TacoTranslate
/
DocumentationPricing
 
 
Tutorial
May 22, 2023

How to implement internationalization in a Next.js application that’s using the Pages Router

Make your React application more accessible and reach new markets with internationalization (i18n).

As the world becomes more globalized, it's increasingly important for web developers to build applications that can cater to users from different countries and cultures. One of the key ways to achieve this is through internationalization (i18n), which allows you to adapt your application to different languages, currencies, and date formats.

In this blog post, we'll explore how to add internationalization to your React Next.js application, with server rendering. TL;DR: See the full example here.

This guide is for Next.js applications that are using the Pages Router.
If you are using the App Router, please see this guide instead.

Step 1: Install a i18n library

To implement internationalization in your Next.js application, we’ll first choose an i18n library. There are several popular libraries, including next-intl. However, in this example, we'll be using TacoTranslate.

TacoTranslate automatically translates your strings to any language using cutting-edge AI, and frees you from the tedious management of JSON files.

Let’s install it using npm in your terminal:

npm install tacotranslate

Step 2: Create a free TacoTranslate account

Now that you’ve got the module installed, it’s time to create your TacoTranslate account, a translation project, and associated API keys. Create an account here. It’s free, and doesn’t require you to add a credit card.

Within the TacoTranslate application UI, create a project, and navigate to its API keys tab. Create one read key, and one read/write key. We’ll save them as environment variables. The read key is what we call public and the read/write key is secret. For example, you could add them to a .env file in the root of your project.

TACOTRANSLATE_PUBLIC_API_KEY=123456
TACOTRANSLATE_SECRET_API_KEY=789010

Be sure to never expose your secret API key on client side production environments.

Step 3: Setting up TacoTranslate

To integrate TacoTranslate with your application, you’ll need to create a client using the API keys from earlier. For example, create a file named /utilities/tacotranslate.ts.

/utilities/tacotranslate.ts
import createTacoTranslateClient from 'tacotranslate';

const tacoTranslate = createTacoTranslateClient({
	apiKey:
		process.env.TACOTRANSLATE_SECRET_API_KEY ??
		process.env.TACOTRANSLATE_PUBLIC_API_KEY ??
		process.env.TACOTRANSLATE_API_KEY,
	projectLocale: process.env.TACOTRANSLATE_PROJECT_LOCALE,
});

export default tacoTranslate;

We’ll be automatically defining TACOTRANSLATE_API_KEY and TACOTRANSLATE_PROJECT_LOCALE shortly.

Creating the client in a separate file makes it easier to use again later. Now, using a custom /pages/_app.tsx, we’ll add the TranslationProvider.

/pages/_app.tsx
import React from 'react';
import {type AppProps} from 'next/app';
import {type Locale, type Translations} from 'tacotranslate';
import {TranslationProvider} from 'tacotranslate/react';
import tacoTranslate from '../utilities/tacotranslate';

type PageProperties = {
	origin: string;
	locale: Locale;
	locales: Locale[];
	translations: Translations;
};

export default function App({Component, pageProps}: AppProps<PageProperties>) {
	const {origin, locale, translations} = pageProps;

	return (
		<TranslationProvider
			origin={origin}
			client={tacoTranslate}
			locale={locale}
			translations={translations}
		>
			<Component {...pageProps} />
		</TranslationProvider>
	);
}

If you already have custom pageProps, please extend the definition with the properties from above.

You should now be able to use the Translate component to translate strings within all of your React components!

import {Translate} from 'tacotranslate/react';

function Component() {
	return <Translate string="Hello, world!"/>
}

Step 4: Implementing server rendering

While client side rendering will work just fine, TacoTranslate also allows for server side rendering of your translations. This greatly improves the user experience by showing translated content immediately, instead of a flash of untranslated content first. Additionally, we can skip network requests on the client, because we already have all the translations we need.

We’ll start by adding two more environment variables into .env.

TACOTRANSLATE_DEFAULT_LOCALE=en
TACOTRANSLATE_WEBSITE_URL=your-website-url.com

TACOTRANSLATE_WEBSITE_URL should be set to the production domain of your current project. This ensures your strings will be set on your production origin. If this is set to anything else, you’ll notice translations won‘t work as expected. TACOTRANSLATE_DEFAULT_LOCALE will ensure your React application doesn’t stop working if translations for some reason can’t be fetched. You can view all the available locale codes in your TacoTranslate dashboard.

Next, we’ll create or modify /next.config.js.

/next.config.js
const {default: createTacoTranslateClient} = require('tacotranslate');

module.exports = async () => {
	const publicApiKey = process.env.TACOTRANSLATE_PUBLIC_API_KEY;
	const secretApiKey = process.env.TACOTRANSLATE_SECRET_API_KEY;
	const {getLocales} = createTacoTranslateClient({apiKey: secretApiKey});
	const locales = await getLocales().catch((error) => {
		console.error(error);
		return [process.env.TACOTRANSLATE_DEFAULT_LOCALE];
	});

	const [projectLocale] = locales;
	const isProduction =
		process.env.TACOTRANSLATE_ENV === 'production' ||
		process.env.VERCEL_ENV === 'production' ||
		(!(process.env.TACOTRANSLATE_ENV || process.env.VERCEL_ENV) &&
			process.env.NODE_ENV === 'production');

	return {
		env: {
			TACOTRANSLATE_API_KEY: isProduction ? publicApiKey : secretApiKey,
			TACOTRANSLATE_PROJECT_LOCALE: isProduction ? projectLocale : undefined,
			TACOTRANSLATE_WEBSITE_URL: process.env.TACOTRANSLATE_WEBSITE_URL,
		},
		i18n: {
			defaultLocale: projectLocale,
			locales,
		},
	};
};

There are a few things to note here. First, we’re creating a TacoTranslate client with a secret read/write API key. Then, we’re fetching all the languages you have activated for your translation project. The first string in the response array is the origin locale code you’ve set for the project.

Now for the crucial part: Deciding whether or not we’re in a production environment. Modify the isProduction check to suit your setup. If we’re in a local, test, or staging environment, we should use the secret read/write API key to make sure new strings are sent for translation. If we‘re in a production environment, we should use the public read key.

Up until now, we’ve only set the Next.js application up with a list of supported languages. The next thing we’ll do is fetch translations for all your pages. First, create a new file /utilities/custom-get-static-props.ts.

/utilities/custom-get-static-props.ts
import {type GetStaticPropsContext} from 'next';
import tacoTranslate from './tacotranslate';

export default async function customGetStaticProps(
	path: string,
	{
		locale = process.env.TACOTRANSLATE_PROJECT_LOCALE ??
			process.env.TACOTRANSLATE_DEFAULT_LOCALE,
		locales,
	}: GetStaticPropsContext
) {
	let origin = `localhost:3000${path}`;

	if (process.env.TACOTRANSLATE_WEBSITE_URL) {
		origin = `${process.env.TACOTRANSLATE_WEBSITE_URL}${path}`;
	} else if (process.env.VERCEL_URL) {
		origin = `${process.env.VERCEL_URL}${path}`;
	}

	const translations = await tacoTranslate
		.getTranslations({locale, origin})
		.catch((error) => {
			console.error(error);
			return {};
		});

	return {
		props: {locale, locales, translations, origin},
		revalidate: 60,
	};
}

This function takes two arguments: One path and a Next.js Static Props Context object. We’re also using the TACOTRANSLATE_WEBSITE_URL environment variable from earlier here. Also, note the revalidate property on the return statement, which tells Next.js to re-build the page after 60 seconds. This will keep the server rendered translations up-to-date.

To use this function in a page, let’s assume you’ve got a page file like /pages/hello-world.tsx.

import {Translate} from 'tacotranslate/react';
import customGetStaticProps from '../utilities/custom-get-static-props';

const path = '/hello-world';

export async function getStaticProps(context) {
	return customGetStaticProps(path, context);
}

export default function Page() {
	return <Translate string="Hello, world!"/>;
}

To ensure we’re fetching translations for the correct page, you’ll need to specify the current pathname within your code. Unfortunately, this information is not provided to us by getStaticProps. pathname should look like your folder path.

For example, if your page is located on pages/user/[id].tsx:

const path = '/user/[id]';

Identical pages should have the same path. Dynamic URL fragments should not be included in the path.

Step 5: Deploy and test!

We’re done! Your React application will now be translated automatically when you add any strings to a Translate component. Note that only environments with read/write permissions on the API key will be able to create new strings to be translated. We recommend having a closed and secured staging environment where you can test your production application with an API key like that, adding new strings before going live. This will prevent anyone anyone from stealing your secret API key, and potentially bloating your translation project by adding new, unrelated strings.

Be sure to check out the complete example over at our GitHub profile. There, you’ll also find an example of how to do this using the App Router! If you encounter any problems, feel free to reach out, and we’ll be more than happy to help.

TacoTranslate lets you automatically localize your React applications quickly to and from any language. Get started today!