Skip to content

feat: add Vietnamese i18n for slash command descriptions - #1431

Merged
kevincodex1 merged 13 commits into
Twigpine:mainfrom
lht3003-rgb:feat/vietnamese-i18n-slash-commands
Jun 12, 2026
Merged

kevincodex1 merged 13 commits into
Twigpine:mainfrom
lht3003-rgb:feat/vietnamese-i18n-slash-commands

Conversation

@lht3003-rgb

@lht3003-rgb lht3003-rgb commented May 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add Vietnamese localization for OpenClaude-owned slash command descriptions.
  • Move command and bundled skill localization resources into the centralized src/i18n module.
  • Use explicit localization keys for OpenClaude-owned command and skill descriptions.
  • Preserve project/plugin/policy/workflow/user-authored command metadata, even when descriptions match built-in English strings.
  • Keep slash command rendering and search behavior using localized/rendered descriptions.

Changes

Area Change
src/i18n/* Add centralized localization types, locale helpers, command description keys, and English/Vietnamese dictionaries
src/commands.ts Localize command descriptions only through explicit localization keys
src/skills/bundled/* Replace inline per-language text blobs with English fallbacks and localization keys
src/plugins/builtinPlugins.ts Use centralized localization for OpenClaude-owned built-in plugin metadata
src/types/command.ts / src/types/plugin.ts Add optional localization metadata fields
src/utils/suggestions/commandSuggestions.test.ts Cover localized slash-command search behavior
src/commands.test.ts Cover localization scoping, fallback behavior, and external metadata preservation

How 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.ts
  • bun test src/utils/suggestions/commandSuggestions.test.ts

Notes

  • External project/plugin/policy/workflow/user-authored command descriptions are preserved and are not translated by raw English text matching.
  • This PR does not change package.json or add a prepare script.
  • This PR no longer includes git-install testing instructions.

Summary by CodeRabbit

  • New Features

    • Internationalization (English + Vietnamese) for command and skill descriptions with locale detection, interpolation and fallbacks.
    • Slash-command override support to improve suggestion selection and command execution.
  • Tests

    • Expanded tests for localization, bundled-skill localization, duplicate-command/Enter behavior, model/provider isolation, and env validation.
  • Chores

    • Pinned Node.js runtime to version 22.
  • Bug Fixes

    • Startup environment-variable validation to fail fast on invalid config.

kevincodex1
kevincodex1 previously approved these changes May 29, 2026

@kevincodex1 kevincodex1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Awesome! Thank you for working on this

@kevincodex1
kevincodex1 requested a review from jatmn May 29, 2026 15:40

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 imports getConfig from ../../utils/config.js, but that module does not export getConfig; the exported runtime accessor is getGlobalConfig. Because this call throws and is swallowed, detectLocale() always returns en, so setting "language": "vietnamese" or "vi" never changes /loop, /simplify, or /update-config descriptions. 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 a prepare script and documents npm install -g git+https://github.com/lht3003-rgb/openclaude.git, but the package scripts still only have prepack. Since dist/cli.mjs is not tracked in git and the bin wrapper exits when dist is missing, a git install from the fork will not produce a runnable CLI unless the build is run during install. Please either add the prepare script the PR claims, or remove the git-install instructions/claim from the PR scope.

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 reads homedir()/.claude/settings.json directly, 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 configured language through 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 a prepare script and asks reviewers to test npm install -g git+https://github.com/lht3003-rgb/openclaude.git, but package.json still only has prepack. bin/openclaude exits when dist/cli.mjs is 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 to 0.15.1, which adds release churn without fixing the install path this PR claims to address. Please either add the real prepare hook or drop the git-install/version change from this PR.

kevincodex1
kevincodex1 previously approved these changes May 30, 2026

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 call t() while the skills are registered at startup. OpenClaude already resets its settings cache and updates app state when language changes, 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 new commandDescVi table includes prompt built-ins such as Review a pull request and Generate a report analyzing your OpenClaude sessions, but formatDescriptionWithSource() returns prompt built-ins unchanged before calling the translation helper. As a result, /review and /insights still show English descriptions with language: "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 jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 call t() while the skill is registered, and registerBundledSkill() stores that resolved string on the command object. The new formatDescriptionWithSource() translation path fixes prompt built-ins such as /review, but it does not cover these long /loop, /simplify, or /update-config descriptions because they are not in commandDescVi. If a user starts in English and changes language to 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 as ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, CLAUDE_CONFIG_DIR, and NODE_EXTRA_CA_CERTS use z.string().min(1).optional(). Before this change, the runtime treated empty values as unset with truthiness checks such as if (process.env.ANTHROPIC_API_KEY) and if (process.env.NODE_EXTRA_CA_CERTS). With this PR, launching OpenClaude with ANTHROPIC_API_KEY= or NODE_EXTRA_CA_CERTS= exits before config initialization, even though those were previously harmless absent values. Please normalize empty strings to undefined or allow empty strings for optional env vars that the rest of the app already treats as unset.

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 through formatDescriptionWithSource(), but the Fuse index used for searching is still built from the raw cmd.description. For translated built-ins such as /review, a Vietnamese session shows Đánh giá pull request in the picker, but searching for /đánh returns 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 /config changes. 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.

@lht3003-rgb
lht3003-rgb force-pushed the feat/vietnamese-i18n-slash-commands branch from 034c460 to 05daa9b Compare June 1, 2026 04:47

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 with description: "Review a pull request" now renders as Đánh giá pull request (project) when language is 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 jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

please rebase on main to fix merge conflicts

@lht3003-rgb
lht3003-rgb force-pushed the feat/vietnamese-i18n-slash-commands branch from 3cc1bee to d9f84b9 Compare June 2, 2026 01:13
@kevincodex1

Copy link
Copy Markdown
Member

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?

@kevincodex1
kevincodex1 requested a review from jatmn June 2, 2026 01:19
kevincodex1
kevincodex1 previously approved these changes Jun 2, 2026
@kevincodex1

Copy link
Copy Markdown
Member

please check again bro @jatmn . I think we should put all localization in a single folder

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 in commandDescVi is rewritten in Vietnamese. The new test even codifies that non-prompt local descriptions like Set 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 in src/skills/bundled/i18n.ts, while bundled skill translations are stored separately inside individual skill implementations (batch.ts, debug.ts, loop.ts, simplify.ts, and updateConfig.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 a prepare script and asks reviewers to test npm install -g git+https://github.com/lht3003-rgb/openclaude.git, but the current diff no longer changes package.json and the scripts still only include prepack. 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.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c9fdd82d-5c70-4242-b491-9e1667a9b2b2

📥 Commits

Reviewing files that changed from the base of the PR and between f418831 and 354857f.

📒 Files selected for processing (2)
  • src/plugins/builtinPlugins.ts
  • src/skills/bundledSkills.ts
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{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/plugins/builtinPlugins.ts
  • src/skills/bundledSkills.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Typecheck TypeScript code before submitting (use bun run typecheck)

Files:

  • src/plugins/builtinPlugins.ts
  • src/skills/bundledSkills.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/plugins/builtinPlugins.ts
  • src/skills/bundledSkills.ts
**

⚙️ CodeRabbit configuration file

**: # Contributing to OpenClaude

Thanks 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 fix: skip assertMinVersion for third-party providers #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/plugins/builtinPlugins.ts
  • src/skills/bundledSkills.ts
src/{skills,utils/plugins,services/mcp}/**

⚙️ CodeRabbit configuration file

src/{skills,utils/plugins,services/mcp}/**: Review skill/plugin/MCP behavior as a trust boundary. Check registry fetches, local and remote installs, path normalization, hash verification, revocation/trust metadata, tools_required handling, config-home behavior, and startup-time loading. Block on path traversal risk, unverified downloads, silent trust promotion, or unexpected code/tool activation.

Files:

  • src/skills/bundledSkills.ts
🔇 Additional comments (2)
src/plugins/builtinPlugins.ts (1)

145-150: LGTM!

src/skills/bundledSkills.ts (1)

90-94: LGTM!


📝 Walkthrough

Walkthrough

Adds 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.

Changes

Internationalization System

Layer / File(s) Summary
i18n types and locale detection
src/i18n/types.ts, src/i18n/locale.ts
Locale/type definitions and detectLocale() that maps session/initial settings into `'en'
Language bundles and localize facade
src/i18n/languages/en.ts, src/i18n/languages/vi.ts, src/i18n/index.ts, src/i18n/commandDescriptions.ts
English and Vietnamese dictionaries; localize(key,fallback,values) with fallback and interpolation; command-name→localization-key lookup.
Command & plugin type and metadata wiring
src/types/command.ts, src/types/plugin.ts, src/commands.ts, src/plugins/builtinPlugins.ts
Add typed localizationKey/whenToUseLocalizationKey/descriptionKey fields; attach localizationKey to COMMANDS and render built-in/plugin descriptions via localize.
Bundled skills localization
src/skills/bundledSkills.ts, src/skills/bundled/*
Add descriptionKey/whenToUseKey to bundled skill metadata and compute localized description/whenToUse via getters, exposing raw localization keys at runtime.
Search & suggestion indexing
src/utils/suggestions/commandSuggestions.ts
Cache Fuse index by command snapshot signature including renderedDescription; centralize getRenderedCommandDescription, add getCommandSuggestionForEnter, and switch token normalization to Unicode-aware classes.
Localization tests
src/commands.test.ts, src/utils/suggestions/commandSuggestions.test.ts
Expand tests verifying localized description rendering, bundled skill localization/fallback, localized suggestion matching, duplicate-command selection, and Enter behavior.

Environment Variable Validation

Layer / File(s) Summary
Env schema and validator
src/utils/envValidation.ts, src/utils/envValidation.test.ts
Add Zod EnvSchema and validateEnvVars() that parses process.env, logs errors and exits on failure; tests check empty optional vars become undefined.
Init integration
src/entrypoints/init.ts
Call validateEnvVars() early in init() and again after applying safe/hydrated env vars before network/proxy setup.

Slash-command override & submission plumbing

Layer / File(s) Summary
Typeahead and input contracts
src/hooks/useTypeahead.tsx, src/components/PromptInput/PromptInput.tsx, src/screens/REPL.tsx, src/types/textInputTypes.ts
Extend onSubmit/options and QueuedCommand types to accept slashCommandOverride?: Command; use getCommandSuggestionForEnter to derive command on Enter for command suggestions.
Submission queue and forwarding
src/utils/handlePromptSubmit.ts
Add slashCommandOverride to HandlePromptSubmitParams, include it in enqueue payloads and constructed QueuedCommand.
Processing and resolution
src/utils/processUserInput/*, src/utils/processUserInput/processSlashCommand.tsx
Thread slashCommandOverride through processUserInput → processUserInputBase → processSlashCommand; introduce resolveSlashCommand which prefers a matching override when resolving commands.

Tests, infra, and toolchain

Layer / File(s) Summary
Model-test isolation & attribution
src/utils/model/model.openai-shim-providers.test.ts, src/utils/attribution.test.ts
Improve test reset/restore behavior, mock/restore modelAllowlist/providers to avoid leakage; adapt attribution assertion style.
Suggestion & command tests
src/commands.test.ts, src/utils/suggestions/commandSuggestions.test.ts
Add tests for localized descriptions, bundled skill localization, duplicate-command handling, and Enter normalization.
Node toolchain pin
.node-version, .nvmrc
Pin Node.js runtime to version 22.

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • kevincodex1
  • jatmn
🚥 Pre-merge checks | ✅ 5 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Risk Surface Disclosed ⚠️ Warning PR touches startup/config-home (init.ts validateEnvVars/envValidation) and skills/plugins (builtinPlugins + bundled skills), but PR description/notes don’t disclose the risk surface or whether it’s... Update the PR description/review with a “Risk surface” note covering startup/env validation + skill/plugin changes, and explicitly state whether any part is a blocker (or why not).
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding Vietnamese i18n for slash command descriptions, matching the substantial i18n infrastructure and localization additions in the changeset.
Description check ✅ Passed The description covers all required template sections: summary of changes, detailed impact/scope table, language switching instructions, comprehensive test plan, and relevant notes addressing preservation of external metadata and build implications.
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.
No Hidden Policy Change ✅ Passed No hidden policy change found: init.ts only adds validateEnvVars twice; envValidation schema validates API keys/proxies/CA only, with no telemetry/trust/routing/permission-policy logic changes dete...

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@lht3003-rgb

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review.

I’ve updated the implementation to address the remaining i18n issues:

  • Moved command and bundled skill localization resources into the centralized src/i18n module.
  • Removed raw English text-match localization from the command description render path.
  • Command descriptions are now localized only when an explicit localizationKey is present.
  • Preserved project/plugin/policy/workflow/user-authored metadata even when descriptions match built-in English strings.
  • Added tests for external metadata preservation, explicit localization keys, fallback behavior, bundled skill localization, and localized slash-command search.

Validation:

  • bun test src/commands.test.ts
  • bun test src/utils/suggestions/commandSuggestions.test.ts

I also updated the PR body/test plan to remove the stale prepare/git-install claim and keep it aligned with the current localization-only scope.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/i18n/types.ts (1)

3-6: ⚡ Quick win

Derive LocalizationKey from the base dictionary to prevent future key drift

Right now src/i18n/types.ts defines LocalizationKey = string, so src/i18n/commandDescriptions.ts and src/i18n/index.ts can compile even when a key is wrong—missing keys will silently fall back via dictionaries[locale]?.[key] ?? en[key] ?? fallback. EN and VI key sets are currently aligned, and all commandDescriptions.ts values 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) with satisfies 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 win

Strengthen commit trailer assertion to avoid false positives.

toStartWith + toEndWith can 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5925a9c and 11b8a44.

📒 Files selected for processing (27)
  • .node-version
  • .nvmrc
  • src/commands.test.ts
  • src/commands.ts
  • src/entrypoints/init.ts
  • src/hooks/useTypeahead.tsx
  • src/i18n/commandDescriptions.ts
  • src/i18n/index.ts
  • src/i18n/languages/en.ts
  • src/i18n/languages/vi.ts
  • src/i18n/locale.ts
  • src/i18n/types.ts
  • src/plugins/builtinPlugins.ts
  • src/skills/bundled/batch.ts
  • src/skills/bundled/debug.ts
  • src/skills/bundled/loop.ts
  • src/skills/bundled/simplify.ts
  • src/skills/bundled/updateConfig.ts
  • src/skills/bundledSkills.ts
  • src/types/command.ts
  • src/types/plugin.ts
  • src/utils/attribution.test.ts
  • src/utils/envValidation.test.ts
  • src/utils/envValidation.ts
  • src/utils/model/model.openai-shim-providers.test.ts
  • src/utils/suggestions/commandSuggestions.test.ts
  • src/utils/suggestions/commandSuggestions.ts

Comment thread src/entrypoints/init.ts
Comment thread src/skills/bundledSkills.ts

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 selected SuggestionItem.metadata, and applyCommandSuggestion() then calls getCommand(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 /review row 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 calls validateEnvVars() before applySafeConfigEnvironmentVariables() and applyExtraCACertsFromConfig(). Those later calls can populate HTTP_PROXY, HTTPS_PROXY, and NODE_EXTRA_CA_CERTS from 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.

@lht3003-rgb

Copy link
Copy Markdown
Contributor Author

Thanks for the follow-up review.

I pushed an update addressing the two latest P2 items:

  • Preserved the selected duplicate slash-command row on Enter by carrying the selected command object through the submit path instead of resolving duplicate names with the first matching command.
  • Re-ran environment validation after config-backed environment values are applied during startup, so hydrated proxy/CA values are validated before network setup.

Validation:

  • bun test src/utils/suggestions/commandSuggestions.test.ts src/utils/processUserInput/processSlashCommand.test.ts src/utils/envValidation.test.ts src/commands.test.ts
  • bun run build

Both passed locally.

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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.ts reliably returns no Vietnamese matches for /đánh and /khoảng. The trigger is the existing attribution test's mock.module('./settings/settings.js'), which replaces getInitialSettings() process-wide while these new tests rely on setSessionSettingsCache() being observed by detectLocale(). Please isolate the new i18n suggestion tests from global settings-module mocks, or make the locale test setup use the same settings path that detectLocale() actually reads under multi-file test execution, so this coverage does not flake/fail when run with neighboring tests.

@lht3003-rgb
lht3003-rgb force-pushed the feat/vietnamese-i18n-slash-commands branch from 559784a to bdabc78 Compare June 12, 2026 06:45
@lht3003-rgb

Copy link
Copy Markdown
Contributor Author

Updated the localized command suggestion path.

The suggestion index already uses rendered descriptions from formatDescriptionWithSource(command), and the cache signature includes renderedDescription. The remaining issue was locale detection during combined test runs: detectLocale() could fall back to getInitialSettings() and miss the session language set by useLanguage('vietnamese').

detectLocale() now checks the session settings cache first, then falls back to initial settings. This keeps localized slash-command search reactive without reintroducing raw English text-match localization.

Verified locally:

  • bun test src/utils/suggestions/commandSuggestions.test.ts → 6 pass, 0 fail
  • bun test src/commands.test.ts src/utils/suggestions/commandSuggestions.test.ts src/utils/envValidation.test.ts src/utils/attribution.test.ts src/utils/model/model.openai-shim-providers.test.ts → 61 pass, 0 fail
  • git diff --check → pass

lht3003-rgb and others added 8 commits June 12, 2026 14:18
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.
@kevincodex1

Copy link
Copy Markdown
Member

thank you so much for working on this @lht3003-rgb . may I ask to rebase to latest main and kindly fix conflicts

@lht3003-rgb
lht3003-rgb force-pushed the feat/vietnamese-i18n-slash-commands branch from bdabc78 to f418831 Compare June 12, 2026 07:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between bdabc78 and f418831.

📒 Files selected for processing (14)
  • .node-version
  • .nvmrc
  • src/commands.test.ts
  • src/commands.ts
  • src/components/PromptInput/PromptInput.tsx
  • src/entrypoints/init.ts
  • src/hooks/useTypeahead.tsx
  • src/i18n/commandDescriptions.ts
  • src/i18n/index.ts
  • src/i18n/languages/en.ts
  • src/i18n/languages/vi.ts
  • src/i18n/locale.ts
  • src/i18n/types.ts
  • src/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.ts
  • src/i18n/locale.ts
  • src/i18n/languages/en.ts
  • src/i18n/commandDescriptions.ts
  • src/i18n/languages/vi.ts
  • src/hooks/useTypeahead.tsx
  • src/components/PromptInput/PromptInput.tsx
  • src/entrypoints/init.ts
  • src/i18n/index.ts
  • src/commands.test.ts
  • src/commands.ts
  • src/plugins/builtinPlugins.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Typecheck TypeScript code before submitting (use bun run typecheck)

Files:

  • src/i18n/types.ts
  • src/i18n/locale.ts
  • src/i18n/languages/en.ts
  • src/i18n/commandDescriptions.ts
  • src/i18n/languages/vi.ts
  • src/hooks/useTypeahead.tsx
  • src/components/PromptInput/PromptInput.tsx
  • src/entrypoints/init.ts
  • src/i18n/index.ts
  • src/commands.test.ts
  • src/commands.ts
  • src/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.ts
  • src/i18n/locale.ts
  • src/i18n/languages/en.ts
  • src/i18n/commandDescriptions.ts
  • src/i18n/languages/vi.ts
  • src/hooks/useTypeahead.tsx
  • src/components/PromptInput/PromptInput.tsx
  • src/entrypoints/init.ts
  • src/i18n/index.ts
  • src/commands.test.ts
  • src/commands.ts
  • src/plugins/builtinPlugins.ts
**

⚙️ CodeRabbit configuration file

**: # Contributing to OpenClaude

Thanks 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.ts
  • src/i18n/locale.ts
  • src/i18n/languages/en.ts
  • src/i18n/commandDescriptions.ts
  • src/i18n/languages/vi.ts
  • src/hooks/useTypeahead.tsx
  • src/components/PromptInput/PromptInput.tsx
  • src/entrypoints/init.ts
  • src/i18n/index.ts
  • src/commands.test.ts
  • src/commands.ts
  • src/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.ts and src/i18n/languages/vi.ts export 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 win

Correctly 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) and configureGlobalAgents() (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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between bdabc78 and f418831.

📒 Files selected for processing (14)
  • .node-version
  • .nvmrc
  • src/commands.test.ts
  • src/commands.ts
  • src/components/PromptInput/PromptInput.tsx
  • src/entrypoints/init.ts
  • src/hooks/useTypeahead.tsx
  • src/i18n/commandDescriptions.ts
  • src/i18n/index.ts
  • src/i18n/languages/en.ts
  • src/i18n/languages/vi.ts
  • src/i18n/locale.ts
  • src/i18n/types.ts
  • src/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.ts and src/i18n/languages/vi.ts export 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 win

Correctly 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) and configureGlobalAgents() (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 win

Goal command import is out of scope for i18n PR.

This PR is focused on Vietnamese localization. Adding the goal command (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 description and whenToUse means 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 jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the contribution. I do not see any actionable issues from my review.

@kevincodex1 LGTM

@kevincodex1 kevincodex1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM!

@kevincodex1
kevincodex1 merged commit 89d0531 into Twigpine:main Jun 12, 2026
4 checks passed
deagwon97 pushed a commit to deagwon97/openclaude that referenced this pull request Jun 15, 2026
* 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>
@coderabbitai coderabbitai Bot mentioned this pull request Jun 24, 2026
3 of 4 tasks
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.

3 participants