Ask Cat › AI Tool Summary › DeepL
DeepL Glossaries for Traditional Chinese (2026): Create With zh, Translate With ZH-HANT — the Variant Code Fails
Article last updated:2026-09-03
The annoying part of machine translation is not awkward phrasing. It is that the same term comes out differently every time — a brand name gets translated instead of kept, a product name gets split, and a technical term alternates between two wordings across a single document. Review time goes into fixing the same handful of words over and over.
DeepL’s answer is the glossary: you declare that a given source term must render as a given target term. Officially, DeepL then flexes those entries for case, gender, tense, and other grammar features where the target language inflects — it is not a blind find-and-replace.
Traditional Chinese, though, has a trap that is spelled out in the documentation and almost never in tutorials: a glossary can only be created with the language code zh. Passing zh-Hant fails. Here is the whole flow.
1. First, confirm Chinese supports glossaries at all
It does. Reading DeepL’s supported-languages table directly (checked 2026-09-03), all three Chinese codes carry the glossary flag:
| Code | Language | Glossary support |
|---|---|---|
ZH | Chinese (unspecified variant) | Yes |
ZH-HANT | Chinese (traditional) | Yes |
ZH-HANS | Chinese (simplified) | Yes |
Most people read that table and immediately try to create a glossary with zh-Hant. That is where it breaks.
2. The trap: root code to create, variant code to translate
DeepL separates root language codes (zh, pt, fr) from variant codes (zh-Hant, pt-BR, fr-CA). The official guide on customizations for variants publishes this table:
| Use this | Not this |
|---|---|
zh | zh-Hant, zh-Hans |
pt | pt-BR, pt-PT |
fr | fr-CA, fr-CH |
de | de-CH |
es | es-ES, es-419 |
The documented rule: customizations such as glossaries and style rules must be created with the root code, and attempting to create one with a variant code will fail.
So where does the traditional-versus-simplified distinction happen? In the translation request. Create the glossary with zh, then pass target_lang: ZH-HANT when translating — the glossary still applies. DeepL states the same thing for English: a glossary whose target is EN applies when translating into EN-US and EN-GB alike.
In practice, if your traditional and simplified wordings differ, build two glossaries, both with zh as the target language but with different entries, and pass the matching glossary_id depending on whether you are translating into ZH-HANT or ZH-HANS. That is exactly the pattern in DeepL’s own Portuguese example, where two glossaries — one saying “nota fiscal”, one saying “fatura” — are both created with the root code PT.
3. Create your first glossary (v3 endpoints)
Understand the v3 shape first: a glossary holds one or more dictionaries, and each dictionary covers a single language pair in one direction. Want both directions? Add a second, reversed dictionary.
curl -X POST https://api.deepl.com/v3/glossaries \
--header "Authorization: DeepL-Auth-Key $API_KEY" \
--header "Content-Type: application/json" \
--data '{
"name": "AMPM Brand Glossary",
"dictionaries": [
{
"source_lang": "en",
"target_lang": "zh",
"entries": "prompt\t提示詞\nagent\t代理程式",
"entries_format": "tsv"
}
]
}'
A success returns 201 with a body like this:
{
"glossary_id": "def3a26b-3e84-45b3-84ae-0c0aaf3525f7",
"ready": true,
"name": "AMPM Brand Glossary",
"dictionaries": [
{ "source_lang": "en", "target_lang": "zh", "entry_count": 2 }
],
"creation_time": "2025-08-03T14:16:18.329Z"
}
Keep the glossary_id — you need it on every translation call.
If your terminology already lives in a CSV file, the documented approach is to pipe it through jq -Rs so the file contents land in the entries field without hand-escaping.
Note: on a free API key the host is
api-free.deepl.com; paid keys useapi.deepl.com. That split is stated in DeepL’s getting-started documentation.
4. Using it in a translation — and the second mandatory condition
curl -X POST https://api.deepl.com/v2/translate \
--header "Authorization: DeepL-Auth-Key $API_KEY" \
--header "Content-Type: application/json" \
--data '{
"text": ["Write a better prompt for the agent."],
"source_lang": "EN",
"target_lang": "ZH-HANT",
"glossary_id": "def3a26b-3e84-45b3-84ae-0c0aaf3525f7"
}'
Three things to internalise:
source_langis mandatory. The documentation is blunt: glossaries cannot yet be used with automatic source language detection. If your pipeline relies on auto-detect, this is where it fails — and it fails quietly, with a normal-looking translation and no glossary applied.- Management is v3; translation stays on v2. DeepL states that the v3 endpoints handle glossary management only. Looking for a v3 translate endpoint is a dead end.
- The language pair must match the request, and
glossary_idcannot be combined withglossary_ids(the array form, capped at five glossaries).
5. Edit, read, delete: PUT and PATCH do not mean the same thing
Editability is v3’s headline advantage — v2 glossaries are immutable, and changing one means deleting and recreating it. But the two editing endpoints behave differently enough that picking the wrong one destroys entries:
| Method | Scope | Behaviour |
|---|---|---|
PUT /v3/glossaries/{id}/dictionaries | One dictionary | Creates the dictionary for that language pair, or replaces it entirely if it exists |
PATCH /v3/glossaries/{id} | Whole glossary | Updates metadata such as the name; entries passed for a language pair are merged into the existing dictionary |
The short version: PATCH to add terms (merge), PUT to swap the whole list (replace). Note also that a single PUT or PATCH changes one dictionary — changing the same source phrase across several language pairs means one call per dictionary.
Reading and deleting:
GET /v3/glossarieslists every glossary with per-dictionary metadata (no entries)GET /v3/glossaries/{id}/entriesreturns one dictionary’s entries, selected via thesource_langandtarget_langquery parameters; currently TSV onlyDELETE /v3/glossaries/{id}deletes the whole glossaryDELETE /v3/glossaries/{id}/dictionaries?source_lang=...&target_lang=...deletes a single dictionary
One compatibility trap worth flagging: DeepL warns against mixing v2 and v3 in the same integration. Once a glossary has been edited via v3, the v2 endpoints can no longer query it correctly, and to prevent data loss, deleting such a glossary through v2 is disabled — you must use the v3 deletion endpoint.
6. Five formatting rules that silently drop entries
This is where real projects break, because a malformed entry usually does not raise an error — the rule simply never applies. From the documented limits:
- No duplicate source entries, and neither source nor target may be empty.
- No control characters (
\tor\ninside a phrase), no Unicode newlines, and no leading or trailing whitespace. Pasting from a spreadsheet is the usual culprit for trailing spaces. - In CSV, fields containing commas or double quotes must be wrapped in double quotes, and a double quote inside a quoted field is escaped by doubling it. TSV is the same, with a tab as the separator.
- CSV entries may optionally append source and target language after the phrases — and entries whose languages do not match the dictionary’s pair are ignored. Ignored, not rejected.
- Size limits: up to 10 MB of entries per dictionary, so a glossary with five dictionaries holds up to 50 MB; the glossary name and each source and target phrase are capped at 1024 UTF-8 bytes.
7. How many glossaries does an account get?
This is the item second-hand articles most often get wrong, because two unrelated numbers circulate. Both were checked on 2026-09-03:
- On the API side: the older v2 glossary endpoint spec states that 1,000 glossaries are allowed per account, while the current v3 management guide says only that the number of glossaries per account is limited by your plan, linking back to the official API plan page.
- On the DeepL Translator (web and app) side: the official plan page, read as plain text on 2026-09-03, shows the free version at 50,000 characters per month and 1 glossary; Individual at 300,000 characters per month and 1 glossary; Team at 1,000,000 characters per user per month and 5 glossaries; Business and Enterprise listed as unlimited glossaries.
These are separate allowances. A Translator plan’s glossary count says nothing about what an API key may create. If you are building on the API, the API plan is the one that governs.
8. What this article does not pin down
- Current API plan tiers (Free / Developer / Growth): character allowances, monthly price, and glossary caps. DeepL’s API pricing block is dynamically rendered, and this round’s plain-text read did not return any price figures, so no API prices appear above — all marked unverified. Our own tool page carries a second-hand, unconfirmed note (that API Free and API Pro stopped being sold from July 2026 in favour of Developer or Growth); until a first-hand view of the pricing page confirms it, treat that as a lead, not a fact.
- The exact number of glossary-capable languages. The v2 endpoint spec’s prose list and the current supported-languages table do not fully agree (the former’s list mentions Thai, the latter’s glossary flag does not cover it). This article uses only the per-language support flags and does not commit to a total.
- Whether free API keys are still open to new sign-ups. A “Free API Key” registration link (
productId=api-developer) is still present on the official API page, but we did not complete a sign-up to verify it, so we make no claim that one can still be obtained.
9. The order of operations that works
- Check your language in the supported-languages table and take its root code (Traditional Chinese:
zh). - Create the glossary with
POST /v3/glossaries, target language set to the root code, and store theglossary_id. - Only at translation time do you pass
target_lang: ZH-HANT— and always includesource_lang. - Verify with a real sentence containing the term. If nothing changed, the cause is usually a missing
source_langor a trailing space in an entry. - Afterwards,
PATCHto add terms,PUTto replace a list, and keep the whole project on v3 rather than mixing versions.
Official links
- Managing glossaries (v3 endpoints; source of the commands above): https://developers.deepl.com/docs/customize/managing-glossaries
- Customizations for language variants (source of the root-code table): https://developers.deepl.com/docs/customize/customizations-for-variants
- Glossary v2 vs v3 endpoints: https://developers.deepl.com/docs/customize/glossary-v2-vs-v3-endpoints
- Supported languages (source of the glossary support flags): https://developers.deepl.com/docs/getting-started/supported-languages
- Translate endpoint parameters (
glossary_idconditions): https://developers.deepl.com/api-reference/translate/request-translation
Related reading
What Amo and Pimi think
If you need high translation quality and want to preserve document formatting, try the free version's 50,000 characters first. But we couldn't confirm the paid plan prices firsthand — sources contradict each other — so before subscribing, be sure to check the current plans and prices on the official site yourself.
Let's take a look at these
- DeepL Comprehensive Introduction: Pricing, Features, and Actual Limitations
- DeepL Is the free quota enough?
- DeepL Alternatives
- Comprehensive Free Quota List for All Tools

