Supported languages

The language table

Language Code Counts as dense script
English en No
Spanish es No
French fr No
French (Canada) fr-CA No
German de No
Italian it No
Portuguese (Brazil) pt-BR No
Portuguese (Portugal) pt-PT No
Dutch nl No
Chinese (Simplified) zh-Hans Yes — billed at 3.5×
Chinese (Traditional) zh-Hant Yes — billed at 3.5×
Japanese ja Yes — billed at 3.5×
Korean ko Yes — billed at 3.5×
Arabic ar No
Russian ru No
Hindi hi Yes — billed at 3.5×
Turkish tr No
Vietnamese vi No
Thai th Yes — billed at 3.5×
Indonesian id No
Polish pl No
Ukrainian uk No
Czech cs No
Romanian ro No
Hungarian hu No
Greek el No
Swedish sv No
Danish da No
Norwegian (Bokmål) nb No
Finnish fi No
Malay ms No
Persian fa No
Urdu ur No
Marathi mr Yes — billed at 3.5×
Nepali ne Yes — billed at 3.5×

Chinese and Portuguese are split into their written variants rather than offered as one code, because the two are not interchangeable in a document anyone ships: zh-Hans and zh-Hant are different scripts, and pt-BR and pt-PT differ in vocabulary and register.

French is offered twice: fr is French as written in France, and fr-CA is Canadian French. Québec French differs in vocabulary, in typography and in how numbers and currency are written, so a text meant for Canadian readers should be requested as fr-CA.

How codes are matched

Matching is case-insensitive on the exact code. Nothing else is accepted:

  • EN and en both resolve to en.
  • zh-hans resolves to zh-Hans.
  • en-US and fr-FR are rejected — a regional code that is not in the table is not folded to its base language.
  • Bare zh and bare pt are rejected — the variant is the thing being chosen, so there is no default to fall back on.
Note: this is deliberate. Accepting en-US would mean quietly deciding that a regional request is the same as the base language; refusing it means the offered set is unambiguous and you find out at request time, not in the delivered text.

Terminology and translation-memory uploads are the one place codes are read more loosely, because the files come from other tools: each code is read as the language in the table it stands for. A regional tag such as en-US or en-GB is accepted there and applies to en, and a Chinese tag by region counts by script (zh-TW as zh-Hant, zh-CN as zh-Hans). The variants stay apart there too: a pt-PT glossary or memory never applies to a pt-BR request, nor zh-Hans to zh-Hant, nor fr to fr-CA or the other way round — while fr-FR and fr-BE are read as fr. So bare zh and pt are refused, as is a code whose language is not in the table. A glossary CSV’s language columns may also name the language instead of coding it (English, Chinese (Simplified)).

Source and target

There is no restricted direction list. Every language in the table can be a source or a target, and each side of a pair is validated on its own.

  • target_lang is required on every translation request.
  • source_lang is optional where an endpoint accepts it, and defaults to en. Send it explicitly whenever the source is not English.

Translation memory and terminology are held per language pair. A glossary or memory you build for English → French applies to that pair only; the reverse direction and every other pair start empty. Their capacity allowances are also counted per pair — see Limits & quotas.

What a rejected code returns

An unsupported code fails validation before any translation work begins, so nothing is billed and nothing is stored. The response is 422 with a string detail beginning unsupported language(s):, naming the codes exactly as you sent them and then listing the supported set. (In the batch shape the same rejection is reported inside the batch’s validation message, as unsupported language followed by the code.)

HTTP/1.1 422 Unprocessable Entity
content-type: application/json

{"detail":"unsupported language(s): 'en-CA'. Supported: en, es, fr, fr-CA, de, it, pt-BR, pt-PT, nl, zh-Hans, zh-Hant, ja, ko, ar, ru, hi, tr, vi, th, id, pl, uk, cs, ro, hu, el, sv, da, nb, fi, ms, fa, ur, mr, ne"}

Branch on the type of detail, not on the status code: framework parameter validation also returns 422, but with an array detail. Both shapes are described on Conventions & errors.

Dense-script billing weight

Chinese, Japanese, Korean, Thai, Hindi, Marathi and Nepali pack far more content into a character than Latin text does. Billing is denominated in source characters, so a pair involving one of those scripts counts 3.5 characters of allowance per source character.

  • The weight applies when either side of the pair is a dense script — into one (en → ja) or out of one (ja → en).
  • It is applied once, never squared, when both sides are dense.
  • Arabic, Russian, Turkish and Vietnamese are not weighted. They are alphabetic and sit close to Latin, and weighting them would overcharge.

The weighted count is what the monthly allowance check uses, so a request that would pass the allowance unweighted can still be refused — see Do Chinese, Japanese, Thai and Hindi count the same? and Dense-script character weighting in the API reference.


What's next

  • Text translation API — where source_lang and target_lang are sent, and what comes back.
  • Pricing & billing FAQ — how source characters and the dense-script weight turn into a monthly allowance.
  • Getting started — run a first translation and watch the memory answer the second one.