Merge lp:~jtv/launchpad/bug-488218 into lp:launchpad

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Jeroen T. Vermeulen
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~jtv/launchpad/bug-488218
Merge into: lp:launchpad
Diff against target: 325 lines (+105/-61)
7 files modified
lib/lp/translations/browser/person.py (+2/-0)
lib/lp/translations/doc/pofile.txt (+39/-12)
lib/lp/translations/model/pofile.py (+9/-2)
lib/lp/translations/model/potmsgset.py (+14/-11)
lib/lp/translations/stories/standalone/xx-translations-to-complete.txt (+25/-0)
lib/lp/translations/tests/test_pofile.py (+1/-0)
lib/lp/translations/tests/test_potmsgset.py (+15/-36)
To merge this branch: bzr merge lp:~jtv/launchpad/bug-488218
Reviewer Review Type Date Requested Status
Michael Nelson (community) code Approve
Review via email: mp+15247@code.launchpad.net

Commit message

Attribute "credits" translationmessages to rosetta_experts; never list rosetta_experts as contributor.

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

= Bug 488218 =

Some translatable messages (POTMsgSets) are special. They are not
really translatable; they represent translation credits and their
"translations" are generated on-demand.

In order to stop these messages from showing up as untranslated, we
create special, "fake" translation messages for them.

But every time we create a TranslationMessage, the fact is recorded as a
contribution made by the message's translator. In this case, the last
translator for the POFile was recorded as the translator for the credits
message; or failing that, its owner.

So we had phantom "contributions" based on these automatically generated
messages. This branch fixes that by:

1. Making the Rosetta Experts team the translator for these messages.

2. Never listing Rosetta Experts as a contributor. Translations are
made by persons, not teams, and this team isn't for translation as such
anyway.

The tests for ownership are simplified; a new test shows explicitly that
the Rosetta Experts team is ignored in the contributors list. You'll
note a small drive-by there as well.

To test:
{{{
./bin/test -vv -t pofile.txt -t test_pofile -t test_potmsgset -t translations-to-complete
}}}

To Q/A: import a template with a translation credits message. For
example:

msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "Text"
msgstr ""

msgid "translation-credits"
msgstr ""

Then visit a (still blank) translation of the template, and log out from
there. This will create (because of a known, low-priority bug) a POFile
for that translation.

Log back in and look at your personal Translations page, under Activity.
There should be no reference to the POFile you just created; without
this branch, there is.

Also look at the translation credits message. Both before and after, it
will show your username. But previously it would show you as the
translator; now it will show Rosetta Administrators as the translator.

Finally, there turned out to be an oops waiting to happen when visiting
the Translations page for rosetta_experts, because the browser code
recognized that the team is now active as a translator, and was trying
to list translations the team could help complete. Teams should not be
considered translators in that context. I added a bit of pagetest.

Jeroen

Revision history for this message
Michael Nelson (michael.nelson) wrote :
Download full text (14.4 KiB)

Hi Jeroen,

Thanks for all the multiple drive-by's!

r=me, but two thoughts. The first is general - is there not a better way to handle
these translation credits so that they're not translatable messages
at all? I guess not, otherwise you would have done it.

Second thought: you said in your cover letter that "translations are made
by persons, not teams", but translations are still displayed for other
teams - just not the rosetta experts, is that right?
(eg. http://pastebin.ubuntu.com/328399/), if so, why? (just for my
understanding)

> === modified file 'lib/lp/translations/browser/person.py'
> --- lib/lp/translations/browser/person.py 2009-09-17 20:11:48 +0000
> +++ lib/lp/translations/browser/person.py 2009-11-26 10:47:06 +0000
> @@ -215,6 +215,8 @@
> @property
> def person_is_translator(self):
> """Is this person active in translations?"""
> + if self.context.isTeam():
> + return False
> person = ITranslationsPerson(self.context)
> history = person.getTranslationHistory(self.history_horizon).any()
> return history is not None
>
> === modified file 'lib/lp/translations/doc/pofile.txt'
> --- lib/lp/translations/doc/pofile.txt 2009-10-29 17:46:00 +0000
> +++ lib/lp/translations/doc/pofile.txt 2009-11-26 10:47:06 +0000
> @@ -1031,8 +1031,17 @@
> The 'contributors' property of a POFile returns all the people who contributed
> translations to it.
>
> - >>> [person.name for person in evolution_es.contributors]
> - [u'carlos', u'mark', u'no-priv']
> + >>> def print_names(persons):
> + ... """Print name for each of `persons`."""
> + ... for person in persons:
> + ... print person.name
> + ... print "--"
> +
> + >>> print_names(evolution_es.contributors)
> + carlos
> + mark
> + no-priv
> + --
>
> If you have a distroseries and want to know all the people who contributed
> translations on a given language for that distroseries, you can use
> @@ -1042,9 +1051,16 @@
> >>> from lp.registry.model.distroseries import DistroSeries
> >>> hoary = DistroSeries.selectOneBy(name="hoary")
> >>> spanish = Language.selectOneBy(code="es")
> - >>> [p.name for p in hoary.getPOFileContributorsByLanguage(spanish)]
> - [u'jorge-gonzalez-gonzalez', u'carlos', u'valyag', u'danner', u'name16',
> - u'name12', u'ubuntu-translators', u'tsukimi']
> + >>> print_names(hoary.getPOFileContributorsByLanguage(spanish))
> + jorge-gonzalez-gonzalez
> + carlos
> + valyag
> + danner
> + name16
> + name12
> + ubuntu-translators
> + tsukimi
> + --
>
> # We can see that there is another translator that doesn't appear in
> # previous list because the template he translated is not current.
> @@ -1052,8 +1068,9 @@
> >>> non_current_pofile.potemplate.iscurrent
> False
>
> - >>> [p.name for p in non_current_pofile.contributors]
> - [u'jordi']
> + >>> print_names(non_current_pofile.contributors)
> + jordi
> + --
>
> >>> non_current_pofile.potemplate.distroseries == hoary
> True
> @@ -1061,6 +1078,17 @@
> >>> non_current_pofile.language == spanish
> True...

review: Approve (code)
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Thanks for the review!

> r=me, but two thoughts. The first is general - is there not a better way to
> handle
> these translation credits so that they're not translatable messages
> at all? I guess not, otherwise you would have done it.

Right. It's actually an elegant solution in the problem domain that these are in all respects translatable messages. Another way of looking at it is that we, as an implementation, just happen to automate their translation.

> Second thought: you said in your cover letter that "translations are made
> by persons, not teams", but translations are still displayed for other
> teams - just not the rosetta experts, is that right?
> (eg. http://pastebin.ubuntu.com/328399/), if so, why? (just for my
> understanding)

Yes. One of the tests also showed translations made by another team, though I don't know how it was supposed to arrive at a situation where those can exist. One way I could think of, though, is by changing a person into a team. I believe that's possible, though I haven't checked.

Functionally, there's nothing wrong with crediting team contributions if they should exist. It's really just in the case of rosetta_experts that listing the team as a contributor becomes totally meaningless.

Jeroen

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/translations/browser/person.py'
--- lib/lp/translations/browser/person.py 2009-09-17 20:11:48 +0000
+++ lib/lp/translations/browser/person.py 2009-11-25 17:00:32 +0000
@@ -215,6 +215,8 @@
215 @property215 @property
216 def person_is_translator(self):216 def person_is_translator(self):
217 """Is this person active in translations?"""217 """Is this person active in translations?"""
218 if self.context.isTeam():
219 return False
218 person = ITranslationsPerson(self.context)220 person = ITranslationsPerson(self.context)
219 history = person.getTranslationHistory(self.history_horizon).any()221 history = person.getTranslationHistory(self.history_horizon).any()
220 return history is not None222 return history is not None
221223
=== modified file 'lib/lp/translations/doc/pofile.txt'
--- lib/lp/translations/doc/pofile.txt 2009-10-29 17:46:00 +0000
+++ lib/lp/translations/doc/pofile.txt 2009-11-25 17:00:32 +0000
@@ -1031,8 +1031,17 @@
1031The 'contributors' property of a POFile returns all the people who contributed1031The 'contributors' property of a POFile returns all the people who contributed
1032translations to it.1032translations to it.
10331033
1034 >>> [person.name for person in evolution_es.contributors]1034 >>> def print_names(persons):
1035 [u'carlos', u'mark', u'no-priv']1035 ... """Print name for each of `persons`."""
1036 ... for person in persons:
1037 ... print person.name
1038 ... print "--"
1039
1040 >>> print_names(evolution_es.contributors)
1041 carlos
1042 mark
1043 no-priv
1044 --
10361045
1037If you have a distroseries and want to know all the people who contributed1046If you have a distroseries and want to know all the people who contributed
1038translations on a given language for that distroseries, you can use1047translations on a given language for that distroseries, you can use
@@ -1042,9 +1051,16 @@
1042 >>> from lp.registry.model.distroseries import DistroSeries1051 >>> from lp.registry.model.distroseries import DistroSeries
1043 >>> hoary = DistroSeries.selectOneBy(name="hoary")1052 >>> hoary = DistroSeries.selectOneBy(name="hoary")
1044 >>> spanish = Language.selectOneBy(code="es")1053 >>> spanish = Language.selectOneBy(code="es")
1045 >>> [p.name for p in hoary.getPOFileContributorsByLanguage(spanish)]1054 >>> print_names(hoary.getPOFileContributorsByLanguage(spanish))
1046 [u'jorge-gonzalez-gonzalez', u'carlos', u'valyag', u'danner', u'name16',1055 jorge-gonzalez-gonzalez
1047 u'name12', u'ubuntu-translators', u'tsukimi']1056 carlos
1057 valyag
1058 danner
1059 name16
1060 name12
1061 ubuntu-translators
1062 tsukimi
1063 --
10481064
1049 # We can see that there is another translator that doesn't appear in1065 # We can see that there is another translator that doesn't appear in
1050 # previous list because the template he translated is not current.1066 # previous list because the template he translated is not current.
@@ -1052,8 +1068,9 @@
1052 >>> non_current_pofile.potemplate.iscurrent1068 >>> non_current_pofile.potemplate.iscurrent
1053 False1069 False
10541070
1055 >>> [p.name for p in non_current_pofile.contributors]1071 >>> print_names(non_current_pofile.contributors)
1056 [u'jordi']1072 jordi
1073 --
10571074
1058 >>> non_current_pofile.potemplate.distroseries == hoary1075 >>> non_current_pofile.potemplate.distroseries == hoary
1059 True1076 True
@@ -1061,6 +1078,17 @@
1061 >>> non_current_pofile.language == spanish1078 >>> non_current_pofile.language == spanish
1062 True1079 True
10631080
1081The rosetta_experts team is special: it never shows up in contributors
1082lists.
1083
1084 >>> experts_pofile = factory.makePOFile('nl')
1085 >>> experts_message = factory.makeTranslationMessage(
1086 ... pofile=experts_pofile, translator=rosetta_experts,
1087 ... reviewer=rosetta_experts, translations=['hi'])
1088
1089 >>> print_names(experts_pofile.contributors)
1090 --
1091
10641092
1065== getPOTMsgSetTranslated ==1093== getPOTMsgSetTranslated ==
10661094
@@ -1191,7 +1219,6 @@
1191 Happy translator1219 Happy translator
1192 Launchpad Contributions:1220 Launchpad Contributions:
1193 Carlos ...1221 Carlos ...
1194 Rosetta Administrators...
11951222
1196Emails of translators just has the dummy translation.1223Emails of translators just has the dummy translation.
11971224
@@ -1210,7 +1237,7 @@
12101237
1211 >>> print alsa_translation.prepareTranslationCredits(1238 >>> print alsa_translation.prepareTranslationCredits(
1212 ... emails_of_translators)1239 ... emails_of_translators)
1213 ,,carlos@canonical.com,rosetta@launchpad.net1240 ,,carlos@canonical.com
12141241
1215Names of translators just has the dummy translation.1242Names of translators just has the dummy translation.
12161243
@@ -1228,7 +1255,7 @@
12281255
1229 >>> print alsa_translation.prepareTranslationCredits(1256 >>> print alsa_translation.prepareTranslationCredits(
1230 ... names_of_translators)1257 ... names_of_translators)
1231 ,Launchpad Contributions:,Carlos P... M...,Rosetta Administrators1258 ,Launchpad Contributions:,Carlos P... M...
12321259
1233Lets add a newly supported KDE context message with credit strings1260Lets add a newly supported KDE context message with credit strings
1234split into two: context and message, instead of a single message with1261split into two: context and message, instead of a single message with
@@ -1241,7 +1268,7 @@
1241prepareTranslationCredits works on such messages as well:1268prepareTranslationCredits works on such messages as well:
12421269
1243 >>> print alsa_translation.prepareTranslationCredits(new_kde_name_credits)1270 >>> print alsa_translation.prepareTranslationCredits(new_kde_name_credits)
1244 ,Launchpad Contributions:,Carlos P... M...,Rosetta Administrators1271 ,Launchpad Contributions:,Carlos P... M...
12451272
1246Similar happens for email credits as with name credits.1273Similar happens for email credits as with name credits.
12471274
@@ -1249,7 +1276,7 @@
1249 ... singular_text=u"Your emails", plural_text=None,1276 ... singular_text=u"Your emails", plural_text=None,
1250 ... context=u"EMAIL OF TRANSLATORS")1277 ... context=u"EMAIL OF TRANSLATORS")
1251 >>> print alsa_translation.prepareTranslationCredits(new_kde_email_credits)1278 >>> print alsa_translation.prepareTranslationCredits(new_kde_email_credits)
1252 ,,carlos@canonical.com,rosetta@launchpad.net1279 ,,carlos@canonical.com
12531280
12541281
1255== POFileToTranslationFileDataAdapter ==1282== POFileToTranslationFileDataAdapter ==
12561283
=== modified file 'lib/lp/translations/model/pofile.py'
--- lib/lp/translations/model/pofile.py 2009-11-17 09:50:33 +0000
+++ lib/lp/translations/model/pofile.py 2009-11-25 17:00:32 +0000
@@ -36,6 +36,7 @@
36from canonical.launchpad.webapp.publisher import canonical_url36from canonical.launchpad.webapp.publisher import canonical_url
37from canonical.librarian.interfaces import ILibrarianClient37from canonical.librarian.interfaces import ILibrarianClient
38from lp.registry.interfaces.person import validate_public_person38from lp.registry.interfaces.person import validate_public_person
39from lp.registry.model.person import Person
39from lp.translations.utilities.rosettastats import RosettaStats40from lp.translations.utilities.rosettastats import RosettaStats
40from lp.translations.interfaces.pofile import IPOFile, IPOFileSet41from lp.translations.interfaces.pofile import IPOFile, IPOFileSet
41from lp.translations.interfaces.potmsgset import (42from lp.translations.interfaces.potmsgset import (
@@ -504,10 +505,15 @@
504 @property505 @property
505 def contributors(self):506 def contributors(self):
506 """See `IPOFile`."""507 """See `IPOFile`."""
507 from lp.registry.model.person import Person508 # Translation credit messages are "translated" by
509 # rosetta_experts. Shouldn't show up in contributors lists
510 # though.
511 admin_team = getUtility(ILaunchpadCelebrities).rosetta_experts
512
508 contributors = Person.select("""513 contributors = Person.select("""
509 POFileTranslator.person = Person.id AND514 POFileTranslator.person = Person.id AND
510 POFileTranslator.pofile = %s""" % quote(self),515 POFileTranslator.person <> %s AND
516 POFileTranslator.pofile = %s""" % sqlvalues(admin_team, self),
511 clauseTables=["POFileTranslator"],517 clauseTables=["POFileTranslator"],
512 distinct=True,518 distinct=True,
513 # XXX: kiko 2006-10-19:519 # XXX: kiko 2006-10-19:
@@ -516,6 +522,7 @@
516 # function to the column results and then ignore it -- just522 # function to the column results and then ignore it -- just
517 # like selectAlso does, ironically.523 # like selectAlso does, ironically.
518 orderBy=["Person.displayname", "Person.name"])524 orderBy=["Person.displayname", "Person.name"])
525
519 return contributors526 return contributors
520527
521 def prepareTranslationCredits(self, potmsgset):528 def prepareTranslationCredits(self, potmsgset):
522529
=== modified file 'lib/lp/translations/model/potmsgset.py'
--- lib/lp/translations/model/potmsgset.py 2009-11-11 11:29:09 +0000
+++ lib/lp/translations/model/potmsgset.py 2009-11-25 17:00:32 +0000
@@ -1053,17 +1053,20 @@
10531053
1054 def setTranslationCreditsToTranslated(self, pofile):1054 def setTranslationCreditsToTranslated(self, pofile):
1055 """See `IPOTMsgSet`."""1055 """See `IPOTMsgSet`."""
1056 if self.is_translation_credit:1056 if not self.is_translation_credit:
1057 translation = self.getSharedTranslationMessage(pofile.language)1057 return
1058 if translation is None:1058
1059 translator = pofile.lasttranslator1059 if self.getSharedTranslationMessage(pofile.language) is not None:
1060 if translator is None:1060 return
1061 translator = pofile.owner1061
1062 message = self.updateTranslation(1062 # The credits message has a fixed "translator."
1063 pofile, translator, [credits_message_str],1063 translator = getUtility(ILaunchpadCelebrities).rosetta_experts
1064 is_imported=False, allow_credits=True,1064
1065 force_shared=True, force_edition_rights=True,1065 message = self.updateTranslation(
1066 lock_timestamp=datetime.datetime.now(pytz.UTC))1066 pofile, translator, [credits_message_str],
1067 is_imported=False, allow_credits=True,
1068 force_shared=True, force_edition_rights=True,
1069 lock_timestamp=datetime.datetime.now(pytz.UTC))
10671070
1068 def setSequence(self, potemplate, sequence):1071 def setSequence(self, potemplate, sequence):
1069 """See `IPOTMsgSet`."""1072 """See `IPOTMsgSet`."""
10701073
=== modified file 'lib/lp/translations/stories/standalone/xx-translations-to-complete.txt'
--- lib/lp/translations/stories/standalone/xx-translations-to-complete.txt 2009-08-31 13:55:35 +0000
+++ lib/lp/translations/stories/standalone/xx-translations-to-complete.txt 2009-11-25 17:00:32 +0000
@@ -62,3 +62,28 @@
62 ... pierre_browser.contents, 'translations-to-complete-table')62 ... pierre_browser.contents, 'translations-to-complete-table')
63 >>> print tag63 >>> print tag
64 None64 None
65
66
67Teams
68-----
69
70The Rosetta administrators, as a special case, can act as a translator
71for automatically generated messages. Nevertheless, its Translations
72page does not show any translations to complete--even to a member of the team.
73
74 >>> login('carlos@canonical.com')
75 >>> from zope.component import getUtility
76 >>> from canonical.launchpad.interfaces.launchpad import (
77 ... ILaunchpadCelebrities)
78 >>> pofile = factory.makePOFile('ru')
79 >>> rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts
80 >>> message = factory.makeTranslationMessage(
81 ... pofile=pofile, translator=rosetta_experts, translations=['x'])
82 >>> logout()
83
84 >>> carlos_browser = setupBrowser('Basic carlos@canonical.com:test')
85 >>> experts_home = 'http://translations.launchpad.dev/~rosetta-admins'
86 >>> carlos_browser.open(experts_home)
87
88 >>> print extract_text(find_tag_by_id(
89 ... jean_browser.contents, 'translations-to-complete-table'))
6590
=== modified file 'lib/lp/translations/tests/test_pofile.py'
--- lib/lp/translations/tests/test_pofile.py 2009-10-30 10:29:25 +0000
+++ lib/lp/translations/tests/test_pofile.py 2009-11-25 17:00:32 +0000
@@ -911,6 +911,7 @@
911 self.assertNotEqual(None, stable_potemplate.getPOFileByLang('eo'))911 self.assertNotEqual(None, stable_potemplate.getPOFileByLang('eo'))
912 self.assertNotEqual(None, stable_potemplate.getPOFileByLang('de'))912 self.assertNotEqual(None, stable_potemplate.getPOFileByLang('de'))
913913
914
914class TestTranslationCredits(TestCaseWithFactory):915class TestTranslationCredits(TestCaseWithFactory):
915 """Test generation of translation credits."""916 """Test generation of translation credits."""
916917
917918
=== modified file 'lib/lp/translations/tests/test_potmsgset.py'
--- lib/lp/translations/tests/test_potmsgset.py 2009-11-11 11:38:22 +0000
+++ lib/lp/translations/tests/test_potmsgset.py 2009-11-25 17:00:32 +0000
@@ -15,6 +15,7 @@
15from zope.security.proxy import isinstance as zope_isinstance15from zope.security.proxy import isinstance as zope_isinstance
16from zope.security.proxy import removeSecurityProxy16from zope.security.proxy import removeSecurityProxy
1717
18from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
18from lp.registry.interfaces.person import IPersonSet19from lp.registry.interfaces.person import IPersonSet
19from lp.registry.interfaces.product import IProductSet20from lp.registry.interfaces.product import IProductSet
20from lp.services.worlddata.interfaces.language import ILanguageSet21from lp.services.worlddata.interfaces.language import ILanguageSet
@@ -23,7 +24,6 @@
23from lp.translations.interfaces.translationfileformat import (24from lp.translations.interfaces.translationfileformat import (
24 TranslationFileFormat)25 TranslationFileFormat)
25from lp.translations.interfaces.translationmessage import TranslationConflict26from lp.translations.interfaces.translationmessage import TranslationConflict
26from lp.translations.interfaces.translationsperson import ITranslationsPerson
27from lp.translations.model.translationmessage import (27from lp.translations.model.translationmessage import (
28 DummyTranslationMessage)28 DummyTranslationMessage)
2929
@@ -675,41 +675,20 @@
675 self.assertNotEqual(None, current_shared)675 self.assertNotEqual(None, current_shared)
676 self.assertEqual(None, current_shared.potemplate)676 self.assertEqual(None, current_shared.potemplate)
677677
678 def test_setTranslationCreditsToTranslated_permissions(self):678 def test_setTranslationCreditsToTranslated_submitter(self):
679 # Even if POFile.owner has not agreed to the Launchpad679 # Submitter on the automated translation message is always
680 # translations licensing policy, automated credit680 # the rosetta_experts team.
681 # messages are still created.681 sr_pofile = self.factory.makePOFile('sr', self.devel_potemplate)
682 sr_pofile = self.factory.makePOFile('sr', self.devel_potemplate)682 translator = self.factory.makePerson()
683 owner = sr_pofile.owner683 sr_pofile.lasttranslator = translator
684 ITranslationsPerson(owner).translations_relicensing_agreement = False684 sr_pofile.owner = translator
685 credits_potmsgset = self.factory.makePOTMsgSet(685 credits_potmsgset = self.factory.makePOTMsgSet(
686 self.devel_potemplate, singular=u'translator-credits')686 self.devel_potemplate, singular=u'translator-credits')
687 current = credits_potmsgset.getCurrentTranslationMessage(687 current = credits_potmsgset.getCurrentTranslationMessage(
688 self.devel_potemplate, sr_pofile.language)688 self.devel_potemplate, sr_pofile.language)
689 self.assertEqual(owner, current.submitter)689
690690 rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts
691 def test_setTranslationCreditsToTranslated_submitter_lasttranslator(self):691 self.assertEqual(rosetta_experts, current.submitter)
692 # Submitter on the automated translation message is set to
693 # POFile.lasttranslator if it's defined.
694 sr_pofile = self.factory.makePOFile('sr', self.devel_potemplate)
695 last_translator = self.factory.makePerson()
696 sr_pofile.lasttranslator = last_translator
697 credits_potmsgset = self.factory.makePOTMsgSet(
698 self.devel_potemplate, singular=u'translator-credits')
699 current = credits_potmsgset.getCurrentTranslationMessage(
700 self.devel_potemplate, sr_pofile.language)
701 self.assertEqual(last_translator, current.submitter)
702
703 def test_setTranslationCreditsToTranslated_submitter_owner(self):
704 # Submitter on the automated translation message is set to
705 # POFile.owner if POFile.lasttranslator is not defined.
706 sr_pofile = self.factory.makePOFile('sr', self.devel_potemplate)
707 self.assertEqual(None, sr_pofile.lasttranslator)
708 credits_potmsgset = self.factory.makePOTMsgSet(
709 self.devel_potemplate, singular=u'translator-credits')
710 current = credits_potmsgset.getCurrentTranslationMessage(
711 self.devel_potemplate, sr_pofile.language)
712 self.assertEqual(sr_pofile.owner, current.submitter)
713692
714693
715class TestPOTMsgSetSuggestions(TestCaseWithFactory):694class TestPOTMsgSetSuggestions(TestCaseWithFactory):