From 73f70b5e28f7640ee8d72eb3c070596d163feca1 Mon Sep 17 00:00:00 2001 From: chahinebrini Date: Tue, 19 May 2026 22:01:57 +0200 Subject: [PATCH] fix(language): auto-sync from user_metadata.locale at sign-in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: User mit iOS-Sprache=Arabisch sah App auf Englisch wenn Localization.getLocales() auf seinem Setup nicht zuverlässig 'ar' zurückgab (iOS-Region≠Sprache, App-Override etc). Fix: bei sign-in (init() initial-getSession + onAuthStateChange für SIGNED_IN events) wird session.user.user_metadata.locale gelesen. Wenn AsyncStorage @rebreak/language NOCH NICHT gesetzt ist (User hat keine explicit Choice gemacht) → silent apply der server-locale (inkl. RTL-flip, KEIN Restart-Alert). Respektiert User-Choice: wenn AsyncStorage gefüllt ist (z.B. User hat manuell in Settings gewechselt), bleibt das gewinnen. --- apps/rebreak-native/stores/auth.ts | 7 +++++++ apps/rebreak-native/stores/language.ts | 29 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/apps/rebreak-native/stores/auth.ts b/apps/rebreak-native/stores/auth.ts index 584527a..17d4de7 100644 --- a/apps/rebreak-native/stores/auth.ts +++ b/apps/rebreak-native/stores/auth.ts @@ -7,6 +7,7 @@ import * as AppleAuthentication from 'expo-apple-authentication'; import { supabase } from '../lib/supabase'; import { apiFetch } from '../lib/api'; import i18n from '../lib/i18n'; +import { syncLanguageFromUserMetadata } from './language'; const SUPPORTED_LOCALES = ['de', 'en', 'fr', 'ar'] as const; type SupportedLocale = (typeof SUPPORTED_LOCALES)[number]; @@ -69,9 +70,15 @@ export const useAuthStore = create((set) => ({ user: data.session?.user ?? null, loading: false, }); + if (data.session?.user) { + void syncLanguageFromUserMetadata(data.session.user); + } supabase.auth.onAuthStateChange((_event, session) => { set({ session, user: session?.user ?? null }); + if (session?.user) { + void syncLanguageFromUserMetadata(session.user); + } }); }, diff --git a/apps/rebreak-native/stores/language.ts b/apps/rebreak-native/stores/language.ts index 6aef435..a21af21 100644 --- a/apps/rebreak-native/stores/language.ts +++ b/apps/rebreak-native/stores/language.ts @@ -61,3 +61,32 @@ export const useLanguageStore = create((set) => ({ } }, })); + +// Auto-sync language from session.user.user_metadata.locale beim Sign-In. +// Wenn AsyncStorage @rebreak/language LEER ist (kein explicit user-choice) +// und Server-side metadata.locale gesetzt — silent apply (kein Restart-Alert). +// Respektiert User-Choice: AsyncStorage gewinnt immer wenn gesetzt. +export async function syncLanguageFromUserMetadata( + user: { user_metadata?: { locale?: string | null } | null } | null, +): Promise { + if (!user) return; + const raw = user.user_metadata?.locale; + if (!raw) return; + const short = String(raw).split('-')[0].toLowerCase(); + const valid: AppLanguage[] = ['de', 'en', 'fr', 'ar']; + if (!(valid as readonly string[]).includes(short)) return; + const lang = short as AppLanguage; + + const stored = await AsyncStorage.getItem(STORAGE_KEY); + if (stored) return; // explicit user-choice wins + + if (i18n.language === lang) { + await AsyncStorage.setItem(STORAGE_KEY, lang); + return; + } + + await AsyncStorage.setItem(STORAGE_KEY, lang); + await i18n.changeLanguage(lang); + applyRTL(lang); + useLanguageStore.setState({ language: lang }); +}