how to implement Gatsby internationalization (i18n)

Gatsby i18n: Guide to Gatsby multi-language localization

In this tutorial we’re going to discuss how to implement Gatsby internationalization i18n in your apps. Gatsby is an open-source front-end framework that allows you to create dynamic and optimized websites. It uses React to build pages and structure content and GraphQL to manage site data. Furthermore, it provides a cloud platform to host your application. Like in many frameworks, it also supports localization and internationalization through several packages. In this tutorial, we are going to discuss how to use gatsby-plugin-react-i18next for Gatsby internationalization.

First, let’s briefly discuss what internationalization and localization are and why they are crucial. Internationalization (i18n) is making your web content usable for different regions or locales in the world without engineering changes. Internationalization is essential for a website that has users worldwide. Localization involves text translation, formatting of numbers, strings, currencies, measurement units, and dates based on the users’ detected locale. While implementing l10n you also should take cultural specifics into account. Localization helps to create more user-friendly interfaces for a diverse range of users. In addition, it gives the customers a positive user experience, leading to an increase in the customer base. 

Let’s move on to discover how we can implement Gatsby i18n in a given application. I have developed a small application using the example code snippets in this article. You can find it on GitHub.

    Choosing a package for Gatsby i18n

    There are several React i18n libraries you can use for Gatsby localization. When choosing a React plugin for localization, ask yourself the following questions:

    • Are you already using the package in another project?
    • Does the chosen package meet your and your users’ needs? 
    • Is there any package familiar to you or your team?
    • Is the package well documented and maintained?

    Here is a list of popular React i18n libraries:

    In our guide, we will be using the Gatsby-plugin-react-i18next library to achieve localization.

    Gatsby i18n with gatsby-plugin-react-i18next

    The gatsby-plugin-react-i18next library allows you to build Gatsby websites in multiple languages. Providing seamless integration with react-i18next, the gatsby-plugin-react-i18next library creates routes for each language enabling search engines to quickly find the correct website version. You don’t need to create separate pages for each language when using this plugin, like pages/en/index.js or pages/es/index.js. Instead, you can specify multi-language URL routes in a single page component.

    Moreover, it does code splitting and load translation for each page separately. Finally, this process automatically redirects to the appropriate content format according to the users’ preferred language.

    You can refer to gatsby-plugin-react-i18next documentation here.

    Getting Started with Gatsby 

    In the previous section, we went through a detailed description of the gatsby-plugin-react-i18next plugin. Now let’s move to the implementation of our application. Let’s first create a small Gatsby Application.

    Create a minimalist Gatsby site 

    Let’s install gatsby CLI  with the following command:

    npm install -g gatsby-cli

    Please note that you need to have Node v12.13 or newer installed on your machine before executing this command. We are using Node v14.15.4 and NPM 6.14.10 for this implementation. 

    Next, we need to create a Gatsby application with the following command:

    gatsby new

    After typing this command, it will open up an interactive prompt asking you some questions about the application you want to build. Choose the following answers:

    What would you like to call your site?

    √ · Gatsby_Localization

    What would you like to name the folder where your site will be created?

    √ Gatsby/ gatsby_localization

    Will you be using a CMS?

    √ No (or I’ll add it later)

    Would you like to install a styling system?

    √ No (or I’ll add it later)

    Would you like to install additional features with other plugins?

    √ Install gatsby-plugin-gatsby-cloud

    Shall we do this? (Y/n) 

    √ Yes

    According to the answers, it will create an application with the folder structure as shown below:

    Open your src/pages/index.js file and replace its contents with the following code:

    import * as React from 'react';
     
    const IndexPage = () => {
     
     return (  
       <main>
         <h1>Welcome to my Gatsby site!</h1>
         <p>My name is Shanika</p>
         <p>My profession is SSE</p>
       </main>
     )
    };
     
    export default IndexPage;

    Then go to the application’s folder by typing the following command:

    cd gatsby_localization

    Finally, start the development server by running the following command:

    gatsby develop

    You can now open your app in the browser by visiting http://localhost:8000/.

    You can edit src/pages/index.js (or any other file), and it will update in real-time!

    Okay, now we have a very simple Gatsby application that we can use to integrate the gatsby-plugin-react-i18next package!

    Configuring gatsby-plugin-react-i18next for Gatsby i18n

    Installing npm packages

    We need the following three npm packages to build our application:

    Let’s discuss their usage before installing them. The i18next library is a popular internationalization framework for browsers or any other JavaScript environment. The react-i18next is a powerful internationalization framework for React / React Native, which is based on i18next. We can install all these npm packages with the following command:

    npm install --save gatsby-plugin-react-i18next i18next react-i18next

    If you have successfully installed those packages, your package.json file should have the following dependencies:

    Now, let’s add localization capability to our application. We will be using three languages for localization in our application: English, French, and Arabic.

    Adding language JSON resources to the project

    Create a new locales folder inside your gatsby_localization project and add three folders — en, fr, ar — for each language. Then, add language-specific JSON resource files. For example:

    • /locales/en/translation.json
    • /locales/fr/translation.json
    • /locales/ar/translation.json

    To load these JSON resources, you need to install the gatsby-source-filesystem plugin and then fetch using GraphQL query. You can install the package using the following command:

    gatsby-source-filesystem

    Setting up gatsby-config.js

    Next, you need to insert the following configurations in your gatsby/config.js file:

    module.exports = {
      siteMetadata: {
        title: "Gatsby_Localization",
      },
      plugins: [
      {
        resolve: `gatsby-source-filesystem`,
        options: {
          path: `${__dirname}/locales`,
          name: `locale`
        }
      },
      {
        resolve: `gatsby-plugin-react-i18next`,
        options: {
          localeJsonSourceName: `locale`,
          languages: [`en`, `fr`, `ar`],
          defaultLanguage: `en`,
          siteUrl: `http://localhost:8000/`,
          i18nextOptions: {
            interpolation: {
              escapeValue: false 
            },
            keySeparator: false,
            nsSeparator: false
          },
          pages: [
            {
              matchPath: '/:lang?/blog/:uid',
              getLanguageFromPath: true,
              excludeLanguages: ['es']
            },
            {
              matchPath: '/preview',
              languages: ['en']
            }
          ]
        }
      }
      ],
    };
    

    Let’s see the meaning of each configuration option from the following tables.

    Gatsby-source-filesystem options

    Option Description
    path Path to the directory where you keep the language-specific JSON resource file. In this example, it is in the /gatsby_localization/locales folder
    name Specify the name to identify that folder

     

    Gatsby-plugin-react-i18next options

    Option Description
    languages  These are the codes corresponding to each language. We will be using three languages in the demo application for this tutorial: English, French, and Arabic.  
    defaultLanguage  The default language code when loading the site. For this example, we will set it to ‘en.’
    localeJsonSourceName The gatsby-source-filesystem will load the name of the source folder where language JSON files are located. Its name is set in the ‘name’ option of the gatsby-source-filesystem options. Default is ‘locale.’
    siteUrl Your site URL. 
    pages an array of page options used to modify plugin behavior for specific pages
    i18nextOptions i18next configuration options

    Now that we have configured our application for localization, we will learn how we can do standard text translation in the next section. 

     

    Regular text translation in Gatsby i18n

    Using UseTranstation React hook and Trans components

    The gatsby-plugin-react-i18next exposes all react-i18next methods and components. Therefore, we can employ useTranslation hook and Trans component of react-i18next to translate your pages. With the Trans component, you can specify which text has to be translated:

    import React from 'react';
    import {graphql} from 'gatsby';
    import Header from './header';
    import {Trans, useTranslation} from 'gatsby-plugin-react-i18next';
     
    const IndexPage = () => {
     
      const { t } = useTranslation();
     
      return (  
        <main>
          <h1><Header></Header></h1>
          <h1><Trans>Welcome to my Gatsby site!</Trans></h1>
          <p><Trans>My name is Shanika</Trans></p>
          <p><Trans>My profession is SSE</Trans></p>
          <p><Trans>My Birthday is 1990/10/10</Trans></p>
          <p>{t('message')}</p>
        </main>
      )
    };
     
    export default IndexPage;
     
    export const query = graphql`
      query($language: String!) {
        locales: allLocale(filter: {language: {eq: $language}}) {
          edges {
            node {
              ns
              data
              language
            }
          }
        }
      }
    `;
    

    As you can see, we have used the t("message")  function in the return section. We can use this t function to translate content provided in the chosen language. 

    Adding translations into JSON resource files

    Next, we have to add the relevant translated messages to JSON files we have already created. Add the following content to each corresponding JSON file accordingly. Note that you can always modify and add your text. If you have added the translations successfully, they should contain the following:

    locales/en/translation.json file

    {
        "Welcome to my Gatsby site!": "Welcome to my Gatsby site!",
        "My name is Shanika": "My name is Shanika”,
        "My profession is SSE": "My profession is SSE"
    }
    

    locales/fr/translation.json file

    {
        "Welcome to my Gatsby site!": "Bienvenue sur mon site Gatsby !",
        "My name is Shanika": "Je m'appelle Shanika",
        "My profession is SSE": "Ma profession est ESS"
    }
    

    locales/ar/translation.json file

    {
        "Welcome to my Gatsby site!": "مرحبًا بكم في موقع Gatsby الخاص بي!",
        "My name is Shanika": "اسمي شانيكا",
        "My profession is SSE": "مهنتي هي SSE"
    }
    

    Now let’s test if we can load correct content through the browser. If you type the corresponding URL in the browser’s address bar,  as you can see from the following images, it will load the translated version of the page accordingly:

    Gatsby i18n

    Gatsby i18n

    Ok, we are done with our regular text translation part. Next, we will see how we can change the languages using a language switcher. 

     

    Language switcher

    To implement a language switcher, you can use the useI18next react hook in gatsby-plugin-react-i18next plugin.  

    Lets’ create a <Header> react component containing the links to the languages. First, create a separate file in the src folder and name it header.js. Then add the following code to that file. Here we use the <Link> component to specify links to each language:

    import React from 'react';
    import {graphql} from 'gatsby';
    import {Link, useI18next} from 'gatsby-plugin-react-i18next';
     
    const Header = ({title}) => {
        const {languages, originalPath} = useI18next();
        return (
          <header className="main-header">
            <h1 style={{margin: 0}}>
              <Link
                to="/"
                style={{
                  color: `white`,
                  textDecoration: `none`
                }}>
                {title}
              </Link>
            </h1>
            <ul className="languages">
              {languages.map((lng) => (
                <li key={lng}>
                  <Link to={originalPath} language={lng}>
                    {lng}
                  </Link>
                </li>
              ))}
            </ul>
          </header>
        );
    };
     
    export default Header;

    In this code, the originalPath attribute defines the page path for the language, and languages define the supported language keys. 

    Then include that component in the index.js file to include the language switcher on the main page:

    import Header from './header';
    <main>
         <h1><Header></Header></h1>
         <h1><Trans>Welcome to my Gatsby site!</Trans></h1>
         <p><Trans>My name is Shanika</Trans></p>
         <p><Trans>My profession is SSE</Trans></p>
       </main>

    Then the page will look like the following:

    Gatsby i18n

    As shown in the following figures, it will load the respective language resource files if you click on the links:

    Gatsby i18n

    Gatsby i18n

    Excluding languages

    You can also limit the languages for a specific page. In the example below, we have set the languages of the about page to only English, excluding other languages:

    pages: [
            {
              matchPath: '/about',
              languages: ['en']
            }
    ]
    

    You also can exclude a page that has a language key in its URL path. Suppose you have a news page that uses a different language translator or plugin. You can exclude that page in the gatsby-config.js file:

    pages: [
           {
              matchPath: '/:lang?/news,
              getLanguageFromPath: true,
              excludeLanguages: ['es']
           }     
    ]
    

    To identify which part of the URL path specifies the language key, you have to set the :lang? parameter in the URL path. You can select the languages you need to exclude in the excludeLanguages option. In this example, you will get pages for all languages except for ‘es.’  Moreover, you can omit the excludeLanguages option if you want to get all the languages from the path. 

    Fetching translations for specific namespaces

    We can also store translations for a single language in multiple files. For example:

    – gatsby_localization/

    — locales/

    —– de

    ——- translation.json

    ——- common.json

    ——- index.json

    —– en

    ——- translation.json

    ——- common.json

    ——- index.json

     

    If your app has large pages with lots of translations, you can employ Gatsby GraphQL queries to fetch specific namespaces. You can specify them under the ns and language fields. In the following example, we have added namespaces common and index. Therefore, it will load only common.json and index.json files. In addition, the plugin will add all other loaded namespaces as fallback namespaces:

    export const query = graphql`
      query($language: String!) {
        locales: allLocale(filter: {ns: {in: ["common", "index"]}, language: {eq: $language}}) {
          edges {
            node {
              ns
              data
              language
            }
          }
        }
      }
    `;

    Date localization in Gatsby

    You can format the dates of your Gatsby application using moment.js and numeral.js or the intl api. I chose to use two different date formats, YYYY/MM/DD and DD-MM-YYYY, for this tutorial. First, install MomentJS using the following command:

    npm install --save moment react-moment

    Then, import the moment package into your project:

    import moment from 'moment';

    Now, let’s define two date variables with different formats as follows:

    const date1 = moment(new Date()).format('DD-MM-YYYY');
    const date2 = moment(new Date()).format('DD/MM/YYYY');

    Add the following date keys to the index.js file

    <p>{t("date_format_one", {date1})}</p>
    <p>{t("date_format_two", {date2})}</p>

    Next, insert the translated versions of key values to each language JSON file:

    "date_format_one": " La date actuelle est {{date1}}",
    "date_format_two": " La date actuelle est {{date2}}"

    After saving the file, you can see the output of each date in a specific format:

    That’s it, great job!

    Translating with Lokalise

    Developing an application with internationalization is not that difficult as it seems to be. However, using the right tools and libraries will make this process much more manageable when applying internationalization to your project. You will no longer need to waste your time and energy translating each text and element right inside the codebase. And Lokalise is the perfect tool for internationalizing an app with the least amount of effort. 

    The process of integrating Lokalise with your application is relatively easy. Follow the below steps to start using Lokalise:

    1. Grab your free trial.
    2. Then, install the Lokalise CLI to your PC. You can create projects, upload, and download translation files with this command-line interface.
    3. Then open your Lokalise profile and navigate to the “API tokens” section. Create a new read/write token (remember to keep it private) and copy it.
    4. Now, you can create a new translation project on Lokalise and set the base language to English.
    5. Open your project, click the “More” button, and navigate to the Settings section.
    6. There, you have to copy the project ID. Then you can execute the following command: lokalise2 file upload --token <token> --project-id <project_id> --lang_iso en --file PATH/TO/PROJECT/src/locales/translations/en/translations.json.
    7. The above command will upload English translations from your Aurelia app to Lokalise. To upload more languages, you have to execute the above command to the relevant JSON files.
    8. Now, you can proceed to the project page and perform translations there or invite a new collaborator to help you out.
    9. Finally, you can download the modified translations with the following command: lokalise2 file download --token <token> --project-id <project_id> --format json --dest PATH/TO/PROJECT/src/locales/.

    Lokalise provides other features, including project branching, integrations with popular services like GitHub or Bitbucket, quality assurance checks, and many more!

    Conclusion

    So, in this tutorial, we’ve discussed how we can use the Gatsby framework for developing an application that supports Gatsby i18n. We’ve learned how to translate a regular text with the gatsby-plugin-react-i18next and several other features such as how to exclude pages from translating, use specific namespaces, and date formatting. Finally, we discussed integrating a translation management system into our application to simplify the translation process. You can build much more complex Gatsby projects using the concepts taught here. Our website also provides other dev tutorials; for example, if you’re a JS developer our React-intl and React i18next guides might come in handy.

    Talk to one of our localization specialists

    Book a call with one of our localization specialists and get a tailored consultation that can guide you on your localization path.

    Get a demo

    Related posts

    Learn something new every two weeks

    Get the latest in localization delivered straight to your inbox.

    Related articles
    Localization made easy. Why wait?