Detect missing translation keys during compile time (Typescript)

This tip is for anyone who wants to translate their TypeScript-based applications, such as when using React, Angular (ngx-translate), or VueJS.

You know how missing translation keys can be a real pain? They can cause issues in your app, and you only find out about them when you test the whole thing. And the eror only pops up when you actually try to use that key. Luckily, there's an easy way to fix this if you're using TypeScript.

Suppose you have the following translation file: en.json:

  "greeting": "Hello",
  "farewell": "Goodbye",
  "thanks": "Thank you"

You can now import the language file into your application:

import * as enJson from './en.json';
export type TranslationKeys = keyof typeof enJson;

To import the .json files, you have to modify your tsconfig.json:

  "compilerOptions": {
    "resolveJsonModule": true,
    // ... other compiler options
  // ... other settings

Now, you can use the TranslationKeys type in your application like this:

import type {TranslationKeys} from "./TranslationKeys";

const translate = (key: TranslationKeys) => console.log(key); // just a dummy function

translate("greeting"); // ok
translate("missingkey"); // type-error

Update the translate(key: TranslationKeys) function, as a wraper for the 'real' translation function.

Nice bonus: You get Intellisense auto-completion for your prompts in Visual Studio Code and PhpStrom:

Auto-Completion for translation keys
Auto completion for translation keys in Visual-Studio Code and PhpStorm

The limitation is that it doesn't work with nested JSON files.

You have to convert the file

    "main": {
        "sub": "a sub key"

to this, to make it work:

    "main.sub": "a sub key"

The great thing is that BabelEdit does this for you. After importing the keys,

After importing your project, simply open the settings and change the Format to JSON with namespaces in keys, tree view.

Converting JSON file formats from nested to flat keys.
Converting JSON file formats from nested to flat keys.

BabelEdit also keeps the files consistent for you so that it's sufficient to only use your primary language in the import.

To check all languages you can use:

import * as enJson from './en.json';
import * as deJson from './de.json';
export type TranslationKeys = keyof typeof enJson & keyof typeof deJson;