habr / bblslug
CLI translation tool for HTML and plain text using LLM-based APIs.
Installs: 1 030
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/habr/bblslug
Requires
- php: >=8.0
- ext-curl: *
- ext-mbstring: *
- symfony/yaml: ^7.3
Requires (Dev)
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.13
This package is auto-updated.
Last update: 2025-12-24 14:51:56 UTC
README
Bblslug is a versatile translation tool that can be used as both a CLI utility and a PHP library.
It leverages LLM-based APIs to translate plain text, HTML and JSON while preserving structure, code blocks, and URLs via placeholder filters.
APIs supported:
- Anthropic (Claude):
anthropic:claude-haiku-3.5- Claude Haiku 3.5 (latest)anthropic:claude-opus-4- Claude Opus 4 (20250514)anthropic:claude-sonnet-4- Claude Sonnet 4 (20250514)
- DeepL:
deepl:free- DeepL free tierdeepl:pro- DeepL pro tier
- Google (Gemini):
google:gemini-2.5-flash- Gemini 2.5 Flashgoogle:gemini-2.5-flash-lite- Gemini 2.5 Flash Litegoogle:gemini-2.5-pro- Gemini 2.5 Progoogle:gemini-2.0-flash- Gemini 2.0 Flash
- OpenAI (GPT):
openai:gpt-5- OpenAI GPT-5openai:gpt-5-mini- OpenAI GPT-5 Miniopenai:gpt-5-nano- OpenAI GPT-5 Nanoopenai:gpt-4o- OpenAI GPT-4oopenai:gpt-4o-mini- OpenAI GPT-4o Miniopenai:gpt-4- OpenAI GPT-4openai:gpt-4-turbo- OpenAI GPT-4 Turbo
- Yandex:
yandex:gpt-lite- YandexGPT Liteyandex:gpt-pro- YandexGPT Proyandex:gpt-32k- YandexGPT Pro 32K
- X.ai:
xai:grok-4- Grok 4xai:grok-3- Grok 3xai:grok-3-mini- Grok 3 Mini
Features
- Supports HTML, JSON and plain text (
--format=text|html|json) - Placeholder-based protection with filters:
html_pre,html_code,url, etc. - Model selection via
--model=vendor:name - Fully configurable backend registry (via
resources/models.yaml) - Dry-run mode to preview placeholders without making API calls
- Variables (
--variables) to send or override model-specific options - Verbose mode (
--verbose) to print request previews - Can be invoked as a CLI tool or embedded in PHP code
- Validation of container syntax for HTML or JSON; disable with
--no-validate
Installation
composer require habr/bblslug chmod +x vendor/bin/bblslug
CLI Usage
Prepare
-
Always specify a model with
--model=vendor:nameoption. -
Export your API key(s) before running:
export ANTHROPIC_API_KEY=... export DEEPL_FREE_API_KEY=... export DEEPL_PRO_API_KEY=... export GOOGLE_API_KEY=... export OPENAI_API_KEY=... export YANDEX_API_KEY=... && export YANDEX_FOLDER_ID=... export XAI_API_KEY=...
NB! Some vendors require additional parameters, e.g. YANDEX_FOLDER_ID.
- Input / output:
- If
--sourceis omitted, Bblslug reads from STDIN. - If
--translatedis omitted, Bblslug writes to STDOUT.
- Optional proxy:
To route requests through a proxy (e.g. HTTP or SOCKS5), use the --proxy option or set the BBLSLUG_PROXY environment variable:
# using CLI flag vendor/bin/bblslug --proxy="http://localhost:8888" ... # or set it globally export BBLSLUG_PROXY="socks5h://127.0.0.1:9050"
This works for all HTTP requests and supports authentication (http://user:pass@host:port).
Show available models
vendor/bin/bblslug --list-models
Show available prompt templates
vendor/bin/bblslug --list-prompts
Translate an HTML file and write to another file
vendor/bin/bblslug \ --model=vendor:name \ --format=html \ --source=input.html \ --translated=output.html
Translate an JSON file and write to another file
vendor/bin/bblslug \ --model=vendor:name \ --format=json \ --source=input.json \ --translated=output.json
Translate an HTML file and write to another file with filters
vendor/bin/bblslug \ --model=vendor:name \ --format=html \ --source=input.html \ --translated=output.html \ --filters=url,html_code,html_pre
Add translation context (prompt), source and target language
vendor/bin/bblslug \
--model=vendor:name \
--format=html \
--source=input.html \
--translated=output.html \
--target-lang=EN \
--source-lang=DE \
--context="Translate as a professional technical translator"
Pass model-specific variables
vendor/bin/bblslug \ --model=vendor:name \ --format=text \ --variables=foo=bar,foo2=bar2 \ --source=in.txt \ --translated=out.txt
Choose a different prompt template
vendor/bin/bblslug \ --model=vendor:name \ --format=html \ --source=input.html \ --translated=out.html \ --prompt-key=smart-legal
Dry-run placeholders only
vendor/bin/bblslug \ --model=vendor:name \ --format=text \ --filters=url \ --source=input.txt \ --dry-run
Verbose mode (prints request preview to stderr)
vendor/bin/bblslug \ --model=vendor:name \ --format=html \ --verbose \ --source=input.html \ --translated=out.html
Pipe STDIN → file
cat input.txt | vendor/bin/bblslug \
--model=vendor:name \
--format=text \
--translated=out.txt
Pipe STDIN → STDOUT
echo "Hello world" | vendor/bin/bblslug \ --model=vendor:name \ --format=text > translated.out
Disable validation
For HTML and JSON formats, Bblslug performs basic syntax validation before and after translation. To skip this step, add:
vendor/bin/bblslug \ --model=vendor:name \ --format=html \ --no-validate \ --source=input.html \ --translated=out.html
Statistics
-
Usage metrics
After each translation (when not in dry-run), Bblslug prints to stderr a summary of consumed usage metrics, for example:
Usage metrics: Tokens: Total: 1074 ----------------- Prompt: 631 Completion: 443
PHP Library Usage
You can embed Bblslug in your PHP project.
Quickstart
- Install:
composer require habr/bblslug
- Require & Import:
require 'vendor/autoload.php'; use Bblslug\Bblslug;
Translate
Text translation function example:
$text = file_get_contents('input.html'); $result = Bblslug::translate( apiKey: getenv('MODEL_API_KEY'), // API key for the chosen model format: 'html', // 'text', 'html' of 'json' modelKey: 'vendor:model', // Model identifier (e.g. deepl:free, openai:gpt-4o, etc.) text: $text, // Source text to be translated // optional: // Additional context/prompt pass to model context: 'Translate as a professional technical translator', filters: ['url','html_code'], // List of placeholder filters promptKey: 'translator', // which prompt template to use proxy: getenv('BBLSLUG_PROXY'), // Optional proxy URI (http://..., socks5h://...) sourceLang: 'DE', // Source language code (optional; autodetect if null) targetLang: 'EN', // Target language code (optional; default from driver settings) validate: false, // perform or skip syntax validation for container formats variables: ['foo'=>'bar'], // model-specific overrides verbose: true, // If true, returns debug request/response ); echo $result['result'];
Result structure:
[ 'original' => string, // Original input 'prepared' => string, // After placeholder filters 'result' => string, // Translated result 'httpStatus' => int, // HTTP status 'debugRequest' => string, // Request debug 'debugResponse' => string, // Response debug 'rawResponseBody' => string, // Response body 'consumed' => [ // Normalized usage metrics 'tokens' => [ 'total' => int, // Total tokens consumed 'breakdown' => [ // Per-type breakdown 'prompt' => int, // Name depeds of model 'completion' => int, // Name depeds of model ], ], // additional categories if supported by the model... 'lengths' => [ // Text length statistics 'original' => int, // - original text 'prepared' => int, // - after placeholder filters 'translated' => int, // - returned translated text ], 'filterStats' => [ // Placeholder stats ['filter'=>'url','count'=>3], … ], ]
List available models
$modelsByVendor = Bblslug::listModels(); foreach ($modelsByVendor as $vendor => $models) { echo "Vendor: {$vendor}\n"; foreach ($models as $key => $config) { printf(" - %s: %s\n", $key, $config['notes'] ?? '(no notes)'); } }
Returns an array like:
[ 'deepl' => ['deepl:free' => […], 'deepl:pro' => […]], 'openai' => ['openai:gpt-4' => […], …], … ]
List available prompts
$prompts = Bblslug::listPrompts(); foreach ($prompts as $key => $info) { $formats = implode(', ', $info['formats']); echo "{$key} ({$formats})"; if (! empty($info['notes'])) { echo " – {$info['notes']}"; } echo "\n"; }
Returns an array like:
[ 'translator' => [ 'formats' => ['text', 'html', 'json'], 'notes' => 'professional translator template', ], 'legal' => [ 'formats' => ['text'], 'notes' => 'legal-style translator template', ], // … ]
Error handling
try { $res = Bblslug::translate(...); } catch (\InvalidArgumentException $e) { // invalid model, missing API key, etc. } catch (\RuntimeException $e) { // HTTP error, parse failure, driver-specific error }
Samples
You can find sample input files under the samples/ directory.
License
This project is licensed under the MIT License – see the LICENSE file for details.