A command-line tool for translating i18n (internationalization) files to multiple languages using the Sylliba translation service.
- String extraction: Scan TypeScript/JavaScript source files and generate i18n files automatically
- Multi-format support: JSON, YAML, PO/POT, Properties, JavaScript/TypeScript, Python, Rust
- Batch translation: Translate to multiple languages in one command
- Placeholder preservation: Automatically protects
{variables},%sprintf-style, HTML tags, and ICU syntax - Auto language detection: Detects the source language from your strings
- Namespaced keys: Generates keys like
app.module.string_namefrom file paths - Dry-run mode: Preview what would be translated without making API calls
- JSON output: Machine-readable output for CI/CD integration
- Secure credential storage: API keys stored securely in
~/.sylliba/
# Using pip
pip install sylliba-cli
# Using pipx (recommended for CLI tools)
pipx install sylliba-cli
# Using uv
uv tool install sylliba-cli# Extract strings from your TypeScript/React project
sylliba extract src/ --app myapp --output locales/en.json
# Set your API key (get one from the Sylliba web interface)
sylliba login --api-key sk_live_your_key_here
# Translate to multiple languages
sylliba translate locales/en.json --to "French,Spanish,German,Japanese"
# Preview a file's contents
sylliba preview locales/en.json
# List supported formats
sylliba formatsExtract translatable strings from TypeScript/JavaScript source files and generate an i18n file.
sylliba extract [directory] [options]Arguments:
[directory]: Directory to scan (default: current directory)
Options:
--output, -o: Output file path (default:<app>.<lang>.json)--app, -a: Application name for key namespace (default:app)--format, -f: Output format:json,yaml,nested-json(default:nested-json)--exclude, -e: Comma-separated patterns to exclude--dry-run, -n: Show what would be extracted without writing--json, -j: Output extraction summary as JSON
Supported patterns:
| Framework | Patterns |
|---|---|
| React i18next | t("string"), <Trans>text</Trans> |
| Vue i18n | $t("string"), {{ $t("string") }} |
| react-intl | formatMessage({ defaultMessage: "string" }) |
| Angular | $localize\string`` |
| Generic | __("string"), i18n.t("string") |
Key generation:
Keys are namespaced based on file path: app.module.string_slug
src/components/Button.tsxwitht("Submit")→app.button.submit- Long strings are truncated with a hash for uniqueness
Examples:
# Extract from React/Next.js project
sylliba extract src/ --app myapp --output locales/en.json
# Extract from Vue project
sylliba extract . --app frontend --format nested-json
# Preview extraction without writing
sylliba extract src/ --dry-run
# Exclude test files
sylliba extract . --exclude "test,spec,__tests__,mock"
# Full workflow: extract, then translate
sylliba extract src/ --output locales/en.json
sylliba translate locales/en.json --to "French,Spanish,German"Translate an i18n file to one or more target languages.
sylliba translate <file> --to <languages> [options]Arguments:
<file>: Path to the i18n file to translate
Options:
--to, -t: Target language(s), comma-separated (required)--source, -s: Source language (default: English)--output, -o: Output directory (default: same as input file)--dry-run, -n: Show what would be done without making API calls--json, -j: Output results as JSON--concurrency, -c: Maximum concurrent translation requests (default: 5)--no-placeholders: Disable placeholder preservation--service-url: Override the translation service URL
Examples:
# Basic translation
sylliba translate locales/en.json --to French
# Multiple languages with custom output directory
sylliba translate src/i18n/en.yaml --to "French,Spanish,German" -o ./translations
# Dry run to see what would happen
sylliba translate en.json --to "French,Spanish" --dry-run
# JSON output for scripting
sylliba translate en.json --to French --json | jq '.output_files'Preview the contents of an i18n file.
sylliba preview <file> [options]Options:
--limit, -l: Maximum number of strings to show (default: 50)--keys, -k: Show only keys without values--json, -j: Output as JSON
Examples:
# Preview with default limit
sylliba preview en.json
# Show only keys
sylliba preview en.json --keys
# Preview as JSON
sylliba preview en.json --jsonList all supported i18n file formats.
sylliba formats [options]Options:
--json, -j: Output as JSON
Store your API key for authentication.
sylliba login --api-key <key> [--service-url <url>]Options:
--api-key, -k: Your Sylliba API key (required)--service-url, -u: Custom translation service URL
Remove stored credentials.
sylliba logoutShow current authentication status.
sylliba whoamiDisplay your current usage statistics.
sylliba usageManage API keys (requires authentication).
# List your API keys
sylliba api-key list
# Create a new API key
sylliba api-key create --name "CI/CD Key"
# Delete an API key
sylliba api-key delete <key-id>| Format | Extensions | Description |
|---|---|---|
| JSON | .json |
Flat or nested JSON objects |
| YAML | .yaml, .yml |
YAML files with nested values |
| PO/POT | .po, .pot |
GNU gettext with msgctxt support |
| Properties | .properties |
Java properties files |
| JavaScript | .js, .ts, .mjs |
ES modules and CommonJS exports |
| Python | .py |
Python dictionary files |
| Rust | .rs |
phf_map! and HashMap literals |
The CLI automatically detects and preserves common placeholder patterns during translation:
| Type | Pattern | Example |
|---|---|---|
| Python format | {name}, {0} |
Hello, {name}! |
| Template double | {{variable}} |
Welcome, {{user}} |
| Printf | %s, %d, %.2f |
You have %d items |
| Dollar | $name, ${expr} |
Hello, $user |
| HTML tags | <b>, </b> |
Click <b>here</b> |
| HTML entities | , ’ |
Copyright © |
| ICU plural | {n, plural, ...} |
{count, plural, one {# item} other {# items}} |
| ICU select | {x, select, ...} |
{gender, select, male {He} female {She}} |
To disable placeholder preservation, use --no-placeholders.
TRANSLATION_SERVICE_URL: Base URL of the translation serviceSYLLIBA_API_KEY: API key for authentication (alternative tosylliba login)SYLLIBA_SOURCE_LANGUAGE: Default source language (default: English)SYLLIBA_CONCURRENCY: Default concurrency limit (default: 5)
Credentials are stored in ~/.sylliba/config.json with restricted permissions (0600).
The CLI automatically searches for a .env file in the current directory and parent directories.
name: Translate i18n
on:
push:
paths:
- 'locales/en.json'
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install Sylliba CLI
run: pip install sylliba-cli
- name: Translate
env:
SYLLIBA_API_KEY: ${{ secrets.SYLLIBA_API_KEY }}
TRANSLATION_SERVICE_URL: ${{ secrets.SYLLIBA_SERVICE_URL }}
run: |
sylliba translate locales/en.json \
--to "French,Spanish,German,Japanese" \
--output locales/
- name: Commit translations
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "chore: update translations"# Get list of output files
sylliba translate en.json --to "French,Spanish" --json | jq -r '.output_files | keys[]'
# Check if translation succeeded
if sylliba translate en.json --to French --json | jq -e '.errors | length == 0' > /dev/null; then
echo "Translation successful"
fi| Code | Description |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Usage error |
| 3 | Service error (API unavailable) |
# Clone the repository
git clone https://github.com/hydra-dynamix/sylliba-cli.git
cd sylliba-cli
# Install development dependencies
uv sync --all-extras
# Run tests
uv run pytest -v
# Run linter
uv run ruff check .
# Type checking
uv run mypy src/MIT License - see LICENSE for details.