From fdba21526068665d7ee1ac8a7977522f6564e8cf Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Sun, 18 May 2025 12:35:11 +0300 Subject: [PATCH 1/3] i18n: Add charset related settings Fixes #404758 (cherry picked from commit e8581078a13f63278c8dadfcf7d44aeea0bc1dd8) --- doc/release-notes/rl-2505.section.md | 1 + nixos/modules/config/i18n.nix | 59 +++++++++++++++++++++------- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/doc/release-notes/rl-2505.section.md b/doc/release-notes/rl-2505.section.md index defb47f1e5b6..fb46f6ac04d6 100644 --- a/doc/release-notes/rl-2505.section.md +++ b/doc/release-notes/rl-2505.section.md @@ -374,6 +374,7 @@ - `i18n.extraLocales` should now be the preferred way to install additional locales. - `i18n.supportedLocales` is now considered an implementation detail and will be hidden from the documentation. But the option will still continue to work. - `i18n.supportedLocales` will now trigger a warning when it omits any locale set in `i18n.defaultLocale`, `i18n.extraLocales` or `i18n.extraLocaleSettings`. + - The options `i18n.defaultCharset` & `i18n.localeCharsets` were added, and they complement `i18n.defaultLocale` & `i18n.extraLocaleSettings` respectively - allowing to control the character set used per locale setting. - `titaniumenv`, `titanium`, and `titanium-alloy` have been removed due to lack of maintenance in Nixpkgs []{#sec-nixpkgs-release-25.05-incompatibilities-titanium-removed}. diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix index 42b91ff9628a..02498dd15363 100644 --- a/nixos/modules/config/i18n.nix +++ b/nixos/modules/config/i18n.nix @@ -5,15 +5,21 @@ ... }: let + sanitizeUTF8Capitalization = + lang: (lib.replaceStrings [ "utf8" "utf-8" "UTF8" ] [ "UTF-8" "UTF-8" "UTF-8" ] lang); aggregatedLocales = - (builtins.map - (l: (lib.replaceStrings [ "utf8" "utf-8" "UTF8" ] [ "UTF-8" "UTF-8" "UTF-8" ] l) + "/UTF-8") - ( - [ config.i18n.defaultLocale ] - ++ (lib.optionals (builtins.isList config.i18n.extraLocales) config.i18n.extraLocales) - ++ (lib.attrValues (lib.filterAttrs (n: v: n != "LANGUAGE") config.i18n.extraLocaleSettings)) - ) - ) + [ + "${config.i18n.defaultLocale}/${config.i18n.defaultCharset}" + ] + ++ lib.pipe config.i18n.extraLocaleSettings [ + # TODO: Explain why is this filter added here... + (lib.filterAttrs (n: v: n != "LANGUAGE")) + (lib.mapAttrs (n: v: (sanitizeUTF8Capitalization v))) + (lib.mapAttrsToList (LCRole: lang: lang + "/" + (config.i18n.localeCharsets.${LCRole} or "UTF-8"))) + ] + ++ (builtins.map sanitizeUTF8Capitalization ( + lib.optionals (builtins.isList config.i18n.extraLocales) config.i18n.extraLocales + )) ++ (lib.optional (builtins.isString config.i18n.extraLocales) config.i18n.extraLocales); in { @@ -48,16 +54,24 @@ in default = "en_US.UTF-8"; example = "nl_NL.UTF-8"; description = '' - The default locale. It determines the language for program - messages, the format for dates and times, sort order, and so on. - It also determines the character set, such as UTF-8. + The default locale. It determines the language for program messages, + the format for dates and times, sort order, and so on. Setting the + default character set is done via {option}`i18n.defaultCharset`. + ''; + }; + defaultCharset = lib.mkOption { + type = lib.types.str; + default = "UTF-8"; + example = "ISO-8859-8"; + description = '' + The default locale character set. ''; }; extraLocales = lib.mkOption { type = lib.types.either (lib.types.listOf lib.types.str) (lib.types.enum [ "all" ]); default = [ ]; - example = [ "nl_NL.UTF-8" ]; + example = [ "nl_NL.UTF-8/UTF-8" ]; description = '' Additional locales that the system should support, besides the ones configured with {option}`i18n.defaultLocale` and @@ -74,9 +88,24 @@ in LC_TIME = "de_DE.UTF-8"; }; description = '' - A set of additional system-wide locale settings other than - `LANG` which can be configured with - {option}`i18n.defaultLocale`. + A set of additional system-wide locale settings other than `LANG` + which can be configured with {option}`i18n.defaultLocale`. Note that + the `/UTF-8` suffix used in {option}`i18n.extraLocales` indicates a + character set, and it must not be added manually here. To use a + non-`UTF-8` character set such as ISO-XXXX-8, the + {option}`i18n.localeCharsets` can be used. + ''; + }; + localeCharsets = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + default = { }; + example = { + LC_MESSAGES = "ISO-8859-15"; + LC_TIME = "ISO-8859-1"; + }; + description = '' + Per each {option}`i18n.extraLocaleSettings`, choose the character set + to use for it. Essentially defaults to UTF-8 for all of them. ''; }; From 53efec63d6f19b6556d13146ee618242ae94d44f Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Sun, 18 May 2025 18:21:47 +0300 Subject: [PATCH 2/3] nixosTests.i18n: init (cherry picked from commit cbbd59e14e18f0aa98b2f4c962dfdeaf91d22785) --- nixos/tests/all-tests.nix | 1 + nixos/tests/i18n.nix | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 nixos/tests/i18n.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index f28dd70c29e9..5e277301b909 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -993,6 +993,7 @@ in orthanc = runTest ./orthanc.nix; owncast = handleTest ./owncast.nix { }; outline = handleTest ./outline.nix { }; + i18n = runTest ./i18n.nix; image-contents = handleTest ./image-contents.nix { }; openvscode-server = handleTest ./openvscode-server.nix { }; open-webui = runTest ./open-webui.nix; diff --git a/nixos/tests/i18n.nix b/nixos/tests/i18n.nix new file mode 100644 index 000000000000..a0493b7c62f5 --- /dev/null +++ b/nixos/tests/i18n.nix @@ -0,0 +1,43 @@ +{ lib, ... }: +{ + name = "glibLocales-custom-builds"; + meta.maintainers = with lib.maintainers; [ doronbehar ]; + + nodes = { + nonUTF8Charset = { + i18n = { + defaultLocale = "en_US"; + defaultCharset = "ISO-8859-1"; + }; + }; + extraLocales1 = { + i18n = { + defaultLocale = "en_US.UTF-8"; + extraLocales = [ + "nl_NL.UTF-8/UTF-8" + ]; + }; + }; + extraLocaleSettings = { + i18n = { + defaultLocale = "en_US.UTF-8"; + extraLocaleSettings = { + LC_MESSAGES = "en_US.UTF-8"; + LC_TIME = "de_DE.UTF-8"; + }; + }; + }; + localeCharsets = { + i18n = { + defaultLocale = "en_US.UTF-8"; + extraLocaleSettings = { + LC_TIME = "de_DE"; + }; + localeCharsets = { + LC_TIME = "ISO-8859-1"; + }; + }; + }; + }; + testScript = { nodes, ... }: ""; +} From ef5bc91e93fa4cfac047c05353f9a87f5c7bca66 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Sun, 18 May 2025 18:43:20 +0300 Subject: [PATCH 3/3] nixos/i18n: Remove special handling of LANGUAGE Partially revert #179194 which first filtered `extraLocaleSettings.LANGUAGE`. Indeed this environment variable is given precedence according to: https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html So using it will simply make all other `extraLocaleSettings` be ignored in practice, but the OS shouldn't ignore it when aggregating the locales required in general, as this setup should still be legitimate, and it may even be useful if you wish to set it by default and use `env -u LANGUAGE` for some programs. (cherry picked from commit 263297b4e5d3aa820be4b98e20e00a40e33aa4e7) --- nixos/modules/config/i18n.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix index 02498dd15363..22a47d5bdffa 100644 --- a/nixos/modules/config/i18n.nix +++ b/nixos/modules/config/i18n.nix @@ -12,8 +12,6 @@ let "${config.i18n.defaultLocale}/${config.i18n.defaultCharset}" ] ++ lib.pipe config.i18n.extraLocaleSettings [ - # TODO: Explain why is this filter added here... - (lib.filterAttrs (n: v: n != "LANGUAGE")) (lib.mapAttrs (n: v: (sanitizeUTF8Capitalization v))) (lib.mapAttrsToList (LCRole: lang: lang + "/" + (config.i18n.localeCharsets.${LCRole} or "UTF-8"))) ]