Making Your App Multilingual

The boilerplate includes a ready-to-use internationalization (i18n) system that makes creating multilingual apps simple. This guide will walk you through the process with practical examples.

What You’ll Learn

  • How to use existing translations
  • Adding new text and phrases
  • Working with dynamic content (variables)
  • Creating a new language
  • Building a complete multilingual feature

Simple Translation Examples

Let’s learn how to use translations in your app with a simple Fortune Cookie example.

Step 1: Set Up Your Translation Files

1

Find the translation files

Your app already has translation files in:
lib/i18n/locales/en/common.json  # English
lib/i18n/locales/fr/common.json  # French
2

Add translations to English file

Open lib/i18n/locales/en/common.json and add:
{
  "fortune": {
    "title": "Your Fortune",
    "message": "Today is your lucky day!",
    "button": "New Fortune"
  }
}
3

Add same translations in French

Open lib/i18n/locales/fr/common.json and add:
{
  "fortune": {
    "title": "Votre Fortune",
    "message": "Aujourd'hui est votre jour de chance !",
    "button": "Nouvelle Fortune"
  }
}

Step 2: Use the Translations in Your Component

Here’s a basic example of using translations:
import { View } from 'react-native';
import { Text } from '~/components/ui/text';
import { Button } from '~/components/ui/button';
import { useTranslation } from '~/lib/i18n/useTranslation';

export function FortuneMessage() {
  // This gives you the translation function
  const { t } = useTranslation();
  
  return (
    <View className="p-4 bg-card rounded-lg">
      {/* Title in current language */}
      <Text className="text-xl font-bold text-foreground mb-2">
        {t('fortune.title')}
      </Text>
      
      {/* Fortune message in current language */}
      <Text className="text-muted-foreground mb-4">
        {t('fortune.message')}
      </Text>
      
      {/* Button with text in current language */}
      <Button onPress={() => {}}>
        <Text className="text-primary-foreground">
          {t('fortune.button')}
        </Text>
      </Button>
    </View>
  );
}
That’s it! The component will automatically display text in the user’s selected language.

Step 3: Using Variables in Translations

You can also include dynamic content in your translations:
1

Add translations with variables

Add to your English file (en/common.json):
{
  "greeting": {
    "welcome": "Welcome, {{name}}!",
    "lucky_number": "Your lucky number today is {{number}}."
  }
}
And to your French file (fr/common.json):
{
  "greeting": {
    "welcome": "Bienvenue, {{name}} !",
    "lucky_number": "Votre numéro de chance aujourd'hui est {{number}}."
  }
}
Notice the {{name}} and {{number}} placeholders.
2

Use variables in your component

Here’s how to use these translations with variables:
import { View } from 'react-native';
import { Text } from '~/components/ui/text';
import { Card } from '~/components/ui/card';
import { useTranslation } from '~/lib/i18n/useTranslation';

export function Greeting() {
const { t } = useTranslation();
const userName = 'Alex';
const luckyNumber = 7;

return (
<Card className="p-4">
  {/* Pass the name variable to the translation */}
  <Text className="text-lg font-bold mb-2">
    {t('greeting.welcome', { name: userName })}
  </Text>
  
  {/* Pass the number variable to the translation */}
  <Text className="text-muted-foreground">
    {t('greeting.lucky_number', { number: luckyNumber })}
  </Text>
</Card>
);
}
The second parameter to the t() function is an object containing your variable values.

Adding a New Language

Now let’s add Spanish as a new language option:
1

Create language folder and file

# Create folder for Spanish translations
mkdir lib/i18n/locales/es

# Copy English file as a template
copy lib/i18n/locales/en/common.json lib/i18n/locales/es/common.json
2

Translate to new language

Edit lib/i18n/locales/es/common.json with Spanish translations:
{
  "profile": {
    "greeting": "¡Hola, {{name}}! Actualiza tu perfil a continuación.",
    "title": "Tu Perfil",
    "nameLabel": "Nombre Completo",
    "emailLabel": "Correo Electrónico",
    "bioLabel": "Acerca de Mí",
    "saveButton": "Guardar Perfil",
    "successMessage": "¡Perfil actualizado con éxito!"
  }
}
3

Register the new language

Open lib/i18n/i18n.ts and update it to include Spanish:
// Import language files
import enCommon from './locales/en/common.json';
import frCommon from './locales/fr/common.json';
import esCommon from './locales/es/common.json'; // Add this

// Configure resources
const resources = {
  en: { common: enCommon },
  fr: { common: frCommon },
  es: { common: esCommon }  // Add this
};
4

Add to language selector

Find the language selection component (components/account/LanguageSettingsSheet.tsx) and add Spanish:
const languages = [
  { code: 'en', name: 'English', nativeName: 'English' },
  { code: 'fr', name: 'French', nativeName: 'Français' },
  { code: 'es', name: 'Spanish', nativeName: 'Español' }, // Add this
];

Testing Your Translations

To make sure your translations work correctly:
  1. Open your app and navigate to the language settings (usually in the account/settings section)
  2. Switch between languages and verify your text appears correctly
  3. Check that variable substitutions work as expected

Best Practices

  • Stay organized: Group translations by feature (“profile”, “settings”, etc.)
  • Be consistent: Use the same key naming patterns throughout
  • Keep keys in English: Even for translations, keep the key names in English
  • Test thoroughly: Test all languages after adding new translations
  • Use descriptive keys: Keys like “profile.nameLabel” are self-explanatory

Additional Resources