Skip to content

feat(settings): add Chinese (zh-CN) i18n support#935

Open
LHLAL wants to merge 1 commit into
crynta:mainfrom
LHLAL:feat/i18n-zh-cn
Open

feat(settings): add Chinese (zh-CN) i18n support#935
LHLAL wants to merge 1 commit into
crynta:mainfrom
LHLAL:feat/i18n-zh-cn

Conversation

@LHLAL

@LHLAL LHLAL commented Jul 3, 2026

Copy link
Copy Markdown

What

Why

How

Testing

  • pnpm exec tsc --noEmit clean
  • Manual smoke-test of the affected feature
  • (If you touched src-tauri/) cargo test --locked and cargo clippy --all-targets --locked -- -D warnings clean
  • (If you changed a #[tauri::command] signature) called out below so the FE caller can be updated in lockstep
  • (If UI) tested in pnpm tauri dev
  • Platforms tested:
  • Shells tested (if relevant):

Screenshots / GIFs

Notes for reviewer

Summary by CodeRabbit

  • New Features

    • Added in-app language switching between English and Simplified Chinese.
    • Expanded translation coverage across Settings, including themes, shortcuts, models, agents, general preferences, and About.
  • Bug Fixes

    • Localized validation, status, and error messages for a more consistent experience.
    • Improved fallback behavior so missing text now shows English or the key instead of blank or incorrect labels.

@LHLAL LHLAL requested a review from crynta as a code owner July 3, 2026 10:39
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a persisted i18n layer (Zustand store, useTranslation hook, translate helper, English/Chinese locale JSON files) and applies it throughout the settings UI, replacing hardcoded strings with translation keys across SettingsApp and all section components, plus adding a language selector dropdown.

Changes

Internationalization implementation

Layer / File(s) Summary
i18n store, hook, and locale data
src/i18n/index.ts, src/i18n/locales/en.json, src/i18n/locales/zh-CN.json
Adds Locale/TranslationKey types, persisted useI18nStore, getNestedValue, useTranslation(), translate(), AVAILABLE_LOCALES, and the English/Chinese message data.
SettingsApp tabs and language selector
src/settings/SettingsApp.tsx
Converts tab labels to labelKey-based translation, wires t/locale into the component, and adds a language selector dropdown.
AboutSection localization
src/settings/sections/AboutSection.tsx
Localizes updater status text, header, build/license/source/website labels, and GitHub/issue buttons.
AgentsSection, editors, and validation
src/settings/sections/AgentsSection.tsx
Localizes agent/snippet cards, editor dialogs, custom instructions, and translates snippet handle validation errors.
GeneralSection localization
src/settings/sections/GeneralSection.tsx
Converts option constants to translation keys and localizes editor/explorer/terminal/shell/startup settings and sub-inputs.
ModelsSection localization
src/settings/sections/ModelsSection.tsx
Localizes provider/endpoint cards, autocomplete row, status line, and voice input blocks.
ShortcutsSection localization
src/settings/sections/ShortcutsSection.tsx
Adds group key mapping and localizes headers, reset dialog, search placeholder, and recording status text.
ThemesSection localization
src/settings/sections/ThemesSection.tsx
Localizes theme/background labels, buttons, dropdown text, and image validation/import error messages.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related PRs

  • crynta/terax-ai#811: Both PRs touch voice-input UI in ModelsSection.tsx—one configures Groq/Whisper.cpp voice inputs, this one localizes those same labels.
  • crynta/terax-ai#815: Both PRs modify the "Editor theme" dropdown in ThemesSection.tsx, with this PR localizing text the other PR introduces/reshapes.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title follows Conventional Commits and accurately summarizes the settings i18n addition, including Chinese (zh-CN) support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/settings/sections/ModelsSection.tsx (1)

743-747: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

"not connected" is translated 30 lines below but hardcoded here.

Line 745's dropdown badge still reads a literal not connected, while the near-identical concept at line 776 now goes through t("models.notConnected"). Same string, two different fates — zh-CN users will see mixed English/Chinese in the same dropdown.

🌐 Proposed fix
                       {!pConfigured ? (
                         <span className="ml-auto text-[9.5px] normal-case tracking-normal text-muted-foreground/70">
-                          not connected
+                          {t("models.notConnected")}
                         </span>
                       ) : null}
Same localization pass also leaves "Connected" badges, "Docs", "Test", and "Save" buttons hardcoded elsewhere in this file — worth a follow-up sweep for full zh-CN coverage.

Also applies to: 774-777

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/settings/sections/ModelsSection.tsx` around lines 743 - 747, The
ModelsSection dropdown still hardcodes the “not connected” badge in one branch
while the same label already uses t("models.notConnected") elsewhere; update the
conditional badge rendering in ModelsSection to use the translation helper
consistently so zh-CN users don’t see mixed language. While you’re there, sweep
the nearby badge/button labels in the same component (such as the Connected,
Docs, Test, and Save text) and route them through the existing i18n keys or add
matching keys where needed.
🧹 Nitpick comments (5)
src/i18n/index.ts (2)

65-72: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate resolution logic between useTranslation and translate.

Both functions repeat the same "lookup then fall back to English then key" sequence. Worth extracting a shared resolve(messages, key) helper to keep the two paths from drifting.

Also applies to: 78-84

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/index.ts` around lines 65 - 72, Both useTranslation and translate
duplicate the same lookup/fallback flow, so extract a shared resolve(messages,
key) helper in the i18n module and have both functions delegate to it. Keep the
logic centralized around getNestedValue, locales.en fallback, and final key
fallback so the two paths stay consistent and don’t drift.

14-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

TranslationKey is exported but never enforced.

useTranslation()'s returned function and translate() both accept a plain key: string, so the whole point of NestedKeyOf<typeof en> (compile-time key safety, catching typos like "agents.hanlde") is lost. Every call site in the sections is currently free to pass an invalid key that silently falls back to itself (line 70/83).

Type the key parameter
-  return (key: string): string => {
+  return (key: TranslationKey): string => {
     const value = getNestedValue(messages, key);
     if (value !== undefined) return value;
     // Fallback to English
     const enValue = getNestedValue(locales.en, key);
     return enValue ?? key;
   };
 }
...
-export function translate(key: string, locale?: Locale): string {
+export function translate(key: TranslationKey, locale?: Locale): string {

Also applies to: 61-84

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/index.ts` around lines 14 - 24, `TranslationKey` is defined but not
actually used, so invalid translation keys still compile. Update the key
parameter types in `useTranslation()` and `translate()` from plain `string` to
`TranslationKey` (or a generic constrained to it), and propagate that type
through the returned translator function so call sites in the sections get
compile-time key safety and typo detection.
src/settings/SettingsApp.tsx (1)

23-45: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Type labelKey as TranslationKey here. useTranslation() falls back to the raw key when a translation is missing, so leaving this as string lets a typo in TABS reach the UI with no build-time signal. src/settings/SettingsApp.tsx:38-45

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/settings/SettingsApp.tsx` around lines 23 - 45, The TABS metadata is
using an untyped string for labelKey, which allows invalid i18n keys to slip
into the UI; update the SettingsApp.tsx TABS definition so labelKey is typed as
TranslationKey instead of string. Use the existing useTranslation/TranslationKey
types in this file to keep the tab labels checked at compile time and prevent
typos in the tab entries like general, themes, shortcuts, models, agents, and
about.
src/settings/sections/AgentsSection.tsx (1)

543-545: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Drop the commented-out savedTick JSX.

Dead, disabled markup sitting in a hunk you just touched. Per repo convention, default to no comments and no leftover code.

🧹 Proposed fix
-        {/* {savedTick > 0 ? (
-          <span className="text-[10px] text-muted-foreground">Saved</span>
-        ) : null} */}
         {draft && (
As per coding guidelines, "Default to no comments; if a comment is genuinely needed, keep it to 1-2 lines explaining why, not what, and avoid AI-generic filler."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/settings/sections/AgentsSection.tsx` around lines 543 - 545, Remove the
commented-out savedTick JSX from AgentsSection so there is no leftover disabled
markup in the touched block; keep the render logic clean and ensure the
component only contains the active JSX around savedTick and the surrounding
settings UI.

Source: Coding guidelines

src/settings/sections/ThemesSection.tsx (1)

193-193: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

t param in .map((t) => ...) shadows the translation function.

Not a bug today (nothing inside the loop calls t(...)), but the new const t = useTranslation() at the top now collides with this pre-existing loop variable naming. Anyone adding a translated string inside the theme card render later will get confusing type errors or silently reference the wrong t. Renaming the loop var (e.g. theme) removes the trap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/settings/sections/ThemesSection.tsx` at line 193, The theme list render
in ThemesSection has a naming collision because the .map callback uses t, which
shadows the translation function returned by useTranslation(). Rename the loop
variable in the themes.map callback to a non-conflicting name such as theme, and
update all references inside that render block so future calls to t(...) remain
unambiguous.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/i18n/locales/en.json`:
- Around line 127-137: The models locale object contains a duplicate "test" key,
which should be defined only once. Remove the redundant "test" entry in the same
translation block and make sure the remaining key is the single source of truth;
apply the same cleanup to the corresponding models object in zh-CN.json so both
locale files stay consistent.

In `@src/settings/sections/AboutSection.tsx`:
- Around line 46-49: The AboutSection status label still hardcodes English in
the available/manualAvailable branches, so update the ternary in
AboutSection.tsx to route those cases through translation like the other
branches. Add new i18n keys for the action prefixes used by the status text
(about.installVersion and about.updateToVersion) in both en.json and zh-CN.json,
then compose the localized prefix with the version value in the AboutSection
rendering logic.

In `@src/settings/sections/AgentsSection.tsx`:
- Line 411: The three save buttons in AgentsSection are using the ModelsSection
translation key instead of an agents-scoped/shared key. Update the save label in
AgentEditorDialog, SnippetEditorDialog, and CustomInstructionsBlock to use a new
agents.save or common.save translation key, and add that key to both locale
files so these components no longer depend on models.save.

In `@src/settings/sections/ModelsSection.tsx`:
- Line 776: The rendered text in ModelsSection is using a literal em dash in the
not-connected message, which violates the repo’s punctuation guideline. Update
the JSX in the ModelsSection rendering path so the separator between
t("models.notConnected") and getProvider(provider).label uses a non-em-dash
alternative, and make sure no other nearby UI strings in this component
introduce em dashes.

In `@src/settings/SettingsApp.tsx`:
- Around line 126-153: The language switcher button in SettingsApp still uses a
hardcoded English tooltip, so update the DropdownMenuTrigger button’s title to
use the existing translation function instead of the literal “Language”. Locate
the language selector block in SettingsApp and route that label through t()
consistently with the rest of the file so the tooltip is localized.

---

Outside diff comments:
In `@src/settings/sections/ModelsSection.tsx`:
- Around line 743-747: The ModelsSection dropdown still hardcodes the “not
connected” badge in one branch while the same label already uses
t("models.notConnected") elsewhere; update the conditional badge rendering in
ModelsSection to use the translation helper consistently so zh-CN users don’t
see mixed language. While you’re there, sweep the nearby badge/button labels in
the same component (such as the Connected, Docs, Test, and Save text) and route
them through the existing i18n keys or add matching keys where needed.

---

Nitpick comments:
In `@src/i18n/index.ts`:
- Around line 65-72: Both useTranslation and translate duplicate the same
lookup/fallback flow, so extract a shared resolve(messages, key) helper in the
i18n module and have both functions delegate to it. Keep the logic centralized
around getNestedValue, locales.en fallback, and final key fallback so the two
paths stay consistent and don’t drift.
- Around line 14-24: `TranslationKey` is defined but not actually used, so
invalid translation keys still compile. Update the key parameter types in
`useTranslation()` and `translate()` from plain `string` to `TranslationKey` (or
a generic constrained to it), and propagate that type through the returned
translator function so call sites in the sections get compile-time key safety
and typo detection.

In `@src/settings/sections/AgentsSection.tsx`:
- Around line 543-545: Remove the commented-out savedTick JSX from AgentsSection
so there is no leftover disabled markup in the touched block; keep the render
logic clean and ensure the component only contains the active JSX around
savedTick and the surrounding settings UI.

In `@src/settings/sections/ThemesSection.tsx`:
- Line 193: The theme list render in ThemesSection has a naming collision
because the .map callback uses t, which shadows the translation function
returned by useTranslation(). Rename the loop variable in the themes.map
callback to a non-conflicting name such as theme, and update all references
inside that render block so future calls to t(...) remain unambiguous.

In `@src/settings/SettingsApp.tsx`:
- Around line 23-45: The TABS metadata is using an untyped string for labelKey,
which allows invalid i18n keys to slip into the UI; update the SettingsApp.tsx
TABS definition so labelKey is typed as TranslationKey instead of string. Use
the existing useTranslation/TranslationKey types in this file to keep the tab
labels checked at compile time and prevent typos in the tab entries like
general, themes, shortcuts, models, agents, and about.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: adbf2f55-a41d-4f18-8cf8-54ad6ac5b62f

📥 Commits

Reviewing files that changed from the base of the PR and between fef9f22 and ecf52f8.

📒 Files selected for processing (10)
  • src/i18n/index.ts
  • src/i18n/locales/en.json
  • src/i18n/locales/zh-CN.json
  • src/settings/SettingsApp.tsx
  • src/settings/sections/AboutSection.tsx
  • src/settings/sections/AgentsSection.tsx
  • src/settings/sections/GeneralSection.tsx
  • src/settings/sections/ModelsSection.tsx
  • src/settings/sections/ShortcutsSection.tsx
  • src/settings/sections/ThemesSection.tsx

Comment thread src/i18n/locales/en.json
Comment on lines +127 to +137
"test": "Test",
"modelId": "Model ID",
"context": "Context",
"apiKey": "API key",
"optional": "Optional — leave empty for unauthenticated endpoints",
"save": "Save",
"removeKey": "Remove key",
"reachable": "Reachable — server responded.",
"notReachable": "Could not reach the server.",
"test": "Test",
"testing": "Testing…",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Duplicate "test" key in the models object.

"test": "Test" is defined twice (Line 127 and Line 136). The JSON parser silently keeps the last one; both happen to hold the same value now, but it's a latent trap if a future edit touches only one copy (e.g. localization tooling regenerating one entry). Same duplication exists in zh-CN.json.

Fix
     "baseURL": "Base URL",
-    "test": "Test",
     "modelId": "Model ID",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"test": "Test",
"modelId": "Model ID",
"context": "Context",
"apiKey": "API key",
"optional": "Optional — leave empty for unauthenticated endpoints",
"save": "Save",
"removeKey": "Remove key",
"reachable": "Reachable — server responded.",
"notReachable": "Could not reach the server.",
"test": "Test",
"testing": "Testing…",
"baseURL": "Base URL",
"modelId": "Model ID",
"context": "Context",
"apiKey": "API key",
"optional": "Optional — leave empty for unauthenticated endpoints",
"save": "Save",
"removeKey": "Remove key",
"reachable": "Reachable — server responded.",
"notReachable": "Could not reach the server.",
"test": "Test",
"testing": "Testing…",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/locales/en.json` around lines 127 - 137, The models locale object
contains a duplicate "test" key, which should be defined only once. Remove the
redundant "test" entry in the same translation block and make sure the remaining
key is the single source of truth; apply the same cleanup to the corresponding
models object in zh-CN.json so both locale files stay consistent.

Comment on lines 46 to 49
: available
? `Install v${status.update.version}`
: manualAvailable
? `Update to v${status.info.version}`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Install/update version strings never got translated.

Every other branch of this ternary routes through t(...), but the available/manualAvailable branches still hardcode English: `Install v${status.update.version}` and `Update to v${status.info.version}`. On zh-CN this button will silently show English text for the two most action-relevant states (an update is actually ready to install). The AI summary claims "install/update version messaging" was localized too, so this looks like an oversight rather than intent.

Since useTranslation() has no interpolation support, the cheapest fix is splitting into a translated prefix + raw version:

🌐 Proposed fix
               : available
-                ? `Install v${status.update.version}`
+                ? `${t("about.installVersion")} v${status.update.version}`
                 : manualAvailable
-                  ? `Update to v${status.info.version}`
+                  ? `${t("about.updateToVersion")} v${status.info.version}`
                   : t("about.checkForUpdates");

New keys (about.installVersion = "Install", about.updateToVersion = "Update to") need to be added to both en.json and zh-CN.json.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/settings/sections/AboutSection.tsx` around lines 46 - 49, The
AboutSection status label still hardcodes English in the
available/manualAvailable branches, so update the ternary in AboutSection.tsx to
route those cases through translation like the other branches. Add new i18n keys
for the action prefixes used by the status text (about.installVersion and
about.updateToVersion) in both en.json and zh-CN.json, then compose the
localized prefix with the version value in the AboutSection rendering logic.

onClick={() => onSave({ ...draft, builtIn: false })}
>
Save
{t("models.save")}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Save buttons borrow models.save instead of an agents-scoped key.

Three separate save buttons in this file (AgentEditorDialog, SnippetEditorDialog, CustomInstructionsBlock) all call t("models.save"). Every other string in this file is properly namespaced under agents.*; reaching into ModelsSection's namespace couples these two unrelated modules together — if ModelsSection ever renames or removes that key, three buttons here break silently. Worth introducing a shared common.save key (or agents.save) instead.

♻️ Proposed fix
-            {t("models.save")}
+            {t("common.save")}

(apply to all three occurrences, plus add common.save to both locale files)

Also applies to: 519-519, 548-548

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/settings/sections/AgentsSection.tsx` at line 411, The three save buttons
in AgentsSection are using the ModelsSection translation key instead of an
agents-scoped/shared key. Update the save label in AgentEditorDialog,
SnippetEditorDialog, and CustomInstructionsBlock to use a new agents.save or
common.save translation key, and add that key to both locale files so these
components no longer depend on models.save.

{enabled && !hasKey ? (
<p className="pl-19 text-[10.5px] text-muted-foreground">
{getProvider(provider).label} isn't connected — add it below.
{t("models.notConnected")} — {getProvider(provider).label}.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Em dash slipped into rendered UI text.

{t("models.notConnected")} — {getProvider(provider).label}. uses a literal em dash. Repo guideline bans em dashes everywhere, including in code/strings.

✏️ Proposed fix
-          {t("models.notConnected")} — {getProvider(provider).label}.
+          {t("models.notConnected")}: {getProvider(provider).label}.
As per coding guidelines, "Do not use em dashes anywhere, including code, comments, commits, and docs."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{t("models.notConnected")} {getProvider(provider).label}.
{t("models.notConnected")}: {getProvider(provider).label}.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/settings/sections/ModelsSection.tsx` at line 776, The rendered text in
ModelsSection is using a literal em dash in the not-connected message, which
violates the repo’s punctuation guideline. Update the JSX in the ModelsSection
rendering path so the separator between t("models.notConnected") and
getProvider(provider).label uses a non-em-dash alternative, and make sure no
other nearby UI strings in this component introduce em dashes.

Source: Coding guidelines

Comment on lines +126 to +153
{/* Language Selector */}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className="mr-2 size-7 text-muted-foreground hover:text-foreground"
title="Language"
>
<HugeiconsIcon icon={Globe02Icon} size={14} strokeWidth={1.75} />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="min-w-32 p-1">
{AVAILABLE_LOCALES.map((locale) => (
<DropdownMenuItem
key={locale.value}
onSelect={() => setLocale(locale.value as Locale)}
className="flex items-center justify-between gap-2 text-[12px]"
>
<span>{locale.label}</span>
{currentLocale === locale.value && (
<span className="text-[10px] text-muted-foreground">✓</span>
)}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Untranslated tooltip on the language switcher itself.

title="Language" at Line 133 is hardcoded English — the one string in this feature that ships un-localized is, fittingly, the language selector's own label. Should route through t() like everything else in this file.

diff
             <Button
               variant="ghost"
               size="icon"
               className="mr-2 size-7 text-muted-foreground hover:text-foreground"
-              title="Language"
+              title={t("settings.language")}
             >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{/* Language Selector */}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className="mr-2 size-7 text-muted-foreground hover:text-foreground"
title="Language"
>
<HugeiconsIcon icon={Globe02Icon} size={14} strokeWidth={1.75} />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="min-w-32 p-1">
{AVAILABLE_LOCALES.map((locale) => (
<DropdownMenuItem
key={locale.value}
onSelect={() => setLocale(locale.value as Locale)}
className="flex items-center justify-between gap-2 text-[12px]"
>
<span>{locale.label}</span>
{currentLocale === locale.value && (
<span className="text-[10px] text-muted-foreground"></span>
)}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
{/* Language Selector */}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className="mr-2 size-7 text-muted-foreground hover:text-foreground"
title={t("settings.language")}
>
<HugeiconsIcon icon={Globe02Icon} size={14} strokeWidth={1.75} />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="min-w-32 p-1">
{AVAILABLE_LOCALES.map((locale) => (
<DropdownMenuItem
key={locale.value}
onSelect={() => setLocale(locale.value as Locale)}
className="flex items-center justify-between gap-2 text-[12px]"
>
<span>{locale.label}</span>
{currentLocale === locale.value && (
<span className="text-[10px] text-muted-foreground"></span>
)}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/settings/SettingsApp.tsx` around lines 126 - 153, The language switcher
button in SettingsApp still uses a hardcoded English tooltip, so update the
DropdownMenuTrigger button’s title to use the existing translation function
instead of the literal “Language”. Locate the language selector block in
SettingsApp and route that label through t() consistently with the rest of the
file so the tooltip is localized.

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