Coverage, and how it grows
This project does not guess a locale into existence. A row below exists because someone wrote the rules down, cited a normative source for each one, and backed it with fixtures the conformance suite runs on every change. That is the only way a locale is added — including by you.
The same sentence, ten locales
German lowers the opening quote. Swiss German turns it into guillemets pointing outward. French
puts a no-break space inside them (U+00A0) and a narrow one before
! ? ; (U+202F). Finnish and Swedish close with the same glyph they open with.
British English swaps the primary and secondary levels round. Every one of these is correct — in
exactly one place.
Rendered by the engine from the inputs shown, not typed by hand. Regenerate with
npx tsx brand/tools/gen_examples.ts.
Coverage table
| Locale | Name | Rules cited | Fixtures | Primary sources |
|---|---|---|---|---|
| en-US | English (US) | dashes, ellipsis, hyphen, nbsp, quotes | 215 | Chicago Manual of Style; BIPM (SI units) |
| en-GB | English (UK) | dashes, ellipsis, hyphen, nbsp, quotes | 151 | University of Oxford Style Guide; BIPM (SI units) |
| de-DE | German (Germany) | dashes, hyphen, nbsp, quotes | 65 | Duden Rechtschreibregeln; DIN 5008 |
| de-CH | German (Switzerland) | dashes, hyphen, nbsp, quotes | 60 | Schweizerische Bundeskanzlei, Schreibweisungen |
| fr | French | dashes, hyphen, nbsp, quotes | 72 | Imprimerie nationale, Lexique; Jacques André, Petites leçons de typographie |
| fr-CA | French (Canada) | dashes, ellipsis, hyphen, nbsp, quotes | 33 | Office québécois de la langue française; Jacques André |
| ru | Russian | dashes, ellipsis, hyphen, nbsp, quotes | 83 | Мильчин & Чельцова, Справочник издателя и автора; Розенталь |
| fi | Finnish | dashes, ellipsis, hyphen, nbsp, quotes | 155 | Kotimaisten kielten keskus (Kotus), Kielitoimiston ohjepankki |
| sv | Swedish | dashes, ellipsis, hyphen, nbsp, quotes | 153 | Institutet för språk och folkminnen (Språkrådet), Snabba skrivregler |
| el | Greek | apostrophe, dashes, ellipsis, hyphen, nbsp, quotes, spaces, symbols | 28 | EU Interinstitutional Style Guide (Greek); Unicode Standard 17.0 |
Locale count and citations read directly from spec/locales/; fixture totals from
spec/fixtures/. en and de are aliases resolving to
en-US and de-DE (spec/rules/locale-resolution.md).
Italian is not in that table. Neither is Spanish, Polish, Portuguese, Japanese, Arabic or every other language this format could describe. That is not a roadmap with dates attached — it is simply what nobody has cited yet. There is no fixed cap on how many locales this project covers: coverage is a goal, and the only gate is evidence.
None of this is Italian-specific guidance; nothing below has been checked against an Italian style authority. It is the exact sequence anyone adds any locale through, illustrated with the locale this table is missing.
spec/schema/locale.schema.jsonIt defines what a locale file may say: quote glyphs and inner-space rule, the parenthetical and range dash convention, whether ellipsis abbreviates after terminal punctuation, hyphen-binding word lists, and the no-break-space triggers. Literal strings, literal code points, string lists and enum values only — no regex, no priority numbers, no conditionals. If Italian needs a distinction the schema can't express, that is a spec discussion, not a workaround in the locale file.
spec/locales/it.json
One field at a time, each backed by a citation in the mandatory sources
array — a national style guide, a standards body (Accademia della Crusca, a major dictionary
or publisher's house style), never a blog post or a contributor's own habit. A locale is
accepted only as the triple this table enforces: data, fixtures, citation.
spec/fixtures/it.json
One { "in", "out", "rule" } pair per behaviour the citation asserts, plus at
least one edge case per rule — the ordinary sentence is not the interesting test, the nested
quote or nasty numeric range is. Every fixture is automatically also an idempotency case:
transform(out) === out is checked for free.
spec/locales/registry.json
Add "it" to the locales array. Only add an alias (it-CH
→ it, say) if the fallback is itself a cited decision, not a guess of
convenience.
npm run validate:spec checks the file against the schema and NFC-normalizes it;
npm run gen && npm test runs the new fixtures through the conformance
suite and the fast-check idempotency property. Both must be green — a red run
blocks the locale, not just a warning.
Disagreements about what Italian actually does are settled by citation, not preference — if a review turns up a more normative source, that source wins, not whoever argued longer.
Rules are cross-locale algorithms, not per-language code. spec/rules/order.json is
the single source of truth for a rule's id, pipeline order, default and which locale fields it
reads; spec/rules/<id>.md is normative prose written before the
implementation — extracting a spec from a finished implementation is exactly the rework this
project's spec-first discipline exists to avoid. A behaviour change starts with a fixture in
spec/fixtures/, not a diff in src/rules/. Implementation constraints
that are already binding, even with one runtime shipped: no regex in a rule (Go's RE2 has no
lookbehind — a rule is a single left-to-right scan over code points with explicit lookaround),
index by Unicode code point rather than a native string, and rules emit edits for the
pipeline to apply rather than mutating text directly, so applyEdits can enforce the
contract instead of trusting it.