Skip to content

fix(i18n): align agent ui copy and keys#1337

Merged
zerob13 merged 3 commits intodevfrom
fix/agent-ui-i18n
Mar 9, 2026
Merged

fix(i18n): align agent ui copy and keys#1337
zerob13 merged 3 commits intodevfrom
fix/agent-ui-i18n

Conversation

@yyhhyyyyyy
Copy link
Collaborator

@yyhhyyyyyy yyhhyyyyyy commented Mar 8, 2026

align agent ui copy and keys

Summary by CodeRabbit

  • New Features
    • Expanded localization across the app: sidebar, chat placeholders, new-thread headings, project selector, and permission mode labels now use translations.
    • Improved placeholder behavior so editor placeholders update dynamically with locale changes.
    • Added localized time/project labels for session groups and improved empty-state/tooltip translations.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0e32586-ec0e-448b-aadc-5da98c47f08c

📥 Commits

Reviewing files that changed from the base of the PR and between dec3887 and 942c82d.

📒 Files selected for processing (16)
  • src/renderer/src/i18n/da-DK/chat.json
  • src/renderer/src/i18n/da-DK/common.json
  • src/renderer/src/i18n/fa-IR/chat.json
  • src/renderer/src/i18n/fa-IR/common.json
  • src/renderer/src/i18n/fr-FR/chat.json
  • src/renderer/src/i18n/fr-FR/common.json
  • src/renderer/src/i18n/he-IL/chat.json
  • src/renderer/src/i18n/he-IL/common.json
  • src/renderer/src/i18n/ja-JP/chat.json
  • src/renderer/src/i18n/ja-JP/common.json
  • src/renderer/src/i18n/ko-KR/chat.json
  • src/renderer/src/i18n/ko-KR/common.json
  • src/renderer/src/i18n/pt-BR/chat.json
  • src/renderer/src/i18n/pt-BR/common.json
  • src/renderer/src/i18n/ru-RU/chat.json
  • src/renderer/src/i18n/ru-RU/common.json
🚧 Files skipped from review as they are similar to previous changes (12)
  • src/renderer/src/i18n/ru-RU/common.json
  • src/renderer/src/i18n/pt-BR/common.json
  • src/renderer/src/i18n/fa-IR/common.json
  • src/renderer/src/i18n/ko-KR/chat.json
  • src/renderer/src/i18n/ko-KR/common.json
  • src/renderer/src/i18n/da-DK/common.json
  • src/renderer/src/i18n/ru-RU/chat.json
  • src/renderer/src/i18n/fr-FR/common.json
  • src/renderer/src/i18n/he-IL/common.json
  • src/renderer/src/i18n/fa-IR/chat.json
  • src/renderer/src/i18n/fr-FR/chat.json
  • src/renderer/src/i18n/ja-JP/common.json

📝 Walkthrough

Walkthrough

This PR replaces hardcoded UI strings with vue-i18n translations across renderer components and pages, consolidates removed newThread.json entries into locale chat.json files, adds time/project common keys, and propagates optional labelKey through session grouping while removing some store-level computed name getters.

Changes

Cohort / File(s) Summary
Vue Components & Pages
src/renderer/src/components/NewThreadMock.vue, src/renderer/src/components/WindowSideBar.vue, src/renderer/src/components/chat/ChatInputBox.vue, src/renderer/src/components/chat/ChatStatusBar.vue, src/renderer/src/components/mock/MockInputBox.vue, src/renderer/src/components/mock/MockStatusBar.vue, src/renderer/src/pages/ChatPage.vue, src/renderer/src/pages/NewThreadPage.vue
Switched hardcoded UI strings to useI18n/t(...). Added component-level computed fallbacks (e.g., resolved placeholders, selectedProjectName) and watchers where needed. No business logic changes.
i18n — chat.json (locales)
src/renderer/src/i18n/*/chat.json (en-US, da-DK, fa-IR, fr-FR, he-IL, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW)
Updated input.placeholder; added newThread.title, permissionMode (default/fullAccess), and sidebar keys across locale chat.json files.
i18n — common.json (locales)
src/renderer/src/i18n/*/common.json (all locales)
Added top-level time (today/yesterday/lastWeek/older) and project (select/none/recent/openFolder) translation groups to each locale's common file.
i18n index & newThread deletions
src/renderer/src/i18n/*/index.ts, src/renderer/src/i18n/*/newThread.json (all locales)
Removed imports/exports of newThread from each locale index and deleted separate newThread.json files (content consolidated into chat.json).
Stores — UI
src/renderer/src/stores/ui/agent.ts, src/renderer/src/stores/ui/project.ts, src/renderer/src/stores/ui/session.ts
Removed selectedAgentName and selectedProjectName computed getters from agent/project stores. Added optional labelKey?: string to SessionGroup and updated grouping to emit localized label keys instead of hardcoded English labels.
Tests
test/renderer/components/WindowSideBar.test.ts, test/renderer/stores/sessionStore.test.ts
Updated test fixtures/types to include optional labelKey and assertions to expect propagated labelKey values (e.g., common.time.today).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

codex

Suggested reviewers

  • zerob13

Poem

🐰 Strings once scattered across files and clocks,
I stitched them in locales, tidy as socks.
From stores to components I hopped with delight,
Now UI speaks many tongues — hopsetted and bright. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix(i18n): align agent ui copy and keys' accurately reflects the primary changes, which involve aligning UI copy with internationalization (i18n) keys across multiple components and locale files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/agent-ui-i18n

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (8)
src/renderer/src/i18n/he-IL/common.json-103-114 (1)

103-114: ⚠️ Potential issue | 🟡 Minor

Missing Hebrew translations for new i18n keys.

The time and project groups contain English strings instead of Hebrew translations. For proper localization, these should be translated:

Key Current (English) Expected (Hebrew)
time.today "Today" "היום"
time.yesterday "Yesterday" "אתמול"
time.lastWeek "Last week" "השבוע שעבר"
time.older "Older" "ישן יותר"
project.select "Select project" "בחר פרויקט"
project.none "No project" "ללא פרויקט"
project.recent "Recent projects" "פרויקטים אחרונים"
project.openFolder "Open folder..." "פתח תיקייה..."

Based on learnings: All user-facing strings must use i18n keys (supports 12 languages).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/i18n/he-IL/common.json` around lines 103 - 114, Replace the
English strings in the i18n keys with the provided Hebrew translations: update
time.today to "היום", time.yesterday to "אתמול", time.lastWeek to "השבוע שעבר",
time.older to "ישן יותר", and update project.select to "בחר פרויקט",
project.none to "ללא פרויקט", project.recent to "פרויקטים אחרונים",
project.openFolder to "פתח תיקייה..."; make these changes in the same JSON
structure (keys: time.*, project.*) so UI reads localized Hebrew strings.
src/renderer/src/i18n/ko-KR/common.json-103-114 (1)

103-114: ⚠️ Potential issue | 🟡 Minor

Missing Korean translations for new i18n keys.

The time and project groups contain English strings instead of Korean translations. For proper localization, these should be translated:

Key Current (English) Expected (Korean)
time.today "Today" "오늘"
time.yesterday "Yesterday" "어제"
time.lastWeek "Last week" "지난 주"
time.older "Older" "이전"
project.select "Select project" "프로젝트 선택"
project.none "No project" "프로젝트 없음"
project.recent "Recent projects" "최근 프로젝트"
project.openFolder "Open folder..." "폴더 열기..."

Based on learnings: All user-facing strings must use i18n keys (supports 12 languages).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/i18n/ko-KR/common.json` around lines 103 - 114, The JSON
entries under the "time" and "project" keys currently contain English strings;
replace them with the provided Korean translations for the keys time.today,
time.yesterday, time.lastWeek, time.older and project.select, project.none,
project.recent, project.openFolder so the renderer uses localized strings (e.g.,
time.today -> "오늘", project.openFolder -> "폴더 열기..."). Update
src/renderer/src/i18n/ko-KR/common.json by substituting each English value with
its corresponding Korean value while keeping the existing key names and JSON
structure intact.
src/renderer/src/i18n/fa-IR/chat.json-214-229 (1)

214-229: ⚠️ Potential issue | 🟡 Minor

Missing Persian translations for new i18n keys.

The newThread, permissionMode, and sidebar sections contain English strings instead of Persian translations. For proper localization, these should be translated. For example:

Key Current (English) Expected (Persian)
newThread.title "Build and explore" "ساخت و کاوش"
permissionMode.default "Default permissions" "مجوزهای پیش‌فرض"
permissionMode.fullAccess "Full access" "دسترسی کامل"
sidebar.allAgents "All Agents" "همه عامل‌ها"
sidebar.emptyTitle "No conversations yet" "هنوز گفتگویی وجود ندارد"

Based on learnings: All user-facing strings must use i18n keys (supports 12 languages).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/i18n/fa-IR/chat.json` around lines 214 - 229, Replace the
English strings in the fa-IR i18n JSON by providing Persian translations for the
new keys: update newThread.title to "ساخت و کاوش", permissionMode.default to
"مجوزهای پیش‌فرض", permissionMode.fullAccess to "دسترسی کامل", and translate
sidebar entries such as sidebar.allAgents -> "همه عامل‌ها", sidebar.emptyTitle
-> "هنوز گفتگویی وجود ندارد" (also localize sidebar.expandSidebar,
collapseSidebar, groupByDate, groupByProject, emptyDescription, etc.) so all
user-facing strings under newThread, permissionMode, and sidebar are in Persian.
src/renderer/src/i18n/fa-IR/common.json-103-114 (1)

103-114: ⚠️ Potential issue | 🟡 Minor

Missing Persian translations for new i18n keys.

The time and project groups contain English strings instead of Persian translations. For proper localization, these should be translated:

Key Current (English) Expected (Persian)
time.today "Today" "امروز"
time.yesterday "Yesterday" "دیروز"
time.lastWeek "Last week" "هفته گذشته"
time.older "Older" "قدیمی‌تر"
project.select "Select project" "انتخاب پروژه"
project.none "No project" "بدون پروژه"
project.recent "Recent projects" "پروژه‌های اخیر"
project.openFolder "Open folder..." "باز کردن پوشه..."

Based on learnings: All user-facing strings must use i18n keys (supports 12 languages).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/i18n/fa-IR/common.json` around lines 103 - 114, Replace the
English placeholders in the "time" and "project" i18n groups with the provided
Persian translations: update time.today → "امروز", time.yesterday → "دیروز",
time.lastWeek → "هفته گذشته", time.older → "قدیمی‌تر", and update project.select
→ "انتخاب پروژه", project.none → "بدون پروژه", project.recent → "پروژه‌های
اخیر", project.openFolder → "باز کردن پوشه..."; ensure you change the values for
the keys "time" (today, yesterday, lastWeek, older) and "project" (select, none,
recent, openFolder) in the JSON so all user-facing strings use the Persian
translations.
src/renderer/src/i18n/fa-IR/chat.json-3-3 (1)

3-3: ⚠️ Potential issue | 🟡 Minor

Input placeholder changed from Persian to English.

The input.placeholder appears to have been replaced with the English version. This should retain a Persian translation for consistency with the rest of the locale file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/i18n/fa-IR/chat.json` at line 3, The input.placeholder value
was replaced with English; restore a Persian translation for the
"input.placeholder" key (keep the mention tokens like "@" and "/" intact),
replacing "Ask DeepChat anything, @ to mention files, / for commands" with an
appropriate Persian string and preserving valid JSON syntax and punctuation for
the "input.placeholder" entry.
src/renderer/src/components/NewThreadMock.vue-44-46 (1)

44-46: ⚠️ Potential issue | 🟡 Minor

Localize the custom-folder selection label too.

Lines 44-46 now localize the menu item, but Line 96 still assigns selectedProject the hardcoded English string Custom folder. After clicking it, the visible project label flips back to English in non-English locales.

Based on learnings: Use vue-i18n keys from src/renderer/src/i18n for all user-facing strings; never hardcode UI text.

Also applies to: 94-96

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/components/NewThreadMock.vue` around lines 44 - 46, The
selectedProject label is being set to the hardcoded English string "Custom
folder" (so locale flips back to English); update the code paths that assign
selectedProject (notably the selectCustomProject method and the assignment
around the previous selectedProject usage at lines ~94-96) to use the vue-i18n
translator instead of a literal string (e.g., replace the hardcoded value with
t('<appropriate i18n key>') using the same namespace as
t('common.project.openFolder')—ensure you pick the correct key from
src/renderer/src/i18n and use that key wherever "Custom folder" was hardcoded).
src/renderer/src/pages/NewThreadPage.vue-129-131 (1)

129-131: ⚠️ Potential issue | 🟡 Minor

Nullish coalescing won't catch empty project names.

The ?? operator only handles null/undefined, not empty strings. Per the relevant snippets, openFolderPicker() derives the project name via selectedPath.split('/').pop() ?? selectedPath, which returns "" when a path ends with /. An empty string would be displayed instead of the fallback.

🔧 Proposed fix using logical OR
 const selectedProjectName = computed(
-  () => projectStore.selectedProject?.name ?? t('common.project.select')
+  () => projectStore.selectedProject?.name || t('common.project.select')
 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/pages/NewThreadPage.vue` around lines 129 - 131, The
computed selectedProjectName uses the nullish coalescing operator
(projectStore.selectedProject?.name ?? t('common.project.select')) which misses
empty-string names (e.g., when openFolderPicker() produces "" via
selectedPath.split('/').pop()); change the fallback logic to treat empty strings
as missing—use a truthy check (e.g., replace the ?? with || or explicitly check
for empty string) so selectedProjectName returns t('common.project.select') when
projectStore.selectedProject?.name is "" or falsy.
src/renderer/src/components/mock/MockStatusBar.vue-76-84 (1)

76-84: ⚠️ Potential issue | 🟡 Minor

Hardcoded "Restricted" string breaks i18n consistency.

Line 80 still uses a hardcoded "Restricted" string while the adjacent items use t('chat.permissionMode.default') and t('chat.permissionMode.fullAccess'). All permission mode labels should use i18n keys.

🔧 Proposed fix
         <DropdownMenuItem class="text-xs py-1.5 px-2">{{
           t('chat.permissionMode.default')
         }}</DropdownMenuItem>
-        <DropdownMenuItem class="text-xs py-1.5 px-2">Restricted</DropdownMenuItem>
+        <DropdownMenuItem class="text-xs py-1.5 px-2">{{
+          t('chat.permissionMode.restricted')
+        }}</DropdownMenuItem>
         <DropdownMenuItem class="text-xs py-1.5 px-2">{{
           t('chat.permissionMode.fullAccess')
         }}</DropdownMenuItem>

Based on learnings: "All user-facing strings must use i18n keys (supports 12 languages)" and "Use vue-i18n keys from src/renderer/src/i18n for all user-facing strings; never hardcode UI text".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/components/mock/MockStatusBar.vue` around lines 76 - 84, The
DropdownMenuItem in MockStatusBar.vue uses a hardcoded "Restricted" string;
replace it with the corresponding vue-i18n call (e.g.,
t('chat.permissionMode.restricted')) so all three menu items use i18n keys like
t('chat.permissionMode.default'), t('chat.permissionMode.restricted'), and
t('chat.permissionMode.fullAccess'); if the 'chat.permissionMode.restricted' key
does not exist in the i18n files under src/renderer/src/i18n, add it for all
supported languages.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/renderer/src/i18n/da-DK/chat.json`:
- Line 22: The Danish locale file has English strings instead of translations;
replace the English text for the keys "placeholder" (currently "Ask DeepChat
anything, @ to mention files, / for commands") and the related labels
"newThread", "permissionMode", and entries under "sidebar" (also noted around
lines 214–228) with proper Danish translations so Danish users see localized
text; update each value in src/renderer/src/i18n/da-DK/chat.json for those keys
to correct Danish phrases while keeping the JSON keys unchanged.

In `@src/renderer/src/i18n/da-DK/common.json`:
- Around line 103-114: Replace the English placeholder values under the JSON
keys with Danish translations: update time.today -> "I dag", time.yesterday ->
"I går", time.lastWeek -> "Sidste uge", time.older -> "Ældre"; and update
project.select -> "Vælg projekt", project.none -> "Intet projekt",
project.recent -> "Seneste projekter", project.openFolder -> "Åbn mappe...".
Ensure the keys time.* and project.* are preserved exactly and only the string
values are changed.

In `@src/renderer/src/i18n/fr-FR/chat.json`:
- Line 3: The French locale file contains English strings that must be
translated: update the keys "placeholder", "newThread", "permissionMode", and
"sidebar" in the fr-FR chat.json (and the similar entries around lines 214-228)
to proper French translations, replacing the English text while preserving JSON
structure and punctuation; ensure pluralization/variables (if any) remain intact
and run a quick validation to confirm the JSON stays valid after translation.

In `@src/renderer/src/i18n/fr-FR/common.json`:
- Around line 103-114: The JSON contains English strings under the keys
time.today, time.yesterday, time.lastWeek, time.older and project.select,
project.none, project.recent, project.openFolder; replace those English values
with the correct French translations (e.g. time.today -> "Aujourd'hui",
time.yesterday -> "Hier", time.lastWeek -> "La semaine dernière", time.older ->
"Plus ancien", project.select -> "Sélectionner un projet", project.none ->
"Aucun projet", project.recent -> "Projets récents", project.openFolder ->
"Ouvrir le dossier...") so French users see localized text; update only the
string values for these keys in the file.

In `@src/renderer/src/i18n/he-IL/chat.json`:
- Line 3: Translate the remaining English strings in the he-IL locale JSON
(specifically the "placeholder" key plus the new keys "newThread",
"permissionMode", and "sidebar") into proper Hebrew so the UI is fully
localized; locate the keys in the JSON (e.g., "placeholder": "Ask DeepChat
anything, @ to mention files, / for commands") and replace their English values
with Hebrew equivalents, and apply the same translations for the corresponding
entries referenced around lines 214-228 to avoid mixed-language UI.

In `@src/renderer/src/i18n/ja-JP/chat.json`:
- Line 3: The ja-JP chat locale contains English literals that must be
translated: replace the value for the "placeholder" key and the English strings
for the new-thread title, permission labels, and sidebar empty-state keys (the
chat.json keys around the later block mentioned) with proper Japanese
translations, preserving the JSON key names and encoding (UTF-8) and keeping the
same punctuation/placeholder tokens (e.g., @, /) exactly where appropriate;
ensure the updated values are valid JSON strings and consistent with other
locale phrasing.

In `@src/renderer/src/i18n/ja-JP/common.json`:
- Around line 103-114: Replace the English values under the "time" and "project"
keys with Japanese translations: set time.today -> "今日", time.yesterday -> "昨日",
time.lastWeek -> "先週", time.older -> "以前"; and set project.select ->
"プロジェクトを選択", project.none -> "プロジェクトなし", project.recent -> "最近のプロジェクト",
project.openFolder -> "フォルダーを開く...". Update these values in the JSON object
(keys: "time", "project", and the nested keys listed) so the file contains the
Japanese strings instead of English.

In `@src/renderer/src/i18n/ko-KR/chat.json`:
- Line 3: The Korean locale file contains English strings: replace the English
values for the keys "placeholder", "newThread", "permissionMode", and "sidebar"
(and the related entries around lines 214–228) with appropriate Korean
translations so the UI is fully localized; locate the entries named
"placeholder", "newThread", "permissionMode", and any "sidebar" label keys in
src/renderer/src/i18n/ko-KR/chat.json and update their string values to Korean
equivalents while preserving JSON key names and punctuation.

In `@src/renderer/src/i18n/pt-BR/chat.json`:
- Line 3: Replace the English placeholder string under the "placeholder" key in
the pt-BR chat.json with a Portuguese translation; update the value from "Ask
DeepChat anything, @ to mention files, / for commands" to a natural Portuguese
equivalent such as "Pergunte qualquer coisa ao DeepChat, use @ para mencionar
arquivos e / para comandos" so the i18n key "placeholder" contains the correct
Brazilian Portuguese text.
- Around line 214-228: Replace the English values in the JSON keys with
Portuguese translations: set newThread.title to "Criar e explorar"; set
permissionMode.default to "Permissões padrão" and permissionMode.fullAccess to
"Acesso total"; and update sidebar keys as follows — allAgents: "Todos os
Agentes", expandSidebar: "Expandir barra lateral", collapseSidebar: "Recolher
barra lateral", groupByDate: "Agrupar por data", groupByProject: "Agrupar por
projeto", emptyTitle: "Ainda não há conversas", emptyDescription: "Inicie um
novo chat para começar"; keep the existing key names (newThread, permissionMode,
sidebar) and only replace the string values.

In `@src/renderer/src/i18n/pt-BR/common.json`:
- Around line 103-114: The JSON contains English strings under the "time" and
"project" keys; update the values for "time.today", "time.yesterday",
"time.lastWeek", "time.older" and for "project.select", "project.none",
"project.recent", "project.openFolder" to their Portuguese equivalents (e.g.,
"Hoje", "Ontem", "Semana passada", "Mais antigos", "Selecionar projeto", "Nenhum
projeto", "Projetos recentes", "Abrir pasta..."), preserving the existing keys
and JSON structure.

In `@src/renderer/src/i18n/ru-RU/chat.json`:
- Line 3: The ru-RU locale file currently contains English strings that must be
translated: replace the English value for the "placeholder" key with a proper
Russian translation and do the same for the other English entries mentioned (the
new-thread title, permission label keys, and sidebar empty state keys) — keep
all keys exactly as they are (e.g., "placeholder", the new-thread title key,
permission label keys, and the sidebar empty state key(s)) but swap their
English values for accurate Russian text so the ru-RU locale contains only
Russian copy.

In `@src/renderer/src/i18n/ru-RU/common.json`:
- Around line 103-114: Replace the English values in the "time" and "project"
locale keys with Russian translations: set time.today -> "Сегодня",
time.yesterday -> "Вчера", time.lastWeek -> "На прошлой неделе", time.older ->
"Ранее"; and set project.select -> "Выбрать проект", project.none -> "Нет
проекта", project.recent -> "Недавние проекты", project.openFolder -> "Открыть
папку...". Update the JSON entries for the keys "time.today", "time.yesterday",
"time.lastWeek", "time.older", "project.select", "project.none",
"project.recent", and "project.openFolder" accordingly so the ru-RU/common.json
contains Russian text for these labels.

In `@src/renderer/src/stores/ui/session.ts`:
- Around line 110-112: The label derivation in the session store mapping (the
object returned from Array.from(projectMap.entries())) fails for Windows paths
and trailing separators; change the logic that computes label (the ternary using
dir === '__no_project__' ? ... : (dir.split('/').pop() ?? dir)) to first
normalize and trim trailing separators (e.g., remove trailing '/' or '\' with a
regex) and then split on both '/' and '\' (or use a regex like /[\/\\]/) to take
the final segment; keep the '__no_project__' check and still set labelKey to
'common.project.none' when appropriate.

---

Minor comments:
In `@src/renderer/src/components/mock/MockStatusBar.vue`:
- Around line 76-84: The DropdownMenuItem in MockStatusBar.vue uses a hardcoded
"Restricted" string; replace it with the corresponding vue-i18n call (e.g.,
t('chat.permissionMode.restricted')) so all three menu items use i18n keys like
t('chat.permissionMode.default'), t('chat.permissionMode.restricted'), and
t('chat.permissionMode.fullAccess'); if the 'chat.permissionMode.restricted' key
does not exist in the i18n files under src/renderer/src/i18n, add it for all
supported languages.

In `@src/renderer/src/components/NewThreadMock.vue`:
- Around line 44-46: The selectedProject label is being set to the hardcoded
English string "Custom folder" (so locale flips back to English); update the
code paths that assign selectedProject (notably the selectCustomProject method
and the assignment around the previous selectedProject usage at lines ~94-96) to
use the vue-i18n translator instead of a literal string (e.g., replace the
hardcoded value with t('<appropriate i18n key>') using the same namespace as
t('common.project.openFolder')—ensure you pick the correct key from
src/renderer/src/i18n and use that key wherever "Custom folder" was hardcoded).

In `@src/renderer/src/i18n/fa-IR/chat.json`:
- Around line 214-229: Replace the English strings in the fa-IR i18n JSON by
providing Persian translations for the new keys: update newThread.title to "ساخت
و کاوش", permissionMode.default to "مجوزهای پیش‌فرض", permissionMode.fullAccess
to "دسترسی کامل", and translate sidebar entries such as sidebar.allAgents ->
"همه عامل‌ها", sidebar.emptyTitle -> "هنوز گفتگویی وجود ندارد" (also localize
sidebar.expandSidebar, collapseSidebar, groupByDate, groupByProject,
emptyDescription, etc.) so all user-facing strings under newThread,
permissionMode, and sidebar are in Persian.
- Line 3: The input.placeholder value was replaced with English; restore a
Persian translation for the "input.placeholder" key (keep the mention tokens
like "@" and "/" intact), replacing "Ask DeepChat anything, @ to mention files,
/ for commands" with an appropriate Persian string and preserving valid JSON
syntax and punctuation for the "input.placeholder" entry.

In `@src/renderer/src/i18n/fa-IR/common.json`:
- Around line 103-114: Replace the English placeholders in the "time" and
"project" i18n groups with the provided Persian translations: update time.today
→ "امروز", time.yesterday → "دیروز", time.lastWeek → "هفته گذشته", time.older →
"قدیمی‌تر", and update project.select → "انتخاب پروژه", project.none → "بدون
پروژه", project.recent → "پروژه‌های اخیر", project.openFolder → "باز کردن
پوشه..."; ensure you change the values for the keys "time" (today, yesterday,
lastWeek, older) and "project" (select, none, recent, openFolder) in the JSON so
all user-facing strings use the Persian translations.

In `@src/renderer/src/i18n/he-IL/common.json`:
- Around line 103-114: Replace the English strings in the i18n keys with the
provided Hebrew translations: update time.today to "היום", time.yesterday to
"אתמול", time.lastWeek to "השבוע שעבר", time.older to "ישן יותר", and update
project.select to "בחר פרויקט", project.none to "ללא פרויקט", project.recent to
"פרויקטים אחרונים", project.openFolder to "פתח תיקייה..."; make these changes in
the same JSON structure (keys: time.*, project.*) so UI reads localized Hebrew
strings.

In `@src/renderer/src/i18n/ko-KR/common.json`:
- Around line 103-114: The JSON entries under the "time" and "project" keys
currently contain English strings; replace them with the provided Korean
translations for the keys time.today, time.yesterday, time.lastWeek, time.older
and project.select, project.none, project.recent, project.openFolder so the
renderer uses localized strings (e.g., time.today -> "오늘", project.openFolder ->
"폴더 열기..."). Update src/renderer/src/i18n/ko-KR/common.json by substituting each
English value with its corresponding Korean value while keeping the existing key
names and JSON structure intact.

In `@src/renderer/src/pages/NewThreadPage.vue`:
- Around line 129-131: The computed selectedProjectName uses the nullish
coalescing operator (projectStore.selectedProject?.name ??
t('common.project.select')) which misses empty-string names (e.g., when
openFolderPicker() produces "" via selectedPath.split('/').pop()); change the
fallback logic to treat empty strings as missing—use a truthy check (e.g.,
replace the ?? with || or explicitly check for empty string) so
selectedProjectName returns t('common.project.select') when
projectStore.selectedProject?.name is "" or falsy.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4dddeb12-bef3-4b18-98b2-564f3b3911a8

📥 Commits

Reviewing files that changed from the base of the PR and between de2408b and dec3887.

📒 Files selected for processing (61)
  • src/renderer/src/components/NewThreadMock.vue
  • src/renderer/src/components/WindowSideBar.vue
  • src/renderer/src/components/chat/ChatInputBox.vue
  • src/renderer/src/components/chat/ChatStatusBar.vue
  • src/renderer/src/components/mock/MockInputBox.vue
  • src/renderer/src/components/mock/MockStatusBar.vue
  • src/renderer/src/i18n/da-DK/chat.json
  • src/renderer/src/i18n/da-DK/common.json
  • src/renderer/src/i18n/da-DK/index.ts
  • src/renderer/src/i18n/da-DK/newThread.json
  • src/renderer/src/i18n/en-US/chat.json
  • src/renderer/src/i18n/en-US/common.json
  • src/renderer/src/i18n/en-US/index.ts
  • src/renderer/src/i18n/en-US/newThread.json
  • src/renderer/src/i18n/fa-IR/chat.json
  • src/renderer/src/i18n/fa-IR/common.json
  • src/renderer/src/i18n/fa-IR/index.ts
  • src/renderer/src/i18n/fa-IR/newThread.json
  • src/renderer/src/i18n/fr-FR/chat.json
  • src/renderer/src/i18n/fr-FR/common.json
  • src/renderer/src/i18n/fr-FR/index.ts
  • src/renderer/src/i18n/fr-FR/newThread.json
  • src/renderer/src/i18n/he-IL/chat.json
  • src/renderer/src/i18n/he-IL/common.json
  • src/renderer/src/i18n/he-IL/index.ts
  • src/renderer/src/i18n/he-IL/newThread.json
  • src/renderer/src/i18n/ja-JP/chat.json
  • src/renderer/src/i18n/ja-JP/common.json
  • src/renderer/src/i18n/ja-JP/index.ts
  • src/renderer/src/i18n/ja-JP/newThread.json
  • src/renderer/src/i18n/ko-KR/chat.json
  • src/renderer/src/i18n/ko-KR/common.json
  • src/renderer/src/i18n/ko-KR/index.ts
  • src/renderer/src/i18n/ko-KR/newThread.json
  • src/renderer/src/i18n/pt-BR/chat.json
  • src/renderer/src/i18n/pt-BR/common.json
  • src/renderer/src/i18n/pt-BR/index.ts
  • src/renderer/src/i18n/pt-BR/newThread.json
  • src/renderer/src/i18n/ru-RU/chat.json
  • src/renderer/src/i18n/ru-RU/common.json
  • src/renderer/src/i18n/ru-RU/index.ts
  • src/renderer/src/i18n/ru-RU/newThread.json
  • src/renderer/src/i18n/zh-CN/chat.json
  • src/renderer/src/i18n/zh-CN/common.json
  • src/renderer/src/i18n/zh-CN/index.ts
  • src/renderer/src/i18n/zh-CN/newThread.json
  • src/renderer/src/i18n/zh-HK/chat.json
  • src/renderer/src/i18n/zh-HK/common.json
  • src/renderer/src/i18n/zh-HK/index.ts
  • src/renderer/src/i18n/zh-HK/newThread.json
  • src/renderer/src/i18n/zh-TW/chat.json
  • src/renderer/src/i18n/zh-TW/common.json
  • src/renderer/src/i18n/zh-TW/index.ts
  • src/renderer/src/i18n/zh-TW/newThread.json
  • src/renderer/src/pages/ChatPage.vue
  • src/renderer/src/pages/NewThreadPage.vue
  • src/renderer/src/stores/ui/agent.ts
  • src/renderer/src/stores/ui/project.ts
  • src/renderer/src/stores/ui/session.ts
  • test/renderer/components/WindowSideBar.test.ts
  • test/renderer/stores/sessionStore.test.ts
💤 Files with no reviewable changes (26)
  • src/renderer/src/stores/ui/project.ts
  • src/renderer/src/i18n/ru-RU/newThread.json
  • src/renderer/src/i18n/zh-CN/index.ts
  • src/renderer/src/i18n/he-IL/index.ts
  • src/renderer/src/i18n/fr-FR/newThread.json
  • src/renderer/src/stores/ui/agent.ts
  • src/renderer/src/i18n/en-US/index.ts
  • src/renderer/src/i18n/he-IL/newThread.json
  • src/renderer/src/i18n/fa-IR/newThread.json
  • src/renderer/src/i18n/da-DK/index.ts
  • src/renderer/src/i18n/ja-JP/index.ts
  • src/renderer/src/i18n/zh-HK/newThread.json
  • src/renderer/src/i18n/zh-HK/index.ts
  • src/renderer/src/i18n/en-US/newThread.json
  • src/renderer/src/i18n/ru-RU/index.ts
  • src/renderer/src/i18n/zh-TW/newThread.json
  • src/renderer/src/i18n/ko-KR/index.ts
  • src/renderer/src/i18n/ja-JP/newThread.json
  • src/renderer/src/i18n/pt-BR/index.ts
  • src/renderer/src/i18n/zh-CN/newThread.json
  • src/renderer/src/i18n/ko-KR/newThread.json
  • src/renderer/src/i18n/da-DK/newThread.json
  • src/renderer/src/i18n/zh-TW/index.ts
  • src/renderer/src/i18n/fr-FR/index.ts
  • src/renderer/src/i18n/fa-IR/index.ts
  • src/renderer/src/i18n/pt-BR/newThread.json

Comment on lines 110 to +112
return Array.from(projectMap.entries()).map(([dir, sessions]) => ({
label: dir.split('/').pop() ?? dir,
label: dir === '__no_project__' ? 'common.project.none' : (dir.split('/').pop() ?? dir),
labelKey: dir === '__no_project__' ? 'common.project.none' : undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle Windows and trailing-slash project paths when deriving the group label.

dir.split('/').pop() leaves Windows paths as full C:\... strings and returns an empty label for paths ending with /, so the project header can be wrong or blank.

♻️ Suggested fix
   return Array.from(projectMap.entries()).map(([dir, sessions]) => ({
-    label: dir === '__no_project__' ? 'common.project.none' : (dir.split('/').pop() ?? dir),
+    label:
+      dir === '__no_project__'
+        ? 'common.project.none'
+        : dir.split(/[\\/]/).filter(Boolean).pop() ?? dir,
     labelKey: dir === '__no_project__' ? 'common.project.none' : undefined,
     sessions
   }))
📝 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
return Array.from(projectMap.entries()).map(([dir, sessions]) => ({
label: dir.split('/').pop() ?? dir,
label: dir === '__no_project__' ? 'common.project.none' : (dir.split('/').pop() ?? dir),
labelKey: dir === '__no_project__' ? 'common.project.none' : undefined,
return Array.from(projectMap.entries()).map(([dir, sessions]) => ({
label:
dir === '__no_project__'
? 'common.project.none'
: dir.split(/[\\/]/).filter(Boolean).pop() ?? dir,
labelKey: dir === '__no_project__' ? 'common.project.none' : undefined,
sessions
}))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/stores/ui/session.ts` around lines 110 - 112, The label
derivation in the session store mapping (the object returned from
Array.from(projectMap.entries())) fails for Windows paths and trailing
separators; change the logic that computes label (the ternary using dir ===
'__no_project__' ? ... : (dir.split('/').pop() ?? dir)) to first normalize and
trim trailing separators (e.g., remove trailing '/' or '\' with a regex) and
then split on both '/' and '\' (or use a regex like /[\/\\]/) to take the final
segment; keep the '__no_project__' check and still set labelKey to
'common.project.none' when appropriate.

@zerob13 zerob13 merged commit 33efa3d into dev Mar 9, 2026
2 checks passed
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