Languages and regions
The pages people read can be drawn in any language, for any region, that has a catalog. That covers the sign-in screens, consent, sign-out, the user portal and the admin console. English is the source language. These are shipped:
| Language | Locales the chooser offers | Catalogs |
|---|---|---|
| English | en |
en |
| French | fr-FR, fr-CA |
fr, and fr-CA for Canadian wording |
| Spanish | es-MX, es-PA, es-ES |
es (Latin American), and es-ES for Spain |
| Chinese (Simplified) | zh-CN |
zh-Hans |
| Chinese (Traditional) | zh-HK, zh-TW |
zh-Hant, and zh-Hant-HK for Hong Kong wording |
| Filipino (Tagalog) | fil-PH |
fil |
| Swedish | sv-SE |
sv |
User-facing pages lists every page a person sees, and whether each is translated yet.
What is translated so far (#539, in phases). The sign-in screens and every second-factor step, the emailed and wallet sign-ins, consent, the hand-off pages, sign-out, the front door, the realm chooser and the GNAP pages, the user portal (with a language field on the person’s own account), the built-in mail and the admin console — including the text the server writes into a console page’s data (#543): setting descriptions, policy rules, each page’s notes and the protocol metadata. See Text the server writes.
Every catalog except English was machine-written and has not been reviewed by a native speaker. Each catalog’s status is in
common/locales/catalogs.json(machine-unreviewed). Have the text reviewed before you rely on it, and mark a catalogreviewedonce it has been.
Errors are always in English. Refusals, validation messages, error pages, protocol error descriptions and log lines are never translated. A page in Swedish shows a refused password in English.
Which language a page is drawn in
The first of these that a catalog answers wins:
ui_localeson the OpenID Connect authorization request in progress (Core 1.0, section 3.1.2.1). It is honoured on the sign-in screens. The discovery document’sui_locales_supportedlists the offered locales.- The person’s own
preferredLanguage(RFC 2798), once the page knows who they are. A value the locale policy filled in when the account was created is treated as the policy’s, not the person’s, and ranks after the browser (4). Once the person or an administrator sets a language, it is theirs and ranks here. - The language chooser on the page, which is remembered in a cookie.
- The browser’s
Accept-Language. - The realm’s locale policy: the default for the application the page is drawn for.
A language with no catalog is skipped in favour of the next one. A reader whose browser asks for German, then French, reads French.
Dates and numbers are formatted for the locale that won, even where the words
come from a broader catalog. es-PA reads the Spanish catalog and gets
Panamanian date formats. Times are given in UTC and say so.
Matching follows BCP 47 lookup, with the script worked out from the region.
zh-HK and zh-TW read Traditional Chinese and never Simplified. zh and
zh-CN read Simplified. tl is read as Filipino.
What a region changes
A locale has a language and, often, a region: fr-CA is French as used in
Canada. The region decides three things:
- Wording. Where a region says something differently, its overlay catalog
says it that way, and only there. Some examples:
fr-CAsays courriel and témoin where France says e-mail and cookie.es-ESsays ordenador and cartera where Latin America says computadora and billetera.zh-HKsays 電郵 where Taiwan says 電子郵件.
A region with no overlay reads its language’s base catalog.
es-MX,es-PAandfr-BEall do. - Dates, times and numbers. These are always formatted for the exact
locale chosen, even with no overlay:
es-PAandes-ESwrite the same date differently. Times are given in UTC and name the zone, so nobody has to guess which zone a page means. - Plurals. Plural forms follow the language’s own rules (Unicode CLDR). Chinese has one form, French counts 0 and 1 as singular, and English does not.
A locale with no catalog at all, de-CH for instance, is passed over in
favour of the reader’s next preference. If nothing answers, the realm’s
default is used. The realm’s default can itself be a locale with no catalog,
such as de-CH. Pages are then English but format dates and numbers for that
locale.
Right-to-left languages
The page’s direction is set from the locale (dir="rtl" for Arabic, Hebrew,
Persian, Urdu and the other right-to-left scripts). No code changes when a
right-to-left catalog is added. None is shipped yet.
The language chooser
Every user-facing page carries a small Language form. It works without JavaScript. Choosing a language:
- remembers it in the
sts_langcookie, which lasts a year, isHttpOnlyand isSameSite=Lax; - if you are signed in, also sets your own
preferredLanguage, because your entry outranks the cookie; - returns you to the page you were on. The return address is always a path on
this service. Anything else returns you to
/.
A language no catalog answers is refused (STS-I18N-0008).
The locale policy
The locale policy is the fifth kind of policy on Directory → Policies,
with a tab of its own. Set it there, or with
POST /admin-api/policies/save-locale-policy.
| Field | Default | What it does |
|---|---|---|
defaultLocale |
en |
Any BCP 47 tag. Pages fall back to it. Mail to a person whose entry names no language is written in it. A tag no catalog answers is kept: dates and numbers are formatted for it, and the words are English. |
populatePreferredLanguage |
on | A person created without a preferredLanguage is given defaultLocale as one, so mail, the locale claim and SCIM have a value. Existing entries are never rewritten. A page ranks a filled-in value after the browser’s language, until somebody changes it (stsPreferredLanguagePopulated records what was written). |
The default profile applies everywhere in the realm. A realm with no
default of its own follows the default realm’s.
Profiles per application
A realm may keep named profiles. Each has the two fields above and a list
of the applications it applies to (selectApplications: identifiers or
client_ids). An application can be on one named profile at most, and a
save that would put it on a second is refused (STS-I18N-0007). A named
profile applies:
- to the pages drawn for one of its applications: its sign-in screen and
consent, and the portal and the console, which are applications too
(
sts-user-portal,sts-admin-console); - to a person that application caused to be created: a person provisioned by its SCIM client, or created by signing in to it.
A person created from the console or /admin-api gets the default profile’s
language. Named profiles belong to their realm and are not inherited.
Replaces mail.defaultLanguage
mail.defaultLanguage (STS_MAIL_DEFAULT_LANGUAGE) was removed. Pages and
mail now share one default, the locale policy’s. A service started with the
old setting still named refuses to start and says what replaced it.
Adding a language
A catalog is data:
- Add a row to
common/locales/catalogs.json, with its tag, its name in its own language and its status. If the chooser should offer it, add it toofferedas well. - Add
common/locales/<namespace>/<tag>.jsonfor each namespace. A regional catalog (fr-CA) holds only the messages whose wording differs from its base (fr).
tests/i18n_catalogs.js checks every catalog against the English one: the
same keys, the same {placeholders} and the same inline markup. A
right-to-left language is drawn with dir="rtl" without further change.
Text the server writes
Some of what a console page shows is written by the server into the page’s
data rather than by the console. Examples are setting labels and
descriptions, policy rules, the notes on the Mode, Encryption, PKI, SCIM and
LDAP pages, scheduler jobs, caches and the protocol metadata. The management API translates that text, but
only when the request names a language in Accept-Language:
- The console always sends the language it chose for you, so its pages are drawn in that language.
- A script or integration that sends no
Accept-Languagegets English, whatever the realm’s locale policy defaults to. Its answers are the same as before this was added. Send the header to get translated text, for exampleAccept-Language: fr. - The OpenAPI documents (
/admin-api/openapi.jsonand the console’s own) are always English.
Values are never translated, only the server’s own sentences. Error messages
stay English. A coverage note keeps its first word (full, partial or
minimal) in English, because software reads it. A few sentences remain
English: scheduler jobs a node registers only after it starts, a cache whose
lifetime text is computed in a module that has no template for it, and
text written by another node running an older build.
A sentence that has changed since it was translated is shown in English until
its translation is updated. An out-of-date translation is never shown. These
translations are machine-written and unreviewed, like the catalogs above.
Regional overlays (fr-CA, es-ES, zh-Hant-HK) use their base language’s
text for now.