Description
Hello there!
I digged a bit into the code.
When starting up a fresh project using:
npx create-expo-stack@latest poster --tamagui --expo-router --supabase --i18next
On languageDetector.ts
, these lines returns an error when testing or trying to build for production Expo web
:
const locales = Localization.getLocales();
const firstLanguageCode = locales[0].languageCode ?? 'en';
Localization.getLocales()
returns an empty array []
. This is not in accordance to the documentation.
As a result, the next line causes an error when testing Expo web.
https://docs.expo.dev/versions/latest/sdk/localization/#localizationgetlocales
List of user's locales, returned as an array of objects of type Locale. Guaranteed to contain at least 1 element.
Digging deeper:
In the module expo-localization/ExpoLocalization.ts
, getLocales()
start with:
getLocales(): Locale[] {
const locales = getNavigatorLocales();
getNavigatorLocales()
is defined on the same file:
const getNavigatorLocales = () => {
return Platform.isDOMAvailable ? navigator.languages || [navigator.language] : [];
};
On expo-modules-core/src/Platform.ts
, Platform
defines the isDOMAvailable
property:
isDOMAvailable,
/**
* Denotes if the current environment can attach event listeners
* to the window. This will return false in native React
* runtimes and Node.js.
*/
It reads the defaults from environment/browser.ts
:
// In standard node environments there is no DOM API
export const isDOMAvailable = false;
export const canUseEventListeners = false;
export const canUseViewport = false;
This is causing the inconsistent behavior on web
, which is not in accordance to the documentation.
I worked around it with the following steps:
- install
i18next-browser-languagedetector
(official i18n package) - create file
core/i18n/languageDetectorWeb.ts
with this code:
import LanguageDetector from 'i18next-browser-languagedetector';
export const languageDetectorWeb = new LanguageDetector();
- changed core/i18n/init.ts to read:
...
import { languageDetectorWeb } from './languageDetectorWeb'; //added new language detector just for the web
...
return i18n
.use(Platform.OS === 'web' ? languageDetectorWeb : languageDetector) // use one or the other language detector depending on platform
...
Not sure if it's the ideal solution, as I am working around something that's plainly not working as the documentation says.
But since I created the app using create-expo-stack, I figured you may want to implement this to have a more feature-complete solution out-of-the-box.