feat: add Vietnamese i18n for slash command descriptions - #1431
Conversation
kevincodex1
left a comment
There was a problem hiding this comment.
Awesome! Thank you for working on this
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the contribution. I took a pass through the changed skill registration paths and found a couple of issues that need to be addressed before this is ready.
Findings
-
[P2] Read the exported settings/config API so Vietnamese is actually selected
src/skills/bundled/i18n.ts:23
The new helper importsgetConfigfrom../../utils/config.js, but that module does not exportgetConfig; the exported runtime accessor isgetGlobalConfig. Because this call throws and is swallowed,detectLocale()always returnsen, so setting"language": "vietnamese"or"vi"never changes/loop,/simplify, or/update-configdescriptions. Please wire this to the real settings/config accessor and cover the Vietnamese branch with a focused test. -
[P2] Add the claimed git-install build hook or remove the install claim
package.json:68
The PR body says this adds apreparescript and documentsnpm install -g git+https://github.com/lht3003-rgb/openclaude.git, but the package scripts still only haveprepack. Sincedist/cli.mjsis not tracked in git and the bin wrapper exits whendistis missing, a git install from the fork will not produce a runnable CLI unless the build is run during install. Please either add thepreparescript the PR claims, or remove the git-install instructions/claim from the PR scope.
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I took another pass through the changed paths and found issues that still need to be addressed before this is ready.
Findings
-
[P2] Read the effective settings stack instead of hardcoding a legacy home-path file
src/skills/bundled/i18n.ts:25
detectLocale()now readshomedir()/.claude/settings.jsondirectly, but OpenClaude's runtime settings come from the merged settings stack (.openclaude,CLAUDE_CONFIG_DIR, project.openclaude/settings.json, local settings, and policy overrides). As written, the Vietnamese descriptions still stay in English for anyone who configuredlanguagethrough those supported paths instead of that one legacy file. Please wire this through the existing settings API so the slash-command descriptions follow the same effective config the rest of the app uses. -
[P2] The PR still does not add the promised git-install build hook
package.json:25
The PR body still says this change adds apreparescript and asks reviewers to testnpm install -g git+https://github.com/lht3003-rgb/openclaude.git, butpackage.jsonstill only hasprepack.bin/openclaudeexits whendist/cli.mjsis missing, so a git install from the fork still will not produce a runnable CLI. The only package metadata change now is a version bump to0.15.1, which adds release churn without fixing the install path this PR claims to address. Please either add the realpreparehook or drop the git-install/version change from this PR.
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I took another pass through the changed command/i18n paths and found issues that still need to be addressed before this is ready.
Findings
-
[P2] Re-read locale when settings change
src/skills/bundled/i18n.ts:24
detectLocale()caches the first language it sees forever, and the bundled skill descriptions callt()while the skills are registered at startup. OpenClaude already resets its settings cache and updates app state whenlanguagechanges, so after a user switches from English to Vietnamese, or back to English, the command UI keeps using the old locale until the process restarts. Please either make the command descriptions resolve the current effective setting at render time, or reset this i18n cache/rebuild the affected command entries when settings change. -
[P2] Translate prompt-type built-in commands too
src/commands.ts:779
The newcommandDescVitable includes prompt built-ins such asReview a pull requestandGenerate a report analyzing your OpenClaude sessions, butformatDescriptionWithSource()returns prompt built-ins unchanged before calling the translation helper. As a result,/reviewand/insightsstill show English descriptions withlanguage: "vietnamese", even though this PR claims Vietnamese translations for all slash command descriptions. Please apply the same translation path before returning prompt built-in descriptions, while preserving the existing source suffix behavior for workflows/plugins/bundled skills.
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I took another pass through the changed command/i18n paths and found issues that still need to be addressed before this is ready.
Findings
-
[P2] Keep bundled skill descriptions reactive to language changes
src/skills/bundled/loop.ts:208
The bundled skill descriptions still callt()while the skill is registered, andregisterBundledSkill()stores that resolved string on the command object. The newformatDescriptionWithSource()translation path fixes prompt built-ins such as/review, but it does not cover these long/loop,/simplify, or/update-configdescriptions because they are not incommandDescVi. If a user starts in English and changeslanguageto Vietnamese through/config, those bundled skill descriptions stay English; if they start in Vietnamese and switch back, they stay Vietnamese until restart. Please resolve the bundled-skill description at render time or rebuild/reset the affected bundled command entries when the settings cache is invalidated. -
[P2] Do not exit when optional env vars are present but empty
src/utils/envValidation.ts:46
The new startup validation treats empty optional environment variables as fatal because fields such asANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN,CLAUDE_CONFIG_DIR, andNODE_EXTRA_CA_CERTSusez.string().min(1).optional(). Before this change, the runtime treated empty values as unset with truthiness checks such asif (process.env.ANTHROPIC_API_KEY)andif (process.env.NODE_EXTRA_CA_CERTS). With this PR, launching OpenClaude withANTHROPIC_API_KEY=orNODE_EXTRA_CA_CERTS=exits before config initialization, even though those were previously harmless absent values. Please normalize empty strings toundefinedor allow empty strings for optional env vars that the rest of the app already treats as unset.
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I rechecked the changed command/i18n paths and found an issue that still needs to be addressed.
Findings
- [P2] Index slash-command search with the localized descriptions
src/utils/suggestions/commandSuggestions.ts:42
The slash picker now displays translated descriptions throughformatDescriptionWithSource(), but the Fuse index used for searching is still built from the rawcmd.description. For translated built-ins such as/review, a Vietnamese session showsĐánh giá pull requestin the picker, but searching for/đánhreturns no result while searching the old English text (/pull) still matches and displays the Vietnamese row. The same cache also stays keyed only by the command-array identity, so getter-based bundled descriptions can keep the previous language in the search index after/configchanges. Please build or invalidate this index using the same localized description text that the picker renders, so translated descriptions are actually searchable after startup and language changes.
034c460 to
05daa9b
Compare
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I rechecked the changed command/i18n paths and found an issue that still needs to be addressed.
Findings
- [P2] Keep the localized search fix scoped to OpenClaude-owned descriptions
src/commands.ts:765
The latest update correctly addresses the requested search-index issue by using rendered localized descriptions, but the translation call is now applied before checking the command source. That makes user, project, policy, workflow, and plugin commands with ordinary English descriptions that happen to match one of the built-in translation keys get rewritten in Vietnamese even though they are not OpenClaude-owned strings. For example, a project command withdescription: "Review a pull request"now renders asĐánh giá pull request (project)whenlanguageis Vietnamese. Please keep the localized-search fix, but scope translation to the built-in/local/bundled descriptions this PR owns, or otherwise mark which command descriptions are safe to translate, so custom and plugin-authored metadata is preserved.
jatmn
left a comment
There was a problem hiding this comment.
please rebase on main to fix merge conflicts
3cc1bee to
d9f84b9
Compare
|
hi thank you so much for working on localization. i have a couple of thoughts here, planning to put all languages in one single file, rather than scattered. if we merge this, can you continue working on this localization feature? |
|
please check again bro @jatmn . I think we should put all localization in a single folder |
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I rechecked the changed command/i18n paths and found issues that still need to be addressed.
Findings
-
[P2] Keep translations scoped to OpenClaude-owned command metadata
src/commands.ts:759
formatDescriptionWithSource()still translates the description before it checks the command source, so any plugin, project, policy, workflow, or user skill whose author-provided description happens to equal one of the English strings incommandDescViis rewritten in Vietnamese. The new test even codifies that non-prompt local descriptions likeSet the AI model for OpenClaude (currently GPT-5)are translated by text match alone. That means externally-authored metadata is no longer preserved, which was the previous review concern. Please only translate built-in/local/bundled descriptions that OpenClaude owns, or tag translatable command descriptions explicitly before passing them through the i18n table. -
[P2] Follow the maintainer-requested central localization layout
src/skills/bundled/i18n.ts:55
Per maintainer request, localization resources should live in a central location instead of being scattered through feature files. This update still keeps one Vietnamese lookup table insrc/skills/bundled/i18n.ts, while bundled skill translations are stored separately inside individual skill implementations (batch.ts,debug.ts,loop.ts,simplify.ts, andupdateConfig.ts). Please move these language strings into a central localization folder/module keyed by command/skill id, and keep command/skill definitions from owning per-language text blobs. -
[P3] Remove the stale git-install/prepare-script claim
package.json:24
The PR body still says this change adds apreparescript and asks reviewers to testnpm install -g git+https://github.com/lht3003-rgb/openclaude.git, but the current diff no longer changespackage.jsonand the scripts still only includeprepack. That makes the review description drift from the implementation and revives the earlier git-install concern even though the code change has been dropped. Please update the PR body/test plan to describe the current localization-only scope, or include the actual package change if git installs are still intended to be part of this PR.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (5)**/*.{ts,tsx,js,jsx,py}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
**/*.{ts,tsx}📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
**/*⚙️ CodeRabbit configuration file
Files:
**⚙️ CodeRabbit configuration file
Files:
src/{skills,utils/plugins,services/mcp}/**⚙️ CodeRabbit configuration file
Files:
🔇 Additional comments (2)
📝 WalkthroughWalkthroughAdds i18n (en/vi) and a localize facade; attaches localization keys to commands, plugins, and bundled skills; updates suggestion indexing to use rendered localized descriptions; adds Zod startup env validation and invokes it during init; threads optional slashCommandOverride through typeahead, submit, queueing, and processing. Pins Node to v22. ChangesInternationalization System
Environment Variable Validation
Slash-command override & submission plumbing
Tests, infra, and toolchain
🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 5 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Thanks for the detailed review. I’ve updated the implementation to address the remaining i18n issues:
Validation:
I also updated the PR body/test plan to remove the stale |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
src/i18n/types.ts (1)
3-6: ⚡ Quick winDerive
LocalizationKeyfrom the base dictionary to prevent future key driftRight now
src/i18n/types.tsdefinesLocalizationKey = string, sosrc/i18n/commandDescriptions.tsandsrc/i18n/index.tscan compile even when a key is wrong—missing keys will silently fall back viadictionaries[locale]?.[key] ?? en[key] ?? fallback. EN and VI key sets are currently aligned, and allcommandDescriptions.tsvalues exist in EN, but this won’t protect against future typos.Prefer:
export type LocalizationKey = keyof typeof en(or a chosen base dictionary), then type the other dictionaries (and any key maps) withsatisfies Record<LocalizationKey, string>to enforce completeness at compile time.🤖 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/types.ts` around lines 3 - 6, Change LocalizationKey from a plain string to be derived from the base English dictionary so keys are type-checked: replace the current export type LocalizationKey = string with a type built from the base dictionary (keyof typeof en) and update I18nDictionary to use Record<LocalizationKey, string>; then update code that defines the base dictionary (symbol en) and other dictionaries/ maps (e.g., commandDescriptions.ts and any dictionaries object) to use the TypeScript "satisfies Record<LocalizationKey, string>" pattern so missing or misspelled keys will cause compile-time errors instead of silent fallbacks.src/utils/attribution.test.ts (1)
269-270: ⚡ Quick winStrengthen commit trailer assertion to avoid false positives.
toStartWith+toEndWithcan pass with an empty/malformed middle segment. Prefer a single structural assertion.Proposed test tightening
- expect(attribution.commit).toStartWith('Co-Authored-By: ') - expect(attribution.commit).toEndWith(' <openclaude@gitlawb.com>') + expect(attribution.commit).toMatch( + /^Co-Authored-By: .+ <openclaude@gitlawb\.com>$/, + )🤖 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/utils/attribution.test.ts` around lines 269 - 270, Replace the two separate assertions on attribution.commit with a single structural assertion that validates the full trailer format; e.g. assert attribution.commit matches a regex like /^Co-Authored-By: .+ <openclaude@gitlawb.com>$/ so the middle segment is non-empty and properly formatted. Locate the expectations referencing attribution.commit in the test and swap the toStartWith/toEndWith checks for one toMatch/to.match with the anchored regex to avoid false positives.
🤖 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/entrypoints/init.ts`:
- Around line 50-52: The call to validateEnvVars() is currently executed before
applySafeConfigEnvironmentVariables() and applyExtraCACertsFromConfig(),
allowing config-derived proxy/CA values to bypass validation; update init
startup sequence so validateEnvVars() is invoked after
applySafeConfigEnvironmentVariables() and applyExtraCACertsFromConfig() (or
alternatively call validateEnvVars() again immediately after those two
functions) to ensure the effective runtime environment (including settings-based
proxy/CA values) is validated; locate the calls by the function names
validateEnvVars, applySafeConfigEnvironmentVariables, and
applyExtraCACertsFromConfig and adjust ordering or add a second validation
invocation accordingly.
In `@src/skills/bundledSkills.ts`:
- Around line 89-94: The getter whenToUse currently returns undefined when
definition.whenToUse is absent, preventing localization via
definition.whenToUseKey; change the whenToUse getter to call
localize(definition.whenToUseKey, definition.whenToUse) unconditionally when a
whenToUseKey exists (i.e., check definition.whenToUseKey rather than
definition.whenToUse) so keyed localization is honored even without a raw
fallback string; apply the same change pattern to the analogous code in
src/plugins/builtinPlugins.ts (the block around
whenToUse/whenToUseLocalizationKey) so both places use definition.whenToUseKey
as the presence check before calling localize.
---
Nitpick comments:
In `@src/i18n/types.ts`:
- Around line 3-6: Change LocalizationKey from a plain string to be derived from
the base English dictionary so keys are type-checked: replace the current export
type LocalizationKey = string with a type built from the base dictionary (keyof
typeof en) and update I18nDictionary to use Record<LocalizationKey, string>;
then update code that defines the base dictionary (symbol en) and other
dictionaries/ maps (e.g., commandDescriptions.ts and any dictionaries object) to
use the TypeScript "satisfies Record<LocalizationKey, string>" pattern so
missing or misspelled keys will cause compile-time errors instead of silent
fallbacks.
In `@src/utils/attribution.test.ts`:
- Around line 269-270: Replace the two separate assertions on attribution.commit
with a single structural assertion that validates the full trailer format; e.g.
assert attribution.commit matches a regex like /^Co-Authored-By: .+
<openclaude@gitlawb.com>$/ so the middle segment is non-empty and properly
formatted. Locate the expectations referencing attribution.commit in the test
and swap the toStartWith/toEndWith checks for one toMatch/to.match with the
anchored regex to avoid false positives.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 0e52ca6e-516b-4ceb-a62b-54804e6351ae
📒 Files selected for processing (27)
.node-version.nvmrcsrc/commands.test.tssrc/commands.tssrc/entrypoints/init.tssrc/hooks/useTypeahead.tsxsrc/i18n/commandDescriptions.tssrc/i18n/index.tssrc/i18n/languages/en.tssrc/i18n/languages/vi.tssrc/i18n/locale.tssrc/i18n/types.tssrc/plugins/builtinPlugins.tssrc/skills/bundled/batch.tssrc/skills/bundled/debug.tssrc/skills/bundled/loop.tssrc/skills/bundled/simplify.tssrc/skills/bundled/updateConfig.tssrc/skills/bundledSkills.tssrc/types/command.tssrc/types/plugin.tssrc/utils/attribution.test.tssrc/utils/envValidation.test.tssrc/utils/envValidation.tssrc/utils/model/model.openai-shim-providers.test.tssrc/utils/suggestions/commandSuggestions.test.tssrc/utils/suggestions/commandSuggestions.ts
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I rechecked the changed command/i18n paths and found issues that still need to be addressed.
Findings
-
[P2] Preserve the selected duplicate command row on Enter
src/hooks/useTypeahead.tsx:1147
The new exact-name branch converts the selected command suggestion back into a plain command name whenever the input is exactly/name. That loses the selectedSuggestionItem.metadata, andapplyCommandSuggestion()then callsgetCommand(name, commands), which returns the first command with that name. Slash command suggestions intentionally keep duplicate names from different sources because user/project/policy/plugin commands can have different implementations, so a user who arrows to the project or plugin/reviewrow and presses Enter can now execute whichever same-name command appears first instead of the row they selected. Please keep the normalized-name fix without discarding the selected suggestion object when there are duplicate same-name commands. -
[P2] Complete CodeRabbit's request to validate the hydrated startup environment
src/entrypoints/init.ts:52
CodeRabbit's review thread is still unresolved, and the current patch still callsvalidateEnvVars()beforeapplySafeConfigEnvironmentVariables()andapplyExtraCACertsFromConfig(). Those later calls can populateHTTP_PROXY,HTTPS_PROXY, andNODE_EXTRA_CA_CERTSfrom trusted settings before proxy/CA/network setup, so invalid settings-derived values bypass this new validation and only fail later in the startup path. Please complete that review request by validating after those config-backed environment values have been applied, or by re-running validation there.
|
Thanks for the follow-up review. I pushed an update addressing the two latest P2 items:
Validation:
Both passed locally. |
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I rechecked the changed command/i18n paths and found an issue that still needs to be addressed.
Findings
- [P2] Isolate the localized suggestion tests from shared settings mocks
src/utils/suggestions/commandSuggestions.test.ts:91
The new localized-search tests pass when this file runs by itself, but they fail in a normal multi-file Bun run:bun test src/commands.test.ts src/utils/suggestions/commandSuggestions.test.ts src/utils/envValidation.test.ts src/utils/processUserInput/processSlashCommand.test.ts src/utils/attribution.test.ts src/utils/model/model.openai-shim-providers.test.tsreliably returns no Vietnamese matches for/đánhand/khoảng. The trigger is the existing attribution test'smock.module('./settings/settings.js'), which replacesgetInitialSettings()process-wide while these new tests rely onsetSessionSettingsCache()being observed bydetectLocale(). Please isolate the new i18n suggestion tests from global settings-module mocks, or make the locale test setup use the same settings path thatdetectLocale()actually reads under multi-file test execution, so this coverage does not flake/fail when run with neighboring tests.
559784a to
bdabc78
Compare
|
Updated the localized command suggestion path. The suggestion index already uses rendered descriptions from
Verified locally:
|
Add a simple i18n helper that reads the `language` setting from config
to display localized skill descriptions. Currently supports English
(default) and Vietnamese.
To switch to Vietnamese, set in ~/.claude/settings.json:
{ "language": "vietnamese" }
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
- Fix detectLocale() to read ~/.claude/settings.json directly via
readFileSync instead of broken require('../../utils/config.js')
- Add commandDescVi translation map with 85 Vietnamese descriptions
- Export translateCommandDescription() for use in command rendering
- Modify formatDescriptionWithSource() to translate descriptions
when language is set to "vietnamese"
- Bump version to 0.15.1
When installing via `npm install -g git+https://...`, npm runs the `prepare` script automatically. This ensures the CLI is built from source during installation. Requires Bun to be installed globally. Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
… node version files ## Changes ### 1. Fix prompt-type command translations (src/commands.ts) - `formatDescriptionWithSource()` now calls `translateCommandDescription()` for ALL command types - Previously only translated `builtin`/`mcp` source commands - Now translates: workflow, plugin, bundled, and default cases - Fixes: /review, /insights, and other prompt-type commands now display Vietnamese ### 2. Add missing Vietnamese translations (src/skills/bundled/i18n.ts) Added 17 new command translations: - /btw: "Đặt câu hỏi nhanh bên lề mà không làm gián đoạn cuộc hội thoại chính" - /compact: "Xóa lịch sử hội thoại nhưng giữ tóm tắt trong ngữ cảnh" - /auto-fix: "Cấu hình tự động sửa: chạy lint/test sau khi AI chỉnh sửa" - /bridge-kick: "Chèn trạng thái lỗi bridge để kiểm thử khôi phục thủ công" - /review: "Hoàn thành đánh giá bảo mật cho các thay đổi đang chờ trên nhánh hiện tại" - +12 more commands ### 3. Add Zod env validation at startup (src/utils/envValidation.ts) - New file: validates critical env vars using Zod at startup - Crashes immediately if invalid (instead of wasting time) - Validated vars: ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, CLAUDE_CONFIG_DIR, HTTP_PROXY, HTTPS_PROXY, NODE_EXTRA_CA_CERTS - Integrated into src/entrypoints/init.ts ### 4. Add node version files - .nvmrc: Node 22 - .node-version: Node 22 - Matches Dockerfile (node:22-slim) and package.json engines (>=22.0.0) ## Test Results - 3007 pass, 11 fail (all in changeDetector.test.ts - pre-existing, unrelated to i18n) Co-Authored-By: OpenClaude <noreply@openclaude.ai>
Search rendered localized command descriptions and rebuild the Fuse index when language-sensitive text changes. Preserve Unicode letters and numbers for Vietnamese slash queries, localize the remaining requested command descriptions, and keep exact slash command submission from following a stale highlighted suggestion. Tests: bun test src/commands.test.ts; bun test src/utils/suggestions/commandSuggestions.test.ts; bun test src/utils/envValidation.test.ts Thanks to @jatmn for the patient review and guidance.
|
thank you so much for working on this @lht3003-rgb . may I ask to rebase to latest main and kindly fix conflicts |
bdabc78 to
f418831
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/commands.ts`:
- Line 7: The PR accidentally adds the unrelated goal command; remove the import
statement "import goal from './commands/goal/index.js'" and any references to
the goal symbol in the commands registry/array and exports (the added
occurrences of goal in the file) so the Vietnamese i18n change only contains
localization updates, and create a separate commit/PR to introduce the goal
command instead.
In `@src/plugins/builtinPlugins.ts`:
- Around line 137-149: The getters for description (get description) and
whenToUse (get whenToUse) are intentionally used to re-evaluate localization on
each access for dynamic locale switching; confirm this intent and either leave
them as-is or, if these properties are accessed in performance-sensitive code
paths, replace with memoized results (e.g., compute once per locale change) or
convert to plain properties populated when the command is registered; reference
the getters named description and whenToUse and the related keys descriptionKey
and whenToUseKey when making the change.
🪄 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: ASSERTIVE
Plan: Pro Plus
Run ID: 2328063f-60a9-47fd-9455-80fb7f0f5919
📒 Files selected for processing (14)
.node-version.nvmrcsrc/commands.test.tssrc/commands.tssrc/components/PromptInput/PromptInput.tsxsrc/entrypoints/init.tssrc/hooks/useTypeahead.tsxsrc/i18n/commandDescriptions.tssrc/i18n/index.tssrc/i18n/languages/en.tssrc/i18n/languages/vi.tssrc/i18n/locale.tssrc/i18n/types.tssrc/plugins/builtinPlugins.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx,js,jsx,py}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.{ts,tsx,js,jsx,py}: Follow the existing code style in the touched files
Keep comments useful and concise
Files:
src/i18n/types.tssrc/i18n/locale.tssrc/i18n/languages/en.tssrc/i18n/commandDescriptions.tssrc/i18n/languages/vi.tssrc/hooks/useTypeahead.tsxsrc/components/PromptInput/PromptInput.tsxsrc/entrypoints/init.tssrc/i18n/index.tssrc/commands.test.tssrc/commands.tssrc/plugins/builtinPlugins.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Typecheck TypeScript code before submitting (use
bun run typecheck)
Files:
src/i18n/types.tssrc/i18n/locale.tssrc/i18n/languages/en.tssrc/i18n/commandDescriptions.tssrc/i18n/languages/vi.tssrc/hooks/useTypeahead.tsxsrc/components/PromptInput/PromptInput.tsxsrc/entrypoints/init.tssrc/i18n/index.tssrc/commands.test.tssrc/commands.tssrc/plugins/builtinPlugins.ts
**/*
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/i18n/types.tssrc/i18n/locale.tssrc/i18n/languages/en.tssrc/i18n/commandDescriptions.tssrc/i18n/languages/vi.tssrc/hooks/useTypeahead.tsxsrc/components/PromptInput/PromptInput.tsxsrc/entrypoints/init.tssrc/i18n/index.tssrc/commands.test.tssrc/commands.tssrc/plugins/builtinPlugins.ts
**
⚙️ CodeRabbit configuration file
**: # Contributing to OpenClaudeThanks for contributing.
OpenClaude is a fast-moving open-source coding-agent CLI with support for multiple providers, local backends, MCP, and a terminal-first workflow. The best contributions here are focused, well-tested, and easy to review.
Before You Start
- Search existing issues and discussions before opening a new thread.
- Check open pull requests for work that overlaps with your contribution. If a PR already exists that addresses the same change, open an issue or discussion first to align on direction — duplicate PRs may be closed without review.
- Use issues for confirmed bugs and actionable feature work.
- Use discussions for setup help, ideas, and general community conversation.
- For larger changes, open an issue first so the scope is clear before implementation.
- For security reports, follow SECURITY.md.
Pull Requests
Every PR needs a reason. Your PR description must include:
- what changed and why
- the user or developer impact
- the exact checks you ran
- a linked issue when one exists, using
Fixes#123, `Closes `#123, or another clear link- screenshots when the PR touches UI, terminal presentation, or the VS Code extension
- which provider path was tested when the PR changes provider behavior
The PR author is responsible for ensuring their PR is merge-ready. PRs with merge conflicts will not be reviewed or approved until the conflicts are resolved.
Issues are the recommended starting point for anything non-trivial — opening one first helps avoid wasted effort if the change is out of scope or already being worked on. Small fixes, doc corrections, and obvious improvements can stand on their own without a linked issue, as long as the PR description explains the intent.
What Gets Closed Without Review
PRs may be closed without review...
Files:
src/i18n/types.tssrc/i18n/locale.tssrc/i18n/languages/en.tssrc/i18n/commandDescriptions.tssrc/i18n/languages/vi.tssrc/hooks/useTypeahead.tsxsrc/components/PromptInput/PromptInput.tsxsrc/entrypoints/init.tssrc/i18n/index.tssrc/commands.test.tssrc/commands.tssrc/plugins/builtinPlugins.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}
⚙️ CodeRabbit configuration file
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.
Files:
src/entrypoints/init.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/commands.test.ts
🔇 Additional comments (21)
.node-version (1)
1-1: LGTM!.nvmrc (1)
1-1: LGTM!src/commands.test.ts (1)
1-1: LGTM!Also applies to: 6-32, 101-321
src/i18n/types.ts (1)
1-7: LGTM!src/i18n/locale.ts (1)
5-19: LGTM!src/i18n/languages/en.ts (1)
1-106: LGTM!src/i18n/commandDescriptions.ts (1)
3-69: LGTM!src/i18n/index.ts (1)
19-41: LGTM!src/commands.ts (2)
171-174: LGTM!Also applies to: 372-377
762-800: LGTM!src/plugins/builtinPlugins.ts (1)
83-83: LGTM!src/i18n/languages/vi.ts (1)
1-107: Verify i18n dictionary key consistency (en/vi)
src/i18n/languages/en.tsandsrc/i18n/languages/vi.tsexport the same set of keys (67), so there’s no key-mismatch fallback risk.src/hooks/useTypeahead.tsx (3)
25-25: LGTM!
83-83: LGTM!
1141-1149: LGTM!src/components/PromptInput/PromptInput.tsx (3)
173-173: LGTM!
994-994: LGTM!
1114-1116: LGTM!src/entrypoints/init.ts (3)
2-2: LGTM!
71-73: ⚡ Quick winCorrectly validates config-backed environment values before network setup.
This re-validation checkpoint ensures config-hydrated proxy and CA cert values are validated before
configureGlobalMTLS()(line 115) andconfigureGlobalAgents()(line 124) consume them. This directly addresses the past review concern that bad config-backed proxy/CA values were bypassing validation and failing later during network setup.
50-52: Early validateEnvVars() timing is compatible with the current EnvSchema.EnvSchema marks ANTHROPIC_* keys, CLAUDE_CONFIG_DIR, HTTP_PROXY/HTTPS_PROXY, and NODE_EXTRA_CA_CERTS as optional (and proxy vars accept unset/empty or a valid URL). So the early validateEnvVars() before enableConfigs/applySafeConfigEnvironmentVariables() won’t fail just because config-backed values haven’t been applied yet—only malformed user-provided values will exit(1). The later validateEnvVars() after applySafeConfigEnvironmentVariables() covers the hydrated values.
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 2
🤖 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/commands.ts`:
- Line 7: The PR accidentally adds the unrelated goal command; remove the import
statement "import goal from './commands/goal/index.js'" and any references to
the goal symbol in the commands registry/array and exports (the added
occurrences of goal in the file) so the Vietnamese i18n change only contains
localization updates, and create a separate commit/PR to introduce the goal
command instead.
In `@src/plugins/builtinPlugins.ts`:
- Around line 137-149: The getters for description (get description) and
whenToUse (get whenToUse) are intentionally used to re-evaluate localization on
each access for dynamic locale switching; confirm this intent and either leave
them as-is or, if these properties are accessed in performance-sensitive code
paths, replace with memoized results (e.g., compute once per locale change) or
convert to plain properties populated when the command is registered; reference
the getters named description and whenToUse and the related keys descriptionKey
and whenToUseKey when making the change.
🪄 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: ASSERTIVE
Plan: Pro Plus
Run ID: 2328063f-60a9-47fd-9455-80fb7f0f5919
📒 Files selected for processing (14)
.node-version.nvmrcsrc/commands.test.tssrc/commands.tssrc/components/PromptInput/PromptInput.tsxsrc/entrypoints/init.tssrc/hooks/useTypeahead.tsxsrc/i18n/commandDescriptions.tssrc/i18n/index.tssrc/i18n/languages/en.tssrc/i18n/languages/vi.tssrc/i18n/locale.tssrc/i18n/types.tssrc/plugins/builtinPlugins.ts
📜 Review details
🔇 Additional comments (21)
.node-version (1)
1-1: LGTM!.nvmrc (1)
1-1: LGTM!src/commands.test.ts (1)
1-1: LGTM!Also applies to: 6-32, 101-321
src/i18n/types.ts (1)
1-7: LGTM!src/i18n/locale.ts (1)
5-19: LGTM!src/i18n/languages/en.ts (1)
1-106: LGTM!src/i18n/commandDescriptions.ts (1)
3-69: LGTM!src/i18n/index.ts (1)
19-41: LGTM!src/commands.ts (2)
171-174: LGTM!Also applies to: 372-377
762-800: LGTM!src/plugins/builtinPlugins.ts (1)
83-83: LGTM!src/i18n/languages/vi.ts (1)
1-107: Verify i18n dictionary key consistency (en/vi)
src/i18n/languages/en.tsandsrc/i18n/languages/vi.tsexport the same set of keys (67), so there’s no key-mismatch fallback risk.src/hooks/useTypeahead.tsx (3)
25-25: LGTM!
83-83: LGTM!
1141-1149: LGTM!src/components/PromptInput/PromptInput.tsx (3)
173-173: LGTM!
994-994: LGTM!
1114-1116: LGTM!src/entrypoints/init.ts (3)
2-2: LGTM!
71-73: ⚡ Quick winCorrectly validates config-backed environment values before network setup.
This re-validation checkpoint ensures config-hydrated proxy and CA cert values are validated before
configureGlobalMTLS()(line 115) andconfigureGlobalAgents()(line 124) consume them. This directly addresses the past review concern that bad config-backed proxy/CA values were bypassing validation and failing later during network setup.
50-52: Early validateEnvVars() timing is compatible with the current EnvSchema.EnvSchema marks ANTHROPIC_* keys, CLAUDE_CONFIG_DIR, HTTP_PROXY/HTTPS_PROXY, and NODE_EXTRA_CA_CERTS as optional (and proxy vars accept unset/empty or a valid URL). So the early validateEnvVars() before enableConfigs/applySafeConfigEnvironmentVariables() won’t fail just because config-backed values haven’t been applied yet—only malformed user-provided values will exit(1). The later validateEnvVars() after applySafeConfigEnvironmentVariables() covers the hydrated values.
🛑 Comments failed to post (2)
src/commands.ts (1)
7-7:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winGoal command import is out of scope for i18n PR.
This PR is focused on Vietnamese localization. Adding the
goalcommand (lines 7, 333, 664, 692) is unrelated and should be in a separate commit/PR. Per AGENTS.md: "Avoid mixing unrelated cleanup into the same change."🤖 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/commands.ts` at line 7, The PR accidentally adds the unrelated goal command; remove the import statement "import goal from './commands/goal/index.js'" and any references to the goal symbol in the commands registry/array and exports (the added occurrences of goal in the file) so the Vietnamese i18n change only contains localization updates, and create a separate commit/PR to introduce the goal command instead.Source: Coding guidelines
src/plugins/builtinPlugins.ts (1)
137-149: 🧹 Nitpick | 🔵 Trivial | 💤 Low value
Confirm getter pattern is intentional for dynamic locale switching.
Using getters for
descriptionandwhenToUsemeans they're re-evaluated on every access. This enables immediate locale changes without cache invalidation, but adds a small runtime cost. If command descriptions are accessed in performance-sensitive paths (e.g., tight loops), consider memoization. Otherwise, this pattern is sound for i18n.🤖 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/plugins/builtinPlugins.ts` around lines 137 - 149, The getters for description (get description) and whenToUse (get whenToUse) are intentionally used to re-evaluate localization on each access for dynamic locale switching; confirm this intent and either leave them as-is or, if these properties are accessed in performance-sensitive code paths, replace with memoized results (e.g., compute once per locale change) or convert to plain properties populated when the command is registered; reference the getters named description and whenToUse and the related keys descriptionKey and whenToUseKey when making the change.
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the contribution. I do not see any actionable issues from my review.
@kevincodex1 LGTM
* feat: add Vietnamese i18n support for slash command descriptions
Add a simple i18n helper that reads the `language` setting from config
to display localized skill descriptions. Currently supports English
(default) and Vietnamese.
To switch to Vietnamese, set in ~/.claude/settings.json:
{ "language": "vietnamese" }
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
* feat(i18n): add Vietnamese translations for all 85 command descriptions
- Fix detectLocale() to read ~/.claude/settings.json directly via
readFileSync instead of broken require('../../utils/config.js')
- Add commandDescVi translation map with 85 Vietnamese descriptions
- Export translateCommandDescription() for use in command rendering
- Modify formatDescriptionWithSource() to translate descriptions
when language is set to "vietnamese"
- Bump version to 0.15.1
* fix: add prepare script for git-based installs
When installing via `npm install -g git+https://...`, npm runs the
`prepare` script automatically. This ensures the CLI is built from
source during installation.
Requires Bun to be installed globally.
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
* fix(i18n): read locale from merged settings
* feat(i18n): translate all prompt-type commands + add env validation + node version files
## Changes
### 1. Fix prompt-type command translations (src/commands.ts)
- `formatDescriptionWithSource()` now calls `translateCommandDescription()` for ALL command types
- Previously only translated `builtin`/`mcp` source commands
- Now translates: workflow, plugin, bundled, and default cases
- Fixes: /review, /insights, and other prompt-type commands now display Vietnamese
### 2. Add missing Vietnamese translations (src/skills/bundled/i18n.ts)
Added 17 new command translations:
- /btw: "Đặt câu hỏi nhanh bên lề mà không làm gián đoạn cuộc hội thoại chính"
- /compact: "Xóa lịch sử hội thoại nhưng giữ tóm tắt trong ngữ cảnh"
- /auto-fix: "Cấu hình tự động sửa: chạy lint/test sau khi AI chỉnh sửa"
- /bridge-kick: "Chèn trạng thái lỗi bridge để kiểm thử khôi phục thủ công"
- /review: "Hoàn thành đánh giá bảo mật cho các thay đổi đang chờ trên nhánh hiện tại"
- +12 more commands
### 3. Add Zod env validation at startup (src/utils/envValidation.ts)
- New file: validates critical env vars using Zod at startup
- Crashes immediately if invalid (instead of wasting time)
- Validated vars: ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, CLAUDE_CONFIG_DIR, HTTP_PROXY, HTTPS_PROXY, NODE_EXTRA_CA_CERTS
- Integrated into src/entrypoints/init.ts
### 4. Add node version files
- .nvmrc: Node 22
- .node-version: Node 22
- Matches Dockerfile (node:22-slim) and package.json engines (>=22.0.0)
## Test Results
- 3007 pass, 11 fail (all in changeDetector.test.ts - pre-existing, unrelated to i18n)
Co-Authored-By: OpenClaude <noreply@openclaude.ai>
* fix: restore validateBoundedIntEnvVar in envValidation.ts
* Localize bundled skills descriptions at read time
* fix(i18n): localize slash command suggestions
Search rendered localized command descriptions and rebuild the Fuse index when language-sensitive text changes.
Preserve Unicode letters and numbers for Vietnamese slash queries, localize the remaining requested command descriptions, and keep exact slash command submission from following a stale highlighted suggestion.
Tests: bun test src/commands.test.ts; bun test src/utils/suggestions/commandSuggestions.test.ts; bun test src/utils/envValidation.test.ts
Thanks to @jatmn for the patient review and guidance.
* fix(i18n): tighten slash command localization scope
* fix(i18n): centralize localization and preserve external metadata
* fix(commands): scope localized descriptions to OpenClaude-owned commands
* fix(i18n): read session language before initial settings
* fix(i18n): prefer whenToUse localization keys
---------
Co-authored-by: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Co-authored-by: OpenClaude <noreply@openclaude.ai>
Co-authored-by: lht3003-rgb <lht3003-rgb@users.noreply.github.com>
Summary
src/i18nmodule.Changes
src/i18n/*src/commands.tssrc/skills/bundled/*src/plugins/builtinPlugins.tssrc/types/command.ts/src/types/plugin.tssrc/utils/suggestions/commandSuggestions.test.tssrc/commands.test.tsHow to switch language
Set the OpenClaude language setting to Vietnamese or English through the normal configuration flow.
Supported values:
{ "language": "vietnamese" } { "language": "vi" } { "language": "english" } { "language": "en" }Test plan
bun test src/commands.test.tsbun test src/utils/suggestions/commandSuggestions.test.tsNotes
package.jsonor add apreparescript.Summary by CodeRabbit
New Features
Tests
Chores
Bug Fixes