Files
zitadel/apps/login/src/lib/i18n.ts
T
ab0f045499 feat(login): dynamically configure languages based on settings (#11372)
Closes #11199 

# Which Problems Are Solved

This PR refactors the login app to load allowed languages and the
default language directly from the Zitadel API equivalents
(`getGeneralSettings`), rather than relying on a hardcoded list. This
ensures that the available languages in the UI and the locale selection
logic match the instance's configuration.

# How the Problems Are Solved

- Fetches allowed languages server-side and passes them to the
LanguageSwitcher
- The NEXT_LOCALE cookie and Accept-Language headers are now strictly
validated against the API-provided allowed languages.
- Fallback: If a cookie requests an unsupported language, the system now
falls back to the API's defaultLanguage (instead of valid but
unconfigured defaults).

# Additional Changes

Helper: Added `getLanguage(code)` to map API language codes to display
names (utilizing Intl.DisplayNames if the code isn't in our static
mapping).

---------

Co-authored-by: Livio Spring <[email protected]>
2026-02-24 08:07:58 +00:00

75 lines
1.1 KiB
TypeScript

export interface Lang {
name: string;
code: string;
}
export const LANGS: Lang[] = [
{
name: "English",
code: "en",
},
{
name: "Deutsch",
code: "de",
},
{
name: "Italiano",
code: "it",
},
{
name: "Español",
code: "es",
},
{
name: "Français",
code: "fr",
},
{
name: "Nederlands",
code: "nl",
},
{
name: "Polski",
code: "pl",
},
{
name: "简体中文",
code: "zh",
},
{
name: "Русский",
code: "ru",
},
{
name: "Türkçe",
code: "tr",
},
{
name: "日本語",
code: "ja",
},
{
name: "Українська",
code: "uk",
},
{
name: "العربية",
code: "ar",
},
];
export const LANGUAGE_COOKIE_NAME = "NEXT_LOCALE";
export const LANGUAGE_HEADER_NAME = "accept-language";
export function getLanguage(code: string): Lang {
const lang = LANGS.find((l) => l.code === code);
if (lang) {
return lang;
}
return {
code,
name: new Intl.DisplayNames([code], { type: "language" }).of(code) || code,
};
}