Internationalization
Overview
weNow supports 50 languages via i18next with the react-i18next integration. The app automatically detects the device locale on first launch and sets the UI language accordingly. If the detected locale is not among the 50 supported languages, the app falls back to English. The user's language preference is persisted to AsyncStorage so it survives app restarts.
Supported Languages
| Code | Language | Native Name |
|---|---|---|
| af | Afrikaans | Afrikaans |
| ar | Arabic | العربية |
| bg | Bulgarian | Български |
| bn | Bengali | বাংলা |
| ca | Catalan | Català |
| cs | Czech | Čeština |
| da | Danish | Dansk |
| de | German | Deutsch |
| el | Greek | Ελληνικά |
| en | English | English |
| es | Spanish | Español |
| fa | Persian | فارسی |
| fi | Finnish | Suomi |
| fil | Filipino | Filipino |
| fr | French | Français |
| he | Hebrew | עברית |
| hi | Hindi | हिन्दी |
| hr | Croatian | Hrvatski |
| hu | Hungarian | Magyar |
| id | Indonesian | Bahasa Indonesia |
| it | Italian | Italiano |
| ja | Japanese | 日本語 |
| km | Khmer | ភាសាខ្មែរ |
| kn | Kannada | ಕನ್ನಡ |
| ko | Korean | 한국어 |
| lt | Lithuanian | Lietuvių |
| lv | Latvian | Latviešu |
| ml | Malayalam | മലയാളം |
| mr | Marathi | मराठी |
| ms | Malay | Bahasa Melayu |
| my | Burmese | မြန်မာဘာသာ |
| nb | Norwegian | Norsk Bokmål |
| nl | Dutch | Nederlands |
| pl | Polish | Polski |
| pt | Portuguese | Português |
| ro | Romanian | Română |
| ru | Russian | Русский |
| si | Sinhala | සිංහල |
| sk | Slovak | Slovenčina |
| sr | Serbian | Српски |
| sv | Swedish | Svenska |
| sw | Swahili | Kiswahili |
| ta | Tamil | தமிழ் |
| te | Telugu | తెలుగు |
| th | Thai | ไทย |
| tr | Turkish | Türkçe |
| uk | Ukrainian | Українська |
| ur | Urdu | اردو |
| vi | Vietnamese | Tiếng Việt |
| zh | Chinese | 中文 |
Technical Setup
The internationalization system is built on the following stack:
- i18next -- core internationalization framework
- react-i18next -- React bindings providing the
useTranslationhook andTranscomponent
Key files:
src/i18n/index.ts-- i18next initialization, resource imports, AsyncStorage language detectorsrc/i18n/languages.ts-- list of supported languages with codes and display namessrc/i18n/locales/*.json-- one JSON translation file per language (50 files total)
How to Add a New Language
- Create the locale file -- Add a new JSON file in
src/i18n/locales/named with the language code (e.g.,sw.json). Copy the structure fromen.jsonand translate all values. - Register the language -- Add the language entry (code, name, native name) to the array in
src/i18n/languages.ts. - Import in i18n config -- Import the new locale JSON in
src/i18n/index.tsand add it to theresourcesobject passed toi18next.init().
Translation Keys
Translation strings are organized into the following sections within each locale JSON file:
- common -- shared UI strings (OK, Cancel, generic text)
- weather -- main weather screen UI (search placeholder, ensemble title, forecast titles, remaining requests)
- errors -- error messages and fallback text (all sources failed, permission denied, etc.)
- onboarding -- first-launch screen text
- widgetConfig -- widget configuration screen (city search, forecast mode toggle)
- settings -- settings screen labels (language, data sources, feedback, privacy/terms links)
- comingSoon -- premium/paywall page (pitch, features, price)
- ad -- self-served ad card labels (
sponsored,dismiss,accessibilityHint, plus the legacyadSpace/upgradeToRemove) - accuracy -- source accuracy tracking (most accurate, off by, not enough data)
Widget Localization
Android home screen widgets run in a headless JavaScript context that does not have access to react-i18next, so they handle localization differently from the main app:
- Day names in forecast widgets use
Intl.DateTimeFormatwith the device locale (e.g., "Mon", "Tue") and fall back to English abbreviations ifIntlis unavailable. - Hour labels in hourly forecast mode are formatted as "14h", "15h" -- language-independent.
- Weather descriptions are returned by the backend in the language matching the app's locale (the
langparameter is forwarded to providers that support localized responses), so they render in the user's language. - Hardcoded fallbacks ("Tap to set location", "Loading weather...", "Tap to open") are currently English-only because they appear before any data has been fetched.
- The widget configuration screen runs in the main app context, not headless, so it uses
react-i18nextnormally with keys under thewidgetConfignamespace.