qwen-code/docs/users/features/language.md
tanzhenxin f6315b378d
refactor(cli): revert dynamic slash command LLM translation (#4145)
* refactor(cli): revert dynamic slash command LLM translation (#4137)

Removes the runtime LLM-translation path for dynamic slash command
descriptions added in #3871, along with its `general.dynamicCommandTranslation`
setting and the `/language translate` subcommand tree.

Keeps the built-in locale coverage from the same PR untouched. Localization
of dynamic command descriptions should be solved at the source (manifest
fields, not runtime model calls); see #4137 for the proposed alternative.

* refactor(cli): drop translate prompts from mustTranslateKeys

Follow-up to the dynamic command translation revert: the 7 prompt keys
were stripped from every locale file in the previous commit, but the
allow-list in mustTranslateKeys still demanded them.

* refactor(cli): drop dead CommandService.fromCommands and vacuous tests

Follow-up cleanup after the dynamic command translation revert.

CommandService.fromCommands was introduced by #3871 solely to wrap the
LLM-translated command list. With the LLM-translation path gone, it has
no remaining non-test callers — remove it and the matching test mock.

Also drop two assertions in languageCommand.test.ts that checked for the
absence of a top-level /language cache command. They tested a migration
state that never existed in this branch and now pass vacuously.

* docs: drop /language translate references after revert

Two user-facing docs documented the /language translate subcommands
(status/on/off/cache refresh/clear) that were removed in the dynamic
command translation revert. Strip them so users following the docs
don't hit "Invalid command" errors.

* refactor(cli): drop unused localizeDescription field

The DynamicCommandLocalizationService that read this flag was removed in
the revert, leaving the field with five setters and zero readers. Drop the
field, its JSDoc, and the five `localizeDescription: true` assignments.
Also tidy the now-misleading `modelDescription` JSDoc and the stale
`reloadCommands` comment that referenced the removed feature.

* refactor(cli): drop unused getLanguageNameForTranslationTarget

The only caller was the removed DynamicCommandLocalizationService.
Remove the function from `i18n/languages.ts` and the matching
import + re-export from `i18n/index.ts`.
2026-05-15 16:01:16 +08:00

8.3 KiB
Raw Permalink Blame History

Internationalization (i18n) & Language

Qwen Code is built for multilingual workflows: it supports UI localization (i18n/l10n) in the CLI, lets you choose the assistant output language, and allows custom UI language packs.

Overview

From a user point of view, Qwen Codes “internationalization” spans multiple layers:

Capability / Setting What it controls Where stored
/language ui Terminal UI text (menus, system messages, prompts) ~/.qwen/settings.json
/language output Language the AI responds in (an output preference, not UI translation) ~/.qwen/output-language.md
Custom UI language packs Overrides/extends built-in UI translations ~/.qwen/locales/*.js

UI Language

This is the CLIs UI localization layer (i18n/l10n): it controls the language of menus, prompts, and system messages.

Setting the UI Language

Use the /language ui command:

/language ui zh-CN    # Chinese
/language ui en-US    # English
/language ui ru-RU    # Russian
/language ui de-DE    # German
/language ui ja-JP    # Japanese
/language ui pt-BR    # Portuguese (Brazil)
/language ui fr-FR    # French
/language ui ca-ES    # Catalan

Aliases are also supported:

/language ui zh       # Chinese
/language ui en       # English
/language ui ru       # Russian
/language ui de       # German
/language ui ja       # Japanese
/language ui pt       # Portuguese
/language ui fr       # French
/language ui ca       # Catalan

Auto-detection

On first startup, Qwen Code detects your system locale and sets the UI language automatically.

Detection priority:

  1. QWEN_CODE_LANG environment variable
  2. LANG environment variable
  3. System locale via JavaScript Intl API
  4. Default: English

LLM Output Language

The LLM output language controls what language the AI assistant responds in, regardless of what language you type your questions in.

How It Works

The LLM output language is controlled by a rule file at ~/.qwen/output-language.md. This file is automatically included in the LLM's context during startup, instructing it to respond in the specified language.

Auto-detection

On first startup, if no output-language.md file exists, Qwen Code automatically creates one based on your system locale. For example:

  • System locale zh creates a rule for Chinese responses
  • System locale en creates a rule for English responses
  • System locale ru creates a rule for Russian responses
  • System locale de creates a rule for German responses
  • System locale ja creates a rule for Japanese responses
  • System locale pt creates a rule for Portuguese responses
  • System locale fr creates a rule for French responses
  • System locale ca creates a rule for Catalan responses

Manual Setting

Use /language output <language> to change:

/language output Chinese
/language output English
/language output Japanese
/language output German

Any language name works. The LLM will be instructed to respond in that language.

Note

After changing the output language, restart Qwen Code for the change to take effect.

File Location

~/.qwen/output-language.md

Configuration

Via Settings Dialog

  1. Run /settings
  2. Find "Language" under General
  3. Select your preferred UI language

Via Environment Variable

export QWEN_CODE_LANG=zh

This influences auto-detection on first startup (if you havent set a UI language and no output-language.md file exists yet).

Custom Language Packs

For UI translations, you can create custom language packs in ~/.qwen/locales/:

  • Example: ~/.qwen/locales/es.js for Spanish
  • Example: ~/.qwen/locales/fr.js for French

User directory takes precedence over built-in translations.

Tip

Contributions are welcome! If youd like to improve built-in translations or add new languages. For a concrete example, see PR #1238: feat(i18n): add Russian language support.

Maintaining zh-TW (Traditional Chinese for Taiwan)

zh-TW is not an automatic OpenCC s2t conversion of zh.js — it is a hand-maintained Taiwan-vocabulary translation. When adding or updating keys, please follow the conventions below.

The "CI enforced?" column indicates whether npm run check-i18n will fail the build on a violation. Rows marked No are style guidance enforced by review only — typically because the offending form has a legitimate non-UI meaning (文件 can mean "document", 打開 is colloquially fine in Taiwan).

Avoid Use instead CI enforced? Reason
文件 (file) 檔案 No Taiwan term for filesystem files (but 文件 can legitimately mean "document")
服務器 / 服务器 伺服器 Yes Taiwan term for "server"
菜單 / 菜单 選單 Yes Taiwan term for "menu"
鏈接 / 链接 連結 Yes Taiwan term for "link" (bare is fine — e.g. 區塊鏈)
打開 開啟 No Taiwan-preferred verb for "open" (UI); 打開 is colloquially common
爲 / 啓 / 曆史 / 鏈接 為 / 啟 / 歷史 / 連結 Yes Variant Traditional forms from raw OpenCC s2t. Note: is context-dependent and correct in calendar terms (日曆, 農曆, 西曆); CI only flags the bigram 曆史, not bare .

If you are not a Traditional Chinese speaker and need to bootstrap a value, do not paste raw OpenCC s2t output: the default s2t profile emits variant Traditional characters (e.g. 爲, 啓) that Taiwan does not use, and never rewrites Mainland-Chinese vocabulary (服務器, 菜單). Prefer s2twp.json (Simplified → Taiwan with phrase mapping) as a starting point and then ask a Taiwan-Chinese speaker to review.

The check-i18n script (run in CI via npm run check-i18n) will fail the build if any of the CI-enforced substrings above end up in a zh-TW value. See scripts/check-i18n.ts → ZH_TW_FORBIDDEN_PATTERNS for the full list. If a translation legitimately needs to contain a CI-forbidden substring, add its key to ZH_TW_ALLOWED_EXCEPTIONS in the same file with a brief justification.

Note

The check uses plain substring matching, which does not understand Chinese word boundaries. A bigram pattern can therefore false-positive across compound-word boundaries — for example, 區塊鏈接口 (= 區塊鏈 + 接口) contains the substring 鏈接 even though neither word is incorrect. If you hit a surprising CI failure of this kind, add the translation key to ZH_TW_ALLOWED_EXCEPTIONS rather than removing the pattern.

Language Pack Format

// ~/.qwen/locales/es.js
export default {
  Hello: 'Hola',
  Settings: 'Configuracion',
  // ... more translations
};
  • /language - Show current language settings
  • /language ui [lang] - Set UI language
  • /language output <language> - Set LLM output language
  • /settings - Open settings dialog