Add localization test to a module

It is a good idea to test completeness of localization files. Such tests prevent incomplete and incorrect app localization. In CzechIdM, we use localization files <language>.json to define text descriptions in application for different languages.

When we write localization messages for more than one language, one common mistake usually appears: missing path to localization message in one of the languages. To prevent this we use our own TestHelper.js utility. You can find it here. TODO:link czechidm-core/src/utils/TestHelper.js

This article describes how to test existing localization files for correctness. For how to create a localization file, see TODO:link.

This is how <language>.json file looks like:

{
  "app": {
    "name": "CzechIdM",
    "author": {
      "name": "BCV solutions s.r.o.",
      "homePage": "http://www.bcvsolutions.eu"
    }
  }
}

A file contains a number of "paths" to localization messages (we extract them with a help of JSONPath library). Paths for the file above look like:

['app']
['app']['name']
['app']['author']
['app']['author']['name']
['app']['author']['homePage']

Whole test runs on lists of localization paths. Those lists are built from the root of JSON document, depth-first.

This test works specifically with CS.json and EN.json files. The utility, basically, compares paths to every single localization message. Test runs when you start building frontend part of CzechIdM (using gulp). If there is a localization missing in one of JSON files (and, therefore, in a paths list), frontend app build will fail and the utility will show missing localization paths. Successful test result is similar to the output below:

[2018-03-09 13:35:46.277] [DEBUG] [default] - acc: Comparing JSON catalogs - ok
[2018-03-09 13:35:46.480] [DEBUG] [default] - core: Comparing JSON catalogs - ok
[2018-03-09 13:35:46.658] [DEBUG] [default] - example: Comparing JSON catalogs - ok
[2018-03-09 13:35:46.663] [DEBUG] [default] - vs: Comparing JSON catalogs - ok
[2018-03-09 13:35:46.667] [DEBUG] [default] - rpt: Comparing JSON catalogs - ok

Localization of singulars

When we translate a singular noun, paths lists are checked whether they both contain particular localization path (e.g. "[app][roles][user]"). If they do, everything is OK. If they do not contain the localization path, a message is logged. Because localization paths lists are ordered, the algorithm marks the positions in lists where the paths match again. Everything on positions between two matching paths is logged.

Plural localizations

Exception is in singular and plural description. When the plural is recognized, it will check if CS and EN are in match despite different properties. CS messages are specified by number behind underscore and EN messages ends with word plural behind the underscore. If it has plural amount, paths to localizations should end in this forms:

CS

example_0 (optional)
example_1
example_2
example_5

EN

example_0 (optional)
example
example_plural

Comparison

*Table: how program compares plural messages*

Messages that ends with _0 are optional but if its found in CS or EN language, it's also checked for pair in other language.

Not every application module contains messages that need to be translated. On the other hand, some of the modules do. That is why you have to explicitly add the localization test to a module.

  1. Create file Localization-test.js in "<module>/test/localization/".
  2. Constants "cs" and "en" should point to localization files in the module. The path in example code (below) should fit most cases.
  3. Insert following code into Localization-test.js file:
Localization-test.js
import chai, { expect } from 'chai';
import dirtyChai from 'dirty-chai';
import { LocalizationTester } from 'czechidm-core/src/utils/TestHelper';
chai.use(dirtyChai);
 
/**
 * Validate localization
 *
 * @author Radek Tomiška
 */
describe('Comparing JSON catalogs', function test() {
  it('- vs', function validate() {
    const cs = require('../../src/locales/cs.json');
    const en = require('../../src/locales/en.json');
    //
    const localizationTester = new LocalizationTester();
    expect(localizationTester.compareMessages(cs, en)).to.be.true();
    LOGGER.debug('vs: Comparing JSON catalogs - ok');
  });
});
  • by fiserp