Merge lp:~stevenk/launchpad/remove-suggested-translation-files into lp:launchpad
- remove-suggested-translation-files
- Merge into devel
Proposed by
Steve Kowalik
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Steve Kowalik | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 16421 | ||||
Proposed branch: | lp:~stevenk/launchpad/remove-suggested-translation-files | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
338 lines (+39/-145) 5 files modified
lib/lp/translations/browser/person.py (+3/-19) lib/lp/translations/browser/tests/test_persontranslationview.py (+15/-47) lib/lp/translations/interfaces/translationsperson.py (+1/-10) lib/lp/translations/model/translationsperson.py (+18/-67) lib/lp/translations/tests/test_potmsgset.py (+2/-2) |
||||
To merge this branch: | bzr merge lp:~stevenk/launchpad/remove-suggested-translation-files | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+143058@code.launchpad.net |
Commit message
Stop displaying random results in the list of suggestions on Person:
Description of the change
Destroy ITranslationsPe
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/translations/browser/person.py' | |||
2 | --- lib/lp/translations/browser/person.py 2012-10-30 15:54:00 +0000 | |||
3 | +++ lib/lp/translations/browser/person.py 2013-01-14 03:38:22 +0000 | |||
4 | @@ -1,4 +1,4 @@ | |||
6 | 1 | # Copyright 2009-2011 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
7 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
8 | 3 | 3 | ||
9 | 4 | """Person-related translations view classes.""" | 4 | """Person-related translations view classes.""" |
10 | @@ -333,17 +333,6 @@ | |||
11 | 333 | 333 | ||
12 | 334 | return TranslateLinksAggregator().aggregate(pofiles) | 334 | return TranslateLinksAggregator().aggregate(pofiles) |
13 | 335 | 335 | ||
14 | 336 | def _suggestTargetsForTranslation(self, max_fetch=None): | ||
15 | 337 | """Suggest translations this person could be helping complete.""" | ||
16 | 338 | person = ITranslationsPerson(self.context) | ||
17 | 339 | pofiles = person.suggestTranslatableFiles( | ||
18 | 340 | no_older_than=self.history_horizon) | ||
19 | 341 | |||
20 | 342 | if max_fetch is not None: | ||
21 | 343 | pofiles = pofiles[:max_fetch] | ||
22 | 344 | |||
23 | 345 | return TranslateLinksAggregator().aggregate(pofiles) | ||
24 | 346 | |||
25 | 347 | @cachedproperty | 336 | @cachedproperty |
26 | 348 | def all_projects_and_packages_to_review(self): | 337 | def all_projects_and_packages_to_review(self): |
27 | 349 | """Top projects and packages for this person to review.""" | 338 | """Top projects and packages for this person to review.""" |
28 | @@ -408,10 +397,10 @@ | |||
29 | 408 | """Suggest translations for this person to help complete.""" | 397 | """Suggest translations for this person to help complete.""" |
30 | 409 | # Maximum number of translations to list that need the most work | 398 | # Maximum number of translations to list that need the most work |
31 | 410 | # done. | 399 | # done. |
33 | 411 | max_urgent_targets = 3 | 400 | max_urgent_targets = 5 |
34 | 412 | # Maximum number of translations to list that are almost | 401 | # Maximum number of translations to list that are almost |
35 | 413 | # complete. | 402 | # complete. |
37 | 414 | max_almost_complete_targets = 3 | 403 | max_almost_complete_targets = 5 |
38 | 415 | # Length of overall list to display. | 404 | # Length of overall list to display. |
39 | 416 | list_length = 10 | 405 | list_length = 10 |
40 | 417 | 406 | ||
41 | @@ -426,11 +415,6 @@ | |||
42 | 426 | overall, almost_complete, max_almost_complete_targets, | 415 | overall, almost_complete, max_almost_complete_targets, |
43 | 427 | list_length) | 416 | list_length) |
44 | 428 | 417 | ||
45 | 429 | fetch = 5 * (list_length - len(overall)) | ||
46 | 430 | suggestions = self._suggestTargetsForTranslation(fetch) | ||
47 | 431 | overall = self._addToTargetsList( | ||
48 | 432 | overall, suggestions, list_length, list_length) | ||
49 | 433 | |||
50 | 434 | return overall | 418 | return overall |
51 | 435 | 419 | ||
52 | 436 | to_complete_template = ViewPageTemplateFile( | 420 | to_complete_template = ViewPageTemplateFile( |
53 | 437 | 421 | ||
54 | === modified file 'lib/lp/translations/browser/tests/test_persontranslationview.py' | |||
55 | --- lib/lp/translations/browser/tests/test_persontranslationview.py 2012-10-30 15:54:00 +0000 | |||
56 | +++ lib/lp/translations/browser/tests/test_persontranslationview.py 2013-01-14 03:38:22 +0000 | |||
57 | @@ -1,4 +1,4 @@ | |||
59 | 1 | # Copyright 2009 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
60 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
61 | 3 | 3 | ||
62 | 4 | __metaclass__ = type | 4 | __metaclass__ = type |
63 | @@ -308,38 +308,9 @@ | |||
64 | 308 | nonurgent_pofile.potemplate.productseries.product, | 308 | nonurgent_pofile.potemplate.productseries.product, |
65 | 309 | descriptions[0]['target']) | 309 | descriptions[0]['target']) |
66 | 310 | 310 | ||
67 | 311 | def test_suggestTargetsForTranslation(self): | ||
68 | 312 | # suggestTargetsForTranslation finds targets that the person | ||
69 | 313 | # could help translate. | ||
70 | 314 | previous_contrib = self._makePOFiles(1, previously_worked_on=True) | ||
71 | 315 | pofile = self._makePOFiles(1, previously_worked_on=False)[0] | ||
72 | 316 | self._addUntranslatedMessages(pofile, 1) | ||
73 | 317 | |||
74 | 318 | descriptions = self.view._suggestTargetsForTranslation() | ||
75 | 319 | |||
76 | 320 | self.assertEqual(1, len(descriptions)) | ||
77 | 321 | self.assertEqual( | ||
78 | 322 | pofile.potemplate.productseries.product, | ||
79 | 323 | descriptions[0]['target']) | ||
80 | 324 | |||
81 | 325 | def test_suggestTargetsForTranslation_limits_query(self): | ||
82 | 326 | # The max_fetch argument limits how many POFiles | ||
83 | 327 | # suggestTargetsForTranslation fetches. | ||
84 | 328 | previous_contrib = self._makePOFiles(1, previously_worked_on=True) | ||
85 | 329 | pofiles = self._makePOFiles(3, previously_worked_on=False) | ||
86 | 330 | for pofile in pofiles: | ||
87 | 331 | self._addUntranslatedMessages(pofile, 1) | ||
88 | 332 | |||
89 | 333 | descriptions = self.view._suggestTargetsForTranslation(max_fetch=2) | ||
90 | 334 | |||
91 | 335 | self.assertEqual(2, len(descriptions)) | ||
92 | 336 | self.assertNotEqual( | ||
93 | 337 | descriptions[0]['target'], descriptions[1]['target']) | ||
94 | 338 | |||
95 | 339 | def test_top_projects_and_packages_to_translate(self): | 311 | def test_top_projects_and_packages_to_translate(self): |
96 | 340 | # top_projects_and_packages_to_translate lists targets that the | 312 | # top_projects_and_packages_to_translate lists targets that the |
99 | 341 | # user has worked on and could help translate, followed by | 313 | # user has worked on and could help translate. |
98 | 342 | # randomly suggested ones that also need translation. | ||
100 | 343 | worked_on = self._makePOFiles(1, previously_worked_on=True)[0] | 314 | worked_on = self._makePOFiles(1, previously_worked_on=True)[0] |
101 | 344 | self._addUntranslatedMessages(worked_on, 1) | 315 | self._addUntranslatedMessages(worked_on, 1) |
102 | 345 | not_worked_on = self._makePOFiles(1, previously_worked_on=False)[0] | 316 | not_worked_on = self._makePOFiles(1, previously_worked_on=False)[0] |
103 | @@ -347,16 +318,13 @@ | |||
104 | 347 | 318 | ||
105 | 348 | descriptions = self.view.top_projects_and_packages_to_translate | 319 | descriptions = self.view.top_projects_and_packages_to_translate |
106 | 349 | 320 | ||
108 | 350 | self.assertEqual(2, len(descriptions)) | 321 | self.assertEqual(1, len(descriptions)) |
109 | 351 | self.assertEqual( | 322 | self.assertEqual( |
110 | 352 | worked_on.potemplate.productseries.product, | 323 | worked_on.potemplate.productseries.product, |
111 | 353 | descriptions[0]['target']) | 324 | descriptions[0]['target']) |
112 | 354 | self.assertEqual( | ||
113 | 355 | not_worked_on.potemplate.productseries.product, | ||
114 | 356 | descriptions[1]['target']) | ||
115 | 357 | 325 | ||
116 | 358 | def test_top_p_n_p_to_translate_caps_existing_involvement(self): | 326 | def test_top_p_n_p_to_translate_caps_existing_involvement(self): |
118 | 359 | # top_projects_and_packages_to_translate shows no more than 6 | 327 | # top_projects_and_packages_to_translate shows up to ten |
119 | 360 | # targets that the user has already worked on. | 328 | # targets that the user has already worked on. |
120 | 361 | pofiles = self._makePOFiles(7, previously_worked_on=True) | 329 | pofiles = self._makePOFiles(7, previously_worked_on=True) |
121 | 362 | for pofile in pofiles: | 330 | for pofile in pofiles: |
122 | @@ -364,12 +332,12 @@ | |||
123 | 364 | 332 | ||
124 | 365 | descriptions = self.view.top_projects_and_packages_to_translate | 333 | descriptions = self.view.top_projects_and_packages_to_translate |
125 | 366 | 334 | ||
127 | 367 | self.assertEqual(6, len(descriptions)) | 335 | self.assertEqual(7, len(descriptions)) |
128 | 368 | 336 | ||
129 | 369 | def test_top_p_n_p_to_translate_lists_most_and_least_translated(self): | 337 | def test_top_p_n_p_to_translate_lists_most_and_least_translated(self): |
133 | 370 | # Of the maximum of 6 translations that the user has already | 338 | # Of the maximum of ten translations that the user has already |
134 | 371 | # worked on, the first 3 will be the ones with the most | 339 | # worked on, the first 5 will be the ones with the most |
135 | 372 | # untranslated strings; the last 3 will have the fewest. | 340 | # untranslated strings; the last 5 will have the fewest. |
136 | 373 | # We create a lot more POFiles because internally the property | 341 | # We create a lot more POFiles because internally the property |
137 | 374 | # will fetch many POFiles. | 342 | # will fetch many POFiles. |
138 | 375 | pofiles = self._makePOFiles(50, previously_worked_on=True) | 343 | pofiles = self._makePOFiles(50, previously_worked_on=True) |
139 | @@ -380,15 +348,15 @@ | |||
140 | 380 | 348 | ||
141 | 381 | descriptions = self.view.top_projects_and_packages_to_translate | 349 | descriptions = self.view.top_projects_and_packages_to_translate |
142 | 382 | 350 | ||
144 | 383 | self.assertEqual(6, len(descriptions)) | 351 | self.assertEqual(10, len(descriptions)) |
145 | 384 | targets = [item['target'] for item in descriptions] | 352 | targets = [item['target'] for item in descriptions] |
146 | 385 | 353 | ||
153 | 386 | # We happen to know that no more than 15 POFiles are fetched for | 354 | # We happen to know that no more than 25 POFiles are fetched for |
154 | 387 | # each of the two categories, so the top 3 targets must be taken | 355 | # each of the two categories, so the top 5 targets must be taken |
155 | 388 | # from the last 15 pofiles and the next 3 must be taken from the | 356 | # from the last 25 pofiles and the next 5 must be taken from the |
156 | 389 | # first 15 pofiles. | 357 | # first 25 pofiles. |
157 | 390 | self.assertTrue(set(targets[:3]).issubset(products[15:])) | 358 | self.assertTrue(set(targets[:5]).issubset(products[25:])) |
158 | 391 | self.assertTrue(set(targets[3:]).issubset(products[:15])) | 359 | self.assertTrue(set(targets[5:]).issubset(products[:25])) |
159 | 392 | 360 | ||
160 | 393 | # No target is mentioned more than once in the listing. | 361 | # No target is mentioned more than once in the listing. |
161 | 394 | self.assertEqual(len(targets), len(set(targets))) | 362 | self.assertEqual(len(targets), len(set(targets))) |
162 | 395 | 363 | ||
163 | === modified file 'lib/lp/translations/interfaces/translationsperson.py' | |||
164 | --- lib/lp/translations/interfaces/translationsperson.py 2012-10-29 06:13:44 +0000 | |||
165 | +++ lib/lp/translations/interfaces/translationsperson.py 2013-01-14 03:38:22 +0000 | |||
166 | @@ -1,4 +1,4 @@ | |||
168 | 1 | # Copyright 2009 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
169 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
170 | 3 | 3 | ||
171 | 4 | __metaclass__ = type | 4 | __metaclass__ = type |
172 | @@ -72,12 +72,3 @@ | |||
173 | 72 | :return: A query result of `POFile`s ordered by number of | 72 | :return: A query result of `POFile`s ordered by number of |
174 | 73 | untranslated messages. | 73 | untranslated messages. |
175 | 74 | """ | 74 | """ |
176 | 75 | |||
177 | 76 | def suggestTranslatableFiles(no_older_than=None): | ||
178 | 77 | """Suggest `POFile`s this person could help translate. | ||
179 | 78 | |||
180 | 79 | Similar to `getTranslatableFiles`, this method picks an | ||
181 | 80 | arbitrary series of `POFile`s that the user is not a reviewer | ||
182 | 81 | for and has not worked on recently, but which are in a language | ||
183 | 82 | the user works in. | ||
184 | 83 | """ | ||
185 | 84 | 75 | ||
186 | === modified file 'lib/lp/translations/model/translationsperson.py' | |||
187 | --- lib/lp/translations/model/translationsperson.py 2012-10-30 15:54:00 +0000 | |||
188 | +++ lib/lp/translations/model/translationsperson.py 2013-01-14 03:38:22 +0000 | |||
189 | @@ -1,4 +1,4 @@ | |||
191 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
192 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
193 | 3 | 3 | ||
194 | 4 | __metaclass__ = type | 4 | __metaclass__ = type |
195 | @@ -161,15 +161,9 @@ | |||
196 | 161 | '(SELECT * FROM translatable_distroseries)'))).config( | 161 | '(SELECT * FROM translatable_distroseries)'))).config( |
197 | 162 | distinct=True).order_by(POFile.date_changed) | 162 | distinct=True).order_by(POFile.date_changed) |
198 | 163 | 163 | ||
201 | 164 | def _queryTranslatableFiles(self, worked_on, no_older_than=None, | 164 | def _queryTranslatableFiles(self, no_older_than=None, languages=None): |
200 | 165 | languages=None): | ||
202 | 166 | """Get `POFile`s this person could help translate. | 165 | """Get `POFile`s this person could help translate. |
203 | 167 | 166 | ||
204 | 168 | :param worked_on: If True, get `POFile`s that the person has | ||
205 | 169 | been working on recently (where "recently" is defined as | ||
206 | 170 | `no_older_than`). If False, get ones that the person has | ||
207 | 171 | not been working on recently (those that the person has | ||
208 | 172 | never worked on, or last worked on before `no_older_than`). | ||
209 | 173 | :param no_older_than: Oldest involvement to consider. If the | 167 | :param no_older_than: Oldest involvement to consider. If the |
210 | 174 | person last worked on a `POFile` before this date, that | 168 | person last worked on a `POFile` before this date, that |
211 | 175 | counts as not having worked on it. | 169 | counts as not having worked on it. |
212 | @@ -179,18 +173,25 @@ | |||
213 | 179 | if self.person.is_team: | 173 | if self.person.is_team: |
214 | 180 | return [] | 174 | return [] |
215 | 181 | 175 | ||
221 | 182 | tables = self._composePOFileReviewerJoins( | 176 | tables = self._composePOFileReviewerJoins(expect_reviewer_status=False) |
222 | 183 | expect_reviewer_status=False) | 177 | |
223 | 184 | 178 | join_condition = And( | |
224 | 185 | translator_join, translator_condition = ( | 179 | POFileTranslator.personID == self.person.id, |
225 | 186 | self._composePOFileTranslatorJoin(worked_on, no_older_than)) | 180 | POFileTranslator.pofileID == POFile.id, |
226 | 181 | POFile.language != getUtility(ILaunchpadCelebrities).english) | ||
227 | 182 | |||
228 | 183 | if no_older_than is not None: | ||
229 | 184 | join_condition = And( | ||
230 | 185 | join_condition, | ||
231 | 186 | POFileTranslator.date_last_touched >= no_older_than) | ||
232 | 187 | |||
233 | 188 | translator_join = Join(POFileTranslator, join_condition) | ||
234 | 187 | tables.append(translator_join) | 189 | tables.append(translator_join) |
235 | 188 | 190 | ||
236 | 189 | translated_count = ( | 191 | translated_count = ( |
237 | 190 | POFile.currentcount + POFile.updatescount + POFile.rosettacount) | 192 | POFile.currentcount + POFile.updatescount + POFile.rosettacount) |
238 | 191 | 193 | ||
241 | 192 | conditions = And( | 194 | conditions = translated_count < POTemplate.messagecount |
240 | 193 | translated_count < POTemplate.messagecount, translator_condition) | ||
242 | 194 | 195 | ||
243 | 195 | # The person must not be a reviewer for this translation (unless | 196 | # The person must not be a reviewer for this translation (unless |
244 | 196 | # it's in the sense that any user gets review permissions | 197 | # it's in the sense that any user gets review permissions |
245 | @@ -219,12 +220,11 @@ | |||
246 | 219 | if languages is not None: | 220 | if languages is not None: |
247 | 220 | conditions = And(conditions, POFile.languageID.is_in(languages)) | 221 | conditions = And(conditions, POFile.languageID.is_in(languages)) |
248 | 221 | 222 | ||
251 | 222 | source = Store.of(self.person).using(*tables) | 223 | return Store.of(self.person).using(*tables).find(POFile, conditions) |
250 | 223 | return source.find(POFile, conditions) | ||
252 | 224 | 224 | ||
253 | 225 | def getTranslatableFiles(self, no_older_than=None, urgent_first=True): | 225 | def getTranslatableFiles(self, no_older_than=None, urgent_first=True): |
254 | 226 | """See `ITranslationsPerson`.""" | 226 | """See `ITranslationsPerson`.""" |
256 | 227 | results = self._queryTranslatableFiles(True, no_older_than) | 227 | results = self._queryTranslatableFiles(no_older_than) |
257 | 228 | 228 | ||
258 | 229 | translated_count = ( | 229 | translated_count = ( |
259 | 230 | POFile.currentcount + POFile.updatescount + POFile.rosettacount) | 230 | POFile.currentcount + POFile.updatescount + POFile.rosettacount) |
260 | @@ -234,16 +234,6 @@ | |||
261 | 234 | 234 | ||
262 | 235 | return results.order_by(ordering) | 235 | return results.order_by(ordering) |
263 | 236 | 236 | ||
264 | 237 | def suggestTranslatableFiles(self, no_older_than=None): | ||
265 | 238 | """See `ITranslationsPerson`.""" | ||
266 | 239 | # XXX JeroenVermeulen 2009-08-28: Ideally this would also check | ||
267 | 240 | # for a free licence. That's hard to do in SQL though. | ||
268 | 241 | languages = set([ | ||
269 | 242 | language.id for language in self.translatable_languages]) | ||
270 | 243 | results = self._queryTranslatableFiles( | ||
271 | 244 | False, no_older_than, languages=languages) | ||
272 | 245 | return results.order_by(['random()']) | ||
273 | 246 | |||
274 | 247 | def _composePOFileReviewerCTEs(self, no_older_than): | 237 | def _composePOFileReviewerCTEs(self, no_older_than): |
275 | 248 | """Compose Storm CTEs for common `POFile` queries. | 238 | """Compose Storm CTEs for common `POFile` queries. |
276 | 249 | 239 | ||
277 | @@ -405,42 +395,3 @@ | |||
278 | 405 | TranslatorJoin, | 395 | TranslatorJoin, |
279 | 406 | TranslationTeamJoin, | 396 | TranslationTeamJoin, |
280 | 407 | ] | 397 | ] |
281 | 408 | |||
282 | 409 | def _composePOFileTranslatorJoin(self, expected_presence, | ||
283 | 410 | no_older_than=None): | ||
284 | 411 | """Compose join condition for `POFileTranslator`. | ||
285 | 412 | |||
286 | 413 | Checks for a `POFileTranslator` record matching a `POFile` and | ||
287 | 414 | `Person` in a join. | ||
288 | 415 | |||
289 | 416 | :param expected_presence: whether the `POFileTranslator` record | ||
290 | 417 | is to be present, or absent. The join will enforce presence | ||
291 | 418 | through a regular inner join, or absence by an outer join | ||
292 | 419 | with a condition that the record not be present. | ||
293 | 420 | :param no_older_than: optional cutoff date. `POFileTranslator` | ||
294 | 421 | records older than this date are not considered. | ||
295 | 422 | :return: a tuple of the join, and a condition to be checked by | ||
296 | 423 | the query. Combine it with the query's other conditions | ||
297 | 424 | using `And`. | ||
298 | 425 | """ | ||
299 | 426 | join_condition = And( | ||
300 | 427 | POFileTranslator.personID == self.person.id, | ||
301 | 428 | POFileTranslator.pofileID == POFile.id, | ||
302 | 429 | POFile.language != getUtility(ILaunchpadCelebrities).english) | ||
303 | 430 | |||
304 | 431 | if no_older_than is not None: | ||
305 | 432 | join_condition = And( | ||
306 | 433 | join_condition, | ||
307 | 434 | POFileTranslator.date_last_touched >= no_older_than) | ||
308 | 435 | |||
309 | 436 | if expected_presence: | ||
310 | 437 | # A regular inner join enforces this. No need for an extra | ||
311 | 438 | # condition; the join does it more efficiently. | ||
312 | 439 | return Join(POFileTranslator, join_condition), True | ||
313 | 440 | else: | ||
314 | 441 | # Check for absence. Usually the best way to check for this | ||
315 | 442 | # is an outer join plus a condition that the outer join | ||
316 | 443 | # match no record. | ||
317 | 444 | return ( | ||
318 | 445 | LeftJoin(POFileTranslator, join_condition), | ||
319 | 446 | POFileTranslator.id == None) | ||
320 | 447 | 398 | ||
321 | === modified file 'lib/lp/translations/tests/test_potmsgset.py' | |||
322 | --- lib/lp/translations/tests/test_potmsgset.py 2013-01-07 02:40:55 +0000 | |||
323 | +++ lib/lp/translations/tests/test_potmsgset.py 2013-01-14 03:38:22 +0000 | |||
324 | @@ -1,4 +1,4 @@ | |||
326 | 1 | # Copyright 2009-2010 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
327 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
328 | 3 | 3 | ||
329 | 4 | __metaclass__ = type | 4 | __metaclass__ = type |
330 | @@ -408,7 +408,7 @@ | |||
331 | 408 | self.assertContentEqual( | 408 | self.assertContentEqual( |
332 | 409 | self.potmsgset.getExternallyUsedTranslationMessages(language), | 409 | self.potmsgset.getExternallyUsedTranslationMessages(language), |
333 | 410 | [other_translation, current_translation]) | 410 | [other_translation, current_translation]) |
335 | 411 | self.assertEquals( | 411 | self.assertContentEqual( |
336 | 412 | self.potmsgset.getExternallySuggestedOrUsedTranslationMessages( | 412 | self.potmsgset.getExternallySuggestedOrUsedTranslationMessages( |
337 | 413 | used_languages=[language])[language].used, | 413 | used_languages=[language])[language].used, |
338 | 414 | [other_translation, current_translation]) | 414 | [other_translation, current_translation]) |