diff --git a/messages/de.json b/messages/de.json
index 6061798f..91d7f1db 100644
--- a/messages/de.json
+++ b/messages/de.json
@@ -48,6 +48,7 @@
"description": "Wählen Sie Ihre Region und Sprache. Die Währung wird durch die ausgewählte Region festgelegt.",
"region": "Region",
"language": "Sprache",
+ "noSupportedLanguage": "Sprache nicht verfügbar",
"updatePreferences": "Einstellungen aktualisieren",
"updatingPreferences": "Einstellungen werden aktualisiert...",
"updatePreferencesFailed": "Die regionalen Einstellungen konnten nicht aktualisiert werden. Bitte versuchen Sie es erneut."
diff --git a/messages/en.json b/messages/en.json
index 8c5a8807..58edfe96 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -48,6 +48,7 @@
"description": "Choose your region and language. Currency is set by the selected region.",
"region": "Region",
"language": "Language",
+ "noSupportedLanguage": "Language unavailable",
"updatePreferences": "Update preferences",
"updatingPreferences": "Updating preferences...",
"updatePreferencesFailed": "We couldn't update your region preferences. Please try again."
diff --git a/messages/es.json b/messages/es.json
index 9db1c1d4..6d0e74e6 100644
--- a/messages/es.json
+++ b/messages/es.json
@@ -48,6 +48,7 @@
"description": "Elige tu región e idioma. La moneda depende de la región seleccionada.",
"region": "Región",
"language": "Idioma",
+ "noSupportedLanguage": "Idioma no disponible",
"updatePreferences": "Actualizar preferencias",
"updatingPreferences": "Actualizando preferencias...",
"updatePreferencesFailed": "No pudimos actualizar tus preferencias regionales. Inténtalo de nuevo."
diff --git a/messages/fr.json b/messages/fr.json
index 81e2ecaf..2f7b091a 100644
--- a/messages/fr.json
+++ b/messages/fr.json
@@ -48,6 +48,7 @@
"description": "Choisissez votre région et votre langue. La devise dépend de la région sélectionnée.",
"region": "Région",
"language": "Langue",
+ "noSupportedLanguage": "Langue indisponible",
"updatePreferences": "Mettre à jour les préférences",
"updatingPreferences": "Mise à jour des préférences...",
"updatePreferencesFailed": "Impossible de mettre à jour vos préférences régionales. Veuillez réessayer."
diff --git a/messages/pl.json b/messages/pl.json
index 22ac0a33..5910c2df 100644
--- a/messages/pl.json
+++ b/messages/pl.json
@@ -48,6 +48,7 @@
"description": "Wybierz region i język. Waluta jest ustawiana na podstawie wybranego regionu.",
"region": "Region",
"language": "Język",
+ "noSupportedLanguage": "Język niedostępny",
"updatePreferences": "Zaktualizuj preferencje",
"updatingPreferences": "Aktualizowanie preferencji...",
"updatePreferencesFailed": "Nie udało się zaktualizować preferencji regionalnych. Spróbuj ponownie."
diff --git a/src/app/[country]/[locale]/layout.test.tsx b/src/app/[country]/[locale]/layout.test.tsx
index 615a1c56..1a5eb0d9 100644
--- a/src/app/[country]/[locale]/layout.test.tsx
+++ b/src/app/[country]/[locale]/layout.test.tsx
@@ -143,6 +143,27 @@ describe("CountryLocaleLayout Market fallback", () => {
});
});
+ it("renders a Market configured with en-GB at the lowercase route", async () => {
+ mocks.getMarkets.mockResolvedValue({
+ data: [
+ market({
+ default_locale: "en-GB",
+ supported_locales: [],
+ country_isos: ["GB"],
+ countries: [country("GB")],
+ }),
+ ],
+ });
+
+ await expect(
+ CountryLocaleLayoutContent({
+ children: ,
+ params: Promise.resolve({ country: "gb", locale: "en-gb" }),
+ }),
+ ).resolves.toBeDefined();
+ expect(mocks.redirect).not.toHaveBeenCalled();
+ });
+
it("redirects an unknown country to the default Market and keeps the page", async () => {
mocks.getMarkets.mockResolvedValue({ data: [market()] });
mocks.headers.mockResolvedValue(
diff --git a/src/components/layout/RegionPreferences.tsx b/src/components/layout/RegionPreferences.tsx
index 4f65444d..4a81fb34 100644
--- a/src/components/layout/RegionPreferences.tsx
+++ b/src/components/layout/RegionPreferences.tsx
@@ -25,6 +25,8 @@ import {
} from "@/components/ui/native-select";
import { type CountryWithMarket, useStore } from "@/contexts/StoreContext";
import { useCountrySwitch } from "@/hooks/useCountrySwitch";
+import { resolveSupportedLocale, type SupportedLocale } from "@/i18n/locales";
+import { toRouteLocale } from "@/i18n/normalize";
import { cn } from "@/lib/utils";
interface RegionPreferencesProps {
@@ -65,9 +67,15 @@ function getCountry(
}
function getSupportedLocales(entry: CountryWithMarket): string[] {
- return entry.supported_locales.length > 0
- ? entry.supported_locales
- : [entry.default_locale];
+ const locales = [entry.default_locale, ...entry.supported_locales];
+
+ return Array.from(
+ new Set(
+ locales
+ .map((locale) => resolveSupportedLocale(locale))
+ .filter((locale): locale is SupportedLocale => locale !== undefined),
+ ),
+ );
}
export function RegionPreferences({ variant }: RegionPreferencesProps) {
@@ -88,7 +96,7 @@ export function RegionPreferences({ variant }: RegionPreferencesProps) {
getCountry(countries, draftCountry) ?? getCountry(countries, country);
const localeOptions = selectedCountry
? getSupportedLocales(selectedCountry)
- : [locale];
+ : [toRouteLocale(locale) ?? locale];
const languageDisplayNames = useMemo(() => {
try {
return new Intl.DisplayNames([locale], { type: "language" });
@@ -111,11 +119,14 @@ export function RegionPreferences({ variant }: RegionPreferencesProps) {
if (!entry) return;
const supportedLocales = getSupportedLocales(entry);
+
setDraftCountry(nextCountry);
setDraftLocale((currentLocale) =>
- supportedLocales.includes(currentLocale)
- ? currentLocale
- : entry.default_locale || supportedLocales[0],
+ supportedLocales.includes(
+ toRouteLocale(currentLocale) ?? currentLocale.toLowerCase(),
+ )
+ ? (toRouteLocale(currentLocale) ?? currentLocale.toLowerCase())
+ : (supportedLocales[0] ?? ""),
);
setSwitchError(false);
}
@@ -124,7 +135,13 @@ export function RegionPreferences({ variant }: RegionPreferencesProps) {
event: FormEvent,
): Promise {
event.preventDefault();
- if (!selectedCountry) return;
+ if (
+ !selectedCountry ||
+ localeOptions.length === 0 ||
+ !localeOptions.includes(draftLocale)
+ ) {
+ return;
+ }
setSwitchError(false);
const switched = await handleCountrySelect(selectedCountry, draftLocale);
@@ -139,6 +156,8 @@ export function RegionPreferences({ variant }: RegionPreferencesProps) {
}
const isHeaderVariant = variant === "header";
+ const hasRenderableLocale =
+ localeOptions.length > 0 && localeOptions.includes(draftLocale);
return (