Search code examples
react-nativei18nextasyncstorage

AsyncStorage: Invariant Violation: Module AppRegistry is not a registered callable module


I'm using react-i18next to translate a React Native app. It works, but I can't retrieve the user's locale in AsyncStorage when launching the app. The error is:

ERROR TypeError: undefined is not a function, js engine: hermes ERROR Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication). A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native., js engine: hermes

The code is:

import i18n, { LanguageDetectorAsyncModule } from "i18next";
import { initReactI18next } from "react-i18next";
import { Platform, NativeModules } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import en from "./en.json";
import fr from "./fr.json";

const languages = {
  EN: "en",
  FR: "fr",
};

const resources = {
  en: { translation: en },
  fr: { translation: fr },
};

const detectLocale = async () => {
  const storedLocale = await AsyncStorage.getItem("locale");
  if (storedLocale) {
    return JSON.parse(storedLocale);
  }
  const mobileLocale =
    Platform.OS === "ios"
      ? NativeModules.SettingsManager.settings.AppleLocale ||
        NativeModules.SettingsManager.settings.AppleLanguages[0]
      : NativeModules.I18nManager.localeIdentifier;
  if (mobileLocale) {
    return mobileLocale.split("_")[0];
  }
  return languages.EN;
};

const LanguageDetector = {
  type: "languageDetector" as LanguageDetectorAsyncModule["type"],
  async: false,
  init: () => {},
  detect: detectLocale,
  cacheUserLanguage: () => {},
};

export default i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    resources,
    fallbackLng: languages.EN,
    keySeparator: ".",
    whitelist: [languages.EN, languages.FR],
    interpolation: { escapeValue: false },
  });

So the error comes from the detectLocale function, called in LanguageDetector.detect(). It's async, I use the await keyword. Everything works fine without AsyncStorage, so the error must come from here.

I use React Native CLI, no expo, the version is the most recent one to this date: 0.64.1.


Solution

  • I was having a similiar issue. In order to use async custom language detector, you need to set async to true. Then you will receive callback function on detect().

    
    
    const languageDetector: LanguageDetectorAsyncModule = {
      type: "languageDetector",
      async: true,
      // Since we set async to true, detect has now callback function...
      detect: async (callback: (lang: string) => void) => {
      const language = await AsyncStorage.getItem('language')
        callback(lastSelectedLang);
      },
      init: () => {},
      cacheUserLanguage: (lng: string) =>
        AsyncStorage.setItem('language', lng),
    };