1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """Class that manages TikiWiki files for translation. Tiki files are <strike>ugly and
23 inconsistent</strike> formatted as a single large PHP array with several special
24 sections identified by comments. Example current as of 2008-12-01::
25
26 <?php
27 // Many comments at the top
28 $lang=Array(
29 // ### Start of unused words
30 "aaa" => "zzz",
31 // ### end of unused words
32
33 // ### start of untranslated words
34 // "bbb" => "yyy",
35 // ### end of untranslated words
36
37 // ### start of possibly untranslated words
38 "ccc" => "xxx",
39 // ### end of possibly untranslated words
40
41 "ddd" => "www",
42 "###end###"=>"###end###");
43 ?>
44
45 In addition there are several auto-generated //-style comments scattered through the
46 page and array, some of which matter when being parsed.
47
48 This has all been gleaned from the
49 U{TikiWiki source<http://tikiwiki.svn.sourceforge.net/viewvc/tikiwiki/trunk/get_strings.php?view=markup>}.
50 As far as I know no detailed documentation exists for the tiki language.php files.
51
52 """
53
54 import datetime
55 import re
56
57 from translate.misc import wStringIO
58 from translate.storage import base
59
60
62 """A tiki unit entry."""
63
64 - def __init__(self, source=None, encoding="UTF-8"):
67
69 """Returns a string formatted to be inserted into a tiki language.php file."""
70 ret = u'"%s" => "%s",' % (self.source, self.target)
71 if self.location == ["untranslated"]:
72 ret = u'// ' + ret
73 return ret + "\n"
74
76 """Location is defined by the comments in the file. This function will only
77 set valid locations.
78
79 @param location: Where the string is located in the file. Must be a valid location.
80 """
81 if location in ['unused', 'untranslated', 'possiblyuntranslated', 'translated']:
82 self.location.append(location)
83
85 """Returns the a list of the location(s) of the string."""
86 return self.location
87
88
90 """Represents a tiki language.php file."""
91
93 """If an inputfile is specified it will be parsed.
94
95 @param inputfile: Either a string or a filehandle of the source file
96 """
97 base.TranslationStore.__init__(self, TikiUnit)
98 self.units = []
99 self.filename = getattr(inputfile, 'name', '')
100 if inputfile is not None:
101 self.parse(inputfile)
102
104 """Will return a formatted tiki-style language.php file."""
105 _unused = []
106 _untranslated = []
107 _possiblyuntranslated = []
108 _translated = []
109
110 output = self._tiki_header()
111
112
113 for unit in self.units:
114 if unit.getlocations() == ["unused"]:
115 _unused.append(unit)
116 elif unit.getlocations() == ["untranslated"]:
117 _untranslated.append(unit)
118 elif unit.getlocations() == ["possiblyuntranslated"]:
119 _possiblyuntranslated.append(unit)
120 else:
121 _translated.append(unit)
122
123 output += "// ### Start of unused words\n"
124 for unit in _unused:
125 output += unicode(unit)
126 output += "// ### end of unused words\n\n"
127 output += "// ### start of untranslated words\n"
128 for unit in _untranslated:
129 output += unicode(unit)
130 output += "// ### end of untranslated words\n\n"
131 output += "// ### start of possibly untranslated words\n"
132 for unit in _possiblyuntranslated:
133 output += unicode(unit)
134 output += "// ### end of possibly untranslated words\n\n"
135 for unit in _translated:
136 output += unicode(unit)
137
138 output += self._tiki_footer()
139 return output.encode('UTF-8')
140
142 """Returns a tiki-file header string."""
143 return u"<?php // -*- coding:utf-8 -*-\n// Generated from po2tiki on %s\n\n$lang=Array(\n" % datetime.datetime.now()
144
148
150 """Parse the given input into source units.
151
152 @param input: the source, either a string or filehandle
153 """
154 if hasattr(input, "name"):
155 self.filename = input.name
156
157 if isinstance(input, str):
158 input = wStringIO.StringIO(input)
159
160 _split_regex = re.compile(r"^(?:// )?\"(.*)\" => \"(.*)\",$", re.UNICODE)
161
162 try:
163 _location = "translated"
164
165 for line in input:
166
167
168 if line.count("### Start of unused words"):
169 _location = "unused"
170 elif line.count("### start of untranslated words"):
171 _location = "untranslated"
172 elif line.count("### start of possibly untranslated words"):
173 _location = "possiblyuntranslated"
174 elif line.count("### end of unused words"):
175 _location = "translated"
176 elif line.count("### end of untranslated words"):
177 _location = "translated"
178 elif line.count("### end of possibly untranslated words"):
179 _location = "translated"
180
181 match = _split_regex.match(line)
182
183 if match:
184 unit = self.addsourceunit("".join(match.group(1)))
185
186 if not _location == "untranslated":
187 unit.settarget(match.group(2))
188 unit.addlocation(_location)
189 finally:
190 input.close()
191