gcharset: Add g_get_language_names_with_category

g_get_language_names() uses LC_MESSAGES and the fallback is useful
for other locale categories too.

https://bugzilla.gnome.org/show_bug.cgi?id=751826
This commit is contained in:
Takao Fujiwara 2018-03-05 19:50:33 +09:00 committed by Philip Withnall
parent 15201345de
commit e311a45653
4 changed files with 128 additions and 15 deletions

View File

@ -18,6 +18,7 @@
#include "config.h"
#include "gcharset.h"
#include "gcharsetprivate.h"
#include "garray.h"
@ -553,44 +554,77 @@ language_names_cache_free (gpointer data)
* that must not be modified or freed.
*
* Since: 2.6
**/
*/
const gchar * const *
g_get_language_names (void)
{
static GPrivate cache_private = G_PRIVATE_INIT (language_names_cache_free);
GLanguageNamesCache *cache = g_private_get (&cache_private);
const gchar *value;
return g_get_language_names_with_category ("LC_MESSAGES");
}
/**
* g_get_language_names_with_category:
* @category_name: a locale category name
*
* Computes a list of applicable locale names with a locale category name,
* which can be used to construct the fallback locale-dependent filenames
* or search paths. The returned list is sorted from most desirable to
* least desirable and always contains the default locale "C".
*
* This function consults the environment variables `LANGUAGE`, `LC_ALL`,
* @category_name, and `LANG` to find the list of locales specified by the
* user.
*
* g_get_language_names() returns g_get_language_names_with_category("LC_MESSAGES").
*
* Returns: (array zero-terminated=1) (transfer none): a %NULL-terminated array of strings owned by GLib
* that must not be modified or freed.
*
* Since: 2.58
*/
const gchar * const *
g_get_language_names_with_category (const gchar *category_name)
{
static GPrivate cache_private = G_PRIVATE_INIT ((void (*)(gpointer)) g_hash_table_remove_all);
GHashTable *cache = g_private_get (&cache_private);
const gchar *languages;
GLanguageNamesCache *name_cache;
g_return_val_if_fail (category_name != NULL, NULL);
if (!cache)
{
cache = g_new0 (GLanguageNamesCache, 1);
cache = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, language_names_cache_free);
g_private_set (&cache_private, cache);
}
value = guess_category_value ("LC_MESSAGES");
if (!value)
value = "C";
languages = guess_category_value (category_name);
if (!languages)
languages = "C";
if (!(cache->languages && strcmp (cache->languages, value) == 0))
name_cache = (GLanguageNamesCache *) g_hash_table_lookup (cache, category_name);
if (!(name_cache && name_cache->languages &&
strcmp (name_cache->languages, languages) == 0))
{
GPtrArray *array;
gchar **alist, **a;
g_free (cache->languages);
g_strfreev (cache->language_names);
cache->languages = g_strdup (value);
g_hash_table_remove (cache, category_name);
array = g_ptr_array_sized_new (8);
alist = g_strsplit (value, ":", 0);
alist = g_strsplit (languages, ":", 0);
for (a = alist; *a; a++)
append_locale_variants (array, unalias_lang (*a));
g_strfreev (alist);
g_ptr_array_add (array, g_strdup ("C"));
g_ptr_array_add (array, NULL);
cache->language_names = (gchar **) g_ptr_array_free (array, FALSE);
name_cache = g_new0 (GLanguageNamesCache, 1);
name_cache->languages = g_strdup (languages);
name_cache->language_names = (gchar **) g_ptr_array_free (array, FALSE);
g_hash_table_insert (cache, g_strdup (category_name), name_cache);
}
return (const gchar * const *) cache->language_names;
return (const gchar * const *) name_cache->language_names;
}

View File

@ -34,6 +34,9 @@ gchar * g_get_codeset (void);
GLIB_AVAILABLE_IN_ALL
const gchar * const * g_get_language_names (void);
GLIB_AVAILABLE_IN_2_58
const gchar * const * g_get_language_names_with_category
(const gchar *category_name);
GLIB_AVAILABLE_IN_ALL
gchar ** g_get_locale_variants (const gchar *locale);

75
glib/tests/charset.c Normal file
View File

@ -0,0 +1,75 @@
/*
* Copyright 2018 Red Hat, Inc.
*
* 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.
*
* See the included COPYING file for more information.
*/
#undef G_DISABLE_ASSERT
#undef G_LOG_DOMAIN
#include "glib.h"
#define TEST_LOCALE "fr_FR.UTF-8@latin:en_US.UTF-8"
const gchar *TEST_RESULT[] = {
"fr_FR.UTF-8@latin",
"fr_FR@latin",
"fr.UTF-8@latin",
"fr@latin",
"fr_FR.UTF-8",
"fr_FR",
"fr.UTF-8",
"fr",
"en_US.UTF-8",
"en_US",
"en.UTF-8",
"en",
"C",
NULL
};
const gchar *TEST_TABLE[] = {
"LANGUAGE",
"LC_ALL",
"LC_CTYPE",
"LANG",
NULL
};
static void
test_language_names_with_category (void)
{
const gchar * const *language_names = NULL;
gsize i, j;
for (i = 0; TEST_TABLE[i]; ++i)
{
g_test_message ("Test %" G_GSIZE_FORMAT, i);
g_assert_true (g_setenv (TEST_TABLE[i], TEST_LOCALE, TRUE));
language_names = g_get_language_names_with_category ("LC_CTYPE");
g_assert_cmpuint (g_strv_length ((gchar **)language_names), ==, g_strv_length ((gchar **)TEST_RESULT));
for (j = 0; language_names[j]; ++j)
{
g_assert_cmpstr (language_names[j], ==, TEST_RESULT[j]);
}
g_unsetenv (TEST_TABLE[i]);
}
}
int
main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
g_test_bug_base ("http://bugs.gnome.org/");
g_test_add_func ("/charset/language_names_with_category", test_language_names_with_category);
return g_test_run ();
}

View File

@ -6,6 +6,7 @@ glib_tests = [
'bookmarkfile',
'bytes',
'cache',
'charset',
'checksum',
'collate',
'cond',