From 9bf3620aef69ce47b5f5729cab30caef14e7b9d1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 14 Nov 2023 16:54:38 +0000 Subject: [PATCH] common: Move locale utils to their own small translation unit This reduces the size of flatpak-utils and flatpak-dir, which are both too large. Signed-off-by: Simon McVittie --- common/Makefile.am.inc | 2 + common/flatpak-dir-private.h | 16 -- common/flatpak-dir.c | 297 +------------------- common/flatpak-locale-utils-private.h | 44 +++ common/flatpak-locale-utils.c | 388 ++++++++++++++++++++++++++ common/flatpak-utils-private.h | 4 - common/flatpak-utils.c | 61 ---- common/meson.build | 1 + tests/test-locale-utils.c | 2 +- 9 files changed, 437 insertions(+), 378 deletions(-) create mode 100644 common/flatpak-locale-utils-private.h create mode 100644 common/flatpak-locale-utils.c diff --git a/common/Makefile.am.inc b/common/Makefile.am.inc index 7f9af9561..d08b8d12d 100644 --- a/common/Makefile.am.inc +++ b/common/Makefile.am.inc @@ -160,6 +160,8 @@ libflatpak_common_la_SOURCES = \ common/flatpak-json-oci.c \ common/flatpak-json-private.h \ common/flatpak-json.c \ + common/flatpak-locale-utils-private.h \ + common/flatpak-locale-utils.c \ common/flatpak-metadata-private.h \ common/flatpak-oci-registry-private.h \ common/flatpak-oci-registry.c \ diff --git a/common/flatpak-dir-private.h b/common/flatpak-dir-private.h index 59ae500ac..2f7cf8971 100644 --- a/common/flatpak-dir-private.h +++ b/common/flatpak-dir-private.h @@ -1053,20 +1053,4 @@ char ** flatpak_dir_list_unused_refs (Fla GCancellable *cancellable, GError **error); -const GPtrArray *flatpak_get_system_locales (void); -const GPtrArray *flatpak_get_user_locales (void); - -/* Only for regression tests, should not be used directly */ -GDBusProxy *flatpak_locale_get_localed_dbus_proxy (void); -void flatpak_get_locale_langs_from_localed_dbus (GDBusProxy *proxy, - GPtrArray *langs); -GDBusProxy *flatpak_locale_get_accounts_dbus_proxy (void); -gboolean flatpak_get_all_langs_from_accounts_dbus (GDBusProxy *proxy, - GPtrArray *langs); -void flatpak_get_locale_langs_from_accounts_dbus (GDBusProxy *proxy, - GPtrArray *langs); -void flatpak_get_locale_langs_from_accounts_dbus_for_user (GDBusProxy *proxy, - GPtrArray *langs, - guint uid); - #endif /* __FLATPAK_DIR_H__ */ diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index faa086da2..f6a2f872a 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -50,6 +50,7 @@ #include "flatpak-appdata-private.h" #include "flatpak-dir-private.h" #include "flatpak-error.h" +#include "flatpak-locale-utils-private.h" #include "flatpak-oci-registry-private.h" #include "flatpak-ref.h" #include "flatpak-run-private.h" @@ -16096,243 +16097,6 @@ flatpak_dir_get_remote_auto_install_authenticator_ref (FlatpakDir *self, return g_steal_pointer (&ref); } - -GDBusProxy * -flatpak_locale_get_localed_dbus_proxy (void) -{ - const char *localed_bus_name = "org.freedesktop.locale1"; - const char *localed_object_path = "/org/freedesktop/locale1"; - const char *localed_interface_name = localed_bus_name; - - return g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - localed_bus_name, - localed_object_path, - localed_interface_name, - NULL, - NULL); -} - -void -flatpak_get_locale_langs_from_localed_dbus (GDBusProxy *proxy, GPtrArray *langs) -{ - g_autoptr(GVariant) locale_variant = NULL; - g_autofree const gchar **strv = NULL; - gsize i, j; - - locale_variant = g_dbus_proxy_get_cached_property (proxy, "Locale"); - if (locale_variant == NULL) - return; - - strv = g_variant_get_strv (locale_variant, NULL); - - for (i = 0; strv[i]; i++) - { - const gchar *locale = NULL; - g_autofree char *lang = NULL; - - const char * const *categories = flatpak_get_locale_categories (); - - for (j = 0; categories[j]; j++) - { - g_autofree char *prefix = g_strdup_printf ("%s=", categories[j]); - if (g_str_has_prefix (strv[i], prefix)) - { - locale = strv[i] + strlen (prefix); - break; - } - } - - if (locale == NULL || strcmp (locale, "") == 0) - continue; - - lang = flatpak_get_lang_from_locale (locale); - if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) - g_ptr_array_add (langs, g_steal_pointer (&lang)); - } -} - -GDBusProxy * -flatpak_locale_get_accounts_dbus_proxy (void) -{ - const char *accounts_bus_name = "org.freedesktop.Accounts"; - const char *accounts_object_path = "/org/freedesktop/Accounts"; - const char *accounts_interface_name = accounts_bus_name; - - return g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - accounts_bus_name, - accounts_object_path, - accounts_interface_name, - NULL, - NULL); -} - -gboolean -flatpak_get_all_langs_from_accounts_dbus (GDBusProxy *proxy, GPtrArray *langs) -{ - g_auto(GStrv) all_langs = NULL; - int i; - g_autoptr(GVariant) ret = NULL; - g_autoptr(GError) error = NULL; - - ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "GetUsersLanguages", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - if (!ret) - { - g_debug ("Failed to get languages for all users: %s", error->message); - return FALSE; - } - - g_variant_get (ret, - "(^as)", - &all_langs); - - if (all_langs != NULL) - { - for (i = 0; all_langs[i] != NULL; i++) - { - g_autofree char *lang = NULL; - lang = flatpak_get_lang_from_locale (all_langs[i]); - if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) - g_ptr_array_add (langs, g_steal_pointer (&lang)); - } - } - - return TRUE; -} - -void -flatpak_get_locale_langs_from_accounts_dbus (GDBusProxy *proxy, GPtrArray *langs) -{ - const char *accounts_bus_name = "org.freedesktop.Accounts"; - const char *accounts_interface_name = "org.freedesktop.Accounts.User"; - g_auto(GStrv) object_paths = NULL; - int i; - g_autoptr(GVariant) ret = NULL; - - ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "ListCachedUsers", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL); - if (ret != NULL) - g_variant_get (ret, - "(^ao)", - &object_paths); - - if (object_paths != NULL) - { - for (i = 0; object_paths[i] != NULL; i++) - { - g_autoptr(GDBusProxy) accounts_proxy = NULL; - g_autoptr(GVariant) value = NULL; - - accounts_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - accounts_bus_name, - object_paths[i], - accounts_interface_name, - NULL, - NULL); - - if (accounts_proxy) - { - value = g_dbus_proxy_get_cached_property (accounts_proxy, "Language"); - if (value != NULL) - { - const char *locale = g_variant_get_string (value, NULL); - g_autofree char *lang = NULL; - - if (strcmp (locale, "") == 0) - continue; /* This user wants the system default locale */ - - lang = flatpak_get_lang_from_locale (locale); - if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) - g_ptr_array_add (langs, g_steal_pointer (&lang)); - } - } - } - } -} - -void -flatpak_get_locale_langs_from_accounts_dbus_for_user (GDBusProxy *proxy, GPtrArray *langs, guint uid) -{ - const char *accounts_bus_name = "org.freedesktop.Accounts"; - const char *accounts_interface_name = "org.freedesktop.Accounts.User"; - g_autofree char *object_path = NULL; - g_autoptr(GVariant) ret = NULL; - - ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), - "FindUserById", - g_variant_new ("(x)", uid), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL); - if (ret != NULL) - g_variant_get (ret, "(o)", &object_path); - - if (object_path != NULL) - { - g_autoptr(GDBusProxy) accounts_proxy = NULL; - g_autoptr(GVariant) value = NULL; - - accounts_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - accounts_bus_name, - object_path, - accounts_interface_name, - NULL, - NULL); - if (!accounts_proxy) - return; - - value = g_dbus_proxy_get_cached_property (accounts_proxy, "Languages"); - if (value != NULL) - { - const char **locales = g_variant_get_strv (value, NULL); - guint i; - - for (i = 0; locales != NULL && locales[i] != NULL; i++) - { - g_autofree char *lang = NULL; - lang = flatpak_get_lang_from_locale (locales[i]); - if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) - g_ptr_array_add (langs, g_steal_pointer (&lang)); - } - } - else - { - value = g_dbus_proxy_get_cached_property (accounts_proxy, "Language"); - if (value != NULL) - { - const char *locale = g_variant_get_string (value, NULL); - g_autofree char *lang = NULL; - - if (strcmp (locale, "") != 0) - { - lang = flatpak_get_lang_from_locale (locale); - if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) - g_ptr_array_add (langs, g_steal_pointer (&lang)); - } - } - } - } -} - static int cmpstringp (const void *p1, const void *p2) { @@ -16363,65 +16127,6 @@ flatpak_dir_get_config_strv (FlatpakDir *self, char *key) return NULL; } -const GPtrArray * -flatpak_get_system_locales (void) -{ - static GPtrArray *cached = NULL; - - if (g_once_init_enter (&cached)) - { - GPtrArray *langs = g_ptr_array_new_with_free_func (g_free); - g_autoptr(GDBusProxy) accounts_proxy = NULL; - - accounts_proxy = flatpak_locale_get_accounts_dbus_proxy (); - - if (accounts_proxy == NULL - || !flatpak_get_all_langs_from_accounts_dbus (accounts_proxy, langs)) - { - g_autoptr(GDBusProxy) localed_proxy = NULL; - - /* Get the system default locales */ - localed_proxy = flatpak_locale_get_localed_dbus_proxy (); - if (localed_proxy != NULL) - flatpak_get_locale_langs_from_localed_dbus (localed_proxy, langs); - - /* Now add the user account locales from AccountsService. If accounts_proxy is - * not NULL, it means that AccountsService exists */ - if (accounts_proxy != NULL) - flatpak_get_locale_langs_from_accounts_dbus (accounts_proxy, langs); - } - - g_ptr_array_add (langs, NULL); - - g_once_init_leave (&cached, langs); - } - - return (const GPtrArray *)cached; -} - -const GPtrArray * -flatpak_get_user_locales (void) -{ - static GPtrArray *cached = NULL; - - if (g_once_init_enter (&cached)) - { - GPtrArray *langs = g_ptr_array_new_with_free_func (g_free); - g_autoptr(GDBusProxy) accounts_proxy = NULL; - - accounts_proxy = flatpak_locale_get_accounts_dbus_proxy (); - - if (accounts_proxy != NULL) - flatpak_get_locale_langs_from_accounts_dbus_for_user (accounts_proxy, langs, getuid ()); - - g_ptr_array_add (langs, NULL); - - g_once_init_leave (&cached, langs); - } - - return (const GPtrArray *)cached; -} - char ** flatpak_dir_get_default_locales (FlatpakDir *self) { diff --git a/common/flatpak-locale-utils-private.h b/common/flatpak-locale-utils-private.h new file mode 100644 index 000000000..0519d209c --- /dev/null +++ b/common/flatpak-locale-utils-private.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2014 Red Hat, Inc + * Copyright © 2023 Collabora Ltd. + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Alexander Larsson + */ + +#pragma once + +#include + +const char * const *flatpak_get_locale_categories (void); +char *flatpak_get_lang_from_locale (const char *locale); +char **flatpak_get_current_locale_langs (void); +const GPtrArray *flatpak_get_system_locales (void); +const GPtrArray *flatpak_get_user_locales (void); + +/* Only for regression tests, should not be used directly */ +GDBusProxy *flatpak_locale_get_localed_dbus_proxy (void); +void flatpak_get_locale_langs_from_localed_dbus (GDBusProxy *proxy, + GPtrArray *langs); +GDBusProxy *flatpak_locale_get_accounts_dbus_proxy (void); +gboolean flatpak_get_all_langs_from_accounts_dbus (GDBusProxy *proxy, + GPtrArray *langs); +void flatpak_get_locale_langs_from_accounts_dbus (GDBusProxy *proxy, + GPtrArray *langs); +void flatpak_get_locale_langs_from_accounts_dbus_for_user (GDBusProxy *proxy, + GPtrArray *langs, + guint uid); diff --git a/common/flatpak-locale-utils.c b/common/flatpak-locale-utils.c new file mode 100644 index 000000000..859721bc2 --- /dev/null +++ b/common/flatpak-locale-utils.c @@ -0,0 +1,388 @@ +/* vi:set et sw=2 sts=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e-s: + * Copyright © 2014-2019 Red Hat, Inc + * Copyright © 2017 Endless Mobile, Inc. + * Copyright © 2023 Collabora Ltd. + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Alexander Larsson + * Philip Withnall + * Matthew Leeds + */ + +#include "config.h" +#include "flatpak-locale-utils-private.h" + +#include +#include "libglnx.h" + +#include "flatpak-utils-private.h" + +const char * const * +flatpak_get_locale_categories (void) +{ + /* See locale(7) for these categories */ + static const char * const categories[] = { + "LANG", "LC_ALL", "LC_MESSAGES", "LC_ADDRESS", "LC_COLLATE", "LC_CTYPE", + "LC_IDENTIFICATION", "LC_MONETARY", "LC_MEASUREMENT", "LC_NAME", "LC_NUMERIC", + "LC_PAPER", "LC_TELEPHONE", "LC_TIME", + NULL + }; + + return categories; +} + +char * +flatpak_get_lang_from_locale (const char *locale) +{ + g_autofree char *lang = g_strdup (locale); + char *c; + + c = strchr (lang, '@'); + if (c != NULL) + *c = 0; + c = strchr (lang, '_'); + if (c != NULL) + *c = 0; + c = strchr (lang, '.'); + if (c != NULL) + *c = 0; + + if (strcmp (lang, "C") == 0) + return NULL; + + return g_steal_pointer (&lang); +} + +char ** +flatpak_get_current_locale_langs (void) +{ + const char * const *categories = flatpak_get_locale_categories (); + GPtrArray *langs = g_ptr_array_new (); + int i; + + for (; categories != NULL && *categories != NULL; categories++) + { + const gchar * const *locales = g_get_language_names_with_category (*categories); + + for (i = 0; locales[i] != NULL; i++) + { + g_autofree char *lang = flatpak_get_lang_from_locale (locales[i]); + if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) + g_ptr_array_add (langs, g_steal_pointer (&lang)); + } + } + + g_ptr_array_sort (langs, flatpak_strcmp0_ptr); + g_ptr_array_add (langs, NULL); + + return (char **) g_ptr_array_free (langs, FALSE); +} + +GDBusProxy * +flatpak_locale_get_localed_dbus_proxy (void) +{ + const char *localed_bus_name = "org.freedesktop.locale1"; + const char *localed_object_path = "/org/freedesktop/locale1"; + const char *localed_interface_name = localed_bus_name; + + return g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + localed_bus_name, + localed_object_path, + localed_interface_name, + NULL, + NULL); +} + +void +flatpak_get_locale_langs_from_localed_dbus (GDBusProxy *proxy, GPtrArray *langs) +{ + g_autoptr(GVariant) locale_variant = NULL; + g_autofree const gchar **strv = NULL; + gsize i, j; + + locale_variant = g_dbus_proxy_get_cached_property (proxy, "Locale"); + if (locale_variant == NULL) + return; + + strv = g_variant_get_strv (locale_variant, NULL); + + for (i = 0; strv[i]; i++) + { + const gchar *locale = NULL; + g_autofree char *lang = NULL; + + const char * const *categories = flatpak_get_locale_categories (); + + for (j = 0; categories[j]; j++) + { + g_autofree char *prefix = g_strdup_printf ("%s=", categories[j]); + if (g_str_has_prefix (strv[i], prefix)) + { + locale = strv[i] + strlen (prefix); + break; + } + } + + if (locale == NULL || strcmp (locale, "") == 0) + continue; + + lang = flatpak_get_lang_from_locale (locale); + if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) + g_ptr_array_add (langs, g_steal_pointer (&lang)); + } +} + +GDBusProxy * +flatpak_locale_get_accounts_dbus_proxy (void) +{ + const char *accounts_bus_name = "org.freedesktop.Accounts"; + const char *accounts_object_path = "/org/freedesktop/Accounts"; + const char *accounts_interface_name = accounts_bus_name; + + return g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + accounts_bus_name, + accounts_object_path, + accounts_interface_name, + NULL, + NULL); +} + +gboolean +flatpak_get_all_langs_from_accounts_dbus (GDBusProxy *proxy, GPtrArray *langs) +{ + g_auto(GStrv) all_langs = NULL; + int i; + g_autoptr(GVariant) ret = NULL; + g_autoptr(GError) error = NULL; + + ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "GetUsersLanguages", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (!ret) + { + g_debug ("Failed to get languages for all users: %s", error->message); + return FALSE; + } + + g_variant_get (ret, + "(^as)", + &all_langs); + + if (all_langs != NULL) + { + for (i = 0; all_langs[i] != NULL; i++) + { + g_autofree char *lang = NULL; + lang = flatpak_get_lang_from_locale (all_langs[i]); + if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) + g_ptr_array_add (langs, g_steal_pointer (&lang)); + } + } + + return TRUE; +} + +void +flatpak_get_locale_langs_from_accounts_dbus (GDBusProxy *proxy, GPtrArray *langs) +{ + const char *accounts_bus_name = "org.freedesktop.Accounts"; + const char *accounts_interface_name = "org.freedesktop.Accounts.User"; + g_auto(GStrv) object_paths = NULL; + int i; + g_autoptr(GVariant) ret = NULL; + + ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "ListCachedUsers", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL); + if (ret != NULL) + g_variant_get (ret, + "(^ao)", + &object_paths); + + if (object_paths != NULL) + { + for (i = 0; object_paths[i] != NULL; i++) + { + g_autoptr(GDBusProxy) accounts_proxy = NULL; + g_autoptr(GVariant) value = NULL; + + accounts_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + accounts_bus_name, + object_paths[i], + accounts_interface_name, + NULL, + NULL); + + if (accounts_proxy) + { + value = g_dbus_proxy_get_cached_property (accounts_proxy, "Language"); + if (value != NULL) + { + const char *locale = g_variant_get_string (value, NULL); + g_autofree char *lang = NULL; + + if (strcmp (locale, "") == 0) + continue; /* This user wants the system default locale */ + + lang = flatpak_get_lang_from_locale (locale); + if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) + g_ptr_array_add (langs, g_steal_pointer (&lang)); + } + } + } + } +} + +void +flatpak_get_locale_langs_from_accounts_dbus_for_user (GDBusProxy *proxy, GPtrArray *langs, guint uid) +{ + const char *accounts_bus_name = "org.freedesktop.Accounts"; + const char *accounts_interface_name = "org.freedesktop.Accounts.User"; + g_autofree char *object_path = NULL; + g_autoptr(GVariant) ret = NULL; + + ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "FindUserById", + g_variant_new ("(x)", uid), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL); + if (ret != NULL) + g_variant_get (ret, "(o)", &object_path); + + if (object_path != NULL) + { + g_autoptr(GDBusProxy) accounts_proxy = NULL; + g_autoptr(GVariant) value = NULL; + + accounts_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + accounts_bus_name, + object_path, + accounts_interface_name, + NULL, + NULL); + if (!accounts_proxy) + return; + + value = g_dbus_proxy_get_cached_property (accounts_proxy, "Languages"); + if (value != NULL) + { + const char **locales = g_variant_get_strv (value, NULL); + guint i; + + for (i = 0; locales != NULL && locales[i] != NULL; i++) + { + g_autofree char *lang = NULL; + lang = flatpak_get_lang_from_locale (locales[i]); + if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) + g_ptr_array_add (langs, g_steal_pointer (&lang)); + } + } + else + { + value = g_dbus_proxy_get_cached_property (accounts_proxy, "Language"); + if (value != NULL) + { + const char *locale = g_variant_get_string (value, NULL); + g_autofree char *lang = NULL; + + if (strcmp (locale, "") != 0) + { + lang = flatpak_get_lang_from_locale (locale); + if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) + g_ptr_array_add (langs, g_steal_pointer (&lang)); + } + } + } + } +} + +const GPtrArray * +flatpak_get_system_locales (void) +{ + static GPtrArray *cached = NULL; + + if (g_once_init_enter (&cached)) + { + GPtrArray *langs = g_ptr_array_new_with_free_func (g_free); + g_autoptr(GDBusProxy) accounts_proxy = NULL; + + accounts_proxy = flatpak_locale_get_accounts_dbus_proxy (); + + if (accounts_proxy == NULL + || !flatpak_get_all_langs_from_accounts_dbus (accounts_proxy, langs)) + { + g_autoptr(GDBusProxy) localed_proxy = NULL; + + /* Get the system default locales */ + localed_proxy = flatpak_locale_get_localed_dbus_proxy (); + if (localed_proxy != NULL) + flatpak_get_locale_langs_from_localed_dbus (localed_proxy, langs); + + /* Now add the user account locales from AccountsService. If accounts_proxy is + * not NULL, it means that AccountsService exists */ + if (accounts_proxy != NULL) + flatpak_get_locale_langs_from_accounts_dbus (accounts_proxy, langs); + } + + g_ptr_array_add (langs, NULL); + + g_once_init_leave (&cached, langs); + } + + return (const GPtrArray *)cached; +} + +const GPtrArray * +flatpak_get_user_locales (void) +{ + static GPtrArray *cached = NULL; + + if (g_once_init_enter (&cached)) + { + GPtrArray *langs = g_ptr_array_new_with_free_func (g_free); + g_autoptr(GDBusProxy) accounts_proxy = NULL; + + accounts_proxy = flatpak_locale_get_accounts_dbus_proxy (); + + if (accounts_proxy != NULL) + flatpak_get_locale_langs_from_accounts_dbus_for_user (accounts_proxy, langs, getuid ()); + + g_ptr_array_add (langs, NULL); + + g_once_init_leave (&cached, langs); + } + + return (const GPtrArray *)cached; +} diff --git a/common/flatpak-utils-private.h b/common/flatpak-utils-private.h index 6187c48a0..b9a68cdae 100644 --- a/common/flatpak-utils-private.h +++ b/common/flatpak-utils-private.h @@ -107,10 +107,6 @@ char **flatpak_strv_merge (char **strv1, char **flatpak_subpaths_merge (char **subpaths1, char **subpaths2); -const char * const *flatpak_get_locale_categories (void); -char *flatpak_get_lang_from_locale (const char *locale); -char **flatpak_get_current_locale_langs (void); - GBytes * flatpak_read_stream (GInputStream * in, gboolean null_terminate, GError **error); diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c index 7c2c60f2c..be9f1d462 100644 --- a/common/flatpak-utils.c +++ b/common/flatpak-utils.c @@ -7401,42 +7401,6 @@ flatpak_subpaths_merge (char **subpaths1, return res; } -const char * const * -flatpak_get_locale_categories (void) -{ - /* See locale(7) for these categories */ - static const char * const categories[] = { - "LANG", "LC_ALL", "LC_MESSAGES", "LC_ADDRESS", "LC_COLLATE", "LC_CTYPE", - "LC_IDENTIFICATION", "LC_MONETARY", "LC_MEASUREMENT", "LC_NAME", "LC_NUMERIC", - "LC_PAPER", "LC_TELEPHONE", "LC_TIME", - NULL - }; - - return categories; -} - -char * -flatpak_get_lang_from_locale (const char *locale) -{ - g_autofree char *lang = g_strdup (locale); - char *c; - - c = strchr (lang, '@'); - if (c != NULL) - *c = 0; - c = strchr (lang, '_'); - if (c != NULL) - *c = 0; - c = strchr (lang, '.'); - if (c != NULL) - *c = 0; - - if (strcmp (lang, "C") == 0) - return NULL; - - return g_steal_pointer (&lang); -} - gboolean flatpak_g_ptr_array_contains_string (GPtrArray *array, const char *str) { @@ -7450,31 +7414,6 @@ flatpak_g_ptr_array_contains_string (GPtrArray *array, const char *str) return FALSE; } -char ** -flatpak_get_current_locale_langs (void) -{ - const char * const *categories = flatpak_get_locale_categories (); - GPtrArray *langs = g_ptr_array_new (); - int i; - - for (; categories != NULL && *categories != NULL; categories++) - { - const gchar * const *locales = g_get_language_names_with_category (*categories); - - for (i = 0; locales[i] != NULL; i++) - { - g_autofree char *lang = flatpak_get_lang_from_locale (locales[i]); - if (lang != NULL && !flatpak_g_ptr_array_contains_string (langs, lang)) - g_ptr_array_add (langs, g_steal_pointer (&lang)); - } - } - - g_ptr_array_sort (langs, flatpak_strcmp0_ptr); - g_ptr_array_add (langs, NULL); - - return (char **) g_ptr_array_free (langs, FALSE); -} - void flatpak_log_dir_access (FlatpakDir *dir) { diff --git a/common/meson.build b/common/meson.build index 18f0249a6..0dc07d288 100644 --- a/common/meson.build +++ b/common/meson.build @@ -176,6 +176,7 @@ sources = [ 'flatpak-instance.c', 'flatpak-json-oci.c', 'flatpak-json.c', + 'flatpak-locale-utils.c', 'flatpak-oci-registry.c', 'flatpak-portal-error.c', 'flatpak-progress.c', diff --git a/tests/test-locale-utils.c b/tests/test-locale-utils.c index 8fe92fd70..38e708794 100644 --- a/tests/test-locale-utils.c +++ b/tests/test-locale-utils.c @@ -9,7 +9,7 @@ #include "libglnx.h" #include "flatpak.h" -#include "flatpak-utils-private.h" +#include "flatpak-locale-utils-private.h" #include "tests/testlib.h"