mirror of
https://github.com/flatpak/flatpak.git
synced 2026-01-03 05:18:00 -05:00
app: Allow locales to be stored in the extra-languages key
In order to configure gnome-software to show specific apps in one region without showing to all language speakers, we allow the storage of full locales on the extra-languages key. However, these locales are ignored when calling flatpak_installation_get_default_languages, so locales will be reduced to their language identifier (eg. en_IN locale will be returned as 'en', and az_Latn_AZ will be returned as 'az'). In order to get the full locales, we can call flatpak_installation_get_default_locales instead, which can return languages and locales.
This commit is contained in:
@@ -63,12 +63,79 @@ looks_like_a_language (const char *s)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
looks_like_a_region (const char *s)
|
||||
{
|
||||
g_auto(GStrv) locale = g_strsplit (s, "_", 3);
|
||||
int i;
|
||||
int len;
|
||||
|
||||
if (!looks_like_a_language(locale[0]))
|
||||
return FALSE;
|
||||
|
||||
if (locale[1] != NULL)
|
||||
{
|
||||
len = strlen (locale[1]);
|
||||
|
||||
// This can be either GB or Latn
|
||||
if (len < 2 || len > 4)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if ((locale[2] == NULL) && (!g_ascii_isalpha (locale[1][i]) || !g_ascii_isupper (locale[1][i])))
|
||||
return FALSE;
|
||||
else if (!g_ascii_isalpha (locale[1][i]))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_strv_length (locale) > 2)
|
||||
{
|
||||
len = strlen (locale[2]);
|
||||
|
||||
if (len < 2 || len > 3)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (!g_ascii_isalpha (locale[2][i]) || !g_ascii_isupper (locale[2][i]))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char *
|
||||
parse_locale (const char *value, GError **error)
|
||||
{
|
||||
g_auto(GStrv) strs = NULL;
|
||||
int i;
|
||||
|
||||
strs = g_strsplit (value, ";", 0);
|
||||
for (i = 0; strs[i]; i++)
|
||||
{
|
||||
if (!looks_like_a_language (strs[i]) && !looks_like_a_region (strs[i]))
|
||||
{
|
||||
flatpak_fail (error, _("'%s' does not look like a language/locale code"), strs[i]);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return g_strdup (value);
|
||||
}
|
||||
|
||||
static char *
|
||||
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++)
|
||||
{
|
||||
@@ -83,27 +150,17 @@ parse_lang (const char *value, GError **error)
|
||||
}
|
||||
|
||||
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)
|
||||
print_locale (const char *value)
|
||||
{
|
||||
return g_strdup (value);
|
||||
}
|
||||
|
||||
static char *
|
||||
print_special_lang (const char *value)
|
||||
print_lang (const char *value)
|
||||
{
|
||||
if (*value == 0)
|
||||
return g_strdup ("*all*");
|
||||
return print_lang (value);
|
||||
return g_strdup (value);
|
||||
}
|
||||
|
||||
static char *
|
||||
@@ -123,8 +180,8 @@ typedef struct
|
||||
} ConfigKey;
|
||||
|
||||
ConfigKey keys[] = {
|
||||
{ "languages", parse_special_lang, print_special_lang, get_lang_default },
|
||||
{ "extra-languages", parse_lang, print_lang, NULL },
|
||||
{ "languages", parse_lang, print_lang, get_lang_default },
|
||||
{ "extra-languages", parse_locale, print_locale, NULL },
|
||||
};
|
||||
|
||||
static ConfigKey *
|
||||
|
||||
@@ -955,7 +955,9 @@ gboolean flatpak_dir_resolve_p2p_refs (FlatpakDir *self,
|
||||
GError **error);
|
||||
|
||||
|
||||
char ** flatpak_dir_get_default_locales (FlatpakDir *self);
|
||||
char ** flatpak_dir_get_default_locale_languages (FlatpakDir *self);
|
||||
char ** flatpak_dir_get_locales (FlatpakDir *self);
|
||||
char ** flatpak_dir_get_locale_languages (FlatpakDir *self);
|
||||
char ** flatpak_dir_get_locale_subpaths (FlatpakDir *self);
|
||||
|
||||
|
||||
@@ -14561,20 +14561,13 @@ flatpak_dir_get_config_strv (FlatpakDir *self, char *key)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char **
|
||||
flatpak_dir_get_default_locale_languages (FlatpakDir *self)
|
||||
static void
|
||||
get_system_locales (FlatpakDir *self, GPtrArray *langs)
|
||||
{
|
||||
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 sort_strv (flatpak_strv_merge (extra_languages, flatpak_get_current_locale_langs ()));
|
||||
|
||||
/* Then get the system default locales */
|
||||
/* Get the system default locales */
|
||||
localed_proxy = get_localed_dbus_proxy ();
|
||||
if (localed_proxy != NULL)
|
||||
get_locale_langs_from_localed_dbus (localed_proxy, langs);
|
||||
@@ -14584,12 +14577,67 @@ flatpak_dir_get_default_locale_languages (FlatpakDir *self)
|
||||
accounts_proxy = get_accounts_dbus_proxy ();
|
||||
if (accounts_proxy != NULL)
|
||||
get_locale_langs_from_accounts_dbus (accounts_proxy, langs);
|
||||
|
||||
g_ptr_array_add (langs, NULL);
|
||||
}
|
||||
|
||||
char **
|
||||
flatpak_dir_get_default_locales (FlatpakDir *self)
|
||||
{
|
||||
g_autoptr(GPtrArray) langs = g_ptr_array_new_with_free_func (g_free);
|
||||
g_auto(GStrv) extra_languages = NULL;
|
||||
|
||||
extra_languages = flatpak_dir_get_config_strv (self, "xa.extra-languages");
|
||||
|
||||
if (flatpak_dir_is_user (self))
|
||||
return sort_strv (flatpak_strv_merge (extra_languages, flatpak_get_current_locale_langs ()));
|
||||
|
||||
/* Then get the system default locales */
|
||||
get_system_locales (self, langs);
|
||||
|
||||
return sort_strv (flatpak_strv_merge (extra_languages, (char **) langs->pdata));
|
||||
}
|
||||
|
||||
char **
|
||||
flatpak_dir_get_default_locale_languages (FlatpakDir *self)
|
||||
{
|
||||
g_autoptr(GPtrArray) langs = g_ptr_array_new_with_free_func (g_free);
|
||||
g_auto(GStrv) extra_languages = NULL;
|
||||
int i;
|
||||
|
||||
extra_languages = flatpak_dir_get_config_strv (self, "xa.extra-languages");
|
||||
for (i = 0; extra_languages != NULL && extra_languages[i] != NULL; i++)
|
||||
{
|
||||
g_auto(GStrv) locales = g_strsplit (extra_languages[i], "_", -1);
|
||||
g_free (extra_languages[i]);
|
||||
extra_languages[i] = g_strdup (locales[0]);
|
||||
}
|
||||
|
||||
if (flatpak_dir_is_user (self))
|
||||
return sort_strv (flatpak_strv_merge (extra_languages, flatpak_get_current_locale_langs ()));
|
||||
|
||||
/* Then get the system default locales */
|
||||
get_system_locales (self, langs);
|
||||
|
||||
return sort_strv (flatpak_strv_merge (extra_languages, (char **) langs->pdata));
|
||||
}
|
||||
|
||||
char **
|
||||
flatpak_dir_get_locales (FlatpakDir *self)
|
||||
{
|
||||
char **langs = NULL;
|
||||
|
||||
/* 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_locales (self);
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
flatpak_dir_get_locale_languages (FlatpakDir *self)
|
||||
{
|
||||
|
||||
@@ -1682,6 +1682,32 @@ flatpak_installation_get_default_languages (FlatpakInstallation *self,
|
||||
return flatpak_dir_get_locale_languages (dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* flatpak_installation_get_default_locales:
|
||||
* @self: a #FlatpakInstallation
|
||||
* @error: return location for a #GError
|
||||
*
|
||||
* Like flatpak_installation_get_default_languages() but includes region
|
||||
* information (e.g. en_US rather than en) which may be included in the
|
||||
* xa.extra-languages configuration.
|
||||
*
|
||||
* Returns: (array zero-terminated=1) (element-type utf8) (transfer full):
|
||||
* A possibly empty array of language and locale strings, or %NULL on error.
|
||||
* Since: 1.5.1
|
||||
*/
|
||||
char **
|
||||
flatpak_installation_get_default_locales (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_locales (dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* flatpak_installation_get_min_free_space_bytes:
|
||||
* @self: a #FlatpakInstallation
|
||||
|
||||
@@ -298,6 +298,8 @@ FLATPAK_EXTERN char * flatpak_installation_get_config (FlatpakIns
|
||||
GError **error);
|
||||
FLATPAK_EXTERN char ** flatpak_installation_get_default_languages (FlatpakInstallation *self,
|
||||
GError **error);
|
||||
FLATPAK_EXTERN char ** flatpak_installation_get_default_locales (FlatpakInstallation *self,
|
||||
GError **error);
|
||||
FLATPAK_EXTERN char * flatpak_installation_load_app_overrides (FlatpakInstallation *self,
|
||||
const char *app_id,
|
||||
GCancellable *cancellable,
|
||||
|
||||
@@ -70,7 +70,8 @@
|
||||
<listitem><para>
|
||||
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.
|
||||
semicolon-separated list of two-letter language codes or locale identifiers
|
||||
(eg. en;en_DK;az_Latn_AZ).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
@@ -253,6 +253,22 @@ clean_languages (void)
|
||||
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
configure_extra_languages (void)
|
||||
{
|
||||
char *argv[] = { "flatpak", "config", "--user", "--set", "extra-languages", "de_DE", NULL };
|
||||
|
||||
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
clean_extra_languages (void)
|
||||
{
|
||||
char *argv[] = { "flatpak", "config", "--user", "--unset", "extra-languages", NULL };
|
||||
|
||||
run_test_subprocess (argv, RUN_TEST_SUBPROCESS_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
test_languages_config (void)
|
||||
{
|
||||
@@ -273,18 +289,31 @@ test_languages_config (void)
|
||||
value = flatpak_installation_get_default_languages (inst, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpstr (value[0], ==, "en");
|
||||
g_assert_null (value[1]);
|
||||
|
||||
res = flatpak_installation_set_config_sync (inst, "extra-languages", "en;pt", NULL, &error);
|
||||
res = flatpak_installation_set_config_sync (inst, "extra-languages", "pt_BR;az_Latn_AZ;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], ==, "en");
|
||||
g_assert_cmpstr (value[1], ==, "pt");
|
||||
g_assert_null (value[2]);
|
||||
g_assert_cmpstr (value[0], ==, "az");
|
||||
g_assert_cmpstr (value[1], ==, "en");
|
||||
g_assert_cmpstr (value[2], ==, "es");
|
||||
g_assert_cmpstr (value[3], ==, "pt");
|
||||
g_assert_null (value[4]);
|
||||
|
||||
g_clear_pointer (&value, g_free);
|
||||
g_clear_pointer (&value, g_strfreev);
|
||||
|
||||
value = flatpak_installation_get_default_locales (inst, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpstr (value[0], ==, "az_Latn_AZ");
|
||||
g_assert_cmpstr (value[1], ==, "en");
|
||||
g_assert_cmpstr (value[2], ==, "es");
|
||||
g_assert_cmpstr (value[3], ==, "pt_BR");
|
||||
g_assert_null (value[4]);
|
||||
|
||||
g_clear_pointer (&value, g_strfreev);
|
||||
|
||||
res = flatpak_installation_set_config_sync (inst, "languages", "ar;es", NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
@@ -296,7 +325,8 @@ test_languages_config (void)
|
||||
g_assert_cmpstr (value[1], ==, "es");
|
||||
g_assert_null (value[2]);
|
||||
|
||||
g_clear_pointer (&value, g_free);
|
||||
g_clear_pointer (&value, g_strfreev);
|
||||
clean_extra_languages ();
|
||||
configure_languages ();
|
||||
}
|
||||
|
||||
@@ -1083,6 +1113,45 @@ test_list_remote_related_refs (void)
|
||||
g_assert_true (should_download);
|
||||
g_assert_true (should_delete);
|
||||
g_assert_false (should_autoprune);
|
||||
|
||||
// Make the test with extra-languages, instead of languages
|
||||
clean_languages();
|
||||
configure_extra_languages();
|
||||
|
||||
inst = flatpak_installation_new_user (NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
refs = flatpak_installation_list_remote_related_refs_sync (inst, repo_name, app, NULL, &error);
|
||||
g_assert_nonnull (refs);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_cmpint (refs->len, ==, 1);
|
||||
ref = g_ptr_array_index (refs, 0);
|
||||
|
||||
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Hello.Locale");
|
||||
g_assert_true (flatpak_related_ref_should_download (ref));
|
||||
g_assert_true (flatpak_related_ref_should_delete (ref));
|
||||
g_assert_false (flatpak_related_ref_should_autoprune (ref));
|
||||
g_assert (g_strv_length ((char **) flatpak_related_ref_get_subpaths (ref)) == 2);
|
||||
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[0], ==, "/de");
|
||||
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[1], ==, "/en");
|
||||
|
||||
g_object_get (ref,
|
||||
"subpaths", &subpaths,
|
||||
"should-download", &should_download,
|
||||
"should-delete", &should_delete,
|
||||
"should-autoprune", &should_autoprune,
|
||||
NULL);
|
||||
|
||||
g_assert (g_strv_length (subpaths) == 2);
|
||||
g_assert_cmpstr (subpaths[0], ==, "/de");
|
||||
g_assert_cmpstr (subpaths[1], ==, "/en");
|
||||
g_assert_true (should_download);
|
||||
g_assert_true (should_delete);
|
||||
g_assert_false (should_autoprune);
|
||||
|
||||
configure_languages();
|
||||
clean_extra_languages();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3578,6 +3647,59 @@ test_list_installed_related_refs (void)
|
||||
g_assert_false (flatpak_related_ref_should_autoprune (ref));
|
||||
g_assert (g_strv_length ((char **) flatpak_related_ref_get_subpaths (ref)) == 1);
|
||||
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[0], ==, "/de");
|
||||
|
||||
// Make the test with extra-languages, instead of languages
|
||||
clean_languages();
|
||||
configure_extra_languages();
|
||||
empty_installation (inst);
|
||||
|
||||
refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
|
||||
g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED);
|
||||
g_assert_null (refs);
|
||||
g_clear_error (&error);
|
||||
|
||||
iref = flatpak_installation_install (inst, repo_name, FLATPAK_REF_KIND_APP, "org.test.Hello", NULL, "master", NULL, NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (iref);
|
||||
g_clear_object (&iref);
|
||||
|
||||
refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (refs);
|
||||
g_assert_cmpint (refs->len, ==, 0);
|
||||
g_clear_pointer (&refs, g_ptr_array_unref);
|
||||
|
||||
transaction = flatpak_transaction_new_for_installation (inst, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (transaction);
|
||||
|
||||
res = flatpak_transaction_add_update (transaction, app, NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (res);
|
||||
|
||||
flatpak_transaction_run (transaction, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (res);
|
||||
|
||||
g_clear_object (&transaction);
|
||||
|
||||
refs = flatpak_installation_list_installed_related_refs_sync (inst, repo_name, app, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (refs);
|
||||
g_assert_cmpint (refs->len, ==, 1);
|
||||
|
||||
ref = g_ptr_array_index (refs, 0);
|
||||
|
||||
g_assert_cmpstr (flatpak_ref_get_name (FLATPAK_REF (ref)), ==, "org.test.Hello.Locale");
|
||||
g_assert_true (flatpak_related_ref_should_download (ref));
|
||||
g_assert_true (flatpak_related_ref_should_delete (ref));
|
||||
g_assert_false (flatpak_related_ref_should_autoprune (ref));
|
||||
g_assert (g_strv_length ((char **) flatpak_related_ref_get_subpaths (ref)) == 2);
|
||||
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[0], ==, "/de");
|
||||
g_assert_cmpstr (flatpak_related_ref_get_subpaths (ref)[1], ==, "/en");
|
||||
|
||||
configure_languages();
|
||||
clean_extra_languages();
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
Reference in New Issue
Block a user