Skip to main content

Internationalization

We make use of react-i18next, a powerful internationalization framework for React / React Native which is based on i18next. In certain projects we also use:

In order to understand how this repository implements i18n, it is important to understand how these libraries work. The remainder of this document assumes a working knowledge of these libraries.

Adding i18n to your project

  1. add i18next-parser.config.js to project root.
const i18nextParserConfigBase = require('../../i18next-parser.config.base') // this file is located in the workspace root

module.exports = {
  ...i18nextParserConfigBase,
  input: ['src/**/*.{js,jsx,ts,tsx}']
}
  1. add extract-translations command to targets object and implicitDependencies to base object in project.json. You must replace PROJECT_PATH with your project path e.g. apps/journeys.
{
  ...
  "implicitDependencies": ["locales"],
  "targets": {
    "extract-translations": {
      "executor": "@nx/workspace:run-commands",
      "options": {
        "commands": [
          {
            "command": "npx i18next --config PROJECT_PATH/i18next-parser.config.js"
          }
        ]
      }
    }
    ...

  }
}
  1. update your components to make use of useTranslation hooks, appWithTranslation HOCs, Trans components etc in order to indicate to the parser that there is a string available for translation.

It is very important that you include a namespace. This namespace should be a dashed version of your project path. For example apps/journeys would become apps-journeys or libs/journeys/ui would become libs-journeys-ui.

import { useTranslation } from 'next-i18next'

function Component() {
  const { t } = useTranslation('libs-journeys-ui') // must include namespace
  return <div>{t('hello world')}</div>
}
  1. run nx command extract-translations for the project you are working on. This should pull all of the strings requiring translations into a namespaced file for example locales/en/libs-journeys-ui.json ready for translation. This needs to be committed and kept up to date. This is tested in CI so will fail if not correctly updated.

Next.js configuration

  1. update input in i18next-parser.config.js located in the project root
const i18nextParserConfigBase = require('../../i18next-parser.config.base')

module.exports = {
  ...i18nextParserConfigBase,
  input: ['src/**/*.{js,jsx,ts,tsx}', 'pages/**/*.{js,jsx,ts,tsx}']
}
  1. add next-i18next.config.js to the project root
const path = require('path')

/**
 * @type {import('next-i18next').UserConfig}
 **/
const i18nConfig = {
  i18n: {
    defaultLocale: 'en',
    locales: ['en'],
    localePath: path.resolve('./libs/locales')
  }
}

module.exports = i18nConfig
  1. update next.config.js
const { i18n } = require('./next-i18next.config')

const nextConfig = {
  i18n,
  ...
}
  1. update pages/_app.tsx to use appWithTranslation HOC
import { appWithTranslation } from 'next-i18next'
import i18nConfig from '../next-i18next.config'

// your _app component
function CustomApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default appWithTranslation(JourneysApp, i18nConfig)
  1. add async function on your page-level components, via either getStaticProps or getServerSideProps (depending on your use case)
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import i18nConfig from '../next-i18next.config' // project root

export async function getStaticProps({ locale }) {
  return {
    props: {
      ...(await serverSideTranslations(
        context.locale ?? 'en',
        ['apps-watch'], // namespaces your components make use of
        i18nConfig
      ))
    },
  };
}