Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

08 — Form Specifications (i18n Module)

Forms in the (planned) translation console: New Key, Key Editor (per-locale fields), Add Locale, Sync export. Validation derives from the live service contract (i18n.service.ts:32-45) so the editor can never author a string the runtime can't render.


1. New Key form (/admin/i18n/keys/new) (planned)

FieldTypeRequiredConstraints / validation
keyAppTextField (mono)yes/^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)*$/; unique; ≤ 120 chars; namespace hint errors. leave. announcement.
paramsParamsChips (editable)notokens match \w+; deduped; order-insensitive
en valueAppTextField multilineyesplaceholder self-check: every {token} in value ⊆ declared params (else block); { } escaping not supported (literal {{ unsupported — must match runtime regex \{(\w+)\})
other localesAppTextFieldnosame placeholder check once en exists; empty allowed → missing

Submit

  • POST /api/v1/i18n/keys (planned) → 201 → navigate to Key Editor.
  • Duplicate key → 409 inline "key exists" + "Open existing".
  • Offline → banner; values preserved (in-memory draft).

Error messages (translated themselves)

Form errors must use i18n keys (errors.validation etc.) — the console is dogfooding the module.


2. Key Editor — per-locale field validation (the critical contract)

RuleEnforcementSource of truth
Placeholder parityevery locale's {token} set == en source seti18n.service.ts:42-44 (/\{(\w+)\}/g)
Missing paramvalue contains {days} not in source → error: runtime would print literal {days} (i18n.service.ts:43)runtime fallback behavior
Extra paramvalue uses {x} absent from source → amber warn (translator added token runtime won't fill)same regex
Empty value in shipped localeerror, block savetranslate() would return '', breaking never-empty fallback (i18n.service.ts:40)
Key immutabilitykey read-only in editor; rename = delete + create (planned)
Lengthwarn > 200 chars (push payload limits (forward-looking))

Save flow

PUT /api/v1/i18n/keys/:key (planned) with { values: { <locale>: string } }. Optimistic; on 409 conflict (stale version) → dialog "Reload or overwrite" (06 §2).


3. Add Locale form (/admin/i18n/locales) (planned)

FieldTypeRequiredValidation
locale tagselect from SUPPORTED_LOCALES minus shippedyesmust be in i18n.service.ts:11-21
directionread-only "LTR" (all current locales LTR)RTL (forward-looking)
nameAppTextField (native endonym)yesnon-empty, ≤ 40 chars

Submit → creates empty catalog → all keys missing → drift flow (03_User_Journey.md §J5).


4. Sync export (/admin/i18n/sync) (planned)

FieldDetail
FormatCSV: key, en, hi, ta, …, status
Filtermissing-only / all / placeholder-drift-only
Deliverydownload; Crowdin upload is (planned) per IMPLEMENTATION_PLAN.md:845

5. Runtime parity guarantee

Whatever the editor allows, runtime behavior is fixed:

  • unknown key → returns key literal (i18n.service.ts:40, spec i18n.service.spec.ts:44-46)
  • unknown locale → English catalog (i18n.service.spec.ts:48-51)
  • missing param → literal {name} retained (i18n.service.ts:43)

The console must therefore treat en as immutable source-of-truth for params and all other locales as derived — enforced by §2 rules and the CI drift check (planned).