Skip to content

feat: add korean localization toggle#561

Open
gracefully91 wants to merge 3 commits intorealproject7:mainfrom
gracefully91:main
Open

feat: add korean localization toggle#561
gracefully91 wants to merge 3 commits intorealproject7:mainfrom
gracefully91:main

Conversation

@gracefully91
Copy link
Copy Markdown

한글화 해봤습니다~~

설정에 언어 선택 버튼도 넣었는데 확인해보세유~~

Copy link
Copy Markdown
Owner

@realproject7 realproject7 left a comment

Choose a reason for hiding this comment

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

Thanks for the Korean localization work @gracefully91 — the translations are natural and well done!

However, requesting changes before this can be merged:

Bug

  • Duplicate span in SetupWizard.tsx: The original English "Custom ports" <span> is left in alongside the new translated <span>, so both render side by side. The original should be replaced, not duplicated.

Code quality

  • Inline ternary pattern doesn't scale. Currently every string uses locale === "ko" ? "한글" : "English" directly in JSX — this is repeated hundreds of times across 18 files. Your own SettingsPage.tsx already uses a much cleaner dictionary (COPY) pattern. Could you refactor the other components to use the same approach? For example:
// Per-component or shared dictionary
const COPY = {
  en: { title: "Settings", save: "Save" },
  ko: { title: "설정", save: "저장" },
};
const t = COPY[locale];

// Then in JSX:
<h1>{t.title}</h1>

This keeps components readable and makes adding a third language trivial.

Minor

  • \n- in the welcome message headline ("QuadWork에 오신 걸 환영합니다\n- 첫 AI 개발 팀을 설정해볼까요") looks like a formatting artifact.

Happy to merge once these are addressed!

@gracefully91
Copy link
Copy Markdown
Author

Hi @realproject7! I've addressed all three points:

Bug — Removed the duplicate for "Custom ports" in SetupWizard.tsx
Code quality — Refactored all 16 components to use the per-component COPY dictionary pattern (matching SettingsPage.tsx)
Minor — Fixed the \n- artifact → restored as \n— to preserve the intended line break

Ready for re-review! 🍊

Copy link
Copy Markdown
Owner

@realproject7 realproject7 left a comment

Choose a reason for hiding this comment

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

Thanks for addressing the duplicate span and the \n- artifact — both are fixed!

The COPY dictionary refactor is partially done but 49 inline locale === "ko" ternaries still remain in JSX across 17 files. These need to be moved into the COPY dictionaries for consistency and maintainability.


What needs to change

Rule: Every user-visible string must live in the COPY dictionary

No inline ternaries in JSX. Every locale === "ko" ? "한글" : "English" in rendering code should be replaced by a COPY key. The only place locale should appear in a component is:

const { locale } = useLocale();
const t = COPY[locale];

After that, JSX should only reference t.someKey — never locale directly.

How to handle strings with interpolation

Some inline ternaries were left because the string contains dynamic values like ${count}. Use a function in the COPY dictionary:

// ❌ Current (inline ternary with interpolation)
<span>{locale === "ko" ? `${count}개 항목` : `${count} items`}</span>

// ✅ Correct (function in COPY)
const COPY = {
  en: {
    itemCount: (n: number) => `${n} items`,
  },
  ko: {
    itemCount: (n: number) => `${n}개 항목`,
  },
};

// In JSX:
<span>{t.itemCount(count)}</span>

How to handle JSX elements inside translated strings

For strings that contain inline <code>, <strong>, etc., split the COPY entry into parts:

// ❌ Current (fragile string split)
t.cleanupIntro.split("~/.quadwork/{id}/agentchattr")

// ✅ Correct (structured COPY entries)
const COPY = {
  en: {
    cleanupBefore: "Per-project clones are necessary so multiple projects can run AgentChattr simultaneously without port conflicts. Existing v1 users are auto-migrated to per-project clones on the next ",
    cleanupCode: "~/.quadwork/{id}/agentchattr",
    cleanupAfter: "; once every project has a working clone, the legacy shared install can be removed safely via ",
  },
  ko: {
    cleanupBefore: "프로젝트별 클론은 ...",
    cleanupCode: "~/.quadwork/{id}/agentchattr",
    cleanupAfter: "; 모든 프로젝트에 ...",
  },
};

// In JSX:
<p>{t.cleanupBefore}<code>{t.cleanupCode}</code>{t.cleanupAfter}</p>

Files with remaining inline ternaries (all must be fixed)

High priority (many ternaries)

  1. SetupWizard.tsx — 13 inline ternaries

    • getInitialSteps() function has 12 ternaries for step labels and subtitles. Move all step label and subtitle strings into COPY:
      // ❌ Current
      { label: locale === "ko" ? "필수 도구" : "Prerequisites", subtitle: locale === "ko" ? "필수 도구 확인" : "Check required tools" }
      
      // ✅ Move to COPY
      const COPY = {
        en: {
          stepPrereqLabel: "Prerequisites",
          stepPrereqSubtitle: "Check required tools",
          // ... all other steps
        },
        ko: {
          stepPrereqLabel: "필수 도구",
          stepPrereqSubtitle: "필수 도구 확인",
        },
      };
      
      // Then:
      { label: t.stepPrereqLabel, subtitle: t.stepPrereqSubtitle }
    • Also fix the remaining JSX ternaries ("auto-detected", "no local clone found", branch protection text)
  2. GitHubPanel.tsx — 7 inline ternaries

    • Rate limit messages, Issues/PRs headers with counts, tooltip bodies
    • Use function pattern for count interpolations: issuesHeader: (n: number) => \ISSUES (${n})``
  3. BatchProgressPanel.tsx — 5 inline ternaries

    • Batch number display, items count, tooltip text
  4. HomeDashboard.tsx — 5 inline ternaries

    • Project count display
    • timeAgo() function has 4 ternaries for time units — move all into COPY as functions: minutesAgo: (n: number) => \${n}분 전``

Medium priority (1-2 ternaries each)

  1. ControlBar.tsx — 2 (tooltip help text for Keep Mac Awake and Notification Sound)
  2. AgentModelsWidget.tsx — 1-2
  3. AgentTerminalsGrid.tsx — 1-2
  4. DiscordBridgeWidget.tsx — 1-2
  5. TelegramBridgeWidget.tsx — 1-2
  6. LoopGuardWidget.tsx — 1-2
  7. OperatorFeaturesPanel.tsx — 1-2
  8. ProjectDashboard.tsx — 1-2
  9. ProjectHistoryWidget.tsx — 1-2
  10. ScheduledTriggerWidget.tsx — 1-2

For all of these: move the remaining tooltip bodies and dynamic labels into each file's COPY dictionary.


Other fixes needed

  1. Remove unnecessary type casts in SetupWizard.tsxlocale as "en" | "ko" is redundant since useLocale() already returns Locale which is "en" | "ko". Just use COPY[locale] directly.

  2. SettingsPage.tsx cleanup text — replace the fragile .split("~/.quadwork/{id}/agentchattr") approach with structured COPY entries (see example above).


Checklist before re-requesting review

  • Zero locale === "ko" ternaries remain in any JSX/rendering code
  • All user-visible strings live in COPY dictionaries
  • Strings with dynamic values use function entries in COPY
  • Strings with JSX elements use structured COPY entries (before/after pattern)
  • No as "en" | "ko" type casts
  • npm run build passes cleanly

@gracefully91
Copy link
Copy Markdown
Author

All 49 inline locale === "ko" ternaries have been moved into COPY dictionaries across all 17 files.

Removed the as "en" | "ko" type casts and replaced the .split() pattern in SettingsPage with structured before/code/after entries.

Thanks for the detailed breakdown!

@realproject7
Copy link
Copy Markdown
Owner

Hi @gracefully91! The localization work looks great — translations are natural and the COPY dictionary refactor is clean. Two things needed before we can merge:


1. Rebase on current main (critical)

Your fork is based on an older main. Since you opened this PR, we've merged 10+ PRs (security fixes, AC crash recovery, init/launch separation, etc.). Your branch currently carries reverse diffs to server files (server/index.js, bin/quadwork.js, server/routes.js, etc.) that would revert critical fixes if merged.

Git shows no merge conflicts, but that makes it worse — the reverts would happen silently.

Please rebase your branch on the latest main:

# Add the upstream remote (if not already)
git remote add upstream https://github.com/realproject7/quadwork.git

# Fetch latest
git fetch upstream main

# Rebase your branch
git rebase upstream/main

# Force-push to update the PR
git push --force-with-lease origin main

After rebasing, the diff should only show changes in src/, src/lib/locale.ts, and src/app/globals.css — no changes to server/, bin/, scripts/, or package.json.

2. Remove unused COPY keys in SettingsPage.tsx

These 4 keys are defined but never used in JSX (the function versions onlyInstalledMsg / installOtherMsg replaced them):

onlyInstalledPrefix
onlyInstalledSuffix
installOther
forMoreBackendOptions

Remove them from both the en and ko objects in SettingsPage.tsx's COPY dictionary.

3. Verify build

After rebasing, please confirm npm run build passes cleanly.


That's it! Once rebased and cleaned up, we're ready to merge. Thanks for the thorough work on this 🙏

@gracefully91
Copy link
Copy Markdown
Author

gracefully91 commented Apr 27, 2026

Good Night @realproject7!

I’ve updated the PR to address all your feedback:

  1. Rebase complete: I've rebased the branch onto the latest upstream/main.
    The diff now correctly shows changes only in src/,
    src/lib/locale.ts, and src/app/globals.css. All reverse diffs to the server and bin files have been cleared.

  2. Cleanup: Removed the 4 unused COPY keys (onlyInstalledPrefix, onlyInstalledSuffix, installOther,
    forMoreBackendOptions) from SettingsPage.tsx.
    I also refactored the CLI installation message to use the oneCliInstalled key and a cleaner localization logic.

  3. Refined Translations: Polished several Korean strings (especially the @Head instructions in the help modal)
    to make them more natural.

  4. Verified Build: Confirmed that npm run build passes cleanly without any type errors.

Everything should be ready for review now. Thanks! 🙏

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.

2 participants