Skip to content

feat(i18n-ko): core — add ko to UiLocale model - #5011

Draft
heeoneie wants to merge 1 commit into
apache:mainfrom
heeoneie:feat/i18n-ko-core-ui-locale
Draft

feat(i18n-ko): core — add ko to UiLocale model#5011
heeoneie wants to merge 1 commit into
apache:mainfrom
heeoneie:feat/i18n-ko-core-ui-locale

Conversation

@heeoneie

@heeoneie heeoneie commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Do not merge. This is the shared core base for the Korean locale stack, opened as a draft at @me2seeks's request on #3975. It must not land on main on its own.

Refs #3975. Part of #3974.

Why this cannot merge alone

UiCatalog<T> is Record<UiLocale, T>, so adding ko to UI_LOCALES makes every catalog in the repository require a ko entry — 126 of them at the time I counted. This branch enables the locale; the catalogs arrive here and in the slice PRs. CI on this branch is expected to be red until every strict catalog is complete. That is the atomic/stacked delivery model working as intended, not a regression.

Delivery contract

Per @me2seeks's decision on #3975:

What is here now

  • UI_LOCALES gains ko; isUiLocale and isUiLocalePreference accept it.
  • resolveSystemUiLocale recognises ko via /^ko(?:[-.]|$)/iu, reusing the existing trim and _- normalisation.
  • uiLocaleToIntlLocale maps koko-KR and returns the literal union 'zh-CN' | 'zh-TW' | 'en' | 'ko-KR' rather than widening to string, so the set of tags we actually emit stays visible in the signature. Adopted from @scs0209's shape in feat(i18n-ko): native surfaces and E2E fixtures #4515 — we reached the same mapping independently.
  • Locale tests, including kok-IN → en so that a later simplification of the pattern to /^ko/i cannot silently start matching Konkani, and both system-language ordering assertions (['en', 'ko'] → en, ['ko', 'en'] → ko).

Landing next on this branch

The three core catalogs that block @maka/core from compiling with ko, per the delivery decision: redaction.ts (GENERALIZED_ERROR_COPY), relative-time.ts (JUST_NOW) and tool-quiet-preview.ts (STRINGS_BY_LOCALE).

Notes

  • The ['zh', 'en'] in feat(i18n-ko): core — add ko to UiLocale model #3975's body is stale. UI_LOCALES is ['zh-CN', 'zh-TW', 'en'] on main since feat(i18n): add Traditional Chinese locale #3853, and zh survives only as a legacy persisted value that normalizeUiLocalePreference folds into zh-CN.
  • The existing test asserted uiLocaleToIntlLocale(locale) === locale. ko is the first locale to break that identity, so it is replaced with a pinned tag table plus a new Intl.Locale(tag).baseName === tag canonicality check.
  • The type-invisible locale paths I catalogued on feat(i18n-ko): core — add ko to UiLocale model #3975 — E2E/Storybook locale globals, hardcoded locale branches, parseLocaleFlag — are not addressed here. @me2seeks asked for them to be assigned before integration; I will open a tracking issue and link it from this PR.

@scs0209 @ggbdpq @xiechimon — this is the branch to rebase onto.

Verification

Run on this branch, rebased onto 93a8dd785:

  • npx biome check packages/core/src/ui-locale.ts packages/core/src/__tests__/ui-locale.test.ts — clean.
  • Locale suite — 29/29 pass. The workspace build is blocked by the catalog gap described above, so ui-locale.ts and its test were compiled on their own and run under node --test rather than through test:dist.
  • tsc --noEmit -p packages/core/tsconfig.json — 4 errors, all of them the missing ko catalogs in redaction.ts, relative-time.ts and tool-quiet-preview.ts, i.e. exactly the three files listed under "Landing next on this branch". No other error in @maka/core.
  • Repo-wide npm run typecheck — the ko gap accounts for 126 catalog sites across 61 files; the remaining errors cascade from @maka/core failing to emit.

Not run: npm run build and the full npm test, both blocked by the same catalog gap. They are expected to stay red until the strict catalogs are complete.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code — drafted the ui-locale.ts change and the locale tests, and this description. Reviewed, verified and submitted by me; the affected commit carries a Generated-by: Claude Code trailer, which must survive the eventual squash.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Lint, format and the locale suite pass. Typecheck does not, and is not expected to on this branch alone — see Verification and "Why this cannot merge alone".

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

Add `ko` to UI_LOCALES so the closed locale vocabulary carries Korean:
the `isUiLocale`/`isUiLocalePreference` guards accept it, and
`resolveSystemUiLocale` recognizes the `ko` prefix through the existing
case-insensitive, `_`-normalizing path (`ko`, `ko-KR`, `ko_KR`,
`ko_KR.UTF-8`), so an `auto` preference resolves to it without being
persisted.

`uiLocaleToIntlLocale` stops being identity. Every locale so far was
already the tag `Intl` wants; bare `ko` leaves the region open, and the
region is what selects Korean date, number, and plural formatting, so it
is widened to `ko-KR`. The return type becomes the literal union of the
tags actually emitted — `'zh-CN' | 'zh-TW' | 'en' | 'ko-KR'` — rather
than `string`, so the set stays visible in the signature. Every call
site feeds an `Intl` constructor, `toLocaleString`, or `localeCompare`,
all of which take `string`, so narrowing it is safe.

The formatter test can no longer assert identity, so it pins the tag
table instead and checks each tag is canonical, which keeps a locale
added later from reaching `Intl` without a deliberate tag.

Refs apache#3975

Generated-by: Claude Code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/S Under 100 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant