omnisense / omnilang
Omnilang: translate a text or a page, whatever the engine, under any PHP host - plain text or HTML with its tags kept, formality where the engine has it, the source language detected, glossaries, whole documents. Four contracts (translate, detect, glossary, documents), a registry that falls back fro
Requires
- php: >=8.2
- ext-mbstring: *
- omnisense/contracts: ^1.0@dev
- symfony/http-client-contracts: ^3.0
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.0
- symfony/http-client: ^6.4|^7.0|^8.0
Suggests
- omnilang/amazon: Amazon Translate: translate (formality), terminologies, documents; IAM credentials (Signature Version 4)
- omnilang/azure: Azure AI Translator: translate, detect, documents; a key and its region
- omnilang/deepl: DeepL API: translate (text, HTML, formality), glossaries, documents; a key
- omnilang/google: Google Cloud Translation - Advanced (v3): translate, detect, glossaries, documents; an OAuth access token
- omnilang/libretranslate: LibreTranslate, self-hosted (AGPL-3.0): translate, detect, files; no key by default
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-10 08:18:46 UTC
README
Translate a text or a page, whatever the engine, under any PHP host: one family for machine translation, in four contracts, with a fallback from one engine to the next.
| Contract | What it answers |
|---|---|
TranslatorInterface |
texts translated, plain or HTML with its tags kept, a register (formal, informal) where the engine has one, a glossary where it keeps them; the source language detected when none is given; the languages it translates |
DetectorInterface |
the language a text is in, how sure the engine is, the other languages it thought of |
GlossaryInterface |
the engine's glossaries made, listed, read, deleted - and applied through a translation |
DocumentsInterface |
whole documents translated, their layout kept: at once, or as a job followed until done |
| Provider | Contracts | Credentials |
|---|---|---|
| omnilang/deepl | translate (HTML, formality), glossary (v3), documents (async) | a key |
| omnilang/google | translate (HTML), detect, glossary (no create), documents (PDF, Office) - Cloud Translation v3 | an OAuth access token |
| omnilang/azure | translate (HTML), detect, documents (sync, custom domain) - Translator v3.0 | a key and its region |
| omnilang/amazon | translate (formality), glossary (terminologies), documents (HTML, text, DOCX) | IAM credentials (Signature Version 4, no SDK) |
| omnilang/libretranslate | translate (HTML), detect, documents - a self-hosted server | none by default |
use Omnilang\Model\{Formality, TranslationQuery}; use Omnilang\Registry; $lang = new Registry([new DeeplFactory($http), new LibretranslateFactory($http)], [ 'deepl' => ['factory' => 'deepl', 'options' => ['key' => 'env:DEEPL_API_KEY']], 'local' => ['factory' => 'libretranslate', 'options' => ['base_uri' => 'http://libretranslate:5000']], ], fallback: ['deepl', 'local']); $lang->translateText('Chambre double avec vue', 'en')->text; // DeepL, else the local server $lang->translate(TranslationQuery::html('<p>Réservez <b>maintenant</b></p>', 'ja', formality: Formality::Formal)); $lang->detect('Guten Morgen')[0]->language->code; // "de", by the first engine that detects
Keys go by reference: 'env:DEEPL_API_KEY' is read from the environment when the engine is built
(or the application passes the value it reads from its vault, %env(DEEPL_API_KEY)% in Symfony);
a configuration file never holds a key, and no error, copy or trace ever quotes one.
Fallback
translate(), detect() and translateDocument() go down an order: the one given to the call,
else the registry's fallback, else every engine keeping the contract in the configuration's
order. An engine that cannot take the query (HTML, a glossary it does not keep, a document type it
does not read) is passed over; one that fails - out of reach, over a limit, an error answered (a
spent quota: DeepL's 456, Google's 403) - hands over to the next. When none is left,
FallbackFailedException holds every failure by name. A wrong query or configuration is thrown at
once, never passed on. Each Translation says which engine made it ($provider).
translator(), detector(), glossary() and documents() give one engine, behind its guard;
get() the engine itself.
Usage policies
Each provider declares its usage policy as data (its policy.json, named in its composer.json's
extra.omnisense.policy): rate limits, rights (commercial use, caching, storage, attribution),
requirements, and where and when it was read - with what a call count cannot say (quotas in
characters, data retention) in its notes. Every call through the registry is held to it: checked
before, counted after, refused with UsageLimitReachedException once a limit is reached or while
the engine asks to wait (a 429 and its Retry-After). A query longer than one request of the engine
takes is cut into as many requests, each counted. A site may tighten a policy, never loosen it:
'deepl' => [ 'factory' => 'deepl', 'options' => ['key' => 'env:DEEPL_API_KEY'], 'policy' => ['rateLimits' => [['max' => 2000, 'window' => 'day', 'operations' => ['translate']]]], 'usage' => ['commercial' => true], ],
$lang->policy('deepl'), $lang->policies(): what a site's "about our translations" page shows
(DeepL and Google require their attribution beside every translation). See
docs/policies.md.
The boundaries: a site's own catalogues (messages.fr.yaml, Crowdin, Lokalise) are Symfony's translation providers', not this family's; a translation by a language model goes through Symfony AI, not omnilang.
omnisense/omnilang requires omnisense/contracts (the kernel every omnisense family builds on:
provider, factory, registry, JSON client, usage policies, testing kit) and
symfony/http-client-contracts, nothing else: no framework, no HTTP client of its own (each
provider requires symfony/http-client and takes the application's).
composer require omnisense/omnilang omnilang/deepl
Documentation
docs/index.md: installation (plain PHP first), Symfony, models, providers, policies, testing, the harness, errors, writing a provider.
Licence
MIT