# react-native: React Native Quickstart with Expo
URL: https://generaltranslation.com/en-US/docs/react-native.mdx
---
title: React Native Quickstart with Expo
description: Easily internationalize your React Native App with gt-react-native and Expo
---
`gt-react-native` is still experimental and may not work for all projects.
Please let us know if you encounter any issues by [opening an issue on GitHub](https://github.com/generaltranslation/gt/issues).
**Quick Setup:** Try `npx gtx-cli@latest` for automatic configuration. See the
[Setup Wizard](/docs/cli/init) guide or use our [AI tools
integration](/docs/overview/ai-tools).
Looking for React Native CLI app quickstart? See our [React Native Quickstart](/docs/react-native/tutorials/quickstart) guide.
## Installation
Install the `gt-react-native` and `gtx-cli` packages:
```bash
npm i gt-react-native
npm i -D gtx-cli
```
```bash
yarn add gt-react-native
yarn add --dev gtx-cli
```
```bash
bun add gt-react-native
bun add --dev gtx-cli
```
```bash
pnpm add gt-react-native
pnpm add --save-dev gtx-cli
```
## Setup
### Configuration
Create a `gt.config.json` file in your project root.
This will contain your project's configuration.
```json title="gt.config.json"
{
"defaultLocale": "en",
"locales": ["fr", "es"],
"files": {
"gt": {
"output": "content/[locale].json"
}
}
}
```
Here we have specified that we will translate our project into French and Spanish, and we want to save our translations to the `content/[locale].json` file.
### Environment variables
Add to your `.env.local` file for development hot-reloading and on-demand translations:
```bash title=".env.local"
EXPO_PUBLIC_GT_DEV_API_KEY="your-dev-api-key"
EXPO_PUBLIC_GT_PROJECT_ID="your-project-id"
```
**Dev vs prod keys:** Use a `gtx-dev-` key locally. Use a production key (`gtx-api-`) in CI/CD if you run `gtx-cli translate` during deploy.
Never expose production API keys in your app bundle or commit them to source control.
Example production environment variables:
```bash title=".env"
GT_API_KEY="your-production-api-key"
GT_PROJECT_ID="your-project-id"
```
Get your free API keys at [dash.generaltranslation.com](https://dash.generaltranslation.com/signup) or run:
```bash
npx gtx-cli auth
```
`gt-react-native` is an i18n library that can work standalone without any environment variables.
Without them, the library will act very similarly to other i18n libraries, and will still have core internationalization functionality.
However, `gt-react-native` also offers a native integration with the General Translation platform.
This integration unlocks additional functionality in the library, such as:
- Translation Hot Reloading in Development
- Automatic AI translations
- Syncing translations with the General Translation platform
- Native integration with our translation CDN
To avoid using the General Translation platform, just don't set any environment variables.
### Loading translations
Next, create a `loadTranslations.ts` file in your project root.
This will handle pulling translations from the `content/[locale].json` files.
```tsx title="loadTranslations.ts"
// Unfortunately, metro is not compatible with dynamic imports,
// so we must specify the translations for each locale manually.
const translations: Record = {
fr: require("@/content/fr.json"),
es: require("@/content/es.json"),
};
export function loadTranslations(locale: string) {
return translations[locale] ?? {};
}
```
You can use the `loadTranslations` function to load translations from a custom source.
This is useful when you need to load translations from a different source, such as a custom API.
### `GTProvider` [#provider]
The [`GTProvider`](/docs/react-native/api/components/gtprovider) component provides translation context to client-side components. It manages locale state, translations, and enables the [`useGT`](/docs/react-native/api/strings/use-gt) and [`useTranslations`](/docs/react-native/api/dictionary/use-translations) hooks.
Add the [`GTProvider`](/docs/react-native/api/components/gtprovider) to your root component:
```tsx title="_layout.tsx"
import { GTProvider } from 'gt-react-native';
import gtConfig from '../gt.config.json';
import { loadTranslations } from './loadTranslations.ts';
export default function RootLayout() {
return (
{children}
)
}
```
### Polyfills
Because the React Native JS runtime does not automatically polyfill the `Intl` object, you need to polyfill it manually.
You can either use the babel plugin or polyfill manually.
#### Babel plugin
For the babel plugin, under `entryPointFilePath` just specify the entry point of your app (can often be found in the `"main"` field of your `package.json`).
```js title="babel.config.js"
import gtPlugin from 'gt-react-native/plugin';
import { createRequire } from 'module';
import gtConfig from './gt.config.json' with { type: 'json' };
const require = createRequire(import.meta.url);
export default function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
[
gtPlugin,
{
locales: [gtConfig.defaultLocale, ...gtConfig.locales],
entryPointFilePath: require.resolve('expo-router/entry'),
},
],
],
};
}
```
#### Manual polyfilling
If you run into issues with the babel plugin, you can polyfill manually.
You will need to npm install and then polyfill the base imports as well as locale-specific imports.
The following is an example of polyfilling every possible import, but in reality, you may only need a subset of these.
For more information see [FormatJS's documentation on polyfilling](https://formatjs.github.io/docs/polyfills).
```tsx title="main.tsx"
// base polyfills:
import '@formatjs/intl-getcanonicallocales/polyfill';
import '@formatjs/intl-locale/polyfill';
import '@formatjs/intl-displaynames/polyfill';
import '@formatjs/intl-listformat/polyfill';
import '@formatjs/intl-pluralrules/polyfill-force'; // https://github.com/formatjs/formatjs/issues/4463
import '@formatjs/intl-numberformat/polyfill';
import '@formatjs/intl-relativetimeformat/polyfill';
import '@formatjs/intl-datetimeformat/polyfill';
import '@formatjs/intl-datetimeformat/add-all-tz';
// locale polyfills:
// en polyfills
import '@formatjs/intl-displaynames/locale-data/en';
import '@formatjs/intl-listformat/locale-data/en';
import '@formatjs/intl-pluralrules/locale-data/en';
import '@formatjs/intl-numberformat/locale-data/en';
import '@formatjs/intl-relativetimeformat/locale-data/en';
import '@formatjs/intl-datetimeformat/locale-data/en';
// zh polyfills
import '@formatjs/intl-displaynames/locale-data/zh';
import '@formatjs/intl-listformat/locale-data/zh';
import '@formatjs/intl-pluralrules/locale-data/zh';
import '@formatjs/intl-numberformat/locale-data/zh';
import '@formatjs/intl-relativetimeformat/locale-data/zh';
import '@formatjs/intl-datetimeformat/locale-data/zh';
```
---
## Testing your app
Test your translations by switching languages:
1. **Add a locale selection dropdown** using [``](/docs/react-native/api/components/locale-selector):
```tsx
import { LocaleSelector } from 'gt-react-native';
function App() {
return ;
}
```
2. **Start your dev server**:
```bash
npx expo start --dev-client
```
3. Visit your development app and change languages via the locale selection dropdown.
In development, translations happen on-demand (you'll see a brief loading time). In production, translations are pre-generated by the CLI.
### Troubleshooting
```bash
ERROR [Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'GtReactNative' could not be found. Verify that a module by this name is registered in the native binary.]
```
This error occurs when the `gt-react-native` native module hasn't been linked into your app binary. Common causes:
1. **You're using Expo Go instead of a development build.** Expo Go doesn't support custom native modules. Switch to a development build:
```bash
npx expo run:ios
# or
npx expo run:android
```
2. **Pods are out of date (iOS).** If you're already using a development build, try reinstalling pods:
```bash
cd ios && pod install && cd ..
```
If that doesn't work, try a clean install:
```bash
cd ios && rm -rf build Pods Podfile.lock && pod install && cd ..
```
**On-Demand Translation**
You may notice when loading languages in development, translations will take a few seconds to be displayed.
This happens because your app is being translated in real time.
We refer to this process as an "on-demand translation".
This **only happens in dev** so you can easily prototype your app in different languages.
All translations are preloaded in production, so there will be no delay.
Follow our guide on [shipping to production](/docs/react-native/tutorials/quickdeploy).
The most likely cause of an inaccurate translation is ambiguous wording.
For example, "apple" can be a fruit or a technology company.
To fix this, you can provide more context to the translation with the `context` prop.
The [``](/docs/react-native/api/components/t) component and [`useGT`](/docs/react-native/api/strings/use-gt) hook both support a `context` prop.
For example:
```jsx
Apple
```
---
## Deployment
For production, you need to translate content since runtime translation is disabled.
1. **Get a production API key** from [dash.generaltranslation.com](https://dash.generaltranslation.com).
Production keys begin with `gtx-api-` (different from dev keys which start with `gtx-dev-`). Learn more about [environment differences](/docs/react-native/concepts/environments).
2. **Add to your CI/CD environment**:
```bash
GT_PROJECT_ID=your-project-id
GT_API_KEY=gtx-api-your-production-key
```
3. **Run the translate command** to translate your content:
```bash
npx gtx-cli translate
```
You can configure the behavior of the translate command with the [`gt.config.json`](/docs/cli/reference/config) file.
See the [CLI Tool](/docs/cli/translate) reference guide for more information.
4. **Update your build script** to translate before building:
```json title="package.json"
{
"scripts": {
"build": "npx gtx-cli translate && <...YOUR_BUILD_COMMAND...>"
}
}
```
If you're not using the General Translation platform, you can still use `gt-react-native` in production.
However, you'll need to manually translate your content before deploying your application.
Instead of running `translate`, run the `generate` command to generate JSON files containing all of your translation data (in your source language).
```bash
npx gtx-cli generate
```
Then, you'll need to manually edit / translate these files, and load them into your application with [`loadTranslations`](/docs/react-native/guides/local-tx).
## Next steps
- [`` Component Guide](/docs/react-native/guides/t) - Deep dive into the [``](/docs/react-native/api/components/t) component and JSX translation
- [String Translation Guide](/docs/react-native/guides/strings) - Using [`useGT`](/docs/react-native/api/strings/use-gt)
- [Variable Components](/docs/react-native/guides/variables) - Handle dynamic content with [``](/docs/react-native/api/components/var), [``](/docs/react-native/api/components/num), etc.