A React Native & Lynx i18n solution that helps you keep your translations organized

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 ( ); }; 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 ( {title} {description} {contentFetch} ); };

Mar 21, 2025 - 16:39
 0
A React Native & Lynx i18n solution that helps you keep your translations organized

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>
  );
};