Weblate and i18next json files

There’s a bug report on github about JSON format breaks i18next files due to automatic restructuring. Actually it flattens your i18next json file and makes it unusable for further usage.

So after starting with a json file like:

{
    "navbar": {
        "reward": "Rewards",
        "about": "About"
    }
}

you end up with a committed file which was transformed into this:

{
    "navbar.reward": "Rewards",
    "navbar.about": "About"
}

Use Weblate PRE_COMMIT_SCRIPTS

Weblate offers script hooks before or after a repository action happens. I’m using one of those hooks to execute a short Python script which reformats json again to be usable in i18next translation tools again. The script below is also available on Github:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
import argparse
import codecs
import json


__author__ = 'Daniel Widerin <daniel@widerin.net>'
__license__ = 'MIT'


class HierarchicalDict(dict):

    def __init__(self, *args, **kwargs):
        self.update(*args, **kwargs)

    def __setitem__(self, key, val):
        dict.__setitem__(self, key, val)

    def update(self, *args, **kwargs):
        for key, val in dict(*args, **kwargs).items():
            keys = key.split('.')
            if len(keys) > 1:
                self._decode(keys, val)
            else:
                self[key] = val

    def _decode(self, keys, value):
        storage = self
        for key in keys[:-1]:
            if key not in storage:
                storage[key] = {}
            storage = storage[key]
        storage[keys[-1]] = value


def main():
    parser = argparse.ArgumentParser(
        description='Recover flattened json file.')
    parser.add_argument(
        'files', metavar='FILE', type=str, nargs='+',
        help='Files to process')
    parser.add_argument(
        '--indent', default=4, type=int, dest='indent',
        help='json indentation for outfile')
    args = parser.parse_args()

    for filename in args.files:
        try:
            raw = codecs.open(filename, 'r', encoding='utf-8').read()
            data = json.loads(raw, object_pairs_hook=HierarchicalDict)

            with codecs.open(filename, 'w', encoding='utf-8') as outfile:
                json.dump(data, outfile,
                          sort_keys=True,
                          indent=args.indent,
                          ensure_ascii=False)
        except Exception as ex:
            print('Error processing {0:s}'.format(filename), ex)


if __name__ == '__main__':
    main()

After you’ve added the script to PRE_COMMIT_SCRIPTS in weblate/settings.py file it should be available in component add/edit forms in Django admin interface:

../../_images/weblate_configure_pre-commit.png

Comments

comments powered by Disqus