A powerful command-line tool for translating text between languages using various Large Language Model (LLM) providers.
- Multiple LLM Providers: Support for OpenAI, Anthropic, Google, Ollama, OpenRouter, and CLI-based providers (Claude Code, Codex, Qwen Code)
- Flexible Input/Output: File-based and pipe modes
- Smart Text Processing: Automatic chunking for long texts
- Format Preservation: Maintains Markdown and HTML formatting
- Glossary Support: Ensure consistent translation of technical terms
- Strong Validation Mode: Verify translations don't contain source language text
- Proxy Support: HTTP, HTTPS, and SOCKS5 proxy configuration
- Retry Logic: Automatic retries with exponential backoff
- Configurable: YAML configuration files with environment variable support
- Text Analysis: Sentiment analysis, emotion detection, topic classification, tag extraction, named entity recognition (NER), event extraction, usefulness detection, temporal focus analysis, and advertising detection
go install github.com/foxzi/llm-translate/cmd/llm-translate@latestgit clone https://github.com/foxzi/llm-translate.git
cd llm-translate
make build# Translate text from English to Russian
echo "Hello world" | llm-translate -t ru
# Translate a file
llm-translate -i document.txt -o document_ru.txt -f en -t ru# Use Anthropic Claude
llm-translate -p anthropic -m claude-3-5-sonnet-20241022 -i text.txt -t ru
# Use local Ollama
llm-translate -p ollama -m llama3.2 -i text.txt -t es
# Use Google Gemini
llm-translate -p google -m gemini-2.0-flash -i text.txt -t fr
# Use local Claude Code CLI (no API key needed)
llm-translate -p claude-cli -i text.txt -t ru
# Use local Codex CLI (no API key needed)
llm-translate -p codex-cli -i text.txt -t es
# Use local Qwen Code CLI (no API key needed)
llm-translate -p qwen-cli -i text.txt -t ruCreate a configuration file at ~/.config/llm-translate/config.yaml:
default_provider: openai
default_target_language: ru
settings:
# LLM generation settings
temperature: 0.3 # Creativity level (0.0-1.0, lower = more deterministic)
max_tokens: 4096 # Maximum tokens in LLM response
timeout: 60 # Request timeout in seconds
chunk_size: 3000 # Characters per chunk for long texts
preserve_format: false # Preserve markdown/HTML formatting
retry_count: 3 # Number of retries on failure
retry_delay: 1 # Delay between retries in seconds
# Text analysis settings (results added to frontmatter)
sentiment: false # Analyze sentiment (positive/negative/neutral with score)
tags_count: 5 # Extract N keywords/tags (0 = disabled)
classify: false # Classify by topics, scope, news_type
emotions: false # Detect emotions (fear, anger, hope, uncertainty, optimism, panic)
factuality: false # Check factuality (confirmed, rumors, forecasts, unsourced)
impact: false # Who is affected (individuals, business, government, investors, consumers)
sensationalism: false # Sensationalism level (neutral, emotional, clickbait, manipulative)
entities: false # Extract named entities (persons, organizations, locations, dates, amounts)
events: false # Extract key events mentioned in text
usefulness: false # Detect useless/spam content (advertising, empty announcements, etc.)
time_focus: false # Analyze temporal focus (past/present/future) and detect predictions
ad_detect: false # Detect advertising content (direct, native, sponsored, PR)
providers:
openai:
api_key: ${OPENAI_API_KEY}
base_url: https://api.openai.com/v1
model: gpt-4o-mini
anthropic:
api_key: ${ANTHROPIC_API_KEY}
base_url: https://api.anthropic.com
model: claude-3-5-sonnet-20241022
google:
api_key: ${GOOGLE_API_KEY}
base_url: https://generativelanguage.googleapis.com/v1beta
model: gemini-2.0-flash
ollama:
base_url: http://localhost:11434
model: llama3.2
openrouter:
api_key: ${OPENROUTER_API_KEY}
base_url: https://openrouter.ai/api/v1
model: anthropic/claude-3.5-sonnet
# CLI-based providers (use locally installed CLI tools)
claude-cli:
base_url: claude # path to claude binary
codex-cli:
base_url: codex # path to codex binary
qwen-cli:
base_url: qwen # path to qwen binary
# Strong validation settings
strong_validation:
enabled: false
max_retries: 3
allowed_patterns:
- '\b[A-Z]{2,}\b' # Acronyms
- '`[^`]+`' # Code blocks
allowed_terms:
- API
- HTTP
- JSON
# Proxy configuration
proxy:
url: socks5://proxy.example.com:1080
username: ${PROXY_USER}
password: ${PROXY_PASS}
no_proxy:
- localhost
- 127.0.0.1| Variable | Description |
|---|---|
LLM_TRANSLATE_CONFIG |
Path to configuration file |
LLM_TRANSLATE_PROVIDER |
Default provider |
LLM_TRANSLATE_MODEL |
Default model |
LLM_TRANSLATE_PROXY |
Proxy URL |
OPENAI_API_KEY |
OpenAI API key |
ANTHROPIC_API_KEY |
Anthropic API key |
GOOGLE_API_KEY |
Google API key |
OPENROUTER_API_KEY |
OpenRouter API key |
| Flag | Short | Description | Default |
|---|---|---|---|
--input |
-i |
Input file | stdin |
--output |
-o |
Output file | stdout |
--dir |
-d |
Input directory for recursive translation | - |
--ext |
File extensions to translate | .md,.txt | |
--suffix |
Output file suffix (e.g., _ru) | _<lang> | |
--prefix |
Output file prefix (e.g., ru_) | - | |
--from |
-f |
Source language | auto |
--to |
-t |
Target language | en |
--provider |
-p |
LLM provider | from config |
--model |
-m |
Model to use | from config |
--config |
-c |
Config file path | ~/.config/llm-translate/config.yaml |
--api-key |
-k |
API key | from config |
--temperature |
Generation temperature | 0.3 | |
--max-tokens |
Max response tokens | 4096 | |
--style |
Translation style | - | |
--glossary |
-g |
Glossary file | - |
--preserve-format |
Keep formatting | false | |
--strong |
-s |
Strong validation mode | false |
--sentiment |
Analyze sentiment of translated text | false | |
--tags |
Extract N tags from text (0 to disable) | 0 | |
--classify |
Classify text by topics, scope, and type | false | |
--emotions |
Analyze emotions (fear, anger, hope, etc.) | false | |
--factuality |
Check factuality (confirmed, rumors, forecasts, unsourced) | false | |
--impact |
Analyze who is affected (individuals, business, government, etc.) | false | |
--sensationalism |
Analyze sensationalism level (neutral, emotional, clickbait, manipulative) | false | |
--entities |
Extract named entities (persons, organizations, locations, dates, amounts) | false | |
--events |
Extract key events from text | false | |
--usefulness |
Detect useless/spam content (advertising, empty announcements) | false | |
--time-focus |
Analyze temporal focus (past/present/future) and detect predictions | false | |
--ad-detect |
Detect advertising content (direct, native, sponsored, PR) | false | |
--verbose |
Verbose output | false | |
--version |
-v |
Show version | - |
--quiet |
-q |
Quiet mode | false |
--proxy |
-x |
Proxy server | from config |
--help |
-h |
Show help | - |
Translate all files in a directory recursively:
# Translate all .md and .txt files (default extensions)
llm-translate -d ./docs -t ru
# Output: file.md -> file_ru.md
# Custom suffix
llm-translate -d ./docs -t ru --suffix _russian
# Output: file.md -> file_russian.md
# Use prefix instead
llm-translate -d ./docs -t ru --prefix ru_
# Output: file.md -> ru_file.md
# Specific extensions
llm-translate -d ./content -t ru --ext ".md,.html"
# Already translated files are automatically skipped# Formal style for official documents
llm-translate -i letter.txt -o letter_de.txt -t de --style formal
# Technical style preserving terminology
llm-translate -i docs.md -o docs_ru.md -t ru --style technicalCreate a glossary file terms.yaml:
terms:
- source: "machine learning"
target: "машинное обучение"
- source: "API"
target: "API"
note: "не переводить"Use it in translation:
llm-translate -i tech.txt -o tech_ru.txt -t ru --glossary terms.yamlEnsures the translation doesn't contain untranslated source language text:
llm-translate -i document.txt -o document_ru.txt -f en -t ru --strongAnalyze translated text for sentiment, emotions, classification, impact, and extract key tags. Results are added to frontmatter in Markdown files.
# Analyze sentiment of translated text
llm-translate -i article.txt -o article_ru.txt -t ru --sentiment
# Extract 5 tags from translated text
llm-translate -i article.txt -o article_ru.txt -t ru --tags 5
# Classify by topics, scope, and news type
llm-translate -i article.txt -o article_ru.txt -t ru --classify
# Analyze emotions (fear, anger, hope, uncertainty, optimism, panic)
llm-translate -i article.txt -o article_ru.txt -t ru --emotions
# Check factuality (confirmed data, rumors, forecasts, unsourced claims)
llm-translate -i article.txt -o article_ru.txt -t ru --factuality
# Analyze who is affected by the news
llm-translate -i article.txt -o article_ru.txt -t ru --impact
# Analyze sensationalism level
llm-translate -i article.txt -o article_ru.txt -t ru --sensationalism
# Extract named entities (persons, organizations, locations, dates, amounts)
llm-translate -i article.txt -o article_ru.txt -t ru --entities
# Extract key events from text
llm-translate -i article.txt -o article_ru.txt -t ru --events
# Detect useless/spam content
llm-translate -i article.txt -o article_ru.txt -t ru --usefulness
# Analyze temporal focus and detect predictions
llm-translate -i article.txt -o article_ru.txt -t ru --time-focus
# Detect advertising content
llm-translate -i article.txt -o article_ru.txt -t ru --ad-detect
# Full analysis - combine all
llm-translate -i article.txt -o article_ru.txt -t ru \
--sentiment --tags 5 --classify --emotions --factuality --impact \
--sensationalism --entities --events --usefulness --time-focus --ad-detectOutput frontmatter example:
---
title: Article
sentiment: positive
sentiment_score: 0.75
tags:
- technology
- innovation
- ai
topics:
- technology
- economics
scope:
- international
news_type:
- corporate
emotions:
fear: 0.2
hope: 0.8
optimism: 0.7
factuality: confirmed
factuality_confidence: 0.85
factuality_evidence:
- official_source
- statistics
- quotes
affected:
- business
- investors
- consumers
sensationalism: neutral
sensationalism_confidence: 0.9
sensationalism_markers:
- factual_language
persons:
- Tim Cook
- Sundar Pichai
organizations:
- Apple
- Google
- European Commission
locations:
- California
- Brussels
dates:
- January 2024
- Q2 2025
amounts:
- $500 million
- 15%
events:
- Apple announced new iPhone regulations compliance
- European Commission approved merger deal
useful_content: true
useful_confidence: 0.85
useful_reasons:
- factual_information
- contains_analysis
time_focus: present
time_focus_confidence: 0.8
is_prediction: false
time_indicators:
- announced
- approved
- this week
ad_type: none
ad_confidence: 0.9
---Classification categories:
- Topics: politics, economics, technology, medicine, incidents
- Scope: regional, international
- News type: corporate, regulatory, macro
Emotions detected:
- fear, anger, hope, uncertainty, optimism, panic (with intensity 0.0-1.0)
Factuality types:
- confirmed: verified facts with clear sources or official data
- rumors: unverified information, hearsay, "sources say"
- forecasts: predictions, projections, future expectations
- unsourced: claims without attribution or evidence
Impact - who is affected:
- individuals, business, government, investors, consumers
Sensationalism levels:
- neutral: factual, balanced reporting without emotional language
- emotional: emotionally charged language, dramatic descriptions
- clickbait: exaggerated headlines, curiosity gaps, misleading hooks
- manipulative: deliberate distortion, fear-mongering, propaganda techniques
Named entities (NER):
- persons: person names mentioned in text
- organizations: companies, institutions, agencies
- locations: places, cities, countries, regions
- dates: dates, time references, periods
- amounts: monetary values, percentages, numbers
Events extraction:
- Key events mentioned in the text as structured list
Usefulness detection:
- useful: contains factual information, analysis, new insights, verifiable data
- useless: advertising, sponsored content, empty announcements, clickbait with no substance, auto-generated content
Time focus analysis:
- past: describes events that already happened, historical analysis, retrospective
- present: describes current situation, ongoing events, breaking news
- future: describes predictions, forecasts, expectations, planned events
- mixed: contains significant elements of multiple time frames
- is_prediction: true only when text contains explicit predictions, forecasts, or speculations about future outcomes (not for scheduled events or confirmed plans)
Advertising detection:
- none: genuine editorial/news content with no advertising intent
- direct: explicit advertising, product promotion, call-to-action, commercial offer
- native: advertising disguised as editorial content, paid placement that mimics news
- sponsored: clearly marked sponsored content, paid partnership, branded content
- pr: press release, corporate announcement promoting company/product without editorial value
Configuration in YAML:
settings:
sentiment: true
tags_count: 5
classify: true
emotions: true
factuality: true
impact: true
sensationalism: true
entities: true
events: true
usefulness: true
time_focus: true
ad_detect: true# Using SOCKS5 proxy
llm-translate -i file.txt -o output.txt -t ru \
--proxy socks5://proxy.example.com:1080
# HTTP proxy with authentication
llm-translate -i file.txt -o output.txt -t ru \
--proxy http://user:pass@proxy.example.com:8080# Translate README preserving Markdown formatting
llm-translate -i README.md -o README_ru.md -t ru --preserve-format# Translate all files in a directory
llm-translate -d ./docs -t ru
# Translate only markdown files with custom suffix
llm-translate -d ./content -t ru --ext ".md" --suffix _translated# Extract and translate
curl https://example.com/api/docs | \
jq -r '.content' | \
llm-translate -t ru > translated.txt# Start Ollama server first
ollama serve
# Translate using local model
llm-translate -p ollama -m llama3.2 -i text.txt -t esUse locally installed and authorized CLI tools (Claude Code, Codex, Qwen Code) without managing API keys:
# Using Claude Code CLI (must be installed and authorized)
llm-translate -p claude-cli -i article.txt -t ru
# Using Codex CLI (must be installed and authorized)
llm-translate -p codex-cli -i article.txt -t ru --sentiment --tags 5
# Using Qwen Code CLI (must be installed and authorized)
llm-translate -p qwen-cli -i article.txt -t ru --sentiment --tags 5
# Specify custom path to CLI binary
llm-translate -p claude-cli -u /usr/local/bin/claude -i text.txt -t ruRequirements:
- Claude Code CLI: Install from https://claude.ai/code
- Codex CLI: Install from https://github.com/openai/codex
- Qwen Code CLI: Install from https://github.com/nicepkg/qwen-code
Advantages:
- No API keys in config files
- Uses CLI's own authorization
- Leverages existing billing/limits
Use standard ISO 639-1 codes:
en- Englishru- Russiande- Germanfr- Frenches- Spanishzh- Chineseja- Japaneseko- Koreanauto- Auto-detect source language
| Code | Description |
|---|---|
| 0 | Success |
| 1 | Invalid arguments |
| 2 | Configuration error |
| 3 | Input file error |
| 4 | Output file error |
| 5 | API error |
| 6 | Token limit exceeded |
| 7 | Timeout |
| 8 | Strong validation failed |
- Go 1.21 or later
- Make (optional)
# Using make
make build
# Or directly with go
go build -o bin/llm-translate cmd/llm-translate/main.go
# Build for all platforms
make build-allmake test
# With coverage
make test-coverage- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE file for details
For issues and feature requests, please use the GitHub issue tracker.