Skip to content

feat(i18n): add gettext zh_CN runtime POC - #1775

Open
WeissHymmnos wants to merge 1 commit into
HyDE-Project:devfrom
WeissHymmnos:feat-zh-cn-i18n
Open

feat(i18n): add gettext zh_CN runtime POC#1775
WeissHymmnos wants to merge 1 commit into
HyDE-Project:devfrom
WeissHymmnos:feat-zh-cn-i18n

Conversation

@WeissHymmnos

@WeissHymmnos WeissHymmnos commented Jun 6, 2026

Copy link
Copy Markdown

Summary

This PR adds a small gettext-based runtime i18n proof of concept for HyDE, focused on Simplified Chinese (zh_CN). It replaces the earlier custom JSON language-pack direction with a more standard gettext-style workflow.

The scope is intentionally small: this PR establishes the foundation and demonstrates it on notifications and the keybinding hint UI only.

Changes

  • Add gettext translation sources under Source/locale/:
    • hyde.pot
    • zh_CN/LC_MESSAGES/hyde.po
    • build.py
    • README.md
  • Track generated runtime artifacts:
    • Configs/.local/share/hyde/locale/zh_CN/LC_MESSAGES/hyde.mo
    • Configs/.local/share/hyde/locale/zh_CN.sh
  • Add a Python gettext helper:
    • Configs/.local/lib/hyde/pyutils/i18n.py
  • Upgrade the existing Bash localization POC:
    • Configs/.local/lib/hyde/shutils/l10n.sh
  • Localize a small set of high-impact runtime strings in:
    • Configs/.local/lib/hyde/notifications.py
    • Configs/.local/lib/hyde/keybinds_hint.sh

Design notes

  • .po files are the editable translation source.
  • .mo files are generated for Python/gettext consumers.
  • Bash uses a lightweight generated associative-array map from the same .po file.
  • Language resolution order is HYDE_LANG, I18N_LANGUAGE, LC_MESSAGES, LANG, then English/original strings.
  • Missing translation files and missing keys fall back to the original English strings.
  • This PR does not localize the installer, Waybar-wide strings, or the rest of the repository.

Test plan

Passed locally:

python3 Source/locale/build.py
msgfmt --check --output-file=/tmp/hyde-zh_CN-check.mo Source/locale/zh_CN/LC_MESSAGES/hyde.po
python3 -m py_compile Source/locale/build.py Configs/.local/lib/hyde/pyutils/i18n.py Configs/.local/lib/hyde/notifications.py
bash -n Configs/.local/lib/hyde/shutils/l10n.sh Configs/.local/lib/hyde/keybinds_hint.sh Configs/.local/share/hyde/locale/zh_CN.sh
shellcheck Configs/.local/lib/hyde/shutils/l10n.sh Configs/.local/lib/hyde/keybinds_hint.sh Configs/.local/share/hyde/locale/zh_CN.sh
git diff --check
pre-commit run --files <changed files>

Also tested with fake desktop commands:

  • HYDE_LANG=zh_CN makes notifications.py output Chinese tooltip labels.
  • HYDE_LANG=en keeps English notification labels.
  • Missing locale files fall back to English/default strings without crashing.
  • HYDE_LANG=zh_CN makes keybinds_hint.sh use Chinese no-rofi text, Rofi labels, and repeat prompt text.
  • HYDE_LANG takes precedence over an existing DESKTOP_LANG value.

I did not use full pre-commit run --all-files because the upstream baseline still includes unrelated full-repo issues such as the known broken symlink.

Summary by CodeRabbit

  • New Features

    • Added internationalization (i18n) infrastructure with Simplified Chinese runtime localization as a proof-of-concept, enabling translated notification actions and keybinding hint labels.
    • Language selection via HYDE_LANG, I18N_LANGUAGE, LC_MESSAGES, or LANG environment variables; falls back to English when translations are unavailable.
  • Documentation

    • Added localization workflow documentation and build tooling for managing translation assets.

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds gettext-based runtime localization infrastructure to HyDE. Python and Bash modules provide translation utilities; a build system manages .pot/.po/.mo artifacts and generates Bash locale maps; keybinds and notifications scripts are integrated to use localized strings; and initial Simplified Chinese translations are supplied.

Changes

Internationalization Infrastructure and Gettext Integration

Layer / File(s) Summary
Python i18n Module
Configs/.local/lib/hyde/pyutils/i18n.py
DOMAIN constant and t() function for gettext translation with locale normalization, environment-based language selection, cached loading, fallback handling, and optional % interpolation.
Bash l10n Module
Configs/.local/lib/hyde/shutils/l10n.sh
Locale normalization, directory resolution, sourcing of translation maps from share/config directories, and hyde_gettext helper for associative-array translation lookup with fallback. Also updates send_notifs and print_log_L to translate message arguments.
Keybinds Hint Integration
Configs/.local/lib/hyde/keybinds_hint.sh
Sources l10n.sh and uses hyde_gettext to localize trap messages, error notifications, rofi UI labels (header, repeat prompt), and repeat confirmation logic.
Notifications Integration
Configs/.local/lib/hyde/notifications.py
Imports and uses the t() i18n function to localize tooltip action labels; emits UTF-8 JSON via ensure_ascii=False.
Locale Build System
Source/locale/build.py
Python script orchestrating the full gettext pipeline: POT template generation, PO file merging, MO binary compilation, and Bash locale map generation; includes header normalization, PO parsing, and ANSI-C Bash quoting helpers.
Localization Resources
Source/locale/hyde.pot, Source/locale/zh_CN/LC_MESSAGES/hyde.po, Configs/.local/share/hyde/locale/zh_CN.sh
Gettext template, Simplified Chinese translations for notifications and keybind hints, and generated Bash associative-array locale map.
Documentation
Source/locale/README.md, CHANGELOG.md
Explains gettext-based localization architecture, language selection precedence, runtime consumer behavior, translation regeneration workflow, and changelog entry for the i18n POC.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Poem

🐰 The locale strings now dance in Chinese hue,
Gettext maps bubble through Bash and Python true,
Build scripts weave .po threads tight,
Every notification glows with translation's light,
Keybinds speak in many tongues—what a sight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.12% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding gettext-based zh_CN runtime localization as a POC, which is the primary purpose of this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Configs/.local/lib/hyde/i18n.sh`:
- Around line 13-14: The i18n normalization maps "zh_TW | zh_HK | zh_MO" to
"zh_TW" in Configs/.local/lib/hyde/i18n.sh but there is no corresponding
zh_TW.json in Configs/.local/share/hyde/i18n/, so Traditional Chinese
translations will be missing; fix by either adding a zh_TW.json translation file
to Configs/.local/share/hyde/i18n/ with the needed strings, or change the
normalization in i18n.sh (the case that currently returns "zh_TW") to map those
locales to an existing locale (e.g., "zh_CN") or to a documented fallback value,
and update any README/docs to state the chosen fallback behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d17344dc-5ea0-4853-a30d-5176619dfb8a

📥 Commits

Reviewing files that changed from the base of the PR and between e024636 and f493f8d.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • Configs/.local/lib/hyde/i18n.sh
  • Configs/.local/lib/hyde/keybinds_hint.sh
  • Configs/.local/lib/hyde/notifications.py
  • Configs/.local/lib/hyde/pyutils/i18n.py
  • Configs/.local/share/hyde/i18n/en.json
  • Configs/.local/share/hyde/i18n/zh_CN.json

Comment thread Configs/.local/lib/hyde/i18n.sh Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Configs/.local/lib/hyde/pyutils/i18n.py (1)

43-50: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Broaden exception handling to prevent crashes on invalid JSON structure or I/O errors.

The function can crash in several scenarios not covered by the current exception handling:

  1. Non-dict JSON root: If the JSON file contains [], "string", or 123, line 50's data.items() raises AttributeError.
  2. I/O errors: read_text() can raise UnicodeDecodeError (invalid UTF-8), PermissionError, or other OSError variants that aren't caught.

The Bash contract (context snippet 3) checks file readability and gracefully returns empty on errors.

🛡️ Recommended fix to handle all errors gracefully
 `@lru_cache`(maxsize=None)
 def _load(lang: str) -> dict[str, str]:
     path = _base_dir() / f"{lang}.json"
     try:
         data = json.loads(path.read_text(encoding="utf-8"))
-    except (FileNotFoundError, json.JSONDecodeError):
+        if not isinstance(data, dict):
+            return {}
+    except (FileNotFoundError, json.JSONDecodeError, OSError):
         return {}
     return {key: value for key, value in data.items() if isinstance(value, str)}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Configs/.local/lib/hyde/pyutils/i18n.py` around lines 43 - 50, The
_load(lang: str) function should tolerate non-dict JSON roots and I/O/decoding
errors; update its error handling so that any exceptions from path.read_text()
(e.g., OSError, UnicodeDecodeError) and JSON parsing are caught and that the
parsed data is validated as a dict before calling data.items() (e.g., check
isinstance(data, dict) and return {} otherwise). In short: wrap
read_text/json.loads in a broader try/except (catch OSError, UnicodeDecodeError,
json.JSONDecodeError) and after parsing guard against non-dict roots (or catch
AttributeError/TypeError) and return {} on any failure, leaving the
`@lru_cache-decorated` _load signature intact.
🧹 Nitpick comments (1)
Configs/.local/lib/hyde/pyutils/i18n.py (1)

16-16: ⚡ Quick win

Dead code: empty string check is unreachable.

Line 8 converts empty string to "en" via the or operator before any checks, so the "" case on line 16 can never match. The behavior is still correct (empty becomes "en"), but the check is confusing.

♻️ Simplify by removing unreachable condition
-    if lang in {"", "C", "POSIX"}:
+    if lang in {"C", "POSIX"}:
         return "en"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Configs/.local/lib/hyde/pyutils/i18n.py` at line 16, The check `if lang in
{"", "C", "POSIX"}:` contains an unreachable `""` branch because `lang` is
normalized earlier with `lang = lang or "en"`; remove the empty-string literal
from the set so the condition becomes `if lang in {"C", "POSIX"}:` (locate the
check by searching for the `lang` variable and the `if lang in` expression in
i18n.py) and run tests to confirm behavior remains the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@Configs/.local/lib/hyde/pyutils/i18n.py`:
- Around line 43-50: The _load(lang: str) function should tolerate non-dict JSON
roots and I/O/decoding errors; update its error handling so that any exceptions
from path.read_text() (e.g., OSError, UnicodeDecodeError) and JSON parsing are
caught and that the parsed data is validated as a dict before calling
data.items() (e.g., check isinstance(data, dict) and return {} otherwise). In
short: wrap read_text/json.loads in a broader try/except (catch OSError,
UnicodeDecodeError, json.JSONDecodeError) and after parsing guard against
non-dict roots (or catch AttributeError/TypeError) and return {} on any failure,
leaving the `@lru_cache-decorated` _load signature intact.

---

Nitpick comments:
In `@Configs/.local/lib/hyde/pyutils/i18n.py`:
- Line 16: The check `if lang in {"", "C", "POSIX"}:` contains an unreachable
`""` branch because `lang` is normalized earlier with `lang = lang or "en"`;
remove the empty-string literal from the set so the condition becomes `if lang
in {"C", "POSIX"}:` (locate the check by searching for the `lang` variable and
the `if lang in` expression in i18n.py) and run tests to confirm behavior
remains the same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 026fcc4c-b910-4210-8aae-1cd0bf8866d4

📥 Commits

Reviewing files that changed from the base of the PR and between f493f8d and 0dd532d.

📒 Files selected for processing (2)
  • Configs/.local/lib/hyde/i18n.sh
  • Configs/.local/lib/hyde/pyutils/i18n.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • Configs/.local/lib/hyde/i18n.sh

@kRHYME7

kRHYME7 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

iirc there is a standard way to do this . python uses that already and other language. and I remembered I tried making a translation for bash too. Let me check again I forgot about that template

@kRHYME7

kRHYME7 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

So My Idea is to have a .po file for translations. Then we just need to generate a .mo files that will be use for python and lua or go using the gettext lib.
for bash we can make script that reads the .po file then makes a hash table (associative array ) and maps the translation. this way we will have minimal changes in the code.

@kRHYME7

kRHYME7 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Some of you ideas are amazing. Will try to head to that direction.

@WeissHymmnos

Copy link
Copy Markdown
Author

That sounds good to me. Using gettext with .po / .mo files is probably more standard and easier to maintain long-term.

@WeissHymmnos WeissHymmnos changed the title feat(i18n): add zh_CN runtime language pack feat(i18n): add gettext zh_CN runtime POC Jun 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Configs/.local/lib/hyde/pyutils/i18n.py`:
- Around line 9-18: The _normalize_locale function currently preserves original
casing for most locales; update it to produce canonical casing (lowercase
language, uppercase territory) after stripping modifiers and replacing hyphens
with underscores. In _normalize_locale, after computing lang = ... and lang =
lang.replace("-", "_"), split lang on "_" into parts; if there are two parts
(language and territory) return f"{parts[0].lower()}_{parts[1].upper()}"; if
there is one part return parts[0].lower(); keep the existing special-case
returns for "", "c", "posix" -> "en" and the zh variants -> "zh_CN", and ensure
you still return lang (now normalized) at the end.

In `@Configs/.local/lib/hyde/shutils/l10n.sh`:
- Around line 4-22: The _hyde_l10n_normalize_locale function currently returns
the original $lang for non-special cases which preserves user casing; change the
default normalization to produce a consistent format of lowercase language and
uppercase territory with an underscore separator (e.g., fr_FR): transform $lang
to use '_' not '-', split on '_' (or '-') into language and territory, lowercase
the language token, uppercase the territory token if present, then printf the
reconstructed value; keep the special-cased zh/zh_CN behavior and only apply
this normalization in the default (*) branch so functions like
_hyde_l10n_normalize_locale always return a predictable casing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4801b530-6ef8-42d5-afe3-b9e66ce5c363

📥 Commits

Reviewing files that changed from the base of the PR and between 493631e and 780efcd.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • Configs/.local/lib/hyde/keybinds_hint.sh
  • Configs/.local/lib/hyde/notifications.py
  • Configs/.local/lib/hyde/pyutils/i18n.py
  • Configs/.local/lib/hyde/shutils/l10n.sh
  • Configs/.local/share/hyde/locale/zh_CN.sh
  • Configs/.local/share/hyde/locale/zh_CN/LC_MESSAGES/hyde.mo
  • Source/locale/README.md
  • Source/locale/build.py
  • Source/locale/hyde.pot
  • Source/locale/zh_CN/LC_MESSAGES/hyde.po
✅ Files skipped from review due to trivial changes (5)
  • Source/locale/hyde.pot
  • Configs/.local/share/hyde/locale/zh_CN.sh
  • Source/locale/README.md
  • Source/locale/zh_CN/LC_MESSAGES/hyde.po
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • Configs/.local/lib/hyde/keybinds_hint.sh
  • Configs/.local/lib/hyde/notifications.py

Comment on lines +9 to +18
def _normalize_locale(lang: str | None) -> str:
lang = (lang or "en").split(":", 1)[0].split(".", 1)[0].split("@", 1)[0]
lang = lang.replace("-", "_")
lowered = lang.lower()

if lowered in {"", "c", "posix"}:
return "en"
if lowered in {"zh", "zh_cn", "zh_sg"}:
return "zh_CN"
return lang

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Locale normalization doesn't standardize case for non-special-cased locales.

The function preserves the original casing after basic transformations (strip modifiers, replace hyphens) for all locales except the hardcoded special cases. Standard locale identifiers use lowercase language codes and uppercase territory codes (e.g., fr_FR, de_DE). If a user sets LANG=FR_FR or LANG=fr-fr, the normalization will produce FR_FR or fr_fr respectively, but gettext will look for directories with those exact names. If future locale directories follow the standard fr_FR pattern, lookups will fail for non-canonical casings.

Currently this only affects hypothetical future locales, since zh_CN is explicitly normalized. Consider normalizing all locales to lowercase language + uppercase territory to handle arbitrary LANG values robustly.

Suggested fix to normalize case consistently
 def _normalize_locale(lang: str | None) -> str:
     lang = (lang or "en").split(":", 1)[0].split(".", 1)[0].split("@", 1)[0]
     lang = lang.replace("-", "_")
-    lowered = lang.lower()
+    parts = lang.split("_", 1)
+    normalized = parts[0].lower() + ("_" + parts[1].upper() if len(parts) > 1 else "")

-    if lowered in {"", "c", "posix"}:
+    if normalized in {"", "c", "posix"}:
         return "en"
-    if lowered in {"zh", "zh_cn", "zh_sg"}:
+    if normalized in {"zh", "zh_CN", "zh_SG"}:
         return "zh_CN"
-    return lang
+    return normalized
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Configs/.local/lib/hyde/pyutils/i18n.py` around lines 9 - 18, The
_normalize_locale function currently preserves original casing for most locales;
update it to produce canonical casing (lowercase language, uppercase territory)
after stripping modifiers and replacing hyphens with underscores. In
_normalize_locale, after computing lang = ... and lang = lang.replace("-", "_"),
split lang on "_" into parts; if there are two parts (language and territory)
return f"{parts[0].lower()}_{parts[1].upper()}"; if there is one part return
parts[0].lower(); keep the existing special-case returns for "", "c", "posix" ->
"en" and the zh variants -> "zh_CN", and ensure you still return lang (now
normalized) at the end.

Comment on lines +4 to +22
_hyde_l10n_normalize_locale() {
local lang="${1:-${HYDE_LANG:-${I18N_LANGUAGE:-${LC_MESSAGES:-${LANG:-en}}}}}"
lang="${lang%%:*}"
lang="${lang%%.*}"
lang="${lang%%@*}"
lang="${lang//-/_}"

# Initialize the _T associative array for translations
declare -A _T 2>/dev/null || : # Localization support
[[ -f "${XDG_DATA_HOME:-$HOME/.local/share}/hyde/locale/${DESKTOP_LANG}.sh" ]] && source "${XDG_DATA_HOME:-$HOME/.local/share}/hyde/locale/${DESKTOP_LANG}.sh"
[[ -f "${XDG_CONFIG_HOME:-$HOME/.config}/hyde/locale/${DESKTOP_LANG}.sh" ]] && source "${XDG_CONFIG_HOME:-$HOME/.config}/hyde/locale/${DESKTOP_LANG}.sh"
case "${lang,,}" in
"" | c | posix)
printf '%s\n' "en"
;;
zh | zh_cn | zh_sg)
printf '%s\n' "zh_CN"
;;
*)
printf '%s\n' "$lang"
;;
esac
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Locale normalization doesn't standardize case for non-special-cased locales.

This Bash function has the same case-preservation behavior as the Python version in i18n.py. The case "${lang,,}" statement lowercases for comparison, but line 19 returns the original $lang for non-special-cased locales. If a user sets LANG=FR_FR or LANG=fr-fr, the function will return FR_FR or fr_fr, but the locale map files are expected to match the exact casing of the source directory structure.

Since only zh_CN is currently special-cased to always return "zh_CN", this works today. Future locales should either be special-cased or the normalization should enforce lowercase language + uppercase territory for consistency.

Suggested fix to normalize case consistently
     case "${lang,,}" in
         "" | c | posix)
             printf '%s\n' "en"
             ;;
         zh | zh_cn | zh_sg)
             printf '%s\n' "zh_CN"
             ;;
         *)
-            printf '%s\n' "$lang"
+            # Normalize to lowercase language + uppercase territory
+            if [[ "$lang" =~ ^([a-zA-Z]+)_([a-zA-Z]+)$ ]]; then
+                printf '%s\n' "${BASH_REMATCH[1],,}_${BASH_REMATCH[2]^^}"
+            else
+                printf '%s\n' "${lang,,}"
+            fi
             ;;
     esac
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Configs/.local/lib/hyde/shutils/l10n.sh` around lines 4 - 22, The
_hyde_l10n_normalize_locale function currently returns the original $lang for
non-special cases which preserves user casing; change the default normalization
to produce a consistent format of lowercase language and uppercase territory
with an underscore separator (e.g., fr_FR): transform $lang to use '_' not '-',
split on '_' (or '-') into language and territory, lowercase the language token,
uppercase the territory token if present, then printf the reconstructed value;
keep the special-cased zh/zh_CN behavior and only apply this normalization in
the default (*) branch so functions like _hyde_l10n_normalize_locale always
return a predictable casing.

@github-actions

Copy link
Copy Markdown
Contributor

This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants