Merge lp:~henninge/launchpad/bug-565294-devel into lp:launchpad
- bug-565294-devel
- Merge into devel
Proposed by
Henning Eggers
Status: | Merged |
---|---|
Approved by: | Henning Eggers |
Approved revision: | no longer in the source branch. |
Merged at revision: | not available |
Proposed branch: | lp:~henninge/launchpad/bug-565294-devel |
Merge into: | lp:launchpad |
Diff against target: |
763 lines (+219/-89) 2 files modified
lib/lp/translations/model/pofile.py (+42/-23) lib/lp/translations/tests/test_pofile.py (+177/-66) |
To merge this branch: | bzr merge lp:~henninge/launchpad/bug-565294-devel |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Nelson (community) | code | Approve | |
Review via email:
|
Commit message
When exporting PO files, use the plural information from the imported file in some cases instead of the information from the language database.
Description of the change
Merging already approved branch into devel instead of production-devel.
https:/
No changes since last approval. ;-)
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/translations/model/pofile.py' |
2 | --- lib/lp/translations/model/pofile.py 2010-01-14 16:39:18 +0000 |
3 | +++ lib/lp/translations/model/pofile.py 2010-04-26 10:23:30 +0000 |
4 | @@ -34,7 +34,6 @@ |
5 | from canonical.launchpad.webapp.interfaces import ( |
6 | DEFAULT_FLAVOR, IStoreSelector, MAIN_STORE, MASTER_FLAVOR) |
7 | from canonical.launchpad.webapp.publisher import canonical_url |
8 | -from canonical.librarian.interfaces import ILibrarianClient |
9 | from lp.registry.interfaces.person import validate_public_person |
10 | from lp.registry.model.person import Person |
11 | from lp.translations.utilities.rosettastats import RosettaStats |
12 | @@ -792,7 +791,6 @@ |
13 | |
14 | # A POT set has "new" suggestions if there is a non current |
15 | # TranslationMessage newer than the current reviewed one. |
16 | - store = Store.of(self) |
17 | query = ( |
18 | """POTMsgSet.id IN (SELECT DISTINCT TranslationMessage.potmsgset |
19 | FROM TranslationMessage, TranslationTemplateItem, POTMsgSet |
20 | @@ -1026,10 +1024,6 @@ |
21 | entry_to_import = removeSecurityProxy(entry_to_import) |
22 | |
23 | translation_importer = getUtility(ITranslationImporter) |
24 | - librarian_client = getUtility(ILibrarianClient) |
25 | - |
26 | - import_file = librarian_client.getFileByAlias( |
27 | - entry_to_import.content.id) |
28 | |
29 | # While importing a file, there are two kinds of errors: |
30 | # |
31 | @@ -1125,7 +1119,6 @@ |
32 | # There were some errors with translations. |
33 | errorsdetails = '' |
34 | for error in errors: |
35 | - pofile = error['pofile'] |
36 | potmsgset = error['potmsgset'] |
37 | pomessage = error['pomessage'] |
38 | error_message = error['error-message'] |
39 | @@ -1706,6 +1699,47 @@ |
40 | |
41 | return self._pofile.language.code |
42 | |
43 | + def _isWesternPluralForm(self, number, expression): |
44 | + # Western style is nplurals=2;plural=n!=1. |
45 | + if number != 2: |
46 | + return False |
47 | + if expression is None: |
48 | + return False |
49 | + # Normalize: Remove spaces. |
50 | + expression = expression.replace(' ', '') |
51 | + # Normalize: Remove enclosing brackets. |
52 | + expression = expression.strip('()') |
53 | + return expression in ('n!=1', '1!=n', 'n>1', '1<n') |
54 | + |
55 | + def _updateHeaderPluralInfo(self, header): |
56 | + header_nplurals = header.number_plural_forms |
57 | + database_nplurals = self._pofile.language.pluralforms |
58 | + # These checks are here to catch cases where the plural information |
59 | + # from the header might be more acurate than what we have in the |
60 | + # database. This is usually the case when the number of plural forms |
61 | + # has grown but not if it's the standard western form. |
62 | + # See bug 565294 |
63 | + if header_nplurals is not None and database_nplurals is not None: |
64 | + if header_nplurals > database_nplurals: |
65 | + is_western = self._isWesternPluralForm( |
66 | + header_nplurals, header.plural_form_expression) |
67 | + if not is_western: |
68 | + # Use existing information from the header. |
69 | + return |
70 | + if database_nplurals is None: |
71 | + # In all other cases we never use the plural info from the header. |
72 | + header.number_plural_forms = None |
73 | + header.plural_form_expression = None |
74 | + else: |
75 | + # We have pluralforms information for this language so we |
76 | + # update the header to be sure that we use the language |
77 | + # information from our database instead of using the one |
78 | + # that we got from upstream. We check this information so |
79 | + # we are sure it's valid. |
80 | + header.number_plural_forms = self._pofile.language.pluralforms |
81 | + header.plural_form_expression = ( |
82 | + self._pofile.language.pluralexpression) |
83 | + |
84 | @cachedproperty |
85 | def header(self): |
86 | """See `ITranslationFileData`.""" |
87 | @@ -1713,28 +1747,13 @@ |
88 | translation_header = self._pofile.getHeader() |
89 | # Update default fields based on its values in the template header. |
90 | translation_header.updateFromTemplateHeader(template_header) |
91 | - date_reviewed = None |
92 | translation_header.translation_revision_date = ( |
93 | self._pofile.date_changed) |
94 | |
95 | translation_header.comment = self._pofile.topcomment |
96 | |
97 | if self._pofile.potemplate.hasPluralMessage(): |
98 | - number_plural_forms = None |
99 | - plural_form_expression = None |
100 | - if self._pofile.language.pluralforms is not None: |
101 | - # We have pluralforms information for this language so we |
102 | - # update the header to be sure that we use the language |
103 | - # information from our database instead of use the one |
104 | - # that we got from upstream. We check this information so |
105 | - # we are sure it's valid. |
106 | - number_plural_forms = self._pofile.language.pluralforms |
107 | - plural_form_expression = ( |
108 | - self._pofile.language.pluralexpression) |
109 | - |
110 | - translation_header.number_plural_forms = number_plural_forms |
111 | - translation_header.plural_form_expression = plural_form_expression |
112 | - |
113 | + self._updateHeaderPluralInfo(translation_header) |
114 | if (self._pofile.lasttranslator is not None): |
115 | email = self._pofile.lasttranslator.safe_email_or_blank |
116 | if not email: |
117 | |
118 | === modified file 'lib/lp/translations/tests/test_pofile.py' |
119 | --- lib/lp/translations/tests/test_pofile.py 2010-01-12 21:29:03 +0000 |
120 | +++ lib/lp/translations/tests/test_pofile.py 2010-04-26 10:23:30 +0000 |
121 | @@ -7,7 +7,8 @@ |
122 | |
123 | from datetime import datetime, timedelta |
124 | import pytz |
125 | -import unittest |
126 | +from textwrap import dedent |
127 | +from unittest import TestLoader |
128 | |
129 | from zope.component import getAdapter, getUtility |
130 | from zope.security.proxy import removeSecurityProxy |
131 | @@ -93,7 +94,7 @@ |
132 | self.assertEquals(found_potmsgsets, [plural_potmsgset]) |
133 | |
134 | # Search translations as well. |
135 | - translation = self.factory.makeTranslationMessage( |
136 | + self.factory.makeTranslationMessage( |
137 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
138 | translations=[u"One translation message"]) |
139 | found_potmsgsets = list( |
140 | @@ -101,7 +102,7 @@ |
141 | self.assertEquals(found_potmsgsets, [potmsgset]) |
142 | |
143 | # Search matches all plural forms. |
144 | - plural_translation = self.factory.makeTranslationMessage( |
145 | + self.factory.makeTranslationMessage( |
146 | pofile=self.devel_sr_pofile, potmsgset=plural_potmsgset, |
147 | translations=[u"One translation message", |
148 | u"Plural translation message", |
149 | @@ -153,7 +154,7 @@ |
150 | # If somebody else provides a translation, it's not added to the |
151 | # list of submitter's translations. |
152 | someone_else = self.factory.makePerson() |
153 | - other_translation = self.factory.makeTranslationMessage( |
154 | + self.factory.makeTranslationMessage( |
155 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
156 | translations=[u"Another translation"], |
157 | translator=someone_else) |
158 | @@ -166,7 +167,7 @@ |
159 | # to the list of submitter's translations for *former* POFile. |
160 | self.devel_sr_latin_pofile = self.factory.makePOFile( |
161 | 'sr', variant=u'latin', potemplate=self.devel_potemplate) |
162 | - latin_translation = self.factory.makeTranslationMessage( |
163 | + self.factory.makeTranslationMessage( |
164 | pofile=self.devel_sr_latin_pofile, potmsgset=potmsgset, |
165 | translations=[u"Yet another translation"], |
166 | translator=submitter) |
167 | @@ -194,7 +195,7 @@ |
168 | self.assertEquals(found_translations, []) |
169 | |
170 | # When a diverged translation is added, the potmsgset is returned. |
171 | - translation = self.factory.makeTranslationMessage( |
172 | + self.factory.makeTranslationMessage( |
173 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
174 | translations=[u"Translation"]) |
175 | found_translations = list( |
176 | @@ -202,7 +203,7 @@ |
177 | self.assertEquals(found_translations, [self.potmsgset]) |
178 | |
179 | # If diverged translation is empty, POTMsgSet is not listed. |
180 | - translation = self.factory.makeTranslationMessage( |
181 | + self.factory.makeTranslationMessage( |
182 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
183 | translations=[u""]) |
184 | found_translations = list( |
185 | @@ -214,7 +215,7 @@ |
186 | # translation for the POTMsgSet as well. |
187 | |
188 | # We create a shared translation first. |
189 | - shared_translation = self.factory.makeSharedTranslationMessage( |
190 | + self.factory.makeSharedTranslationMessage( |
191 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
192 | translations=[u"Shared translation"]) |
193 | |
194 | @@ -224,7 +225,7 @@ |
195 | self.assertEquals(found_translations, [self.potmsgset]) |
196 | |
197 | # When an empty diverged translation is added, nothing is listed. |
198 | - translation = self.factory.makeTranslationMessage( |
199 | + self.factory.makeTranslationMessage( |
200 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
201 | translations=[u""]) |
202 | found_translations = list( |
203 | @@ -232,7 +233,7 @@ |
204 | self.assertEquals(found_translations, []) |
205 | |
206 | # If diverged translation is non-empty, POTMsgSet is listed. |
207 | - translation = self.factory.makeTranslationMessage( |
208 | + self.factory.makeTranslationMessage( |
209 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
210 | translations=[u"Translation"]) |
211 | found_translations = list( |
212 | @@ -244,7 +245,7 @@ |
213 | # empty shared translation for the POTMsgSet as well. |
214 | |
215 | # We create an empty shared translation first. |
216 | - shared_translation = self.factory.makeSharedTranslationMessage( |
217 | + self.factory.makeSharedTranslationMessage( |
218 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
219 | translations=[u""]) |
220 | |
221 | @@ -255,7 +256,7 @@ |
222 | self.assertEquals(found_translations, []) |
223 | |
224 | # When an empty diverged translation is added, nothing is listed. |
225 | - translation = self.factory.makeTranslationMessage( |
226 | + self.factory.makeTranslationMessage( |
227 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
228 | translations=[u""]) |
229 | found_translations = list( |
230 | @@ -263,7 +264,7 @@ |
231 | self.assertEquals(found_translations, []) |
232 | |
233 | # If diverged translation is non-empty, POTMsgSet is listed. |
234 | - translation = self.factory.makeTranslationMessage( |
235 | + self.factory.makeTranslationMessage( |
236 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
237 | translations=[u"Translation"]) |
238 | found_translations = list( |
239 | @@ -275,7 +276,7 @@ |
240 | # translated message. |
241 | |
242 | # Add a diverged translation on the included POTMsgSet... |
243 | - translation = self.factory.makeTranslationMessage( |
244 | + self.factory.makeTranslationMessage( |
245 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
246 | translations=[u"Diverged translation"]) |
247 | |
248 | @@ -284,7 +285,7 @@ |
249 | u"Translated text") |
250 | potmsgset.setSequence(self.devel_potemplate, 2) |
251 | |
252 | - shared_translation = self.factory.makeSharedTranslationMessage( |
253 | + self.factory.makeSharedTranslationMessage( |
254 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
255 | translations=[u"Shared translation"]) |
256 | |
257 | @@ -303,7 +304,7 @@ |
258 | self.assertEquals(found_translations, [self.potmsgset]) |
259 | |
260 | # When a diverged translation is added, the potmsgset is returned. |
261 | - translation = self.factory.makeTranslationMessage( |
262 | + self.factory.makeTranslationMessage( |
263 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
264 | translations=[u"Translation"]) |
265 | found_translations = list( |
266 | @@ -311,7 +312,7 @@ |
267 | self.assertEquals(found_translations, []) |
268 | |
269 | # If diverged translation is empty, POTMsgSet is not listed. |
270 | - translation = self.factory.makeTranslationMessage( |
271 | + self.factory.makeTranslationMessage( |
272 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
273 | translations=[u""]) |
274 | found_translations = list( |
275 | @@ -323,7 +324,7 @@ |
276 | # translation for the POTMsgSet as well. |
277 | |
278 | # We create a shared translation first. |
279 | - shared_translation = self.factory.makeSharedTranslationMessage( |
280 | + self.factory.makeSharedTranslationMessage( |
281 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
282 | translations=[u"Shared translation"]) |
283 | |
284 | @@ -333,7 +334,7 @@ |
285 | self.assertEquals(found_translations, []) |
286 | |
287 | # When an empty diverged translation is added, nothing is listed. |
288 | - translation = self.factory.makeTranslationMessage( |
289 | + self.factory.makeTranslationMessage( |
290 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
291 | translations=[u""]) |
292 | found_translations = list( |
293 | @@ -341,7 +342,7 @@ |
294 | self.assertEquals(found_translations, [self.potmsgset]) |
295 | |
296 | # If diverged translation is non-empty, POTMsgSet is listed. |
297 | - translation = self.factory.makeTranslationMessage( |
298 | + self.factory.makeTranslationMessage( |
299 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
300 | translations=[u"Translation"]) |
301 | found_translations = list( |
302 | @@ -353,7 +354,7 @@ |
303 | # empty shared translation for the POTMsgSet as well. |
304 | |
305 | # We create an empty shared translation first. |
306 | - shared_translation = self.factory.makeSharedTranslationMessage( |
307 | + self.factory.makeSharedTranslationMessage( |
308 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
309 | translations=[u""]) |
310 | |
311 | @@ -364,7 +365,7 @@ |
312 | self.assertEquals(found_translations, [self.potmsgset]) |
313 | |
314 | # When an empty diverged translation is added, nothing is listed. |
315 | - translation = self.factory.makeTranslationMessage( |
316 | + self.factory.makeTranslationMessage( |
317 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
318 | translations=[u""]) |
319 | found_translations = list( |
320 | @@ -372,7 +373,7 @@ |
321 | self.assertEquals(found_translations, [self.potmsgset]) |
322 | |
323 | # If diverged translation is non-empty, POTMsgSet is listed. |
324 | - translation = self.factory.makeTranslationMessage( |
325 | + self.factory.makeTranslationMessage( |
326 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
327 | translations=[u"Translation"]) |
328 | found_translations = list( |
329 | @@ -384,7 +385,7 @@ |
330 | # untranslated message. |
331 | |
332 | # Add an empty translation to the included POTMsgSet... |
333 | - translation = self.factory.makeTranslationMessage( |
334 | + self.factory.makeTranslationMessage( |
335 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
336 | translations=[u""]) |
337 | |
338 | @@ -478,14 +479,14 @@ |
339 | |
340 | # A POTMsgSet has a shared, current translation created 5 days ago. |
341 | date_created = datetime.now(pytz.UTC)-timedelta(5) |
342 | - translation = self.factory.makeSharedTranslationMessage( |
343 | + self.factory.makeSharedTranslationMessage( |
344 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
345 | translations=[u"Shared translation"], date_updated=date_created) |
346 | |
347 | # And we also have a diverged translation created a day after shared |
348 | # current translation. |
349 | diverged_date = date_created + timedelta(1) |
350 | - translation = self.factory.makeTranslationMessage( |
351 | + self.factory.makeTranslationMessage( |
352 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
353 | translations=[u"Old translation"], date_updated=diverged_date) |
354 | |
355 | @@ -536,7 +537,7 @@ |
356 | # Test that multiple unreviewed POTMsgSets are returned. |
357 | |
358 | # One POTMsgSet has no translations, but only a suggestion. |
359 | - translation = self.factory.makeTranslationMessage( |
360 | + self.factory.makeTranslationMessage( |
361 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
362 | translations=[u"New suggestion"], suggestion=True) |
363 | |
364 | @@ -545,11 +546,11 @@ |
365 | u"Translated text") |
366 | potmsgset.setSequence(self.devel_potemplate, 2) |
367 | date_created = datetime.now(pytz.UTC) - timedelta(5) |
368 | - translation = self.factory.makeTranslationMessage( |
369 | + self.factory.makeTranslationMessage( |
370 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
371 | translations=[u"Translation"], date_updated=date_created) |
372 | suggestion_date = date_created + timedelta(1) |
373 | - translation = self.factory.makeTranslationMessage( |
374 | + self.factory.makeTranslationMessage( |
375 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
376 | translations=[u"New suggestion"], suggestion=True, |
377 | date_updated=suggestion_date) |
378 | @@ -562,12 +563,12 @@ |
379 | def test_getPOTMsgSetWithNewSuggestions_distinct(self): |
380 | # Provide two suggestions on a single message and make sure |
381 | # a POTMsgSet is returned only once. |
382 | - translation1 = self.factory.makeSharedTranslationMessage( |
383 | + self.factory.makeSharedTranslationMessage( |
384 | pofile=self.devel_sr_pofile, |
385 | potmsgset=self.potmsgset, |
386 | translations=["A suggestion"], |
387 | suggestion=True) |
388 | - translation2 = self.factory.makeSharedTranslationMessage( |
389 | + self.factory.makeSharedTranslationMessage( |
390 | pofile=self.devel_sr_pofile, |
391 | potmsgset=self.potmsgset, |
392 | translations=["Another suggestion"], |
393 | @@ -646,7 +647,6 @@ |
394 | |
395 | # But adding a diverged current and imported translation means |
396 | # that it's not changed anymore. |
397 | - old_translation = translation |
398 | translation = self.factory.makeTranslationMessage( |
399 | pofile=self.devel_sr_pofile, potmsgset=self.potmsgset, |
400 | translations=[u"Diverged imported"], is_imported=True, |
401 | @@ -753,42 +753,42 @@ |
402 | # Second POTMsgSet is untranslated, but with a suggestion. |
403 | potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate) |
404 | potmsgset.setSequence(self.devel_potemplate, 2) |
405 | - translation = self.factory.makeTranslationMessage( |
406 | + self.factory.makeTranslationMessage( |
407 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
408 | translations=[u"Unreviewed suggestion"], suggestion=True) |
409 | |
410 | # Third POTMsgSet is translated, and with a suggestion. |
411 | potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate) |
412 | potmsgset.setSequence(self.devel_potemplate, 3) |
413 | - translation = self.factory.makeTranslationMessage( |
414 | + self.factory.makeTranslationMessage( |
415 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
416 | translations=[u"Translation"], suggestion=False, |
417 | date_updated=datetime.now(pytz.UTC)-timedelta(1)) |
418 | - translation = self.factory.makeTranslationMessage( |
419 | + self.factory.makeTranslationMessage( |
420 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
421 | translations=[u"Another suggestion"], suggestion=True) |
422 | |
423 | # Fourth POTMsgSet is translated in import. |
424 | potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate) |
425 | potmsgset.setSequence(self.devel_potemplate, 4) |
426 | - translation = self.factory.makeTranslationMessage( |
427 | + self.factory.makeTranslationMessage( |
428 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
429 | translations=[u"Imported translation"], is_imported=True) |
430 | |
431 | # Fifth POTMsgSet is translated in import, but changed in LP. |
432 | potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate) |
433 | potmsgset.setSequence(self.devel_potemplate, 5) |
434 | - translation = self.factory.makeTranslationMessage( |
435 | + self.factory.makeTranslationMessage( |
436 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
437 | translations=[u"Imported translation"], is_imported=True) |
438 | - translation = self.factory.makeTranslationMessage( |
439 | + self.factory.makeTranslationMessage( |
440 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
441 | translations=[u"LP translation"], is_imported=False) |
442 | |
443 | # Sixth POTMsgSet is translated in LP only. |
444 | potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate) |
445 | potmsgset.setSequence(self.devel_potemplate, 6) |
446 | - translation = self.factory.makeTranslationMessage( |
447 | + self.factory.makeTranslationMessage( |
448 | pofile=self.devel_sr_pofile, potmsgset=potmsgset, |
449 | translations=[u"New translation"], is_imported=False) |
450 | |
451 | @@ -810,7 +810,7 @@ |
452 | def test_TranslationFileData_adapter(self): |
453 | # Test that exporting works correctly with shared and diverged |
454 | # messages. |
455 | - shared_translation = self.factory.makeSharedTranslationMessage( |
456 | + self.factory.makeSharedTranslationMessage( |
457 | pofile=self.devel_sr_pofile, |
458 | potmsgset=self.potmsgset, |
459 | translations=["Shared translation"]) |
460 | @@ -827,7 +827,7 @@ |
461 | "Shared translation")]) |
462 | |
463 | # When we add a diverged translation, only that is exported. |
464 | - diverged_translation = self.factory.makeTranslationMessage( |
465 | + self.factory.makeTranslationMessage( |
466 | pofile=self.devel_sr_pofile, |
467 | potmsgset=self.potmsgset, |
468 | translations=["Diverged translation"], |
469 | @@ -887,7 +887,7 @@ |
470 | productseries=self.foo_stable, name="template-2") |
471 | |
472 | self.assertEqual(None, potemplate_devel_1.getPOFileByLang('eo')) |
473 | - pofile_devel = potemplate_devel_1.newPOFile('eo') |
474 | + potemplate_devel_1.newPOFile('eo') |
475 | self.assertEqual(None, potemplate_stable_2.getPOFileByLang('eo')) |
476 | |
477 | def test_potemplate_creation(self): |
478 | @@ -895,14 +895,14 @@ |
479 | # all shared potemplates. |
480 | foo_other = self.factory.makeProductSeries( |
481 | name='other', product=self.foo) |
482 | - other_potemplate = self.factory.makePOTemplate( |
483 | + self.factory.makePOTemplate( |
484 | productseries=foo_other, name="messages") |
485 | devel_potemplate = self.factory.makePOTemplate( |
486 | productseries=self.foo_devel, name="messages") |
487 | # These will automatically be shared across all sharing templates. |
488 | # They will also be created in the 'other' series. |
489 | - pofile_devel_eo = devel_potemplate.newPOFile('eo') |
490 | - pofile_devel_de = devel_potemplate.newPOFile('de') |
491 | + devel_potemplate.newPOFile('eo') |
492 | + devel_potemplate.newPOFile('de') |
493 | |
494 | stable_potemplate = self.factory.makePOTemplate( |
495 | productseries=self.foo_stable, name="messages") |
496 | @@ -1015,11 +1015,11 @@ |
497 | def test_getPOTMsgSetTranslated_ordering(self): |
498 | # Translate both POTMsgSets in devel_sr_pofile, so |
499 | # they are returned with getPOTMsgSetTranslated() call. |
500 | - translation1 = self.factory.makeSharedTranslationMessage( |
501 | + self.factory.makeSharedTranslationMessage( |
502 | pofile=self.devel_sr_pofile, |
503 | potmsgset=self.potmsgset1, |
504 | translations=["Shared translation"]) |
505 | - translation2 = self.factory.makeSharedTranslationMessage( |
506 | + self.factory.makeSharedTranslationMessage( |
507 | pofile=self.devel_sr_pofile, |
508 | potmsgset=self.potmsgset2, |
509 | translations=["Another shared translation"]) |
510 | @@ -1073,22 +1073,22 @@ |
511 | def test_getPOTMsgSetChangedInLaunchpad_ordering(self): |
512 | # Suggest a translation on both POTMsgSets in devel_sr_pofile, |
513 | # so they are returned with getPOTMsgSetWithNewSuggestions() call. |
514 | - imported1 = self.factory.makeSharedTranslationMessage( |
515 | + self.factory.makeSharedTranslationMessage( |
516 | pofile=self.devel_sr_pofile, |
517 | potmsgset=self.potmsgset1, |
518 | translations=["Imported"], |
519 | is_imported=True) |
520 | - translation1 = self.factory.makeSharedTranslationMessage( |
521 | + self.factory.makeSharedTranslationMessage( |
522 | pofile=self.devel_sr_pofile, |
523 | potmsgset=self.potmsgset1, |
524 | translations=["Changed"], |
525 | is_imported=False) |
526 | - imported2 = self.factory.makeSharedTranslationMessage( |
527 | + self.factory.makeSharedTranslationMessage( |
528 | pofile=self.devel_sr_pofile, |
529 | potmsgset=self.potmsgset2, |
530 | translations=["Another imported"], |
531 | is_imported=True) |
532 | - translation2 = self.factory.makeSharedTranslationMessage( |
533 | + self.factory.makeSharedTranslationMessage( |
534 | pofile=self.devel_sr_pofile, |
535 | potmsgset=self.potmsgset2, |
536 | translations=["Another changed"], |
537 | @@ -1186,11 +1186,11 @@ |
538 | # This test will go away when potmsgset.sequence goes away. |
539 | |
540 | # Give the method something to search for. |
541 | - translation1 = self.factory.makeSharedTranslationMessage( |
542 | + self.factory.makeSharedTranslationMessage( |
543 | pofile=self.devel_sr_pofile, |
544 | potmsgset=self.potmsgset1, |
545 | translations=["Shared translation"]) |
546 | - translation2 = self.factory.makeSharedTranslationMessage( |
547 | + self.factory.makeSharedTranslationMessage( |
548 | pofile=self.devel_sr_pofile, |
549 | potmsgset=self.potmsgset2, |
550 | translations=["Another shared translation"]) |
551 | @@ -1410,7 +1410,7 @@ |
552 | # All POFiles with translation credits messages are |
553 | # returned along with relevant POTMsgSets. |
554 | potemplate1 = self.factory.makePOTemplate() |
555 | - credits_potmsgset = self.factory.makePOTMsgSet( |
556 | + self.factory.makePOTMsgSet( |
557 | potemplate1, singular=u'translator-credits', sequence=1) |
558 | |
559 | sr_pofile = self.factory.makePOFile('sr', potemplate=potemplate1) |
560 | @@ -1430,7 +1430,7 @@ |
561 | # If another POTemplate has a translation credits message, it's |
562 | # returned as well. |
563 | potemplate2 = self.factory.makePOTemplate() |
564 | - kde_credits_potmsgset = self.factory.makePOTMsgSet( |
565 | + self.factory.makePOTMsgSet( |
566 | potemplate2, singular=u'Your names', |
567 | context=u'NAME OF TRANSLATORS', sequence=1) |
568 | sr_kde_pofile = self.factory.makePOFile('sr', potemplate=potemplate2) |
569 | @@ -1493,7 +1493,7 @@ |
570 | def test_getPOFilesByPathAndOrigin_path_mismatch(self): |
571 | # getPOFilesByPathAndOrigin matches on POFile path. |
572 | template = self.factory.makePOTemplate() |
573 | - pofile = template.newPOFile('ta') |
574 | + template.newPOFile('ta') |
575 | |
576 | not_found = self.pofileset.getPOFilesByPathAndOrigin( |
577 | 'tu.po', distroseries=template.distroseries, |
578 | @@ -1613,7 +1613,7 @@ |
579 | self.assertEquals(self.pofile.currentCount(), 0) |
580 | |
581 | # Adding an imported translation increases currentCount(). |
582 | - imported = self.factory.makeTranslationMessage( |
583 | + self.factory.makeTranslationMessage( |
584 | pofile=self.pofile, |
585 | potmsgset=self.potmsgset, |
586 | translations=["Imported current"], |
587 | @@ -1624,7 +1624,7 @@ |
588 | # Adding a suggestion (i.e. unused translation) |
589 | # will not change the current count when there's |
590 | # already an imported message. |
591 | - suggestion = self.factory.makeTranslationMessage( |
592 | + self.factory.makeTranslationMessage( |
593 | pofile=self.pofile, |
594 | potmsgset=self.potmsgset, |
595 | translations=["A suggestion"], |
596 | @@ -1640,7 +1640,7 @@ |
597 | |
598 | # Adding a current translation for an untranslated |
599 | # message increases the count of new translations in LP. |
600 | - current = self.factory.makeTranslationMessage( |
601 | + self.factory.makeTranslationMessage( |
602 | pofile=self.pofile, |
603 | potmsgset=self.potmsgset, |
604 | translations=["Current"]) |
605 | @@ -1651,12 +1651,12 @@ |
606 | # If we get an 'imported' translation for what |
607 | # we already have as 'new', it's not considered 'new' |
608 | # anymore since it has been synced. |
609 | - current = self.factory.makeTranslationMessage( |
610 | + self.factory.makeTranslationMessage( |
611 | pofile=self.pofile, |
612 | potmsgset=self.potmsgset, |
613 | translations=["Current"]) |
614 | # Reimport it but with is_imported=True. |
615 | - imported = self.factory.makeTranslationMessage( |
616 | + self.factory.makeTranslationMessage( |
617 | pofile=self.pofile, |
618 | potmsgset=self.potmsgset, |
619 | translations=["Current"], |
620 | @@ -1669,12 +1669,12 @@ |
621 | # If we change an 'imported' translation through |
622 | # Launchpad, it's still not considered 'new', |
623 | # but an 'update' instead. |
624 | - imported = self.factory.makeTranslationMessage( |
625 | + self.factory.makeTranslationMessage( |
626 | pofile=self.pofile, |
627 | potmsgset=self.potmsgset, |
628 | translations=["Imported"], |
629 | is_imported=True) |
630 | - update = self.factory.makeTranslationMessage( |
631 | + self.factory.makeTranslationMessage( |
632 | pofile=self.pofile, |
633 | potmsgset=self.potmsgset, |
634 | translations=["Changed"]) |
635 | @@ -1722,8 +1722,7 @@ |
636 | |
637 | def test_getTranslationRows_sequence(self): |
638 | # Test for correct sorting of obsolete messages (where sequence=0). |
639 | - msgsets = [ |
640 | - self._createMessageSet(msg) for msg in self.TEST_MESSAGES] |
641 | + [self._createMessageSet(msg) for msg in self.TEST_MESSAGES] |
642 | for rownum, row in enumerate( |
643 | self.pofile.getTranslationRows()): |
644 | self.failUnlessEqual( |
645 | @@ -1732,5 +1731,117 @@ |
646 | "(sequence=0) to the end of the file.") |
647 | |
648 | |
649 | +class TestPOFileToTranslationFileDataAdapter(TestCaseWithFactory): |
650 | + """Test POFile being adapted to IPOFileToTranslationFileData.""" |
651 | + |
652 | + layer = ZopelessDatabaseLayer |
653 | + |
654 | + header = dedent(""" |
655 | + Project-Id-Version: foo |
656 | + Report-Msgid-Bugs-To: |
657 | + POT-Creation-Date: 2007-07-09 03:39+0100 |
658 | + PO-Revision-Date: 2001-09-09 01:46+0000 |
659 | + Last-Translator: Kubla Kahn <kk@pleasure-dome.com> |
660 | + Language-Team: Serbian <sr@li.org> |
661 | + MIME-Version: 1.0 |
662 | + Content-Type: text/plain; charset=UTF-8 |
663 | + Content-Transfer-Encoding: 8bit |
664 | + Plural-Forms: %s""") |
665 | + |
666 | + western_plural = "nplurals=2; plural=(n != 1)" |
667 | + other_2_plural = "nplurals=2; plural=(n > 0)" |
668 | + generic_plural = "nplurals=INTEGER; plural=EXPRESSION" |
669 | + serbian3_plural = ("nplurals=3; plural=(n%10==1 && n%100!=11 " |
670 | + "? 0 : n%10>=2 && n%10<=4 && (n% 100<10 || n%100>=20) " |
671 | + "? 1 : 2)") |
672 | + serbian4_plural = ("nplurals=4; plural=(n==1 ? 3 : (n%10==1 && n%100!=11 " |
673 | + "? 0 : n%10>=2 && n%10<=4 && (n% 100<10 || n%100>=20) " |
674 | + "? 1 : 2))") |
675 | + plural_template = "nplurals=%d; plural=%s" |
676 | + |
677 | + def _makePOFileWithPlural(self, language_code): |
678 | + pofile = removeSecurityProxy(self.factory.makePOFile(language_code)) |
679 | + self.factory.makePOTMsgSet( |
680 | + pofile.potemplate, singular=u"Foo", plural=u"Bar", sequence=1) |
681 | + return pofile |
682 | + |
683 | + def test_header_pluralform_equal(self): |
684 | + # If the number of plural forms in the header is equal to that in the |
685 | + # language entry, use the data from the language entry. |
686 | + sr_pofile = self._makePOFileWithPlural('sr') |
687 | + sr_pofile.header = self.header % self.serbian3_plural |
688 | + |
689 | + translation_file_data = getAdapter( |
690 | + sr_pofile, ITranslationFileData, 'all_messages') |
691 | + self.assertEqual(3, translation_file_data.header.number_plural_forms) |
692 | + # The expression from the header starts with a "(", the language entry |
693 | + # does not. |
694 | + self.assertEqual( |
695 | + u"n%10==1 && n%100!=11", |
696 | + translation_file_data.header.plural_form_expression[:20]) |
697 | + |
698 | + def test_header_pluralform_larger(self): |
699 | + # If the number of plural forms in the header is larger than in the |
700 | + # language entry, use the data from the header. |
701 | + sr_pofile = self._makePOFileWithPlural('sr') |
702 | + sr_pofile.header = self.header % self.serbian4_plural |
703 | + |
704 | + translation_file_data = getAdapter( |
705 | + sr_pofile, ITranslationFileData, 'all_messages') |
706 | + self.assertEqual(4, translation_file_data.header.number_plural_forms) |
707 | + self.assertEqual( |
708 | + u"(n==1 ? 3 : (n%10==1", |
709 | + translation_file_data.header.plural_form_expression[:20]) |
710 | + |
711 | + def test_header_pluralform_larger_but_western(self): |
712 | + # If the plural form expression in the header is the standard western |
713 | + # expression, use the data from the language entry if present. |
714 | + # Use Japanese because it has only one plural form which is less |
715 | + # than the 2 the western style has. |
716 | + ja_pofile = self._makePOFileWithPlural('ja') |
717 | + # The expression comes in different forms. |
718 | + for expr in ('(n != 1)', '1 != n', 'n>1', '(1 < n)'): |
719 | + plural_info = self.plural_template % (2, expr) |
720 | + ja_pofile.header = self.header % plural_info |
721 | + |
722 | + translation_file_data = getAdapter( |
723 | + ja_pofile, ITranslationFileData, 'all_messages') |
724 | + nplurals_expected = 1 |
725 | + nplurals = translation_file_data.header.number_plural_forms |
726 | + self.assertEqual( |
727 | + nplurals_expected, nplurals, |
728 | + "%d != %d for '%s'" % (nplurals_expected, nplurals, expr)) |
729 | + # The plural form expression for Japanese (or any other language |
730 | + # with just one form) is simply '0'. |
731 | + self.assertEqual( |
732 | + u"0", translation_file_data.header.plural_form_expression) |
733 | + |
734 | + def test_header_pluralform_2_but_not_western(self): |
735 | + # If the plural form expression in the header reports two but is not |
736 | + # the standard western expression, use the data from the header. |
737 | + # Use Japanese because it has only one plural form which is less |
738 | + # than the 2 the western style has. |
739 | + ja_pofile = self._makePOFileWithPlural('ja') |
740 | + ja_pofile.header = self.header % self.other_2_plural |
741 | + |
742 | + translation_file_data = getAdapter( |
743 | + ja_pofile, ITranslationFileData, 'all_messages') |
744 | + self.assertEqual(2, translation_file_data.header.number_plural_forms) |
745 | + self.assertEqual( |
746 | + u"(n > 0)", translation_file_data.header.plural_form_expression) |
747 | + |
748 | + def test_header_pluralform_generic(self): |
749 | + # If the plural form expression in the header is a generic one (no |
750 | + # information), use the data from the language entry if present. |
751 | + ja_pofile = self._makePOFileWithPlural('ja') |
752 | + ja_pofile.header = self.header % self.generic_plural |
753 | + |
754 | + translation_file_data = getAdapter( |
755 | + ja_pofile, ITranslationFileData, 'all_messages') |
756 | + self.assertEqual(1, translation_file_data.header.number_plural_forms) |
757 | + self.assertEqual( |
758 | + u"0", translation_file_data.header.plural_form_expression) |
759 | + |
760 | + |
761 | def test_suite(): |
762 | - return unittest.TestLoader().loadTestsFromName(__name__) |
763 | + return TestLoader().loadTestsFromName(__name__) |
See previous review at https:/ /code.edge. launchpad. net/~henninge/ launchpad/ bug-565294- nplurals