JSON5 & human-friendly software localization

JSON5 & human-friendly software localization

Featured on Hashnode

The old, good(?) JSON

The JSON format became very important in many different fields, and one of them is also the software localization.

However, JSON is a bit limited in the sense of human-friendliness for this field (and not only for it) - it’s strict, and there are a lot of double quotes :-). It’s not forgiving. It doesn’t have comments that are great for quickly providing a context for translators in a way that the comment is not a part of the content.

For some of these shortcomings, there are different solutions such as the metadata in Flutter’s ARB format defined with @ prefix.

{
  "string_key": "Translations",
  "@string_key": {
    "description": "Context for translator."
  }
}

Not quite simple to read and a bit wordy for a simple comment. However, it's a useful concept when there is more structured contextual information to provide.

Back to the topic, the fact that JSON is limited inspired new formats such as HJSON and JSON5.

JSON5 - JSON for Humans

JSON5 is fully backward compatible, and a valid JSON file is also a valid JSON5 file. But there are also many interesting additional features that you don't find in JSON:

Objects

  • Object keys may be an ECMAScript 5.1 IdentifierName.
  • Objects may have a single trailing comma.

Arrays

  • Arrays may have a single trailing comma.

Strings

  • Strings may be single quoted.
  • Strings may span multiple lines by escaping new line characters.
  • Strings may include character escapes.

Numbers

  • Numbers may be hexadecimal.
  • Numbers may have a leading or trailing decimal point.
  • Numbers may be IEEE 754 positive infinity, negative infinity, and NaN.
  • Numbers may begin with an explicit plus sign.

Comments

  • Single and multi-line comments are allowed.

White Space

  • Additional white space characters are allowed.

JSON5 - Human-friendly localization

As you can see from the simple example below, it's more comfortable to use it than the standard JSON files.

{

  menu: {
    share: 'Share "this"'
  }

  // Please keep the name short.
  shortName: 'Short Name',

  /*
  It's also possible to use multi-line comments to
  provide additional context for translators.
  */  
  json5IsGreat: "It is!"

  andForgiving: "There's trailing comma... no problem.",
}

No support for JSON5? There is a solution!

So you would like to use JSON5 to make your life easier, but your current localization solution supports only JSON? No problem at all.

Use JSON5 for your source language strings and use Localazy as a translation management platform. It's completely free for the majority of apps, it translates your app to up to 80 languages for free with shared translations, it supports JSON5, and it can output standard JSON files.

Working out of the box

My app uses JSON for localization and I have translated files stored in the folder translations. I've added a new folders trans_source with my source JSON5 file. So the structure of my project is like this:

- app
  - trans_source
    - en.json5
  - translations
    - en.json
    - cs.json
    - de.json
    - zh-TW.json
    - ...
  - src
  - resources
  - ...
  - localazy.json

Whenever I add a new feature, I also add new texts to en.json5. I can enjoy all the features of JSON5, most notably, I use comments for providing a context for translators, but I also like the possibility to use single quotes to avoid escaping of double-quotes, etc. No double quotes for keys is also a great improvement.

You can notice that there is localazy.json file, which is a configuration file for Localazy CLI with this content:

{
  "readKey": "my-read-key",
  "writeKey": "my-write-key",

  "upload": {
    "type": "json5",
    "files": "trans_source/en.json5"
  },

  "download": {
    "includeSourceLang": true,
    "files": "translations/${lang}.json"
  }
}

And that's everything!

When I add new texts to en.json5, I just invoke localazy upload from the command line to send the updated file to the Localazy platform.

As a part of my build, localazy download is automatically invoked, and it downloads all translated files (including the source language; enabled by "includeSourceLang": true) to the translations folder. Localazy outputs valid JSON files for JSON5 input, so it all works with my existing JSON-based localization solution out-of-the-box, and I can manage translations comfortably through Localazy and even get a huge portion of my app translated for free with shared translations. Win-Win.

As an addition, for JSON5, Localazy also supports ARB-style metadata, arrays, plurals, multilingual files and other features, so I can use anything I need and currently use with the standard JSON.

Flutter's ARB supported too!

Flutter's ARB is just a specification based on top of the standard JSON, so the solution described above can be used with minimal changes also for your Flutter apps.

Forget about complicated structures starting with @ just to tell your translator that you need him to keep the name short ;-).