Browse pages
Localization
Localization makes routes, messages, formatting, metadata, and tests locale-aware while stored Domain values remain locale-neutral.
Intent#
Localization makes routes, messages, formatting, metadata, and tests locale-aware while stored Domain values remain locale-neutral.
Activation#
Activation scope: project.
Applicable specification kinds: None.
The consumer enables locale when the product supports more than one locale. A possible future translation does not activate it. The product brief or decision records locales, default locale, fallback behavior, and URL strategy.
Baseline relationship#
This extension replaces no baseline rule.
This extension switches on no record type.
Standards#
Record supported locale behavior#
ruleguidanceRequirement A localization decision MUST list supported locales, default locale, fallback chain, user selection, browser detection, owner, and status.
Rationale One decision defines the product's locale contract before catalogs and routes appear. A draft names its decider and decide-by date.
Avoid catalog-only locale claims#
ruleguidanceRequirement A product MUST NOT infer supported locales from catalog files alone.
Rationale Catalog presence cannot define routing, fallback, selection, or browser-detection behavior.
Define one locale route shape#
ruleguidanceRequirement A localized application MUST define one documented locale route shape.
Rationale One shape gives users, crawlers, and links a predictable localized address. A path segment is the default shape. It gives every localized page a distinct address for links, crawlers, and cache entries. A cookie or header shape serves several locales from one address, so a shared cache and a search index see one of them. An application with no public pages, whose locale is a property of the signed-in account, documents one of those shapes instead.
Example /nl/orders/42 places the locale in the documented path segment, so a crawler and a shared cache each address one language.
Handle unavailable locale segments#
ruleguidanceRequirement A localized application MUST redirect unsupported or missing locale segments according to product policy.
Rationale The policy identifies the fallback or error behavior for an unavailable route locale.
Avoid duplicate localized URLs#
ruleguidanceRequirement A localized application MUST NOT publish multiple indexable URLs for the same localized content.
Rationale Duplicate indexable locations split search and canonical-link behavior.
Store user-facing copy in catalogs#
ruleguidanceRequirement A localized application MUST store user-facing copy in locale catalogs.
Rationale Catalogs separate translated wording from application behavior and source code.
Name messages by meaning#
ruleguidanceRequirement A locale catalog MUST use semantic keys that cite Term records rather than source-language sentences.
Rationale A meaning-based key remains stable when one language changes wording.
Example orders.cancel.confirmation identifies intent without copying the English sentence.
Complete or fall back catalog values#
ruleguidanceRequirement Each supported locale MUST contain required keys or use its declared fallback.
Rationale A declared fallback prevents missing copy from becoming an unreviewed runtime behavior.
The declaration states the fallback locale and what a missing key does at build time. A key missing from the default locale fails the build. No fallback exists for it, and the interface renders its identifier. A key missing from a non-default locale reports a warning and falls back. Shipping one untranslated string costs less than blocking a release on it.
Example A catalog check runs in the frontend lint gate. The two outcomes are visible before review, not in a browser.
Follow the validation message grammar#
ruleguidanceRequirement A validation catalog MUST state the field label, what is wrong, and what is accepted, without technical wording.
Rationale The shape holds in every language. Each language's sentence pattern lives on the field's Term labels and the language's writing page.
Example The Term record for a field carries the sentence pattern for each supported language.
Resolve every shown identifier#
ruleguidanceRequirement A screen MUST resolve every closed-set code it renders to its Term record label and never render the raw code, excluding user-facing reference numbers.
Rationale The code is a contract value. The Term label is copy. A resolution value, a refusal ground, a role code, or a billing state carries its label beside the rest of the screen's copy.
Example A shipment row shows the Term label for shipment-delayed in the active locale.
Format values with active locale#
ruleguidanceRequirement A localized interface MUST format dates, times, numbers, currency, plurals, lists, and relative time by active locale.
Rationale User-facing formatted values need the selected locale's conventions.
The platform supplies all of them. The Intl namespace has DateTimeFormat, NumberFormat, PluralRules, ListFormat, and RelativeTimeFormat. Each one carries the locale data the browser already ships. A project-written formatter for any of these is a second locale database that no one updates. Its plural rules are wrong for the first language with more than two forms.
Example Create one formatter instance per locale and reuse it. Construction is the expensive part.
Preserve locale-neutral business data#
ruleguidanceRequirement Domain values and API contracts MUST remain locale-neutral unless a use case explicitly exchanges localized content.
Rationale Stable business values and wire contracts do not change with interface language.
Localize public presentation content#
ruleguidanceRequirement Public metadata, form labels, validation messages, and user-safe errors MUST follow the active locale.
Rationale Visible content needs the same locale behavior as the page that presents it.
Keep stable error codes locale-neutral#
ruleguidanceRequirement A stable API error code MUST NOT change by locale.
Rationale Programmatic consumers need one code regardless of the caller's presentation locale.
Conventions#
Use one catalog root#
conventionguidanceDefault Keep catalogs under one application-owned locale root.
Replacement A consumer records a departure as an Exception record with reason and review date.
Rationale One root makes ownership and catalog discovery predictable.
Split catalogs by module when needed#
conventionguidanceDefault Split catalogs by module only when catalog size requires it.
Replacement A consumer records a departure as an Exception record with reason and review date.
Rationale Module splitting follows a measured size boundary instead of early fragmentation.
Use BCP 47 identifiers#
conventionguidanceDefault Use BCP 47 locale identifiers.
Replacement A consumer records a departure as an Exception record with reason and review date.
Rationale BCP 47 gives routes, catalogs, and selection one familiar identifier form.
Keep locale selection explicit#
conventionguidanceDefault Keep locale selection in the URL or documented session preference.
Replacement A consumer records a departure as an Exception record with reason and review date.
Rationale Explicit selection avoids an implicit global locale that callers cannot inspect.
Dependencies#
No library is selected by this extension. A localization package needs a decision and manifest pin.
Verification#
| ID | Mark | Evidence |
|---|---|---|
| litespec/ext/locale#record-supported-locale-behavior | guidance | Does the decision list locales, default, fallback, selection, owner, and status? |
| litespec/ext/locale#avoid-catalog-only-locale-claims | guidance | Is supported-locale evidence the decision rather than catalog files? |
| litespec/ext/locale#define-one-locale-route-shape | guidance | Does the application define and use one locale route shape? |
| litespec/ext/locale#handle-unavailable-locale-segments | guidance | Do unsupported or missing locale segments follow product policy? |
| litespec/ext/locale#avoid-duplicate-localized-urls | guidance | Is there one indexable URL per localized content item? |
| litespec/ext/locale#store-user-facing-copy-in-catalogs | guidance | Is user-facing copy stored in locale catalogs? |
| litespec/ext/locale#name-messages-by-meaning | guidance | Do catalog keys cite Term records instead of source sentences? |
| litespec/ext/locale#complete-or-fall-back-catalog-values | guidance | Does each locale resolve required keys or use its declared fallback? |
| litespec/ext/locale#follow-the-validation-message-grammar | guidance | Does each validation message state label, fault, and accepted input? |
| litespec/ext/locale#resolve-every-shown-identifier | guidance | Does each shown code render its Term label rather than the raw code? |
| litespec/ext/locale#format-values-with-active-locale | guidance | Are dates, numbers, currency, plurals, lists, and relative time localized? |
| litespec/ext/locale#preserve-locale-neutral-business-data | guidance | Do Domain values and API contracts stay locale-neutral? |
| litespec/ext/locale#localize-public-presentation-content | guidance | Do metadata, labels, validation, and safe errors follow the active locale? |
| litespec/ext/locale#keep-stable-error-codes-locale-neutral | guidance | Is each stable error code identical across locales? |
| litespec/ext/locale#use-one-catalog-root | guidance | Do catalogs sit under one owned root or record an Exception? |
| litespec/ext/locale#split-catalogs-by-module-when-needed | guidance | Is each module split justified by size or is an Exception recorded? |
| litespec/ext/locale#use-bcp-47-identifiers | guidance | Are locale identifiers BCP 47 or is an Exception recorded? |
| litespec/ext/locale#keep-locale-selection-explicit | guidance | Is selection in the URL or a documented session preference? |