Many thanks for the review. Here is the diff. === modified file 'lib/lp/translations/browser/serieslanguage.py' --- lib/lp/translations/browser/serieslanguage.py 2009-12-11 01:12:22 +0000 +++ lib/lp/translations/browser/serieslanguage.py 2009-12-11 16:09:04 +0000 @@ -14,6 +14,7 @@ from canonical.cachedproperty import cachedproperty from canonical.launchpad.webapp import LaunchpadView +from canonical.launchpad.webapp.tales import PersonFormatterAPI from canonical.launchpad.webapp.batching import BatchNavigator from canonical.launchpad.webapp.publisher import Navigation from lp.translations.interfaces.distroserieslanguage import ( @@ -26,9 +27,12 @@ IProductSeriesLanguage) -class SeriesLanguageView(LaunchpadView): - """View class to render translation status for an `IDistroSeries` - and `IProductSeries`""" +class BaseSeriesLanguageView(LaunchpadView): + """View base class to render translation status for an + `IDistroSeries` and `IProductSeries` + + This class should not be directly instantiated. + """ pofiles = None label = "Translatable templates" @@ -36,7 +40,9 @@ parent = None translationgroup = None - def initialize(self): + def initialize(self, series, translationgroup): + self.series = series + self.translationgroup = translationgroup self.form = self.request.form self.batchnav = BatchNavigator( @@ -46,14 +52,20 @@ self.pofiles = self.context.getPOFilesFor( self.batchnav.currentBatch()) - @cachedproperty + @property def translation_group(self): - """Is there a translation group for these translations.""" + """Return the translation group for these translations. + + Return None if there's no translation group for them. + """ return self.translationgroup @cachedproperty def translation_team(self): - """Is there a translation team for these translations.""" + """Return the translation team for these translations. + + Return None if there's no translation team for them. + """ if self.translation_group is not None: team = self.translation_group.query_translator( self.context.language) @@ -62,98 +74,80 @@ return team @property - def show_not_logged_in(self): - """Should we display a notice that user is not logged in?""" - return self.user is None + def access_level_description(self): + if self.user is None: + return ("You are not logged in. Please log in to work " + + "on translations.") - @property - def show_no_license(self): - """Should we display a notice that licence was not accepted?""" - if self.show_not_logged_in: - return False translations_person = ITranslationsPerson(self.user) - return not translations_person.translations_relicensing_agreement - - @property - def show_full_edit(self): - """Should we display a notice that user is not logged in?""" - if (self.show_not_logged_in or - self.show_no_license): - return False - - sample_pofile = self.pofiles[0] - if sample_pofile is None: - return False - - return sample_pofile.canEditTranslations(self.user) - - @property - def show_can_suggest(self): - """Should we display a notice that user is not logged in?""" - if (self.show_not_logged_in or - self.show_no_license or - self.show_full_edit): - return False - - sample_pofile = self.pofiles[0] - if sample_pofile is None: - return False - - return sample_pofile.canAddSuggestions(self.user) - - @property - def show_only_managers(self): - """Should we display a notice that user is not logged in?""" - if (self.show_not_logged_in or - self.show_no_license or - self.show_full_edit or - self.show_can_suggest): - return False - - sample_pofile = self.pofiles[0] - if sample_pofile is None: - return False - - if (sample_pofile.translationpermission == - TranslationPermission.CLOSED): - return True - else: - return False - - @property - def show_no_managers(self): - """Should we display a notice that user is not logged in?""" - if (self.show_not_logged_in or - self.show_no_license or - self.show_full_edit or - self.show_can_suggest or - self.show_only_managers): - return False + translations_contact_link = None + + if self.translation_team: + translations_contact_link = PersonFormatterAPI( + self.translation_team.translator).link(None) + elif self.translation_group: + translations_contact_link = PersonFormatterAPI( + self.translation_group.owner).link(None) + + if not translations_person.translations_relicensing_agreement: + translation_license_url = PersonFormatterAPI( + translations_person).url() + '/translations/+licensing' + return ("To make translations in Launchpad you need to " + + "agree with the " + + "Translations licensing.") % ( + translation_license_url) + + sample_pofile = self.pofiles[0] + if sample_pofile is not None: + if sample_pofile.canEditTranslations(self.user): + return "You can add and review translations." + + if sample_pofile.canAddSuggestions(self.user): + return ("Your suggestions will be held for review by " + + "the managers of these translations. If you " + + "need help, or your translations are not being " + + "reviewed, please get in touch with " + + "%s") % translations_contact_link + + permission = sample_pofile.translationpermission + if permission == TranslationPermission.CLOSED: + return ("These templates can be translated only by " + + "its managers") + + # no-managers if self.translation_team is None: - return True - else: - return False - - -class DistroSeriesLanguageView(SeriesLanguageView, LaunchpadView): + return ("Since there is nobody to manage translation " + + "approvals into this language, your cannot add " + + "new suggestions. If you are interested in making " + + "translations, please contact %s") % ( + translations_contact_link) + + raise AssertionError( + "BUG! Couldn't identify the user's access level for these " + "translations.") + + +class DistroSeriesLanguageView(BaseSeriesLanguageView, LaunchpadView): """View class to render translation status for an `IDistroSeries`.""" def initialize(self): - self.series = self.context.distroseries - SeriesLanguageView.initialize(self) + series = self.context.distroseries + super(DistroSeriesLanguageView, self).initialize( + series=series, + translationgroup=series.distribution.translationgroup) self.parent = self.series.distribution - self.translationgroup = self.series.distribution.translationgroup - - -class ProductSeriesLanguageView(SeriesLanguageView, LaunchpadView): + + +class ProductSeriesLanguageView(BaseSeriesLanguageView, LaunchpadView): """View class to render translation status for an `IProductSeries`.""" def initialize(self): - self.series = self.context.productseries - SeriesLanguageView.initialize(self) + series = self.context.productseries + super(ProductSeriesLanguageView, self).initialize( + series=series, + translationgroup=series.product.translationgroup) self.context.recalculateCounts() self.parent = self.series.product - self.translationgroup = self.series.product.translationgroup class DistroSeriesLanguageNavigation(Navigation): === modified file 'lib/lp/translations/browser/tests/test_productserieslanguage_views.py' --- lib/lp/translations/browser/tests/test_productserieslanguage_views.py 2009-07-17 00:26:05 +0000 +++ lib/lp/translations/browser/tests/test_productserieslanguage_views.py 2009-12-11 16:09:04 +0000 @@ -7,7 +7,7 @@ from zope.component import getUtility -from lp.translations.browser.productserieslanguage import ( +from lp.translations.browser.serieslanguage import ( ProductSeriesLanguageView) from lp.translations.interfaces.translator import ITranslatorSet from canonical.launchpad.webapp.servers import LaunchpadTestRequest === modified file 'lib/lp/translations/stories/standalone/xx-serieslanguage-index.txt' --- lib/lp/translations/stories/standalone/xx-serieslanguage-index.txt 2009-12-11 01:03:25 +0000 +++ lib/lp/translations/stories/standalone/xx-serieslanguage-index.txt 2009-12-11 16:15:33 +0000 @@ -1,4 +1,4 @@ -Product of distribution release series language overview +Product or distribution release series language overview ======================================================== These pages are used by translators for accessing all templates in a @@ -17,19 +17,20 @@ Portuguese (Brazil) (pt_BR) : Translations : Series trunk : Evolution Since there is no translation team to manage Portuguese (Brazil) language -in the Evolution's translation group, all user will be informed about it +in the Evolution's translation group, all users will be informed about it and pointed to the translation group owner. - >>> print extract_text(find_tag_by_id(browser.contents, 'group-team-info')) + >>> print extract_text(find_tag_by_id( + ... browser.contents, 'group-team-info')) There is no team to manage Evolution ... translations to ... To set one up, please get in touch with Carlos Perelló Marín. Anonymous users are informed that in order to make translations they need to login first. - >>> browser.getLink('log in').click() - >>> print browser.url - http://translations.launchpad.dev/evolution/trunk/+lang/pt_BR/+login + >>> print extract_text( + ... find_tag_by_id(browser.contents, 'translation-access-level')) + You are not logged in. Please log in to work on translations... Authenticated users will see information about what they can do in these translations. Things like review, only add suggestion or no @@ -39,53 +40,61 @@ informed about this fact and will be able to add translations without requiring a review. - >>> user_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+lang/es') - >>> print extract_text(find_tag_by_id(user_browser.contents, 'group-team-info')) + >>> user_browser.open( + ... 'http://translations.launchpad.dev/ubuntu/hoary/+lang/es') + >>> print extract_text( + ... find_tag_by_id(user_browser.contents, 'group-team-info')) There is no translation group to manage Ubuntu translations. -A translation group is created for Ubuntu, togheter with a translation -person for managing Ubuntu Spanish translations. -The translation policy is also defined as RESTRICTED +Create a translation group for Ubuntu, togheter with a translation +person for managing Ubuntu Spanish translations and set translation +policy to RESTRICTED. +This is done to so see what the page will look like when they exist. - >>> from canonical.launchpad.ftests import login, logout >>> from zope.component import getUtility >>> from canonical.launchpad.interfaces import ILaunchpadCelebrities >>> from lp.translations.interfaces.translationgroup import ( ... TranslationPermission) >>> login('