diff --git a/app/flatpak-builtins-config.c b/app/flatpak-builtins-config.c index 865cd2c1..eb5a8e9a 100644 --- a/app/flatpak-builtins-config.c +++ b/app/flatpak-builtins-config.c @@ -69,10 +69,6 @@ parse_lang (const char *value, GError **error) g_auto(GStrv) strs = NULL; int i; - if (strcmp (value, "*") == 0 || - strcmp (value, "*all*") == 0) - return g_strdup (""); - strs = g_strsplit (value, ";", 0); for (i = 0; strs[i]; i++) { @@ -86,12 +82,28 @@ parse_lang (const char *value, GError **error) return g_strdup (value); } +static char * +parse_special_lang (const char *value, GError **error) +{ + if (strcmp (value, "*") == 0 || + strcmp (value, "*all*") == 0) + return g_strdup (""); + + return parse_lang (value, error); +} + static char * print_lang (const char *value) +{ + return g_strdup (value); +} + +static char * +print_special_lang (const char *value) { if (*value == 0) return g_strdup ("*all*"); - return g_strdup (value); + return print_lang (value); } static char * @@ -111,7 +123,8 @@ typedef struct } ConfigKey; ConfigKey keys[] = { - { "languages", parse_lang, print_lang, get_lang_default }, + { "languages", parse_special_lang, print_special_lang, get_lang_default }, + { "extra-languages", parse_lang, print_lang, NULL }, }; static ConfigKey * diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index b91dadaa..65d91a73 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -14047,17 +14047,37 @@ sort_strv (char **strv) return strv; } +static char ** +flatpak_dir_get_config_strv (FlatpakDir *self, char *key) +{ + GKeyFile *config = flatpak_dir_get_repo_config (self); + g_auto(GStrv) lang = NULL; + + if (config) + { + if (g_key_file_has_key (config, "core", key, NULL)) + { + lang = g_key_file_get_string_list (config, "core", key, NULL, NULL); + return g_steal_pointer (&lang); + } + } + return NULL; +} + char ** flatpak_dir_get_default_locale_languages (FlatpakDir *self) { 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; + g_auto(GStrv) extra_languages = NULL; + + extra_languages = flatpak_dir_get_config_strv (self, "xa.extra-languages"); if (flatpak_dir_is_user (self)) - return flatpak_get_current_locale_langs (); + return sort_strv (flatpak_strv_merge (extra_languages, flatpak_get_current_locale_langs ())); - /* First get the system default locales */ + /* Then get the system default locales */ localed_proxy = get_localed_dbus_proxy (); if (localed_proxy != NULL) get_locale_langs_from_localed_dbus (localed_proxy, langs); @@ -14068,27 +14088,23 @@ flatpak_dir_get_default_locale_languages (FlatpakDir *self) if (accounts_proxy != NULL) get_locale_langs_from_accounts_dbus (accounts_proxy, 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); + return sort_strv (flatpak_strv_merge (extra_languages, (char **) langs->pdata)); } char ** flatpak_dir_get_locale_languages (FlatpakDir *self) { - GKeyFile *config = flatpak_dir_get_repo_config (self); + char **langs = NULL; - if (config) - { - char **langs = g_key_file_get_string_list (config, "core", "xa.languages", NULL, NULL); - if (langs) - return sort_strv (langs); - } + /* Fetch the list of languages specified by xa.languages - if this key is empty, + * this would mean that all languages are accepted. You can read the man for the + * flatpak-config section for more info. + */ + langs = flatpak_dir_get_config_strv (self, "xa.languages"); + if (langs) + return sort_strv (langs); return flatpak_dir_get_default_locale_languages (self); } diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c index 5b4c10de..68a80fbb 100644 --- a/common/flatpak-installation.c +++ b/common/flatpak-installation.c @@ -1648,6 +1648,33 @@ flatpak_installation_get_config (FlatpakInstallation *self, return flatpak_dir_get_config (dir, key, error); } +/** + * flatpak_installation_get_default_languages: + * @self: a #FlatpakInstallation + * @error: return location for a #GError + * + * Get the default languages used by the installation to decide which + * subpaths to install of locale extensions. This list may also be used + * by frontends like GNOME Software to decide which language-specific apps + * to display. An empty array means that all languages should be installed. + * + * Returns: (array zero-terminated=1) (element-type utf8) (transfer full): + * A possibly empty array of locale strings, or %NULL on error. + * Since: 1.5.0 + */ +char ** +flatpak_installation_get_default_languages (FlatpakInstallation *self, + GError **error) +{ + g_autoptr(FlatpakDir) dir = NULL; + + dir = flatpak_installation_get_dir (self, error); + if (dir == NULL) + return NULL; + + return flatpak_dir_get_locale_languages (dir); +} + /** * flatpak_installation_get_min_free_space_bytes: * @self: a #FlatpakInstallation diff --git a/common/flatpak-installation.h b/common/flatpak-installation.h index c6fa500e..c97070ce 100644 --- a/common/flatpak-installation.h +++ b/common/flatpak-installation.h @@ -296,6 +296,8 @@ FLATPAK_EXTERN char * flatpak_installation_get_config (FlatpakIns const char *key, GCancellable *cancellable, GError **error); +FLATPAK_EXTERN char ** flatpak_installation_get_default_languages (FlatpakInstallation *self, + GError **error); FLATPAK_EXTERN char * flatpak_installation_load_app_overrides (FlatpakInstallation *self, const char *app_id, GCancellable *cancellable, diff --git a/doc/flatpak-config.xml b/doc/flatpak-config.xml index e23bcc00..5d05cb54 100644 --- a/doc/flatpak-config.xml +++ b/doc/flatpak-config.xml @@ -62,7 +62,15 @@ The languages that are included when installing Locale extensions. The value is a semicolon-separated list of two-letter language codes, or one of the special values * or all. If this key is unset, flatpak - defaults to including just the current locale. + defaults to including the extra-languages key and the current locale. + + + + extra-languages + + This key is used when languages is not set, and it defines extra locale + extensions on top of the system configured languages. The value is a + semicolon-separated list of two-letter language codes. diff --git a/doc/reference/flatpak-sections.txt b/doc/reference/flatpak-sections.txt index 7df7c09b..a43228e2 100644 --- a/doc/reference/flatpak-sections.txt +++ b/doc/reference/flatpak-sections.txt @@ -47,6 +47,7 @@ flatpak_installation_remove_remote flatpak_installation_update_remote_sync flatpak_installation_cleanup_local_refs_sync flatpak_installation_get_config +flatpak_installation_get_default_languages flatpak_installation_prune_local_repo flatpak_installation_remove_local_ref_sync flatpak_installation_set_config_sync diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c index afc32bad..91dd16db 100644 --- a/system-helper/flatpak-system-helper.c +++ b/system-helper/flatpak-system-helper.c @@ -1120,8 +1120,7 @@ handle_configure (FlatpakSystemHelper *object, return TRUE; } - /* We only support this for now */ - if (strcmp (arg_key, "languages") != 0) + if ((strcmp (arg_key, "languages") != 0) && (strcmp (arg_key, "extra-languages") != 0)) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Unsupported key: %s", arg_key); diff --git a/tests/testlibrary.c b/tests/testlibrary.c index 49726192..0f1edfac 100644 --- a/tests/testlibrary.c +++ b/tests/testlibrary.c @@ -237,6 +237,69 @@ test_installation_config (void) g_assert_no_error (error); } +static void +configure_languages (void) +{ + char *argv[] = { "flatpak", "config", "--user", "--set", "languages", "de", NULL }; + + run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT); +} + +static void +clean_languages (void) +{ + char *argv[] = { "flatpak", "config", "--user", "--unset", "languages", NULL }; + + run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT); +} + +static void +test_languages_config (void) +{ + g_autoptr(FlatpakInstallation) inst = NULL; + g_autofree char *path = NULL; + g_autoptr(GFile) file = NULL; + g_autoptr(GError) error = NULL; + g_auto(GStrv) value = NULL; + gboolean res; + + clean_languages (); + path = g_build_filename (g_get_user_data_dir (), "flatpak", NULL); + file = g_file_new_for_path (path); + inst = flatpak_installation_new_for_path (file, TRUE, NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (inst); + + value = flatpak_installation_get_default_languages (inst, &error); + g_assert_no_error (error); + g_assert_cmpstr (value[0], ==, "en"); + + res = flatpak_installation_set_config_sync (inst, "extra-languages", "en;pt", NULL, &error); + g_assert_no_error (error); + g_assert_true (res); + + value = flatpak_installation_get_default_languages (inst, &error); + g_assert_no_error (error); + g_assert_cmpstr (value[0], ==, "en"); + g_assert_cmpstr (value[1], ==, "pt"); + g_assert_null (value[2]); + + g_clear_pointer (&value, g_free); + + res = flatpak_installation_set_config_sync (inst, "languages", "ar;es", NULL, &error); + g_assert_no_error (error); + g_assert_true (res); + + value = flatpak_installation_get_default_languages (inst, &error); + g_assert_no_error (error); + g_assert_cmpstr (value[0], ==, "ar"); + g_assert_cmpstr (value[1], ==, "es"); + g_assert_null (value[2]); + + g_clear_pointer (&value, g_free); + configure_languages (); +} + static void test_arches (void) { @@ -1829,14 +1892,6 @@ setup_multiple_installations (void) add_extra_installation ("extra-installation-3", NULL, NULL, NULL); } -static void -configure_languages (void) -{ - char *argv[] = { "flatpak", "config", "--user", "--set", "languages", "de", NULL }; - - run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT); -} - static void setup_repo (void) { @@ -1968,6 +2023,7 @@ global_setup (void) g_assert_cmpstr (g_get_user_runtime_dir (), ==, flatpak_runtimedir); g_setenv ("FLATPAK_SYSTEM_HELPER_ON_SESSION", "1", TRUE); + g_setenv ("LANGUAGE", "en", TRUE); test_bus = g_test_dbus_new (G_TEST_DBUS_NONE); @@ -3635,6 +3691,7 @@ main (int argc, char *argv[]) g_test_add_func ("/library/system-installation", test_system_installation); g_test_add_func ("/library/multiple-system-installation", test_multiple_system_installations); g_test_add_func ("/library/installation-config", test_installation_config); + g_test_add_func ("/library/languages-config", test_languages_config); g_test_add_func ("/library/arches", test_arches); g_test_add_func ("/library/ref", test_ref); g_test_add_func ("/library/list-remotes", test_list_remotes);