Skip to content

fix(i18n): add 6 missing translation keys and enforce locale parity in tests - #2995

Open
Zuhef wants to merge 1 commit into
Chainlit:mainfrom
Zuhef:fix/2993-i18n-locale-parity
Open

fix(i18n): add 6 missing translation keys and enforce locale parity in tests#2995
Zuhef wants to merge 1 commit into
Chainlit:mainfrom
Zuhef:fix/2993-i18n-locale-parity

Conversation

@Zuhef

@Zuhef Zuhef commented Jul 29, 2026

Copy link
Copy Markdown

Fixes #2993

Both halves of the issue

1. The six missing keys. Added to the locales that lacked them:

Locale Key added
ar-SA, da-DK chat.favorites.remove
de-DE, it, ko components.DatePickerInput
ja chat.fileUpload.browse

2. A parity test over the real locale files - the durable half. backend/tests/test_translations.py now has a TestShippedTranslationFileParity suite that walks backend/chainlit/translations/ and compares every file against en-US.json using the project's own compare_json_structures.

It is parametrized per locale, so a regression names the offending file in the test id and lists the exact keys in the assertion message:

FAILED backend/tests/test_translations.py::TestShippedTranslationFileParity::test_locale_matches_ground_truth_structure[da-DK.json]
AssertionError: da-DK.json differs from en-US.json:
    Missing key: 'chat.favorites.remove'

Two details from the issue notes:

  • en-US.json needs no special-casing - it is included in the parametrization and comparing it to itself is trivially clean.
  • Because the locale list is globbed at collection time, an empty glob would make every parametrized case silently vanish rather than fail. test_translations_directory_is_discoverable guards that: it asserts the directory exists, that en-US.json is in it, and that more than one locale file was found.

Verification

Ran against the local source tree (PYTHONPATH=backend):

  • pytest backend/tests/test_translations.py - 81 passed (35 pre-existing, plus 46 parametrized locale cases and the discoverability guard).
  • Independently confirmed the six gaps before the change, and zero after, by running compare_json_structures over all 23 locale files.
  • Mutation-checked the new test rather than trusting it: deleting chat.favorites.remove from da-DK.json produces exactly the failure quoted above; restoring it returns to 81 passed. A parity test that cannot fail would be worse than none.

On the translations themselves

The issue notes the six strings are best done by native speakers, and I am not one for these locales. Rather than inventing phrasing, each follows terminology already present in the same file or the established house style:

  • ar-SA reuses the "remove" wording from its existing chat.fileUpload.actions.removeAttachment.
  • da-DK uses Fjern, matching its own removeAttachment value.
  • ja follows the same pattern as its existing dragDrop and removeAttachment entries.
  • The DatePickerInput strings follow the existing fr-FR / es / nl phrasing ("Choisir une date" / "Elige una fecha" / "Kies een datum").

I would welcome native-speaker review on all six, and I am happy to take corrections in this PR. The parity test is the part I would defend on engineering grounds; the wording I would defer on.


Summary by cubic

Adds six missing i18n keys across shipped locales and introduces a parity test to ensure all locale files match en-US.json. Prevents missing-key renders and blocks future gaps.

  • Bug Fixes

    • ar-SA, da-DK: add chat.favorites.remove.
    • de-DE, it, ko: add components.DatePickerInput placeholders (single, range).
    • ja: add chat.fileUpload.browse.
  • Tests

    • Parametrized parity test compares each shipped locale to en-US.json using compare_json_structures, failing with exact missing keys.
    • Add a discoverability guard so tests don’t pass vacuously if the translations directory changes.

Written for commit 1bc1a30. Summary will update on new commits.

Review in cubic

…n tests

Six keys present in en-US.json were missing from other locale files, so users
on those locales fell through to a missing-key render instead of translated
text:

  ar-SA, da-DK   chat.favorites.remove
  de-DE, it, ko  components.DatePickerInput
  ja             chat.fileUpload.browse

Nothing caught this, which is why the gaps accumulated across three separate
PRs. `chainlit lint-translations` loads en-US.json from the package and then
lints the *consuming app's* .chainlit/translations/ directory, not
backend/chainlit/translations/, and test_translations.py only exercised
compare_json_structures against synthetic in-test dictionaries.

Add a parametrized suite that walks the shipped locale files and compares each
against en-US.json, so every locale gets its own test id and a failure names
both the file and the missing key. en-US.json needs no special-casing since
comparing it to itself is trivially clean. A separate test asserts the
directory is discoverable, so the parametrized cases cannot pass vacuously if
the directory is ever moved or renamed.

The six translations follow the terminology already present in each file:
ar-SA and da-DK reuse the remove wording from
chat.fileUpload.actions.removeAttachment, and the date-picker strings follow
the existing fr-FR/es/nl phrasing. They would still benefit from
native-speaker review.

Fixes Chainlit#2993
@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. translation Translation or localisation of strings. unit-tests Has unit tests. labels Jul 29, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 7 files

Re-trigger cubic

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

Labels

size:XS This PR changes 0-9 lines, ignoring generated files. translation Translation or localisation of strings. unit-tests Has unit tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

i18n: 6 translation keys missing across 6 locales, and nothing enforces parity

1 participant