Merge lp:~henninge/launchpad/db-devel-688519-getusedtranslationmessage into lp:launchpad/db-devel

Proposed by Henning Eggers on 2010-12-16
Status: Merged
Approved by: Curtis Hovey on 2010-12-17
Approved revision: no longer in the source branch.
Merged at revision: 10070
Proposed branch: lp:~henninge/launchpad/db-devel-688519-getusedtranslationmessage
Merge into: lp:launchpad/db-devel
Diff against target: 842 lines (+199/-170)
17 files modified
lib/lp/testing/factory.py (+12/-11)
lib/lp/translations/doc/poimport.txt (+4/-4)
lib/lp/translations/doc/potmsgset.txt (+8/-8)
lib/lp/translations/interfaces/potmsgset.py (+14/-0)
lib/lp/translations/model/potmsgset.py (+34/-12)
lib/lp/translations/model/side.py (+3/-4)
lib/lp/translations/model/translatablemessage.py (+4/-3)
lib/lp/translations/model/translationmessage.py (+3/-0)
lib/lp/translations/scripts/message_sharing_migration.py (+6/-8)
lib/lp/translations/scripts/tests/test_message_sharing_migration.py (+3/-3)
lib/lp/translations/tests/helpers.py (+7/-19)
lib/lp/translations/tests/potmsgset-update-translation.txt (+11/-10)
lib/lp/translations/tests/test_potmsgset.py (+72/-66)
lib/lp/translations/tests/test_suggestions.py (+2/-3)
lib/lp/translations/tests/test_translatablemessage.py (+5/-8)
lib/lp/translations/utilities/tests/import-flags.txt (+2/-2)
lib/lp/translations/utilities/tests/test_xpi_import.py (+9/-9)
To merge this branch: bzr merge lp:~henninge/launchpad/db-devel-688519-getusedtranslationmessage
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code 2010-12-17 Approve on 2010-12-17
j.c.sackett (community) code* 2010-12-16 Approve on 2010-12-17
Review via email: mp+43924@code.launchpad.net

Commit Message

[r=jcsackett,sinzui][ui=none][bug=688519] Replacement for getImportedTranslationMessage and getSharedTranslationMessage. Stop using makeCurrent*.

Description of the Change

= Summary =

The goal of this branch was to find an alternative for methods that use
POTMsgSet._getUsedTranslationMessage, which are
getCurrentTranslationMessage, getImportedTranslationMessage, and
getSharedTranslationMessage. These alternatives were found but cannot be
used in all places so that the old methods have to be kept around.

The branch is quite long because a lot of call sites could still be updated.

Another fix that came up while doing this was to remove the use of
TranslationMessage.makeCurrentUbunut and makeCurrentUpstream from code that
uses the new model. In the new model the work done by them has been moved to
higher levels.

A few more other things were fixed, see the details below.

== Proposed fix ==

The getImportedTranslationMessage and getSharedTranslationMessage were
replaced by getOtherTranslation and getSharedTranslation which use
getCurrentTranslation which already existed.

The makeCurrent* methods were called in the central
TranslationSideTraits.setFlag method. Its implemetation now sets the
respective flag attributes directly without checking if other flags need to
be cleared first. Only one call site needed to be fixed because it did not
unset a flag properly.

== Pre-implementation notes ==

More and earlier pre-implementation chatting with Danilo would have
prevented some turns that this branch took but it's OK now. There are a lot
more things that could be fixed but they should not become part of this
branch.

== Implementation details ==

Any change not mentioned here is either a mechanical replacement or was
already mentioned.

lib/lp/testing/factory.py:
The factory method makeCurrentTranslationMessage did not create diverged
message properly which was now causing tests to fail. That now routes
through makeDivergedTranslationMessage which already existed.

lib/lp/translations/model/potmsgset.py:
The singular_text property was patched to work with the new model by looking
for English translations on both sides. That approach is still subject to
discussion but works for now.
An added setFlag call fixes setCurrentTranslation.

lib/lp/translations/tests/helpers.py:
I found that get_all_translations_current_anywhere was named wrongly because
it explicitely looks for diverged messages. Also its implementation and also
its call site were overly complicated. I fixed it to be simpler.

lib/lp/translations/tests/test_potmsgset.py:
The bigger test changes in here were the incentive for this branch. Some of
the concepts tested here don't apply any more, so I updated the test to be
more useful. This could be done for a lot more tests but not in this branch.

I just saw that I left two tests disabled in there. They should pass now,
though. I will re-enable them an push the change.

lib/lp/translations/tests/test_translatablemessage.py:
The factory method makeCurrentTranslationMessage now takes date_created and
date_reviewed parameters.

== Tests ==

Best to run all translations tests.
bin/test -vvm lp.translations

== Demo and Q/A ==

QA is part of the QA for the recife branch.

= Launchpad lint =

I removed a lot of lint as you can see in the branch.

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/translations/scripts/tests/test_message_sharing_migration.py
  lib/lp/translations/utilities/tests/import-flags.txt
  lib/lp/translations/model/side.py
  lib/lp/translations/interfaces/potmsgset.py
  lib/lp/translations/scripts/message_sharing_migration.py
  lib/lp/testing/factory.py
  lib/lp/translations/tests/helpers.py
  lib/lp/translations/tests/test_potmsgset.py
  lib/lp/translations/utilities/tests/test_xpi_import.py
  lib/lp/translations/doc/poimport.txt
  lib/lp/translations/tests/potmsgset-update-translation.txt
  lib/lp/translations/tests/test_translatablemessage.py
  lib/lp/translations/model/potmsgset.py
  lib/lp/translations/model/translatablemessage.py
  lib/lp/translations/doc/potmsgset.txt
  lib/lp/translations/tests/test_suggestions.py
  lib/lp/translations/model/translationmessage.py

./lib/lp/translations/utilities/tests/import-flags.txt
       1: narrative uses a moin header.
      14: narrative uses a moin header.
      23: source exceeds 78 characters.
      91: narrative uses a moin header.
     242: narrative exceeds 78 characters.
./lib/lp/translations/model/potmsgset.py
     307: W291 trailing whitespace
     307: Line has trailing whitespace.

To post a comment you must log in.
j.c.sackett (jcsackett) wrote :
Download full text (15.2 KiB)

Henninge--

This is quite a branch.

Is it safe to assume this is preceding further work? I like the changes, but it seems like this introduces yet another way to do things without getting rid of the old way that I think this branch is supposed to cleanup.

Overall, there's a lot of cleanup in this branch I appreciate. I have some other questions below and a few commenting nitpicks/questions. Feel free to answer here or track me down in IRC.

> === modified file 'lib/lp/testing/factory.py'
> --- lib/lp/testing/factory.py 2010-12-15 04:45:54 +0000
> +++ lib/lp/testing/factory.py 2010-12-16 16:04:00 +0000
> @@ -2671,24 +2671,25 @@
> potmsgset.singular_text, translations,
> pofile.language.pluralforms)
>
> - message = potmsgset.setCurrentTranslation(
> - pofile, translator, translations,
> - RosettaTranslationOrigin.ROSETTAWEB,
> - share_with_other_side=current_other)
> - naked_message = removeSecurityProxy(message)
> -
> if diverged:
> - naked_message.potemplate = pofile.potemplate
> + message = self.makeDivergedTranslationMessage(
> + pofile, potmsgset, translator, reviewer,
> + translations, date_created)
> + else:
> + message = potmsgset.setCurrentTranslation(
> + pofile, translator, translations,
> + RosettaTranslationOrigin.ROSETTAWEB,
> + share_with_other_side=current_other)
> + if date_created is not None:
> + removeSecurityProxy(message).date_created = date_created
>
> - if date_created is not None:
> - naked_message.date_created = date_created
> message.markReviewed(reviewer, date_reviewed)
>
> return message

Thanks for improving the use of naked objects through that stretch.

> === modified file 'lib/lp/translations/model/potmsgset.py'
> --- lib/lp/translations/model/potmsgset.py 2010-12-02 16:13:51 +0000
> +++ lib/lp/translations/model/potmsgset.py 2010-12-16 16:04:00 +0000
> @@ -245,10 +245,17 @@
> self._cached_singular_text = self.msgid_singular.msgid
> return self._cached_singular_text
>
> - # Singular text is stored as an "English translation."
> - translation_message = self.getCurrentTranslationMessage(
> - potemplate=None,
> - language=getUtility(ILaunchpadCelebrities).english)
> + # Singular text is stored as an "English translation." Search on
> + # both sides.
> + # XXX henninge 2010-12-14, bug=690196 This may still need some
> + # re-thinking. Maybe even add "getAnyCurrentTranslation".
> + translation_message = self.getCurrentTranslation(
> + None, getUtility(ILaunchpadCelebrities).english,
> + TranslationSide.UBUNTU)
> + if translation_message is None:
> + translation_message = self.getCurrentTranslation(
> + None, getUtility(ILaunchpadCelebrities).english,
> + TranslationSide.UPSTREAM)
> if translation_message is not None:
> msgstr0 = translation_message.msgstr0
> ...

review: Needs Information (code*)
Henning Eggers (henninge) wrote :
Download full text (13.4 KiB)

Am 16.12.2010 19:33, schrieb j.c.sackett:
> Review: Needs Information code*
> Henninge--
>
> This is quite a branch.

I know. Sorry about that.

>
> Is it safe to assume this is preceding further work?

Yes, there is more to come. I am sorry I forgot to mention the big picture. We
recently merged our "recife" feature branch which introduces a new model to
share translations between Ubuntu and upstream projects. This is not primarily
a change in the database model (some column and index renaming) but in the way
we use it. The work is mostly done but there is still a lot of cruft flying
around. The work to remove that is ongoing and this branch is part of it.

Thank you very much for ploughing through this branch. Please find my comments
below.

Cheers,
Henning

>> === modified file 'lib/lp/translations/model/potmsgset.py'
>> --- lib/lp/translations/model/potmsgset.py 2010-12-02 16:13:51 +0000
>> +++ lib/lp/translations/model/potmsgset.py 2010-12-16 16:04:00 +0000
>> @@ -245,10 +245,17 @@
>> self._cached_singular_text = self.msgid_singular.msgid
>> return self._cached_singular_text
>>
>> - # Singular text is stored as an "English translation."
>> - translation_message = self.getCurrentTranslationMessage(
>> - potemplate=None,
>> - language=getUtility(ILaunchpadCelebrities).english)
>> + # Singular text is stored as an "English translation." Search on
>> + # both sides.
>> + # XXX henninge 2010-12-14, bug=690196 This may still need some
>> + # re-thinking. Maybe even add "getAnyCurrentTranslation".
>> + translation_message = self.getCurrentTranslation(
>> + None, getUtility(ILaunchpadCelebrities).english,
>> + TranslationSide.UBUNTU)
>> + if translation_message is None:
>> + translation_message = self.getCurrentTranslation(
>> + None, getUtility(ILaunchpadCelebrities).english,
>> + TranslationSide.UPSTREAM)
>> if translation_message is not None:
>> msgstr0 = translation_message.msgstr0
>> if msgstr0 is not None:
>
> I'm not sure I understand what's going on here; could you explain more what
> the possible re-thinking entails?
>
> If I understand correctly, a new model requires looking at both UPSTREAM
> and UBUNTU translations to see if anything exists;

Well, that is what needs to be discussed. ;) Looking on both sides is the safe
approach for now to make sure we find anything. The bug report suggests other
solution, including a model change.

> I'm guessing the new model is the side.py thing? Or is this a new "conceptual model" ?

The TranslationSideTraits in side.py are a central part of the new conceptual
model. Another one is the setCurrentTranslation method which is the code that
is now doing what updateTranslation used to do.

Along with introducing the new model, we did some major restructuring in the
code because the old code (mainly updateTranslation) is too complex (in a bad
way) to try and change it to the new model. We now have more smaller methods
that share the work that updateTranslation used to do.

>
>> @@ -335,6 +343,18...

j.c.sackett (jcsackett) wrote :

Henning--

Thanks for addressing my comments and questions.

>> I know this method already existed, but as the use of assert statements has
>> become deprecated, it wouldn't hurt to clean this up into a normal,
>> more informative exception.
>
>Hm, I have not heard of that deprecation yet. The style guide points to
>https://dev.launchpad.net/AssertionsInLaunchpad
>which suggests that this is a correct use of an assert statement.

I hadn't seen that page; my understanding was that we were removing them from lp code, but that page makes a strong argument in your favor. I'll drop the issue, thanks for pointing me to those docs.

I look forwards to the future branches that continue cleaning this up, thanks for the start!

review: Approve (code*)
Curtis Hovey (sinzui) wrote :

I have no remarks.

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/testing/factory.py'
2--- lib/lp/testing/factory.py 2010-12-17 04:26:11 +0000
3+++ lib/lp/testing/factory.py 2010-12-17 10:33:38 +0000
4@@ -2656,24 +2656,25 @@
5 potmsgset.singular_text, translations,
6 pofile.language.pluralforms)
7
8- message = potmsgset.setCurrentTranslation(
9- pofile, translator, translations,
10- RosettaTranslationOrigin.ROSETTAWEB,
11- share_with_other_side=current_other)
12- naked_message = removeSecurityProxy(message)
13-
14 if diverged:
15- naked_message.potemplate = pofile.potemplate
16+ message = self.makeDivergedTranslationMessage(
17+ pofile, potmsgset, translator, reviewer,
18+ translations, date_created)
19+ else:
20+ message = potmsgset.setCurrentTranslation(
21+ pofile, translator, translations,
22+ RosettaTranslationOrigin.ROSETTAWEB,
23+ share_with_other_side=current_other)
24+ if date_created is not None:
25+ removeSecurityProxy(message).date_created = date_created
26
27- if date_created is not None:
28- naked_message.date_created = date_created
29 message.markReviewed(reviewer, date_reviewed)
30
31 return message
32
33 def makeDivergedTranslationMessage(self, pofile=None, potmsgset=None,
34 translator=None, reviewer=None,
35- translations=None):
36+ translations=None, date_created=None):
37 """Create a diverged, current `TranslationMessage`."""
38 if pofile is None:
39 pofile = self.makePOFile('lt')
40@@ -2682,7 +2683,7 @@
41
42 message = self.makeSuggestion(
43 pofile=pofile, potmsgset=potmsgset, translator=translator,
44- translations=translations)
45+ translations=translations, date_created=date_created)
46 return message.approveAsDiverged(pofile, reviewer)
47
48 def makeTranslation(self, pofile, sequence,
49
50=== modified file 'lib/lp/translations/doc/poimport.txt'
51--- lib/lp/translations/doc/poimport.txt 2010-12-02 16:13:51 +0000
52+++ lib/lp/translations/doc/poimport.txt 2010-12-17 10:33:38 +0000
53@@ -318,8 +318,8 @@
54
55 And should be accepted by our validator.
56
57- >>> upstream_message = message.potmsgset.getImportedTranslationMessage(
58- ... pofile.potemplate, pofile.language)
59+ >>> upstream_message = message.potmsgset.getOtherTranslation(
60+ ... pofile.language, pofile.potemplate.translation_side)
61 >>> upstream_message.validation_status == TranslationValidationStatus.OK
62 True
63
64@@ -337,8 +337,8 @@
65
66 >>> potmsgset = pofile.potemplate.getPOTMsgSetByMsgIDText(
67 ... u'Singular %d', u'Plural %d')
68- >>> imported_translationmessage = potmsgset.getImportedTranslationMessage(
69- ... pofile.potemplate, pofile.language)
70+ >>> imported_translationmessage = potmsgset.getOtherTranslation(
71+ ... pofile.language, pofile.potemplate.translation_side)
72 >>> print imported_translationmessage.validation_status.name
73 OK
74
75
76=== modified file 'lib/lp/translations/doc/potmsgset.txt'
77--- lib/lp/translations/doc/potmsgset.txt 2010-12-02 16:13:51 +0000
78+++ lib/lp/translations/doc/potmsgset.txt 2010-12-17 10:33:38 +0000
79@@ -245,8 +245,8 @@
80 >>> print upstream_potmsgset.getCurrentTranslationMessage(
81 ... evolution_potemplate, catalan)
82 None
83- >>> print upstream_potmsgset.getImportedTranslationMessage(
84- ... evolution_potemplate, catalan)
85+ >>> print upstream_potmsgset.getOtherTranslation(
86+ ... catalan, evolution_potemplate.translation_side)
87 None
88 >>> list(upstream_potmsgset.getLocalTranslationMessages(
89 ... evolution_potemplate, catalan))
90@@ -290,8 +290,8 @@
91 >>> print upstream_potmsgset.getCurrentTranslationMessage(
92 ... evolution_potemplate, catalan)
93 None
94- >>> print upstream_potmsgset.getImportedTranslationMessage(
95- ... evolution_potemplate, catalan)
96+ >>> print upstream_potmsgset.getOtherTranslation(
97+ ... catalan, evolution_potemplate.translation_side)
98 None
99 >>> list(upstream_potmsgset.getLocalTranslationMessages(
100 ... evolution_potemplate, catalan))
101@@ -339,8 +339,8 @@
102 ... evolution_potemplate, catalan)
103 >>> print current
104 None
105- >>> imported = upstream_potmsgset.getImportedTranslationMessage(
106- ... evolution_potemplate, catalan)
107+ >>> imported = upstream_potmsgset.getOtherTranslation(
108+ ... catalan, evolution_potemplate.translation_side)
109 >>> print imported
110 None
111
112@@ -871,8 +871,8 @@
113 ... pmount_man_template, pofile.language)
114 >>> print current
115 None
116- >>> imported = potmsgset_untranslated.getImportedTranslationMessage(
117- ... pmount_man_template, pofile.language)
118+ >>> imported = potmsgset_untranslated.getOtherTranslation(
119+ ... pofile.language, pmount_man_template.translation_side)
120 >>> print imported
121 None
122
123
124=== modified file 'lib/lp/translations/interfaces/potmsgset.py'
125--- lib/lp/translations/interfaces/potmsgset.py 2010-12-02 16:13:51 +0000
126+++ lib/lp/translations/interfaces/potmsgset.py 2010-12-17 10:33:38 +0000
127@@ -157,6 +157,20 @@
128 def getSharedTranslationMessage(language):
129 """Returns a shared TranslationMessage."""
130
131+ def getOtherTranslation(language, side):
132+ """Returns the TranslationMessage that is current on the other side.
133+
134+ :param language: The language in which to find the message.
135+ :param side: The side from which this message is seen.
136+ """
137+
138+ def getSharedTranslation(language, side):
139+ """Returns a shared TranslationMessage.
140+
141+ :param language: The language in which to find the message.
142+ :param side: The side from which this message is seen.
143+ """
144+
145 def getLocalTranslationMessages(potemplate, language,
146 include_dismissed=False,
147 include_unreviewed=True):
148
149=== modified file 'lib/lp/translations/model/potmsgset.py'
150--- lib/lp/translations/model/potmsgset.py 2010-12-02 16:13:51 +0000
151+++ lib/lp/translations/model/potmsgset.py 2010-12-17 10:33:38 +0000
152@@ -245,10 +245,17 @@
153 self._cached_singular_text = self.msgid_singular.msgid
154 return self._cached_singular_text
155
156- # Singular text is stored as an "English translation."
157- translation_message = self.getCurrentTranslationMessage(
158- potemplate=None,
159- language=getUtility(ILaunchpadCelebrities).english)
160+ # Singular text is stored as an "English translation." Search on
161+ # both sides.
162+ # XXX henninge 2010-12-14, bug=690196 This may still need some
163+ # re-thinking. Maybe even add "getAnyCurrentTranslation".
164+ translation_message = self.getCurrentTranslation(
165+ None, getUtility(ILaunchpadCelebrities).english,
166+ TranslationSide.UBUNTU)
167+ if translation_message is None:
168+ translation_message = self.getCurrentTranslation(
169+ None, getUtility(ILaunchpadCelebrities).english,
170+ TranslationSide.UPSTREAM)
171 if translation_message is not None:
172 msgstr0 = translation_message.msgstr0
173 if msgstr0 is not None:
174@@ -335,6 +342,18 @@
175 return self._getUsedTranslationMessage(
176 None, language, current=True)
177
178+ def getOtherTranslation(self, language, side):
179+ """See `IPOTMsgSet`."""
180+ traits = getUtility(
181+ ITranslationSideTraitsSet).getTraits(side)
182+ return self.getCurrentTranslation(
183+ None, language, traits.other_side_traits.side)
184+
185+ def getSharedTranslation(self, language, side):
186+ """See `IPOTMsgSet`."""
187+ return self.getCurrentTranslation(
188+ None, language, side)
189+
190 def getCurrentTranslation(self, potemplate, language, side):
191 """See `IPOTMsgSet`."""
192 assert side is not None, "Translation side must be specified."
193@@ -487,12 +506,12 @@
194
195 def hasTranslationChangedInLaunchpad(self, potemplate, language):
196 """See `IPOTMsgSet`."""
197- imported_translation = self.getImportedTranslationMessage(
198- potemplate, language)
199- current_translation = self.getCurrentTranslationMessage(
200- potemplate, language)
201- return (imported_translation is not None and
202- imported_translation != current_translation)
203+ other_translation = self.getOtherTranslation(
204+ language, potemplate.translation_side)
205+ current_translation = self.getCurrentTranslation(
206+ potemplate, language, potemplate.translation_side)
207+ return (other_translation is not None and
208+ other_translation != current_translation)
209
210 def isTranslationNewerThan(self, pofile, timestamp):
211 """See `IPOTMsgSet`."""
212@@ -1239,6 +1258,8 @@
213 lock_timestamp=None):
214 """Set the current translation.
215
216+ https://dev.launchpad.net/Translations/Specs/setCurrentTranslation
217+
218 :param pofile: The `POFile` to set the translation in.
219 :param submitter: The `Person` who produced this translation.
220 :param origin: The translation's `RosettaTranslationOrigin`.
221@@ -1373,6 +1394,7 @@
222 traits.other_side_traits.setFlag(message, True)
223 elif character == '+':
224 if share_with_other_side:
225+ traits.other_side_traits.setFlag(incumbent_message, False)
226 traits.other_side_traits.setFlag(message, True)
227 else:
228 raise AssertionError(
229@@ -1603,8 +1625,8 @@
230 if not self.is_translation_credit:
231 return
232
233- shared_upstream_translation = self.getCurrentTranslation(
234- None, pofile.language, TranslationSide.UPSTREAM)
235+ shared_upstream_translation = self.getSharedTranslation(
236+ pofile.language, TranslationSide.UPSTREAM)
237
238 if shared_upstream_translation is not None:
239 return
240
241=== modified file 'lib/lp/translations/model/side.py'
242--- lib/lp/translations/model/side.py 2010-12-02 11:01:43 +0000
243+++ lib/lp/translations/model/side.py 2010-12-17 10:33:38 +0000
244@@ -10,6 +10,7 @@
245 ]
246
247 from zope.interface import implements
248+from zope.security.proxy import removeSecurityProxy
249
250 from lp.translations.interfaces.side import (
251 ITranslationSideTraits,
252@@ -39,10 +40,8 @@
253
254 def setFlag(self, translationmessage, value):
255 """See `ITranslationSideTraits`."""
256- if self.side == TranslationSide.UPSTREAM:
257- translationmessage.makeCurrentUpstream(value)
258- else:
259- translationmessage.makeCurrentUbuntu(value)
260+ naked_tm = removeSecurityProxy(translationmessage)
261+ setattr(naked_tm, self.flag_name, value)
262
263
264 class TranslationSideTraitsSet:
265
266=== modified file 'lib/lp/translations/model/translatablemessage.py'
267--- lib/lp/translations/model/translatablemessage.py 2010-12-02 16:13:51 +0000
268+++ lib/lp/translations/model/translatablemessage.py 2010-12-17 10:33:38 +0000
269@@ -92,12 +92,13 @@
270
271 def getImportedTranslation(self):
272 """See `ITranslatableMessage`"""
273- return self.potmsgset.getImportedTranslationMessage(self.potemplate,
274- self.language)
275+ return self.potmsgset.getOtherTranslation(
276+ self.language, self.potemplate.translation_side)
277
278 def getSharedTranslation(self):
279 """See `ITranslatableMessage`"""
280- return self.potmsgset.getSharedTranslationMessage(self.language)
281+ return self.potmsgset.getSharedTranslation(
282+ self.language, self.potemplate.translation_side)
283
284 def getAllSuggestions(self):
285 """See `ITranslatableMessage`"""
286
287=== modified file 'lib/lp/translations/model/translationmessage.py'
288--- lib/lp/translations/model/translationmessage.py 2010-12-02 16:13:51 +0000
289+++ lib/lp/translations/model/translationmessage.py 2010-12-17 10:33:38 +0000
290@@ -398,6 +398,9 @@
291
292 def shareIfPossible(self):
293 """See `ITranslationMessage`."""
294+ # XXX henninge 2010-12-14 bug=690254: This method still needs some
295+ # thought on how it relates to the new model.
296+
297 if self.potemplate is None:
298 # Already converged.
299 return
300
301=== modified file 'lib/lp/translations/scripts/message_sharing_migration.py'
302--- lib/lp/translations/scripts/message_sharing_migration.py 2010-12-02 16:13:51 +0000
303+++ lib/lp/translations/scripts/message_sharing_migration.py 2010-12-17 10:33:38 +0000
304@@ -3,7 +3,7 @@
305
306 __metaclass__ = type
307 __all__ = [
308- 'MessageSharingMerge'
309+ 'MessageSharingMerge',
310 ]
311
312
313@@ -78,7 +78,7 @@
314
315 This adds all of the subordinate's TranslationTemplateItems to the
316 representative's set of TranslationTemplateItems.
317-
318+
319 Any duplicates are deleted, so after this, the subordinate will no
320 longer have any TranslationTemplateItems.
321 """
322@@ -127,8 +127,8 @@
323
324 :param message: a `TranslationMessage` to drop flags on.
325 :param incumbents: a sequence of reference messages. If any of
326- these has either is_current_ubuntu or is_current_upstream set, that same
327- flag will be dropped on message (if set).
328+ these has either is_current_ubuntu or is_current_upstream set, that
329+ same flag will be dropped on message (if set).
330 """
331 if incumbents:
332 for incumbent in incumbents:
333@@ -458,8 +458,7 @@
334 """Get list of ids for `template`'s `POTMsgSet`s."""
335 return [
336 potmsgset.id
337- for potmsgset in template.getPOTMsgSets(False, prefetch=False)
338- ]
339+ for potmsgset in template.getPOTMsgSets(False, prefetch=False)]
340
341 def _mergeTranslationMessages(self, potemplates):
342 """Share `TranslationMessage`s between templates where possible."""
343@@ -505,8 +504,7 @@
344 tm = removeSecurityProxy(tm)
345 msgstr_ids = tuple([
346 getattr(tm, 'msgstr%dID' % form)
347- for form in xrange(TranslationConstants.MAX_PLURAL_FORMS)
348- ])
349+ for form in xrange(TranslationConstants.MAX_PLURAL_FORMS)])
350
351 return (tm.potemplateID, tm.languageID) + msgstr_ids
352
353
354=== modified file 'lib/lp/translations/scripts/tests/test_message_sharing_migration.py'
355--- lib/lp/translations/scripts/tests/test_message_sharing_migration.py 2010-12-02 16:13:51 +0000
356+++ lib/lp/translations/scripts/tests/test_message_sharing_migration.py 2010-12-17 10:33:38 +0000
357@@ -212,8 +212,8 @@
358 potemplate=template, language=self.dutch)
359 if not message:
360 # No diverged message here, so check for a shared one.
361- message = potmsgset.getSharedTranslationMessage(
362- language=self.dutch)
363+ message = potmsgset.getSharedTranslation(
364+ language=self.dutch, side=template.translation_side)
365 return message
366
367 def _getMessages(self):
368@@ -594,7 +594,7 @@
369
370 # The duplicates have been cleaned up.
371 self.assertEqual(potmsgset.getAllTranslationMessages().count(), 1)
372-
373+
374 # The is_current_ubuntu and is_current_upstream flags from the
375 # duplicate messages have been merged into a single message,
376 # current in both ubuntu and upstream.
377
378=== modified file 'lib/lp/translations/tests/helpers.py'
379--- lib/lp/translations/tests/helpers.py 2010-11-17 12:30:06 +0000
380+++ lib/lp/translations/tests/helpers.py 2010-12-17 10:33:38 +0000
381@@ -7,10 +7,7 @@
382 'make_translationmessage_for_context',
383 ]
384
385-from storm.expr import (
386- Coalesce,
387- Or,
388- )
389+from storm.expr import Or
390 from storm.store import Store
391 from zope.component import getUtility
392 from zope.security.proxy import removeSecurityProxy
393@@ -88,11 +85,10 @@
394 return new_message
395
396
397-def get_all_translations_current_anywhere(pofile, potmsgset):
398- """Get current `TranslationMessage`s for this `POTMsgSet` and language.
399+def get_all_translations_diverged_anywhere(pofile, potmsgset):
400+ """Get diverged `TranslationMessage`s for this `POTMsgSet` and language.
401
402- The `TranslationMessage`s can be in use anywhere; the `pofile` only
403- selects the language.
404+ Leave out translations diverged to pofile.potemplate.
405 """
406 result = Store.of(potmsgset).find(
407 TranslationMessage,
408@@ -101,8 +97,9 @@
409 TranslationMessage.is_current_ubuntu == True,
410 TranslationMessage.is_current_upstream == True),
411 TranslationMessage.potemplate != None,
412+ TranslationMessage.potemplate != pofile.potemplate,
413 TranslationMessage.language == pofile.language)
414- return result.order_by(-Coalesce(TranslationMessage.potemplateID, -1))
415+ return result.order_by(-TranslationMessage.potemplateID)
416
417
418 def summarize_current_translations(pofile, potmsgset):
419@@ -135,16 +132,7 @@
420 "There is a diverged 'other' translation for "
421 "this same template, which should be impossible.")
422
423- all_used = get_all_translations_current_anywhere(
424- pofile, potmsgset)
425- diverged = []
426- for suggestion in all_used:
427- if ((suggestion.potemplate is not None and
428- suggestion.potemplate != template) and
429- (suggestion.is_current_ubuntu or
430- suggestion.is_current_upstream)):
431- # It's diverged for another template and current somewhere.
432- diverged.append(suggestion)
433+ diverged = list(get_all_translations_diverged_anywhere(pofile, potmsgset))
434 return (
435 current_shared, current_diverged,
436 other_shared, diverged)
437
438=== modified file 'lib/lp/translations/tests/potmsgset-update-translation.txt'
439--- lib/lp/translations/tests/potmsgset-update-translation.txt 2010-12-02 16:13:51 +0000
440+++ lib/lp/translations/tests/potmsgset-update-translation.txt 2010-12-17 10:33:38 +0000
441@@ -53,16 +53,16 @@
442 We change the upstream one, and thus, the one in Launchpad will be changed
443 too at the same time.
444
445- >>> message = potmsgset.updateTranslation(
446- ... pofile_es, carlos, {0: u'foo '}, is_current_upstream=True,
447- ... lock_timestamp=datetime.datetime.now(UTC))
448+ >>> message = potmsgset.updateTranslation(
449+ ... pofile_es, carlos, {0: u'foo '}, is_current_upstream=True,
450+ ... lock_timestamp=datetime.datetime.now(UTC))
451
452- >>> message.msgstr0.translation
453- u'foo '
454- >>> message.is_complete
455- True
456- >>> message.is_current_upstream
457- True
458+ >>> message.msgstr0.translation
459+ u'foo '
460+ >>> message.is_complete
461+ True
462+ >>> message.is_current_upstream
463+ True
464
465 Even more, if there is no translation at all in Launchpad, we still get
466 the update from upstream.
467@@ -131,7 +131,8 @@
468 >>> message.is_complete
469 True
470
471- >>> message = potmsgset.getImportedTranslationMessage(upstream_evo, spanish)
472+ >>> message = potmsgset.getImportedTranslationMessage(
473+ ... upstream_evo, spanish)
474 >>> message.translations
475 [u'bars ']
476
477
478=== modified file 'lib/lp/translations/tests/test_potmsgset.py'
479--- lib/lp/translations/tests/test_potmsgset.py 2010-12-10 13:44:57 +0000
480+++ lib/lp/translations/tests/test_potmsgset.py 2010-12-17 10:33:38 +0000
481@@ -246,55 +246,57 @@
482 self.assertEquals(self.potmsgset.getCurrentTranslationMessage(
483 self.stable_potemplate, serbian), shared_translation)
484
485-
486- # XXX henninge 2010-12-10 bug=688519: The meaning of imported is gone
487- # and so this test and the method it is testing need to be updated.
488- def test_getImportedTranslationMessage(self):
489- """Test how shared and diverged current translation messages
490- interact."""
491- # Share a POTMsgSet in two templates, and get a Serbian POFile.
492- self.potmsgset.setSequence(self.stable_potemplate, 1)
493- sr_pofile = self.factory.makePOFile('sr', self.devel_potemplate)
494- serbian = sr_pofile.language
495-
496- # A shared translation is imported in both templates.
497- shared_translation = self.factory.makeSharedTranslationMessage(
498- pofile=sr_pofile, potmsgset=self.potmsgset,
499- is_current_upstream=True)
500- self.assertEquals(self.potmsgset.getImportedTranslationMessage(
501- self.devel_potemplate, serbian), shared_translation)
502- self.assertEquals(self.potmsgset.getImportedTranslationMessage(
503- self.stable_potemplate, serbian), shared_translation)
504-
505- # Adding a diverged translation in one template makes that one
506- # an imported translation there.
507- diverged_translation = self.factory.makeTranslationMessage(
508- pofile=sr_pofile, potmsgset=self.potmsgset,
509- is_current_upstream=True, force_diverged=True)
510- self.assertEquals(self.potmsgset.getImportedTranslationMessage(
511- self.devel_potemplate, serbian), diverged_translation)
512- self.assertEquals(self.potmsgset.getImportedTranslationMessage(
513- self.stable_potemplate, serbian), shared_translation)
514-
515- def test_getSharedTranslationMessage(self):
516- """Test how shared and diverged current translation messages
517- interact."""
518+ def test_getOtherTranslation(self):
519+ # Get the translation on the other side.
520+ # Share POTMsgSet in a template on the other side.
521+ distroseries = self.factory.makeUbuntuDistroSeries()
522+ sourcepackagename = self.factory.makeSourcePackageName()
523+ ubuntu_potemplate = self.factory.makePOTemplate(
524+ distroseries=distroseries, sourcepackagename=sourcepackagename)
525+ self.potmsgset.setSequence(ubuntu_potemplate, 1)
526+ # Get POFiles on both sides.
527+ pofile = self.factory.makePOFile(potemplate=self.devel_potemplate)
528+ ubuntu_pofile = self.factory.makePOFile(
529+ potemplate=ubuntu_potemplate, language=pofile.language)
530+
531+ # A shared translation is current on both sides.
532+ shared_translation = self.factory.makeCurrentTranslationMessage(
533+ pofile=pofile, potmsgset=self.potmsgset, current_other=True)
534+ self.assertEquals(self.potmsgset.getCurrentTranslationMessage(
535+ ubuntu_potemplate, ubuntu_pofile.language), shared_translation)
536+ self.assertEquals(self.potmsgset.getOtherTranslation(
537+ pofile.language, self.devel_potemplate.translation_side),
538+ shared_translation)
539+
540+ # A diverted translation on the other side is not returned.
541+ diverged_translation = self.factory.makeCurrentTranslationMessage(
542+ pofile=ubuntu_pofile, potmsgset=self.potmsgset, diverged=True)
543+ self.assertEquals(self.potmsgset.getCurrentTranslationMessage(
544+ ubuntu_potemplate, ubuntu_pofile.language), diverged_translation)
545+ self.assertEquals(self.potmsgset.getOtherTranslation(
546+ pofile.language, self.devel_potemplate.translation_side),
547+ shared_translation)
548+
549+ def test_getSharedTranslation(self):
550+ # Get the current shared translation, not the diverged one.
551 # Share a POTMsgSet in two templates, and get a Serbian POFile.
552 sr_pofile = self.factory.makePOFile('sr', self.devel_potemplate)
553 serbian = sr_pofile.language
554
555 # A shared translation matches the current one.
556- shared_translation = self.factory.makeSharedTranslationMessage(
557+ shared_translation = self.factory.makeCurrentTranslationMessage(
558 pofile=sr_pofile, potmsgset=self.potmsgset)
559 self.assertEquals(
560- self.potmsgset.getSharedTranslationMessage(serbian),
561+ self.potmsgset.getSharedTranslation(
562+ serbian, self.stable_potemplate.translation_side),
563 shared_translation)
564
565 # Adding a diverged translation doesn't break getSharedTM.
566 diverged_translation = self.factory.makeCurrentTranslationMessage(
567 pofile=sr_pofile, potmsgset=self.potmsgset, diverged=True)
568 self.assertEquals(
569- self.potmsgset.getSharedTranslationMessage(serbian),
570+ self.potmsgset.getSharedTranslation(
571+ serbian, self.stable_potemplate.translation_side),
572 shared_translation)
573
574 def test_getLocalTranslationMessages(self):
575@@ -489,9 +491,8 @@
576
577 # If only a current, non-imported translation exists, it's not
578 # changed in Ubuntu.
579- current_shared = self.factory.makeSharedTranslationMessage(
580- pofile=sr_pofile, potmsgset=self.potmsgset,
581- is_current_upstream=False)
582+ current_shared = self.factory.makeCurrentTranslationMessage(
583+ pofile=sr_pofile, potmsgset=self.potmsgset)
584 self.assertEquals(
585 self.potmsgset.hasTranslationChangedInLaunchpad(
586 self.devel_potemplate, serbian),
587@@ -499,10 +500,9 @@
588
589 # If the current upstream translation is also current in Ubuntu,
590 # it's not changed in Ubuntu.
591- current_shared.makeCurrentUbuntu(False)
592- imported_shared = self.factory.makeSharedTranslationMessage(
593+ imported_shared = self.factory.makeCurrentTranslationMessage(
594 pofile=sr_pofile, potmsgset=self.potmsgset,
595- is_current_upstream=True)
596+ current_other=True)
597 self.assertEquals(
598 self.potmsgset.hasTranslationChangedInLaunchpad(
599 self.devel_potemplate, serbian),
600@@ -510,18 +510,19 @@
601
602 # If there's a current, diverged translation, and an imported
603 # non-current one, it's changed in Ubuntu.
604- imported_shared.makeCurrentUbuntu(False)
605 current_diverged = self.factory.makeCurrentTranslationMessage(
606- pofile=sr_pofile, potmsgset=self.potmsgset,
607- current_other=False)
608+ pofile=sr_pofile, potmsgset=self.potmsgset, diverged=True)
609 self.assertEquals(
610 self.potmsgset.hasTranslationChangedInLaunchpad(
611 self.devel_potemplate, serbian),
612 True)
613
614- # If the upstream one is shared and used in Ubuntu, yet there is
615- # a diverged Ubuntu translation as well, it is changed in Ubuntu.
616- imported_shared.makeCurrentUbuntu(False)
617+ # If there is a different non-diverged translation,
618+ # it's changed in Ubuntu.
619+ current = self.factory.makeCurrentTranslationMessage(
620+ pofile=sr_pofile, potmsgset=self.potmsgset)
621+ self.assertTrue(current.is_current_upstream)
622+ self.assertTrue(imported_shared.is_current_ubuntu)
623 self.assertEquals(
624 self.potmsgset.hasTranslationChangedInLaunchpad(
625 self.devel_potemplate, serbian),
626@@ -747,23 +748,26 @@
627 sr_pofile = self.factory.makePOFile('sr', self.devel_potemplate)
628 credits_potmsgset = self.factory.makePOTMsgSet(
629 self.devel_potemplate, singular=u'translator-credits')
630- diverged_credits = credits_potmsgset.setCurrentTranslation(
631- sr_pofile, sr_pofile.potemplate.owner, {0: 'credits'},
632- RosettaTranslationOrigin.SCM, share_with_other_side=True)
633+ diverged_credits = self.factory.makeCurrentTranslationMessage(
634+ sr_pofile, credits_potmsgset)
635 # Since translation credits are special, we can't easily create
636 # a diverged translation on it, though it may already exist in
637 # the DB.
638 removeSecurityProxy(diverged_credits).potemplate = (
639 sr_pofile.potemplate)
640 # Make sure that worked (not a real test).
641- self.assertTrue(diverged_credits.is_current_upstream)
642- self.assertEquals(sr_pofile.potemplate, diverged_credits.potemplate)
643+ test_diverged_credits = credits_potmsgset.getCurrentTranslation(
644+ sr_pofile.potemplate, sr_pofile.language,
645+ sr_pofile.potemplate.translation_side)
646+ self.assertTrue(test_diverged_credits.is_current_upstream)
647+ self.assertEquals(
648+ sr_pofile.potemplate, test_diverged_credits.potemplate)
649
650 credits_potmsgset.setTranslationCreditsToTranslated(sr_pofile)
651
652 # Shared translation is generated.
653- shared = credits_potmsgset.getCurrentTranslation(
654- None, sr_pofile.language, TranslationSide.UPSTREAM)
655+ shared = credits_potmsgset.getSharedTranslation(
656+ sr_pofile.language, sr_pofile.potemplate.translation_side)
657 self.assertNotEquals(diverged_credits, shared)
658 self.assertIsNot(None, shared)
659
660@@ -1437,8 +1441,9 @@
661 eo_pofile, credits, translations=[imported_credits],
662 current_other=True)
663
664- eo_translation = credits.getCurrentTranslationMessage(
665- self.potemplate, eo_pofile.language)
666+ eo_translation = credits.getCurrentTranslation(
667+ self.potemplate, eo_pofile.language,
668+ self.potemplate.translation_side)
669 self.assertEqual(imported_credits, eo_translation.msgstr0.translation,
670 "Imported translation credits do not replace dummy credits.")
671
672@@ -1712,7 +1717,7 @@
673 for form in xrange(forms))
674
675 def test_baseline(self):
676- # setCurrentTranslation sets the current upstream translation
677+ # setCurrentTranslation sets the current translation
678 # for a message.
679 pofile, potmsgset = self._makePOFileAndPOTMsgSet()
680 translations = self._makeTranslations(potmsgset)
681@@ -1721,8 +1726,9 @@
682 message = potmsgset.setCurrentTranslation(
683 pofile, pofile.potemplate.owner, translations, origin)
684
685- self.assertEqual(message, potmsgset.getImportedTranslationMessage(
686- pofile.potemplate, pofile.language))
687+ self.assertEqual(message, potmsgset.getCurrentTranslation(
688+ pofile.potemplate, pofile.language,
689+ pofile.potemplate.translation_side))
690 self.assertEqual(origin, message.origin)
691
692 def test_identical(self):
693@@ -1742,18 +1748,18 @@
694 self.assertEqual(pofile.potemplate.owner, message.submitter)
695 self.assertEqual(RosettaTranslationOrigin.ROSETTAWEB, message.origin)
696
697- def test_upstream_also_sets_initial_ubuntu(self):
698- # Setting an upstream translation also initializes the Ubuntu
699- # translation.
700+ def test_share_with_other_side(self):
701+ # If requested, the translation can also be set on the other side.
702 pofile, potmsgset = self._makePOFileAndPOTMsgSet()
703 translations = self._makeTranslations(potmsgset)
704 origin = RosettaTranslationOrigin.ROSETTAWEB
705
706 message = potmsgset.setCurrentTranslation(
707- pofile, pofile.potemplate.owner, translations, origin)
708+ pofile, pofile.potemplate.owner, translations, origin,
709+ share_with_other_side=True)
710
711- self.assertEqual(message, potmsgset.getImportedTranslationMessage(
712- pofile.potemplate, pofile.language))
713+ self.assertEqual(message, potmsgset.getOtherTranslation(
714+ pofile.language, pofile.potemplate.translation_side))
715
716 def test_detects_conflict(self):
717 pofile, potmsgset = self._makePOFileAndPOTMsgSet()
718
719=== modified file 'lib/lp/translations/tests/test_suggestions.py'
720--- lib/lp/translations/tests/test_suggestions.py 2010-12-02 16:13:51 +0000
721+++ lib/lp/translations/tests/test_suggestions.py 2010-12-17 10:33:38 +0000
722@@ -9,7 +9,6 @@
723 )
724 import unittest
725
726-import gettextpo
727 from pytz import timezone
728 import transaction
729 from zope.component import getUtility
730@@ -197,8 +196,8 @@
731 is_current_upstream=True, lock_timestamp=None)
732 current_translation = potmsgset.getCurrentTranslationMessage(
733 self.foo_template, self.foo_nl.language)
734- imported_translation = potmsgset.getImportedTranslationMessage(
735- self.foo_template, self.foo_nl.language)
736+ imported_translation = potmsgset.getOtherTranslation(
737+ self.foo_nl.language, self.foo_template.translation_side)
738
739 self.assertEquals(
740 current_translation, imported_translation,
741
742=== modified file 'lib/lp/translations/tests/test_translatablemessage.py'
743--- lib/lp/translations/tests/test_translatablemessage.py 2010-12-10 11:44:07 +0000
744+++ lib/lp/translations/tests/test_translatablemessage.py 2010-12-17 10:33:38 +0000
745@@ -13,7 +13,6 @@
746 import pytz
747 import transaction
748 from zope.component import getUtility
749-from zope.security.proxy import removeSecurityProxy
750
751 from canonical.testing.layers import ZopelessDatabaseLayer
752 from lp.app.enums import ServiceUsage
753@@ -55,11 +54,9 @@
754 pofile=self.pofile, potmsgset=self.potmsgset,
755 translations=translation,
756 current_other=is_current_ubuntu,
757- diverged=is_diverged)
758- if date_updated is not None:
759- naked_message = removeSecurityProxy(message)
760- naked_message.date_created = date_updated
761- naked_message.date_reviewed = date_updated
762+ diverged=is_diverged,
763+ date_created=date_updated,
764+ date_reviewed=date_updated)
765 else:
766 message = self.factory.makeSuggestion(
767 pofile=self.pofile, potmsgset=self.potmsgset,
768@@ -133,14 +130,14 @@
769 self.assertEqual(translation, current)
770
771 def test_getImportedTranslation(self):
772- translation = self._createTranslation(is_current_upstream=True)
773+ translation = self._createTranslation(is_current_ubuntu=True)
774
775 message = TranslatableMessage(self.potmsgset, self.pofile)
776 imported = message.getImportedTranslation()
777 self.assertEqual(translation, imported)
778
779 def test_getSharedTranslation(self):
780- translation = self._createTranslation(is_current_ubuntu=True)
781+ translation = self._createTranslation(is_current_upstream=True)
782 message = TranslatableMessage(self.potmsgset, self.pofile)
783 shared = message.getSharedTranslation()
784 self.assertEqual(translation, shared)
785
786=== modified file 'lib/lp/translations/utilities/tests/import-flags.txt'
787--- lib/lp/translations/utilities/tests/import-flags.txt 2010-12-02 16:13:51 +0000
788+++ lib/lp/translations/utilities/tests/import-flags.txt 2010-12-17 10:33:38 +0000
789@@ -49,8 +49,8 @@
790 ... msgid = potmsgset.singular_text
791 ... current = potmsgset.getCurrentTranslationMessage(
792 ... pofile.potemplate, pofile.language)
793- ... imported = potmsgset.getImportedTranslationMessage(
794- ... pofile.potemplate, pofile.language)
795+ ... imported = potmsgset.getOtherTranslation(
796+ ... pofile.language, pofile.potemplate.translation_side)
797 ... imported_translation = translation = None
798 ... if imported is not None:
799 ... imported_translation = imported.msgstr0.translation
800
801=== modified file 'lib/lp/translations/utilities/tests/test_xpi_import.py'
802--- lib/lp/translations/utilities/tests/test_xpi_import.py 2010-12-02 16:13:51 +0000
803+++ lib/lp/translations/utilities/tests/test_xpi_import.py 2010-12-17 10:33:38 +0000
804@@ -257,9 +257,9 @@
805 # With this first import, upstream and Ubuntu translations must match.
806 self.assertEquals(
807 translation.translations,
808- potmsgset.getImportedTranslationMessage(
809- self.firefox_template,
810- self.spanish_firefox.language).translations)
811+ potmsgset.getOtherTranslation(
812+ self.spanish_firefox.language,
813+ self.firefox_template.translation_side).translations)
814
815 potmsgset = self.firefox_template.getPOTMsgSetByMsgIDText(
816 u'foozilla.menu.accesskey', context='main/subdir/test2.dtd')
817@@ -274,9 +274,9 @@
818 unwrap(access_key_source_comment))
819 # But for the translation import, we get the key directly.
820 self.assertEquals(
821- potmsgset.getImportedTranslationMessage(
822- self.firefox_template,
823- self.spanish_firefox.language).translations,
824+ potmsgset.getOtherTranslation(
825+ self.spanish_firefox.language,
826+ self.firefox_template.translation_side).translations,
827 [u'M'])
828
829 potmsgset = self.firefox_template.getPOTMsgSetByMsgIDText(
830@@ -292,9 +292,9 @@
831 unwrap(command_key_source_comment))
832 # But for the translation import, we get the key directly.
833 self.assertEquals(
834- potmsgset.getImportedTranslationMessage(
835- self.firefox_template,
836- self.spanish_firefox.language).translations,
837+ potmsgset.getOtherTranslation(
838+ self.spanish_firefox.language,
839+ self.firefox_template.translation_side).translations,
840 [u'm'])
841
842 def test_GetLastTranslator(self):

Subscribers

People subscribed via source and target branches

to status/vote changes: