fr-FR or fr-CA? Choose the market, not just the language
The BCP-47 codes you ship under are fr-FR for France and fr-CA for Canada (Quebec). Two more are worth knowing: fr-BE (Belgium) and fr-CH (Switzerland). You don't have to translate all four — but you do have to decide which base variant your fr file represents, because a French user in Montreal and one in Lyon will flag different words as wrong.
A useful rule of thumb:
- Targeting France, Belgium, Switzerland, or Francophone Africa → base on fr-FR.
- Targeting Quebec / the rest of Canada → ship a dedicated fr-CA file.
- Serving both France and Canada seriously → ship both. strings.dev treats
fr-FR and fr-CA as separate first-class locales rather than collapsing them into one "French."
See the iOS & Android locale code reference for how these map to Xcode and Android resource folders (values-fr-rCA, etc.).
The vocabulary that actually diverges
Quebec French and Metropolitan French share grammar but split hard on everyday product nouns — and Quebec is far less tolerant of anglicisms. France happily writes e-mail in UI copy; Quebec's courriel is not optional there.
| English |
fr-FR (France) |
fr-CA (Canada) |
| email |
e-mail / mail |
courriel |
| weekend |
week-end |
fin de semaine |
| to go shopping |
faire les courses |
magasiner |
| to chat |
chatter |
clavarder |
| parking |
parking |
stationnement |
Get this wrong and the copy isn't incorrect so much as foreign — a Quebec user reads "week-end" and "e-mail" as a France build that nobody adapted.
The same string, two variants
Here the vocabulary split shows up right inside the resource file. Note that the iOS %lld placeholder is carried through untouched in both:
// iOS — Localizable.strings (source: en)
"inbox.unread" = "You have %lld unread emails";
// fr-FR (France)
"inbox.unread" = "Vous avez %lld e-mails non lus";
// fr-CA (Canada) — courriel, never "e-mail"
"inbox.unread" = "Vous avez %lld courriels non lus";
French also runs roughly 15–20% longer than English, so test your tightest labels. "Settings" becomes Réglages on iOS, "Cancel" becomes Annuler, "Done" becomes Terminé — short strings inflate fastest and are exactly where truncation bites.
Typography and formatting French forces on you
French punctuation is not English punctuation with accents. In fr-FR, a narrow no-break space precedes ; : ! ? and sits inside the guillemets « ». That space must survive translation, or your exclamation looks broken:
// Source
"welcome.toast" = "Welcome back, %@!";
// fr-FR — narrow no-break space before the « ! »
"welcome.toast" = "Bon retour, %@ !";
The %@ name placeholder is preserved; the spacing is the point. Quebec typography follows the same rule for the colon but is more permissive before ! ?.
Numbers and currency diverge too:
|
fr-FR |
fr-CA |
| Decimal separator |
comma → 1 234,56 |
comma → 1 234,56 |
| Thousands |
narrow space |
narrow space |
| Currency |
12,99 € (symbol after) |
12,99 $ (CAD, symbol after) |
| Date |
16/07/2026 (jj/mm/aaaa) |
2026-07-16 (aaaa-mm-jj) |
Both variants put the currency symbol after the amount with a space — the opposite of English $12.99. Let the platform's NumberFormatter / NumberFormat handle these from the locale rather than hardcoding.
Plurals: French makes zero singular
This is the classic bug. French uses the singular for 0 and 1 — "0 message", "1 message", but "2 messages". English pluralizes zero; French does not. In CLDR terms, French cardinals use three categories:
| Value |
CLDR category |
Form |
| 0, 1 |
one |
1 message |
| 2, 3, 100… |
other |
2 messages |
| large / compact (e.g. millions) |
many |
1,2 million de messages |
The many category exists for large and compact-notation numbers, where the noun phrase shifts (note the added de). If your counter strings ever render millions in compact form, provide that form; otherwise one and other cover the app. Author these as real .stringsdict / plurals entries, not string concatenation.
Beyond France and Quebec
French is official across France, Canada, Belgium, Switzerland, and much of West and Central Africa — a large advisory market map. These are context for tone and word choice, not separate metadata features: strings.dev localizes your in-app native strings, and App Store listing text is out of scope. Belgian and Swiss French carry their own number words (septante, nonante) and Swiss formatting quirks, so treat fr-FR as a European base and branch only where a market justifies it.
Adding French in strings.dev
Upload your Xcode .xcloc or Android strings.xml, add your app description so every string is translated in context, and pick fr-FR, fr-CA, or both. Brand phrases stay locked via placeholder protection; iOS %@ %lld %1$@ and Android %s %d %1$s are preserved automatically.
On tiers, one honest note: the free Indie plan covers your first language (1 language, unlimited words). Adding French as a second or later locale — or shipping fr-FR and fr-CA together — needs Indie Plus ($20/mo, or $10/mo billed annually) for unlimited languages. See pricing or start on the free plan, and browse the mobile localization guide for the full workflow.