Merge lp://qastaging/~henninge/launchpad/devel-bug-597539-translationmessage-pofile into lp://qastaging/launchpad

Proposed by Henning Eggers
Status: Merged
Approved by: Henning Eggers
Approved revision: no longer in the source branch.
Merged at revision: 11504
Proposed branch: lp://qastaging/~henninge/launchpad/devel-bug-597539-translationmessage-pofile
Merge into: lp://qastaging/launchpad
Diff against target: 1384 lines (+279/-572)
18 files modified
lib/lp/translations/browser/tests/translationmessage-views.txt (+6/-34)
lib/lp/translations/browser/translationmessage.py (+69/-42)
lib/lp/translations/doc/gettext-check-messages.txt (+9/-44)
lib/lp/translations/doc/pofile.txt (+1/-1)
lib/lp/translations/doc/potmsgset.txt (+5/-3)
lib/lp/translations/doc/remove-upstream-translations-script.txt (+0/-142)
lib/lp/translations/interfaces/pofile.py (+7/-0)
lib/lp/translations/interfaces/translationmessage.py (+6/-0)
lib/lp/translations/model/pofile.py (+37/-15)
lib/lp/translations/model/potmsgset.py (+0/-1)
lib/lp/translations/model/translationmessage.py (+11/-1)
lib/lp/translations/scripts/gettext_check_messages.py (+4/-29)
lib/lp/translations/templates/currenttranslationmessage-translate-one.pt (+12/-12)
lib/lp/translations/templates/translationmessage-translate.pt (+1/-1)
lib/lp/translations/tests/pofiletranslator.txt (+1/-12)
lib/lp/translations/tests/test_doc.py (+2/-6)
lib/lp/translations/tests/test_pofile.py (+108/-2)
scripts/rosetta/remove-upstream-translations.py (+0/-227)
To merge this branch: bzr merge lp://qastaging/~henninge/launchpad/devel-bug-597539-translationmessage-pofile
Reviewer Review Type Date Requested Status
Jeroen T. Vermeulen (community) code Approve
Review via email: mp+34441@code.qastaging.launchpad.net

Commit message

Removed remaining uses of TranslationMessage.pofile.

Description of the change

= Bug 597539 =

With the advent of message sharing, the "pofile" attribute of a TranslationMessage became obsolete. TranslationMessage now has a "language" attribute which can be used to find the right POFile if you also know the POTemplate. Since a TranslationMessage can now be shared by multiple POFiles, a direct link makes no sense now.

A lot of code was still using this link, though, since the column in the database still exists and holds values. Since TranslationMessage was still setting pofile upon creation, it most likely pointed to the first POFile that this message was translated in and that mostly worked.

This branch cleans this mess up by hunting down all these uses of the pofile attribute and tries to find an equivalent replacement. Please excuse the diff size, it contains file deletions an repetitive changes in templates and such.

== Proposed fix ==

For each occurrence, one of these fixes was used:

- Use the new "language" attribute if the "pofile" was only used to get to the language. Luckily there were a lot of those cases.
- In view code it was mostly possible to use "browser_pofile" which caches the POFile that the message was currently being viewed in. Some extra code had to be added to make sure it is always set.
- Sometimes the POFile was actually known and there was no reason to use TranslationMessage.pofile.
- Sometimes getOnePOFile will do which just gets any POFile associated with the translation message.
- A new query to find all TranslationMessages for a POFile was introduced.
- Some scripts did not receive nice treatment, one was crippled, the other one plain deleted. ;)

== Implementation details ==

Notes for some specific files.

=== modified file 'lib/lp/translations/browser/tests/translationmessage-views.txt'
Using POFile statistics to show that a form submission succeeded is overkilll, so I removed them.

=== modified file 'lib/lp/translations/browser/translationmessage.py'
I introduced a new parameter 'local_to_pofile' which is passed in from the top to mark local translations explicitly instead of deriving that from the "pofile" attribute. The last chunk is the core of this change.

=== modified file 'lib/lp/translations/doc/gettext-check-messages.txt'
=== modified file 'lib/lp/translations/scripts/gettext_check_messages.py'
This script operates purely on the TranslationMessage table with no relation to a POFile. Finding an imported message is not possible without that information so it had be ridded of that functionality. Obviously this also affected the test. The change has just been commented out because that script will be revisited later anyway in our current feature work and maybe we come up with a better solution.

=== modified file 'lib/lp/translations/tests/test_doc.py'
=== removed file 'lib/lp/translations/doc/remove-upstream-translations-script.txt'
=== removed file 'scripts/rosetta/remove-upstream-translations.py'
This script is not needed anymore so why bother fixing it? Yeah for code deletion!

=== modified file 'lib/lp/translations/interfaces/pofile.py'
=== modified file 'lib/lp/translations/model/pofile.py'
=== modified file 'lib/lp/translations/tests/test_pofile.py'
As POFile.translation_messages cannot be a simple join anymore, I introduced getTranslationMessages to retrieve the messages. This could also be used (with an extra condition) to replace another direct SQL query on the pofile column. Complete with test.

=== modified file 'lib/lp/translations/interfaces/translationmessage.py'
=== modified file 'lib/lp/translations/model/translationmessage.py'
The method ensureBrowserPOFile is simple but had to be in the model class because otherwise assigment to browser_pofile would not be possible.

=== modified file 'lib/lp/translations/model/potmsgset.py'
This is at the heart of this branch because it stops TranslationMessage.pofile from being assigned a value during its creation.

== Test ==

Just run all translation tests, it takes about half an hour.

bin/test -vvcm lp.translations

== QA ==

When this branch is on staging, the pofile column needs to b NULL'ed.

ALTER TABLE translationmessage DISABLE TRIGGER ALL;
UPDATE translationmessage SET pofile=NULL;
ALTER TABLE translationmessage ENABLE TRIGGER ALL;

Then various +translate pages need to be opened and also some imports would be great and similar. Check that
- nothing oopses
- the pofile column remains NULL'ed.

To post a comment you must log in.
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :
Download full text (3.9 KiB)

Hi Henning,

Thanks for finally ridding us of this blemish. Excellent cover letter! There are a few things that need fixing.

Points discussed on IRC:

Good job on cutting down redundant testing in translationmessage-views.txt. Don't introduce actions in doctests with "Let's" though.

I really don't like the idea of keeping dead and broken code in gettext_check_messages.py. When we overhaul the script, it will help if all the code that's in there is valid. If we want to look up how it used to work, we have bzr.

The docstring for ensureBrowserPOFile is a bit ambivalent: it "ensures" and "makes sure" that the browser_pofile is set… "if possible." Which is it? The only scenario I can imagine it coming up empty is where all templates that contained a potmsgset have been deleted. (If a template merely stops using a potmsgset, there will still be a TTI linking the two). That could happen with manual database maintenance. Some 36% of our POTMsgSets (1.3 million) and 17% of our TMs (11.5 million) are orphans. You're adding a check to ensure that these don't show up as external suggestions; we should also clean them out of the database.

For convenience, ensureBrowserPOFile can also return self.browser_pofile.

In getTranslationMessages, the Coalesce is a bit hard to indent nicely. How about e.g. creating a variable "applicable_template = Coalesce(TranslationMessage.potemplateID, self.potemplate.id)" and then having the query say "applicable_template == self.potemplate.id"?

In updateTranslation you pass pofile=None to the TranslationMessage constructor. It's a bit moot with the Recife changes coming up, but better remove that argument altogether.

Points not yet discussed on IRC:

In pofiletranslator.txt, I'd say that the oldest TM "belongs to" pofile #1, rather than "references" it. The reference is obsolete!

Nice job fixing up all those empty result sets we generated.

In test_pofile.py, you use factory.makeTranslationMessage a lot. We now also have more specific factory methods that are 100% on the new model and don't use updateTranslation: makeSuggestion, makeCurrentTranslationMessage, makeDivergedTranslationMessage. Please use those where possible.

Actually test_getTranslationMessages_baseline rolls a bunch of tests into one. That tends to weigh down diagnosis and maintenance—it's similar to the statistics check you removed from that doctest above. Could you break it down into separate "I'm creating a {suggestion,shared,diverged,obsolete} message, and it shows up in getTranslationMessages" tests?

In test_getTranslationMessages_condition, you're testing two factors at the same time: the addition of a query condition, and the effect of this particular condition on different types of messages. All you really want to test here is that the query condition works properly, which is 3 tests with one message each: message matching the condition is found, message not matching the condition is not found, and message matching the condition but for another pofile is still not found (i.e. the query condition narrows the search criteria rather than replacing them). If that's a lot of setUp work, consider giving getTranslationMessages a...

Read more...

review: Approve (code)
Revision history for this message
Henning Eggers (henninge) wrote :

> Hi Henning,
>
> Thanks for finally ridding us of this blemish. Excellent cover letter! There
> are a few things that need fixing.

Yes, and it was fun, too. In parts at least. ;-)

>
> Points discussed on IRC:
>
> Good job on cutting down redundant testing in translationmessage-views.txt.
> Don't introduce actions in doctests with "Let's" though.

Oh, it felt like I was in Rome, you know...
Fixed. ;-)

>
> I really don't like the idea of keeping dead and broken code in
> gettext_check_messages.py. When we overhaul the script, it will help if all
> the code that's in there is valid. If we want to look up how it used to work,
> we have bzr.

Old code is gone.

>
> The docstring for ensureBrowserPOFile is a bit ambivalent: it "ensures" and
> "makes sure" that the browser_pofile is set… "if possible."

Yes, I kinda new that was bad. Improved.

> You're adding a check to ensure that
> these don't show up as external suggestions;

Yes, added. It had to go into four places, where ever ensureBrowserPofile is
used. Since one was in a loop, I added an extra function for it.

>
> For convenience, ensureBrowserPOFile can also return self.browser_pofile.

It does now.

>
> In getTranslationMessages, the Coalesce is a bit hard to indent nicely. How
> about e.g. creating a variable "applicable_template =
> Coalesce(TranslationMessage.potemplateID, self.potemplate.id)" and then having
> the query say "applicable_template == self.potemplate.id"?

Yes, that looks better. Thanks.

>
> In updateTranslation you pass pofile=None to the TranslationMessage
> constructor. It's a bit moot with the Recife changes coming up, but better
> remove that argument altogether.

Removed.

>
>
> Points not yet discussed on IRC:
>
> In pofiletranslator.txt, I'd say that the oldest TM "belongs to" pofile #1,
> rather than "references" it. The reference is obsolete!

Good point. ;)

>
> Nice job fixing up all those empty result sets we generated.

Yeah, they made my eyes hurt.

>
> In test_pofile.py, you use factory.makeTranslationMessage a lot. We now also
> have more specific factory methods that are 100% on the new model and don't
> use updateTranslation: makeSuggestion, makeCurrentTranslationMessage,
> makeDivergedTranslationMessage. Please use those where possible.

Jeroen ...
We don't have those ...
This is *not* the recife branch. ;-P

>
> Actually test_getTranslationMessages_baseline rolls a bunch of tests into one.

Thank you very much for those suggestions for splitting up the tests. I applied them all and like it much better. Great!

Thanks for your review!

Henning

Revision history for this message
Henning Eggers (henninge) wrote :

Incremental diff.

1=== modified file 'lib/lp/translations/browser/tests/translationmessage-views.txt'
2--- lib/lp/translations/browser/tests/translationmessage-views.txt 2010-09-01 10:03:11 +0000
3+++ lib/lp/translations/browser/tests/translationmessage-views.txt 2010-09-03 15:33:28 +0000
4@@ -228,7 +228,7 @@
5
6 == Submitting translations ==
7
8-Let's submit a new translation through the view.
9+A new translation is submitted through the view.
10
11 >>> server_url = '/'.join(
12 ... [canonical_url(translationmessage), '+translate'])
13
14=== modified file 'lib/lp/translations/browser/translationmessage.py'
15--- lib/lp/translations/browser/translationmessage.py 2010-09-01 10:03:57 +0000
16+++ lib/lp/translations/browser/translationmessage.py 2010-09-03 15:15:19 +0000
17@@ -1033,34 +1033,41 @@
18 # Imported one matches the current one.
19 imported_submission = None
20 elif self.imported_translationmessage is not None:
21- self.imported_translationmessage.ensureBrowserPOFile()
22- pofile = self.imported_translationmessage.browser_pofile
23- imported_submission = (
24- convert_translationmessage_to_submission(
25- message=self.imported_translationmessage,
26- current_message=self.context,
27- plural_form=index,
28- pofile=pofile,
29- legal_warning_needed=False,
30- is_empty=False,
31- packaged=True,
32- local_to_pofile=True))
33+ pofile = (
34+ self.imported_translationmessage.ensureBrowserPOFile())
35+ if pofile is None:
36+ imported_submission = None
37+ else:
38+ imported_submission = (
39+ convert_translationmessage_to_submission(
40+ message=self.imported_translationmessage,
41+ current_message=self.context,
42+ plural_form=index,
43+ pofile=pofile,
44+ legal_warning_needed=False,
45+ is_empty=False,
46+ packaged=True,
47+ local_to_pofile=True))
48 else:
49 imported_submission = None
50
51- if (self.context.potemplate is not None and
52- self.shared_translationmessage is not None):
53- self.shared_translationmessage.ensureBrowserPOFile()
54- pofile = self.shared_translationmessage.browser_pofile
55- shared_submission = (
56- convert_translationmessage_to_submission(
57- message=self.shared_translationmessage,
58- current_message=self.context,
59- plural_form=index,
60- pofile=pofile,
61- legal_warning_needed=False,
62- is_empty=False,
63- local_to_pofile=True))
64+ diverged_and_have_shared = (
65+ self.context.potemplate is not None and
66+ self.shared_translationmessage is not None)
67+ if diverged_and_have_shared:
68+ pofile = self.shared_translationmessage.ensureBrowserPOFile()
69+ if pofile is None:
70+ shared_submission = None
71+ else:
72+ shared_submission = (
73+ convert_translationmessage_to_submission(
74+ message=self.shared_translationmessage,
75+ current_message=self.context,
76+ plural_form=index,
77+ pofile=pofile,
78+ legal_warning_needed=False,
79+ is_empty=False,
80+ local_to_pofile=True))
81 else:
82 shared_submission = None
83
84@@ -1143,6 +1150,24 @@
85 else:
86 self.can_confirm_and_dismiss = True
87
88+ def _setOnePOFile(self, messages):
89+ """Return a list of messages that all have a browser_pofile set.
90+
91+ If a pofile cannot be found for a message, it is not included in
92+ the resulting list.
93+ """
94+ result = []
95+ for message in messages:
96+ if message.browser_pofile is None:
97+ pofile = message.getOnePOFile()
98+ if pofile is None:
99+ # Do not include in result.
100+ continue
101+ else:
102+ message.setPOFile(pofile)
103+ result.append(message)
104+ return result
105+
106 def _buildAllSuggestions(self):
107 """Builds all suggestions and puts them into suggestions_block.
108
109@@ -1199,26 +1224,18 @@
110
111 # Get a list of translations which are _used_ as translations
112 # for this same message in a different translation template.
113- externally_used = sorted(
114+ externally_used = self._setOnePOFile(sorted(
115 potmsgset.getExternallyUsedTranslationMessages(language),
116 key=operator.attrgetter("date_created"),
117- reverse=True)
118- for suggestion in externally_used:
119- pofile = suggestion.getOnePOFile()
120- if suggestion.browser_pofile is None:
121- suggestion.setPOFile(pofile)
122+ reverse=True))
123
124 # Get a list of translations which are suggested as
125 # translations for this same message in a different translation
126 # template, but are not used.
127- externally_suggested = sorted(
128+ externally_suggested = self._setOnePOFile(sorted(
129 potmsgset.getExternallySuggestedTranslationMessages(language),
130 key=operator.attrgetter("date_created"),
131- reverse=True)
132- for suggestion in externally_suggested:
133- pofile = suggestion.getOnePOFile()
134- if suggestion.browser_pofile is None:
135- suggestion.setPOFile(pofile)
136+ reverse=True))
137 else:
138 # Don't show suggestions for anonymous users.
139 local = externally_used = externally_suggested = []
140
141=== modified file 'lib/lp/translations/doc/gettext-check-messages.txt'
142--- lib/lp/translations/doc/gettext-check-messages.txt 2010-09-01 17:10:35 +0000
143+++ lib/lp/translations/doc/gettext-check-messages.txt 2010-09-03 15:43:39 +0000
144@@ -100,7 +100,6 @@
145 INFO Messages checked: 1
146 INFO Validation errors: 0
147 INFO Messages disabled: 0
148- INFO Messages unmasked: 0
149 INFO Commit points: ...
150
151
152@@ -126,7 +125,6 @@
153 INFO Messages checked: 1
154 INFO Validation errors: 1
155 INFO Messages disabled: 1
156- INFO Messages unmasked: 0
157 INFO Commit points: ...
158
159 The failed message is demoted to a mere suggestion.
160@@ -134,45 +132,14 @@
161 >>> current_message.is_current
162 False
163
164-Unmasking of imported messages is disabled in the script. That's why
165-although there was a perfectly good imported message that was being
166-masked by the invalid current translation, it will not be activated.
167-
168- >>> imported_message.is_current
169- False
170-
171-If the imported message is also bad, this is reported and the imported
172-message is not activated. But unmasking is disabled anyway.
173-
174- >>> imported_message.is_current = False
175- >>> current_message.is_current = True
176- >>> imported_message.translations = [u'%s %s i']
177-
178- >>> run_checker(["-w id=%s" % quote(current_message.id)])
179- DEBUG Checking messages matching: id=...
180- DEBUG Checking message ...
181- INFO ... (current): format specifications ... are not the same
182- DEBUG Commit point.
183- COMMIT
184- DEBUG Commit point.
185- COMMIT
186- INFO Done.
187- INFO Messages checked: 1
188- INFO Validation errors: 1
189- INFO Messages disabled: 1
190- INFO Messages unmasked: 0
191- INFO Commit points: ...
192-
193- >>> current_message.is_current
194- False
195- >>> imported_message.is_current
196- False
197-
198
199 == Output ==
200
201 Besides current messages, the script's output also distinguishes
202-imported ones, and ones that are completely unused.
203+imported ones, and ones that are completely unused. The imported message
204+happens to produce validation errors.
205+
206+ >>> imported_message.translations = [u'%s %s i']
207
208 In this example we'd like to see a nicely predictable ordering, so we
209 add a sort order using the -o option.
210@@ -191,7 +158,6 @@
211 INFO Messages checked: 2
212 INFO Validation errors: 2
213 INFO Messages disabled: 0
214- INFO Messages unmasked: 0
215 INFO Commit points: 2
216
217 In this case the imported message is checked twice: once all by itself
218@@ -226,7 +192,6 @@
219 INFO Messages checked: 1
220 INFO Validation errors: 1
221 INFO Messages disabled: 1
222- INFO Messages unmasked: 0
223 INFO Commit points: 2
224
225
226@@ -254,5 +219,4 @@
227 INFO Messages checked: 2
228 INFO Validation errors: 2
229 INFO Messages disabled: 0
230- INFO Messages unmasked: 0
231 INFO Commit points: 3
232
233=== modified file 'lib/lp/translations/interfaces/translationmessage.py'
234--- lib/lp/translations/interfaces/translationmessage.py 2010-08-31 12:42:29 +0000
235+++ lib/lp/translations/interfaces/translationmessage.py 2010-09-03 15:19:51 +0000
236@@ -230,7 +230,10 @@
237 """Get any POFile containing this translation."""
238
239 def ensureBrowserPOFile():
240- """Make sure browser_pofile contains something if possible."""
241+ """Assign the result of getOnePOFile to browser_pofile.
242+
243+ If browser_pofile is already set, it is left unchanged.
244+ """
245
246 def isHidden(pofile):
247 """Whether this is an unused, hidden suggestion in `pofile`.
248
249=== modified file 'lib/lp/translations/model/pofile.py'
250--- lib/lp/translations/model/pofile.py 2010-09-02 14:26:24 +0000
251+++ lib/lp/translations/model/pofile.py 2010-09-03 14:49:14 +0000
252@@ -536,13 +536,13 @@
253
254 def getTranslationMessages(self, condition=None):
255 """See `IPOFile`."""
256+ applicable_template = Coalesce(
257+ TranslationMessage.potemplateID, self.potemplate.id)
258 clauses = [
259 TranslationTemplateItem.potmsgsetID == TranslationMessage.potmsgsetID,
260 TranslationTemplateItem.potemplate == self.potemplate,
261 TranslationMessage.language == self.language,
262- Coalesce(
263- TranslationMessage.potemplateID,
264- self.potemplate.id) == self.potemplate.id,
265+ applicable_template == self.potemplate.id,
266 ]
267 if condition is not None:
268 clauses.append(condition)
269
270=== modified file 'lib/lp/translations/model/potmsgset.py'
271--- lib/lp/translations/model/potmsgset.py 2010-09-01 10:02:34 +0000
272+++ lib/lp/translations/model/potmsgset.py 2010-09-03 14:47:09 +0000
273@@ -846,7 +846,6 @@
274 matching_message = TranslationMessage(
275 potmsgset=self,
276 potemplate=pofile.potemplate,
277- pofile=None,
278 language=pofile.language,
279 origin=origin,
280 submitter=submitter,
281
282=== modified file 'lib/lp/translations/model/translationmessage.py'
283--- lib/lp/translations/model/translationmessage.py 2010-09-01 10:02:34 +0000
284+++ lib/lp/translations/model/translationmessage.py 2010-09-03 14:53:24 +0000
285@@ -162,6 +162,7 @@
286
287 def ensureBrowserPOFile(self):
288 """See `ITranslationMessage`."""
289+ return self.browser_pofile
290
291 @property
292 def all_msgstrs(self):
293@@ -387,6 +388,7 @@
294 """See `ITranslationMessage`."""
295 if self.browser_pofile is None:
296 self.browser_pofile = self.getOnePOFile()
297+ return self.browser_pofile
298
299 def _getSharedEquivalent(self):
300 """Get shared message that otherwise exactly matches this one.
301
302=== modified file 'lib/lp/translations/scripts/gettext_check_messages.py'
303--- lib/lp/translations/scripts/gettext_check_messages.py 2010-09-01 17:10:35 +0000
304+++ lib/lp/translations/scripts/gettext_check_messages.py 2010-09-03 15:29:12 +0000
305@@ -42,7 +42,6 @@
306 _check_count = 0
307 _error_count = 0
308 _disable_count = 0
309- _unmask_count = 0
310 _commit_count = 0
311
312 _commit_interval = timedelta(0, 3)
313@@ -73,10 +72,9 @@
314 self.logger.info("Messages checked: %d" % self._check_count)
315 self.logger.info("Validation errors: %d" % self._error_count)
316 self.logger.info("Messages disabled: %d" % self._disable_count)
317- self.logger.info("Messages unmasked: %d" % self._unmask_count)
318 self.logger.info("Commit points: %d" % self._commit_count)
319
320- def _log_bad_message(self, bad_message, unmasked_message, error):
321+ def _log_bad_message(self, bad_message, error):
322 """Report gettext validation error for active message."""
323 currency_markers = []
324 if bad_message.is_current:
325@@ -87,9 +85,6 @@
326 currency_markers.append('unused')
327 currency = ', '.join(currency_markers)
328 self.logger.info("%d (%s): %s" % (bad_message.id, currency, error))
329- if unmasked_message is not None:
330- self.logger.info(
331- "%s: unmasked %s." % (bad_message.id, unmasked_message.id))
332
333 def _check_message_for_error(self, translationmessage):
334 """Return error message for `translationmessage`, if any.
335@@ -108,44 +103,19 @@
336
337 return None
338
339- def _get_imported_alternative(self, translationmessage):
340- """Look for a valid, imported alternative for this message."""
341- # Do not search for an imported alternative.
342- return None
343- # This code is disabled because translationmessage.pofile is not
344- # available anymore. Providing the same functionality now would
345- # require extensive changes to the whole script.
346- # if translationmessage.is_imported:
347- # return None
348-
349- # potmsgset = translationmessage.potmsgset
350- # pofile = translationmessage.pofile
351- # return potmsgset.getImportedTranslationMessage(
352- # pofile.potemplate, pofile.language)
353-
354 def _check_and_fix(self, translationmessage):
355 """Check message against gettext, and fix it if necessary."""
356 error = self._check_message_for_error(translationmessage)
357 if error is None:
358 return
359
360- imported = self._get_imported_alternative(translationmessage)
361- if imported is not None:
362- # There is also an imported message that the current message
363- # was previously masking. If that one passes checks, we can
364- # activate it instead. Disabling the current message
365- # "unmasks" the imported one.
366- imported_error = self._check_message_for_error(imported)
367- if imported_error is not None:
368- imported = None
369+ # Here would be the place to check if another message can be used
370+ # instead of the bad one.
371
372- self._log_bad_message(translationmessage, imported, error)
373+ self._log_bad_message(translationmessage, error)
374 if translationmessage.is_current:
375 translationmessage.is_current = False
376 self._disable_count += 1
377- if imported is not None:
378- imported.is_current = True
379- self._unmask_count += 1
380
381 def _do_commit(self):
382 """Commit ongoing transaction, start a new one."""
383
384=== modified file 'lib/lp/translations/tests/pofiletranslator.txt'
385--- lib/lp/translations/tests/pofiletranslator.txt 2010-09-01 10:03:11 +0000
386+++ lib/lp/translations/tests/pofiletranslator.txt 2010-09-03 14:43:41 +0000
387@@ -24,16 +24,13 @@
388 >>> language_id = 387
389 >>> potmsgset_id = 1
390
391-
392-Note that our oldest TranslationMessage references pofile #1.
393-
394+Note that our oldest TranslationMessage belongs to pofile #1.
395
396 Stub has so far not translated anything in this pofile
397
398 >>> pofiletranslator(stub_id, pofile_id) is None
399 True
400
401-
402 If we add a message, the cache is updated
403
404 >>> cur.execute("""
405
406=== modified file 'lib/lp/translations/tests/test_pofile.py'
407--- lib/lp/translations/tests/test_pofile.py 2010-09-02 14:05:26 +0000
408+++ lib/lp/translations/tests/test_pofile.py 2010-09-03 14:37:51 +0000
409@@ -1752,59 +1752,98 @@
410 "getTranslationRows does not sort obsolete messages "
411 "(sequence=0) to the end of the file.")
412
413- def test_getTranslationMessages_baseline(self):
414- # Return all translation messages for this POFile.
415- # Shared, diverged and obsolete.
416- potmsgset = self.factory.makePOTMsgSet(self.potemplate, sequence=1)
417- suggestion = self.factory.makeTranslationMessage(
418- potmsgset=potmsgset, pofile=self.pofile)
419- current_shared = self.factory.makeTranslationMessage(
420- potmsgset=potmsgset, pofile=self.pofile, force_shared=True)
421- current_diverged = self.factory.makeTranslationMessage(
422- potmsgset=potmsgset, pofile=self.pofile, force_diverged=True)
423- obsolete_potmsgset = self.factory.makePOTMsgSet(
424- self.potemplate, sequence=0)
425- obsolete = self.factory.makeTranslationMessage(
426- potmsgset=obsolete_potmsgset, pofile=self.pofile,
427- force_shared=True)
428-
429- self.assertContentEqual(
430- [current_shared, current_diverged, suggestion, obsolete],
431- self.pofile.getTranslationMessages())
432-
433- def test_getTranslationMessages_condition(self):
434- # Narrow the result set down using a condition.
435- potmsgset = self.factory.makePOTMsgSet(self.potemplate, sequence=1)
436- suggestion = self.factory.makeTranslationMessage(
437- potmsgset=potmsgset, pofile=self.pofile)
438- current_shared = self.factory.makeTranslationMessage(
439- potmsgset=potmsgset, pofile=self.pofile, force_shared=True)
440- current_diverged = self.factory.makeTranslationMessage(
441- potmsgset=potmsgset, pofile=self.pofile, force_diverged=True)
442- obsolete_potmsgset = self.factory.makePOTMsgSet(
443- self.potemplate, sequence=0)
444- obsolete = self.factory.makeTranslationMessage(
445- potmsgset=obsolete_potmsgset, pofile=self.pofile,
446- force_shared=True)
447-
448- self.assertContentEqual(
449- [current_shared, suggestion, obsolete],
450- self.pofile.getTranslationMessages(
451- "TranslationMessage.potemplate IS NULL"))
452-
453+
454+class TestPOFileTranslationMessages(TestCaseWithFactory):
455+ """Test PO file getTranslationMessages method."""
456+
457+ layer = ZopelessDatabaseLayer
458+
459+ def setUp(self):
460+ super(TestPOFileTranslationMessages, self).setUp()
461+ self.pofile = self.factory.makePOFile('eo')
462+ self.potemplate = self.pofile.potemplate
463+ self.potmsgset = self.factory.makePOTMsgSet(
464+ self.potemplate, sequence=1)
465+
466+ def test_getTranslationMessages_current_shared(self):
467+ # A shared message is included in this POFile's messages.
468+ message = self.factory.makeTranslationMessage(
469+ potmsgset=self.potmsgset, pofile=self.pofile, force_shared=True)
470+
471+ self.assertEqual(
472+ [message], list(self.pofile.getTranslationMessages()))
473+
474+ def test_getTranslationMessages_current_diverged(self):
475+ # A diverged message is included in this POFile's messages.
476+ message = self.factory.makeTranslationMessage(
477+ potmsgset=self.potmsgset, pofile=self.pofile, force_diverged=True)
478+
479+ self.assertEqual(
480+ [message], list(self.pofile.getTranslationMessages()))
481+
482+ def test_getTranslationMessages_suggestion(self):
483+ # A suggestion is included in this POFile's messages.
484+ message = self.factory.makeTranslationMessage(
485+ potmsgset=self.potmsgset, pofile=self.pofile)
486+
487+ self.assertEqual(
488+ [message], list(self.pofile.getTranslationMessages()))
489+
490+ def test_getTranslationMessages_obsolete(self):
491+ # A message on an obsolete POTMsgSEt is included in this
492+ # POFile's messages.
493+ potmsgset = self.factory.makePOTMsgSet(self.potemplate, sequence=0)
494+ message = self.factory.makeTranslationMessage(
495+ potmsgset=potmsgset, pofile=self.pofile, force_shared=True)
496+
497+ self.assertEqual(
498+ [message], list(self.pofile.getTranslationMessages()))
499+
500 def test_getTranslationMessages_other_pofile(self):
501- # Messages from other POFiles are not included.
502- potmsgset = self.factory.makePOTMsgSet(self.potemplate, sequence=1)
503- other_pofile = self.factory.makePOFile('de')
504- my_message = self.factory.makeTranslationMessage(
505- potmsgset=potmsgset, pofile=self.pofile)
506- other_message = self.factory.makeTranslationMessage(
507- potmsgset=potmsgset, pofile=other_pofile)
508-
509+ # A message from another POFiles is not included.
510+ other_pofile = self.factory.makePOFile('de')
511+ self.factory.makeTranslationMessage(
512+ potmsgset=self.potmsgset, pofile=other_pofile)
513+
514+ self.assertEqual([], list(self.pofile.getTranslationMessages()))
515+
516+ def test_getTranslationMessages_condition_matches(self):
517+ # A message matching the given condition is included.
518+ # Diverged messages are linked to a specific POTemplate.
519+ message = self.factory.makeTranslationMessage(
520+ potmsgset=self.potmsgset, pofile=self.pofile, force_diverged=True)
521+
522+ self.assertContentEqual(
523+ [message],
524+ self.pofile.getTranslationMessages(
525+ "TranslationMessage.potemplate IS NOT NULL"))
526+
527+ def test_getTranslationMessages_condition_matches_not(self):
528+ # A message not matching the given condition is excluded.
529+ # Shared messages are not linked to a POTemplate.
530+ self.factory.makeTranslationMessage(
531+ potmsgset=self.potmsgset, pofile=self.pofile, force_shared=True)
532+
533+ self.assertContentEqual(
534+ [],
535+ self.pofile.getTranslationMessages(
536+ "TranslationMessage.potemplate IS NOT NULL"))
537+
538+ def test_getTranslationMessages_condition_matches_in_other_pofile(self):
539+ # A message matching given condition but located in another POFile
540+ # is not included.
541+ other_pofile = self.factory.makePOFile('de')
542+ self.factory.makeTranslationMessage(
543+ potmsgset=self.potmsgset, pofile=other_pofile,
544+ force_diverged=True)
545+
546+ self.assertContentEqual(
547+ [],
548+ self.pofile.getTranslationMessages(
549+ "TranslationMessage.potemplate IS NOT NULL"))
550+
551 def test_getTranslationMessages_diverged_elsewhere(self):
552 # Diverged messages from sharing POTemplates are not included.
553- potmsgset = self.factory.makePOTMsgSet(self.potemplate, sequence=1)
554-
555 # Create a sharing potemplate in another product series and share
556 # potmsgset in both templates.
557 other_series = self.factory.makeProductSeries(
558@@ -1813,15 +1852,12 @@
559 productseries=other_series, name=self.potemplate.name)
560 other_pofile = other_template.getPOFileByLang(
561 self.pofile.language.code)
562- potmsgset.setSequence(other_template, 1)
563-
564- my_message = self.factory.makeTranslationMessage(
565- potmsgset=potmsgset, pofile=self.pofile)
566- other_message = self.factory.makeTranslationMessage(
567- potmsgset=potmsgset, pofile=other_pofile, force_diverged=True)
568+ self.potmsgset.setSequence(other_template, 1)
569+ self.factory.makeTranslationMessage(
570+ potmsgset=self.potmsgset, pofile=other_pofile,
571+ force_diverged=True)
572
573- self.assertContentEqual(
574- [my_message], self.pofile.getTranslationMessages())
575+ self.assertEqual([], list(self.pofile.getTranslationMessages()))
576
577
578 class TestPOFileToTranslationFileDataAdapter(TestCaseWithFactory):

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
The diff is not available at this time. You can reload the page or download it.