Thomas Piacentini
← Workshop

Cheat sheet

Localization and Glossary Tools

Original text · English

Run, feed and check three review-first localization projects. Pick a multilingual model and a source language.

Three projects side by side

FactorSubtitle Localization DeskUI String Localization WorkbenchGlossary Hovercard Publisher
BuildsReviewed WebVTT and an HTML deskReviewed locale JSON and a previewAnnotated HTML lesson
LanguagePython 3.10+Node 22.18 or newerNode 22.18 or newer
Input keysvtt, translations, glossary, cpslocale, messages, proposals, valuesglossary, lesson
Outputsreview.html, translation-decisions.json, reviewed.vttlocale.json, unresolved-strings.json, report.htmlreport.html, glossary.json, coverage.json
Review file--decisions decisions.jsonthird argument locale-review.jsonnone
Hard gatereviewed.vtt only when all cues approvedapprove only with no issuesbalanced HTML subset
Sources

Run the reference

CommandWhat it does
python3 cli.py samples/input.json --output demo-outputSubtitle desk on the sample
python3 cli.py <input.json> --output <dir>Subtitle desk on your input
node cli.ts sample.json outputUI workbench or glossary publisher
node cli.ts <input.json> <dir> <review.json>UI workbench with your review
node cli.ts --helpPrints the argument line
Sources

Build and grade your version

TaskCode
Make a starterpython3 scripts/project_test.py <project> --init <dir>
Grade one stagepython3 scripts/project_test.py <project> --stage 1 --path <dir> --strict
Grade all stagespython3 scripts/project_test.py <project> --all --path <dir> --strict
Save a completion report--report completion.json
Grade the referencepython3 scripts/project_test.py <project> --all --solution --strict
Sources

Subtitle desk pipeline

  1. parse_vtt reads WebVTT into cues. It keeps timestamp strings and gives cue-N to cues with no id.
  2. propose takes supplied translations. It replaces source glossary terms longest first.
  3. inspect counts visible characters and sets budget=floor(duration*cps).
  4. export_localized binds the review to a SHA-256 fingerprint of proposals and cps.
  5. You edit decisions.json, set approved per cue, then run again with --decisions.
  6. CLI writes reviewed.vtt only when every cue is approved.
Sources

Subtitle input (samples/input.json)

{
"vtt": "WEBVTT\n\nmap\n00:00.000 --> 00:03.000\nOpen the map.\n...",
"translations": {
"map": "Abre el map.",glossary turns it into "Abre el mapa."
"label": "Escribe un nombre descriptivo ..."2 s at cps 12, budget 24
},
"glossary": {"map": "mapa", "marker": "marcador"},source to target
"cps": 12optional, the default is 17
}
Sources

UI string workbench flow

messagesMessage[]Proposal[]catalogunresolvedsample.jsonmessages, proposalsclientreadCatalog()keys, placeholdersprocessproposeTranslations()issues, needsContextprocessreviewTranslations()approve, reject, pendingprocesslocale.jsonapproved stringsstoreunresolved-strings.jsonkeys with reasonsstore
Nodes and connections
NodeRoleKind
sample.jsonmessages, proposalsclient
readCatalog()keys, placeholdersprocess
proposeTranslations()issues, needsContextprocess
reviewTranslations()approve, reject, pendingprocess
locale.jsonapproved stringsstore
unresolved-strings.jsonkeys with reasonsstore
FromToConnection
sample.jsonreadCatalog()messages
readCatalog()proposeTranslations()Message[]
proposeTranslations()reviewTranslations()Proposal[]
reviewTranslations()locale.jsoncatalog
reviewTranslations()unresolved-strings.jsonunresolved
Sources

Glossary publisher rules

Term id
lower case, matches ^[a-z][a-z0-9-]*$, and is unique.
Phrases
a term or alias must not repeat across the glossary, in any case.
Matching
matchTerms() tries the longest phrase first and needs word boundaries.
Skipped text
text inside pre, code and a stays untouched.
Attributes
only class, id, title, lang and href on a.
Links
href must start with https://, http:// or #.
Definition
a native button with aria-expanded shows a role="note" span.
Sources

Error messages and fixes

SymptomCauseFix
stale reviewProposals or cps changed after reviewUse the new decisions.json from review.html
resolve glossary or acknowledge reading-budget overflowApproved cue misses a term or the budgetAdd the term or set override_budget to true
STYLE and REGION are outside the supported subsetVTT has STYLE or REGION blocksRemove them. NOTE blocks are ignored
Placeholder multiset changedTranslation drops or adds a {name}Keep every placeholder of the source
Stale or invalid translation decisionReview translation differs from the proposalDownload a new locale-review.json
Resolve translation issues or context before approvingAmbiguous key not acknowledgedSet acknowledgeContext to true
Ambiguous repeated phraseSame phrase in two termsGive each phrase one term
Unsupported HTML elementTag outside the allowed subsetUse the listed tags only
Sources

Defaults and limits

SettingDefaultNote
cps17Must be positive and finite
schema_version1In translation-decisions.json
approvedFalseEvery cue starts unapproved
override_budgetFalseNeeded for an over-budget approval
Proposal length2000Characters at most per proposal
schemaVersion1Required in locale-review.json
Output folderoutputSecond argument of the Node CLIs
Exit code on error2The Node CLIs print the message
Sources

Pick a multilingual model

TaskCode
Classification, 100 languagesXLM-R-base fine-tuned
Zero-shot classificationjoeddav/xlm-roberta-large-xnli
Translation, 200 languagesfacebook/nllb-200-distilled-600M
Low-resource languageXLM-V or a related-language fine-tune
Few-shot epochsnum_train_epochs=5
Few-shot learning ratelearning_rate=2e-5
Long-tail scriptsbyte_fallback=True
Sources

Source language choice

Is English always the best source?
No. Language similarity predicts transfer better than corpus size.
Marathi target?
rank_source_languages() puts Hindi above English.
How many target labels?
100 to 500 examples give 95 to 98 percent of the English baseline.
Why not a higher learning rate?
The multilingual alignment collapses to an English-only model.
What is the fertility tax?
Hindi can need 3 to 5 times the tokens of English.
Sources

Tips

  • Report accuracy per language. An aggregate hides the long tail.
  • Check tokenization fertility on target text before you train.
  • Every translation needs a human review. The tools only flag problems.
  • The UI workbench supports simple named placeholders, not ICU messages.
  • Glossary phrases never cross elements or entity boundaries.
  • The HTML runs locally and sends no data to a third-party service.
Sources
Original source
---
id: localization-workbenches
title: Localization and Glossary Tools
code: LG
subtitle: Run, feed and check three review-first localization projects. Pick a multilingual model and a source language.
hue: 28
sources: phases/05-nlp-foundations-to-advanced/18-multilingual-nlp, projects/subtitle-localization-desk, projects/ui-string-localization-workbench, projects/glossary-hovercard-publisher
source_hash: 8406a26bb6811eb3
---

## Three projects side by side
type: comparison
span: 2
from: projects/subtitle-localization-desk/README.md, projects/subtitle-localization-desk/project.json, projects/subtitle-localization-desk/solution/cli.py, projects/ui-string-localization-workbench/README.md, projects/ui-string-localization-workbench/solution/cli.ts, projects/glossary-hovercard-publisher/README.md, projects/glossary-hovercard-publisher/solution/cli.ts

| Factor | Subtitle Localization Desk | UI String Localization Workbench | Glossary Hovercard Publisher |
|---|---|---|---|
| Builds | Reviewed WebVTT and an HTML desk | Reviewed locale JSON and a preview | Annotated HTML lesson |
| Language | Python 3.10+ | Node 22.18 or newer | Node 22.18 or newer |
| Input keys | `vtt`, `translations`, `glossary`, `cps` | `locale`, `messages`, `proposals`, `values` | `glossary`, `lesson` |
| Outputs | `review.html`, `translation-decisions.json`, `reviewed.vtt` | `locale.json`, `unresolved-strings.json`, `report.html` | `report.html`, `glossary.json`, `coverage.json` |
| Review file | `--decisions decisions.json` | third argument `locale-review.json` | none |
| Hard gate | `reviewed.vtt` only when all cues approved | approve only with no issues | balanced HTML subset |

## Run the reference
type: command-table
from: projects/subtitle-localization-desk/README.md, projects/ui-string-localization-workbench/README.md, projects/ui-string-localization-workbench/solution/cli.ts, projects/glossary-hovercard-publisher/README.md

| Command | What it does |
|---|---|
| `python3 cli.py samples/input.json --output demo-output` | Subtitle desk on the sample |
| `python3 cli.py <input.json> --output <dir>` | Subtitle desk on your input |
| `node cli.ts sample.json output` | UI workbench or glossary publisher |
| `node cli.ts <input.json> <dir> <review.json>` | UI workbench with your review |
| `node cli.ts --help` | Prints the argument line |

## Build and grade your version
type: task-table
span: 2
from: projects/subtitle-localization-desk/README.md, projects/ui-string-localization-workbench/README.md, projects/glossary-hovercard-publisher/README.md

| Task | Code |
|---|---|
| Make a starter | `python3 scripts/project_test.py <project> --init <dir>` |
| Grade one stage | `python3 scripts/project_test.py <project> --stage 1 --path <dir> --strict` |
| Grade all stages | `python3 scripts/project_test.py <project> --all --path <dir> --strict` |
| Save a completion report | `--report completion.json` |
| Grade the reference | `python3 scripts/project_test.py <project> --all --solution --strict` |

## Subtitle desk pipeline
type: flow
from: projects/subtitle-localization-desk/API.md, projects/subtitle-localization-desk/solution/main.py, projects/subtitle-localization-desk/solution/cli.py

1. **parse_vtt**: reads WebVTT into cues. It keeps timestamp strings and gives `cue-N` to cues with no id.
2. **propose**: takes supplied translations. It replaces source glossary terms longest first.
3. **inspect**: counts visible characters and sets `budget=floor(duration*cps)`.
4. **export_localized**: binds the review to a SHA-256 `fingerprint` of proposals and cps.
5. **You**: edit `decisions.json`, set `approved` per cue, then run again with `--decisions`.
6. **CLI**: writes `reviewed.vtt` only when every cue is approved.

## Subtitle input (samples/input.json)
type: annotated-code
lang: text
from: projects/subtitle-localization-desk/solution/samples/input.json, projects/subtitle-localization-desk/API.md

```text
{
  "vtt": "WEBVTT\n\nmap\n00:00.000 --> 00:03.000\nOpen the map.\n...",
  "translations": {
    "map": "Abre el map.",  # glossary turns it into "Abre el mapa."
    "label": "Escribe un nombre descriptivo ..."  # 2 s at cps 12, budget 24
  },
  "glossary": {"map": "mapa", "marker": "marcador"},  # source to target
  "cps": 12  # optional, the default is 17
}
```

## UI string workbench flow
type: architecture
from: projects/ui-string-localization-workbench/solution/main.ts, projects/ui-string-localization-workbench/solution/cli.ts, projects/ui-string-localization-workbench/README.md

```arch
node | in | 1,1 | sample.json | messages, proposals | client
node | read | 2,1 | readCatalog() | keys, placeholders | process
node | prop | 3,1 | proposeTranslations() | issues, needsContext | process
node | rev | 3,2 | reviewTranslations() | approve, reject, pending | process
node | loc | 1,2 | locale.json | approved strings | store
node | unr | 2,2 | unresolved-strings.json | keys with reasons | store
edge | in | read | messages
edge | read | prop | Message[]
edge | prop | rev | Proposal[]
edge | rev | loc | catalog
edge | rev | unr | unresolved
```

## Glossary publisher rules
type: concepts
from: projects/glossary-hovercard-publisher/solution/main.ts, projects/glossary-hovercard-publisher/README.md

- **Term id**: lower case, matches `^[a-z][a-z0-9-]*$`, and is unique.
- **Phrases**: a term or alias must not repeat across the glossary, in any case.
- **Matching**: `matchTerms()` tries the longest phrase first and needs word boundaries.
- **Skipped text**: text inside `pre`, `code` and `a` stays untouched.
- **Attributes**: only `class`, `id`, `title`, `lang` and `href` on `a`.
- **Links**: `href` must start with `https://`, `http://` or `#`.
- **Definition**: a native button with `aria-expanded` shows a `role="note"` span.

## Error messages and fixes
type: troubleshooting
from: projects/subtitle-localization-desk/solution/main.py, projects/subtitle-localization-desk/solution/cli.py, projects/ui-string-localization-workbench/solution/main.ts, projects/glossary-hovercard-publisher/solution/main.ts

| Symptom | Cause | Fix |
|---|---|---|
| `stale review` | Proposals or cps changed after review | Use the new `decisions.json` from `review.html` |
| `resolve glossary or acknowledge reading-budget overflow` | Approved cue misses a term or the budget | Add the term or set `override_budget` to true |
| `STYLE and REGION are outside the supported subset` | VTT has STYLE or REGION blocks | Remove them. NOTE blocks are ignored |
| `Placeholder multiset changed` | Translation drops or adds a `{name}` | Keep every placeholder of the source |
| `Stale or invalid translation decision` | Review translation differs from the proposal | Download a new `locale-review.json` |
| `Resolve translation issues or context before approving` | Ambiguous key not acknowledged | Set `acknowledgeContext` to true |
| `Ambiguous repeated phrase` | Same phrase in two terms | Give each phrase one term |
| `Unsupported HTML element` | Tag outside the allowed subset | Use the listed tags only |

## Defaults and limits
type: defaults
from: projects/subtitle-localization-desk/solution/main.py, projects/subtitle-localization-desk/solution/cli.py, projects/ui-string-localization-workbench/solution/main.ts, projects/ui-string-localization-workbench/solution/cli.ts

| Setting | Default | Note |
|---|---|---|
| `cps` | 17 | Must be positive and finite |
| `schema_version` | 1 | In `translation-decisions.json` |
| `approved` | `False` | Every cue starts unapproved |
| `override_budget` | `False` | Needed for an over-budget approval |
| Proposal length | 2000 | Characters at most per proposal |
| `schemaVersion` | 1 | Required in `locale-review.json` |
| Output folder | `output` | Second argument of the Node CLIs |
| Exit code on error | 2 | The Node CLIs print the message |

## Pick a multilingual model
type: task-table
from: phases/05-nlp-foundations-to-advanced/18-multilingual-nlp/docs/en.md

| Task | Code |
|---|---|
| Classification, 100 languages | `XLM-R-base` fine-tuned |
| Zero-shot classification | `joeddav/xlm-roberta-large-xnli` |
| Translation, 200 languages | `facebook/nllb-200-distilled-600M` |
| Low-resource language | `XLM-V` or a related-language fine-tune |
| Few-shot epochs | `num_train_epochs=5` |
| Few-shot learning rate | `learning_rate=2e-5` |
| Long-tail scripts | `byte_fallback=True` |

## Source language choice
type: qa
from: phases/05-nlp-foundations-to-advanced/18-multilingual-nlp/docs/en.md, phases/05-nlp-foundations-to-advanced/18-multilingual-nlp/code/main.py

- **Is English always the best source?** No. Language similarity predicts transfer better than corpus size.
- **Marathi target?** `rank_source_languages()` puts Hindi above English.
- **How many target labels?** 100 to 500 examples give 95 to 98 percent of the English baseline.
- **Why not a higher learning rate?** The multilingual alignment collapses to an English-only model.
- **What is the fertility tax?** Hindi can need 3 to 5 times the tokens of English.

## Tips
type: tips
from: phases/05-nlp-foundations-to-advanced/18-multilingual-nlp/docs/en.md, projects/subtitle-localization-desk/README.md, projects/ui-string-localization-workbench/README.md, projects/glossary-hovercard-publisher/README.md

- Report accuracy per language. An aggregate hides the long tail.
- Check tokenization fertility on target text before you train.
- Every translation needs a human review. The tools only flag problems.
- The UI workbench supports simple named placeholders, not ICU messages.
- Glossary phrases never cross elements or entity boundaries.
- The HTML runs locally and sends no data to a third-party service.
Code and artifacts 1
What you take away

Saved in your notebook on this device.

Sources and limits

Reading checkpoints are self-reported. Test results are recorded separately and apply to the executed cases.

AI Engineering from Scratch · 3f9715c · MIT

Download this file ↓