Product teams
Deliver localized versions of your product faster by automating tedious localization steps.
Localization teams
Streamline your workflows and simplify collaboration with efficient localization management.
Developers teams
Add Transifex to your CI/CD pipeline to continuously deploy new translations.
Marketing teams
Quickly launch multilingual websites to accelerate international growth and conversions.
Translators
Deliver more accurate translations faster, leveraging advanced linguistic tools.
Software localization
Keep software continuously localized and in sync using automated CI/CD workflows.
Website localization
Automate and scale website localization to attract and convert international visitors.
Mobile App localization
Rapidly translate and launch apps globally, ensuring high-quality user experiences across markets.
Get a Personalized Demo Today
Precise, on-brand translations at scale. Language AI delivers context-rich content faster.
Get a personalized demo today
Request a personalized demo to learn how to integrate Transifex into your CI/CD
Product teams
Deliver localized versions of your product faster by automating tedious localization steps.
Localization teams
Streamline your workflows and simplify collaboration with efficient localization management.
Developers teams
Add Transifex to your CI/CD pipeline to continuously deploy new translations.
Marketing teams
Quickly launch multilingual websites to accelerate international growth and conversions.
Translators
Deliver more accurate translations faster, leveraging advanced linguistic tools.
Software localization
Keep software continuously localized and in sync using automated CI/CD workflows.
Website localization
Automate and scale website localization to attract and convert international visitors.
Mobile App localization
Rapidly translate and launch apps globally, ensuring high-quality user experiences across markets.
Get a Personalized Demo Today
Precise, on-brand translations at scale. Language AI delivers context-rich content faster.
Get a personalized demo today
Request a personalized demo to learn how to integrate Transifex into your CI/CD
A well-internationalized app creates a more inclusive user experience – breaking down language barriers and becoming accessible to a wider range of users worldwide. A popular way to implement i18n for your Next.js application is to leverage its inbuilt features.
In this article, we’ve provided a step-by-step guide to localizing a Next.js app using the same approach.
However, this process requires handling multiple files, which can quickly become complex as your app scales.
As an alternative solution, we also discuss a popular localization tool called Transifex Native, which you can directly integrate into your code. This tool allows seamless over-the-air updates of all translations in real-time and provides a convenient way to manage localization.
Let’s get started!
Before we get started with the actual process, let’s quickly recap some fundamental internationalization terminologies:
Locale: It refers to a specific combination of language, region, and cultural conventions used to customize the user experience in software applications.
It includes language codes (such as "en" for English, and "fr" for French), country codes (such as "US" for the United States, and "FR" for France), and additional parameters like date formats, currency symbols, and measurement units.
Routing: In the context of internationalization, routing involves directing users to language-specific versions of a website or application based on their preferences or location. Two common routing strategies are used: Sub-path routing and domain routing.
i18n: Internationalization, often represented by i18n, involves developing software applications adaptable to different languages and regions without requiring code changes.
This includes separating language-specific elements from the core application logic, allowing for easy integration of multiple languages and cultural conventions.
L10n: Localization, or L10N, is the process of adapting a software application or product to the linguistic, cultural, and technical requirements of a specific locale.
This involves translating text and multimedia elements, formatting dates, numbers, and currency, and adjusting other user interface aspects to align with local preferences and conventions.
Since version 10.0.0, Next.js offers native support for internationalized (i18n) routing. With built-in support for defining locales, default locale settings, and domain-specific locales, Next.js automatically handles the routing for you.
When a user accesses the application root (typically /), Next.js automatically detects the preferred locale based on the Accept-Language header and the current domain.
If a locale different from the default is identified:
Let's walk through the step-by-step process of internationalizing a Next.js example app.
If you haven’t already, let’s start by creating a new Next.js app. Here, we are using “my-app” as an example.
To create a new project, use the following command:
<code class="language-shell-session">npx create-next-app@latest my-app</code>
This command sets up everything automatically for you based on the following prompts:
Would you like to use TypeScript? [No]
Would you like to use ESLint? [Yes]
Would you like to use Tailwind CSS? [No]
Would you like to use `src/` directory? [Yes]
Would you like to use App Router? (recommended) [Yes]
Would you like to customize the default import alias (@/*)? [No]
Here are two system requirements for the installation:
Next.js offers two primary routing methods:
Once you’ve created the project, move to the project directory using:
<code class="language-shell-session">cd my-app</code>
Now, install the necessary dependencies for internationalization. For this guide, we'll use `next-intl` due to its ease of use in Next.js environments. Alternatively, you can also use `react-intl` with your Next.js app.
Use the following command to install dependencies:
<code class="language-shell-session">npm install next-intl</code>
Create a `next.config.js` file in the root directory of your project if it doesn't exist already.
Now, add the following configuration to enable i18n routing:
module.exports = {
i18n: {
locales: ['en', 'fr'], // Add your supported locales
defaultLocale: 'en', // Set the default locale
},
// ... other Next.js configurations
};
Here, we’re setting the default locale to English (en) and specifying the supported locales – English (en) and French (fr).
If you opt for app routing, create a directory named `app` under your `my-app` project root. This directory will house your app components and layouts.
You don't need to create an app directory if you're using page routing. Simply proceed with the next steps.
Note: Regardless of the routing approach, the `next.config.js` configuration is essential for both to enable i18n routing.
Create a directory named `locales` under your `my-app` project root.
Now, inside`locales`, create JSON files for each supported language (e.g., `en.json`, `fr.json`). Once done, add your translatable strings as key-value pairs in these JSON files.
// en.json
{
"welcome": "Welcome to my app!",
"home": "Home",
"about": "About"
}
// fr.json
{
"welcome": "Bienvenue sur mon application!",
"home": "Accueil",
"about": "À propos"
}
This step differs slightly depending on your routing method. Let’s discuss both.
For App Routing:
This approach is ideal for complex applications with nested layouts and server-side components.
Here’s an example:
import { appWithTranslation } from 'next-intl';
function RootLayout({ children }) {
return appWithTranslation(children);
}
export default RootLayout;
For Page Routing:
Here’s an example of page routing:
import { appWithTranslation } from 'next-intl';
function MyApp({ Component, pageProps }) {
return appWithTranslation(Component, pageProps);
}
export default MyApp;
Import `useTranslation` from `next-intl` in your components (app or page components depending on your routing).
Now, you can access translated strings using the `t` function provided by `useTranslation`.
Here’s how you can implement it:
import { useTranslation } from 'next-intl';
function MyComponent() {
const { t } = useTranslation();
return (
<div>
<h1>{t('welcome')}</h1>
<p>
<a href="/">
{t('home')}
</a>
</p>
<p>
<a href="/about">
{t('about')}
</a>
</p>
</div>
);
}
For example, in a component named `HomePage.js`, you may use it this way:
import { useTranslation } from 'next-intl';
function HomePage() {
const { t } = useTranslation();
return (
<div>
<h1>{t('welcome')}</h1>
<p>
<a href="/">
{t('home')}
</a>
</p>
<p>
<a href="/about">
{t('about')}
</a>
</p>
</div>
);
}
export default HomePage;
This code retrieves the translated strings for "welcome," "home," and "about" from the active locale's JSON file and displays them within the component.
If you have data fetching on the server using `getStaticProps` or `getServerSideProps`, provide the correct locale during data fetching:
While the basic setup provides core internationalization functionality, you might consider using `i18n.js` and `middleware.js` files for complex scenarios.
- The `i18n.js` file creates custom logic for detecting the user's preferred locale. To implement this, create a file named `i18n.js` in your project's root directory. This file can house the custom i18n logic for complex applications.
Here’s a sample `i18n.js` file. You can provide messages and other options depending on the locale of the user.
import {notFound} from 'next/navigation';
import {getRequestConfig} from 'next-intl/server';
// Can be imported from a shared config
const locales = ['en', 'de'];
export default getRequestConfig(async ({locale}) => {
// Validate that the incoming `locale` parameter is valid
if (!locales.includes(locale as any)) notFound();
return {
messages: (await import(`../messages/${locale}.json`)).default
};
});
- The middleware matches a locale for the request and handles redirects and rewrites accordingly. To implement it, create a file named `middleware.js` in your project's root directory.
Here’s a sample middleware file:
import createMiddleware from 'next-intl/middleware';
export default createMiddleware({
// A list of all locales that are supported
locales: ['en', 'de'],
// Used when no locale matches
defaultLocale: 'en'
});
export const config = {
// Match only internationalized pathnames
matcher: ['/', '/(de|en)/:path*']
};
As discussed, internationalizing your Next.js application can involve managing multiple translation files. This can quickly turn complex when scaling your application or adding more locales.
A simpler internationalization approach that bypasses the hassle of files is to use Transifex Native. This tool is built upon Next.js’ built-in internationalization features, which take care of translation files behind the scenes. Transifex Native also serves translations over the air (OTA), with additional caching and grouping functionality that you control.
To integrate the tool with your Next.js app now, Sign up for a free trial on Transifex.
Once you’ve created your account, follow the next steps to start using Transifex Native to internationalize your Next.js application.
In your Next.js app, install the Transifex Native dependencies for React applications.
Use the following code:
<code class="language-shell-session">npm install @transifex/native @transifex/react @transifex/cli --save</code>
Edit or create a `next.config.js` file in your root folder. Now, add the supported locales and your Transifex Native public token.
// next.config.js
module.exports = {
i18n: {
// These are all the locales you want to support in
// your application
locales: ['en', 'fr', 'de'],
// This is the default locale you want to be used when visiting
// a non-locale prefixed path e.g. `/hello`
defaultLocale: 'en',
localeDetection: false,
},
publicRuntimeConfig: {
TxNativePublicToken: 'YOUR-PUBLIC-TX-NATIVE-TOKEN',
}
}
Add a new `i18n.js` library file in your source folder where the code exists.
Once created, paste the following code:
// nextjs/i18n.js
import { tx, normalizeLocale } from '@transifex/native';
import getConfig from 'next/config';
const { publicRuntimeConfig } = getConfig();
/**
* Used by SSR to pass translation to browser
*
* @param {*} { locale, locales }
* @return {*} { locale, locales, translations }
*/
export async function getServerSideTranslations({ locale, locales }) {
tx.init({
token: publicRuntimeConfig.TxNativePublicToken,
});
// ensure that nextjs locale is in the Transifex format,
// for example, de-de -> de_DE
const txLocale = normalizeLocale(locale);
// load translations over-the-air
await tx.fetchTranslations(txLocale);
return {
locale,
locales,
translations: tx.cache.getTranslations(txLocale),
};
}
/**
* Initialize client-side Transifex Native instance cache
*
* @param {*} { locale, translations }
*/
export function setClientSideTranslations({ locale, translations }) {
if (!locale || !translations) return;
tx.init({
currentLocale: locale,
});
tx.cache.update(locale, translations);
}
After the strings have been marked for translation in the code, you can upload them to Transifex.
Use `@transifex/cli` library to collect all translatable strings and push them to Transifex using the following command:
<code class="language-shell-session">$ npx txjs-cli push <SRC_FOLDER> --token=<PROJECT_TOKEN> --secret=<PROJECT_SECRET></code>
The `@transifex/native` library can be used to push any content from various sources, such as custom files, database etc.
Here’s how it can be done:
const { tx } = require('@transifex/native');
tx.init({
token: 'token',
secret: 'secret',
});
await tx.pushSource({
'mykey': {
string: 'My string',
meta: {
context: 'content', // optional
developer_comment: 'developer comment', // optional
character_limit: 10, // optional
tags: ['tag1', 'tag2'], // optional
occurrences: ['file.jsx', 'file2.js'], // optional
},
}
});
On the pages you'd like i18n to be translated, load translations server-side, and pass them to the client using `getServerSideProps` and `setClientSideTranslations`.
Here’s a sample code below that you can use:
// nextjs/pages/index.js
import { useState } from 'react';
import { T, UT } from '@transifex/react';
import { useRouter } from 'next/router';
import { getServerSideTranslations, setClientSideTranslations } from '../i18n';
export default function Home(props) {
// initialize client-side translation from server side props
setClientSideTranslations(props); // { locale, locales, translations }
return (
<div>
<T _str="Hello world" />
</div>
);
}
export async function getServerSideProps(context) {
const data = await getServerSideTranslations(context)
return {
props: {
...data, // { locale, locales, translations }
}
}
}
To understand better with a live example, view Transifex Native Sandbox. Want to localize a React application? Refer to our Step-by-Step Guide for React Localization.
To get the most out of Transifex, here are some advanced features that you can implement.
If you don’t want to set translations on every page, you can also move the code in the Custom App space. This helps you set your translations globally.
To override the default App component provided by Next.js, use the following code to create a `pages/_app.js` file:
import type { AppProps } from 'next/app'
export default function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
The `Component` prop is the active page, so whenever you navigate between routes, `Component` will change to the new page. Therefore, any props you send to `Component` will be received by the page.
Now, use the following code inside the file:
// nextjs/pages/_app.js
import { setClientSideTranslations } from '../i18n';
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
setClientSideTranslations(pageProps);
return <Component {...pageProps} />
}
You can program custom automatic refresh logic by making some modifications to the `i18n.js` utility function from the previous example.
This will help your app check for fresh translations at specific intervals.
Here’s a sample example for refreshing translations every 10 minutes. To change the interval, modify the `TRANSLATIONS_TTL_SEC` variable with an interval of your choice.
// ------------ <NEW> ------------
const TRANSLATIONS_TTL_SEC = 10 * 60; // 10 minutes
// ------------ </NEW> -----------
/**
* Used by SSR to pass translation to browser
*
* @export
* @param {*} { locale, locales }
* @return {*}
*/
export async function getServerSideTranslations({ locale, locales }) {
tx.init({
token: publicRuntimeConfig.TxNativePublicToken,
});
// ensure that nextjs locale is in the Transifex format,
// for example, de-de -> de_DE
const txLocale = normalizeLocale(locale);
await tx.fetchTranslations(txLocale);
// ------------ <NEW> ------------
// bind a helper object in the Native instance for auto-refresh
tx._autorefresh = tx._autorefresh || {};
if (!tx._autorefresh[txLocale]) {
tx._autorefresh[txLocale] = Date.now();
}
// check for stale content in the background
if (Date.now() - tx._autorefresh[txLocale] > TRANSLATIONS_TTL_SEC * 1000) {
tx._autorefresh[txLocale] = Date.now();
tx.fetchTranslations(txLocale, { refresh: true });
}
// ------------ </NEW> -----------
return {
locale,
locales,
translations: tx.cache.getTranslations(txLocale),
};
}
If your app deals with a lot of content, you can leverage Content Splitting to get optimal performance and reduce data use.
To tag content directly into the code, use the following:
import React, { Component } from 'react';
import { T } from '@transifex/react';
class Example extends Component {
render() {
const user = 'Joe';
return (
<div>
<T _str="Hello world" _tags="homepage" />
<T _str="Hello {username}" username={user} _tags="homepage" />
</div>
);
}
}
By following the steps discussed in our guide, you'll successfully implement i18n in your Next.js application.
Whether you choose a basic setup with the next-intl configuration or leverage the automation capabilities of Transifex Native, you'll be equipped to cater to a global audience.
While Next.js provides in-built features for your i18n and L10N processes, it still requires you to handle files manually. This can be a hassle whether you are trying to track translation versions or collaborate with your team.
Transifex simplifies any issues related to manual translation management by:
Transifex also provides AI-powered tools to scale your content localization at a fraction of the cost and time otherwise required. This AI tool combines the power of public LLMs with human-generated context to ensure error-free translations that maintain your brand voice.
These translations are also SEO-optimized and fit any UI design to suit both the SERPs and your potential customers.
Ready to simplify your Next.js internationalization process? Sign up for a free Transifex account today.