Skip to content

i18n error on expo app web #460

Description

@BrazilianJoe

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.

Image

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:

  1. install i18next-browser-languagedetector (official i18n package)
  2. create file core/i18n/languageDetectorWeb.ts with this code:
import LanguageDetector from 'i18next-browser-languagedetector';

export const languageDetectorWeb = new LanguageDetector();
  1. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions