Skip to content

chore(translations): apply translation validation pass across 16 locales#159

Merged
InstaZDLL merged 2 commits into
mainfrom
chore/translations-validation-pass-pass
May 26, 2026
Merged

chore(translations): apply translation validation pass across 16 locales#159
InstaZDLL merged 2 commits into
mainfrom
chore/translations-validation-pass-pass

Conversation

@InstaZDLL
Copy link
Copy Markdown
Owner

@InstaZDLL InstaZDLL commented May 26, 2026

Summary

Ran secrets/validate-translations.mjs against every non-en locale, then dispatched 4 parallel agents to apply the model-suggested fixes after spot-checking each claim against en.json.

~340 corrections across 16 locales, 521 insertions / 492 deletions, no structural breakage afterwards.

What got applied

  • Music-context false friends — cover → entrance fee, track → footprint, plays → games, library → public library / bookshelf, pitch translated as key/tone, queue as generic waiting line, bitrate as flow rate, scrobble misspellings. Caught across most locales.
  • Plural / grammar bugs — Russian *_few backfilled (one/few/many is three distinct forms), Turkish nouns kept singular after a number ({{count}} parça not parçalar), Korean dropped the spurious pluraliser, Japanese counter words corrected ( for tracks, for albums, for items, for artists).
  • Untranslated UI jargon left in English on recent feature adds — player bar, covers, tray, local-first, EQ preset names, mood-radio category titles.
  • Placeholder integrity — rescued es.json <nombre> rename + hi.json <नाम> variant of the same shape (would have broken runtime template substitution).
  • Korean register normalisation-습니다 / -ㅂ니다 for actions and noun forms for labels in Settings + modals, dropped casual -해요.
  • Chinese punctuation — half-width → full-width in CJK strings per locale convention.
  • Reversed-meaning fixestrackActions.addToPlaylistNamed / removeFromPlaylistNamed were reading "add the playlist to the track" in FR and similar locales → restored Add to "{{name}}" semantics.

What got deliberately skipped (and why)

  • player.controls.repeatAll / repeatOne — the model flagged these as source typos in multiple locale reports, but en.json is intentional: it's the aria-label cycle-next pattern (the label describes what the NEXT click does, not the current state). Verified usage in PlaybackControls.tsx:99-104. Left every locale alone.
  • Brand identifiersDaily Mix and On Repeat left verbatim across all locales. Same policy as WaveFlow / Last.fm / Deezer / ReplayGain / LRCLIB / BPM per CLAUDE.md — smart-playlist family names are part of the product surface, not localisable copy.
  • §5 terminology suggestions — pure renames like "titre vs morceau" in FR, "Library vs Bibliothèque" debates: informational, not bugs. Skipped.
  • Pure register swingstuvous style swings applied only when the rest of the locale was already consistent and this row was a slip-up (FR specifically). Skipped elsewhere when the locale didn't have a clear canonical register.

Validation

bun secrets/validate-translations.mjs --dry-run

Clean afterwards across all 16 locales:

  • 0 missing keys
  • 0 broken placeholders
  • 0 real extra keys (the AR _zero/_two/_few/_many and RU _few plural variants the script flags as "extra" are legitimate i18next per-locale plural forms — EN doesn't have them but the locales need them per CLDR plural rules)

Test plan

  • bun secrets/validate-translations.mjs --dry-run — clean
  • Manual smoke per locale (focus on FR / DE / ES / JA / KO / ZH-CN / TR / RU since they got the most edits) — open the app, switch locale via Settings → Appearance, walk Settings + Library + Playlist + Now Playing + the modal dialogs and confirm nothing breaks visually or text overflows.

Summary by CodeRabbit

  • Documentation
    • Mise à jour des traductions et harmonisation terminologique dans 16 langues (AR, DE, ES, FR, HI, ID, IT, JA, KO, NL, PT‑BR, PT, RU, TR, ZH‑CN, ZH‑TW) : corrections de libellés, formes plurielles, reformulations et standardisation sur onboarding, Mood Radio, player/queue, égaliseur/presets, Wrapped, Last.fm, diagnostics et libellés Hi‑Res.

Ran secrets/validate-translations.mjs against every non-en locale and
applied the model-suggested fixes after spot-checking each claim
against en.json. Net: 16 files, ~340 individual corrections.

Categories applied:
- Literal-MT false friends in music UI: cover → entrance fee, track →
  footprint, plays → games, library → public library / bookshelf,
  pitch translated as key/tone, queue as generic waiting line, bitrate
  as flow rate, etc. Caught across most locales.
- Plural / grammar bugs: Russian *_few backfilled (one/few/many is
  three distinct forms), Turkish nouns kept singular after a number
  ({{count}} parça not parçalar), Korean dropped the spurious 들
  pluraliser after counts, Japanese counter words corrected (曲 for
  tracks, 枚 for albums, 件 for items, 組 for artists).
- Untranslated UI jargon left in English on recent feature adds
  (player bar, covers, tray, local-first, EQ preset names, mood-radio
  category titles, equalizer presets).
- Placeholder integrity: rescued an es.json `<nombre>` rename that
  would have broken the runtime substitution, fixed hi.json `<नाम>`
  variant of the same shape.
- Korean register normalisation: -습니다 / -ㅂ니다 endings for
  actions and noun forms for labels in Settings + modals, dropped
  casual -해요.
- Chinese punctuation: half-width → full-width in CJK strings.
- Reversed-meaning fixes: trackActions.addToPlaylistNamed /
  removeFromPlaylistNamed were reading "add the playlist to the
  track" in FR and similar — restored "Add to {{name}}" semantics.

Categories deliberately skipped:
- player.controls.repeatAll / repeatOne — the model flagged these as
  source typos but en.json is intentional (aria-label cycle-next
  pattern: the label describes what the NEXT click does, not the
  current state). Verified usage in PlaybackControls.tsx.
- Brand identifiers "Daily Mix" and "On Repeat" left verbatim — same
  policy as WaveFlow / Last.fm / Deezer / ReplayGain / LRCLIB / BPM in
  CLAUDE.md (smart-playlist family names are part of the product
  surface, not localisable copy).
- Pure terminology renames from §5 of each report (titre vs morceau in
  FR, etc.) — informational suggestions, not bugs.
- Pure register style swings when the rest of the locale wasn't
  consistent enough to call one form canonical.

Structural check via bun secrets/validate-translations.mjs --dry-run
clean afterwards: zero missing keys, zero broken placeholders, zero
real extra keys (the AR _zero/_two/_few/_many and RU _few plural
variants the script flags are legitimate i18next per-locale plural
forms, not bugs).
@InstaZDLL InstaZDLL added scope: frontend React/Vite frontend (src/) scope: i18n Translations (src/i18n/) labels May 26, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 72e8e23b-9357-46a3-ad6f-f362580014c6

📥 Commits

Reviewing files that changed from the base of the PR and between 666426f and 0d7030a.

📒 Files selected for processing (3)
  • src/i18n/locales/ar.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/nl.json

📝 Walkthrough

Walkthrough

Ce PR met à jour de manière cohérente les chaînes de localisation dans 16 fichiers JSON de langues différentes (arabe, allemand, espagnol, français, hindi, indonésien, italien, japonais, coréen, néerlandais, portugais brésilien, portugais, russe, turc, chinois simplifié et traditionnel). Les changements sont uniquement des valeurs i18n : reformulations, harmonisation terminologique, pluralisations et traductions de termes audio/UI.

Changes

Mise à jour multilingue d'interface utilisateur WaveFlow

Layer / File(s) Summary
Toutes les locales (chaînes i18n)
src/i18n/locales/*.json
Modifications concentrées des valeurs de chaînes dans 16 fichiers de locale : onboarding/Last.fm, Mood Radio/Wrapped, libellés des favoris, navigation/bibliothèque, contrôles player/queue, pipeline audio et préréglages d'égaliseur, réglages (crossfade/gapless), pluriels (notamment russe), éditeur de paroles et corrections mineures d'UI. Toutes les modifications sont des valeurs JSON (aucun changement d'API/structure).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested labels

type: fix

"Seize langues alignées, phrases ajustées,
Mots remplacés, pluriels complétés.
Mood, queue et égaliseurs chantent en cœur,
Un petit PR pour un monde meilleur." 🎶

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Le titre suit Conventional Commits avec scope kebab-case pertinent, et décrit précisément les changements : validation et application de corrections de traductions sur 16 locales.
Description check ✅ Passed La description contient tous les éléments du template : résumé détaillé avec justifications, plan de test complet, validation des corrections, sans artefacts visuels nécessaires pour des changements i18n.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/translations-validation-pass-pass

Comment @coderabbitai help to get the list of available commands and usage tips.

@InstaZDLL InstaZDLL added type: chore Maintenance size: xl > 500 lines labels May 26, 2026
@InstaZDLL InstaZDLL self-assigned this May 26, 2026
@InstaZDLL InstaZDLL enabled auto-merge (squash) May 26, 2026 00:28
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/i18n/locales/ar.json`:
- Around line 692-706: The Arabic translations use "أغنية" in
count_zero/count_one/count_other but "مقطع" in
upNext_zero/upNext_one/upNext_other, creating inconsistent terminology; pick one
term (e.g., change upNext_* to use "أغنية" to match count_*) and update the
values for upNext_zero, upNext_one, and upNext_other to use the same word and
placeholders (keep "{{count}}" and the existing "التالي" prefix), ensuring
plural forms remain consistent with the count_* keys.

In `@src/i18n/locales/fr.json`:
- Around line 427-435: Le bloc de traductions sous le namespace "liked" est
incohérent: vous avez adopté "Titres aimés / coups de cœur" pour
title/unlike/like mais emptyTitle et emptyDescription utilisent encore
"liké/likez"; mettez-les en accord en modifiant les clés emptyTitle et
emptyDescription pour employer la même terminologie (par ex. emptyTitle ->
"Aucun titre aimé" et emptyDescription -> "Les morceaux que vous aimez
apparaîtront ici. Explorez votre bibliothèque et ajoutez-les à vos coups de
cœur."), en gardant les clés existantes (emptyTitle, emptyDescription) pour
éviter de casser les références.

In `@src/i18n/locales/nl.json`:
- Around line 68-77: Update the Dutch translation for the key missingFields to
use the new term “Gedeeld geheim” so the form text matches
secretLabel/secretPlaceholder; locate the JSON entry for "missingFields" and
replace the phrase "secret" with "Gedeeld geheim" (e.g., make it read something
like "Vul API-sleutel, Gedeeld geheim, gebruikersnaam en wachtwoord in.") to
keep terminology consistent with secretLabel and secretPlaceholder.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 241fa0fb-bea0-4cb4-8f8b-b86a188d160e

📥 Commits

Reviewing files that changed from the base of the PR and between cefbe6e and 666426f.

📒 Files selected for processing (16)
  • src/i18n/locales/ar.json
  • src/i18n/locales/de.json
  • src/i18n/locales/es.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/hi.json
  • src/i18n/locales/id.json
  • src/i18n/locales/it.json
  • src/i18n/locales/ja.json
  • src/i18n/locales/ko.json
  • src/i18n/locales/nl.json
  • src/i18n/locales/pt-BR.json
  • src/i18n/locales/pt.json
  • src/i18n/locales/ru.json
  • src/i18n/locales/tr.json
  • src/i18n/locales/zh-CN.json
  • src/i18n/locales/zh-TW.json

Comment thread src/i18n/locales/ar.json
Comment thread src/i18n/locales/fr.json
Comment thread src/i18n/locales/nl.json Outdated
Three small consistency fixes flagged on PR #159 review:

- ar.json `queue.upNext_one/_other`: terminology drift between
  `count_*` ("أغنية") and `upNext_*` ("مقطع") inside the same
  namespace. Aligned `upNext_*` on "أغنية" — the active translation
  for the count fields plus the rest of the music-player surface.
- fr.json `liked.emptyTitle/emptyDescription`: rewrite kept
  `title/like/unlike` on "Titres aimés / Coups de cœur" but left the
  empty-state strings on franglais "liké / likez". Both now match the
  "aimés / coups de cœur" choice.
- nl.json `lastfm.missingFields`: the form's `secretLabel` /
  `secretPlaceholder` were already on "Gedeeld geheim" but the
  validation error still referenced the bare English "secret". Same
  noun across the form now.

Dry-run validation clean on all three locales afterwards.
@InstaZDLL
Copy link
Copy Markdown
Owner Author

InstaZDLL commented May 26, 2026

@coderabbitai Addressed all 3 findings in 0d7030a. All three verified valid against current code and fixed minimally.

ar.json queue.upNext_* — fixed
Confirmed the namespace drift: count_zero/_one/_other say "{{count}} أغنية" but upNext_one/_other were "{{count}} مقطع" — same noun-counter, two words. Aligned upNext_* on أغنية. count_* left as-is (it's the active translation across the rest of the namespace).

fr.json liked.emptyTitle/emptyDescription — fixed
Confirmed: title / like / unlike use "Titres aimés" / "Coups de cœur" but emptyTitle was "Aucun titre liké" and emptyDescription ended with "likez vos titres favoris" — same franglais I missed when applying the FR pass. Both now read "aimé / coups de cœur" to match the rest of the block.

nl.json lastfm.missingFields — fixed
Confirmed: secretLabel = "Gedeeld geheim", secretPlaceholder = "Je gedeelde geheim", but missingFields still listed the bare English "secret" in the error string. Updated to "Vul API-sleutel, Gedeeld geheim, gebruikersnaam en wachtwoord in." per the suggestion.

Dry-run validation clean on all three locales — 0 missing keys, 0 broken placeholders, 0 real extra keys.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

Tip

For best results, initiate chat on the files or code changes.

@InstaZDLL Fixes look spot-on — minimal, targeted, and consistent with the surrounding namespace in each locale. The dry-run being clean on all three is good confirmation. Merging looks safe from a translation-integrity standpoint.

🐇 ✨

@InstaZDLL InstaZDLL merged commit bd7ba3d into main May 26, 2026
13 checks passed
@InstaZDLL InstaZDLL deleted the chore/translations-validation-pass-pass branch May 26, 2026 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: frontend React/Vite frontend (src/) scope: i18n Translations (src/i18n/) size: xl > 500 lines type: chore Maintenance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant