1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 """Insert debug messages into XLIFF and Gettext PO localization files
22
23 See: http://translate.sourceforge.net/wiki/toolkit/podebug for examples and
24 usage instructions.
25 """
26
27 import os
28 import re
29
30 from translate.misc import hash
31 from translate.storage import factory
32 from translate.storage.placeables import StringElem, general
33 from translate.storage.placeables import parse as rich_parse
34 from translate.convert import dtd2po
35
36
38 for stringelem in stringelems:
39 for string in stringelem.flatten():
40 if len(string.sub) > 0:
41 string.sub[0] = prefix + string.sub[0]
42 return stringelems
43
44 podebug_parsers = general.parsers
45 podebug_parsers.remove(general.CapsPlaceable.parse)
46 podebug_parsers.remove(general.CamelCasePlaceable.parse)
47
49 - def __init__(self, format=None, rewritestyle=None, ignoreoption=None):
50 if format is None:
51 self.format = ""
52 else:
53 self.format = format
54 self.rewritefunc = getattr(self, "rewrite_%s" % rewritestyle, None)
55 self.ignorefunc = getattr(self, "ignore_%s" % ignoreoption, None)
56
63
65 return [rewrite.replace("rewrite_", "") for rewrite in dir(cls) if rewrite.startswith("rewrite_")]
66 rewritelist = classmethod(rewritelist)
67
69 if append is None:
70 append = prepend
71 if not isinstance(string, StringElem):
72 string = StringElem(string)
73 string.sub.insert(0, prepend)
74 if unicode(string).endswith(u'\n'):
75
76 try:
77 lastnode = string.flatten()[-1]
78 if isinstance(lastnode.sub[-1], unicode):
79 lastnode.sub[-1] = lastnode.sub[-1].rstrip(u'\n')
80 except IndexError:
81 pass
82 string.sub.append(append + u'\n')
83 else:
84 string.sub.append(append)
85 return string
86
89
92
97
100
102 """Rewrite using Mock Swedish as made famous by Monty Python"""
103 if not isinstance(string, StringElem):
104 string = StringElem(string)
105
106
107 subs = (
108 (r'a([nu])', r'u\1'),
109 (r'A([nu])', r'U\1'),
110 (r'a\B', r'e'),
111 (r'A\B', r'E'),
112 (r'en\b', r'ee'),
113 (r'\Bew', r'oo'),
114 (r'\Be\b', r'e-a'),
115 (r'\be', r'i'),
116 (r'\bE', r'I'),
117 (r'\Bf', r'ff'),
118 (r'\Bir', r'ur'),
119 (r'(\w*?)i(\w*?)$', r'\1ee\2'),
120 (r'\bow', r'oo'),
121 (r'\bo', r'oo'),
122 (r'\bO', r'Oo'),
123 (r'the', r'zee'),
124 (r'The', r'Zee'),
125 (r'th\b', r't'),
126 (r'\Btion', r'shun'),
127 (r'\Bu', r'oo'),
128 (r'\BU', r'Oo'),
129 (r'v', r'f'),
130 (r'V', r'F'),
131 (r'w', r'w'),
132 (r'W', r'W'),
133 (r'([a-z])[.]', r'\1. Bork Bork Bork!'))
134 for a, b in subs:
135 self.apply_to_translatables(string, lambda s: re.sub(a, b, s))
136 return string
137
138 REWRITE_UNICODE_MAP = u"ȦƁƇḒḖƑƓĦĪĴĶĿḾȠǾƤɊŘŞŦŬṼẆẊẎẐ" + u"[\\]^_`" + u"ȧƀƈḓḗƒɠħīĵķŀḿƞǿƥɋřşŧŭṽẇẋẏẑ"
140 """Convert to Unicode characters that look like the source string"""
141 if not isinstance(string, StringElem):
142 string = StringElem(string)
143 def transpose(char):
144 loc = ord(char)-65
145 if loc < 0 or loc > 56:
146 return char
147 return self.REWRITE_UNICODE_MAP[loc]
148 def transformer(s):
149 return ''.join([transpose(c) for c in s])
150 self.apply_to_translatables(string, transformer)
151 return string
152
153 REWRITE_FLIPPED_MAP = u"¡„#$%⅋,()⁎+´-·/012Ɛᔭ59Ƚ86:;<=>?@" + \
154 u"∀ԐↃᗡƎℲ⅁HIſӼ⅂WNOԀÒᴚS⊥∩ɅMX⅄Z" + u"[\\]ᵥ_," + \
155 u"ɐqɔpǝɟƃɥıɾʞʅɯuodbɹsʇnʌʍxʎz"
156
157
158
159
160
161
162
163
164
166 """Convert the string to look flipped upside down."""
167 if not isinstance(string, StringElem):
168 string = StringElem(string)
169 def transpose(char):
170 loc = ord(char)-33
171 if loc < 0 or loc > 89:
172 return char
173 return self.REWRITE_FLIPPED_MAP[loc]
174 def transformer(s):
175 return u"\u202e" + u''.join([transpose(c) for c in s])
176
177
178 self.apply_to_translatables(string, transformer)
179 return string
180
182 return [ignore.replace("ignore_", "") for ignore in dir(cls) if ignore.startswith("ignore_")]
183 ignorelist = classmethod(ignorelist)
184
186 for location in unit.getlocations():
187 if location.startswith("Common.xcu#..Common.View.Localisation"):
188 return True
189 elif location.startswith("profile.lng#STR_DIR_MENU_NEW_"):
190 return True
191 elif location.startswith("profile.lng#STR_DIR_MENU_WIZARD_"):
192 return True
193 return False
194
196 locations = unit.getlocations()
197 if len(locations) == 1 and locations[0].lower().endswith(".accesskey"):
198 return True
199 for location in locations:
200 if dtd2po.is_css_entity(location):
201 return True
202 if location in ["brandShortName", "brandFullName", "vendorShortName"]:
203 return True
204 if location.lower().endswith(".commandkey") or location.endswith(".key"):
205 return True
206 return False
207
209 if unit.source == "default:LTR":
210 return True
211 return False
212
214 if unit.source == "LTR":
215 return True
216 return False
217
239
241 filename = self.shrinkfilename(store.filename)
242 prefix = self.format
243 for formatstr in re.findall("%[0-9c]*[sfFbBdh]", self.format):
244 if formatstr.endswith("s"):
245 formatted = self.shrinkfilename(store.filename)
246 elif formatstr.endswith("f"):
247 formatted = store.filename
248 formatted = os.path.splitext(formatted)[0]
249 elif formatstr.endswith("F"):
250 formatted = store.filename
251 elif formatstr.endswith("b"):
252 formatted = os.path.basename(store.filename)
253 formatted = os.path.splitext(formatted)[0]
254 elif formatstr.endswith("B"):
255 formatted = os.path.basename(store.filename)
256 elif formatstr.endswith("d"):
257 formatted = os.path.dirname(store.filename)
258 elif formatstr.endswith("h"):
259 try:
260 self.hash_len = int(filter(str.isdigit, formatstr[1:-1]))
261 except ValueError:
262 self.hash_len = 4
263 formatted = "@hash_placeholder@"
264 else:
265 continue
266 formatoptions = formatstr[1:-1]
267 if formatoptions and not formatstr.endswith("h"):
268 if "c" in formatoptions and formatted:
269 formatted = formatted[0] + filter(lambda x: x.lower() not in "aeiou", formatted[1:])
270 length = filter(str.isdigit, formatoptions)
271 if length:
272 formatted = formatted[:int(length)]
273 prefix = prefix.replace(formatstr, formatted)
274 for unit in store.units:
275 if not unit.istranslatable():
276 continue
277 unit = self.convertunit(unit, prefix)
278 return store
279
281 if filename.startswith("." + os.sep):
282 filename = filename.replace("." + os.sep, "", 1)
283 dirname = os.path.dirname(filename)
284 dirparts = dirname.split(os.sep)
285 if not dirparts:
286 dirshrunk = ""
287 else:
288 dirshrunk = dirparts[0][:4] + "-"
289 if len(dirparts) > 1:
290 dirshrunk += "".join([dirpart[0] for dirpart in dirparts[1:]]) + "-"
291 baseshrunk = os.path.basename(filename)[:4]
292 if "." in baseshrunk:
293 baseshrunk = baseshrunk[:baseshrunk.find(".")]
294 return dirshrunk + baseshrunk
295
296 -def convertpo(inputfile, outputfile, templatefile, format=None, rewritestyle=None, ignoreoption=None):
297 """Reads in inputfile, changes it to have debug strings, writes to outputfile."""
298
299 inputstore = factory.getobject(inputfile)
300 if inputstore.isempty():
301 return 0
302 convertor = podebug(format=format, rewritestyle=rewritestyle, ignoreoption=ignoreoption)
303 outputstore = convertor.convertstore(inputstore)
304 outputfile.write(str(outputstore))
305 return 1
306
308 from translate.convert import convert
309 formats = {"po":("po", convertpo), "pot":("po", convertpo), "xlf":("xlf", convertpo)}
310 parser = convert.ConvertOptionParser(formats, description=__doc__)
311
312 parser.add_option("-f", "--format", dest="format", default="",
313 help="specify format string")
314 parser.add_option("", "--rewrite", dest="rewritestyle",
315 type="choice", choices=podebug.rewritelist(), metavar="STYLE",
316 help="the translation rewrite style: %s" % ", ".join(podebug.rewritelist()))
317 parser.add_option("", "--ignore", dest="ignoreoption",
318 type="choice", choices=podebug.ignorelist(), metavar="APPLICATION",
319 help="apply tagging ignore rules for the given application: %s" % ", ".join(podebug.ignorelist()))
320 parser.passthrough.append("format")
321 parser.passthrough.append("rewritestyle")
322 parser.passthrough.append("ignoreoption")
323 parser.run()
324
325
326 if __name__ == '__main__':
327 main()
328