Easy Internationalization and in React Native
Internationalization can be a pain For the Brink mobile app, we developed a system that we didn't hate and scaled well.
This is how we organized the i18n logic.
src
├── i18n
│ ├── __tests__
│ │ └── i18n.test.js
│ ├── i18n.js
│ └── locales
│ ├── en.js
│ └── es.js
This next part is where the magic happens. On app load, we pull in the system language so we don't need to ask the user what their preferred language is.
// src/i18n.js
import DeviceInfo from "react-native-device-info"
import I18n from "react-native-i18n"
import en from "./locales/en"
import es from "./locales/es"
/**
* Grab the system locale ('en_US' or 'es_US') from the phones local settings
* and convert it to a two letter language code used by I18n.js. Android returns
* a 4 letter locale, iOS returns two.
* @return {String}
*/
export const getSystemLocale = () => DeviceInfo.getDeviceLocale().substring(0, 2)
I18n.defaultLocale = "en"
I18n.locale = getSystemLocale()
I18n.fallbacks = true
I18n.translations = {
en,
es,
}
export default I18n
Then, you write your translations for each language as a JavaScript object:
// en.js
const translations = {
Nav: {
today: {
title: "Today",
a11yTitle: "Navigate to Today",
},
profile: {
title: "My Profile",
a11yTitle: "Navigate to My Profile",
},
},
}
Then, in your JSX files, you can reference your localizations:
import { createBottomTabNavigator } from "react-navigation"
import TodayContainer from "~/components/TodayContainer"
import ProfileContainer from "~/components/ProfileContainer"
import i18n from "~/i18n/i18n"
const { nav } = i18n.t("Nav")
const tabNavigator = createMaterialTopTabNavigator(
{
Today: {
screen: TodayContainer,
navigationOptions: {
title: nav.today.title,
tabBarAccessibilityLabel: nav.today.a11yTitle,
},
},
Profile: {
screen: ProfileContainer,
navigationOptions: {
title: nav.profile.title,
tabBarAccessibilityLabel: nav.profile.a11yTitle,
},
},
},
}
)