diff options
author | Will Thompson <wjt@endlessos.org> | 2023-02-26 21:45:16 +0000 |
---|---|---|
committer | Will Thompson <wjt@endlessos.org> | 2023-02-27 13:15:49 +0000 |
commit | 3cc1e280a0fb30dc7faa43d6541f0c535ca49cd0 (patch) | |
tree | 7d2ca4b696ed2e70fbdeb20e0d39f5b550a7f433 | |
parent | d42fefe06e4e0f4b4bcf5b5dbdf5c9d3b3eca79b (diff) | |
download | gnome-initial-setup-3cc1e280a0fb30dc7faa43d6541f0c535ca49cd0.tar.gz |
driver: Set all categories when changing locale
Previously, Initial Setup would only change the LC_MESSAGES locale
category when the user selects a different locale on the language page.
However, this caused non-ASCII characters to be mangled after switching
locale. The following test program demonstrates the problem:
#include "config.h"
#include <locale.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <libgweather/gweather.h>
gint
main (gint argc,
gchar *argv[])
{
/* gettext boilerplate */
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
/* Change locale to Czech */
locale_t locale = newlocale (LC_MESSAGES_MASK, "cs_CZ.utf8", (locale_t) 0);
g_assert (locale != (locale_t) 0);
uselocale (locale);
GWeatherLocation *world = gweather_location_get_world ();
GWeatherLocation *praha = gweather_location_find_nearest_city (world, 50.08804, 14.42076);
g_message ("%s", gweather_location_get_name (gweather_location_get_parent (praha)));
return 0;
}
The desired output is “Česká republika”, but this program instead prints
“?esk? republika”. The non-ASCII characters with diacritics are mangled.
The same problem exists in any locale: switch to an English locale in
this way, then search for “Abidjan”; it will be reported to be in “C?te
d’Ivoire”.
The issue appears to be that the LC_CTYPE category is not being changed.
According to locale(7):
> This category determines the interpretation of byte sequences as
> characters (e.g., single versus multibyte characters), character
> classifications (e.g., alphabetic or digit), and the behavior of
> character classes.
Rather than adding this category, just set all categories. It's true
that Initial Setup doesn't use, for instance, anything related to the
locale's measurement system (LC_MEASUREMENT, i.e. metric versus US
customary units) but it should be harmless to set them all.
The change in cc-common-language is probably unnecessary.
insert_language() is checking that the given locale actually exists on
the system before offering it to the user. Surely if
newlocale(LC_MESSAGES_MASK, x, 0) works then newlocale(LC_ALL_MASK, x,
0) will work? But there is no harm in using LC_ALL_MASK and the
consistency is clearer.
Fixes #177
-rw-r--r-- | gnome-initial-setup/cc-common-language.c | 2 | ||||
-rw-r--r-- | gnome-initial-setup/gis-driver.c | 2 |
2 files changed, 2 insertions, 2 deletions
diff --git a/gnome-initial-setup/cc-common-language.c b/gnome-initial-setup/cc-common-language.c index 16dd28f..514a9b9 100644 --- a/gnome-initial-setup/cc-common-language.c +++ b/gnome-initial-setup/cc-common-language.c @@ -241,7 +241,7 @@ insert_language (GHashTable *ht, char *label_untranslated; char *key; - locale = newlocale (LC_MESSAGES_MASK, lang, (locale_t) 0); + locale = newlocale (LC_ALL_MASK, lang, (locale_t) 0); if (locale == (locale_t) 0) { g_debug ("%s: Failed to create locale %s", G_STRFUNC, lang); return; diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c index 3d48629..ffd1548 100644 --- a/gnome-initial-setup/gis-driver.c +++ b/gnome-initial-setup/gis-driver.c @@ -213,7 +213,7 @@ gis_driver_set_user_language (GisDriver *driver, const gchar *lang_id, gboolean if (update_locale) { - locale_t locale = newlocale (LC_MESSAGES_MASK, lang_id, (locale_t) 0); + locale_t locale = newlocale (LC_ALL_MASK, lang_id, (locale_t) 0); if (locale == (locale_t) 0) { g_warning ("Failed to create locale %s: %s", lang_id, g_strerror (errno)); |