Skip to content

Providers ​

lingosync doesn't ship its own translation engine — it calls out to a provider you choose, using your own API key. There's no lock-in and no lingosync-hosted service in the loop.

Built in ​

manual ​

json
{ "provider": { "name": "manual" } }

No network calls, no API key. Returns [locale] original text for every key. Useful for trying out the full sync flow, and for automated tests that shouldn't depend on a real API. This is the provider used in lingosync's own test suite.

deepl ​

The only real translation provider lingosync ships today — it's what the whole project has been built and tested against. Other providers are welcome as contributions (see below), but as of now, DeepL is not optional.

json
{
  "provider": {
    "name": "deepl",
    "apiKeyEnv": "DEEPL_API_KEY"
  }
}

Calls the DeepL API (api-free.deepl.com for free-tier keys, which end in :fx). Batches requests by source/target locale pair to minimize network calls. DeepL is one of the few providers that treats regional variants like EN-US and EN-GB as genuinely distinct translation targets — see Configuration for how to map your locale codes to what DeepL expects via providerLocale.

Get a free API key at deepl.com — the DeepL API Free plan translates up to 500,000 characters per month at no cost, which is enough to try lingosync out or run a small project. That figure is per DeepL's own docs as of this writing; check DeepL's pricing page for current limits before you rely on it — it changes.

Writing your own ​

A provider is a small object matching this interface (src/providers/types.ts):

ts
interface TranslationProvider {
  name: string;
  translateBatch(requests: TranslationRequest[]): Promise<string[]>;
}

interface TranslationRequest {
  text: string;          // already placeholder-shielded
  sourceLocale: string;
  targetLocale: string;  // the resolved providerLocale, not the raw `code`
}

translateBatch receives every key that needs translating for one locale in a single call, and must return translations in the same order. Batching like this — rather than one request per key — is what keeps sync fast and within most providers' rate limits.

To add one:

  1. Create src/providers/your-provider.ts implementing the interface above.
  2. Register it in src/providers/registry.ts's switch statement.
  3. Reference it by name in your package.json config: { "provider": { "name": "your-provider", "apiKeyEnv": "..." } }.

src/providers/deepl.ts is the best reference implementation to copy from — it shows the batching-by-locale-pair pattern and how to surface a clear error when the API key is missing.

A pull request adding a well-tested adapter for another provider (Google Translate, Azure Translator, OpenAI, etc.) is very welcome.

Released under the MIT License.