English

Learn how to implement seamless internationalization (i18n) in your Next.js applications to reach a global audience. Covers routing, content translation, and best practices.

Next.js Internationalization: Building Multi-language Apps for a Global Audience

In today's interconnected world, building applications that cater to a global audience is no longer a luxury – it's a necessity. Next.js, a powerful React framework, provides robust features for implementing internationalization (i18n), allowing you to create multi-language applications that deliver a localized experience to users worldwide. This comprehensive guide will walk you through the essential concepts, techniques, and best practices for building internationalized Next.js applications.

Understanding Internationalization and Localization

Before diving into the specifics of Next.js i18n, let's clarify the key terms:

Essentially, i18n prepares your application for localization. By separating language-dependent elements from the core code, you make it easier to localize the application for different markets.

Why Implement Internationalization in Next.js?

Implementing i18n in your Next.js application offers numerous benefits:

Next.js i18n Features and Configuration

Next.js offers built-in support for i18n through its routing and content management features. The following is a breakdown of the important features:

1. Configuring i18n in next.config.js

The core configuration for i18n resides within the next.config.js file. Here’s an example:


/** @type {import('next').NextConfig} */
const nextConfig = {
  i18n: {
    locales: ['en', 'es', 'fr'], // An array of supported locales (language codes)
    defaultLocale: 'en', // The default locale to use
    localeDetection: true, // Enable/disable automatic locale detection based on browser settings (optional)
    //  domains: [
    //  {
    //    domain: 'example.com',
    //    defaultLocale: 'en',
    //  },
    //  {
    //    domain: 'example.es',
    //    defaultLocale: 'es',
    //  },
    //  ],
  },
}

module.exports = nextConfig;

Explanation:

2. Routing with Locale Prefixes

Next.js automatically prefixes routes with the locale. For example, if you have a page at /about and the locale is 'es' (Spanish), the URL will become /es/about. This enables different language versions of pages and enables search engines to index content for each locale. The framework handles the redirect and routing for you.

3. Utilizing useRouter Hook

The useRouter hook from next/router provides access to the current locale and other routing information.


import { useRouter } from 'next/router';

function MyComponent() {
  const router = useRouter();
  const { locale, locales, defaultLocale } = router;

  return (
    

Current locale: {locale}

Available locales: {locales.join(', ')}

Default locale: {defaultLocale}

); } export default MyComponent;

The router object offers the following key properties:

Content Translation Strategies

Once you've configured your Next.js application for i18n, you'll need to implement strategies for translating your content. Here are several popular approaches:

1. Using a Dedicated Translation Management System (TMS)

For large-scale projects with many languages, a TMS is highly recommended. Popular options include:

Benefits:

2. Creating JSON Translation Files

For smaller projects, using JSON files to store translations is a simple and effective method.

Example Directory Structure:


/src
├── locales
│   ├── en.json
│   └── es.json
├── components
│   └── MyComponent.js
└── pages
    └── index.js

Example en.json:


{
  "greeting": "Hello, world!",
  "welcomeMessage": "Welcome to our website."
}

Example es.json:


{
  "greeting": "¡Hola, mundo!",
  "welcomeMessage": "Bienvenido a nuestro sitio web."
}

Example MyComponent.js:


import { useRouter } from 'next/router';
import en from '../locales/en.json';
import es from '../locales/es.json';

function MyComponent() {
  const { locale } = useRouter();
  const t = locale === 'es' ? es : en;

  return (
    

{t.greeting}

{t.welcomeMessage}

); } export default MyComponent;

This approach provides flexibility and is straightforward for smaller projects. It’s generally easy to update and maintain.

3. Using a Translation Library

Several JavaScript libraries streamline content translation within your React components.

Example with next-i18next (Installation: npm install next-i18next i18next react-i18next):

Create an i18n configuration file (e.g., i18n.js in your root directory):


// i18n.js
import { createServerSideHelpers } from 'next-i18next'
import { i18n } from './next-i18next.config'

export function initI18next(req, res, namespaces = ['common']) {
  const helpers = createServerSideHelpers(
    req, 
    res, 
    i18n, 
    namespaces
  )

  return helpers
}

export { appWithTranslation } from 'next-i18next'
export { i18n }

Create your Next.js configuration for next-i18next.


// next-i18next.config.js
const { i18n } = require('./next-i18next.config');

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es', 'fr'],
  },
  // other configuration
}

module.exports = nextConfig

Add the configuration and the translation import to your _app.js:


import { appWithTranslation } from 'next-i18next';
import '../styles/globals.css';

function MyApp({ Component, pageProps }) {
  return ;
}

export default appWithTranslation(MyApp);

Create a folder and populate it with the locales for your translations.


/public
└── locales
    ├── en
    │   └── common.json
    ├── es
    │   └── common.json
    └── fr
        └── common.json

Example en/common.json:


{
  "greeting": "Hello, world!",
  "welcomeMessage": "Welcome to our website."
}

Using the translation in a component:


import { useTranslation } from 'next-i18next';

function MyComponent() {
  const { t } = useTranslation('common');

  return (
    

{t('greeting')}

{t('welcomeMessage')}

); } export default MyComponent;

This example uses useTranslation hook to retrieve translations based on the current locale.

Handling Dynamic Routes and Static Site Generation (SSG)

Internationalization becomes more complex when dealing with dynamic routes (e.g., blog posts, product pages) and static site generation (SSG).

1. Dynamic Routes (e.g., /blog/[slug])

For dynamic routes, you'll need to generate the correct paths for each locale during build time using getStaticPaths. This function returns an array of paths that Next.js should pre-render.


export async function getStaticPaths() {
  const paths = [];
  const locales = ['en', 'es', 'fr'];
  const posts = await fetchPosts(); // Fetch blog posts data

  posts.forEach(post => {
    locales.forEach(locale => {
      paths.push({
        params: {
          slug: post.slug,
        },
        locale,
      });
    });
  });

  return {
    paths,
    fallback: false, // or 'blocking' if you want to show loading state
  };
}

export async function getStaticProps({ params, locale }) {
  const post = await getPostBySlug(params.slug, locale);

  return {
    props: {
      post,
    },
  };
}

Explanation:

2. Static Site Generation (SSG) with getStaticProps

In getStaticProps, you can fetch translated content based on the locale parameter.


export async function getStaticProps({ params, locale }) {
  // Fetch content based on the locale and params
  const { post } = await getPostBySlug(params.slug, locale);

  return {
    props: {
      post,
    },
  };
}

The getPostBySlug function should fetch the translated content for the given slug and locale, which could be retrieved from your translation files, database, or a CMS.

3. Server-Side Rendering (SSR) with getServerSideProps

For content that needs to be fetched at request time, use getServerSideProps. This is useful if the content changes frequently or is personalized for each user.


export async function getServerSideProps({ params, locale, req, res }) {
  // Fetch data based on the locale and params (e.g., from a database)
  const data = await fetchData(params.slug, locale);

  return {
    props: {
      data,
    },
  };
}

Best Practices for Next.js Internationalization

Following these best practices will help you build robust, maintainable, and user-friendly multi-language applications:

SEO Considerations for Internationalized Websites

Optimizing your internationalized website for search engines is essential for driving organic traffic from around the world. Here are some key SEO best practices:

Example: Building a Simple Multi-language Blog

Let's create a simplified example of a multi-language blog using Next.js. This will provide a more concrete illustration of how to apply the concepts discussed above.

1. Project Setup

Create a new Next.js project:


npx create-next-app my-multi-lang-blog
cd my-multi-lang-blog

2. Configure i18n (next.config.js)


/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  i18n: {
    locales: ['en', 'es', 'fr'],
    defaultLocale: 'en',
  },
}

module.exports = nextConfig

3. Create Translation Files

Create a locales folder in the root directory and add the following JSON files:

locales/en.json:


{
  "title": "Welcome to My Blog",
  "postTitle": "My First Post",
  "postContent": "This is the content of my first blog post."
}

locales/es.json:


{
  "title": "Bienvenido a mi Blog",
  "postTitle": "Mi Primer Post",
  "postContent": "Este es el contenido de mi primer publicación de blog."
}

locales/fr.json:


{
  "title": "Bienvenue sur Mon Blog",
  "postTitle": "Mon Premier Article",
  "postContent": "Ceci est le contenu de mon premier article de blog."
}

4. Create the Blog Post Component (e.g., components/BlogPost.js)


import { useRouter } from 'next/router';
import en from '../locales/en.json';
import es from '../locales/es.json';
import fr from '../locales/fr.json';

function BlogPost() {
  const router = useRouter();
  const { locale } = router;

  let translations;
  switch (locale) {
    case 'es':
      translations = es;
      break;
    case 'fr':
      translations = fr;
      break;
    default:
      translations = en;
  }

  return (
    

{translations.postTitle}

{translations.postContent}

); } export default BlogPost;

5. Create the Index Page (pages/index.js)


import { useRouter } from 'next/router';
import BlogPost from '../components/BlogPost';
import en from '../locales/en.json';
import es from '../locales/es.json';
import fr from '../locales/fr.json';

function HomePage() {
  const router = useRouter();
  const { locale, locales } = router;

  let translations;
  switch (locale) {
    case 'es':
      translations = es;
      break;
    case 'fr':
      translations = fr;
      break;
    default:
      translations = en;
  }

  return (
    

{translations.title}

{locales.map((l) => ( {l.toUpperCase()} ))}
); } export default HomePage;

This simplified example showcases the fundamental principles of Next.js internationalization. You can expand upon this basic framework to include more complex features, such as dynamic routes and integration with translation management systems. Consider improving the links above with the Link component and add the appropriate locale attribute.

6. Run the Application

Run the application with:


npm run dev

Now you can access your blog at http://localhost:3000 (English), http://localhost:3000/es (Spanish), and http://localhost:3000/fr (French). You should see the title and the blog post content translated based on the selected locale.

Conclusion

Next.js provides a comprehensive set of features for implementing internationalization in your web applications. By following the principles and techniques outlined in this guide, you can create multi-language applications that deliver localized experiences to users around the globe. Remember to plan your i18n strategy early, choose the right translation method for your needs, and prioritize user experience. With careful planning and execution, you can build applications that resonate with a global audience and unlock new opportunities for growth. Continuous learning, keeping up with the latest releases and best practices will ensure that you are utilizing your tools and technologies effectively.

As technology advances, expect to see more advanced i18n features emerge. The ability to reach users across different cultures and linguistic groups will remain a key priority for application developers worldwide. Therefore, mastering the fundamentals of i18n is a valuable skill that will enhance your value in today's global development landscape.