If you're working on making your React Native (or even web) application multilingual, you've probably already tried integrating react-i18next
, i18n-js
, LinguiJS
or other alternatives.
In every project I’ve worked on, the same issues arise:
❌ Unused key-value pairs are never removed.
❌ Content is often duplicated.
❌ Ensuring format consistency across all languages and verifying that each translation is present and accurate becomes challenging, especially when managing more than five locale directories locally.
❌ Even if third-party tools can to solve this problem, by default i18next doesn’t generate TypeScript types, which means you can reference a key like t("my.key")
even if it has been deleted.
❌ Additionally, localization platforms like Localize, Lokalise, or Locize can quickly become costly.
Tired of this complexity, I started looking for a solution to address these problems. I waited, and waited… before finally developing Intlayer.
✨ Key Features of Intlayer
✅ Available for React Native and Lynx
✅ Simple and quick integration
✅ Content declaration in the same directory as your component (or everywhere in your project)
✅ Autogenerated TypeScript Types – No more guessing or runtime errors due to missing keys
✅ Content declaration in either JSON, JS, or TS format
✅ Allows embedding external files (Markdown, TXT, etc.)
✅ Instantly fetch external data with automatic typing
✅ Intlayer natively provides a way to externalize your content and make it editable via a CMS
⚡ Getting Started (React Native)
1️⃣ Install the Required Packages
Run the following command in your project:
npm install intlayer react-intlayer react-native-intlayer
2️⃣ Configure Your Locales
Create an intlayer.config.ts
file in your project root:
import { Locales, type IntlayerConfig } from "intlayer";
const config: IntlayerConfig = {
internationalization: {
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
defaultLocale: Locales.ENGLISH,
},
};
export default config;
3️⃣ Enable Metro Support
Add the Metro bundler plugin to your metro.config.js
:
const { getDefaultConfig } = require("expo/metro-config");
const { configMetroIntlayer } = require("react-native-intlayer/metro");
module.exports = (async () => {
const defaultConfig = getDefaultConfig(__dirname);
return await configMetroIntlayer(defaultConfig);
})();
4️⃣ Wrap Your App with the Intlayer Provider
Modify your _layout.tsx
file to initialize Intlayer and detect the user's language:
import { Stack } from "expo-router";
import { getLocales } from "expo-localization";
import { IntlayerProviderContent } from "react-intlayer";
import { intlayerPolyfill } from "react-native-intlayer";
intlayerPolyfill();
const getDeviceLocale = () => getLocales()[0]?.languageTag;
const RootLayout = () => {
return (
<IntlayerProviderContent defaultLocale={getDeviceLocale()}>
<Stack>
<Stack.Screen name="(tabs)" />
</Stack>
</IntlayerProviderContent>
);
};
export default RootLayout;
5️⃣ Define Translations Close to Your Components
Instead of maintaining large JSON files, define your translations inside the component's directory:
import { t, md, file, type Dictionary } from "intlayer";
const homeScreenContent = {
key: "home-screen",
content: {
title: t({
en: "My Title",
fr: "Mon titre",
es: "Mi título",
}),
description: t({
en: md(file("./myDescription.en.md")),
fr: md(file("./myDescription.fr.md")),
es: md(file("./myDescription.es.md")),
}),
contentFetch: fetch("https://example.com").then((res) => res.text()),
},
} satisfies Dictionary;
export default homeScreenContent;
Now, you can use translations inside your components like this:
import { Text, View } from "react-native";
import { useIntlayer } from "react-intlayer";
const MyComponent = () => {
const { title, description, contentFetch } = useIntlayer("my-component");
return (
<View>
<Text>{title}</Text>
<Text>{description}</Text>
<Text>{contentFetch}</Text>
</View>
);
};
🔄 Switching Languages Dynamically
To allow users to change languages at runtime, use the useLocale
hook:
import { View, Text, TouchableOpacity } from "react-native";
import { getLocaleName } from "intlayer";
import { useLocale } from "react-intlayer";
const LocaleSwitcher = () => {
const { setLocale, availableLocales } = useLocale();
return (
<View>
{availableLocales.map((locale) => (
<TouchableOpacity key={locale} onPress={() => setLocale(locale)}>
<Text>{getLocaleName(locale)}</Text>
</TouchableOpacity>
))}
</View>
);
};
export default LocaleSwitcher;
Resources
⭐ GitHub issues & feedback: Intlayer Repository
📄 Docs: React Native & Expo Docs
🔹 Template: React Native Template
Top comments (0)