DEV Community

Cover image for 🚨 99% of React Native Apps Make This Localization (i18n) Mistake β€” Is Yours One of Them?
Davyd NRB
Davyd NRB

Posted on

🚨 99% of React Native Apps Make This Localization (i18n) Mistake β€” Is Yours One of Them?

One of the most common (and costly) mistakes in multilingual React Native apps is bundling all localization files directly into the JavaScript bundle.

If your app supports several languages (for example: English, Spanish, French, etc.) and you’re still bundling them into JS, you’re doing it the wrong way.

But don’t worry β€” 99% of us have done this.


πŸͺ€ The Problem

Here’s what happens when all locale files are bundled in JS:

  • πŸš€ Increased app size
  • 🐒 Slower app startup
  • 🧠 Higher memory usage (even for unused languages)

This might be fine in development, but it's a performance killer in production.


βœ… The Right Way (Android)

Let’s fix it using two native Android features:

Step 1: Move Locale Files to Native Resources

Instead of bundling JSON locale files in JS, place them in Android's raw resource folders:

android/
└── app/
    └── src/
        └── main/
            └── res/
                β”œβ”€β”€ raw/           # default (e.g. English)
                β”‚   └── localizable.json
                β”œβ”€β”€ raw-es/       # Spanish
                β”‚   └── localizable.json
                β”œβ”€β”€ raw-fr/       # French
                β”‚   └── localizable.json
                β”œβ”€β”€ raw-it/       # Italian
                β”‚   └── localizable.json
                β”œβ”€β”€ raw-pt-rBR/   # Portuguese (Brazil)
                β”‚   └── localizable.json
Enter fullscreen mode Exit fullscreen mode

Now, Android will include only the necessary languages based on the user's device settings.


Step 2: Enable Per-App Language Preferences

Let Android handle locale selection automatically.

2.1 Create locales_config.xml

<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
    <locale android:name="en"/>
    <locale android:name="es"/>
    <locale android:name="fr"/>
    <locale android:name="it"/>
    <locale android:name="pt-br"/>
</locale-config>
Enter fullscreen mode Exit fullscreen mode

Save this file to:
android/app/src/main/res/xml/locales_config.xml

2.2 Register in AndroidManifest.xml

<application
  android:name=".MainApplication"
  android:label="@string/app_name"
+  android:localeConfig="@xml/locales_config"
Enter fullscreen mode Exit fullscreen mode

2.3 Configure resConfigs in build.gradle

In android/app/build.gradle, declare the supported locales:

android {
    defaultConfig {
        ...
        resConfigs "en", "es", "fr", "it", "pt-rBR"
    }
}
Enter fullscreen mode Exit fullscreen mode

🌍 Bonus: Read Locales from Native Side

Now that your locales live natively, it’s time to read them.

In production, use the native resource. In development, load the file directly for faster iteration:

import { Fbtee } from 'react-native-fbtee';

function getLocale() {
  if (__DEV__) {
    return require('../android/app/src/main/res/raw/localizable.json');
  }

  return JSON.parse(Fbtee.readLocalizationFile('localizable'));
}
Enter fullscreen mode Exit fullscreen mode

πŸ“¦ react-native-fbtee enables fast, synchronous file access from native resources.


🧩 Putting It All Together

Here's what happens in practice:

  1. πŸ“² User installs your app.
  2. πŸ“₯ Only the locale matching their device is downloaded.
  3. πŸ” If they change the app language (via system settings), Android dynamically downloads the new locale in the background.
  4. πŸ“¦ Your app reads the updated locale JSON β€” no JS bundle changes needed.

Often, this triggers a push notification like:

Once the download completes, translations are updated β€” you can read updated values.


πŸ“‰ Verify It: Check Your App Size

Tools like Ruler by Spotify can show the difference in download size per locale. You’ll be shocked at how much space you save (πŸ‘‰ see a demo video from MichaΕ‚ PierzchaΕ‚a)..


TL;DR

❌ Don’t do this... βœ… Do this instead
Bundle all locales in JS Use native raw resources
Load all languages in memory Let Android handle locale
Rebuild for every change Load dynamically from native (dev. mode only)

Top comments (1)

Collapse
 
kirill3333 profile image
Kirill Novikov

@retyui Nice article, what about iOS?