Skip to content

i18n error on expo app web #460

Open
@BrazilianJoe

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions