i18n-locale-config
Locale identification and configuration: BCP 47 locale ID structure, the language-vs-country doctrine, per-language collation order, timezone handling, and the region/language matrix. Use when: choosing a locale code, configuring locales/<lang>.json, fixing sort order for a language, or deciding which timezone a deliverable should display.
- License 许可
- AGPL-3.0
- 最近更新
- 2026-11-14
- Stars
- ★ 25
- Forks
- 9
01 前言 Front Matter
- name
- i18n-locale-config
- owner
- i18n-specialist
- scope
- common
- status
- active
- version
- 1.0.1
- metadata
- { "type": "process", "triggers": [ "locale config", "locale code", "BCP 47", "collation", "collation order", "timezone" ] }
- description
- Locale identification and configuration: BCP 47 locale ID structure, the language-vs-country doctrine, per-language collation order, timezone handling, and the region/language matrix. Use when: choosing a locale code, configuring locales/<lang>.json, fixing sort order for a language, or deciding which timezone a deliverable should display.
- last_reviewed
- 1787529600000
03 SKILL.md 正文
Purpose
Defines how the workspace identifies and configures locales. A locale ID is not decoration — it selects collation order, date/number rendering (see the i18n-formatting skill), casing rules, and default timezone display. This skill covers ID structure, the country ≠ language doctrine, collation, timezones, and the supported-locale matrix.
BCP 47 Locale ID Structure
Locale IDs follow BCP 47 / IETF language tags: language[-Script][-REGION][-variant].
| Subtag | Case | Examples | Notes |
|---|---|---|---|
language |
lowercase | en, ko, zh, pt |
ISO 639-1 (two-letter) primary language |
Script |
Titlecase | Hans, Hant, Latn |
ISO 15924; usually inferable, required when a language uses multiple scripts |
REGION |
UPPERCASE | KR, CN, TW, CH, BR |
ISO 3166-1 alpha-2; selects regional conventions, not the country itself |
| variant | lowercase | valencia |
Rare; only when a subtag genuinely changes behavior |
Canonical examples in this workspace:
ko— Korean (regionKRimplied by convention; add-KRonly when disambiguating)zh-CN— Chinese, Simplified script, mainland conventions (ScriptHansimplied)zh-TW— Chinese, Traditional script, Taiwan conventions (ScriptHantimplied)de-CH— German with Swiss conventions (e.g.ssinstead ofß)pt-BRvspt-PT— Brazilian and European Portuguese differ in spelling and formal address
Rules:
- Case is normative:
zh-cnis malformed; writezh-CN. - Do not invent region subtags to encode a target country — the target country lives in the variant's
country_config, never in i18n settings (see below). - Locale files follow constitution §4.2:
locales/<lang-code>.json, flat key-value, withen.jsonas the source of truth for every key.
Language ≠ Country
Constitution §4.3 doctrine — the two axes are independent:
- One country, many languages: CH →
de/fr/it; a Swiss deliverable needs a language decision before a locale decision. - One language, many countries:
enspans dozens of countries;enalone does not encode a market. zh-CN/zh-TWare language+region hybrids — they are locale IDs, never country codes. Mapping "Taiwan market" tozh-TWfor content language is correct; storingzh-TWin a country field is a data-model error.- A country profile's Language & Communication Defaults section references
i18n.locale_codes; it never redefines the project's documentation language.
Consequence for asset registration: language-scoped assets (this suite, the translate skill) are never registered in country_scoped_assets — that registry is for skills whose data access is jurisdiction-specific.
Collation
Sort order is locale-specific. Default Unicode code-point order (what Array.prototype.sort does without a comparator) is wrong for almost every non-English locale.
Always use Intl.Collator (or the platform equivalent) with an explicit locale:
// WRONG — code-point order ignores locale collation rules
["zeta", "Arche", "apple"].sort();
// RIGHT — locale collation (German: umlauts follow locale-specific ordering)
["zeta", "Arche", "apple"].sort(new Intl.Collator("de").compare);
Korean collation specifics (romanized terms — Korean text itself belongs in Korean deliverables, not in English documentation):
- Korean sorts in ganada order — the syllabary's canonical sequence, whose first three syllables romanize as ga-na-da. This is the dictionary order a Korean reader expects.
- Ganada order is not Unicode code-point order: plain
Array.prototype.sort()on Korean text yields code-block order, which misplaces extended and rarely-used syllables.Intl.Collator("ko")applies ganada order correctly — never sort Korean strings without it. - Mixing Hangul and Latin in one list:
kocollation conventionally places ASCII after Hangul; verify with the actual collator rather than assuming.
Collation options that matter:
| Option | Effect | Use when |
|---|---|---|
numeric: true |
"file-2" sorts before "file-10" | Sorting identifiers, filenames, numbered sections |
sensitivity: "base" |
Case- and accent-insensitive | User-facing search/dedup |
sensitivity: "variant" |
Full distinction (default for many locales) | When diacritics change meaning (de umlauts) |
ignorePunctuation: true |
Skips punctuation weights | Loose list sorting |
Locale-divergent examples: Swedish ö sorts after z (not next to o as in German); German ä may sort as ae in phone-book order (de-DE-u-co-phonebk). When sorting user-visible lists, pin the locale explicitly and test with accented input.
Timezone Handling
Rules:
- Store and interchange in UTC (or an explicit offset); convert only at display time.
- Name timezones with IANA identifiers —
Asia/Seoul,Europe/Zurich,America/New_York. Never store fixed abbreviations (KST,CET) as primary data: they are ambiguous and ignore daylight-saving transitions. - Display per locale: the same instant renders with different conventions per locale.
// Same instant, two locales — note date can differ across zones
new Intl.DateTimeFormat("en-US", {
timeZone: "Asia/Seoul",
dateStyle: "medium",
timeStyle: "short",
}).format(new Date("2026-08-24T15:00:00Z"));
// "Aug 25, 2026, 12:00:00 AM" (KST is UTC+9, no DST)
new Intl.DateTimeFormat("ko", {
timeZone: "Asia/Seoul",
dateStyle: "medium",
timeStyle: "short",
}).format(new Date("2026-08-24T15:00:00Z"));
// Korean-locale rendering of the same midnight instant
Convention notes:
Asia/Seoulis UTC+9 with no daylight-saving time — safe for fixed-offset reasoning, but still use the IANA name.- US zones (
America/*) shift twice a year; never cache a fixed offset for them. - A locale does not determine a timezone:
enrenders in whatever zone the user is in. Locale selects format; timezone is a separate, explicit parameter.
Region/Language Matrix
The baseline set is the 16 supported locales of constitution §4.1: en (default), ko, ja, zh-CN, zh-TW, de, es, fr, pt, vi, ms, id, th, ru, it, ar.
When configuring a project or adding a locale:
- Start from the variant's actual audience — a region/language matrix row exists only when the market needs it (e.g.
CH → de, fr, it). - Every key present in any locale file must exist in
en.json(§4.2); missing keys fail closed toen. - Adding a locale is a language decision. Adding a country profile is a jurisdiction decision (constitution §7.3.5, ADR-0057). They proceed through different registries and must not be conflated.
aractivation implies RTL layout obligations — see thei18n-layoutskill before shipping anarlocale.
Boundary
- Rendering formats (dates, numbers, currency) for a chosen locale:
i18n-formatting. - Encoding, RTL/bidi mechanics, fonts:
i18n-layout. - Translating a specific file (hash sync, diff preview): the
translateskill.
04 同仓库更多 Skills
i18n-layout
Text layout and encoding guidance: character encoding (UTF-8, legacy Korean code pages, BOM hazards), line endings, RTL/bidi handling, and script-specific font selection (Hangul focus). Use when: encoding is corrupted or mojibake appears, an RTL locale must render correctly, fonts must be chosen for a script, or CRLF/BOM issues surface.
i18n-layout
Text layout and encoding guidance: character encoding (UTF-8, legacy Korean code pages, BOM hazards), line endings, RTL/bidi handling, and script-specific font selection (Hangul focus). Use when: encoding is corrupted or mojibake appears, an RTL locale must render correctly, fonts must be chosen for a script, or CRLF/BOM issues surface.
i18n-layout
Text layout and encoding guidance: character encoding (UTF-8, legacy Korean code pages, BOM hazards), line endings, RTL/bidi handling, and script-specific font selection (Hangul focus). Use when: encoding is corrupted or mojibake appears, an RTL locale must render correctly, fonts must be chosen for a script, or CRLF/BOM issues surface.
i18n-layout
Text layout and encoding guidance: character encoding (UTF-8, legacy Korean code pages, BOM hazards), line endings, RTL/bidi handling, and script-specific font selection (Hangul focus). Use when: encoding is corrupted or mojibake appears, an RTL locale must render correctly, fonts must be chosen for a script, or CRLF/BOM issues surface.
i18n-layout
Text layout and encoding guidance: character encoding (UTF-8, legacy Korean code pages, BOM hazards), line endings, RTL/bidi handling, and script-specific font selection (Hangul focus). Use when: encoding is corrupted or mojibake appears, an RTL locale must render correctly, fonts must be chosen for a script, or CRLF/BOM issues surface.
i18n-layout
Text layout and encoding guidance: character encoding (UTF-8, legacy Korean code pages, BOM hazards), line endings, RTL/bidi handling, and script-specific font selection (Hangul focus). Use when: encoding is corrupted or mojibake appears, an RTL locale must render correctly, fonts must be chosen for a script, or CRLF/BOM issues surface.