/translate-i18n-json

Translate strings inside JSON files; useful for i18n websites

Primary LanguageJavaScriptMIT LicenseMIT

Translate i18n JSON

A script to help translating and managing updates to your i18n JSON files.

Example with initial en.json language and es.json target language:

  • Create es.json by translating all key/value pairs found in en.json
  • Add to es.json translations of any key/value pairs found in en.json but not present in es.json
  • Remove from es.json all key/value pairs no longer present in en.json
  • Update all strings in es.json that were modified in en.json (updates folder) when comparing to a previous version of en.json (source_of_truth folder)

Note: above examples generalize from any initial language to any target languge (script can update many target language files per run)

Why?

If you ever manually update a string in a translated file, unless the original language changes, you don't want to overwrite your human translation with a less-good machine translation every time you run a translation script. translate-i18n-json avoids this problem.

Additionally, this script avoid wasting your Google Translate credits. Rather than translating every string from the initial .json file into every language every time you update your app/website, this script will only translate (and update) the strings that changed since the last time you ran the script.

Setup

You will need a file .env (rename .env-example to .env and replace dummy string with your own Google API key)

GOOGLE_API_KEY=********* your Google API key *********

Use

Replace the .json file in the source_of_truth folder with your .json file containing the language that needs translating into other languages.

To generate a new translation, look up the ISO-639 code (e.g. es) and place an empty es.json file (with empty object {} inside) into the output folder.

Then npm start will update all files in the output folder with changes:

  • if es.json is empty, all strings from en.json will be translated and es.json will be updated
  • if es.json is missing any keys present in en.json, only those key/value pairs will be translated and added
  • if es.json has keys that en.json does not have, those key/value pairs will be removed
  • if es.json has all the keys that en.json has, no updates will occur
  • if updates folder contains en.json all key/value pairs different from en.json in the source_of_truth folder will be updated/adde to all files in the output folder.

Note: you must use the ISO-639 code for all file names.

Recommended workflow

Here is an easy way to conceputalize the script. There are two modes in which this system works. Mode (1) always happens, mode (2) will happen in addition if you place a json file into the updates folder:

  1. You are adding or removing new key/value pairs to your json and you want those changes to propagate to all your translations, npm start and you're done.
  2. You are also changing some strings (values) in the key/value pairs in your json and you want those strings to also be updated in all your translations
    • put the original file into the source_of_truth folder and the updated file (with the intended text changes) into the updates folder

The idea is this: you have your app/website repository with all your i18n files in some folder. You copy all those files into this repository, putting the original language into source_of_truth and the rest in the output folder. When one day you have made changes to the language in your app/website repository, you copy over just the original language json into source_of_truth (when adding / deleting new key/value pairs) or into updates (when updating strings of already existing key/value pairs).

  • If you run script in mode (1) copy all the output folder files back into your app/website repository when done
  • If you run script in mode (2) move the file from updates into source_of_truth and then copy all the output files into your app/website repository when done

This will keep the translate-i18n-json repository ready for your next updates, regardless of which mode (1) or (2) you will use.

Note: the mode is determined solely by the presense of a file in the updates folder. Mode (1) always happens, and is followed by (2) if a file is present in the updates folder.

Expected file format

Please follow this pattern:

{
  "about": {
    "title": "Best Website Ever"
  },
  "contact": {
    "email": "Please send us an email: hello@lol.com",
    "title": "Contact Us"
  }
}

Note: the nesting of all strings is never deeper or shallower than in the example above.

Testing

You can test how things work by playing with the sample files already present in the repository (3 strings per file, and only 3 language files).

Running npm run reset will reset the output folder to its initial state.

Note: while there is a file present in the updates folder, the script will also update all strings that are different from those found in the source_of_truth file.

Meta

This code grew out of a small script that kept expanding. I don't feel like spending time organizing the code better - even though there are better ways to handle the whole process.