Locales
Every word a card draws itself — a title, a label, an empty state, and the description a screen
reader gets — comes from a translation table. locale picks which one:
?username=octocat&locale=esAn unknown code is an error reading Locale not found, not a silent fallback to English:
a card drawn in the wrong language is worse than a card that says why it could not be.
Available locales
Section titled “Available locales”en, ar, az, bg, bn, ca, cn, zh-tw, cs, de, sw, ur, es, fa, fi, fr,
hi, sa, hu, it, ja, kr, nl, pt-pt, pt-br, np, el, ro, ru, uk-ua, id,
ml, my, ta, sk, tr, pl, uz, vi, se, he, fil, th, sr, sr-latn, no,
be.
What is not translated yet
Section titled “What is not translated yet”A string added to a card is written in English first and translated afterwards, so a locale can be
missing a key that en has. When that happens the card draws the English string for that one line
and renders normally — it does not fail, and it does not fall back to English for the whole card.
Two things are deliberately never translated:
- Error cards. An error is often thrown before the locale has been read, and sometimes because it could not be. They are English.
- Your own text.
custom_titleis drawn exactly as you passed it.
Contributing a translation
Section titled “Contributing a translation”Each card owns its table, in packages/core/src/cards/<card>/locales.ts, one entry per key per
locale. Adding a language means adding your code to each key you can translate;
anything you leave out keeps reading in English until someone fills it in.
A wording can carry the values the card draws into it, as {name} placeholders:
'statcard.title': { en: "{name}'{apostrophe} GitHub Stats", fr: 'Statistiques GitHub de {name}',},Word order is therefore the translation’s own, and so is which values it uses —
French has no use for the possessive {apostrophe} above.
A placeholder the English wording does not supply is the one thing that will not work.
Where the wording depends on a number, write a form per plural category instead.
The card passes a count and the category is picked by the locale’s own rules,
so a language with more than two forms is free to write them all:
'contributedtocard.footer-all': { en: { one: '{count} repository', other: '{count} repositories' }, ru: { one: '{count} репозиторий', few: '{count} репозитория', other: '{count} репозиториев' },},other is the form every locale needs, and the one a category you leave out falls back to.