From 973b5be063e3ddd93500a6f1c6079588c8ff6622 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 19 Apr 2026 12:49:10 +0200 Subject: [PATCH] [PR #11824/39f4cda6 backport][stable-12] locale_gen: support locales not yet listed in /etc/locale.gen (#11883) locale_gen: support locales not yet listed in /etc/locale.gen (#11824) * locale_gen: support locales not yet listed in /etc/locale.gen On systems like Gentoo where /etc/locale.gen starts with only a handful of commented examples, set_locale_glibc() now appends missing locale entries sourced from /usr/share/i18n/SUPPORTED instead of silently doing nothing. Also extracts the shared locale-entry regex into a module-level constant RE_LOCALE_ENTRY. * locale_gen: add changelog fragment for issue 2399 --------- (cherry picked from commit 39f4cda6b5ce563cb6dc9dd83451f521f39719cb) Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 --- .../fragments/11824-locale-gen-gentoo.yml | 4 +++ plugins/modules/locale_gen.py | 36 +++++++++++++++---- 2 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 changelogs/fragments/11824-locale-gen-gentoo.yml diff --git a/changelogs/fragments/11824-locale-gen-gentoo.yml b/changelogs/fragments/11824-locale-gen-gentoo.yml new file mode 100644 index 0000000000..be5a89320d --- /dev/null +++ b/changelogs/fragments/11824-locale-gen-gentoo.yml @@ -0,0 +1,4 @@ +bugfixes: + - "locale_gen - add missing locale entries to ``/etc/locale.gen`` when not already present + (https://github.com/ansible-collections/community.general/issues/2399, + https://github.com/ansible-collections/community.general/pull/11824)." diff --git a/plugins/modules/locale_gen.py b/plugins/modules/locale_gen.py index 7723c11ab4..5b306eb440 100644 --- a/plugins/modules/locale_gen.py +++ b/plugins/modules/locale_gen.py @@ -87,6 +87,7 @@ ETC_LOCALE_GEN = "/etc/locale.gen" VAR_LIB_LOCALES = "/var/lib/locales/supported.d" VAR_LIB_LOCALES_LOCAL = os.path.join(VAR_LIB_LOCALES, "local") SUPPORTED_LOCALES = ["/usr/share/i18n/SUPPORTED", "/usr/local/share/i18n/SUPPORTED"] +RE_LOCALE_ENTRY = re.compile(r"^\s*#?\s*(?P\S+[\._\S]+) (?P\S+)\s*$") LOCALE_NORMALIZATION = { ".utf8": ".UTF-8", ".eucjp": ".EUC-JP", @@ -165,8 +166,7 @@ class LocaleGen(StateModuleHelper): with open(locale_path) as fd: self.vars.available_lines.extend(fd.readlines()) - re_locale_entry = re.compile(r"^\s*#?\s*(?P\S+[\._\S]+) (?P\S+)\s*$") - available_locale_entry_re_matches.extend([re_locale_entry.match(line) for line in self.vars.available_lines]) + available_locale_entry_re_matches.extend([RE_LOCALE_ENTRY.match(line) for line in self.vars.available_lines]) locales_not_found = [] for locale in self.vars.name: @@ -206,12 +206,24 @@ class LocaleGen(StateModuleHelper): name = name.replace(s, r) return name + def _get_charset_from_supported(self, locale): + """Look up the charset for a locale from the SUPPORTED files.""" + for locale_path in SUPPORTED_LOCALES: + if os.path.exists(locale_path): + with open(locale_path) as fd: + for line in fd: + match = RE_LOCALE_ENTRY.match(line) + if match and match.group("locale") == locale: + return match.group("charset") + return None + def set_locale_glibc(self, names, enabled=True): """Sets the state of the locale. Defaults to enabled.""" with open(ETC_LOCALE_GEN) as fr: lines = fr.readlines() - locale_regexes = [] + locale_regexes = {} + matched = set() for name in names: search_string = rf"^#?\s*{re.escape(name)} (?P.+)" @@ -219,16 +231,26 @@ class LocaleGen(StateModuleHelper): new_string = rf"{name} \g" else: new_string = rf"# {name} \g" - re_search = re.compile(search_string) - locale_regexes.append([re_search, new_string]) + locale_regexes[name] = (re.compile(search_string), new_string) def search_replace(line): - for [search, replace] in locale_regexes: - line = search.sub(replace, line) + for name, (search, replace) in locale_regexes.items(): + new_line = search.sub(replace, line) + if new_line != line: + matched.add(name) + line = new_line return line lines = [search_replace(line) for line in lines] + # For locales not found in /etc/locale.gen (e.g. on Gentoo), add them + if enabled: + for name in names: + if name not in matched: + charset = self._get_charset_from_supported(name) + if charset: + lines.append(f"{name} {charset}\n") + # Write the modified content back to the file with open(ETC_LOCALE_GEN, "w") as fw: fw.writelines(lines)