mirror of
https://github.com/flatpak/flatpak.git
synced 2026-02-06 22:11:32 -05:00
dir: Fallback to the system default locale, not all
When Flatpak is fetching a locale extension it has to decide which subpaths to fetch based on what language is being used on the computer. This happens in flatpak_dir_get_locale_subpaths() which indirectly uses the org.freedesktop.Accounts D-Bus object to check what language is configured for each user. The problem is that if any user doesn't have a language set, Flatpak falls back to pulling all languages, rather than checking the system default using localed. The effect is that on Endless OS systems, Flatpak is pulling entire locale extensions rather than just the subset for the configured language, which is a significant waste of bandwidth. In my testing, the "Language" property on the primary user account is not set on Endless, but it is set on Fedora. A side effect of this bug is to cause offline USB app installs to sometimes fail, because if the USB only has a partial locale and you try to pull the whole thing, the pull fails. This commit fixes the issue by doing another D-Bus call to localed to get the system default(s), then checking AccountsService as before, treating an unset language for a user account as meaning "use the system default". Then only if no languages are set for the users or the system, fall back to pulling all languages. The code to communicate with localed is based on the code in gnome-control-center in panels/region/cc-region-panel.c This extra synchronous D-Bus call adds some overhead which might be able to be avoided; see https://github.com/flatpak/flatpak/issues/1938 Using this patch I can see that Flatpak is pulling partial locales now, based on the output of `flatpak list -a | grep partial` after installing Bijiben from Flathub. Closes: #1937 Approved by: alexlarsson
This commit is contained in:
committed by
Atomic Bot
parent
a42af4a795
commit
69fc58d345
@@ -11979,6 +11979,66 @@ flatpak_dir_find_local_related (FlatpakDir *self,
|
||||
return g_steal_pointer (&related);
|
||||
}
|
||||
|
||||
static GDBusProxy *
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
|
||||
/* See locale(7) for these categories */
|
||||
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 };
|
||||
|
||||
for (j = 0; categories[j]; j++)
|
||||
{
|
||||
if (g_str_has_prefix (strv[i], categories[j]))
|
||||
{
|
||||
locale = strv[i] + strlen (categories[j]);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
static GDBusProxy *
|
||||
get_accounts_dbus_proxy (void)
|
||||
{
|
||||
@@ -11996,14 +12056,12 @@ get_accounts_dbus_proxy (void)
|
||||
NULL);
|
||||
}
|
||||
|
||||
static char **
|
||||
get_locale_langs_from_accounts_dbus (GDBusProxy *proxy)
|
||||
static void
|
||||
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";
|
||||
char **object_paths = NULL;
|
||||
|
||||
g_autoptr(GPtrArray) langs = g_ptr_array_new ();
|
||||
int i;
|
||||
g_autoptr(GVariant) ret = NULL;
|
||||
|
||||
@@ -12044,7 +12102,7 @@ get_locale_langs_from_accounts_dbus (GDBusProxy *proxy)
|
||||
g_autofree char *lang = NULL;
|
||||
|
||||
if (strcmp (locale, "") == 0)
|
||||
return NULL; /* At least one user with no defined language, fall back to all languages */
|
||||
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))
|
||||
@@ -12053,14 +12111,6 @@ get_locale_langs_from_accounts_dbus (GDBusProxy *proxy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (langs->len == 0)
|
||||
return NULL; /* No defined languages, fall back to all languages */
|
||||
|
||||
g_ptr_array_sort (langs, flatpak_strcmp0_ptr);
|
||||
g_ptr_array_add (langs, NULL);
|
||||
|
||||
return (char **) g_ptr_array_free (g_steal_pointer (&langs), FALSE);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -12079,22 +12129,32 @@ sort_strv (char **strv)
|
||||
char **
|
||||
flatpak_dir_get_default_locale_languages (FlatpakDir *self)
|
||||
{
|
||||
char **langs = NULL;
|
||||
g_autoptr(GPtrArray) langs = g_ptr_array_new_with_free_func (g_free);
|
||||
g_autoptr(GDBusProxy) localed_proxy = NULL;
|
||||
g_autoptr(GDBusProxy) accounts_proxy = NULL;
|
||||
|
||||
if (flatpak_dir_is_user (self))
|
||||
return flatpak_get_current_locale_langs ();
|
||||
|
||||
/* If proxy is not NULL, it means that AccountService exists
|
||||
* and gets the list of languages from AccountService. */
|
||||
g_autoptr(GDBusProxy) proxy = get_accounts_dbus_proxy ();
|
||||
if (proxy != NULL)
|
||||
langs = get_locale_langs_from_accounts_dbus (proxy);
|
||||
/* First get the system default locales */
|
||||
localed_proxy = get_localed_dbus_proxy ();
|
||||
if (localed_proxy != NULL)
|
||||
get_locale_langs_from_localed_dbus (localed_proxy, langs);
|
||||
|
||||
/* If langs is NULL, it means using all languages */
|
||||
if (langs == NULL)
|
||||
langs = g_new0 (char *, 1);
|
||||
/* Now add the user account locales from AccountsService. If accounts_proxy is
|
||||
* not NULL, it means that AccountsService exists */
|
||||
accounts_proxy = get_accounts_dbus_proxy ();
|
||||
if (accounts_proxy != NULL)
|
||||
get_locale_langs_from_accounts_dbus (accounts_proxy, langs);
|
||||
|
||||
return langs;
|
||||
/* If none were found, fall back to using all languages */
|
||||
if (langs->len == 0)
|
||||
return g_new0 (char *, 1);
|
||||
|
||||
g_ptr_array_sort (langs, flatpak_strcmp0_ptr);
|
||||
g_ptr_array_add (langs, NULL);
|
||||
|
||||
return (char **) g_ptr_array_free (g_steal_pointer (&langs), FALSE);
|
||||
}
|
||||
|
||||
char **
|
||||
|
||||
Reference in New Issue
Block a user