GitHub user glaterza edited a comment on the discussion: Proposal: a 
translation guide, with shared principles and per-language conventions

## Update on translations: what we did and what I propose next

**In short:** I propose a glossary file for each language and one shared list 
of core terms, next to the catalogs. The AI backfill and the CI checks read 
these files. In a local test, the backfill used a glossary term in 5 of 5 runs. 
With the prompt on master, it used the term in 0 of 5. The work is 10 small 
PRs, one issue and one later proposal. Steps 1 to 4 are the main change.

**What I need from you:** a review of the Translation Guide PR, #45181, and 
your view on the direction below. 

Thank you, @hainenber and @sadpandajoe, for the reviews of #44397. @hainenber 
merged it on 2026-10-10.

### Your suggestions and what happened

| Who | Suggestion | Status |
|---|---|---|
| @rusackas, Aug 26 | Worried that nobody would maintain glossaries. Asked for 
automation, such as structured comments in `messages.pot`. Supported shared 
rules on the docs site. | #44397 (`i18n:` notes), Translation Guide #45181 |
| @sfirke, Aug 31 | Rules next to each catalog, or a pointer in each `.po` file 
to follow and update them | Steps 4 and 10 |
| @rusackas, Sep 14 | Agreed: `--add-comments` first, as its own PR; 
tool-checked parts next to the catalogs, prose on the docs site | #44397, and 
this plan |
| @rusackas, Sep 16 | Fix the `msgcat` flag; a separate issue for the missing 
strings | #44395; #44403, closed by #44467 (@sadpandajoe) |
| @rusackas, Sep 23 | Agreed to clear fuzzy entries with broken placeholders 
(#44551); the English fallback as its own PR | #44611 cleared 1,188 entries; 
step 7 |
| @goldjee, Oct 1–2 | A glossary per language for the backfill; the same core 
terms in every string; two style rules (no full stop after a one-sentence 
message; ё or е chosen once) | Steps 3 and 4; the rules are examples in the 
Guide |

Also merged: #44587 by @sadpandajoe fixed the Slovak error in SQL Lab.

### Known problems

#### The AI backfill

1. In my test, the model ignored a note when the other languages had wrong 
translations. For the Russian `Backend`, I gave five languages wrong words, 
such as German «Treiber» ("driver") and French «Serveur» ("server"). The model 
then answered «Драйвер» ("driver") in 29 of 30 runs, with or without a note 
(`claude-sonnet-4-6`). With the real translations, it answered «Бэкенд» in 12 
of 12 runs.
2. The backfill sends the other languages' translations of each string, but not 
the terms that the target catalog already uses. So the model can create a new 
term for a concept that the catalog already names, as in @goldjee's example, 
probably "annotation template".

#### Translator notes

3. pybabel drops a note without an error in four cases:
   - a blank line between the note and the call;
   - the note inside the parentheses of a call;
   - a wrapped Python string with only a comment or nothing after it;
   - the second of two calls on one line.

   I put a note above each of the 1,005 `_(` and `__(` calls in `superset/`, 
without migrations. pybabel dropped 126 of them.

#### The catalogs

4. Some translations are wrong: `Slug` in Dutch and German, `Host` in Italian, 
`Backend` in Russian and French, and `URL Slug` in Dutch. I found these by 
chance, so the list is not complete. Also, Spanish, Romanian and Serbian use 
the same words for "dashboard" and "control panel".
5. Some fuzzy translations that nobody reviewed have a wrong meaning. Superset 
shows fuzzy translations on purpose, and this decision is in the howto. For 
example, Polish and Dutch show "List Users" as "split number" and "Themes" as 
"time". About 14,900 fuzzy entries have no AI backfill comment.
6. No CI check covers placeholders in all catalogs. `msgfmt --check-format 
--use-fuzzy` reports 166 errors, and 14 of them are in reviewed entries. Of the 
166, 137 are in plural entries, and some of those are correct translations.
7. The Polish catalog has the French header and plural rule, so Polish users 
see wrong plural forms, for example «Usunięto 5 pulpity nawigacyjne».

#### The process

8. In the 14 days up to 2026-10-10, 36 commits on master changed 
`messages.pot`, on 12 different days. A PR that changes this file often has 
merge conflicts, so I keep every step small.

<details>
<summary>Corrections to my earlier comments</summary>

- On #44397, I wrote that the note fixed the Russian `Backend`. That result did 
not repeat, and I corrected it there.
- On Sep 17, I wrote that other comments stay out of the catalogs. That was 
wrong: pybabel adds every comment line between the `i18n:` line and the call to 
the note. #45181 corrects the howto.
- On Sep 17, I wrote that the backend drops fuzzy entries. That was wrong: the 
release build compiles the backend with `-f`, and a Docker image built with 
`BUILD_TRANSLATIONS=true` uses `--use-fuzzy`.

</details>

### What I propose

Files that a tool reads go next to the catalogs. Rules for people go on the 
docs site.

1. Rules for people: the Translation Guide, #45181. It includes @goldjee's two 
style rules as examples of decisions that each language makes once.
2. Files for tools: one glossary file per language, next to its catalog, and 
one shared list of core terms. For example, 
`superset/translations/es/glossary.yaml`:

```yaml
style:
  register: informal          # tú (informal)
terms:
  - source: control panel
    target: panel de configuración
    why: '"panel de control" already means dashboard in 118 reviewed entries'
    avoid: [panel de control]
```

`superset/translations/terms.yaml` lists the core terms, with one line of 
English for each. It starts from @goldjee's list. I use "metric" instead of 
"measure", because the UI uses "metric" or "metrics" in 193 strings and 
"measure" in 2:

```
dashboard, filter, chart, metric, dimension, dataset, column, annotation,
annotation layer, annotation template, database connection, SQL Lab
```

The backfill takes each language's translations of these terms from its 
catalog, so a language without a glossary file also benefits. A native speaker 
corrects a term in the glossary file. The files will have the ASF license 
header, and `MANIFEST.in` already ships every file in `superset/translations`.

3. Tools that read these files:
   - With each string, the backfill sends the register, and the glossary terms 
and core terms that the string uses. It skips the old translation of a term 
that has a note or a glossary entry, because that translation can be wrong.
   - The prompt uses one order: a glossary term or a note first, then the terms 
of the catalog, then the other languages. For a string with a note, the 
backfill does not send the other languages.
   - `scripts/translations/backfill_eval.py` translates known hard cases 
several times and counts the correct answers. It calls the model through 
`claude -p`, so the author of a prompt change runs it by hand.
   - The drift check also fails when an `i18n:` comment in the code does not 
reach its entry in `messages.pot`.
   - An advisory CI check lists translations that use a word from a glossary's 
`avoid` list. It checks only entries whose English text contains the `source` 
term.
   - `babel_update.sh` writes a pointer at the top of each `.po` file that has 
a glossary. In the pointer, translators read that they must follow the glossary 
and, if needed, update it.

#### Test of a local prototype

I built the backfill part and ran four cases that I chose, 5 times each, with 
`claude-sonnet-4-6`:

| Case | Prompt on master | Prototype |
|---|---|---|
| Russian "Backend" with a note | 0 of 5 | 5 of 5 had no "driver", but with 
four different words |
| Russian "Backend" with the glossary term «Бэкенд» | 0 of 5 | 5 of 5 |
| Spanish "control panel" with the glossary term «panel de configuración» | 0 
of 5 | 5 of 5 |
| Spanish "dashboard" in a new string, with the catalog term «Panel de control» 
| 0 of 5 | 5 of 5 |

A glossary term or a catalog term gave the same word in all runs. With a note, 
the model chose the right meaning, but it used different words.

<details>
<summary>How the test works</summary>

- In the Russian cases, I gave the model wrong translations in five other 
languages, for example German «Treiber» ("driver").
- In the Spanish control-panel case, the other languages have their own correct 
words, and these words lead to «panel de control» in Spanish. The new dashboard 
string has no translations in other languages.
- A run passes when the answer has the expected word. For the note case, a run 
passes when the answer has no "driver", "server" or "controller". The four 
words were «Бэкенд», «Движок» ("engine"), «База данных» ("database") and «Тип 
системы» ("system type").
- When the prompt also had the translations of the other languages, the note 
case stayed at 0 of 5.

</details>

#### Alternatives I rejected

- A glossary only on the docs site: no tool reads it, and on Aug 26 @rusackas 
worried that nobody would maintain the glossaries.
- Notes only, without glossary files: in the test, a note did not give one 
fixed word.

### Roadmap

Steps 1 to 10 are small, separate PRs. Steps 1 to 4 are the main change.

1. The Translation Guide, #45181. It needs a maintainer's review.
2. The prompt order, no other languages for a string with a note, and 
`backfill_eval.py`.
3. `terms.yaml`, and the backfill sends the core-term translations.
4. A glossary file for `es`, which I will write, and the backfill reads 
glossary files.
5. Fixes for the real `msgfmt` errors. I check the plural forms, and I ask 
native speakers where I cannot judge. Then a CI check for new errors, with a 
list of the correct plural forms.
6. The placement check in the drift check.
7. The English fallback in the backend and in the frontend.
8. The Polish header and plural forms, with a Polish speaker.
9. The advisory `avoid` check.
10. The glossary pointer in each `.po` file that has a glossary.
11. An issue with the wrong translations above, including the Romanian and 
Serbian "dashboard" and "control panel" words.
12. A proposal for the fuzzy translations that nobody reviewed.


GitHub link: 
https://github.com/apache/superset/discussions/43562#discussioncomment-18857741

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: 
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to