claude-babel
v0.1.0
Published
Multilingual translation bridge for Claude Code hooks.
Readme
Claude Babel
Why
Claude Code is often used in multilingual workflows: you may describe intent in Chinese, Japanese, Korean, Spanish, or another language, while most code, logs, APIs, package names, and docs stay in English.
claude-babel adds a small translation layer at the beginning of each turn:
- Detect the user's prompt language.
- If it is not English, translate only the prompt into an English working translation.
- Inject that translation as Claude Code hook context.
- Ask Claude to reply in the user's original language.
It does not interrupt Claude, block tool calls, or force a second answer. The hook is intentionally lightweight.
Claude Code hooks can add context, but cannot silently replace the user's original prompt. So hook mode improves understanding and consistency; it is not a hard guarantee of lower token usage.
Current status
- First version defaults to GLM free model via Zhipu AI / BigModel.
- The default provider/model/base URL are built in.
- Users still need to configure their own API key.
- Future versions can plug in custom model or translation services.
Default GLM settings:
| Setting | Default |
| --- | --- |
| Provider | glm |
| Model | glm-4.7-flash |
| Base URL | https://open.bigmodel.cn/api/paas/v4 |
| Thinking | disabled |
Quick Start
1. Clone or place the project
git clone [email protected]:langchou/claude-babel.git
cd claude-babelFor local development without cloning from GitHub yet:
cd /Users/jonty/code/claude-babel2. Configure the GLM API key
GLM is the default, but it is not anonymous. Configure one of these environment variables:
export ZHIPUAI_API_KEY="your-zhipu-api-key"
# or
export CLAUDE_BABEL_GLM_API_KEY="your-zhipu-api-key"3. Smoke test the hook command
printf '%s\n' '{"session_id":"demo","prompt":"请帮我写一个测试,保留 `src/index.js` 不要翻译。"}' \
| ZHIPUAI_API_KEY="$ZHIPUAI_API_KEY" ./bin/claude-babel.js hook user-prompt-submitYou should see JSON containing hookSpecificOutput.additionalContext with an English working translation.
4. Add the Claude Code hook
Merge this into your Claude Code settings:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "ZHIPUAI_API_KEY=$ZHIPUAI_API_KEY /Users/jonty/code/claude-babel/bin/claude-babel.js hook user-prompt-submit"
}
]
}
]
}
}A copy is available in examples/claude-settings.json.
Only
UserPromptSubmitis configured by default.Stopis intentionally a no-op and is not needed for the first version.
How it works
Input language detection
The detector supports Unicode-script based detection for:
- Chinese
- Japanese
- Korean
- Russian
- Arabic
- Hindi
- Thai
- Hebrew
It also includes lightweight hints for Latin-script languages such as Spanish, French, German, and Portuguese.
Protected content
Before translation, claude-babel protects common technical spans:
- fenced code blocks
- inline code
- URLs
- file paths
This keeps strings like src/index.js, npm test, JSON keys, and stack traces from being translated accidentally.
Hook output
For a Chinese prompt, the hook returns Claude Code hook JSON containing context like:
{
"suppressOutput": true,
"additionalContext": "<claude-babel>...",
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "<claude-babel>..."
}
}The injected additionalContext looks like:
<claude-babel>
The user appears to be writing in Chinese (zh).
A translation provider (glm) produced this English working translation of the user's prompt:
```text
Please help me write a test...
```
Use the English translation to reduce cross-language ambiguity...
Reply to the user in Chinese unless they explicitly ask for another language.
</claude-babel>If the prompt is already English, the hook records state and returns no extra context.
If translation fails, the hook stays non-blocking: it returns a small hint telling Claude to reply in the user's language, but it does not stop the user prompt.
Debugging
1. Check language detection
./bin/claude-babel.js detect "当前项目需要做一个工具"Expected shape:
{"code":"zh","name":"Chinese","confidence":1,"reason":"unicode-script"}2. Test without a real GLM key
Use the echo provider to verify Claude Code hook wiring:
printf '%s\n' '{"session_id":"demo","prompt":"请帮我写测试"}' \
| CLAUDE_BABEL_PROVIDER=echo ./bin/claude-babel.js hook user-prompt-submitThis does not translate; it marks the direction as [Chinese -> English] so you can confirm the hook is running.
3. Test the real GLM call
./bin/claude-babel.js translate "请把这句话翻译成英文"If the key is missing, you will see an error explaining which API-key variables are accepted.
4. Enable debug logs
Debug logs are JSONL and are written outside stdout so they do not break Claude Code's hook JSON parsing.
export CLAUDE_BABEL_DEBUG=1
export CLAUDE_BABEL_DEBUG_DIR=/tmp/claude-babel-debugThen run a hook command and inspect:
tail -f /tmp/claude-babel-debug/debug.jsonlBy default, debug logs do not include prompt content. To include short content previews during local debugging only:
export CLAUDE_BABEL_DEBUG_CONTENT=15. Show a visible Claude Code hook marker
By default Claude Babel is quiet: it injects hook context but does not show a message in the Claude Code transcript. During setup, enable a visible marker:
export CLAUDE_BABEL_VISIBLE=1Chinese prompts will show a hook system message like:
claude-babel: translated zh->en via glmDisable it after validation to keep normal Claude Code output clean.
6. Common issues
| Symptom | Cause | Fix |
| --- | --- | --- |
| translation failed: ... API_KEY ... required | GLM key is missing | Set ZHIPUAI_API_KEY or CLAUDE_BABEL_GLM_API_KEY |
| Hook seems to do nothing | Prompt was detected as English | Run claude-babel detect "..." |
| Claude Code says hook JSON is invalid | Extra text was printed to stdout | Make sure the command runs this script directly and shell startup files do not print text |
| Code/path names get translated | Translator ignored placeholders | File an issue with a sample; protected spans are restored after translation |
Providers
The provider is selected with CLAUDE_BABEL_PROVIDER.
GLM / Zhipu AI / BigModel
Default provider:
export CLAUDE_BABEL_PROVIDER=glm
export ZHIPUAI_API_KEY="your-key"
export CLAUDE_BABEL_GLM_MODEL=glm-4.7-flashAccepted key env names:
CLAUDE_BABEL_GLM_API_KEYZHIPUAI_API_KEYZHIPU_API_KEYGLM_API_KEYBIGMODEL_API_KEY
Ollama
ollama pull qwen2.5:7b-instruct
export CLAUDE_BABEL_PROVIDER=ollama
export CLAUDE_BABEL_OLLAMA_MODEL=qwen2.5:7b-instructLibreTranslate
export CLAUDE_BABEL_PROVIDER=libretranslate
export CLAUDE_BABEL_LIBRETRANSLATE_URL=http://127.0.0.1:5000OpenAI-compatible
export CLAUDE_BABEL_PROVIDER=openai-compatible
export CLAUDE_BABEL_OPENAI_BASE_URL=https://api.openai.com/v1
export CLAUDE_BABEL_OPENAI_API_KEY="your-key"
export CLAUDE_BABEL_OPENAI_MODEL=gpt-4o-miniEcho test provider
export CLAUDE_BABEL_PROVIDER=echoUseful for validating hooks without network calls.
CLI
claude-babel help
claude-babel detect "请帮我写测试"
claude-babel translate "请帮我写测试"
echo '{"session_id":"demo","prompt":"请帮我写测试"}' | claude-babel hook user-prompt-submitDevelopment
npm test
npm run lint
npm pack --dry-runNo runtime npm dependencies are required.
Design principles
- Lightweight intervention only.
- Do not block or interrupt Claude.
- Do not force a second answer.
- Preserve code, paths, commands, identifiers, JSON keys, and logs.
- Make the default path easy with GLM, while keeping providers replaceable.
License
GPL-3.0-or-later. See LICENSE.
