Merge lp:~salgado/launchpad/remove-translatablemessage into lp:launchpad

Proposed by Guilherme Salgado
Status: Merged
Approved by: Ian Booth
Approved revision: no longer in the source branch.
Merged at revision: 14825
Proposed branch: lp:~salgado/launchpad/remove-translatablemessage
Merge into: lp:launchpad
Diff against target: 1326 lines (+9/-1159)
12 files modified
lib/lp/translations/browser/pofile.py (+1/-195)
lib/lp/translations/browser/tests/pofile-base-views.txt (+0/-117)
lib/lp/translations/browser/tests/test_pofile_view.py (+8/-161)
lib/lp/translations/browser/tests/test_translatablemessage_view.py (+0/-97)
lib/lp/translations/browser/translatablemessage.py (+0/-85)
lib/lp/translations/configure.zcml (+0/-5)
lib/lp/translations/interfaces/pofile.py (+0/-6)
lib/lp/translations/interfaces/translatablemessage.py (+0/-115)
lib/lp/translations/model/pofile.py (+0/-5)
lib/lp/translations/model/translatablemessage.py (+0/-134)
lib/lp/translations/tests/test_pofile.py (+0/-10)
lib/lp/translations/tests/test_translatablemessage.py (+0/-229)
To merge this branch: bzr merge lp:~salgado/launchpad/remove-translatablemessage
Reviewer Review Type Date Requested Status
Ian Booth (community) Approve
j.c.sackett (community) Approve
Review via email: mp+93301@code.launchpad.net

Commit message

[r=jcsackett,wallyworld][bug=933910] Remove unused classes TranslatableMessage and POFileBaseView and associated tests.

Description of the change

This removes TranslatableMessage, which was never used anywhere. This is not removing any pages, exported APIs nor breaking any tests, so I'm pretty sure we're not going to lose any functionality.

To post a comment you must log in.
Revision history for this message
j.c.sackett (jcsackett) wrote :

Having read through this, nothing leaps out at me as problematic. Always concerned by that much deletion at once, but sort of delighted too, to be honest.

review: Approve
Revision history for this message
Ian Booth (wallyworld) wrote :

This branch also deletes POFileBaseView which as far as I can tell is unused also. It looks good to land but bear in mind I'm not a translations expert. Let's get this to qastaging and we can rollback if required.

review: Approve
Revision history for this message
Ian Booth (wallyworld) wrote :

I'll land this for the author.

Revision history for this message
Ian Booth (wallyworld) wrote :

Hi Guilherme

So this can be qa'ed once it lands, can you please create a bug and link to the branch and then I'll land for you.

Thanks.

Revision history for this message
Guilherme Salgado (salgado) wrote :

Thanks for the review, guys. Bug filed and linked :)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/translations/browser/pofile.py'
2--- lib/lp/translations/browser/pofile.py 2012-01-01 02:58:52 +0000
3+++ lib/lp/translations/browser/pofile.py 2012-02-15 21:27:19 +0000
4@@ -245,7 +245,7 @@
5
6 @property
7 def documentation_link_bubble(self):
8- """Reference to documentation, if appopriate."""
9+ """Reference to documentation, if appropriate."""
10 if not self.has_any_documentation:
11 return ""
12
13@@ -268,200 +268,6 @@
14 self.introduction_link, self.guide_links])
15
16
17-class POFileBaseView(LaunchpadView, POFileMetadataViewMixin):
18- """A basic view for a POFile
19-
20- This view is different from POFileView as it is the base for a new
21- generation of POFile views that use the new TranslatableMessage class
22- to display messages. They will eventually replace POFileView and its
23- decendants."""
24-
25- DEFAULT_SHOW = 'all'
26- DEFAULT_SIZE = 10
27-
28- def initialize(self):
29- super(POFileBaseView, self).initialize()
30-
31- self._initializeShowOption()
32-
33- self.batchnav = self._buildBatchNavigator()
34-
35- @cachedproperty
36- def contributors(self):
37- return tuple(self.context.contributors)
38-
39- @cachedproperty
40- def user_can_edit(self):
41- """Does the user have full edit rights for this translation?"""
42- return self.context.canEditTranslations(self.user)
43-
44- @cachedproperty
45- def user_can_suggest(self):
46- """Is the user allowed to make suggestions here?"""
47- return self.context.canAddSuggestions(self.user)
48-
49- @property
50- def permission_statement(self):
51- """Construct the statement about permissions.
52-
53- Explain the permissions the current user has on this pofile.
54- """
55-
56- if self.user_can_edit:
57- return _("You have full access to this translation.")
58- if self.user_can_suggest:
59- return _("Your suggestions will be held for review by "
60- "the managers of this translation.")
61- # Check for logged in state
62- if self.user is None:
63- return _("You are not logged in. Please log in to "
64- "work on translations.")
65- if not self.has_translationgroup:
66- return _("This translation is not open for changes.")
67- if self.is_managed:
68- return _("This template can be translated only by its managers.")
69- return _("There is nobody to manage translation into this particular "
70- "language. If you are interested in working on it, please "
71- "contact the translation group.")
72-
73- @property
74- def translation_groups_statement(self):
75- """List translation groups and translation teams for this translation.
76-
77- Returns a HTML string that lists the translation groups and the
78- relevant translators for this translation.
79- """
80- if self.translation_group is not None:
81- language = self.context.language
82- groups = []
83- for group in self.context.potemplate.translationgroups:
84- translator = group.query_translator(language)
85- # XXX: henninge 2009-09-09 bug=426745:
86- # The group and translator should be linkified.
87- if translator is None:
88- groups.append(_(u"%s translation group") % group.title)
89- else:
90- groups.append(_(u"%s assigned by %s") % (
91- translator.translator.displayname, group.title))
92-
93- # There are at most two translation groups, so just using 'and'
94- # is fine here.
95- statement = _(u"This translation is managed by %s.") % (
96- u" and ".join(groups))
97- else:
98- statement = _(u"No translation group has been assigned.")
99- return statement
100-
101- @property
102- def number_of_plural_forms(self):
103- """The number of plural forms for the language or 1 if not known."""
104- if self.context.language.pluralforms is not None:
105- return self.context.language.pluralforms
106- return 1
107-
108- @property
109- def plural_expression(self):
110- """The plural expression for this language or the empty string."""
111- if self.context.language.pluralexpression is not None:
112- return self.context.language.pluralexpression
113- return ""
114-
115- def _initializeShowOption(self):
116- # Get any value given by the user
117- self.show = self.request.form_ng.getOne('show')
118- self.search_text = self.request.form_ng.getOne('search')
119- if self.search_text is not None:
120- self.show = 'all'
121-
122- # Functions that deliver the correct message counts for each
123- # valid option value.
124- count_functions = {
125- 'all': self.context.messageCount,
126- 'translated': self.context.translatedCount,
127- 'untranslated': self.context.untranslatedCount,
128- 'new_suggestions': self.context.unreviewedCount,
129- 'changed_in_ubuntu': self.context.updatesCount,
130- }
131-
132- if self.show not in count_functions:
133- self.show = self.DEFAULT_SHOW
134-
135- self.shown_count = count_functions[self.show]()
136-
137- def _buildBatchNavigator(self):
138- """Construct a BatchNavigator of POTMsgSets and return it."""
139-
140- # Changing the "show" option resets batching.
141- old_show_option = self.request.form_ng.getOne('old_show')
142- show_option_changed = (
143- old_show_option is not None and old_show_option != self.show)
144- if show_option_changed:
145- # Start will be 0 by default.
146- force_start = True
147- else:
148- force_start = False
149- return POFileBatchNavigator(self._getSelectedPOTMsgSets(),
150- self.request, size=self.DEFAULT_SIZE,
151- transient_parameters=["old_show"],
152- force_start=force_start)
153-
154- def _handleShowAll(self):
155- """Get `POTMsgSet`s when filtering for "all" (but possibly searching).
156-
157- Normally returns all `POTMsgSet`s for this `POFile`, but also handles
158- search requests which act as a separate form of filtering.
159- """
160- if self.search_text is None:
161- return self.context.potemplate.getPOTMsgSets()
162-
163- if len(self.search_text) <= 1:
164- self.request.response.addWarningNotification(
165- "Please try searching for a longer string.")
166- return self.context.potemplate.getPOTMsgSets()
167-
168- return self.context.findPOTMsgSetsContaining(text=self.search_text)
169-
170- def _getSelectedPOTMsgSets(self):
171- """Return a list of the POTMsgSets that will be rendered."""
172- # The set of message sets we get is based on the selection of kind
173- # of strings we have in our form.
174- get_functions = {
175- 'all': self._handleShowAll,
176- 'translated': self.context.getPOTMsgSetTranslated,
177- 'untranslated': self.context.getPOTMsgSetUntranslated,
178- 'new_suggestions': self.context.getPOTMsgSetWithNewSuggestions,
179- 'changed_in_ubuntu':
180- self.context.getPOTMsgSetDifferentTranslations,
181- }
182-
183- if self.show not in get_functions:
184- raise UnexpectedFormData('show = "%s"' % self.show)
185-
186- # We cannot listify the results to avoid additional count queries,
187- # because we could end up with a list of more than 32000 items with
188- # an average list of 5000 items.
189- # The batch system will slice the list of items so we will fetch only
190- # the exact number of entries we need to render the page.
191- return get_functions[self.show]()
192-
193- @property
194- def messages(self):
195- """The list of TranslatableMessages to show."""
196- last = None
197- messages = []
198- for potmsgset in self.batchnav.currentBatch():
199- assert (last is None or
200- potmsgset.getSequence(
201- self.context.potemplate) >= last.getSequence(
202- self.context.potemplate)), (
203- "POTMsgSets on page not in ascending sequence order")
204- last = potmsgset
205-
206- messages.append(
207- self.context.makeTranslatableMessage(potmsgset))
208- return messages
209-
210-
211 class POFileView(LaunchpadView):
212 """A basic view for a POFile"""
213
214
215=== removed file 'lib/lp/translations/browser/tests/pofile-base-views.txt'
216--- lib/lp/translations/browser/tests/pofile-base-views.txt 2011-12-24 17:49:30 +0000
217+++ lib/lp/translations/browser/tests/pofile-base-views.txt 1970-01-01 00:00:00 +0000
218@@ -1,117 +0,0 @@
219-POFileBaseView
220-==============
221-
222-POFileBaseView provides different basic information about a POFile and a list
223-of its content as TranslatableMessage objects.
224-
225- >>> from lp.services.webapp.servers import LaunchpadTestRequest
226- >>> from lp.translations.browser.pofile import POFileBaseView
227-
228- >>> potemplate = factory.makePOTemplate()
229- >>> pofile = factory.makePOFile('eo', potemplate)
230-
231- >>> view = POFileBaseView(pofile, LaunchpadTestRequest())
232- >>> view.initialize()
233-
234-The view provides a statement to be displayed to the user about the
235-permissions the user has on the POFile. When not logged in, the user cannot
236-work on translations.
237-
238- >>> print view.permission_statement
239- You are not logged in. Please log in to work on translations.
240-
241-So we'd better log in.
242-
243- >>> login('foo.bar@canonical.com')
244- >>> view = POFileBaseView(pofile, LaunchpadTestRequest())
245- >>> view.initialize()
246- >>> print view.permission_statement
247- You have full access to this translation.
248-
249-The view also provides more detailed information about what the user can do.
250-
251- >>> print view.user_can_edit
252- True
253- >>> print view.user_can_suggest
254- True
255-
256-The view has information about the languages plural forms:
257-
258- >>> print view.number_of_plural_forms
259- 2
260- >>> print view.plural_expression
261- n != 1
262-
263-The view also know about the contributers to the translations in this POFile
264-but currently there have not been any contributions yet.
265-
266- >>> print view.contributors
267- ()
268-
269-So let's make a contribution.
270-
271- >>> contributor = factory.makePerson(displayname="Contri Butor")
272- >>> potmsgset = factory.makePOTMsgSet(potemplate, sequence=1)
273- >>> translation = factory.makeCurrentTranslationMessage(pofile, potmsgset,
274- ... translator=contributor, reviewer=contributor,
275- ... translations=['A translation made by a contributor.'])
276- >>> view = POFileBaseView(pofile, LaunchpadTestRequest())
277- >>> view.initialize()
278- >>> print view.contributors[0].displayname
279- Contri Butor
280-
281-The view has a list of all translations.
282-
283- >>> print view.messages[0].getCurrentTranslation().msgstr0.translation
284- A translation made by a contributor.
285-
286-The view can also tell us about the translation group but the pofile is not
287-yet managed by a translation group.
288-
289- >>> print view.translation_group
290- None
291-
292-The view makes a nice statement about this fact, too.
293-
294- >>> print view.translation_groups_statement
295- No translation group has been assigned.
296-
297-So let's create one and let it manage the translations.
298-
299- >>> group = factory.makeTranslationGroup(title="Test Translators")
300- >>> potemplate.product.translationgroup = group
301- >>> view = POFileBaseView(pofile, LaunchpadTestRequest())
302- >>> view.initialize()
303- >>> print view.translation_group.title
304- Test Translators
305-
306-Who is assigned to do translations into this language? Nobody so far.
307-
308- >>> print view.translator
309- None
310-
311-Let's change that. A single person can be a tanslator
312-
313- >>> translator = factory.makeTranslator('eo', group, contributor)
314- >>> view = POFileBaseView(pofile, LaunchpadTestRequest())
315- >>> view.initialize()
316- >>> print view.translator.displayname
317- Contri Butor
318-
319-See what statement the view makes now.
320-
321- >>> print view.translation_groups_statement
322- This translation is managed by Contri Butor assigned by Test Translators.
323-
324-Neither the group nor the translator have managed to setup some documentation.
325-
326- >>> view.has_any_documentation
327- False
328-
329-But now the group finally got around to it.
330-
331- >>> group.translation_guide_url = "https://launchpad.net/"
332- >>> view = POFileBaseView(pofile, LaunchpadTestRequest())
333- >>> view.initialize()
334- >>> view.has_any_documentation
335- True
336
337=== modified file 'lib/lp/translations/browser/tests/test_pofile_view.py'
338--- lib/lp/translations/browser/tests/test_pofile_view.py 2012-01-01 02:58:52 +0000
339+++ lib/lp/translations/browser/tests/test_pofile_view.py 2012-02-15 21:27:19 +0000
340@@ -3,13 +3,6 @@
341
342 __metaclass__ = type
343
344-from datetime import (
345- datetime,
346- timedelta,
347- )
348-
349-import pytz
350-
351 from lp.app.errors import UnexpectedFormData
352 from lp.services.webapp.servers import LaunchpadTestRequest
353 from lp.testing import (
354@@ -22,135 +15,24 @@
355 DatabaseFunctionalLayer,
356 ZopelessDatabaseLayer,
357 )
358-from lp.translations.browser.pofile import (
359- POFileBaseView,
360- POFileTranslateView,
361- )
362+from lp.translations.browser.pofile import POFileTranslateView
363 from lp.translations.enums import TranslationPermission
364
365
366-class TestPOFileBaseViewFiltering(TestCaseWithFactory):
367- """Test POFileBaseView filtering functions."""
368-
369- layer = ZopelessDatabaseLayer
370-
371- def gen_now(self):
372- now = datetime.now(pytz.UTC)
373- while True:
374- yield now
375- now += timedelta(milliseconds=1)
376-
377- def setUp(self):
378- super(TestPOFileBaseViewFiltering, self).setUp()
379- self.now = self.gen_now().next
380- self.potemplate = self.factory.makePOTemplate()
381- self.pofile = self.factory.makePOFile('eo', self.potemplate)
382-
383- # Create a number of POTMsgsets in different states.
384- # An untranslated message.
385- self.untranslated = self.factory.makePOTMsgSet(
386- self.potemplate, sequence=1)
387- # A translated message.
388- self.translated = self.factory.makePOTMsgSet(
389- self.potemplate, sequence=2)
390- self.factory.makeCurrentTranslationMessage(
391- self.pofile, self.translated)
392- # A translated message with a new suggestion.
393- self.new_suggestion = self.factory.makePOTMsgSet(
394- self.potemplate, sequence=3)
395- now = self.now()
396- self.factory.makeCurrentTranslationMessage(
397- pofile=self.pofile, potmsgset=self.new_suggestion,
398- date_created=now, date_reviewed=now)
399- now = self.now()
400- self.factory.makeSuggestion(
401- pofile=self.pofile, potmsgset=self.new_suggestion,
402- date_created=now)
403- # An upstream that was changed in Ubuntu.
404- self.changed = self.factory.makePOTMsgSet(self.potemplate, sequence=4)
405- now = self.now()
406- ubuntu_translation = self.factory.makeSuggestion(
407- pofile=self.pofile, potmsgset=self.changed, date_created=now)
408- ubuntu_translation.is_current_ubuntu = True
409- now = self.now()
410- self.factory.makeCurrentTranslationMessage(
411- pofile=self.pofile, potmsgset=self.changed, date_created=now,
412- date_reviewed=now)
413-
414- # Update statistics so that shown_count returns correct values.
415- self.pofile.updateStatistics()
416-
417- def _assertEqualPOTMsgSets(self, expected, messages):
418- self.assertEqual(expected, [tm.potmsgset for tm in messages])
419-
420- def test_show_all_messages(self):
421- # The default is to show all messages.
422- view = POFileBaseView(self.pofile, LaunchpadTestRequest())
423- view.initialize()
424- self.assertEqual('all', view.DEFAULT_SHOW)
425- self.assertEqual(view.DEFAULT_SHOW, view.show)
426- self.assertEqual(4, view.shown_count)
427- self._assertEqualPOTMsgSets(
428- [self.untranslated, self.translated,
429- self.new_suggestion, self.changed],
430- view.messages)
431-
432- def test_show_translated(self):
433- form = {'show': 'translated'}
434- view = POFileBaseView(self.pofile, LaunchpadTestRequest(form=form))
435- view.initialize()
436- self.assertEqual(3, view.shown_count)
437- self._assertEqualPOTMsgSets(
438- [self.translated, self.new_suggestion, self.changed],
439- view.messages)
440-
441- def test_show_untranslated(self):
442- form = {'show': 'untranslated'}
443- view = POFileBaseView(self.pofile, LaunchpadTestRequest(form=form))
444- view.initialize()
445- self.assertEqual(1, view.shown_count)
446- self._assertEqualPOTMsgSets([self.untranslated], view.messages)
447-
448- def test_show_new_suggestions(self):
449- form = {'show': 'new_suggestions'}
450- view = POFileBaseView(self.pofile, LaunchpadTestRequest(form=form))
451- view.initialize()
452- self.assertEqual(1, view.shown_count)
453- self._assertEqualPOTMsgSets([self.new_suggestion], view.messages)
454-
455- def test_show_changed_in_ubuntu(self):
456- form = {'show': 'changed_in_ubuntu'}
457- view = POFileBaseView(self.pofile, LaunchpadTestRequest(form=form))
458- view.initialize()
459- self.assertEqual(1, view.shown_count)
460- self._assertEqualPOTMsgSets(
461- [self.changed], view.messages)
462-
463- def test_show_invalid_filter(self):
464- # Invalid filter strings default to showing all messages.
465- form = {'show': 'foo_bar'}
466- view = POFileBaseView(self.pofile, LaunchpadTestRequest(form=form))
467- view.initialize()
468- self.assertEqual(view.DEFAULT_SHOW, view.show)
469- self._assertEqualPOTMsgSets(
470- [self.untranslated, self.translated,
471- self.new_suggestion, self.changed],
472- view.messages)
473-
474-
475-class TestInvalidFilteringMixin:
476+class TestPOFileTranslateViewInvalidFiltering(TestCaseWithFactory):
477 """Test how POFile views reacts to malformed GET requests.
478
479 Since any number of parameters can be entered throug the URL, the view
480 should be robust about them and not produce OOPSes. This is achieved by
481 raising UnexpectedFormData which is communicated to the user instead of
482 being recorded as an OOPS.
483-
484- POFileBaseView and POFileTranslateView implement this separately, so
485- two test cases are needed.
486 """
487+ layer = ZopelessDatabaseLayer
488+ view_class = POFileTranslateView
489
490- view_class = None
491+ def setUp(self):
492+ super(TestPOFileTranslateViewInvalidFiltering, self).setUp()
493+ self.pofile = self.factory.makePOFile('eo')
494
495 def _test_parameter_list(self, parameter_name):
496 # When a parameter is entered multiple times in an URL, it will be
497@@ -170,33 +52,10 @@
498 self._test_parameter_list('show')
499
500
501-class TestPOFileBaseViewInvalidFiltering(TestCaseWithFactory,
502- TestInvalidFilteringMixin):
503- """Test for POFilleBaseView."""
504- layer = ZopelessDatabaseLayer
505- view_class = POFileBaseView
506-
507- def setUp(self):
508- super(TestPOFileBaseViewInvalidFiltering, self).setUp()
509- self.pofile = self.factory.makePOFile('eo')
510-
511-
512-class TestPOFileTranslateViewInvalidFiltering(TestCaseWithFactory,
513- TestInvalidFilteringMixin):
514- """Test for POFilleTranslateView."""
515+class TestPOFileTranslateViewDocumentation(TestCaseWithFactory):
516 layer = ZopelessDatabaseLayer
517 view_class = POFileTranslateView
518
519- def setUp(self):
520- super(TestPOFileTranslateViewInvalidFiltering, self).setUp()
521- self.pofile = self.factory.makePOFile('eo')
522-
523-
524-class DocumentationScenarioMixin:
525- """Tests for `POFileBaseView` and `POFileTranslateView`."""
526- # The view class that's being tested.
527- view_class = None
528-
529 def _makeLoggedInUser(self):
530 """Create a user, and log in as that user."""
531 email = self.factory.getUniqueString() + '@example.com'
532@@ -431,18 +290,6 @@
533 self.assertNotIn(language.englishname, view.documentation_link_bubble)
534
535
536-class TestPOFileBaseViewDocumentation(TestCaseWithFactory,
537- DocumentationScenarioMixin):
538- layer = ZopelessDatabaseLayer
539- view_class = POFileBaseView
540-
541-
542-class TestPOFileTranslateViewDocumentation(TestCaseWithFactory,
543- DocumentationScenarioMixin):
544- layer = ZopelessDatabaseLayer
545- view_class = POFileTranslateView
546-
547-
548 class TestBrowser(BrowserTestCase):
549
550 layer = DatabaseFunctionalLayer
551
552=== removed file 'lib/lp/translations/browser/tests/test_translatablemessage_view.py'
553--- lib/lp/translations/browser/tests/test_translatablemessage_view.py 2012-01-01 02:58:52 +0000
554+++ lib/lp/translations/browser/tests/test_translatablemessage_view.py 1970-01-01 00:00:00 +0000
555@@ -1,97 +0,0 @@
556-# Copyright 2009 Canonical Ltd. This software is licensed under the
557-# GNU Affero General Public License version 3 (see the file LICENSE).
558-
559-__metaclass__ = type
560-
561-from lp.services.webapp.servers import LaunchpadTestRequest
562-from lp.testing import TestCaseWithFactory
563-from lp.testing.layers import LaunchpadZopelessLayer
564-from lp.translations.browser.browser_helpers import text_to_html
565-from lp.translations.browser.translatablemessage import (
566- TranslatableMessageView,
567- )
568-from lp.translations.model.translatablemessage import TranslatableMessage
569-
570-
571-class TestTranslatableMessageView(TestCaseWithFactory):
572- """Test ProductSeries view in translations facet."""
573-
574- layer = LaunchpadZopelessLayer
575-
576- def setUp(self):
577- # Create a POTMsgSet and a POFile to create a TranslatableMessage
578- # from. Create the view from the message.
579- super(TestTranslatableMessageView, self).setUp()
580- self.potemplate = self.factory.makePOTemplate()
581- self.potmsgset = self.factory.makePOTMsgSet(
582- self.potemplate, sequence=1, singular=u"English singular")
583- self.pofile = self.factory.makePOFile('eo', self.potemplate)
584- self.message = None
585-
586- def _create_view(self):
587- self.message = TranslatableMessage(self.potmsgset, self.pofile)
588- return TranslatableMessageView(self.message,
589- LaunchpadTestRequest())
590-
591- def test_empty_message(self):
592- # View information for an empty message.
593- view = self._create_view()
594- info = view.current_translation
595-
596- self.assertEqual(None, info['translator'])
597- self.assertEqual(u'', info['translator_class'])
598- self.assertContentEqual(
599- [{'plural': u"", 'text': u"(no translation yet)"}],
600- info['translations'])
601- self.assertEqual(u'current_empty', info['translation_class'])
602-
603- def test_singular_message(self):
604- # View information for a singular message.
605- translator = self.factory.makePerson()
606- self.factory.makeCurrentTranslationMessage(
607- self.pofile, self.potmsgset,
608- translations=[u'foo'], translator=translator)
609- view = self._create_view()
610- info = view.current_translation
611-
612- self.assertEqual(u'English singular', view.singular_text)
613- self.assertEqual(translator, info['translator'])
614- self.assertEqual('translator_singular', info['translator_class'])
615- self.assertContentEqual(
616- [{'plural': u"", 'text': u"foo"}],
617- info['translations'])
618- self.assertEqual(u'current', info['translation_class'])
619-
620- def test_plural_message(self):
621- # View information for a message with plural.
622- self.potmsgset.updatePluralForm(u'English plural')
623- translator = self.factory.makePerson()
624- self.factory.makeCurrentTranslationMessage(
625- self.pofile, self.potmsgset,
626- translations=[u'foo', u'bar'], translator=translator)
627- view = self._create_view()
628- info = view.current_translation
629-
630- self.assertEqual(u'English plural', view.plural_text)
631- self.assertEqual(translator, info['translator'])
632- self.assertEqual('translator_plural', info['translator_class'])
633- self.assertContentEqual(
634- [{'plural': u"Plural 0:", 'text': u"foo"},
635- {'plural': u"Plural 1:", 'text': u"bar"}],
636- info['translations'])
637- self.assertEqual(u'current', info['translation_class'])
638-
639- def test_browser_message(self):
640- # Special treatment on some characters for browser display.
641- TRANSLATION = u"foo \nbar"
642- translator = self.factory.makePerson()
643- self.potmsgset.updatePluralForm(u'English plural')
644- self.factory.makeCurrentTranslationMessage(
645- self.pofile, self.potmsgset,
646- translations=[TRANSLATION], translator=translator)
647- view = self._create_view()
648- info = view.current_translation
649-
650- self.assertEqual(
651- text_to_html(TRANSLATION, self.potmsgset.flags),
652- info['translations'][0]['text'])
653
654=== removed file 'lib/lp/translations/browser/translatablemessage.py'
655--- lib/lp/translations/browser/translatablemessage.py 2011-12-24 17:49:30 +0000
656+++ lib/lp/translations/browser/translatablemessage.py 1970-01-01 00:00:00 +0000
657@@ -1,85 +0,0 @@
658-# Copyright 2009 Canonical Ltd. This software is licensed under the
659-# GNU Affero General Public License version 3 (see the file LICENSE).
660-
661-"""Browser code for Product Series Languages."""
662-
663-__metaclass__ = type
664-
665-__all__ = ['TranslatableMessageView']
666-
667-from lp.services.webapp import LaunchpadView
668-from lp.translations.browser.browser_helpers import text_to_html
669-
670-
671-class TranslatableMessageView(LaunchpadView):
672- """View class to render an `ITranslatableMessage`."""
673-
674- @property
675- def label(self):
676- """The form label."""
677- return 'Translate messge %d into %s' % (
678- self.context.sequence,
679- self.context.pofile.language.englishname)
680-
681- @property
682- def page_title(self):
683- """The page title."""
684- return self.label
685-
686- @property
687- def singular_text(self):
688- """HTML version of the singular msgid."""
689- return text_to_html(self.context.potmsgset.singular_text,
690- self.context.potmsgset.flags)
691-
692- @property
693- def plural_text(self):
694- """HTML version of the plural msgid."""
695- return text_to_html(self.context.potmsgset.plural_text,
696- self.context.potmsgset.flags)
697-
698- def _translation_info(self, plural, text):
699- """Build a dictionary with 'plural' and 'text' keys."""
700- return {'plural': plural,
701- 'text': text_to_html(text, self.context.potmsgset.flags)}
702-
703- def _make_translation_info(self, translationmessage):
704- """Prepare translation information for the given message."""
705- if self.context.has_plural_forms:
706- translations = [
707- self._translation_info(u"Plural %d:" % index, msgstr)
708- for index, msgstr in enumerate(
709- translationmessage.translations)]
710- translator_class = "translator_plural"
711- else:
712- translations = [self._translation_info(
713- "", translationmessage.msgstr0.translation)]
714- translator_class = "translator_singular"
715- return {
716- 'translator': translationmessage.submitter,
717- 'translation_class': 'current',
718- 'translator_class': translator_class,
719- 'translations': translations,
720- }
721-
722- @property
723- def current_translation(self):
724- """Information about the current translation prepared for display.
725-
726- :returns: A dictionary with the following keys:
727- translator - The IPerson object of the translator or None.
728- translations - A list of dictionaries with the following keys:
729- plural - The plural label to explain this form or an empty string
730- text - The actual translation text as HTML
731- translator_class - the css class to use for the translator
732- translation_class - The css class to use for the translation
733- """
734- current = self.context.getCurrentTranslation()
735- if current is None:
736- return {'translator': None,
737- 'translation_class': 'current_empty',
738- 'translator_class': '',
739- 'translations': [
740- self._translation_info(u"", u"(no translation yet)")]}
741- return self._make_translation_info(current)
742-
743
744=== modified file 'lib/lp/translations/configure.zcml'
745--- lib/lp/translations/configure.zcml 2011-12-24 17:49:30 +0000
746+++ lib/lp/translations/configure.zcml 2012-02-15 21:27:19 +0000
747@@ -515,11 +515,6 @@
748 permission="launchpad.Admin"
749 set_attributes="commenttext sourcecomment filereferences flagscomment"/>
750 </class>
751- <class
752- class="lp.translations.model.translatablemessage.TranslatableMessage">
753- <allow
754- interface="lp.translations.interfaces.translatablemessage.ITranslatableMessage"/>
755- </class>
756
757 <!-- LanguagePack -->
758
759
760=== modified file 'lib/lp/translations/interfaces/pofile.py'
761--- lib/lp/translations/interfaces/pofile.py 2012-01-01 02:58:52 +0000
762+++ lib/lp/translations/interfaces/pofile.py 2012-02-15 21:27:19 +0000
763@@ -210,12 +210,6 @@
764 set down using the condition.
765 """
766
767- def makeTranslatableMessage(potmsgset):
768- """Factory method for an `ITranslatableMessage` object.
769-
770- :param potmsgset: The `IPOTMsgSet` to combine this pofile with.
771- """
772-
773 def export(ignore_obsolete=False, export_utf8=False):
774 """Export this PO file as string.
775
776
777=== removed file 'lib/lp/translations/interfaces/translatablemessage.py'
778--- lib/lp/translations/interfaces/translatablemessage.py 2011-12-24 16:54:44 +0000
779+++ lib/lp/translations/interfaces/translatablemessage.py 1970-01-01 00:00:00 +0000
780@@ -1,115 +0,0 @@
781-# Copyright 2009 Canonical Ltd. This software is licensed under the
782-# GNU Affero General Public License version 3 (see the file LICENSE).
783-
784-# pylint: disable-msg=E0211,E0213
785-
786-from zope.interface import (
787- Attribute,
788- Interface,
789- )
790-from zope.schema import (
791- Bool,
792- Int,
793- )
794-
795-from lp import _
796-
797-
798-__metaclass__ = type
799-
800-__all__ = [
801- 'ITranslatableMessage',
802- ]
803-
804-class ITranslatableMessage(Interface):
805- """An IPOTMsgSet in the context of a certain IPOFile."""
806-
807- pofile = Attribute("The IPOFile")
808- potmsgset = Attribute("The POTMsgset")
809-
810- sequence = Int(
811- title=_("Sequence number within the POTemplate."),
812- required=True)
813-
814- is_obsolete = Bool(
815- title=_("This TranslatableMessage is obsolete"),
816- required=True)
817-
818- is_untranslated = Bool(
819- title=_("The current translation is empty"),
820- required=True)
821-
822- is_current_diverged = Bool(
823- title=_("The current translation is diverged"),
824- required=True)
825-
826- is_current_imported = Bool(
827- title=_("The current translation is used upstream"),
828- required=True)
829-
830- has_plural_forms = Bool(
831- title=_("There is an English plural string"),
832- required=True)
833-
834- number_of_plural_forms = Int(
835- title=_("Number of plural forms in the target language"),
836- required=True)
837-
838- def getCurrentTranslation():
839- """Get the TranslationMessage that holds the current translation."""
840-
841- def getImportedTranslation():
842- """Get the TranslationMessage that is marked as current-upstream.
843-
844- This can be None if there is no such message, or it can be
845- identical to the current Ubuntu translation.
846- """
847-
848- def getSharedTranslation():
849- """Get the TranslationMessage that is marked as shared.
850-
851- This can be None if there is no such message or it can be identical
852- to the current translation if the current translation is shared.
853- """
854-
855- def getAllSuggestions():
856- """Return an iterator over all suggested translations."""
857-
858- def getUnreviewedSuggestions():
859- """Return an iterator over unreviewed suggested translations.
860-
861- Return those translation messages that have a creation date newer
862- than the review date of the current message (have not been reviewed).
863- """
864-
865- def getDismissedSuggestions(include_dismissed=True):
866- """Return an iterator over dismissed suggested translations.
867-
868- Return those translation messages that have a creation date older
869- than the review date of the current message (have been dismissed).
870- """
871-
872- def getExternalTranslations():
873- """Return an iterator over external translations.
874-
875- External translations are translations for the same English string
876- in other products and source packages.
877- """
878-
879- def getExternalSuggestions():
880- """Return an iterator over externally suggested translations.
881-
882- External suggested translations are suggestions for the same English
883- string in other products and source packages.
884- """
885-
886- def dismissAllSuggestions(reviewer, lock_timestamp):
887- """Dismiss all suggestions.
888-
889- :param reviewer: the person that is doing the dismissal.
890- :param lock_timestamp: the timestamp when we checked the values we
891- want to update.
892-
893- Raises TranslationConflict if two edits happen simultaneously.
894- """
895-
896
897=== modified file 'lib/lp/translations/model/pofile.py'
898--- lib/lp/translations/model/pofile.py 2011-12-30 06:14:56 +0000
899+++ lib/lp/translations/model/pofile.py 2012-02-15 21:27:19 +0000
900@@ -102,7 +102,6 @@
901 credits_message_str,
902 POTMsgSet,
903 )
904-from lp.translations.model.translatablemessage import TranslatableMessage
905 from lp.translations.model.translationimportqueue import collect_import_info
906 from lp.translations.model.translationmessage import (
907 make_plurals_sql_fragment,
908@@ -329,10 +328,6 @@
909 """See `IPOFile`."""
910 return self.language.englishname
911
912- def makeTranslatableMessage(self, potmsgset):
913- """See `IPOFile`."""
914- return TranslatableMessage(potmsgset, self)
915-
916 def markChanged(self, translator=None, timestamp=None):
917 """See `IPOFile`."""
918 if timestamp is None:
919
920=== removed file 'lib/lp/translations/model/translatablemessage.py'
921--- lib/lp/translations/model/translatablemessage.py 2010-12-14 16:57:36 +0000
922+++ lib/lp/translations/model/translatablemessage.py 1970-01-01 00:00:00 +0000
923@@ -1,134 +0,0 @@
924-# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
925-# GNU Affero General Public License version 3 (see the file LICENSE).
926-
927-"""Implementation for `ITranslatableMessage`."""
928-
929-__metaclass__ = type
930-
931-__all__ = [
932- 'TranslatableMessage',
933- ]
934-
935-from zope.interface import implements
936-
937-from lp.translations.interfaces.translatablemessage import (
938- ITranslatableMessage,
939- )
940-
941-
942-class TranslatableMessage(object):
943- """See `ITranslatableMessage`."""
944- implements(ITranslatableMessage)
945-
946- potmsgset = None
947- pofile = None
948- sequence = 0
949-
950- def __init__(self, potmsgset, pofile):
951- """Create a new TranslatableMessage object.
952-
953- :param potmsgset: The `IPOTMsgSet` instance that this object refers
954- to.
955- :param pofile: The `IPOFile` instance that the potmsgset is used
956- with.
957-
958- Both potmsgset and pofile must be related, meaning they refer to the
959- same `IPOTemplate` instance.
960- """
961- assert pofile.potemplate.getPOTMsgSetByID(potmsgset.id) != None, (
962- "POTMsgSet and POFile must refer to the same POTemplate.")
963-
964- self.potmsgset = potmsgset
965- self.pofile = pofile
966- self.sequence = potmsgset.getSequence(pofile.potemplate)
967- self.potemplate = pofile.potemplate
968- self.language = pofile.language
969-
970- self._current_translation = self.potmsgset.getCurrentTranslation(
971- self.potemplate, self.language, self.potemplate.translation_side)
972-
973- @property
974- def is_obsolete(self):
975- """See `ITranslatableMessage`"""
976- return self.sequence == 0
977-
978- @property
979- def is_untranslated(self):
980- """See `ITranslatableMessage`"""
981- if self._current_translation is None:
982- return True
983- return self._current_translation.is_empty
984-
985- @property
986- def is_current_diverged(self):
987- """See `ITranslatableMessage`"""
988- if self._current_translation is None:
989- return False
990- return self._current_translation.potemplate == self.potemplate
991-
992- @property
993- def is_current_imported(self):
994- """See `ITranslatableMessage`"""
995- if self._current_translation is None:
996- return False
997- return self._current_translation.is_current_upstream
998-
999- @property
1000- def has_plural_forms(self):
1001- """See `ITranslatableMessage`"""
1002- return self.potmsgset.msgid_plural is not None
1003-
1004- @property
1005- def number_of_plural_forms(self):
1006- """See `ITranslatableMessage`"""
1007- if self.has_plural_forms:
1008- return self.pofile.plural_forms
1009- else:
1010- return 1
1011-
1012- def getCurrentTranslation(self):
1013- """See `ITranslatableMessage`"""
1014- return self._current_translation
1015-
1016- def getImportedTranslation(self):
1017- """See `ITranslatableMessage`"""
1018- return self.potmsgset.getOtherTranslation(
1019- self.language, self.potemplate.translation_side)
1020-
1021- def getSharedTranslation(self):
1022- """See `ITranslatableMessage`"""
1023- return self.potmsgset.getSharedTranslation(
1024- self.language, self.potemplate.translation_side)
1025-
1026- def getAllSuggestions(self):
1027- """See `ITranslatableMessage`"""
1028- return self.potmsgset.getLocalTranslationMessages(
1029- self.potemplate, self.language,
1030- include_dismissed=True, include_unreviewed=True)
1031-
1032- def getUnreviewedSuggestions(self):
1033- """See `ITranslatableMessage`"""
1034- return self.potmsgset.getLocalTranslationMessages(
1035- self.potemplate, self.language,
1036- include_dismissed=False, include_unreviewed=True)
1037-
1038- def getDismissedSuggestions(self):
1039- """See `ITranslatableMessage`"""
1040- return self.potmsgset.getLocalTranslationMessages(
1041- self.potemplate, self.language,
1042- include_dismissed=True, include_unreviewed=False)
1043-
1044- def getExternalTranslations(self):
1045- """See `ITranslatableMessage`"""
1046- lang = self.language
1047- return self.potmsgset.getExternallyUsedTranslationMessages(lang)
1048-
1049- def getExternalSuggestions(self):
1050- """See `ITranslatableMessage`"""
1051- lang = self.language
1052- return self.potmsgset.getExternallySuggestedTranslationMessages(lang)
1053-
1054- def dismissAllSuggestions(self, reviewer, lock_timestamp):
1055- """See `ITranslatableMessage`"""
1056- self.potmsgset.dismissAllSuggestions(
1057- self.pofile, reviewer, lock_timestamp)
1058
1059=== modified file 'lib/lp/translations/tests/test_pofile.py'
1060--- lib/lp/translations/tests/test_pofile.py 2011-12-30 06:14:56 +0000
1061+++ lib/lp/translations/tests/test_pofile.py 2012-02-15 21:27:19 +0000
1062@@ -14,7 +14,6 @@
1063 getAdapter,
1064 getUtility,
1065 )
1066-from zope.interface.verify import verifyObject
1067 from zope.security.proxy import removeSecurityProxy
1068
1069 from lp.app.enums import ServiceUsage
1070@@ -26,9 +25,6 @@
1071 from lp.testing.layers import ZopelessDatabaseLayer
1072 from lp.translations.interfaces.pofile import IPOFileSet
1073 from lp.translations.interfaces.side import ITranslationSideTraitsSet
1074-from lp.translations.interfaces.translatablemessage import (
1075- ITranslatableMessage,
1076- )
1077 from lp.translations.interfaces.translationcommonformat import (
1078 ITranslationFileData,
1079 )
1080@@ -2038,12 +2034,6 @@
1081 self.pofile = self.factory.makePOFile('eo')
1082 self.potemplate = self.pofile.potemplate
1083
1084- def test_makeTranslatableMessage(self):
1085- # TranslatableMessages can be created from the PO file
1086- potmsgset = self.factory.makePOTMsgSet(self.potemplate)
1087- message = self.pofile.makeTranslatableMessage(potmsgset)
1088- verifyObject(ITranslatableMessage, message)
1089-
1090 def _createMessageSet(self, testmsg):
1091 # Create a message set from the test data.
1092 potmsgset = self.factory.makePOTMsgSet(
1093
1094=== removed file 'lib/lp/translations/tests/test_translatablemessage.py'
1095--- lib/lp/translations/tests/test_translatablemessage.py 2012-01-01 02:58:52 +0000
1096+++ lib/lp/translations/tests/test_translatablemessage.py 1970-01-01 00:00:00 +0000
1097@@ -1,229 +0,0 @@
1098-# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
1099-# GNU Affero General Public License version 3 (see the file LICENSE).
1100-
1101-"""Unit tests for `TranslatableMessage`."""
1102-
1103-__metaclass__ = type
1104-
1105-from datetime import (
1106- datetime,
1107- timedelta,
1108- )
1109-
1110-import pytz
1111-import transaction
1112-from zope.component import getUtility
1113-
1114-from lp.app.enums import ServiceUsage
1115-from lp.testing import TestCaseWithFactory
1116-from lp.testing.layers import ZopelessDatabaseLayer
1117-from lp.translations.interfaces.potemplate import IPOTemplateSet
1118-from lp.translations.model.translatablemessage import TranslatableMessage
1119-
1120-
1121-class TestTranslatableMessageBase:
1122- """Common setup for `TranslatableMessage`."""
1123-
1124- layer = ZopelessDatabaseLayer
1125-
1126- def setUp(self):
1127- """Create common objects for all tests.
1128-
1129- Arranges for a `ProductSeries` with `POTemplate` and
1130- `POTMsgSet`, as well as a Esperanto translation.
1131- """
1132- super(TestTranslatableMessageBase, self).setUp()
1133- self.product = self.factory.makeProduct(
1134- translations_usage=ServiceUsage.LAUNCHPAD)
1135- self.trunk = self.product.getSeries('trunk')
1136- self.potemplate = self.factory.makePOTemplate(
1137- productseries=self.trunk)
1138- self.potmsgset = self.factory.makePOTMsgSet(
1139- potemplate=self.potemplate)
1140- self.pofile = self.factory.makePOFile(
1141- potemplate=self.potemplate, language_code='eo')
1142-
1143- def _createTranslation(self, translation=None, is_current_ubuntu=False,
1144- is_current_upstream=False, is_diverged=False,
1145- date_updated=None):
1146- if translation is not None:
1147- translation = [translation]
1148-
1149- if is_current_upstream:
1150- message = self.factory.makeCurrentTranslationMessage(
1151- pofile=self.pofile, potmsgset=self.potmsgset,
1152- translations=translation,
1153- current_other=is_current_ubuntu,
1154- diverged=is_diverged,
1155- date_created=date_updated,
1156- date_reviewed=date_updated)
1157- else:
1158- message = self.factory.makeSuggestion(
1159- pofile=self.pofile, potmsgset=self.potmsgset,
1160- translations=translation, date_created=date_updated)
1161- message.is_current_ubuntu = is_current_ubuntu
1162- self.assertFalse(
1163- is_diverged,
1164- "Diverging message to a template it's not current in.")
1165-
1166- return message
1167-
1168-
1169-class TestTranslatableMessage(TestTranslatableMessageBase,
1170- TestCaseWithFactory):
1171- """Test of `TranslatableMessage` properties and methods."""
1172-
1173- def test_sequence(self):
1174- # After instantiation, the sequence number from the potmsgset is
1175- # available.
1176- self.potmsgset.setSequence(self.potemplate, 1)
1177- message = TranslatableMessage(self.potmsgset, self.pofile)
1178- self.assertEqual(1, message.sequence)
1179-
1180- def test_is_obsolete(self):
1181- # A message is obsolete if the sequence number is 0.
1182- message = TranslatableMessage(self.potmsgset, self.pofile)
1183- self.assertFalse(message.is_obsolete)
1184-
1185- self.potmsgset.setSequence(self.potemplate, 0)
1186- message = TranslatableMessage(self.potmsgset, self.pofile)
1187- self.assertTrue(message.is_obsolete)
1188-
1189- def test_is_untranslated(self):
1190- translation = self._createTranslation('', is_current_ubuntu=True)
1191- message = TranslatableMessage(self.potmsgset, self.pofile)
1192- self.assertTrue(message.is_untranslated)
1193-
1194- def test_is_current_diverged(self):
1195- translation = self._createTranslation(
1196- is_current_upstream=True, is_diverged=True)
1197- message = TranslatableMessage(self.potmsgset, self.pofile)
1198- self.assertTrue(message.is_current_diverged)
1199-
1200- def test_is_current_imported(self):
1201- translation = self._createTranslation(is_current_ubuntu=True,
1202- is_current_upstream=True)
1203- message = TranslatableMessage(self.potmsgset, self.pofile)
1204- self.assertTrue(message.is_current_imported)
1205-
1206- def test_has_plural_forms(self):
1207- message = TranslatableMessage(self.potmsgset, self.pofile)
1208- self.assertFalse(message.has_plural_forms)
1209-
1210- self.potmsgset.updatePluralForm(u"fooplural")
1211- self.assertTrue(message.has_plural_forms)
1212-
1213- def test_number_of_plural_forms(self):
1214- # eo has 2 plural forms, sr has 3
1215- self.potmsgset.updatePluralForm(u"fooplural")
1216- message = TranslatableMessage(self.potmsgset, self.pofile)
1217- self.assertEqual(2, message.number_of_plural_forms)
1218-
1219- sr_pofile = self.factory.makePOFile(
1220- potemplate=self.potemplate, language_code='sr')
1221- message = TranslatableMessage(self.potmsgset, sr_pofile)
1222- self.assertEqual(3, message.number_of_plural_forms)
1223-
1224- def test_getCurrentTranslation(self):
1225- translation = self._createTranslation(is_current_upstream=True)
1226- message = TranslatableMessage(self.potmsgset, self.pofile)
1227- current = message.getCurrentTranslation()
1228- self.assertEqual(translation, current)
1229-
1230- def test_getImportedTranslation(self):
1231- translation = self._createTranslation(is_current_ubuntu=True)
1232-
1233- message = TranslatableMessage(self.potmsgset, self.pofile)
1234- imported = message.getImportedTranslation()
1235- self.assertEqual(translation, imported)
1236-
1237- def test_getSharedTranslation(self):
1238- translation = self._createTranslation(is_current_upstream=True)
1239- message = TranslatableMessage(self.potmsgset, self.pofile)
1240- shared = message.getSharedTranslation()
1241- self.assertEqual(translation, shared)
1242-
1243-
1244-class TestTranslatableMessageExternal(TestTranslatableMessageBase,
1245- TestCaseWithFactory):
1246- """Test of `TranslatableMessage` methods for external translations."""
1247-
1248- def setUp(self):
1249- # Create a potmsgset with the same msg id in another product
1250- super(TestTranslatableMessageExternal, self).setUp()
1251- common_msgid = self.potmsgset.singular_text
1252- self.external_potemplate = self.factory.makePOTemplate()
1253- product = self.external_potemplate.productseries.product
1254- product.translations_usage = ServiceUsage.LAUNCHPAD
1255- self.external_potmsgset = self.factory.makePOTMsgSet(
1256- potemplate=self.external_potemplate,
1257- singular=common_msgid)
1258- self.external_pofile = self.factory.makePOFile(
1259- potemplate=self.external_potemplate, language_code='eo')
1260-
1261- self.external_suggestion = self.factory.makeCurrentTranslationMessage(
1262- pofile=self.external_pofile, potmsgset=self.external_potmsgset)
1263- self.external_current = self.factory.makeCurrentTranslationMessage(
1264- pofile=self.external_pofile, potmsgset=self.external_potmsgset)
1265-
1266- self.message = TranslatableMessage(self.potmsgset, self.pofile)
1267-
1268- self._refreshSuggestiveTemplatesCache()
1269-
1270- def _refreshSuggestiveTemplatesCache(self):
1271- """Refresh the `SuggestivePOTemplate` cache."""
1272- getUtility(IPOTemplateSet).populateSuggestivePOTemplatesCache()
1273-
1274- def test_getExternalTranslations(self):
1275- transaction.commit()
1276- externals = self.message.getExternalTranslations()
1277- self.assertContentEqual([self.external_current], externals)
1278-
1279- def test_getExternalSuggestions(self):
1280- transaction.commit()
1281- externals = self.message.getExternalSuggestions()
1282- self.assertContentEqual([self.external_suggestion], externals)
1283-
1284-
1285-class TestTranslatableMessageSuggestions(TestTranslatableMessageBase,
1286- TestCaseWithFactory):
1287- """Test of `TranslatableMessage` methods for getting suggestions."""
1288-
1289- def gen_now(self):
1290- now = datetime.now(pytz.UTC)
1291- while True:
1292- yield now
1293- now += timedelta(milliseconds=1)
1294-
1295- def setUp(self):
1296- super(TestTranslatableMessageSuggestions, self).setUp()
1297- self.now = self.gen_now().next
1298- self.suggestion1 = self._createTranslation(date_updated=self.now())
1299- self.current = self._createTranslation(
1300- is_current_upstream=True, date_updated=self.now())
1301- self.suggestion2 = self._createTranslation(date_updated=self.now())
1302- self.message = TranslatableMessage(self.potmsgset, self.pofile)
1303-
1304- def test_getAllSuggestions(self):
1305- # There are three different methods to return.
1306- suggestions = self.message.getAllSuggestions()
1307- self.assertContentEqual(
1308- [self.suggestion1, self.suggestion2], suggestions)
1309-
1310- def test_getDismissedSuggestions(self):
1311- # There are three different methods to return.
1312- suggestions = self.message.getDismissedSuggestions()
1313- self.assertContentEqual([self.suggestion1], suggestions)
1314-
1315- def test_getUnreviewedSuggestions(self):
1316- # There are three different methods to return.
1317- suggestions = self.message.getUnreviewedSuggestions()
1318- self.assertContentEqual([self.suggestion2], suggestions)
1319-
1320- def test_dismissAllSuggestions(self):
1321- # Add a suggestion that is newer than the current translation and
1322- # dismiss it. Also show that getSuggestions only returns translations
1323- # that are newer than the current one unless only_new is set to False.
1324- self.message.dismissAllSuggestions(self.potemplate.owner, self.now())
1325- suggestions = self.message.getUnreviewedSuggestions()
1326- self.assertContentEqual([], suggestions)