Skip to content

feat(i18n): add Korean (ko) translation#52

Open
moduvoice wants to merge 1 commit into
Microck:masterfrom
moduvoice:feat/i18n-ko-translation
Open

feat(i18n): add Korean (ko) translation#52
moduvoice wants to merge 1 commit into
Microck:masterfrom
moduvoice:feat/i18n-ko-translation

Conversation

@moduvoice

@moduvoice moduvoice commented Jul 8, 2026

Copy link
Copy Markdown

Motivation

This adds Korean (ko) translation support — to help Korean-speaking users use this
open-source project more comfortably in their own language.
(한국 사람들의 오픈소스 이용에 도움이 되게 하기 위해서 한글화 작업을 하였습니다.)

Changes

  • Added client-next/messages/ko.json — a complete Korean translation mirroring the exact key structure of client-next/messages/en.json (929/929 keys, same nesting as the existing zh-CN.json).
  • Registered ko in client-next/src/components/language-switcher.tsx: added { code: "ko", label: "한국어" } to the locales list, and added a "한" label for the switcher trigger button.

Testing

  • Programmatically flattened and diffed the key sets of en.json and ko.json: 929/929 keys match exactly (no missing, no extra keys).
  • Verified every {placeholder} token (e.g. {count}, {name}, {error}, {provider}) is preserved identically between en.json and ko.json for each key — 0 mismatches.
  • Ran npx tsc --noEmit, npm run lint, and npm run build inside client-next/ after npm install — all completed successfully. The one pre-existing lint error touching language-switcher.tsx (document.cookie assignment) was confirmed via git stash to already exist on master before this change.

AI Assistance Disclosure

  • agent_name: Claude Code
  • agent_version: 2.1.204
  • model_used: Claude Sonnet 5 (claude-sonnet-5)
  • human_testing: No human manually exercised the running application UI (e.g. clicking through screens with the locale switched to Korean) for this change. The checks that were run — and were run by the AI agent, not a human — are: a script-based key-parity and placeholder-parity diff between en.json and ko.json, npx tsc --noEmit, npm run lint, and npm run build, all of which passed. Flagging this explicitly per this repo's AI disclosure policy rather than claiming testing that did not happen.
  • contribution_summary: Added a complete Korean (ko) translation (929/929 keys) and registered it in the language switcher.

Greptile Summary

This PR adds a complete Korean (ko) translation to the application by introducing client-next/messages/ko.json (929 keys, all interpolation placeholders preserved) and registering the locale in language-switcher.tsx.

  • ko.json mirrors the structure of en.json exactly; brand-name values (e.g. common.sync.title = "Sincronizado") are left as-is, matching the English source's intent.
  • language-switcher.tsx adds { code: "ko", label: "한국어" } to the locales array and extends the trigger-button label ternary with a "한" branch, following the same approach used for zh-CN.

Confidence Score: 5/5

Safe to merge — changes are purely additive (a new translation file and two lines in the language switcher) with no risk to existing functionality.

The translation file covers all 929 keys with correct placeholder syntax, and the language-switcher registration is a straightforward additive change that matches the existing zh-CN pattern exactly. The only comments are style suggestions around the ternary label chain.

No files require special attention; both changed files are low-risk.

Important Files Changed

Filename Overview
client-next/messages/ko.json Adds complete 1085-line Korean translation with all 929 keys, all placeholders preserved. One value (common.sync.title = "Sincronizado") is left as-is, matching the English source which also intentionally uses the brand name.
client-next/src/components/language-switcher.tsx Registers ko locale in the locales list and extends the trigger-button label ternary with a "한" label for Korean; pattern mirrors the existing zh-CN handling.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant LanguageSwitcher
    participant Cookie
    participant i18nRequest as i18n/request.ts
    participant ko_json as messages/ko.json

    User->>LanguageSwitcher: clicks "한국어"
    LanguageSwitcher->>Cookie: "set locale=ko (1-year max-age)"
    LanguageSwitcher->>LanguageSwitcher: router.refresh()
    i18nRequest->>Cookie: read locale cookie
    Cookie-->>i18nRequest: "ko"
    i18nRequest->>ko_json: dynamic import messages/ko.json
    ko_json-->>i18nRequest: Korean message map
    i18nRequest-->>User: page rendered in Korean
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant LanguageSwitcher
    participant Cookie
    participant i18nRequest as i18n/request.ts
    participant ko_json as messages/ko.json

    User->>LanguageSwitcher: clicks "한국어"
    LanguageSwitcher->>Cookie: "set locale=ko (1-year max-age)"
    LanguageSwitcher->>LanguageSwitcher: router.refresh()
    i18nRequest->>Cookie: read locale cookie
    Cookie-->>i18nRequest: "ko"
    i18nRequest->>ko_json: dynamic import messages/ko.json
    ko_json-->>i18nRequest: Korean message map
    i18nRequest-->>User: page rendered in Korean
Loading

Fix All in Codex

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
client-next/src/components/language-switcher.tsx:13-17
The trigger-button label is resolved via a growing ternary chain. Each new locale requires a code change here in addition to the `locales` array. Since each locale entry already exists in that array, the label character can live there too, making the button render generically without any per-locale branching.

```suggestion
const locales = [
  { code: "en", label: "English", triggerLabel: "EN" },
  { code: "zh-CN", label: "중文", triggerLabel: "中" },
  { code: "ko", label: "한국어", triggerLabel: "한" },
] as const;
```

### Issue 2 of 2
client-next/src/components/language-switcher.tsx:32-34
With a `triggerLabel` field on each locale entry (see suggestion above on the array), the ternary can be replaced by a simple lookup, so the button automatically reflects whatever label is defined in the array without any additional code changes per locale.

```suggestion
          <span className="text-xs font-medium">
            {locales.find((l) => l.code === currentLocale)?.triggerLabel ?? "EN"}
          </span>
```

Reviews (1): Last reviewed commit: "feat(i18n): add Korean (ko) translation" | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

Adds a complete Korean translation (929/929 keys, matching en.json's
structure) and registers ko in the language switcher.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

@moduvoice is attempting to deploy a commit to the Projects Team on Vercel.

A member of the Team first needs to authorize it.

Comment on lines 13 to 17
const locales = [
{ code: "en", label: "English" },
{ code: "zh-CN", label: "中文" },
{ code: "ko", label: "한국어" },
] as const;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The trigger-button label is resolved via a growing ternary chain. Each new locale requires a code change here in addition to the locales array. Since each locale entry already exists in that array, the label character can live there too, making the button render generically without any per-locale branching.

Suggested change
const locales = [
{ code: "en", label: "English" },
{ code: "zh-CN", label: "中文" },
{ code: "ko", label: "한국어" },
] as const;
const locales = [
{ code: "en", label: "English", triggerLabel: "EN" },
{ code: "zh-CN", label: "중文", triggerLabel: "中" },
{ code: "ko", label: "한국어", triggerLabel: "한" },
] as const;
Prompt To Fix With AI
This is a comment left during a code review.
Path: client-next/src/components/language-switcher.tsx
Line: 13-17

Comment:
The trigger-button label is resolved via a growing ternary chain. Each new locale requires a code change here in addition to the `locales` array. Since each locale entry already exists in that array, the label character can live there too, making the button render generically without any per-locale branching.

```suggestion
const locales = [
  { code: "en", label: "English", triggerLabel: "EN" },
  { code: "zh-CN", label: "중文", triggerLabel: "中" },
  { code: "ko", label: "한국어", triggerLabel: "한" },
] as const;
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex

Comment on lines 32 to 34
<span className="text-xs font-medium">
{currentLocale === "zh-CN" ? "中" : "EN"}
{currentLocale === "zh-CN" ? "中" : currentLocale === "ko" ? "한" : "EN"}
</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 With a triggerLabel field on each locale entry (see suggestion above on the array), the ternary can be replaced by a simple lookup, so the button automatically reflects whatever label is defined in the array without any additional code changes per locale.

Suggested change
<span className="text-xs font-medium">
{currentLocale === "zh-CN" ? "中" : "EN"}
{currentLocale === "zh-CN" ? "中" : currentLocale === "ko" ? "한" : "EN"}
</span>
<span className="text-xs font-medium">
{locales.find((l) => l.code === currentLocale)?.triggerLabel ?? "EN"}
</span>
Prompt To Fix With AI
This is a comment left during a code review.
Path: client-next/src/components/language-switcher.tsx
Line: 32-34

Comment:
With a `triggerLabel` field on each locale entry (see suggestion above on the array), the ternary can be replaced by a simple lookup, so the button automatically reflects whatever label is defined in the array without any additional code changes per locale.

```suggestion
          <span className="text-xs font-medium">
            {locales.find((l) => l.code === currentLocale)?.triggerLabel ?? "EN"}
          </span>
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant