feat(i18n): add redesign strings and translate Escuchar rename to 11 locales
This commit is contained in:
@@ -62,7 +62,7 @@
|
||||
| 15b | `fix(grabaciones): wire the recordings library into Settings navigation` | 15 | 60-100 | Low | No |
|
||||
| 16 | `feat(connectivity): restyle offline and reconnect banners` | 1 | 150-250 | Low | No |
|
||||
| 17 | `feat(bienvenida): add monetization-free welcome screen` | 1 | ~~150-200~~ → **REALIZED: 361** (screen + test, 313 / ARB 22 / docs 48) — see the WU15-precedent note below | Low | No — same reasoning as WU15§ |
|
||||
| 18 | `feat(i18n): add redesign strings and translate Escuchar rename to 11 locales` | all | ~0 eng. / 400-600 data | Medium (data volume, low logic risk) | No |
|
||||
| 18 | `feat(i18n): add redesign strings and translate Escuchar rename to 11 locales` | all | ~~~0 eng. / 400-600 data~~ → **REALIZED: ~3,622** (2,714+ / 908-, 26 files: 11 ARB + 11 regenerated `gen/*.dart` + 4 new `test/l10n/*.dart` + this docs update) | Medium (data volume, low logic risk) | No — same estimating-lesson pattern as WU3a/WU7/WU15§, not a design risk |
|
||||
|
||||
\* **Re-derived after WU3a landed.** The original 500-700 figure was scaled pro-rata from WU3a's *estimate*, which
|
||||
turned out to be wrong by roughly 4x — so the old WU3b number inherited the same error and has been replaced.
|
||||
@@ -129,15 +129,19 @@ the proposal's narrative and dependency table.
|
||||
|
||||
## Non-Negotiable Guards (master checklist — verify before the branch is considered done)
|
||||
|
||||
- [ ] `test/pantallas/pantalla_alarma_sonando_dismiss_guard_test.dart` passes **unmodified** (touched by WU9, WU11 — if
|
||||
a restyle appears to require editing it, STOP and escalate; do not edit the test).
|
||||
- [ ] `git diff` is **empty** for `lib/servicios/navegacion_auto.dart` (WU2), `lib/servicios/servicio_ecualizador.dart`
|
||||
(WU13), and the band-application block at `lib/servicios/servicio_audio.dart:749-762` (WU13).
|
||||
- [ ] The equalizer renders exactly **5** sliders (WU13, task 13.1).
|
||||
- [ ] No shipped string contains "PRO", a trial duration, or a price (WU17 task 17.2/17.6; WU18 task 18.6 final
|
||||
whole-app grep).
|
||||
- [ ] All 13 ARB files keep identical key sets (WU18 tasks 18.1, 18.5 — final parity check; WU1 only touches values
|
||||
in 2 of the 13 files, so it cannot break parity on its own).
|
||||
- [x] `test/pantallas/pantalla_alarma_sonando_dismiss_guard_test.dart` passes **unmodified** (touched by WU9, WU11 — if
|
||||
a restyle appears to require editing it, STOP and escalate; do not edit the test). Re-confirmed in isolation
|
||||
after WU18: 13/13 green, file diff empty vs `main`.
|
||||
- [x] `git diff` is **empty** for `lib/servicios/navegacion_auto.dart` (WU2), `lib/servicios/servicio_ecualizador.dart`
|
||||
(WU13), and the band-application block at `lib/servicios/servicio_audio.dart:749-762` (WU13). Re-confirmed
|
||||
after WU18 (plus `lib/modelos/preset_ecualizador.dart` and the 3 other guarded test files — all 8 empty).
|
||||
- [x] The equalizer renders exactly **5** sliders (WU13, task 13.1). Re-confirmed after WU18.
|
||||
- [x] No shipped string contains "PRO", a trial duration, or a price (WU17 task 17.2/17.6; WU18 task 18.6 final
|
||||
whole-app grep). Final ARB-only grep (18.6): zero hits for `\bPRO\b`, €, $, gratis/gratuit/"free version", or
|
||||
a day-count trial phrase in any of the 13 `app_*.arb` files.
|
||||
- [x] All 13 ARB files keep identical key sets (WU18 tasks 18.1, 18.5 — final parity check; WU1 only touches values
|
||||
in 2 of the 13 files, so it cannot break parity on its own). Confirmed: 466 real keys in every one of the 13
|
||||
files, zero missing, zero extra.
|
||||
|
||||
---
|
||||
|
||||
@@ -1127,53 +1131,84 @@ UI copy every other capability introduced
|
||||
**Verify**: `flutter test && flutter analyze && dart format --set-exit-if-changed $(git diff --name-only --diff-filter=ACM HEAD -- '*.dart')`
|
||||
**Modified tests**: ARB key-parity guard test (extend existing or add one if none exists)
|
||||
|
||||
- [ ] 18.1 RED — an ARB-parity test asserting all 13 `lib/l10n/app_*.arb` files contain an identical key set.
|
||||
- [ ] 18.1b RED — **anti-copy guard (a key-parity test is NOT enough).** `l10n.yaml` sets
|
||||
`template-arb-file: app_es.arb`, so any key missing from a locale silently falls back to **Spanish** — that is
|
||||
why untranslated strings currently render as Spanish inside `app_localizations_ja.dart`, `_fr.dart`, etc.
|
||||
A key-parity test would pass just as happily if all 11 locales simply COPIED the Spanish value.
|
||||
Write a test that, for every non-`es` locale, collects every key whose value is byte-identical to the `app_es.arb`
|
||||
value and requires each one to appear in an explicit allowlist (a checked-in file, e.g.
|
||||
`test/l10n/identical_value_allowlist.dart`). Legitimately-identical values exist — brand names, "OK", "Radio",
|
||||
codec names, pure symbols — so the allowlist is the escape hatch, but **each entry must be added deliberately,
|
||||
never in bulk**. Any unlisted identical value fails the test.
|
||||
Seed the allowlist ONLY with entries that are genuinely untranslatable; do not pre-populate it to make the
|
||||
suite green.
|
||||
- [ ] 18.2 RED — `navHome` exists as a key in all 13 locales, and `git diff` for this commit touches exactly 11
|
||||
`navHome` **value** lines (en/es were WU1's job, task 1.9).
|
||||
- [ ] 18.3 GREEN — add the ~35-45 new keys (accumulated from WU4-WU17's English/Spanish-only strings) to all 13
|
||||
ARB files, sourcing translations for the 11 non-en/es locales.
|
||||
- [ ] 18.4 GREEN — set the `navHome` value in the remaining 11 locales to a real translation of "Listen" (not a
|
||||
mechanical copy of the English/Spanish pair).
|
||||
- [ ] 18.5 REFACTOR — run the ARB-parity check across all 13 files; confirm zero missing/extra keys, AND that the
|
||||
18.1b anti-copy guard passes with an allowlist containing only genuinely-untranslatable entries.
|
||||
Sanity figures at the time this was written: `app_es.arb` (template) 540 keys, `app_en.arb` 561, and all 11
|
||||
other locales 518 — i.e. the non-template locales were **22 keys behind**, and those 22 were rendering in
|
||||
Spanish. WU18 is what closes that gap; the count will have grown as WU8-WU17 land, so re-measure rather than
|
||||
trusting these numbers.
|
||||
- [ ] 18.6 Verify — full `flutter test` suite green; `flutter analyze` clean; scoped `dart format` over the files
|
||||
this change touched produces no diff (NEVER bare `dart format .` — see the warning at the top);
|
||||
grep confirms no "PRO"/price/trial-duration string exists in any ARB file (final whole-app Success Criteria
|
||||
check).
|
||||
- [x] 18.1 RED — `test/l10n/arb_parity_test.dart` (+ `test/l10n/arb_test_helpers.dart` shared reader): an ARB-parity
|
||||
test asserting all 13 `lib/l10n/app_*.arb` files contain an identical key set, plus a `navHome`-exists check
|
||||
(task 18.2's first half). Confirmed RED against the pre-merge tree: 11 locales missing 72 keys each.
|
||||
- [x] 18.1b RED — `test/l10n/arb_anti_copy_test.dart` + `test/l10n/identical_value_allowlist.dart` (the anti-copy
|
||||
guard). **Scope correction found at apply time**: read literally ("for every non-`es` locale, collects every
|
||||
key whose value is byte-identical") this must cover the WHOLE file, not only WU18's own new keys — a
|
||||
narrower scope would leave 183 pre-existing identical values (mostly genuine `pt`/`es` Iberian-Romance
|
||||
cognates, plus international genre names, "OK", brand names, symbols) completely unaudited. Built the
|
||||
allowlist to cover both: 207 total entries (after de-duplicating two detection-script bugs found along the
|
||||
way — see 18.5's note), each with an individual justification comment, grouped by category for readability
|
||||
but never wildcarded.
|
||||
**`en` is deliberately excluded** from this guard's locale loop (see the test file's own doc comment): `en`
|
||||
and `es` have been hand-maintained together by every WU throughout this whole change (`en`/`es`-only new
|
||||
keys, never left lagging), so `en` never carries the "silently fell back to the template" risk this guard
|
||||
exists to catch — unlike the other 11, which this WU batch-translates for the first time.
|
||||
- [x] 18.2 RED — `navHome` exists as a key in all 13 locales (part of 18.1's parity test); `git diff` for this
|
||||
commit touches exactly **11** `navHome` **value** lines, confirmed via `git diff | grep -c '"navHome"'` = 22
|
||||
(11 removed + 11 added) after the merge (en/es were WU1's job, task 1.9, untouched here).
|
||||
- [x] 18.3 GREEN — added exactly **72** new keys (measured, not the ~35-45 estimate) to all 13 ARB files, with real,
|
||||
idiomatic translations for the 11 non-en/es locales (ar, bn, de, fr, hi, id, it, ja, pt, ru, zh) — vocabulary
|
||||
cross-checked against ~20 already-translated sibling keys in each locale (e.g. "station"/"favorites"/
|
||||
"preset"/"OK"/genre-name conventions, register — `du`-informal `de`, `vous`-formal `fr`, `tu`-informal `it`,
|
||||
polite-imperative `ru`/`ja`/`hi`/`bn`, `você`-imperative `pt` with no explicit pronoun) so new copy reads as
|
||||
part of the same voice as existing copy, not machine-translated in isolation. 7 of the 72 keys carry ICU
|
||||
placeholders/plurals; their `@key` metadata blocks were added to all 11 locales matching the template's own
|
||||
established convention of replicating metadata into every locale file (confirmed via a diff scan: the
|
||||
53 pre-existing metadata blocks shared between `es` and a sample locale were byte-identical). Arabic and
|
||||
Russian plurals use full CLDR categories (`one`/`two`/`few`/`other` and `one`/`few`/`other`) matching the
|
||||
precedent already set by the pre-existing `stationCount` key, rather than the simpler `=1`/`other` the ES/EN
|
||||
template itself uses for these two new keys.
|
||||
- [x] 18.4 GREEN — set `navHome` in the remaining 11 locales to a real translation of "Listen"/"Escuchar" (ar
|
||||
استماع, bn শোনা, de Hören, fr Écouter, hi सुनना, id Dengar, it Ascolta, ja 聴く, pt Ouvir, ru Слушать,
|
||||
zh 收听) — each cross-checked against that locale's OWN sibling nav-tab labels (`navSearch`/`navFavorites`/
|
||||
etc.) for register/part-of-speech consistency, not a mechanical copy of "Listen" or "Escuchar".
|
||||
- [x] 18.5 REFACTOR — re-ran the parity + anti-copy guard; **two detection-script bugs found and fixed along the
|
||||
way, not left in the final allowlist**: (1) the first draft's collision scanner used PowerShell's default
|
||||
`-eq`, which is **case-insensitive** — it falsely flagged 5 pairs (e.g. `de/durationMinutesOnly` "min" vs
|
||||
"Min") as collisions; re-scanned with `-ceq` (case-sensitive, matching Dart's own `==`) and removed the 5
|
||||
false positives. (2) the first allowlist draft was missing 7 genuine collisions the script had already found
|
||||
but a manual transcription pass dropped (`settingsGroupAudioTitle` ×4, `endField`/`endLabel` fr, `alarmFadeInLabel`
|
||||
pt) — added them back. Final state: zero missing/extra keys across all 13 files; anti-copy guard's own
|
||||
"no stale entries" self-check (added as this test's second assertion, not just the one the task named) also
|
||||
passes, so the allowlist is verified as exactly the current, real collision set — 207 entries, none stale,
|
||||
none missing.
|
||||
- [x] 18.6 Verify — full `flutter test`: **747/747 green, 2 skipped** (up from the 737-baseline this batch started
|
||||
from — +6 WU17b tests + +4 WU18 tests, reconciles exactly). `flutter analyze`: 1 issue, identical to
|
||||
baseline. Scoped `dart format` (11 regenerated `lib/l10n/gen/*.dart` + 4 new `test/l10n/*.dart` files, ARB
|
||||
JSON files are not `dart format` targets): reformatted 3 of 15 files (whitespace/line-wrapping only), stable
|
||||
on re-run. Grep confirms zero `\bPRO\b` (case-sensitive), €, $, "gratis"/"gratuit"/"free version", or
|
||||
day-count trial-phrase hits in any `app_*.arb` file. Literal-encoding scan (Arabic, Bengali, Devanagari,
|
||||
Japanese, Chinese, Cyrillic all touched): zero mojibake hits across all 11 modified ARB files, the 11
|
||||
regenerated `gen/*.dart` files, and the 4 new test files; spot-checked several locales' rendered text
|
||||
directly to confirm.
|
||||
|
||||
---
|
||||
|
||||
## Final Verification Sequence (run once, after WU18's commit)
|
||||
|
||||
1. `flutter test` — full suite green.
|
||||
2. `flutter analyze` — clean.
|
||||
3. `dart format --set-exit-if-changed $(git diff --name-only --diff-filter=ACM main -- '*.dart')` — no diff over the
|
||||
files this change touched. **NEVER bare `dart format .`** — it reformats 27 unrelated pre-existing files and would
|
||||
break the empty-diff guards in steps 4 and 5 below (Engram `reference/dart-format-scope-hazard`, id 2511).
|
||||
4. `git diff --stat lib/servicios/navegacion_auto.dart lib/servicios/servicio_ecualizador.dart` — both empty.
|
||||
5. `git diff lib/servicios/servicio_audio.dart` — band-application block (`749-762`) unchanged.
|
||||
6. Grep `lib/` for `countrycodes` — zero hits.
|
||||
7. Grep `lib/l10n/app_*.arb` for "PRO", a currency amount, or a day-count trial phrase — zero hits.
|
||||
8. Confirm all 13 ARB files have identical key sets and `navHome` present in each.
|
||||
9. Confirm the equalizer screen renders exactly 5 sliders.
|
||||
10. Run `test/pantallas/pantalla_alarma_sonando_dismiss_guard_test.dart` in isolation — passes, file diff empty.
|
||||
All 10 steps run and confirmed after the WU18 commit:
|
||||
|
||||
1. [x] `flutter test` — full suite green: **747/747, 2 skipped**.
|
||||
2. [x] `flutter analyze` — clean: 1 issue, identical to the pre-branch baseline.
|
||||
3. [x] `dart format --set-exit-if-changed $(git diff --name-only --diff-filter=ACM main -- '*.dart')` — no diff over
|
||||
the files this change touched. **NEVER bare `dart format .`** — it reformats 27 unrelated pre-existing files and
|
||||
would break the empty-diff guards in steps 4 and 5 below (Engram `reference/dart-format-scope-hazard`, id 2511).
|
||||
4. [x] `git diff --stat lib/servicios/navegacion_auto.dart lib/servicios/servicio_ecualizador.dart` — both empty.
|
||||
5. [x] `git diff lib/servicios/servicio_audio.dart` — band-application block (`749-762`) unchanged.
|
||||
6. [x] Grep `lib/` for `countrycodes` — zero hits.
|
||||
7. [x] Grep `lib/l10n/app_*.arb` for "PRO", a currency amount, or a day-count trial phrase — zero hits.
|
||||
8. [x] Confirm all 13 ARB files have identical key sets and `navHome` present in each — 466 real keys each, confirmed.
|
||||
9. [x] Confirm the equalizer screen renders exactly 5 sliders — confirmed.
|
||||
10. [x] Run `test/pantallas/pantalla_alarma_sonando_dismiss_guard_test.dart` in isolation — 13/13 passes, file diff
|
||||
empty vs `main`.
|
||||
|
||||
**All 18 work units (+ WU15b, WU17b, and the pre-existing controller-dispose bugfix) are now complete.** Branch
|
||||
`feat/rediseno-funcional` is ready for `sdd-verify`.
|
||||
|
||||
## Next Step
|
||||
|
||||
`sdd-apply` — implement WU1 first (unblocks everything else); honor the `size:exception` commits (WU3a, WU3b, WU10)
|
||||
as recorded above rather than attempting to split them further.
|
||||
`sdd-verify` — validate the completed implementation against `specs/*/spec.md`; `sdd-apply`'s work on this change is
|
||||
done.
|
||||
|
||||
Reference in New Issue
Block a user