1#!/usr/bin/env python3
2
3# Convert *.json to *.h
4# Usage: ./json2h.py msg_hash_fr.json
5
6import re
7import sys
8import json
9
10try:
11    json_filename = sys.argv[1]
12    h_filename = json_filename.replace('.json', '.h')
13except IndexError:
14    print("Usage: ./template.py <language_postfix>")
15    sys.exit(1)
16
17if json_filename == 'msg_hash_us.json' or json_filename == 'msg_hash_lbl.json':
18    print("Skip")
19    sys.exit(0)
20
21p = re.compile(
22    r'MSG_HASH\s*(?:\/\*(?:.|[\r\n])*?\*\/\s*)*\(\s*(?:\/\*(?:.|[\r\n])*?\*\/\s*)*[a-zA-Z0-9_]+\s*(?:\/\*(?:.|[\r\n])*?\*\/\s*)*,\s*(?:\/\*(?:.|[\r\n])*?\*\/\s*)*\".*\"\s*(?:\/\*(?:.|[\r\n])*?\*\/\s*)*\)')
23
24
25def c89_cut(old_str):
26    new_str = ''
27    byte_count = 0
28    for c in old_str:
29        byte_count += len(c.encode('utf-8'))
30        if byte_count > 500:
31            return new_str + '[...]'
32        new_str += c
33    return new_str
34
35
36def parse_message(message):
37    # remove all comments before the value (= the string)
38    a = message.find('/*')
39    b = message.find('*/')
40    c = message.find('"')
41    new_msg = message
42    while (a >= 0 and b >= 0) and (a < c < b or b < c):
43        new_msg = new_msg[:a] + new_msg[b + 2:]
44        c = new_msg.find('"', a)
45        b = new_msg.find('*/', a)
46        a = new_msg.find('/*', a)
47    # get key word
48    word = new_msg[new_msg.find('(') + 1:new_msg.find(',')].strip()
49
50    # remove all comments after the value (= the string)
51    a = new_msg.rfind('/*')
52    b = new_msg.rfind('*/')
53    d = new_msg.rfind('"')
54    while (a >= 0 and b >= 0) and (a < d < b or a > d):
55        new_msg = new_msg[:a]
56        a = new_msg.rfind('/*')
57        b = new_msg.rfind('*/')
58        d = new_msg.rfind('"')
59    # get value
60    value = new_msg[c + 1:d]
61
62    return word, value
63
64
65def parse_messages(text):
66    result = p.findall(text)
67    seen = set()
68    msg_list = []
69    for msg in result:
70        key, val = parse_message(msg)
71        item = {'key': key, 'val': val, 'msg': msg}
72        msg_list.append(item)
73        if key not in seen:
74            seen.add(key)
75        else:
76            print("Duplicate key: " + key)
77
78    return msg_list
79
80
81def update(messages, template, source_messages):
82    translation = template
83    template_messages = parse_messages(template)
84    for tp_msg in template_messages:
85        old_msg = tp_msg['msg']
86        if tp_msg['key'] in messages and messages[tp_msg['key']] != source_messages[tp_msg['key']]:
87            tp_msg_val = tp_msg['val']
88            tl_msg_val = messages[tp_msg['key']]
89            tl_msg_val = tl_msg_val.replace('"', '\\\"').replace('\n', '')  # escape
90            if tp_msg['key'].find('_QT_') < 0:
91                tl_msg_val = c89_cut(tl_msg_val)
92            # Replace last match, in case the key contains the value string
93            new_msg = old_msg[::-1].replace(tp_msg_val[::-1], tl_msg_val[::-1], 1)[::-1]
94            translation = translation.replace(old_msg, new_msg)
95        # Remove English duplicates and non-translatable strings
96        else:
97            translation = translation.replace(old_msg + '\n', '')
98    return translation
99
100
101with open('msg_hash_us.h', 'r', encoding='utf-8') as template_file:
102    template = template_file.read()
103    with open('msg_hash_us.json', 'r+', encoding='utf-8') as source_json_file:
104        source_messages = json.load(source_json_file)
105        with open(json_filename, 'r+', encoding='utf-8') as json_file:
106            messages = json.load(json_file)
107            new_translation = update(messages, template, source_messages)
108            with open(h_filename, 'w', encoding='utf-8') as h_file:
109                h_file.seek(0)
110                h_file.write(new_translation)
111                h_file.truncate()
112