Use opencode in your native language. LLM always hears English.
LLMs are worse in non-English. Benchmarks confirm it on every frontier model.
- Claude Opus 4.7 / GPT-5.5 / Gemini 3.1 Pro: identical coding tasks scored 5/5 in English but dropped to 0–1/5 in Arabic and Korean (LILT, 2025).
- Anthropic's own numbers: Japanese 96.9%, Korean 96.6%, Yoruba 80.3% — English is always the baseline (Anthropic docs).
- Token tax: Korean ~1.25×, Japanese ~1.25×, Arabic ~3× more tokens per equivalent content. Higher cost, smaller effective context.
This plugin lets you write in your language while the model works in English — best of both worlds.
Full research write-up: docs/why.en.md
./install.shThis installs the local single-file plugin to OpenCode's auto-load directory:
~/.config/opencode/plugins/opencode-translate-local.js
No node_modules, package install, or build step is required.
Add to ~/.config/opencode/opencode.jsonc:
OpenCode auto-loads the installed file from ~/.config/opencode/plugins/. The plugin entry above is used to keep this plugin's options in opencode.jsonc without making OpenCode resolve opencode-translate-local as an npm package.
Do not use "opencode-translate-local" as the plugin specifier here; OpenCode treats bare plugin names as npm packages and will try to install opencode-translate-local@latest. Also avoid file://~/.config/...; use {env:HOME} or an absolute path.
If you do not need opencode.jsonc options, you can omit the plugin entry entirely and rely on the auto-loaded file plus environment variables.
Prefix any message with $en to activate translation for that session.
$en 프로젝트 루트의 package.json을 읽고 요약해줘
All subsequent messages in the same session are translated automatically — no need to repeat $en.
Prefix a message with $raw to skip inbound translation for that message. This is useful for pasted logs,
code, JSON, or other long text that should be sent to the model exactly as written, especially when
alwaysOn is enabled.
| Option | Type | Default | Description |
|---|---|---|---|
model |
string | required | Translator model in provider/model-id form |
variant |
string | optional | Translator model variant / thinking effort (for example, "minimal", "high", or "max") |
lang |
string | required | Language you speak (e.g. "Korean", "Japanese") |
trigger |
string[] | ["$en"] |
Keywords that activate translation |
rawTrigger |
string[] | ["$raw"] |
Keywords that skip inbound translation for one message |
verbose |
boolean | false |
Print translation logs |
baseURL / baseUrl |
string | provider/default | Override the translator API base URL |
apiKey / api_key |
string | provider/default | Override the translator API key |
headers |
object | {} |
Extra HTTP headers |
alwaysOn |
boolean | false |
Translate without a trigger. |
timeoutMs |
number | 30000 |
Per-request timeout. |
allowRemote |
boolean | false |
Permit non-local/non-private URLs. |
logText |
boolean | false |
Log full text in verbose mode. Keep disabled normally. |
Environment variables such as OPENCODE_TRANSLATE_BASE_URL, OPENCODE_TRANSLATE_MODEL, OPENCODE_TRANSLATE_API_KEY, OPENCODE_TRANSLATE_LANG, OPENCODE_TRANSLATE_TRIGGER, OPENCODE_TRANSLATE_RAW_TRIGGER, and OPENCODE_TRANSLATE_VERBOSE are supported as fallbacks.
By default, remote translator URLs are rejected. Only localhost and private IP ranges are allowed unless allowRemote or OPENCODE_TRANSLATE_ALLOW_REMOTE=1 is explicitly set.
This work is based on the MIT-licensed ysm-dev/opencode-translate. Many thanks to the upstream project for the original idea and implementation.


{ "plugin": [ ["file://{env:HOME}/.config/opencode/plugins/opencode-translate-local.js", { "model": "openwebui/gpt-oss-120b", // model to use for translation "variant": "low", // optional model variant / thinking effort "trigger": ["$en"], "rawTrigger": ["$raw"], // skip inbound translation for one message "lang": "Japanese", // language you speak "verbose": false }] ] }