Skip to content

Seven strings 15+ locales translated and one left in English (needs a native speaker) #257

Description

@letuhao

AC-8 of docs/plans/2026-09-13-v0.1.0-ship-acceptance.md. These need a native speaker, not an agent — writing a translation is the judgement T8 reserves for a person.

Seven strings that 15+ locales translated and one or two left in English

Found by scripts/i18n-untranslated-outlier-gate.py (new), which checks the one defect i18n-placeholder-parity-gate.py is structurally blind to: a value that was never translated at all has perfect placeholder parity, because it was copied from the English.

locale(s) key kept the English
ru kgOntology.adopt.scope.project "Project"
ru kgOntology.adopt.scope.user "User"
bn studio.checkpoints.insert "Inserted"
bn usage.purpose.chunk_edit "Chunk Edit"
ja composition.branchdiff.todo "todo"
ja knowledge.temporal.timeline.interval.open "[{{from}} → open)"
th chat.inspector.title "Agent runtime"

The ru pair is the least ambiguous: Project and User are everyday words Russian localises (Проект, Пользователь), and Russian is the most thoroughly translated locale in the repo — only 44 strings identical to English, against 479 for French. These two stand out against that locale's own standard.

ja's "[{{from}} → open)" is a half-translated string: the interval syntax is fine, the word open is not.

th's "Agent runtime" may be a deliberate product term. A Thai reader should decide.

Why these seven and not the other 3,637

3,637 strings across the 17 locales are byte-identical to their English. Most are correct — brand names, PDF, API, OK. Flagging them all would produce a gate nobody reads.

The signal is comparative, so the distribution does the work:

keys identical-to-EN in N locales:
    1 locale:   513        (a gap in that one locale)
    2 locales:  160
    3 locales:   93
   ...
   16 locales:   67        (a convention)
   17 locales:   31

A key that one locale left in English while sixteen translated it is a gap. A key that all seventeen kept is a loanword. The gate flags only <= 2 locales, and only when at least one writes in a non-Latin script — a Latin-script locale borrowing an English word is normal (de alone keeps 473), and including them buries the signal. A UNIVERSAL_TERMS list removes the genuinely universal technical vocabulary (API Key, Bearer token, Raw JSON, Client ID, Temperature), which is why the raw 13 candidates reduce to these 7.

What this does NOT establish

Nothing here reads meaning. A fluent, confident mistranslation passes this gate exactly as it passes placeholder parity. This finds strings that were never translated; it cannot find strings translated wrongly. The 197 machine-translated strings still need a human read, and AC-8 does not reach met on the strength of this file.

Related: #256 (the same "a check that cannot see its subject" shape), and the zh-CN 战役 / zh-TW 活動 disagreement, which is the mistranslation class this gate cannot reach.

Baseline, not permission

All seven are in the gate's BASELINE with a reason, so CI is not red for work that is not an agent's to do. The gate reds the moment an eighth appears, and reds if a BASELINE row becomes stale — so the debt cannot grow quietly, and it cannot be left behind once fixed.

Activity

  1. letuhao commented on Sep 13, 2026

    @letuhao
    OwnerAuthor

    Correction — the fix proposed here violates the repo's own standard

    This issue says the seven strings "need a native speaker, not an agent — writing a translation is the judgement T8 reserves for a person." That is wrong about the workflow, and I am leaving it above rather than editing it away.

    docs/standards/multilingual.md ML-7:

    Only en is hand-authored — it is the single source of truth for UI copy. Every other UI locale is GENERATED by scripts/i18n_translate.py. Never hand-edit a non-en locale JSON (the tool overwrites it and it drifts from en).

    So nobody hand-writes these seven — not an agent, and not a native speaker either. The sanctioned fix already exists as a flag:

    --retry-echoed    also re-translate keys that came back as the English source.
                      One pass — a genuine loan word returns unchanged and stays.
    

    That is precisely this issue's population, and the tool even resolves the ambiguity the UNIVERSAL_TERMS list was approximating: a genuine loan word comes back unchanged and is kept, so Bearer token staying English is a result, not an exemption someone has to curate.

    scripts/i18n_translate.py's own docstring for echoed_keys() describes this exact defect class, and names a case worse than any of the seven:

    the gap a completeness check structurally cannot see: it asserts a key is PRESENT and NON-EMPTY, and English satisfies both forever. Measured live, chat.toolApproval.never_allowed was English in ALL 17 locales

    The correct action is therefore a tool run, not a translation task — and it is not blocked on a person:

    python scripts/i18n_translate.py --retry-echoed

    The seven remain in i18n-untranslated-outlier-gate.py's BASELINE, but the reasons attached to them ("needs a Thai rendering (T8)") describe a workflow the standard forbids and should be re-worded when the run happens.

    What a person is still needed for is unchanged and narrower than this issue implied: whether a translation means the right thing. That is T8/T9, and no tool run settles it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions