1#
2# Copyright 2008-2009 Zuza Software Foundation
3#
4# This file is part of the Translate Toolkit.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, see <http://www.gnu.org/licenses/>.
18
19"""Convert Symbian localisation files to Gettext PO localization files.
20
21See: http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/symb2po.html
22for examples and usage instructions.
23"""
24
25from translate.storage import factory
26from translate.storage.pypo import unescape
27from translate.storage.symbian import (
28    ParseState,
29    eat_whitespace,
30    header_item_or_end_re,
31    header_item_re,
32    identity,
33    read_charset,
34    read_while,
35    skip_no_translate,
36    string_entry_re,
37)
38
39
40def read_header_items(ps):
41    match = read_while(ps, header_item_or_end_re.match, lambda match: match is None)
42    if match.groupdict()["end_comment"] is not None:
43        return {}
44
45    results = {}
46    while match:
47        match_chunks = match.groupdict()
48        ps.read_line()
49        results[match_chunks["key"]] = match_chunks["value"]
50        match = header_item_re.match(ps.current_line)
51
52    match = read_while(ps, identity, lambda line: not line.startswith("*/"))
53    ps.read_line()
54    return results
55
56
57def parse(ps):
58    header = read_header_items(ps)
59    units = []
60    try:
61        while True:
62            eat_whitespace(ps)
63            skip_no_translate(ps)
64            match = string_entry_re.match(ps.current_line)
65            if match is not None:
66                units.append(
67                    (match.groupdict()["id"], unescape(match.groupdict()["str"][1:-1]))
68                )
69            ps.read_line()
70    except StopIteration:
71        pass
72    return header, units
73
74
75def read_symbian(f):
76    lines = list(f)
77    charset = read_charset(lines)
78    return parse(ParseState(iter(lines), charset))
79
80
81def get_template_dict(template_file):
82    if template_file is not None:
83        template_header, template_units = read_symbian(template_file)
84        return template_header, dict(template_units)
85    else:
86        return {}, {}
87
88
89def build_output(units, template_header, template_dict):
90    output_store = factory.classes["po"]()
91    ignore = {"r_string_languagegroup_name"}
92    header_entries = {
93        "Last-Translator": template_header.get("Author", ""),
94        "Language-Team": template_dict.get("r_string_languagegroup_name", ""),
95        "Content-Transfer-Encoding": "8bit",
96        "Content-Type": "text/plain; charset=UTF-8",
97    }
98    output_store.updateheader(add=True, **header_entries)
99    for id, source in units:
100        if id in ignore:
101            continue
102        unit = output_store.UnitClass(source)
103        unit.target = template_dict.get(id, "")
104        unit.addlocation(id)
105        output_store.addunit(unit)
106    return output_store
107
108
109def convert_symbian(
110    input_file, output_file, template_file, pot=False, duplicatestyle="msgctxt"
111):
112    header, units = read_symbian(input_file)
113    template_header, template_dict = get_template_dict(template_file)
114    output_store = build_output(units, template_header, template_dict)
115
116    if output_store.isempty():
117        return 0
118    else:
119        output_store.serialize(output_file)
120        return 1
121
122
123def main(argv=None):
124    from translate.convert import convert
125
126    formats = {"r01": ("po", convert_symbian)}
127    parser = convert.ConvertOptionParser(
128        formats, usetemplates=True, usepots=True, description=__doc__
129    )
130    parser.add_duplicates_option()
131    parser.passthrough.append("pot")
132    parser.run(argv)
133
134
135if __name__ == "__main__":
136    main()
137