Coverage, and how it grows

Ten locales are cited. Everything else is uncovered, not unplanned.

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

Nobody agrees about quotation marks.

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.

English (US) · en-US
She asked, "Isn't this the shop they call 'round the corner'?" ... We'd walked - nearly 3 km - just to find it closed. Copyright (c) 2026; the print measures 40x60 cm.
She asked, Isnt this the shop they call round the corner? Wed walkednearly 3 kmjust to find it closed. Copyright © 2026; the print measures 40×60 cm.
English (UK) · en-GB
She asked, "Isn't this the shop they call 'round the corner'?" ... We'd walked - nearly 3 km - just to find it closed. Copyright (c) 2026; the print measures 40x60 cm.
She asked, Isnt this the shop they call round the corner? Wed walked nearly 3 km just to find it closed. Copyright © 2026; the print measures 40×60 cm.
German · de-DE
Sie fragte: "Ist das nicht der Laden namens 'an der Ecke'?" ... Wir liefen -- fast 3 km -- und fanden ihn leider geschlossen. Copyright (c) 2026, Format 40x60 cm, z. B. für Poster.
Sie fragte: Ist das nicht der Laden namens an der Ecke? Wir liefen fast 3 km und fanden ihn leider geschlossen. Copyright © 2026, Format 40×60 cm, z. B. für Poster.
Swiss German · de-CH
Sie fragte: "Ist das nicht der Laden namens 'an der Ecke'?" ... Wir liefen -- fast 3 km -- und fanden ihn leider geschlossen. Copyright (c) 2026, Format 40x60 cm, z. B. für Poster.
Sie fragte: «Ist das nicht der Laden namens an der Ecke?» Wir liefen fast 3 km und fanden ihn leider geschlossen. Copyright © 2026, Format 40×60 cm, z. B. für Poster.
French · fr
Elle a dit : "Ce n'est pas la librairie qu'on appelle 'le coin', si ?" ... On a marché - presque 3 km - pour la trouver fermée. Copyright (c) 2026 ; le tirage fait 40x60 cm.
Elle a dit : « Ce nest pas la librairie quon appelle le coin, si? » On a marché presque 3 km pour la trouver fermée. Copyright © 2026; le tirage fait 40×60 cm.
French (Canada) · fr-CA
Elle a dit : "Ce n'est pas la librairie qu'on appelle 'le coin', si ?" ... On a marché - presque 3 km - pour la trouver fermée. Copyright (c) 2026 ; le tirage fait 40x60 cm.
Elle a dit : « Ce nest pas la librairie quon appelle le coin, si? » On a marché presque 3 km pour la trouver fermée. Copyright © 2026; le tirage fait 40×60 cm.
Russian · ru
Она спросила: "Это не тот магазинчик, который называют 'за углом'?" ... Мы прошли - почти 3 км - и нашли его закрытым, а что-то достали из-под прилавка. Copyright (c) 2026, формат 40x60 см.
Она спросила: «Это не тот магазинчик, который называют за углом?» Мы прошли почти 3 км и нашли его закрытым, а чтото достали изпод прилавка. Copyright © 2026, формат 40×60 см.
Finnish · fi
Hän kysyi: "Eikö tämä ole se 'nurkan' kirjakauppa?" ... Kävelimme - lähes 3 km - ja löysimme sen kiinni. Copyright (c) 2026; tulosteen koko on 40x60 cm, hinta nousi 10,5 %.
Hän kysyi: Eikö tämä ole se nurkan kirjakauppa? Kävelimme lähes 3 km ja löysimme sen kiinni. Copyright © 2026; tulosteen koko on 40×60 cm, hinta nousi 10,5 %.
Swedish · sv
Hon frågade: "Är det inte affären i 'hörnet'?" ... Vi gick - nästan 3 km - och hittade den stängd. Copyright (c) 2026; trycket mäter 40x60 cm och kostar 10,5 % mer.
Hon frågade: Är det inte affären i hörnet? Vi gick nästan 3 km och hittade den stängd. Copyright © 2026; trycket mäter 40×60 cm och kostar 10,5 % mer.
Greek · el
Ρώτησε: "Δεν είναι αυτό το μαγαζί 'στη γωνία';" ... Περπατήσαμε -- σχεδόν 3 χλμ -- και το βρήκαμε κλειστό. Copyright (c) 2026, μέγεθος 40x60 cm.
Ρώτησε: «Δεν είναι αυτό το μαγαζί στη γωνία;» Περπατήσαμε -- σχεδόν 3 χλμ -- και το βρήκαμε κλειστό. Copyright © 2026, μέγεθος 40×60 cm.

Rendered by the engine from the inputs shown, not typed by hand. Regenerate with npx tsx brand/tools/gen_examples.ts.

Coverage table

Cited, not guessed.

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.

Adding a locale — worked through for Italian

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.

  1. Read spec/schema/locale.schema.json

    It 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.

  2. Write 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.

  3. Add cases to 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.

  4. Register it in spec/locales/registry.json

    Add "it" to the locales array. Only add an alias (it-CHit, say) if the fallback is itself a cited decision, not a guess of convenience.

  5. Validate and test

    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.

  6. Open a pull request

    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.

Changing or adding a rule

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.