Files
FarmaFinder/apps/frontend-mobile/src/i18n/LanguageContext.jsx
T
Antoni Nuñez Romeu ee958d4525
Run Tests on Branches / Detect Changes (push) Successful in 13s
Run Tests on Branches / Backend Tests (push) Has been skipped
Run Tests on Branches / Frontend Tests (push) Successful in 1m40s
Run Tests on Branches / Frontend Mobile Tests (push) Successful in 1m37s
Run Tests on Branches / Parapharmacy API Tests (push) Has been skipped
Run Tests on Branches / PIP Platform Tests (push) Has been skipped
feat(i18n-mobile): add bilingual support (Català / Castellano) for React Native app
Add lightweight i18n system matching the web app architecture.
Language persisted in AsyncStorage('ff-lang').

New files:
- src/i18n/locales/ca.js (~190 translation keys)
- src/i18n/locales/es.js (~190 translation keys)
- src/i18n/LanguageContext.jsx (Provider + AsyncStorage)
- src/i18n/useTranslation.js (hook)
- src/i18n/index.js (barrel export)

Modified 16 files:
- app/_layout.tsx: wrap with LanguageProvider, translate stack titles
- app/(tabs)/_layout.tsx: translate tab bar labels
- app/(tabs)/index.tsx: translate home screen
- app/(tabs)/search.tsx: translate search screen
- app/(tabs)/alerts.tsx: translate alerts screen
- app/(tabs)/profile.tsx: translate profile + add language selector (CA/ES)
- app/(tabs)/scan.tsx: translate scanner screen
- app/auth/login.tsx: translate login/register
- app/medicine/[id].tsx: translate medicine detail
- app/pharmacy/[id].tsx: translate pharmacy detail
- app/product/[source]/[id].tsx: translate product detail
- 5 components: MedicineCard, StockBadge, SearchBar, LoadingSpinner, BarcodeScanner

Language selector in Profile screen (globe icon + CA/ES toggle).
No routes changed. No API calls affected.
2026-07-17 10:22:41 +02:00

51 lines
1.4 KiB
React

import React, { createContext, useState, useCallback, useMemo } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import es from './locales/es';
import ca from './locales/ca';
const locales = { es, ca };
const STORAGE_KEY = 'ff-lang';
function getInitialLang() {
// Default to 'es' - will be updated from AsyncStorage in the provider
return 'es';
}
export const LanguageContext = createContext(null);
export function LanguageProvider({ children }) {
const [lang, setLangState] = useState(getInitialLang);
const [ready, setReady] = useState(false);
// Load saved language on mount
React.useEffect(() => {
AsyncStorage.getItem(STORAGE_KEY).then((saved) => {
if (saved === 'ca' || saved === 'es') {
setLangState(saved);
}
// Default to 'es' if no saved preference
setReady(true);
}).catch(() => {
setReady(true);
});
}, []);
const setLang = useCallback((newLang) => {
if (newLang !== 'ca' && newLang !== 'es') return;
setLangState(newLang);
AsyncStorage.setItem(STORAGE_KEY, newLang).catch(() => {});
}, []);
const t = useCallback((key) => {
return locales[lang]?.[key] || locales.es[key] || key;
}, [lang]);
const value = useMemo(() => ({ lang, setLang, t, ready }), [lang, setLang, t, ready]);
return (
<LanguageContext.Provider value={value}>
{children}
</LanguageContext.Provider>
);
}