Skip to content

Canadian French (fr-CA) as its own locale, not a fallback - #39

Merged
shockalotti merged 5 commits into
Calnode:mainfrom
distronode-corporation:feat/fr-ca-locale
Sep 21, 2026
Merged

shockalotti merged 5 commits into
Calnode:mainfrom
distronode-corporation:feat/fr-ca-locale

Conversation

@distronode-com

Copy link
Copy Markdown
Contributor

First of the features split out of #30, in the order of appetite you described on that thread.

fr-CA currently resolves to the France copy through the primary-subtag fallback. The differences are not stylistic:

fr fr-CA
email e-mail courriel
reschedule reprogrammer / reprogrammation reporter / report
personal data données personnelles renseignements personnels
before ! ? ; narrow no-break space no space
July, abbreviated juil. juill.

The third row is the one that matters most: renseignements personnels is the statutory term in Quebec, so the France word is wrong in a legal sense rather than a register one. The last row is CLDR's own disagreement, not a preference, which is why TestDateTablesMatchCLDR catches it.

The only structural point

This is the first regional locale. Resolve already prefers an exact tag before falling back to the primary subtag, so no matcher change was needed — but that means the risk is not in the new locale, it is in the eight that already work. A visitor sending fr-FR or plain fr must be untouched by this file existing.

TestResolve now pins both directions:

{"Canadian French resolves to its own locale", "fr-CA,fr;q=0.9", "", "fr-CA"},
{"European French is unaffected by fr-CA", "fr-FR,fr;q=0.9", "", "fr"},
{"plain fr is unaffected by fr-CA", "fr", "", "fr"},
{"fr-CA can be selected by the ?lang override", "en", "fr-CA", "fr-CA"},

Mutation-checked rather than assumed: with the locale file moved aside, the two positive cases fail (Resolve("fr-CA,fr;q=0.9", "") = "fr", want "fr-CA") while the two fr/fr-FR cases stay green, which is what they are for — they assert an absence of change and would be worthless if removing the feature moved them.

What is verified and what is not

The three guards the other eight locales pass apply unchanged: same key set as English (TestAllLocalesHaveTheSameKeys), matching printf verbs including the %[1]s/%[2]s positional pair no_available_times_host needs (TestAllLocalesHaveMatchingFormatVerbs), and date tables cross-checked against CLDR (TestDateTablesMatchCLDR). So the structure is verified.

⚠️ The wording is not. It is an unreviewed draft, like every non-English locale in this repository, and nobody who speaks Canadian French has read it. The CHANGELOG says so plainly, so a correction arrives as an ordinary pull request rather than as a bug report from a Quebec booker.

Currency and percent take a non-breaking space before $ and % in Canadian French. No key carries either today, so that rule is recorded in ARCHITECTURE §23 rather than applied — worth writing down before someone adds a priced-event string.

Scope

Nine files: the locale, four test cases, and the doc/CHANGELOG counts that say "8 locales". No handler, no matcher, no schema. internal/i18n passes; the full suite passes on this branch.

Adding a locale is still just adding internal/i18n/locales/<code>.json — init() globs the directory, and nothing else needed a list updating.

🤖 Generated with Claude Code

`fr-CA` currently resolves to the France copy, and the differences are not
stylistic. `courriel` rather than `e-mail`, `reporter`/`report` rather than
`reprogrammer`/`reprogrammation`, `renseignements personnels` rather than
`données personnelles` (the Quebec statutory term, so the wrong one is wrong in
a legal sense rather than a register one), and no space before `!` `?` `;` where
France puts one. CLDR itself disagrees on an abbreviation: July is `juill.` in
fr-CA against `juil.` in fr.

It is the first REGIONAL locale, which is the only structural thing here: the
matcher already prefers an exact tag, so `fr-FR` and plain `fr` are untouched by
this file existing. TestResolve now pins that in both directions rather than
only the new one, since the half that would break silently is the French visitor
who never asked for any of this.

The three guards the other eight locales already pass apply unchanged — same key
set as English, matching printf verbs, and date tables cross-checked against
CLDR — so the structure is verified even though the wording is not.

⚠️ The copy is an unreviewed draft, like every non-English locale here. Nobody
who speaks Canadian French has read it. That is said plainly in the CHANGELOG so
a correction arrives as an ordinary pull request rather than as a bug report.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues — two stale locale counts outside the files this PR already updated.

Reviewed changes One commit adding Canadian French as a first-class regional locale (data + Resolve pins + doc counts). No matcher or handler changes.

  • fr-CA.json locale table New 158-key file with the claimed fr vs fr-CA differences (courriel, reporter/report, renseignements personnels, punctuation spacing, CLDR juill.). Key set matches en; package tests pass.
  • TestResolve pins both directions Exact fr-CA, European fr-FR/fr unaffected, and ?lang=fr-CA override — the half that would break silently if the matcher preferred the new regional tag too broadly.
  • Doc/CHANGELOG counts CLAUDE.md, CONTRIBUTING.md, ARCHITECTURE §23, and the Unreleased CHANGELOG entry now say 9 locales / list fr-CA.

ℹ️ Locale counts still say 8 in two places this PR did not touch

README.md still markets "8 languages" and lists English through Swedish with no Canadian French — the most visible user-facing surface for the feature. docs/ARCHITECTURE.md (~L809, LiveKit "not translated" known issue) still says the booking surfaces "ship in 8 languages (§23)", which now contradicts §23's "9 locales". Historical "8 locales" changelog entries are fine to leave.

Technical details
# Stale locale counts outside the PR's doc set

## Affected sites
- `README.md` ~L193–195 — still "**8 languages**" and the bullet list without Canadian French
- `docs/ARCHITECTURE.md` ~L808–809 — LiveKit known-issue still "ship in 8 languages (§23)" while §23 now says 9

## Required outcome
- User-facing and cross-referenced live counts match the shipped locale set (`en es fr fr-CA de it pt nl sv` / 9)
- Do not rewrite historical CHANGELOG / ARCHITECTURE dated entries that correctly described the state at ship time

## Suggested approach (optional)
- Bump README to 9 languages and add Canadian French to the list (same register as the other names)
- Change ARCHITECTURE L809 "8 languages" → "9 languages" (or "§23's locales") so it stays consistent with §23

Pullfrog  | Fix it ➔ | View workflow run | Using Grok | 𝕏

@shockalotti shockalotti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The locale itself follows the documented pattern (one JSON file, three guards green, honest unreviewed-draft label in CHANGELOG per §23's marketing rule) — no issue with the fr-CA copy as a draft. But this PR puts the docs in a self-contradictory state:

It updates the count to 9 in ARCHITECTURE §23, CONTRIBUTING, and CLAUDE.md, while README.md ("8 languages" bullet) and ARCHITECTURE §18 ("ship in 8 languages") still say 8. Merged as-is, the repo claims 8 and 9 locales at the same time. Please update those two spots to 9 in this PR.

Standing note (no action needed here): per §23's translation-quality rule, fr-CA stays unmarketed until a native speaker reads the booking page, manage page, and four emails end to end — the CHANGELOG already says this, good.

The locale commit moved the count to nine in ARCHITECTURE §23, CONTRIBUTING
and CLAUDE.md but left the README's feature bullet and the LiveKit known
issue in §18 at eight, so the repository claimed both numbers at once. Both
now say nine, and the README's list names Canadian French.

The dated 2026-08-20 entries in the CHANGELOG and the ARCHITECTURE log keep
"8 locales": they describe what shipped that day.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes One docs commit since the prior review, filling the two live locale-count gaps that review called out. No code or locale-table changes in this delta.

  • README language bullet Count is now 9 and the list includes Canadian French alongside French.
  • ARCHITECTURE LiveKit known-issue The §18 line now says the booking surfaces ship in 9 languages, matching §23.

Pullfrog  | View workflow run | Using Grok | 𝕏

@distronode-com

Copy link
Copy Markdown
Contributor Author

Fixed in 6bd9e48: the README feature bullet now says 9 languages and lists Canadian French, and the LiveKit entry in §18 says 9. I left the two dated 2026-08-20 entries (the CHANGELOG and the ARCHITECTURE log) at "8 locales", since they describe what shipped that day.

Understood on the translation rule: fr-CA stays an unreviewed draft until a native speaker has read the booking page, the manage page and the four emails, and the CHANGELOG line keeps saying so.

distronode-com and others added 3 commits September 16, 2026 22:20
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The branch was cut before 0.9.0, when its entry sat under [Unreleased].
0.9.0 renamed that section, and merging main moved the entry with it
without a conflict, so it read as something 0.9.0 shipped. Moved back
under [Unreleased], text unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#40 was squash-merged on 2026-09-17 from a branch cut before 0.9.0
(2026-09-10), and its entry landed under 0.9.0's Added the same way,
without a conflict. 0.9.0 shipped without the setting. Moved under
[Unreleased], text unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes Changelog hygiene after merging main (which cut 0.9.0). No locale-table or matcher changes in this delta.

  • fr-CA changelog placement The Canadian French entry now lives under [Unreleased], not [0.9.0].
  • FRAME_ANCESTORS changelog placement Same correction for the admin frame-ancestors note, which landed on main after the 0.9.0 tag.

Pullfrog  | View workflow run | Using Grok | 𝕏

@distronode-com

Copy link
Copy Markdown
Contributor Author

Merged main in (86a914f), and fixed something the merge did not flag. This branch was cut before 0.9.0, when its CHANGELOG entry sat under [Unreleased]. 0.9.0 renamed that section, and git carried the entry along with no conflict, filing Canadian French under 0.9.0. 60db2b3 moves it back under [Unreleased], text unchanged.

#40 hit the same thing when it was squash-merged: FRAME_ANCESTORS is listed under 0.9.0's Added on main, though 0.9.0 shipped a week before it. 707e4a4 moves that entry too, as its own commit, so it lands with this PR. If you'd rather fix main directly, say so and I'll drop that commit.

@shockalotti
shockalotti merged commit b6ba0a5 into Calnode:main Sep 21, 2026
5 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants