Merge lp:~henninge/launchpad/bug-456562 into lp:launchpad

Proposed by Henning Eggers
Status: Merged
Approved by: Данило Шеган
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~henninge/launchpad/bug-456562
Merge into: lp:launchpad
Diff against target: 334 lines
6 files modified
lib/lp/translations/doc/potmsgset.txt (+53/-8)
lib/lp/translations/interfaces/potemplate.py (+7/-0)
lib/lp/translations/interfaces/potmsgset.py (+24/-2)
lib/lp/translations/model/potemplate.py (+18/-1)
lib/lp/translations/model/potmsgset.py (+27/-5)
lib/lp/translations/tests/test_potemplate.py (+13/-0)
To merge this branch: bzr merge lp:~henninge/launchpad/bug-456562
Reviewer Review Type Date Requested Status
Данило Шеган (community) Approve
Review via email: mp+13792@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Henning Eggers (henninge) wrote :

= Details =

See bug 456562.
Added two methods to access translation credits messages. This is in preparation of solving bug 128324.

== Implementation details ==

I added a class attribute to POTMsgSet to export the list of possible msgids for translation credits. This is used in getTranslationCredits to build the query.

I added a parameter to updateTranslation because it guarded against changing translation credits. This can now be overridden by setting allow_credits to True.

== Test ==

bin/test -vvt potmsgset.txt -t getTranslationCredits

== Demo/QA ==

None yet as these methods are not used yet.

Revision history for this message
Данило Шеган (danilo) wrote :

As I said on IRC, I don't like not_credits and not_credits_either variable naming in the getTranslationCredits test, and I wonder what that None keeps doing in credits_message_info/credits_message_ids but that's not part of this branch, so I am not blocking on it.

Everything else is great!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/translations/doc/potmsgset.txt'
2--- lib/lp/translations/doc/potmsgset.txt 2009-10-21 10:11:01 +0000
3+++ lib/lp/translations/doc/potmsgset.txt 2009-10-22 16:38:12 +0000
4@@ -34,36 +34,81 @@
5 is_translation_credit indicates if the POTMsgSet is translation credits. The
6 property translation_credit_type contains the type of translation credits.
7
8- >>> def print_credit(credit):
9- ... print credit.is_translation_credit
10- ... print credit.translation_credits_type.title
11+ >>> def print_credits(credits):
12+ ... print credits.is_translation_credit
13+ ... print credits.translation_credits_type.title
14
15- >>> print_credit(factory.makePOTMsgSet(potemplate))
16+ >>> print_credits(factory.makePOTMsgSet(potemplate))
17 False
18 Not a translation credits message
19
20- >>> print_credit(factory.makePOTMsgSet(
21+ >>> print_credits(factory.makePOTMsgSet(
22 ... potemplate, singular=u'translator-credits'))
23 True
24 Gnome credits message
25
26- >>> print_credit(factory.makePOTMsgSet(
27+ >>> print_credits(factory.makePOTMsgSet(
28 ... potemplate, singular=u'translation-credits'))
29 True
30 Gnome credits message
31
32- >>> print_credit(factory.makePOTMsgSet(
33+ >>> print_credits(factory.makePOTMsgSet(
34 ... potemplate,
35 ... singular=u'Your emails', context=u'EMAIL OF TRANSLATORS'))
36 True
37 KDE emails credits message
38
39- >>> print_credit(factory.makePOTMsgSet(
40+ >>> print_credits(factory.makePOTMsgSet(
41 ... potemplate, singular=u'_: EMAIL OF TRANSLATORS\nYour emails'))
42 True
43 KDE emails credits message
44
45
46+== POTMsgSet.setTranslationCreditsToTranslated ==
47+
48+If a message is a translation credits message, its translations must be set
49+to some dummy value so that they are counted as "translated" and don't
50+mess up the statistics.
51+
52+ >>> eo_pofile = factory.makePOFile('eo', potemplate=potemplate)
53+ >>> eo_language = eo_pofile.language
54+ >>> gnome_credits = factory.makePOTMsgSet(
55+ ... potemplate, singular=u'translator-credits')
56+ >>> current = gnome_credits.getCurrentTranslationMessage(potemplate,
57+ ... eo_language)
58+ >>> print current
59+ None
60+ >>> login("foo.bar@canonical.com")
61+ >>> gnome_credits.setTranslationCreditsToTranslated(eo_pofile)
62+ >>> current = gnome_credits.getCurrentTranslationMessage(potemplate,
63+ ... eo_language)
64+ >>> print current.msgstr0.translation
65+ This is a dummy translation so that the credits are counted as translated.
66+
67+An imported translation credits message will already contain a translation
68+and is therefore left untouched.
69+
70+ >>> from zope.security.proxy import removeSecurityProxy
71+ >>> sr_pofile = removeSecurityProxy(factory.makePOFile('sr', potemplate=potemplate))
72+ >>> sr_language = sr_pofile.language
73+ >>> sr_credits = factory.makeTranslationMessage(
74+ ... potmsgset=gnome_credits, pofile=sr_pofile, is_imported=True,
75+ ... translations=[u"Some translations credits for Serbian."])
76+ >>> gnome_credits.setTranslationCreditsToTranslated(sr_pofile)
77+ >>> current = gnome_credits.getCurrentTranslationMessage(potemplate,
78+ ... sr_language)
79+ >>> print current.msgstr0.translation
80+ Some translations credits for Serbian.
81+
82+Normal messages will be left untouched, too.
83+
84+ >>> potmsgset.setTranslationCreditsToTranslated(sr_language)
85+ >>> current = potmsgset.getCurrentTranslationMessage(potemplate,
86+ ... sr_pofile)
87+ >>> print current
88+ None
89+
90+
91 == POTMsgSet.normalizeWhitespaces ==
92
93 This function copies the leading and trailing whitespaces from
94
95=== modified file 'lib/lp/translations/interfaces/potemplate.py'
96--- lib/lp/translations/interfaces/potemplate.py 2009-09-15 15:30:59 +0000
97+++ lib/lp/translations/interfaces/potemplate.py 2009-10-22 16:38:12 +0000
98@@ -365,6 +365,13 @@
99 all of them.
100 """
101
102+ def getTranslationCredits():
103+ """Return an iterator over translation credits.
104+
105+ Return all `IPOTMsgSet` objects in this template that are translation
106+ credits.
107+ """
108+
109 def getPOTMsgSetsCount(current=True):
110 """Return the number of POTMsgSet objects related to this object.
111
112
113=== modified file 'lib/lp/translations/interfaces/potmsgset.py'
114--- lib/lp/translations/interfaces/potmsgset.py 2009-10-21 09:54:09 +0000
115+++ lib/lp/translations/interfaces/potmsgset.py 2009-10-22 16:38:12 +0000
116@@ -4,7 +4,7 @@
117 # pylint: disable-msg=E0211,E0213
118
119 from zope.interface import Interface, Attribute
120-from zope.schema import Bool, Choice, Int, Object, Text
121+from zope.schema import Bool, Choice, Int, List, Object, Text
122 from lazr.enum import EnumeratedType, Item
123
124 from canonical.launchpad import _
125@@ -112,6 +112,14 @@
126 gettext uses the original English strings to identify messages.
127 """))
128
129+ credits_message_ids = List(
130+ title=_("List of possible msgids for translation credits"),
131+ readonly=True,
132+ description=_("""
133+ This class attribute is intended to be used to construct database
134+ queries that search for credits messages.
135+ """))
136+
137 def getCurrentDummyTranslationMessage(potemplate, language):
138 """Return a DummyTranslationMessage for this message language.
139
140@@ -195,7 +203,8 @@
141
142 def updateTranslation(pofile, submitter, new_translations, is_imported,
143 lock_timestamp, force_suggestion=False,
144- ignore_errors=False, force_edition_rights=False):
145+ ignore_errors=False, force_edition_rights=False,
146+ allow_credits=False):
147 """Update or create a translation message using `new_translations`.
148
149 :param pofile: a `POFile` to add `new_translations` to.
150@@ -213,6 +222,8 @@
151 should be stored even when an error is detected.
152 :param force_edition_rights: A flag that 'forces' handling this
153 submission as coming from an editor, even if `submitter` is not.
154+ :param allow_credits: Override the protection of translation credits
155+ message.
156
157 If there is an error with the translations and ignore_errors is not
158 True or it's not a fuzzy submit, raises gettextpo.error
159@@ -319,6 +330,17 @@
160 `IPOTemplate`.
161 """
162
163+ def setTranslationCreditsToTranslated(pofile):
164+ """Set the current translation for this translation credits message.
165+
166+ Sets a fixed dummy string as the current translation, if this is a
167+ translation credits message, so that these get counted as
168+ 'translated', too.
169+ Credits messages that already have a translation, imported messages
170+ and normal messages are left untouched.
171+ :param pofile: the POFile to set this translation in.
172+ """
173+
174 def getAllTranslationMessages():
175 """Retrieve all `TranslationMessage`s for this `POTMsgSet`."""
176
177
178=== modified file 'lib/lp/translations/model/potemplate.py'
179--- lib/lp/translations/model/potemplate.py 2009-10-10 13:43:31 +0000
180+++ lib/lp/translations/model/potemplate.py 2009-10-22 16:38:12 +0000
181@@ -24,7 +24,7 @@
182 from sqlobject import (
183 BoolCol, ForeignKey, IntCol, SQLMultipleJoin, SQLObjectNotFound,
184 StringCol)
185-from storm.expr import Alias, And, LeftJoin, Or, SQL
186+from storm.expr import Alias, And, Join, LeftJoin, Or, SQL
187 from storm.info import ClassAlias
188 from storm.store import Store
189 from zope.component import getAdapter, getUtility
190@@ -418,6 +418,23 @@
191 orderBy=['TranslationTemplateItem.sequence'])
192 return query.prejoin(['msgid_singular', 'msgid_plural'])
193
194+ def getTranslationCredits(self):
195+ """See `IPOTemplate`."""
196+ # Find potential credits messages by the message ids.
197+ store = IStore(POTemplate)
198+ credits_ids = ",".join(map(quote, POTMsgSet.credits_message_ids))
199+ origin1 = Join(TranslationTemplateItem,
200+ TranslationTemplateItem.potmsgset == POTMsgSet.id)
201+ origin2 = Join(POMsgID, POTMsgSet.msgid_singular == POMsgID.id)
202+ result = store.using(POTMsgSet, origin1, origin2).find(
203+ POTMsgSet, TranslationTemplateItem.potemplate == self,
204+ "pomsgid.msgid IN (%s)" % credits_ids)
205+ # Filter these candidates because is_translation_credit checks for
206+ # more conditions than the special msgids.
207+ for potmsgset in result:
208+ if potmsgset.is_translation_credit:
209+ yield potmsgset
210+
211 def getPOTMsgSetsCount(self, current=True):
212 """See `IPOTemplate`."""
213 results = self.getPOTMsgSets(current)
214
215=== modified file 'lib/lp/translations/model/potmsgset.py'
216--- lib/lp/translations/model/potmsgset.py 2009-10-21 09:54:09 +0000
217+++ lib/lp/translations/model/potmsgset.py 2009-10-22 16:38:12 +0000
218@@ -6,8 +6,10 @@
219 __metaclass__ = type
220 __all__ = ['POTMsgSet']
221
222+import datetime
223 import gettextpo
224 import logging
225+import pytz
226
227 from zope.interface import implements
228 from zope.component import getUtility
229@@ -49,7 +51,7 @@
230
231 # Msgids that indicate translation credit messages, and their
232 # contexts and type.
233-credit_message_ids = {
234+credits_message_info = {
235 # Regular gettext credits messages.
236 u'translation-credits': (None, TranslationCreditsType.GNOME),
237 u'translator-credits': (None, TranslationCreditsType.GNOME),
238@@ -68,6 +70,10 @@
239 (None, TranslationCreditsType.KDE_NAMES),
240 }
241
242+# String to be used as msgstr for translation credits messages.
243+credits_message_str = (u'This is a dummy translation so that the '
244+ u'credits are counted as translated.')
245+
246
247 class POTMsgSet(SQLBase):
248 implements(IPOTMsgSet)
249@@ -90,6 +96,8 @@
250
251 _cached_uses_english_msgids = None
252
253+ credits_message_ids = credits_message_info.keys()
254+
255 def __storm_invalidated__(self):
256 self._cached_singular_text = None
257 self._cached_uses_english_msgids = None
258@@ -740,7 +748,8 @@
259 def updateTranslation(self, pofile, submitter, new_translations,
260 is_imported, lock_timestamp, force_shared=False,
261 force_diverged=False, force_suggestion=False,
262- ignore_errors=False, force_edition_rights=False):
263+ ignore_errors=False, force_edition_rights=False,
264+ allow_credits=False):
265 """See `IPOTMsgSet`."""
266
267 just_a_suggestion, warn_about_lock_timestamp = (
268@@ -752,7 +761,10 @@
269
270 # If the update is on the translation credits message, yet
271 # update is not is_imported, silently return.
272- if self.is_translation_credit and not is_imported:
273+ deny_credits = (not allow_credits and
274+ self.is_translation_credit and
275+ not is_imported)
276+ if deny_credits:
277 return None
278
279 # Sanitize translations
280@@ -1010,11 +1022,11 @@
281 @property
282 def translation_credits_type(self):
283 """See `IPOTMsgSet`."""
284- if self.msgid_singular.msgid not in credit_message_ids:
285+ if self.msgid_singular.msgid not in credits_message_info:
286 return TranslationCreditsType.NOT_CREDITS
287
288 expected_context, credits_type = (
289- credit_message_ids[self.msgid_singular.msgid])
290+ credits_message_info[self.msgid_singular.msgid])
291 if expected_context is None or (self.context == expected_context):
292 return credits_type
293 return TranslationCreditsType.NOT_CREDITS
294@@ -1039,6 +1051,16 @@
295 pomsgid = POMsgID(msgid=plural_form_text)
296 self.msgid_plural = pomsgid
297
298+ def setTranslationCreditsToTranslated(self, pofile):
299+ """See `IPOTMsgSet`."""
300+ if self.is_translation_credit:
301+ translation = self.getSharedTranslationMessage(pofile.language)
302+ if translation is None:
303+ message = self.updateTranslation(pofile, pofile.owner,
304+ [credits_message_str], False,
305+ datetime.datetime.now(pytz.UTC),
306+ allow_credits=True)
307+
308 def setSequence(self, potemplate, sequence):
309 """See `IPOTMsgSet`."""
310 self.sequence = sequence
311
312=== modified file 'lib/lp/translations/tests/test_potemplate.py'
313--- lib/lp/translations/tests/test_potemplate.py 2009-08-13 19:03:36 +0000
314+++ lib/lp/translations/tests/test_potemplate.py 2009-10-22 16:38:11 +0000
315@@ -65,6 +65,19 @@
316 "(Expected: '%s' Got: '%s')" % (expected, result)
317 )
318
319+ def test_getTranslationCredits(self):
320+ # getTranslationCredits returns only translation credits.
321+ self.factory.makePOTMsgSet(self.potemplate, sequence=1)
322+ gnome_credits = self.factory.makePOTMsgSet(
323+ self.potemplate, sequence=2, singular=u"translator-credits")
324+ kde_credits = self.factory.makePOTMsgSet(
325+ self.potemplate, sequence=3,
326+ singular=u"Your emails", context=u"EMAIL OF TRANSLATORS")
327+ self.factory.makePOTMsgSet(self.potemplate, sequence=4)
328+
329+ self.assertContentEqual([gnome_credits, kde_credits],
330+ self.potemplate.getTranslationCredits())
331+
332
333 class EquivalenceClassTestMixin:
334 """Helper for POTemplate equivalence class tests."""