Skip to content

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

Draft
heeoneie wants to merge 2 commits 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 2 commits 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).

  • redaction.ts (GENERALIZED_ERROR_COPY), relative-time.ts (JUST_NOW) and tool-quiet-preview.ts (STRINGS_BY_LOCALE) carry their ko entries — the three catalogs @maka/core needs in order to compile with ko, per the delivery decision. Their tests mirror the existing zh-CN/zh-TW blocks: the same raw-to-expected table for the error copy plus a Hangul assertion, the just-now string across all three relative-time formatters, and the ko quiet-preview lines.

The core base is complete

@maka/core builds, typechecks and tests green with ko as of 36a4377. What remains red is downstream and belongs to the slice PRs, not to this branch.

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.
  • The CI errors on 36a4377 surface a class I did not count: plain as const locale maps that are indexed with a UiLocale rather than declared as UiCatalog<T>. They are not among the 126 catalog sites, and they only fail once ko is in the union, so the census understates the remaining work. I will fold them into the same tracking issue.

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

Verification

Run on this branch at 36a4377:

  • @maka/core typecheck — clean.
  • Core suite — 841 pass, 0 fail, including 54 across redaction.test.ts, relative-time.test.ts and tool-quiet-preview.test.ts.
  • biome lint and format on the six changed files — clean.
  • npm run build:test — does not complete. It now gets past @maka/core and fails in packages/cli.
  • CI on this commit — the test job fails with 7 errors, every one of them the same shape: a UiLocale expression indexing an as const locale map that carries en, zh-CN and zh-TW but no ko. Two of them are TUI surfaces (the transcript view and the todo panel). None is in @maka/core, and none is introduced by the catalog commit — they follow from ko entering UI_LOCALES in 7b45e32.

Repo-wide typecheck and the full test run are expected to stay red until every strict catalog is 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 @maka/core's typecheck and full suite pass. Repo-wide typecheck and build:test do not, and are 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
`ko` joined `UI_LOCALES` in the previous commit, and `UiCatalog<T>` is
`Record<UiLocale, T>`, so every catalog in the package became structurally
incomplete at once. Three carried copy without a Korean branch:
`GENERALIZED_ERROR_COPY`, `JUST_NOW`, and `STRINGS_BY_LOCALE`. Fill them
in so `@maka/core` typechecks again.

The generalized-error and just-now catalogs are direct translations. The
quiet-preview strings follow the English branch rather than the Chinese
one where the two disagree: `moreQuestions` reports the remainder past
the previewed entry (`외 1개` for two questions) instead of the total the
Chinese branches state, since that is how the count reads naturally in
Korean. `bytes` and `replacements` likewise drop the `共`/`等` prefixes
that have no Korean counterpart.

`uiLocaleToIntlLocale` already widens `ko` to `ko-KR`, so the relative
formatter picks up Korean units without further work; the test pins
`1분 전` to keep that path honest.

Tests mirror the existing per-locale coverage: a full classification
table for Korean asserting Hangul output and no secret leakage, the
shared cross-catalog routing assertions, the just-now and sidebar-unit
cases, and the quiet-preview question-count and background-terminal
lines.

Verified with `npm run build:test` through `@maka/core`, the three
suites under `packages/core/dist/__tests__` (54 passing), the full core
suite (841 passing), and biome lint/format on the touched files.
`@maka/core` typechecks clean. Downstream packages still carry catalogs
without `ko` and are left to their own commits.

Refs apache#3975

Generated-by: Claude Code
@heeoneie

heeoneie commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

The three core catalogs are on the branch now (36a4377): GENERALIZED_ERROR_COPY, JUST_NOW and STRINGS_BY_LOCALE all carry ko, with tests mirroring the existing zh-CN/zh-TW blocks — the same raw→expected table for the error copy plus a Hangul assertion, the just-now string across all three relative-time formatters, and the ko quiet-preview lines.

@maka/core is green with ko: typecheck clean, 841/841 in the core suite, biome lint and format clean. The core base is complete as @me2seeks scoped it, so anyone rebasing onto this branch now gets a @maka/core that builds.

@ggbdpq — one item is off your plate: redaction.ts's GENERALIZED_ERROR_COPY carries its ko entry here, so that core error catalog is done. The rest of #3978 is unchanged — the eight packages/ui/src/*copy.ts files, connection-error-copy.ts and the other core error catalogs, and the main-process fallbacks. Separately: you wrote above that you would start once the core slice merges. Under @me2seeks's delivery decision it never merges on its own, so there is nothing to wait for — this branch is the base and it is ready to build on today.

CI on 36a4377 is red, as expected, and every one of the 7 errors is the same shape: '"en" | "ko" | "zh-CN" | "zh-TW"' can't be used to index type '{ readonly en: ...; readonly 'zh-CN': ...; readonly 'zh-TW': ... }'.

These are as const locale maps indexed with a UiLocale — the TUI transcript view (DETAILED TRANSCRIPT) and the todo panel (Current Todo, Usage: /todo) are two of them. None is in @maka/core, and none is introduced by this commit; they follow from ko entering UI_LOCALES in 7b45e32. @xiechimon — these read as #3979 territory alongside #4349.

Worth recording for the integration plan: these maps are not among the 126 UiCatalog<T> sites I counted. They are plain as const objects that only fail once something indexes them with a UiLocale, so the census understates the remaining work by however many of them exist across the CLI, packages/ui and desktop. I will fold them into the tracking issue I owe @me2seeks for the type-invisible locale paths.

@me2seeks

me2seeks commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

@heeoneie — one contribution-attribution choice before we turn the Korean work into its final integration shape.

The repository cannot grant upstream write access to contributors, and GitHub native stacked PRs require every branch to live in apache/maka. Your current #5011 fork branch therefore cannot join a native stack directly. I do not want the integration process to erase the ownership of the core work you have done.

You do not need to manage an integration branch or rebase other contributors. Please choose the shape you prefer:

  1. Official bridge stack. After feat(i18n-ko): core — add ko to UiLocale model #5011 is reviewed, maintainers recreate its reviewed layer in an apache/maka stack branch, link it explicitly back to feat(i18n-ko): core — add ko to UiLocale model #5011, and carry you as a confirmed co-author on its separate final squash commit. This keeps the core layer separate from the other slices in main.
  2. Keep the fork PR through final integration. feat(i18n-ko): core — add ko to UiLocale model #5011 remains the canonical implementation PR; maintainers compose all reviewed slices only at the end, and the one final squash commit links feat(i18n-ko): core — add ko to UiLocale model #5011 and carries every actual contributor as a confirmed co-author. This has less branch machinery, but does not keep a separate core commit in main.

Both preserve #5011 as your public PR and #5075 as your public audit contribution. The difference is whether the final history has a separate Korean-core squash commit. Please reply 1 or 2; maintainers will handle all follow-on integration work.

@heeoneie

heeoneie commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Two reasons, and one request.

Option 1 is the only one of the two that leaves the locale contract revertible on its own. If resolveSystemUiLocale or uiLocaleToIntlLocale turns out wrong after integration, a separate core commit can be reverted without taking the Korean copy with it. Under option 2 that is one commit containing everything, and the same contract will carry every locale added after this one.

It also fits what #3853 established, and improves on it slightly. That PR merged four commits from AcerYue0:feat/zh-tw-locale into main, each carrying its co-authors, so fork work reaching main under shared authorship is already the norm here. What it did not leave behind was a commit anyone can point at for the locale model itself — all four are titled feat(i18n): add Traditional Chinese locale. Option 1 gives the Korean core the separation zh-TW never got, which seems worth the extra branch step.

The request: please carry the Generated-by: Claude Code trailer onto the recreated commit alongside the co-author line. CONTRIBUTING.md requires it for the AI-assisted part of this work, and it needs to survive recreation the same way it needed to survive a squash.

Happy to rebase #5011 onto whatever you need, or to leave it untouched as the reviewed reference — whichever makes the bridge branch easier to cut. I will keep #5075 updated as the audit gate either way.

@me2seeks

me2seeks commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

@heeoneie — option 1 is confirmed.

I reviewed the exact 36a4377 tree rather than the polluted local checkout: @maka/core builds, and the four affected suites pass 83/83. The ko resolver cases (ko, ko-KR, ko_KR.UTF-8), the kok-IN → en guard, and the ko → ko-KR Intl mapping all behaved as specified. There are no open review threads.

I will recreate the reviewed core layer on an apache/maka bridge branch once the integration stack is ready. Its source provenance stays explicit: this PR remains the reviewed reference, the recreated commit retains Generated-by: Claude Code, and the final squash commit will carry your Co-authored-by trailer.

Please reply with the email address associated with your GitHub account that you want in that trailer (a GitHub noreply address is fine). This avoids guessing an identity address. You do not need to rebase #5011 or manage the bridge branch.

@me2seeks

me2seeks commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

@heeoneie — the official bridge is now open as #5100: #5100

It is based on current main and contains one separate, revertible core commit recreated from the reviewed 36a4377 tree. GitHub has resolved the commit author to your account, and its message retains both trailers:

Generated-by: Claude Code
Co-authored-by: heeoneie <68272931+heeoneie@users.noreply.github.com>

#5011 remains the canonical reviewed source and public record of the work. #5100 is draft-only stack infrastructure; it will not merge by itself. No rebase is needed from you.

scs0209 pushed a commit to scs0209/maka that referenced this pull request Sep 9, 2026
Recreate the reviewed core layer from apache#5011 on the official integration
stack. Add Korean to the closed UI locale vocabulary, system resolution,
and Intl mapping; complete the three @maka/core UI catalogs required by
that strict contract.

Reviewed source: apache#5011 at 36a4377.
Refs apache#3975

Generated-by: Claude Code
Co-authored-by: heeoneie <68272931+heeoneie@users.noreply.github.com>
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.

2 participants