launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #03122
[Merge] lp:~adeuring/launchpad/js-translation-2 into lp:launchpad
Abel Deuring has proposed merging lp:~adeuring/launchpad/js-translation-2 into lp:launchpad with lp:~adeuring/launchpad/js-translation as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~adeuring/launchpad/js-translation-2/+merge/55575
This branch finishes the prepeataion of the translation sharing
settings page for source packages for its "YUIfication".
The page now always includes links to the translation configuration
page of the upstream product and to the translation sync page of
the upstream series. If no packaing link exists, i.e., if no
upstream product series is defined, a dummy link is rendered.
The second change of lib/lp/translations/browser/sourcepackage.py
(@@ -140,10 +142,10 @@) mimics the change from a branch submitted
by Henning earlier today which follows William's reminder to properly
use structured() when HTML data is generated in view class methods.
The third change (@@ -155,12 +157,13 @@) applies this reminder to
another method. This change is not strictly necessary, since the
text was already passed through cgi.escape(), but I think we should
be consistent in the way we generate HTML data in a view class.
The fourth hunk (@@ -339,10 +342,10 @@) lets anther method use
structured().
The two latter changes are a bit questionable, because they let
structured() expand an href attribute, which eequries in theory
a special treatment of characters like '"', '<', '>', but I
don't think this is a real issue, because we insert only Launchpad
URLs, and AFAIK we don't use these characters anywhere.
test: ./bin/test translations -vvt test_sharing_details
no lint
--
https://code.launchpad.net/~adeuring/launchpad/js-translation-2/+merge/55575
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~adeuring/launchpad/js-translation-2 into lp:launchpad.
=== modified file 'lib/lp/translations/browser/sourcepackage.py'
--- lib/lp/translations/browser/sourcepackage.py 2011-03-30 15:33:01 +0000
+++ lib/lp/translations/browser/sourcepackage.py 2011-03-30 15:33:22 +0000
@@ -11,8 +11,6 @@
'SourcePackageTranslationSharingStatus',
]
-import cgi
-
from zope.publisher.interfaces import NotFound
from canonical.launchpad.webapp import (
@@ -29,6 +27,10 @@
from lp.registry.interfaces.sourcepackage import ISourcePackage
from lp.services.features import getFeatureFlag
from lp.translations.browser.poexportrequest import BaseExportView
+from lp.translations.browser.product import ProductTranslationsMenu
+from lp.translations.browser.productseries import (
+ ProductSeriesTranslationsMenu,
+ )
from lp.translations.browser.translations import TranslationsMixin
from lp.translations.browser.translationsharing import (
TranslationSharingDetailsMixin,
@@ -125,10 +127,10 @@
'No upstream templates have been found yet. Please follow '
'the import process by going to the '
'<a href="%s">Translation Import Queue</a> of the '
- 'upstream project series.' %(
+ 'upstream project series.',
canonical_url(
self.context.productseries, rootsite='translations',
- view_name="+imports"))))
+ view_name="+imports")))
if self.is_merge_job_running:
self.request.response.addInfoNotification(
'Translations are currently being linked by a background '
@@ -140,12 +142,13 @@
if self.has_upstream_branch:
# Normally should use BranchFormatterAPI(branch).link(None), but
# on this page, that information is redundant.
- title = cgi.escape(self.upstream_branch.unique_name)
+ title = self.upstream_branch.unique_name
url = canonical_url(self.upstream_branch)
else:
title = ''
url = '#'
- return '<a class="sprite branch link" href="%s">%s</a>' % (url, title)
+ return structured(
+ '<a class="sprite branch link" href="%s">%s</a>', url, title)
def makeConfigCompleteCSS(self, complete, disable, lowlight):
if complete:
@@ -324,10 +327,10 @@
css_class = 'sprite %s unseen' % icon
else:
css_class = 'sprite %s' % icon
- return (
+ return structured(
'<a id="%s" class="%s" href="%s">'
- '<span class="invisible-link">%s</span></a>'
- % (id, css_class, url, text))
+ '<span class="invisible-link">%s</span></a>',
+ id, css_class, url, text)
def edit_branch_link(self, id, icon, text):
"""The HTML link to define or edit a product series branch.
@@ -357,3 +360,75 @@
def change_branch_link(self):
"""The HTML link to change a product series branch."""
return self.edit_branch_link('change-branch', 'edit', 'Change branch')
+
+ def getConfigureTranslationsLink(self, id):
+ """The HTML link to the product translation configuration page.
+ """
+ packaging = self.context.direct_packaging
+ if packaging is not None:
+ productseries = self.context.direct_packaging.productseries
+ product = productseries.product
+ product_menu = ProductTranslationsMenu(product)
+ settings_link = product_menu.settings()
+ url = '%s/%s' % (canonical_url(product), settings_link.target)
+ hidden = not settings_link.enabled
+ else:
+ url = '#'
+ hidden = True
+ icon = 'edit'
+ text = 'Configure Upstream Translations'
+ return self.icon_link(id, icon, url, text, hidden)
+
+ @property
+ def configure_translations_link_unconfigured(self):
+ """The HTML link to the product translation configuration page.
+
+ Variant for the status "not configured"
+ """
+ id = 'upstream-translations-unconfigured'
+ return self.getConfigureTranslationsLink(id)
+
+ @property
+ def configure_translations_link_configured(self):
+ """The HTML link to the product translation configuration page.
+
+ Variant for the status "configured"
+ """
+ id = 'upstream-translations-configured'
+ return self.getConfigureTranslationsLink(id)
+
+ def getTranslationSynchronisationLink(self, id):
+ """The HTML link to the series translation synchronisation page.
+ """
+ packaging = self.context.direct_packaging
+ if packaging is not None:
+ productseries = self.context.direct_packaging.productseries
+ productseries_menu = ProductSeriesTranslationsMenu(productseries)
+ settings_link = productseries_menu.settings()
+ url = '%s/%s' % (
+ canonical_url(productseries), settings_link.target)
+ hidden = not settings_link.enabled
+ else:
+ url = '#'
+ hidden = True
+ icon = 'edit'
+ text = 'Configure Translation Synchronisation'
+ return self.icon_link(id, icon, url, text, hidden)
+
+ @property
+ def translation_sync_link_unconfigured(self):
+ """The HTML link to the series translation synchronisation page.
+
+ Variant for the status "not configured"
+ """
+ id = 'translation-synchronisation-unconfigured'
+ return self.getTranslationSynchronisationLink(id)
+
+ @property
+ def translation_sync_link_configured(self):
+ """The HTML link to the series translation synchronisation page.
+
+ Variant for the status "configured"
+ """
+ id = 'translation-synchronisation-configured'
+ return self.getTranslationSynchronisationLink(id)
=== modified file 'lib/lp/translations/browser/tests/test_sharing_details.py'
--- lib/lp/translations/browser/tests/test_sharing_details.py 2011-03-30 15:33:01 +0000
+++ lib/lp/translations/browser/tests/test_sharing_details.py 2011-03-30 15:33:22 +0000
@@ -419,9 +419,13 @@
Upstream source branch is.*
Change branch
Translations are not enabled on the upstream project.
+ Configure Upstream Translations
Translations are enabled on the upstream project.
+ Configure Upstream Translations
Automatic synchronization of translations is not enabled.
- Automatic synchronization of translations is enabled.""",
+ Configure Translation Synchronisation
+ Automatic synchronization of translations is enabled.
+ Configure Translation Synchronisation""",
extract_text(checklist))
self.assertElementText(
browser, 'packaging-incomplete',
@@ -611,6 +615,7 @@
if real_links:
match = (
r'^http://translations.launchpad.dev/.*/trunk/\+linkbranch$')
+
def link_matcher(url):
return re.search(match, url)
else:
@@ -679,6 +684,118 @@
self.assertBranchLinks(
browser.contents, real_links=True, enabled=True)
+ def assertConfigurationLink(self, contents, real_link, enabled, id,
+ expected_url):
+ if real_link:
+
+ def link_matcher(url):
+ return re.search(expected_url, url)
+ else:
+ link_matcher = '#'
+ if enabled:
+ css_class = 'sprite edit'
+ else:
+ css_class = 'sprite edit unseen'
+ matcher = Tag(id, 'a', attrs={
+ 'id': id,
+ 'href': link_matcher,
+ 'class': css_class})
+ self.assertThat(contents, HTMLContains(matcher))
+
+ def assertTranslationConfigurationLink(self, contents, real_link,
+ enabled, id):
+ expected_url = (
+ r'^http://translations.launchpad.dev/.*/'
+ '\+configure-translations$')
+ self.assertConfigurationLink(
+ contents, real_link, enabled, id, expected_url)
+
+ def assertAllTranslationConfigurationLinks(self, contents, real_link,
+ enabled):
+ self.assertTranslationConfigurationLink(
+ contents, real_link, enabled,
+ id='upstream-translations-unconfigured')
+ self.assertTranslationConfigurationLink(
+ contents, real_link, enabled,
+ id='upstream-translations-configured')
+
+ def test_configure_translations_link__no_packaging_link(self):
+ # If no packaging link exists,
+ # configure_translations_link_unconfigured and
+ # configure_translations_link_configured return hidden dummy
+ # links.
+ sourcepackage = self._makeSourcePackage()
+ browser = self._getSharingDetailsViewBrowser(sourcepackage)
+ self.assertAllTranslationConfigurationLinks(
+ browser.contents, real_link=False, enabled=False)
+
+ def test_configure_translations_link__packaging_link__anon_user(self):
+ # If no packaging link exists,
+ # configure_translations_link_unconfigured and
+ # configure_translations_link_configured return hidden links
+ # pointing to the configuration page for anonymous users.
+ packaging = self.factory.makePackagingLink(in_ubuntu=True)
+ self.configureUpstreamProject(
+ productseries=packaging.productseries)
+ browser = self._getSharingDetailsViewBrowser(packaging.sourcepackage)
+ self.assertAllTranslationConfigurationLinks(
+ browser.contents, real_link=True, enabled=False)
+
+ def test_configure_translations_link__packaging_link__unprivileged_user(
+ self):
+ # If no packaging link exists,
+ # configure_translations_link_unconfigured and
+ # configure_translations_link_configured return hidden links
+ # pointing to the configuration page for users which cannot configure
+ # the product series.
+ packaging = self.factory.makePackagingLink(in_ubuntu=True)
+ self.configureUpstreamProject(
+ productseries=packaging.productseries)
+ browser = self._getSharingDetailsViewBrowser(
+ packaging.sourcepackage, user=self.factory.makePerson())
+ self.assertAllTranslationConfigurationLinks(
+ browser.contents, real_link=True, enabled=False)
+
+ def test_configure_translations_link__packaging_link__privileged_user(
+ self):
+ # If no packaging link exists,
+ # configure_translations_link_unconfigured and
+ # configure_translations_link_configured return visible links
+ # pointing to the configuration page for users which can configure
+ # the product series.
+ packaging = self.factory.makePackagingLink(in_ubuntu=True)
+ self.configureUpstreamProject(
+ productseries=packaging.productseries)
+ browser = self._getSharingDetailsViewBrowser(
+ packaging.sourcepackage, user=packaging.productseries.owner)
+ self.assertAllTranslationConfigurationLinks(
+ browser.contents, real_link=True, enabled=True)
+
+ def assertTranslationSynchronisationLink(self, contents, real_link,
+ enabled, id):
+ expected_url = (
+ r'https://translations.launchpad.dev/.*/trunk'
+ '/+translations-settings')
+ self.assertConfigurationLink(
+ contents, real_link, enabled, id, expected_url)
+
+ def assertAllTranslationSynchronisationLinks(self, contents, real_link,
+ enabled):
+ self.assertTranslationSynchronisationLink(
+ contents, real_link, enabled,
+ id='translation-synchronisation-unconfigured')
+ self.assertTranslationSynchronisationLink(
+ contents, real_link, enabled,
+ id='translation-synchronisation-configured')
+
+ def test_upstream_sync_link__no_packaging_link(self):
+ # If no packaing link exists, translation_sync_link_unconfigured
+ # and translation_sync_link_configured return hidden dummy links.
+ sourcepackage = self._makeSourcePackage()
+ browser = self._getSharingDetailsViewBrowser(sourcepackage)
+ self.assertAllTranslationSynchronisationLinks(
+ browser.contents, real_link=False, enabled=False)
+
class TestTranslationSharingDetailsViewNotifications(TestCaseWithFactory,
ConfigureScenarioMixin):
=== modified file 'lib/lp/translations/templates/sourcepackage-sharing-details.pt'
--- lib/lp/translations/templates/sourcepackage-sharing-details.pt 2011-03-30 15:33:01 +0000
+++ lib/lp/translations/templates/sourcepackage-sharing-details.pt 2011-03-30 15:33:22 +0000
@@ -50,40 +50,36 @@
id="branch-incomplete">
No source branch exists for the upstream series.
<span id="branch-incomplete-picker">
- <a tal:replace="structure view/new_branch_link" />
+ <a tal:replace="structure view/new_branch_link/escapedtext" />
</span>
</li>
<li tal:attributes="class view/branch_complete_class"
id="branch-complete">
Upstream source branch is
<span id="branch-complete-picker">
- <a tal:replace="structure view/branch_link">lp:gimp</a>
- <a tal:replace="structure view/change_branch_link" />
+ <a tal:replace="structure view/branch_link/escapedtext">lp:gimp</a>
+ <a tal:replace="structure view/change_branch_link/escapedtext" />
</span>
</li>
<li tal:attributes="class view/translations_disabled_class"
id="translation-incomplete">
Translations are not enabled on the upstream project.
- <a tal:condition="view/is_packaging_configured"
- tal:replace="structure context/productseries/product/menu:translations/settings/fmt:icon" />
+ <a tal:replace="structure view/configure_translations_link_unconfigured/escapedtext" />
</li>
<li tal:attributes="class view/translations_enabled_class"
id="translation-complete">
Translations are enabled on the upstream project.
- <a tal:condition="view/is_packaging_configured"
- tal:replace="structure context/productseries/product/menu:translations/settings/fmt:icon" />
+ <a tal:replace="structure view/configure_translations_link_configured/escapedtext" />
</li>
<li tal:attributes="class view/upstream_sync_disabled_class"
id="upstream-sync-incomplete">
Automatic synchronization of translations is not enabled.
- <a tal:condition="view/is_packaging_configured"
- tal:replace="structure context/productseries/menu:translations/settings/fmt:icon" />
+ <a tal:replace="structure view/translation_sync_link_unconfigured/escapedtext" />
</li>
<li tal:attributes="class view/upstream_sync_enabled_class"
id="upstream-sync-complete">
Automatic synchronization of translations is enabled.
- <a tal:condition="view/is_packaging_configured"
- tal:replace="structure context/productseries/menu:translations/settings/fmt:icon" />
+ <a tal:replace="structure view/translation_sync_link_configured/escapedtext" />
</li>
</ul>
</dd>