Skip to content

Unify translations, plurals and number/date formats (T13: IN-02, IN-05, IN-06, IN-08, IN-09, IN-10, IN-12, IN-13, IN-15) - #223

Merged
Programcode merged 6 commits into
mainfrom
fix/t13-translations-glossary
Oct 23, 2026
Merged

Programcode merged 6 commits into
mainfrom
fix/t13-translations-glossary

Conversation

@Programcode

Copy link
Copy Markdown
Owner

Summary

T13 from the 22 Oct 2026 QA report on prod, the last translation batch. HU and ES now say the same thing as EN in the Terms sign-in sentence, each language uses one name per tool, role and format, counts take plural forms, and numbers and dates follow the interface language. A new test catches Spanish or Hungarian values left identical to English.

Per issue

IN-02 (Medium): HU Terms said sign-in is by an emailed link (legal text)

Only the sign-in clause of termsPage.p3 changed. The rest of each paragraph is byte-identical to main.

- HU: Google-lal, e-mailben kapott bejelentkezési hivatkozással vagy adminisztrátor által kiadott demókóddal jelentkezhetsz be. A demókódok ideiglenes hozzáférést adnak egy kijelölt fiókhoz. Felelős vagy a fiókod alatt végzett minden tevékenységért.
+ HU: Google-lal, e-mailben kapott hatjegyű kóddal vagy adminisztrátor által kiadott demókóddal jelentkezhetsz be. A demókódok ideiglenes hozzáférést adnak egy kijelölt fiókhoz. Felelős vagy a fiókod alatt végzett minden tevékenységért.
- ES: Puedes iniciar sesión con Google, mediante un enlace enviado por email o con un código demo emitido por un administrador. Los códigos demo proporcionan acceso temporal a una cuenta designada. Eres responsable de toda la actividad de tu cuenta.
+ ES: Puedes iniciar sesión con Google, con un código de seis dígitos enviado por email o con un código demo emitido por un administrador. Los códigos demo proporcionan acceso temporal a una cuenta designada. Eres responsable de toda la actividad de tu cuenta.

ES had the same "link" wording, so it changed too. EN p3 reads "You may sign in with Google, email-based sign-in, or an admin-issued demo code." It doesn't name the six digits. HU and ES now name the code, which is the real flow. LoginPage.tsx asks for six digits and supabase/config.toml sets otp_length = 6. EN was not part of the approval, so I left it alone. Aligning EN to "a six-digit code sent by email" would be a small follow-up. Both review rounds checked these sentences against EN and found them acceptable.

IN-05 (Low): one glossary per language

The glossary is now in docs/standards/ui.md, and the catalogs follow it:

Concept EN ES HU
Crossfire Crossfire Interrogatorio Keresztkérdezés
Sparring Sparring Sparring Vitapárbaj
Timer Timer Cronómetro Időmérő
Case Case Caso Eset (Vitaeset in titles)
Ruthless Ruthless Despiadado Kíméletlen
School format School 4-6-6-3 Formato escolar 4-6-6-3 Iskolai 4-6-6-3
School-format roles Introductor, R1, R2, Conclusor Introductor, R1, R2, Conclusor Bevezető, R1, R2, Záró
Sparring turn sides Pro, Con a favor, en contra Pro, Kontra
Competition formats Public Forum, Lincoln-Douglas, Policy, British Parliamentary, World Schools, Asian Parliamentary same as EN same as EN
Load / Loading Load / Loading Cargar / Cargando Megnyitás / Betöltés
AI AI IA MI
  • Roles. HU Sparring said "Pro Introductor / Pro Conclusor", the Timer said "Bevezető / Összegző" and Generate said "Bevezető / Záró". All now use Bevezető and Záró. Záró avoids clashing with the PF "összegzés" (summary).
  • Formats.
    • Competition format names stay in English in every language, as the free /tools pages and the SEO titles already did. A few of these were translated before and are now English on purpose: ES/HU debate.formats.bp and HU debate.formats.policy. This is deliberate, not a regression. HU Sparring "Public Forum · 8 beszéd" and the Timer's "Nyilvános fórum" now match. So do ES "Foro público", "Política" and "Parlamentario británico", and HU "Politikai", "Szakpolitikai" and "Brit parlamenti".
    • The Timer's "Standard (4-6-6-3)" is now "School 4-6-6-3", the name Sparring and /tools use.
  • Pairs.
    • ES Contrainterrogatorio is now Interrogatorio.
    • ES Temporizador is now Cronómetro.
    • ES Implacable is now Despiadado.
    • HU Kegyetlen is now Kíméletlen.
    • HU Esetépítés (as a saved-item kind) is now Eset.
    • HU Edzőmeccs is now Vitapárbaj.
    • HU időzítő is now időmérő in the tools page titles.
    • HU "Eset generátor" and "Eset támadó" are now Esetgenerátor and Esettámadó.
  • Load vs Loading (HU). The Load buttons on Flowchart and History are now "Megnyitás". "Betöltés" stays for loading states.
  • Format lists. The set of formats per tool can't be unified in the client. The Current Debate list (custom, bp, policy, classroom) is a Zod enum in packages/core that the ai Edge Function also enforces, and Sparring has turn tables for exactly three formats. Changing either needs an Edge Function change, which this batch excludes. The names are now the same everywhere.

IN-06 (Low): HU grammar

  • "A írásstílust" is now "Az írásstílust".
  • "Kérdezd az edződ" is now "Kérdezd az edződet".
  • "Ez a URL" is now "Ez az URL".
  • A sweep of a/az before vowels in both HU catalogs found nothing else ("A oldal" is "Side A").

IN-08 (Low): number separators, gender, duplicate card names

  • Separators. CLDR leaves four-digit numbers ungrouped in Spanish and Hungarian, so formatNumber now uses useGrouping: 'always'. The Sparring counter reads 40/1.200 (ES) and 40/1 200 (HU). Engines that don't know 'always' treat it as true, which is the old behaviour.
  • Gender. ES "contra una oponente" is now "contra un oponente", as in the rest of the catalog.
  • Duplicate names. The ES landing preview showed "Respuesta" on two cards (Answer and Response). Response is now "Réplica" in ES and "Reagálás" in HU.

IN-09 (Nit): HU "MI" vs "AI", DebateLab suffixes

  • MI. Every HU UI string now says MI, with hyphenated compounds (MI-kontextus, MI-modellek, MI-válaszok, MI-keret, MI-ellenfél). "MI-kimenet nyelve" is now the one wording in Settings and the language switcher.
  • Suffixes. DebateLab takes back-vowel suffixes without a hyphen: DebateLabba, DebateLabban, DebateLabhoz, DebateLabot. The catalog mixed both harmonies. Back harmony matched the majority, and it is the form the Terms already use ("DebateLabot"), so no legal text changed for it.
  • Not changed. The Privacy and Terms pages still have a few unhyphenated "MI" compounds ("MI feldolgozás", "MI kimenetek"). They are legal text, which this batch changes only for IN-02.

IN-10 (Low): count strings had no plural forms

  • Every number + noun concatenation now goes through i18next plurals with count:
    • Library summary and badge
    • Library word counts
    • History chat message counts
    • Shared page view count
    • Attack severity counts
    • Factoids found/verified
    • Current Debate counts on Home, the debate page and the debate menu, through debateCountsLabel in CurrentDebateStrip.tsx
  • Keys that already had _one/_other were fine. src/test/i18n-keys.test.ts already enforces the suffixes for literal count calls.
  • Test: src/test/i18n.test.ts checks "1 source" / "2 sources", "1 fuente" / "2 fuentes", "1 forrás" / "2 forrás", and the composed debate counts in all three languages.

IN-12 (Low): untranslated values

  • Translated. The HU length "Standard" is now "Normál", HU "Admin" is "Adminisztráció", ES "Admin" is "Administración" and ES "Info:" is "Información:". The format names above changed too.
  • New test. src/test/i18n-untranslated.test.ts lists every ES/HU value identical to English, in both namespaces. It fails on anything not on its allowlist, and also on allowlist entries that are no longer identical. The allowlist is grouped by reason:
    • product, plan and file-format names
    • competition format names
    • Policy speech codes and school-format role codes
    • motion wording and paper size
    • exordio and units
    • Sparring as the Spanish tool name
    • Spanish words spelled like English (Error, General, Formal, Neutral, Pros, Chats, Social, Debate, Introductor, Conclusor…)
    • one Hungarian word ("Sport")
  • Counts. Counting the test's way (at least two letters outside placeholders), main had 59 such ES values and 35 HU, with no record of which were intended. The QA report's 41 and 15 used a different count. Now 61 ES and 34 HU remain, and every one is on the allowlist with a reason. The ES total went up because the competition format names now stay in English on purpose.

IN-13 (Nit): dd/mm/yyyy, decimals, "N/A"

  • Dates. They name the month: "23 Oct 2026" (EN), "23 oct 2026" (ES), "2026. okt. 23." (HU), with the time appended for date-times.
  • Decimals. The new formatDecimal covers Generate and Ask durations and admin costs and rates ("1,5 s" in ES and HU).
  • N/A. The new common.notAvailable key translates it: N/A, N/D, nincs adat. It is the default fallback in date-format.ts and replaces the literal in PDF export.
  • Side badge. History's saved-case badge now shows the translated side ("A favor", "Mellette") instead of the raw "PRO".
  • Test: src/test/date-format.test.ts covers numbers, decimals, dates and the fallback per language.

IN-15 (Nit): ES placeholders

  • Ask placeholder. At 375 px the Ask input leaves 131 px for text. I measured candidates in the app font in Chromium.
    • ES "Pregunta a tu coach de debate..." is now "Pregunta algo…" (119 px).
    • HU "Kérdezd a vitaedződ..." is now "Mit kérdeznél?" (110 px). It was clipped the same way.
  • "ej., ". "ej., " and "p. ej., " are now "p. ej. " in all seven ES example placeholders.
  • Left open, EN. The English placeholder "Ask your debate coach..." (190 px) also clips at 375 px. I left it, because about 15 e2e specs, the verify recipes and the production canary find the Ask box by that text.

Verification

GitHub Actions minutes are used up, so these are local runs of the full npm run verify, not a CI pass. Verify passed at all three heads: 649f2cd7 (first version), c3ddf907 (round 1 fixes) and ca589e10. ca589e10 is the PR head: the round 2 fixes plus a normal merge of origin/main at 073dd08d (#220, no shared files). At ca589e10:

  • docs:check, lint (eslint, knip, repo rules), typecheck: pass
  • npm test: 88 files, 634 tests passed
  • test:collaboration: 5 files, 30 tests passed
  • test:edge: 457 passed, 0 failed
  • build (vite build, prerender of all 10 public pages, sitemap, site check, build boundaries): pass
  • test:sw: all checks true, including languageSwitchOffline and publicPagesKeepTheirOwnHtml
  • test:e2e:smoke: 47 passed

I reran the specs whose pinned strings this branch changes on desktop and mobile Chromium: e2e/hungarian-parity, localization, first-run, sparring and authed-pages. At ca589e10, 112/112 passed. The first run there failed 4 mobile tests with "Executable doesn't exist", because another process had deleted the shared ~/.cache/ms-playwright mid-run. I reinstalled Chromium with the repo's pinned Playwright (no --force), and the rerun passed. Earlier at 649f2cd7, this run caught one real failure: on mobile, the HU parity spec's "Megnyitás" lookup also matched "Menü megnyitása". It now uses exact: true.

The verify recipe .claude/skills/verify-debatelab/recipes/localization.spec.ts changed only in a comment, the old HU login title. Its assertion reads hu.login.title from the catalog. I didn't rerun it, and I didn't take the shared stack lock.

Screenshots. 42 captures at 375 and 1280 px in EN, ES and HU, taken at 649f2cd7. They are kept locally in .verify/artifacts/t13-evidence/, because gh can't attach them. They come from a credential-free Playwright run on this worktree's port with a stubbed session; only the debates, current_debates, sources and source_folders reads are stubbed. They prove the client only. The later review fixes changed one string on these screens: HU Library now says "Az MI-válaszok…" with a hyphen. In the Sparring setup shots the turn list is collapsed, so the new HU role names show in the format description line, not as turn labels. The captures show:

  • /terms section 3 in all three languages.
  • Sparring setup.
    • counter 40/1,200 (EN), 40/1.200 (ES), 40/1 200 (HU)
    • format list "Formato escolar 4-6-6-3 · 8 intervenciones / Lincoln-Douglas · 5 / Public Forum · 8"
    • HU "Iskolai 4-6-6-3 · 8 beszéd" with the description "bevezető, R1, R2 és záró beszéd"
    • difficulty "Despiadado" / "Kíméletlen"
  • Generate role select: "Bevezető (4 perc)".
  • Library.
    • 1 source: "1 source · 1 active · 1 folder" with the badge "1 source".
    • 2 sources: "2 forrás · 2 aktív · 1 mappa".
    • Dates: "23 Oct 2026" / "2026. okt. 23.".
  • Ask placeholder at 375 px: ES "Pregunta algo…" fits with no clipping.

Review rounds (fresh-context Claude subagent, claude-opus-5-5, full diff against main)

  1. Round 1. 0 High, 1 Medium, 3 Low, 4 Nit.
    • Medium, fixed: the agentic language judge (agentic/pages.e2e.ts) didn't exempt the English format names. No replay entry embeds that text, so nothing needed re-recording.
    • Fixed: the missing space after the bullet in History, the HU MI- hyphenation and the single output-language wording, the drifted onboarding.readyDesc, the admin zero cost, the memoized word count and "Időmérő-kijelző".
    • Rejected: deleting attackResults.critical/major/minor. discuss.ts reads them through a dynamic key.
    • HU/ES p3: acceptable.
  2. Round 2. 0 High, 0 Medium, 2 Low, 5 Nit. The round 1 fixes held, and HU/ES p3 were acceptable again.
    • Lows, fixed:
      • Remaining HU "MI" compounds on the landing page: "MI-szkennelés", "MI-promptba".
      • "Exa-val" is now "Exával".
      • "Esetstruktúra", "Esettámadás-elemzés" and "Az ellenfél várható esete".
      • "vitapárbaj-forduló" in eight History and What's New strings.
    • Nits, fixed:
      • The flowchart dialog says "Nyiss meg", matching the Megnyitás button.
      • The Sparring round says "nincs időmérő".
      • formatDecimal caches its formatters.
      • The glossary notes that the Timer spells out R1 and R2.
    • Nits, left open (below): "Standard (4-6-6-3)" in the generated SEO page, and ES _many plural forms.

Left open

  • EN Terms p3 doesn't mention the six digits (see IN-02). Changing it is a legal-text change that wasn't approved.
  • EN Ask placeholder clips at 375 px (see IN-15). Changing it needs the specs and canary that locate the Ask box by placeholder moved to its label.
  • Legal-text HU "MI" compounds in Privacy and Terms are unhyphenated (see IN-09).
  • Agentic tests weren't run. They need the shared stack and live model keys. agentic/pages.e2e.ts changed only in its exemption text. It uses only agent.assert, which isn't cached, so no replay entry needs re-recording.
  • Generated SEO page. public/online-debate-timer/index.html and scripts/seo_guides.py still say "Standard (4-6-6-3)". The app now says "School 4-6-6-3". Those pages are generated SEO content, outside this batch.
  • Spanish _many plurals. i18next 23 uses the many category for Spanish counts of 1,000,000 and up, and no ES plural in the catalog has a _many form. This predates the batch, and no count in the app gets that large.

To check on the Vercel preview or staging

  • ES and HU in a real phone browser. The Ask placeholder fits at 375 px, and the Sparring counter shows the grouped limit. Safari and WebKit weren't run locally. On Safari 15.3 and older, useGrouping: 'always' falls back to locale grouping, which shows 1200.
  • History with real saved chats and cases: message counts and translated side badges.

No migrations, no Edge Function changes, and no billing or workspace-invite code touched.

🤖 Generated with Claude Code

Programcode and others added 6 commits October 23, 2026 11:37
IN-02: the HU and ES Terms say sign-in uses a six-digit code sent by
email, not a link.
IN-05: one glossary per language for tools, roles and formats, kept in
docs/standards/ui.md. Competition format names stay in English.
IN-06, IN-09: HU article and case fixes, MI instead of AI, and one
suffix form for DebateLab.
IN-08, IN-13: numbers group four-digit values in ES and HU, dates name
the month, decimals use the language separator, N/A is translated.
IN-10: count strings go through i18next plurals.
IN-12: a test lists ES/HU values identical to English, with an
allowlist of intended ones.
IN-15: shorter ES Ask placeholder; "p. ej." without the stray comma.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At 375 px the Ask input leaves 131 px for text. The new placeholders measure 119 px (ES) and 110 px (HU) in the app font.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On mobile, 'Menü megnyitása' also contains 'megnyitás', so the substring match found two buttons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Exempt the English competition format names in the agentic language judge; restore the space after the bullet in History chat rows; hyphenate HU MI- compounds outside the legal pages and use one wording for the AI output language; retranslate onboarding.readyDesc from the current English; localize the admin zero cost; memoize the Library draft word count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hyphenate the remaining HU MI- and vitapárbaj-forduló compounds, join Esetstruktúra and Esettámadás-elemzés, use Exával, say Megnyitás and időmérő in the flowchart dialog and Sparring round, cache formatDecimal formatters, and note in the glossary that the Timer spells out R1 and R2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 23, 2026 12:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Oct 23, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Next included review available in 21 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 073dd08 and ca589e1.

📒 Files selected for processing: 32
  • .claude/skills/verify-debatelab/recipes/localization.spec.ts
  • agentic/pages.e2e.ts
  • docs/standards/ui.md
  • e2e/first-run.spec.ts
  • e2e/full-stack/first-run.spec.ts
  • e2e/hungarian-parity.spec.ts
  • e2e/localization.spec.ts
  • src/components/features/ask/AskChat.tsx
  • src/components/features/attack/AttackResults.tsx
  • src/components/features/debate/CurrentDebateMenu.tsx
  • src/components/features/debate/CurrentDebateStrip.tsx
  • src/components/features/factoids/FactoidsResults.tsx
  • src/components/features/generate/GenerateResults.tsx
  • src/lib/date-format.ts
  • src/lib/pdf-export-utils.ts
  • src/locales/en.json
  • src/locales/es.json
  • src/locales/hu.json
  • src/locales/tools/es.json
  • src/locales/tools/hu.json
  • src/pages/AdminPage.tsx
  • src/pages/CurrentDebatePage.tsx
  • src/pages/HistoryPage.tsx
  • src/pages/HomePage.tsx
  • src/pages/LibraryPage.tsx
  • src/pages/SharedPage.tsx
  • src/test/a11y/names-and-headings.test.tsx
  • src/test/components/LimitReachedModal.test.tsx
  • src/test/components/SubscriptionStatus.test.tsx
  • src/test/date-format.test.ts
  • src/test/i18n-untranslated.test.ts
  • src/test/i18n.test.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.

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

@Programcode
Programcode merged commit 2ac31e6 into main Oct 23, 2026
3 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants