i18n-check: Validating your Next.js internationalization
Introduction
In the previous i18n-check: End to end React i18n testing
post we went into detail on how a React application can be validated in regards to i18n. i18n-check
now also supports next-intl
and also works with next-i18next
out of the box, offering more options in regards to validating Next.js applications.
With the latest changes it’s now possible to validate i18n end to end for a Next.js application if one of the following i18n libraries is used: react-intl
, react-i18next
, next-intl
or next-i18next
This enables you to find untranslated or invalid translation messages in locale files. Additionally, it identifies undefined key (used in the source code but missing in locale files) as well as unused keys (defined in the locale files but not used in the source code).
Checking i18n in a Next.js application
Running checks should help with being able to answer the following questions:
How many keys are missing in the
fr
target language file?
Are all keys valid in the
de
target file?
Are there any keys in the codebase that are missing in the
en
source language file?
Take a look at the following example:
// en.json
"message.greeting": "Hi, <b>{name}</b>!"
// de.json
"message.greeting": "Hallo {name}!"
While the default message contains tags, the message in the de.json
file does not. These tags might have been removed during the translation process or were never added, leading to a mismatch between the source and target language message.
// en.json
"message.greeting": "Hi {user}, it is {today, date, medium}.",
// de.json
"message.greeting": "Hallo {user}, heute ist {today, date, medium} und morgen ist {tomorrow, date, medium}.",
The second example shows that the target translation contains more date information when compared to the source en.json
file, indicating that the source and target translations are out of sync, which can lead to unexpected or weird display errors at runtime.
Running these i18n checks helps us to identify any potential runtime issues before they affect users. So instead of manually keeping track of the state of our translations, we rather want to be informed when something is missing or needs updating.
Setting up i18n-check
To set up i18n-check run the following command:
yarn add --dev @lingual/i18n-check
Alternatively if you are using npm:
npm install --save-dev @lingual/i18n-check
Or if you are using pnpm:
pnpm add --save-dev @lingual/i18n-check
Update the package.json
file and add a new command:
"scripts": {
// ...
"i18n:check": "i18n-check"
}
Run the i18n:check
command directly from the CLI, i.e. yarn i18n:check
.
Validating locale and source files
Checks can run against single files, single folders or a combination of files and folders and mainly depend on on how these localization files are organized inside an existing project.
To get a better understanding, let’s try to got through a basic example (for more advanced scenarios check the README
). A basic setup could for example include a folder called locales containing a number of translation files organized as en-en.json
, fr-fr.json
, it-it.json
etc:
- locales/
- en-en.json
- fr-fr.json
- it-it.json
With the -l
or --locales
option you can define where the target locale files are located and with the -s
or --source
option you can specify the base/reference file/folder to compare the target files against. To define where the source files are located you can use the -u
or --unused
option and also provide the -f
or --format
to tell the parser if we need to check for react-intl
, next-intl
or the i18-next
format.
yarn i18n:check --locales locales --source en-en -f next-intl -u src
The above command would yield the following result:
i18n translations checker
Source: en-en
Found missing keys!
┌──────────────────────────────┬────────────┐
│ file │ key │
├──────────────────────────────┼────────────┤
│ messageExamples/de-de.json │ richText │
│ messageExamples/de-de.json │ nesting1 │
│ messageExamples/de-de.json │ key1 │
└──────────────────────────────┴────────────┘
Found invalid keys!
┌──────────────────────────────┬─────────────────────┐
│ file │ key │
├──────────────────────────────┼─────────────────────┤
│ messageExamples/de-de.json │ multipleVariables │
└──────────────────────────────┴─────────────────────┘
Found unused keys!
┌─────────────────────────────────────────────────┬──────────────────┐
│ file │ key │
├─────────────────────────────────────────────────┼──────────────────┤
│ messageExamples/en-en.json │ format.ebook │
│ messageExamples/en-en.json │ nonExistentKey │
└─────────────────────────────────────────────────┴──────────────────┘
Found undefined keys!
┌──────────────────────────────────────────────────────┬────────────────────────────────┐
│ file │ key │
├──────────────────────────────────────────────────────┼────────────────────────────────┤
│ src/App.tsx │ some.key.that.is.not.defined │
└──────────────────────────────────────────────────────┴────────────────────────────────┘
For more advanced examples check the examples section in the README .
Setup checks on the CI
The following is an example of how you could define a Github workflow for an existing Next.js application, where the source code to parse is under src
.
name: i18n-check
on:
pull_request:
branches:
- main
push:
branches:
- main
jobs:
i18n-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: yarn install & build
run: |
yarn install
yarn build
- name: yarn i18n-check
run: |
yarn i18n:check -l translations/messageExamples -s en-US -u src/ -f next-intl
Checkout i18n-check here
Links
We are working on a new translation management system with first-class branching and CLI integration.
Subscribe to our newsletter and we'll let you know when the beta becomes available.