1 import sys
2 import os
3 import codecs
4 import pygettext
5
6 MESSAGES = []
7
8
10 encodings_map = [
11 (3, codecs.BOM_UTF8, 'UTF-8'),
12 (4, codecs.BOM_UTF32_LE, 'UTF-32LE'),
13 (4, codecs.BOM_UTF32_BE, 'UTF-32BE'),
14 (2, codecs.BOM_UTF16_LE, 'UTF-16LE'),
15 (2, codecs.BOM_UTF16_BE, 'UTF-16BE'),
16 ]
17 for (offset, bom, name) in encodings_map:
18 if bytes[:offset] == bom:
19 return name, offset
20
21 return 'UTF-8', 0
22
23
25 """Signals an error reading .po file."""
26
27
28 -def merge(master_file, language_files):
29 parsed_master_file = parse(master_file)
30 for path in language_files:
31 merging(parsed_master_file, path)
32
33
34 -def merging(parsed_master_file, path):
35 lang_file = parse(path)
36 id_map = {}
37 new_lang = []
38 for msg in lang_file:
39 message = msg['message']
40 if message:
41 id_map[msg['id']] = message
42
43 for msg in parsed_master_file:
44 msg['message'] = id_map.get(msg['id'])
45 new_lang.append(msg)
46
47 save(path, new_lang)
48
49
50 -def items(path, sort_by, dir):
51 po = parse(path)
52 po = po[1:]
53 if sort_by:
54 return sort(po, sort_by, dir)
55
56 return po
57
58
59 -def sort(po, sort_by, dir):
60 group = dict()
61 sorted = list()
62 col_map = dict(id='id', string='message', context='path')
63 for message in po:
64 group.setdefault(message[col_map[sort_by]], []).append(message)
65
66 kg = group.keys()
67 kg.sort()
68 if dir == 'up':
69 kg.reverse()
70
71 for k in kg:
72 sorted.extend(group[k])
73
74 return sorted
75
76
77 -def save(path, message_list):
78 txt = []
79 m = message_list[0]['message']
80 txt.append(m)
81 txt.append(u'\n\n')
82
83 for p in message_list[1:]:
84 message = p['message'] or ''
85 context = p['context']
86 id = p['id']
87 txt.append(u'#: %s' % context)
88 txt.append(u'msgid %s\n' % normalize(id))
89 txt.append(u'msgstr %s\n\n' % normalize(message))
90
91 txt = u''.join(txt)
92 backup_name = path.replace('.po', '.back')
93
94 try:
95 os.remove(backup_name)
96
97 except os.error:
98 pass
99
100 os.rename(path, backup_name)
101 codecs.open(path, 'wb', 'utf-8').write(txt)
102
103
104 -def update(path, msg_id, msg_text):
105 message_list = parse(path)
106 for p in message_list[1:]:
107 if p['id'].strip() == msg_id.strip():
108 p['message'] = msg_text
109 save(path, message_list)
110
111
114
115
117
118 lines = s.split('\n')
119 if len(lines) == 1:
120 s = '"' + quote(s) + '"'
121
122 else:
123 if not lines[-1]:
124 del lines[-1]
125 lines[-1] = lines[-1] + '\n'
126
127 for i in range(len(lines)):
128 lines[i] = quote(lines[i])
129
130 lineterm = '\\n"\n"'
131 s = '""\n"' + lineterm.join(lines) + '"'
132
133 return s
134
135
136 -def add(id, str, context, fuzzy, MESSAGES):
137 "Add a non-fuzzy translation to the dictionary."
138 if fuzzy:
139 return
140
141 c = context.split(':')
142 path = c[0]
143 file = os.path.basename(path)
144 line = c[-1].replace('\n','')
145
146 MESSAGES.append(dict(id=id,
147 message=str,
148 path=path,
149 context=context,
150 file=file,
151 line=line
152 ))
153
154
156 MESSAGES = list()
157 ID = 1
158 STR = 2
159 header = list()
160
161 fd = open(infile, 'rt')
162 encoding, offset = detect_unicode_encoding(fd.read(4))
163 fd.seek(offset)
164 lines = [line.decode(encoding) for line in fd.readlines()]
165
166 section = None
167 fuzzy = 0
168
169
170 lno = 0
171 context = ''
172 prev_context = ''
173 heading = True
174 for l in lines:
175 if not l:
176 continue
177
178 lno += 1
179 if heading:
180 if l.startswith('#: '):
181 heading = False
182
183 if l.startswith('msgid "') and header and \
184 'Generated-By:' in header[-1]:
185 heading = False
186
187 if l.strip() and heading:
188 header.append(l)
189
190
191 if l[0] == '#' and section == STR:
192 add(msgid, msgstr, prev_context, fuzzy, MESSAGES)
193 section = None
194 fuzzy = 0
195
196
197 if l[:2] == '#,' and l.find('fuzzy'):
198 fuzzy = 1
199
200 if l.startswith('#: '):
201 context = l[len('#: '):]
202
203
204 if l[0] == '#':
205 continue
206
207
208 if l.startswith('msgid'):
209 if section == STR:
210 add(msgid, msgstr, prev_context, fuzzy, MESSAGES)
211
212 section = ID
213 prev_context = context
214 l = l[5:]
215 msgid = msgstr = ''
216
217
218 elif l.startswith('msgstr'):
219 section = STR
220 l = l[6:]
221
222
223 l = l.strip()
224 if not l:
225 continue
226
227
228 try:
229 l = eval(l)
230 except Exception, e:
231 print >> sys.stderr, 'Escape error on %s: %d' % (infile, lno), \
232 'before:', repr(l)
233 raise ParseError(e)
234
235 try:
236 l = l.decode('utf8')
237 except UnicodeDecodeError:
238 print >> sys.stderr, 'Encoding error on %s: %d' % (infile, lno), \
239 'before:', repr(l)
240 raise ParseError(e)
241
242 if section == ID:
243 msgid += l
244
245 elif section == STR:
246 msgstr += l
247
248 else:
249 print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
250 'before:'
251 print >> sys.stderr, l
252 raise ParseError(e)
253
254
255 if section == STR:
256 add(msgid, msgstr, prev_context, fuzzy, MESSAGES)
257
258 MESSAGES[0]['message'] = u''.join(header)
259 return MESSAGES
260