mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-07 22:02:50 +00:00
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. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * locale_gen: add changelog fragment for issue 2399 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
4
changelogs/fragments/11824-locale-gen-gentoo.yml
Normal file
4
changelogs/fragments/11824-locale-gen-gentoo.yml
Normal file
@@ -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)."
|
||||||
@@ -87,6 +87,7 @@ ETC_LOCALE_GEN = "/etc/locale.gen"
|
|||||||
VAR_LIB_LOCALES = "/var/lib/locales/supported.d"
|
VAR_LIB_LOCALES = "/var/lib/locales/supported.d"
|
||||||
VAR_LIB_LOCALES_LOCAL = os.path.join(VAR_LIB_LOCALES, "local")
|
VAR_LIB_LOCALES_LOCAL = os.path.join(VAR_LIB_LOCALES, "local")
|
||||||
SUPPORTED_LOCALES = ["/usr/share/i18n/SUPPORTED", "/usr/local/share/i18n/SUPPORTED"]
|
SUPPORTED_LOCALES = ["/usr/share/i18n/SUPPORTED", "/usr/local/share/i18n/SUPPORTED"]
|
||||||
|
RE_LOCALE_ENTRY = re.compile(r"^\s*#?\s*(?P<locale>\S+[\._\S]+) (?P<charset>\S+)\s*$")
|
||||||
LOCALE_NORMALIZATION = {
|
LOCALE_NORMALIZATION = {
|
||||||
".utf8": ".UTF-8",
|
".utf8": ".UTF-8",
|
||||||
".eucjp": ".EUC-JP",
|
".eucjp": ".EUC-JP",
|
||||||
@@ -165,8 +166,7 @@ class LocaleGen(StateModuleHelper):
|
|||||||
with open(locale_path) as fd:
|
with open(locale_path) as fd:
|
||||||
self.vars.available_lines.extend(fd.readlines())
|
self.vars.available_lines.extend(fd.readlines())
|
||||||
|
|
||||||
re_locale_entry = re.compile(r"^\s*#?\s*(?P<locale>\S+[\._\S]+) (?P<charset>\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 = []
|
locales_not_found = []
|
||||||
for locale in self.vars.name:
|
for locale in self.vars.name:
|
||||||
@@ -206,12 +206,24 @@ class LocaleGen(StateModuleHelper):
|
|||||||
name = name.replace(s, r)
|
name = name.replace(s, r)
|
||||||
return name
|
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):
|
def set_locale_glibc(self, names, enabled=True):
|
||||||
"""Sets the state of the locale. Defaults to enabled."""
|
"""Sets the state of the locale. Defaults to enabled."""
|
||||||
with open(ETC_LOCALE_GEN) as fr:
|
with open(ETC_LOCALE_GEN) as fr:
|
||||||
lines = fr.readlines()
|
lines = fr.readlines()
|
||||||
|
|
||||||
locale_regexes = []
|
locale_regexes = {}
|
||||||
|
matched = set()
|
||||||
|
|
||||||
for name in names:
|
for name in names:
|
||||||
search_string = rf"^#?\s*{re.escape(name)} (?P<charset>.+)"
|
search_string = rf"^#?\s*{re.escape(name)} (?P<charset>.+)"
|
||||||
@@ -219,16 +231,26 @@ class LocaleGen(StateModuleHelper):
|
|||||||
new_string = rf"{name} \g<charset>"
|
new_string = rf"{name} \g<charset>"
|
||||||
else:
|
else:
|
||||||
new_string = rf"# {name} \g<charset>"
|
new_string = rf"# {name} \g<charset>"
|
||||||
re_search = re.compile(search_string)
|
locale_regexes[name] = (re.compile(search_string), new_string)
|
||||||
locale_regexes.append([re_search, new_string])
|
|
||||||
|
|
||||||
def search_replace(line):
|
def search_replace(line):
|
||||||
for [search, replace] in locale_regexes:
|
for name, (search, replace) in locale_regexes.items():
|
||||||
line = search.sub(replace, line)
|
new_line = search.sub(replace, line)
|
||||||
|
if new_line != line:
|
||||||
|
matched.add(name)
|
||||||
|
line = new_line
|
||||||
return line
|
return line
|
||||||
|
|
||||||
lines = [search_replace(line) for line in lines]
|
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
|
# Write the modified content back to the file
|
||||||
with open(ETC_LOCALE_GEN, "w") as fw:
|
with open(ETC_LOCALE_GEN, "w") as fw:
|
||||||
fw.writelines(lines)
|
fw.writelines(lines)
|
||||||
|
|||||||
Reference in New Issue
Block a user