← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/series-breadcrumbs-later into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/series-breadcrumbs-later into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #183433 in Launchpad itself: "product series code tab goes to product overview rather than series specific page"
  https://bugs.launchpad.net/launchpad/+bug/183433
  Bug #428665 in Launchpad itself: "Source-package-related pages have mismatched context and application tabs"
  https://bugs.launchpad.net/launchpad/+bug/428665
  Bug #573779 in Launchpad itself: "Site header does not accurately represent section"
  https://bugs.launchpad.net/launchpad/+bug/573779
  Bug #771527 in Launchpad itself: "No 'Answers' facet for DistroSeries"
  https://bugs.launchpad.net/launchpad/+bug/771527

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/series-breadcrumbs-later/+merge/242010
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/series-breadcrumbs-later into lp:launchpad.
=== modified file 'lib/canonical/launchpad/icing/css/layout.css'
--- lib/canonical/launchpad/icing/css/layout.css	2012-03-21 02:32:44 +0000
+++ lib/canonical/launchpad/icing/css/layout.css	2014-11-27 00:36:30 +0000
@@ -91,9 +91,14 @@
     color: #000;
     font-weight: bold;
     font-size: 30px;
-    line-height: 34px;
+    line-height: 30px;
     margin: 0;
     }
+div.watermark-apps-portlet h2.secondary {
+    font-weight: normal;
+    font-size: 20px;
+    line-height: 26px;
+    }
 .watermark-apps-portlet ul.facetmenu {
     margin-top: 6px;
     margin-left: -0.5em;

=== modified file 'lib/lp/app/browser/launchpad.py'
--- lib/lp/app/browser/launchpad.py	2014-11-24 04:31:14 +0000
+++ lib/lp/app/browser/launchpad.py	2014-11-27 00:36:30 +0000
@@ -310,6 +310,10 @@
                         Breadcrumb(
                             breadcrumb.context, rootsite=facet.rootsite,
                             text=facet.text))
+                    # Ensure that all remaining breadcrumbs are
+                    # themselves faceted.
+                    for remaining_crumb in breadcrumbs[idx + 1:]:
+                        remaining_crumb.rootsite_override = facet.rootsite
                     break
         if len(breadcrumbs) > 0:
             page_crumb = self.makeBreadcrumbForRequestedPage()
@@ -346,7 +350,7 @@
         facet = queryUtility(IFacet, name=get_facet(view))
         if facet is not None:
             default_views.append(facet.default_view)
-        if view.__name__ not in default_views:
+        if hasattr(view, '__name__') and view.__name__ not in default_views:
             title = getattr(view, 'page_title', None)
             if title is None:
                 title = getattr(view, 'label', None)
@@ -369,13 +373,12 @@
         return len(self.items) > 1 and not has_major_heading
 
     @property
-    def heading_breadcrumb(self):
-        try:
-            return (
-                crumb for crumb in self.items
-                if IHeadingBreadcrumb.providedBy(crumb)).next()
-        except StopIteration:
-            return None
+    def heading_breadcrumbs(self):
+        crumbs = [
+            crumb for crumb in self.items
+            if IHeadingBreadcrumb.providedBy(crumb)]
+        assert len(crumbs) <= 2
+        return crumbs
 
     def heading(self):
         """Return the heading text for the page.
@@ -394,19 +397,25 @@
         heading = 'h1' if IMajorHeadingView.providedBy(self.context) else 'h2'
         # If there is actually no root context, then it's a top-level
         # context-less page so Launchpad.net is shown as the branding.
-        if self.heading_breadcrumb:
-            title = self.heading_breadcrumb.detail
+        crumbs = self.heading_breadcrumbs
+        if len(crumbs) >= 1:
+            title = crumbs[0].detail
         else:
             title = 'Launchpad.net'
         # For non-editable titles, generate the static heading.
-        return structured(
+        markup = structured(
             "<%(heading)s>%(title)s</%(heading)s>",
             heading=heading, title=title).escapedtext
+        if len(crumbs) >= 2:
+            markup += structured(
+                '\n<%(heading)s class="secondary">%(title)s</%(heading)s>',
+                heading=heading, title=crumbs[1].detail).escapedtext
+        return markup
 
     def logo(self):
         """Return the logo image for the top header breadcrumb's context."""
         logo_context = (
-            self.heading_breadcrumb.context if self.heading_breadcrumb
+            self.heading_breadcrumbs[0].context if self.heading_breadcrumbs
             else None)
         adapter = queryAdapter(logo_context, IPathAdapter, 'image')
         if logo_context != self.context.context and logo_context is not None:

=== modified file 'lib/lp/app/browser/tales.py'
--- lib/lp/app/browser/tales.py	2014-11-16 15:13:55 +0000
+++ lib/lp/app/browser/tales.py	2014-11-27 00:36:30 +0000
@@ -81,8 +81,8 @@
     IContextMenu,
     IFacetMenu,
     ILaunchBag,
+    ILaunchpadRoot,
     INavigationMenu,
-    IPrimaryContext,
     NoCanonicalUrl,
     )
 from lp.services.webapp.menu import (
@@ -276,13 +276,16 @@
 
     def _facet_menu(self):
         """Return the IFacetMenu related to the context."""
+        # XXX wgrant 2014-11-26: Manually instantiate a Hierarchy view
+        # to find the lowest IHeadingBreadcrumb that's in the title,
+        # ensuring that the facet tabs match what's above them. This
+        # whole class needs refactoring once the UI is stable.
+        from lp.app.browser.launchpad import Hierarchy
         try:
-            try:
-                context = IPrimaryContext(self._context).context
-            except TypeError:
-                # Could not adapt raises a type error.  If there was no
-                # way to adapt, then just use self._context.
-                context = self._context
+            context = self._context
+            crumbs = Hierarchy(context, self._request).heading_breadcrumbs
+            if crumbs:
+                context = crumbs[-1].context
             menu = nearest_adapter(context, IFacetMenu)
         except NoCanonicalUrl:
             menu = None

=== modified file 'lib/lp/app/templates/base-layout.pt'
--- lib/lp/app/templates/base-layout.pt	2014-11-16 15:13:55 +0000
+++ lib/lp/app/templates/base-layout.pt	2014-11-27 00:36:30 +0000
@@ -99,9 +99,9 @@
           <h2 tal:replace="structure view/@@+hierarchy/heading">
             Celso Providelo
           </h2>
-          <metal:heading_nav
-            use-macro="context/@@+base-layout-macros/application-buttons"/>
         </div>
+        <metal:heading_nav
+          use-macro="context/@@+base-layout-macros/application-buttons"/>
       </div>
 
       <div class="yui-t4"

=== modified file 'lib/lp/blueprints/stories/standalone/xx-overview.txt'
--- lib/lp/blueprints/stories/standalone/xx-overview.txt	2011-12-21 08:26:19 +0000
+++ lib/lp/blueprints/stories/standalone/xx-overview.txt	2014-11-27 00:36:30 +0000
@@ -50,8 +50,7 @@
 series as an example. To begin with, there are no blueprints listed on
 the blueprints page for 1.0:
 
-    >>> user_browser.open('http://launchpad.dev/firefox/1.0')
-    >>> user_browser.getLink('Blueprints').click()
+    >>> user_browser.open('http://blueprints.launchpad.dev/firefox/1.0')
     >>> main = find_main_content(user_browser.contents)
     >>> print extract_text(main).encode('ascii', 'backslashreplace')
     Blueprints for 1.0
@@ -114,8 +113,7 @@
 Now the blueprint listing for the 1.0 series includes an entry for our chosen
 blueprint. It also lists the milestone to which the blueprint is targeted:
 
-    >>> user_browser.open('http://launchpad.dev/firefox/1.0')
-    >>> user_browser.getLink('Blueprints').click()
+    >>> user_browser.open('http://blueprints.launchpad.dev/firefox/1.0')
     >>> main = find_main_content(user_browser.contents)
     >>> print extract_text(main).encode('ascii', 'backslashreplace')
     Blueprints for 1.0...
@@ -152,8 +150,7 @@
 series as an example. To begin with, there are no blueprints listed on the
 blueprints page for Grumpy:
 
-    >>> user_browser.open('http://launchpad.dev/ubuntu/grumpy')
-    >>> user_browser.getLink('Blueprints').click()
+    >>> user_browser.open('http://blueprints.launchpad.dev/ubuntu/grumpy')
     >>> main = find_main_content(user_browser.contents)
     >>> print extract_text(main).encode('ascii', 'backslashreplace')
     Blueprints for Grumpy
@@ -215,8 +212,7 @@
 Finally, the blueprint listing for Grumpy includes an entry for our chosen
 blueprint. It also lists the milestone to which the blueprint is targeted:
 
-    >>> user_browser.open('http://launchpad.dev/ubuntu/grumpy')
-    >>> user_browser.getLink('Blueprints').click()
+    >>> user_browser.open('http://blueprints.launchpad.dev/ubuntu/grumpy')
     >>> main = find_main_content(user_browser.contents)
     >>> print extract_text(main).encode('ascii', 'backslashreplace')
     Blueprints for Grumpy...

=== modified file 'lib/lp/bugs/stories/bugs/xx-bugs.txt'
--- lib/lp/bugs/stories/bugs/xx-bugs.txt	2014-02-25 09:43:29 +0000
+++ lib/lp/bugs/stories/bugs/xx-bugs.txt	2014-11-27 00:36:30 +0000
@@ -3,7 +3,7 @@
 
     >>> browser.open('http://localhost/ubuntu/hoary/+bugs')
     >>> print browser.title
-    Bugs : Hoary (5.04) : Ubuntu 
+    Hoary (5.04) : Bugs : Ubuntu 
 
 This page checks that we can see a list of bugs on the distributions, in
 this case Ubuntu.

=== modified file 'lib/lp/bugs/stories/bugs/xx-distrorelease-bugs-page.txt'
--- lib/lp/bugs/stories/bugs/xx-distrorelease-bugs-page.txt	2012-10-02 06:36:44 +0000
+++ lib/lp/bugs/stories/bugs/xx-distrorelease-bugs-page.txt	2014-11-27 00:36:30 +0000
@@ -5,7 +5,7 @@
 
     >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu/warty/+bugs')
     >>> anon_browser.title
-    'Bugs : Warty (4.10) : Ubuntu'
+    'Warty (4.10) : Bugs : Ubuntu'
 
     >>> find_tags_by_class(anon_browser.contents, 'buglisting-row') is not None
     True

=== modified file 'lib/lp/bugs/stories/patches-view/patches-view.txt'
--- lib/lp/bugs/stories/patches-view/patches-view.txt	2012-10-09 10:28:02 +0000
+++ lib/lp/bugs/stories/patches-view/patches-view.txt	2014-11-27 00:36:30 +0000
@@ -276,6 +276,6 @@
 The page title and other wording in the page reflects the contents.
 
     >>> print_location(anon_browser.contents)
-    Hierarchy: Patchy 1 > Series trunk > Bugs > Patch attachments in trunk
+    Hierarchy: Patchy 1 > Bugs > Series trunk > Patch attachments in trunk
     Tabs: ...
     Main heading: Patch attachments in trunk

=== modified file 'lib/lp/code/stories/branches/xx-distroseries-branches.txt'
--- lib/lp/code/stories/branches/xx-distroseries-branches.txt	2011-08-03 11:00:11 +0000
+++ lib/lp/code/stories/branches/xx-distroseries-branches.txt	2014-11-27 00:36:30 +0000
@@ -19,13 +19,6 @@
 
     >>> browser.open('http://launchpad.dev/mint/stable')
 
-The code tab is now enabled at the distribution series level.
-
-    >>> print_location_apps(browser.contents)
-    * Overview (selected) ...
-    * Code - http://code.launchpad.dev/mint/stable
-    ...
-
 Going to this page shows us a listing of all branches associated with that
 distribution series ordered by most recently changed first.
 

=== modified file 'lib/lp/registry/browser/distroseries.py'
--- lib/lp/registry/browser/distroseries.py	2014-11-24 01:20:26 +0000
+++ lib/lp/registry/browser/distroseries.py	2014-11-27 00:36:30 +0000
@@ -27,10 +27,7 @@
 from zope.component import getUtility
 from zope.event import notify
 from zope.formlib import form
-from zope.interface import (
-    implements,
-    Interface,
-    )
+from zope.interface import Interface
 from zope.lifecycleevent import ObjectCreatedEvent
 from zope.schema import (
     Choice,
@@ -93,7 +90,6 @@
 from lp.services.webapp.batching import BatchNavigator
 from lp.services.webapp.breadcrumb import Breadcrumb
 from lp.services.webapp.escaping import structured
-from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
 from lp.services.webapp.menu import (
     ApplicationMenu,
     enabled_with_permission,
@@ -202,7 +198,6 @@
 
 class DistroSeriesBreadcrumb(Breadcrumb):
     """Builds a breadcrumb for an `IDistroSeries`."""
-    implements(IMultiFacetedBreadcrumb)
 
     @property
     def text(self):

=== modified file 'lib/lp/registry/browser/productseries.py'
--- lib/lp/registry/browser/productseries.py	2014-11-24 01:20:26 +0000
+++ lib/lp/registry/browser/productseries.py	2014-11-27 00:36:30 +0000
@@ -136,7 +136,6 @@
 from lp.services.webapp.batching import BatchNavigator
 from lp.services.webapp.breadcrumb import Breadcrumb
 from lp.services.webapp.escaping import structured
-from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
 from lp.services.worlddata.helpers import browser_languages
 from lp.services.worlddata.interfaces.country import ICountry
 from lp.services.worlddata.interfaces.language import ILanguageSet
@@ -189,7 +188,6 @@
 
 class ProductSeriesBreadcrumb(Breadcrumb):
     """Builds a breadcrumb for an `IProductSeries`."""
-    implements(IMultiFacetedBreadcrumb)
 
     @property
     def text(self):

=== modified file 'lib/lp/registry/browser/sourcepackage.py'
--- lib/lp/registry/browser/sourcepackage.py	2014-11-24 03:49:26 +0000
+++ lib/lp/registry/browser/sourcepackage.py	2014-11-27 00:36:30 +0000
@@ -31,7 +31,6 @@
     Item,
     )
 from lazr.restful.interface import copy_field
-from lazr.restful.utils import smartquote
 from z3c.ptcompat import ViewPageTemplateFile
 from zope.component import (
     adapter,
@@ -41,10 +40,7 @@
 from zope.formlib.form import Fields
 from zope.formlib.interfaces import IInputWidget
 from zope.formlib.widgets import DropdownWidget
-from zope.interface import (
-    implements,
-    Interface,
-    )
+from zope.interface import Interface
 from zope.schema import (
     Choice,
     TextLine,
@@ -94,7 +90,7 @@
     )
 from lp.services.webapp.breadcrumb import Breadcrumb
 from lp.services.webapp.escaping import structured
-from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
+from lp.services.webapp.interfaces import IBreadcrumb
 from lp.services.webapp.publisher import LaunchpadView
 from lp.services.worlddata.helpers import browser_languages
 from lp.services.worlddata.interfaces.country import ICountry
@@ -203,11 +199,14 @@
 @adapter(ISourcePackage)
 class SourcePackageBreadcrumb(Breadcrumb):
     """Builds a breadcrumb for an `ISourcePackage`."""
-    implements(IMultiFacetedBreadcrumb)
 
     @property
     def text(self):
-        return smartquote('"%s" source package') % (self.context.name)
+        return IBreadcrumb(self.context.distroseries).text
+
+    @property
+    def inside(self):
+        return self.context.distribution_sourcepackage
 
 
 class SourcePackageFacets(StandardLaunchpadFacets):

=== modified file 'lib/lp/registry/stories/distroseries/xx-distroseries-index.txt'
--- lib/lp/registry/stories/distroseries/xx-distroseries-index.txt	2014-02-19 02:11:16 +0000
+++ lib/lp/registry/stories/distroseries/xx-distroseries-index.txt	2014-11-27 00:36:30 +0000
@@ -7,7 +7,7 @@
     >>> user_browser.open('http://launchpad.dev/ubuntu/hoary')
     >>> user_browser.getLink('Help translate').click()
     >>> print user_browser.title
-    Translations : Hoary (5.04) : Ubuntu
+    Hoary (5.04) : Translations : Ubuntu
 
 
 Registering information
@@ -120,7 +120,7 @@
     http://launchpad.dev/ubuntu/warty/+subscribe
 
     >>> print admin_browser.title
-    Subscribe : Bugs : Warty (4.10) : Ubuntu
+    Subscribe : Warty (4.10) : Bugs : Ubuntu
 
 
 Upstream packaging portlet

=== modified file 'lib/lp/registry/stories/productseries/xx-productseries-add-and-edit.txt'
--- lib/lp/registry/stories/productseries/xx-productseries-add-and-edit.txt	2014-02-19 02:11:16 +0000
+++ lib/lp/registry/stories/productseries/xx-productseries-add-and-edit.txt	2014-11-27 00:36:30 +0000
@@ -126,4 +126,4 @@
     >>> print browser.url
     http://launchpad.dev/firefox/unstable/+subscribe
     >>> print browser.title
-    Subscribe : Bugs : Series unstable : Mozilla Firefox
+    Subscribe : Series unstable : Bugs : Mozilla Firefox

=== modified file 'lib/lp/services/webapp/breadcrumb.py'
--- lib/lp/services/webapp/breadcrumb.py	2014-11-24 01:24:27 +0000
+++ lib/lp/services/webapp/breadcrumb.py	2014-11-27 00:36:30 +0000
@@ -33,7 +33,7 @@
     _detail = None
     _url = None
     inside = None
-    _rootsite = None
+    rootsite_override = None
 
     def __init__(self, context, url=None, text=None, inside=None,
                  rootsite=None):
@@ -45,7 +45,7 @@
         if inside is not None:
             self.inside = inside
         if rootsite is not None:
-            self._rootsite = rootsite
+            self.rootsite_override = rootsite
 
     @property
     def rootsite(self):
@@ -54,8 +54,8 @@
         If the `ICanonicalUrlData` for our context defines a rootsite, we
         return that, otherwise we return 'mainsite'.
         """
-        if self._rootsite is not None:
-            return self._rootsite
+        if self.rootsite_override is not None:
+            return self.rootsite_override
         url_data = ICanonicalUrlData(self.context)
         if url_data.rootsite:
             return url_data.rootsite

=== modified file 'lib/lp/services/webapp/doc/menus.txt'
--- lib/lp/services/webapp/doc/menus.txt	2013-04-09 08:22:58 +0000
+++ lib/lp/services/webapp/doc/menus.txt	2014-11-27 00:36:30 +0000
@@ -693,6 +693,7 @@
     ...         self.url1 = url1  # returned from getURL(1)
     ...         self.method = 'GET'
     ...         self.annotations = {}
+    ...         self.traversed_objects = []
     ...
     ...     def getURL(self, level=0):
     ...         assert 0 <= level <=1, 'level must be 0 or 1'

=== modified file 'lib/lp/services/webapp/tests/test_breadcrumbs.py'
--- lib/lp/services/webapp/tests/test_breadcrumbs.py	2014-11-16 16:23:16 +0000
+++ lib/lp/services/webapp/tests/test_breadcrumbs.py	2014-11-27 00:36:30 +0000
@@ -174,11 +174,12 @@
     def test_package_bugtask(self):
         target = self.package_bugtask.target
         distro_url = canonical_url(target.distribution)
-        distroseries_url = canonical_url(target.distroseries)
-        package_url = canonical_url(target)
+        dsp_url = canonical_url(target.distribution_sourcepackage)
+        dsp_bugs_url = canonical_url(
+            target.distribution_sourcepackage, rootsite='bugs')
         package_bugs_url = canonical_url(target, rootsite='bugs')
 
         self.assertBreadcrumbUrls(
-            [distro_url, distroseries_url, package_url, package_bugs_url,
+            [distro_url, dsp_url, dsp_bugs_url, package_bugs_url,
              self.package_bugtask_url],
             self.package_bugtask)

=== modified file 'lib/lp/soyuz/stories/packaging/package-pages-navigation.txt'
--- lib/lp/soyuz/stories/packaging/package-pages-navigation.txt	2014-11-25 07:56:07 +0000
+++ lib/lp/soyuz/stories/packaging/package-pages-navigation.txt	2014-11-27 00:36:30 +0000
@@ -65,9 +65,6 @@
 A distribution source package release build should have almost the same
 navigation as its parent distribution source package release.
 
-(XXX 20080611 mpt: A build probably should belong to a distribution *series*
-source package release, but that's more than I can chew off for now.)
-
     >>> anon_browser.open(
     ...     'http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+build/11')
     >>> print_location(anon_browser.contents)
@@ -84,73 +81,73 @@
 
 == Distribution series source package ==
 
-A distribution series source package has its own Bugs, Translations,
-and Answers.
+A distribution series source package inherits its distribution source
+package's facets.
 
     >>> anon_browser.open(
     ...     'http://launchpad.dev/ubuntu/hoary/+source/alsa-utils')
     >>> print_location(anon_browser.contents)
-    Hierarchy: Ubuntu > Hoary (5.04) > ?alsa-utils? source package
+    Hierarchy: Ubuntu > ?alsa-utils? package > Hoary (5.04)
     Tabs:
-    * Overview (selected) - not linked
-    * Code - http://code.launchpad.dev/ubuntu/hoary/+source/alsa-utils
-    * Bugs - http://bugs.launchpad.dev/ubuntu/hoary/+source/alsa-utils
+    * Overview (selected) - http://launchpad.dev/ubuntu/+source/alsa-utils
+    * Code - http://code.launchpad.dev/ubuntu/+source/alsa-utils
+    * Bugs - http://bugs.launchpad.dev/ubuntu/+source/alsa-utils
     * Blueprints - not linked
-    * Translations - http://translations.launchpad.dev/ubuntu/hoary/+source/alsa-utils
-    * Answers - not linked
+    * Translations - http://translations.launchpad.dev/ubuntu/+source/alsa-utils
+    * Answers - http://answers.launchpad.dev/ubuntu/+source/alsa-utils
     Main heading: ?alsa-utils? source package in Hoary
 
 
 == Distribution series architecture ==
 
-Distribution series architectures pages inherit Code, Bugs, Blueprints and
-Translations from the distribution series.
+Distribution series architectures pages inherit facets from the
+distribution.
 
     >>> anon_browser.open('http://launchpad.dev/ubuntu/hoary/i386')
     >>> print_location(anon_browser.contents)
     Hierarchy: Ubuntu > Hoary (5.04) > i386
     Tabs:
-    * Overview (selected) - http://launchpad.dev/ubuntu/hoary
-    * Code - http://code.launchpad.dev/ubuntu/hoary
-    * Bugs - http://bugs.launchpad.dev/ubuntu/hoary
-    * Blueprints - http://blueprints.launchpad.dev/ubuntu/hoary
-    * Translations - http://translations.launchpad.dev/ubuntu/hoary
-    * Answers - not linked
+    * Overview (selected) - http://launchpad.dev/ubuntu
+    * Code - http://code.launchpad.dev/ubuntu
+    * Bugs - http://bugs.launchpad.dev/ubuntu
+    * Blueprints - http://blueprints.launchpad.dev/ubuntu
+    * Translations - http://translations.launchpad.dev/ubuntu
+    * Answers - http://answers.launchpad.dev/ubuntu
     Main heading: Ubuntu Hoary for i386
 
 
 == Distribution series architecture binary package ==
 
 The distribution series architecture binary packages page inherits Code,
-Bugs, Blueprints and Translations from the distribution series.
+Bugs, Blueprints and Translations from the distribution.
 
     >>> anon_browser.open('http://launchpad.dev/ubuntu/hoary/i386/pmount')
     >>> print_location(anon_browser.contents)
     Hierarchy: Ubuntu > Hoary (5.04) > i386 > pmount
     Tabs:
-    * Overview (selected) - http://launchpad.dev/ubuntu/hoary
-    * Code - http://code.launchpad.dev/ubuntu/hoary
-    * Bugs - http://bugs.launchpad.dev/ubuntu/hoary
-    * Blueprints - http://blueprints.launchpad.dev/ubuntu/hoary
-    * Translations - http://translations.launchpad.dev/ubuntu/hoary
-    * Answers - not linked
+    * Overview (selected) - http://launchpad.dev/ubuntu
+    * Code - http://code.launchpad.dev/ubuntu
+    * Bugs - http://bugs.launchpad.dev/ubuntu
+    * Blueprints - http://blueprints.launchpad.dev/ubuntu
+    * Translations - http://translations.launchpad.dev/ubuntu
+    * Answers - http://answers.launchpad.dev/ubuntu
     Main heading: ?pmount? binary package in Ubuntu Hoary i386
 
 
 == Distribution series architecture binary package release ==
 
-Distribution series architecture binary package releases pages inherit Code,
-Bugs, Blueprints and Translations from the distribution series.
+Distribution series architecture binary package releases pages inherit
+facets from the distribution.
 
     >>> anon_browser.open(
     ...     'http://launchpad.dev/ubuntu/hoary/i386/pmount/0.1-1')
     >>> print_location(anon_browser.contents)
     Hierarchy: Ubuntu > Hoary (5.04) > i386 > pmount > 0.1-1
     Tabs:
-    * Overview (selected) - http://launchpad.dev/ubuntu/hoary
-    * Code - http://code.launchpad.dev/ubuntu/hoary
-    * Bugs - http://bugs.launchpad.dev/ubuntu/hoary
-    * Blueprints - http://blueprints.launchpad.dev/ubuntu/hoary
-    * Translations - http://translations.launchpad.dev/ubuntu/hoary
-    * Answers - not linked
+    * Overview (selected) - http://launchpad.dev/ubuntu
+    * Code - http://code.launchpad.dev/ubuntu
+    * Bugs - http://bugs.launchpad.dev/ubuntu
+    * Blueprints - http://blueprints.launchpad.dev/ubuntu
+    * Translations - http://translations.launchpad.dev/ubuntu
+    * Answers - http://answers.launchpad.dev/ubuntu
     Main heading: pmount 0.1-1 (i386 binary) in ubuntu hoary

=== modified file 'lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt'
--- lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt	2013-07-25 13:45:17 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt	2014-11-27 00:36:30 +0000
@@ -95,7 +95,7 @@
     ...   "http://launchpad.dev/ubuntu/hoary/+source/pmount";)
     >>> anon_browser.getLink("Show builds").click()
     >>> print anon_browser.title
-    Builds : ...pmount... source package : Hoary (5.04) : Ubuntu
+    Builds : Hoary (5.04) : ...pmount... package : Ubuntu
 
     >>> print check_builds_options(anon_browser.contents)
     State present, Name not present

=== modified file 'lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt'
--- lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt	2014-11-09 23:12:08 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt	2014-11-27 00:36:30 +0000
@@ -223,7 +223,7 @@
 
     >>> browser.getLink('copyright').click()
     >>> print browser.title
-    Copyright : ...mozilla-firefox... source package : Warty (4.10) : Ubuntu
+    Copyright : Warty (4.10) : ...mozilla-firefox... package : Ubuntu
 
     >>> print extract_text(find_tag_by_id(browser.contents, 'copyright'))
     Copyright 2010 Ford Prefect.

=== modified file 'lib/lp/soyuz/stories/soyuz/xx-person-packages.txt'
--- lib/lp/soyuz/stories/soyuz/xx-person-packages.txt	2014-07-08 06:34:37 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-person-packages.txt	2014-11-27 00:36:30 +0000
@@ -71,7 +71,7 @@
     <Link text='Ubuntu Hoary' ...>
     >>> link.click()
     >>> browser.title
-    '...cnews... package : Hoary (5.04) : Ubuntu'
+    'Hoary (5.04) : ...cnews... package : Ubuntu'
 
 The third column links to the distribution source package release page. The
 user follows the cnews version link to see the page.

=== modified file 'lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt'
--- lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt	2014-11-09 22:19:51 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt	2014-11-27 00:36:30 +0000
@@ -6,14 +6,14 @@
     >>> user_browser.open(
     ...     "http://launchpad.dev/ubuntu/hoary/+source/pmount/+changelog";)
     >>> print_location(user_browser.contents)
-    Hierarchy: Ubuntu > Hoary (5.04) > ...pmount... source package > Change log
+    Hierarchy: Ubuntu > ...pmount... package > Hoary (5.04) > Change log
     Tabs:
-    * Overview (selected) - http://launchpad.dev/ubuntu/hoary/+source/pmount
-    * Code - http://code.launchpad.dev/ubuntu/hoary/+source/pmount
-    * Bugs - http://bugs.launchpad.dev/ubuntu/hoary/+source/pmount
+    * Overview (selected) - http://launchpad.dev/ubuntu/+source/pmount
+    * Code - http://code.launchpad.dev/ubuntu/+source/pmount
+    * Bugs - http://bugs.launchpad.dev/ubuntu/+source/pmount
     * Blueprints - not linked
-    * Translations - http://translations.launchpad.dev/ubuntu/hoary/+source/pmount
-    * Answers - not linked
+    * Translations - http://translations.launchpad.dev/ubuntu/+source/pmount
+    * Answers - http://answers.launchpad.dev/ubuntu/+source/pmount
     Main heading: Change logs for ...pmount... in Hoary
 
     >>> print extract_text(

=== modified file 'lib/lp/translations/browser/tests/test_breadcrumbs.py'
--- lib/lp/translations/browser/tests/test_breadcrumbs.py	2014-02-19 00:35:25 +0000
+++ lib/lp/translations/browser/tests/test_breadcrumbs.py	2014-11-27 00:36:30 +0000
@@ -36,8 +36,9 @@
         series = self.factory.makeProductSeries(name="test", product=product)
         self.assertBreadcrumbs(
             [("Crumb Tester", 'http://launchpad.dev/crumb-tester'),
-             ("Series test", 'http://launchpad.dev/crumb-tester/test'),
              ("Translations",
+              'http://translations.launchpad.dev/crumb-tester'),
+             ("Series test",
               'http://translations.launchpad.dev/crumb-tester/test')],
             series, rootsite='translations')
 
@@ -57,8 +58,9 @@
             name="test", version="1.0", distribution=distribution)
         self.assertBreadcrumbs(
             [("Crumb Tester", 'http://launchpad.dev/crumb-tester'),
-             ("Test (1.0)", 'http://launchpad.dev/crumb-tester/test'),
              ("Translations",
+              'http://translations.launchpad.dev/crumb-tester'),
+             ("Test (1.0)",
               'http://translations.launchpad.dev/crumb-tester/test')],
             series, rootsite='translations')
 
@@ -119,8 +121,9 @@
 
         self.assertBreadcrumbs(
             [("Crumb Tester", "http://launchpad.dev/crumb-tester";),
-             ("Test (1.0)", "http://launchpad.dev/crumb-tester/test";),
              ("Translations",
+              "http://translations.launchpad.dev/crumb-tester";),
+             ("Test (1.0)",
               "http://translations.launchpad.dev/crumb-tester/test";),
              ("Serbian (sr)",
               "http://translations.launchpad.dev/";
@@ -138,8 +141,9 @@
 
         self.assertBreadcrumbs(
             [("Crumb Tester", "http://launchpad.dev/crumb-tester";),
-             ("Series test", "http://launchpad.dev/crumb-tester/test";),
              ("Translations",
+              "http://translations.launchpad.dev/crumb-tester";),
+             ("Series test",
               "http://translations.launchpad.dev/crumb-tester/test";),
              ("Serbian (sr)",
               "http://translations.launchpad.dev/";
@@ -160,8 +164,9 @@
             name="template", productseries=series)
         self.assertBreadcrumbs(
             [("Crumb Tester", "http://launchpad.dev/crumb-tester";),
-             ("Series test", "http://launchpad.dev/crumb-tester/test";),
              ("Translations",
+              "http://translations.launchpad.dev/crumb-tester";),
+             ("Series test",
               "http://translations.launchpad.dev/crumb-tester/test";),
              (smartquote('Template "template"'),
               "http://translations.launchpad.dev/";
@@ -184,8 +189,9 @@
 
         self.assertBreadcrumbs(
             [("Crumb Tester", "http://launchpad.dev/crumb-tester";),
-             ("Series test", "http://launchpad.dev/crumb-tester/test";),
              ("Translations",
+              "http://translations.launchpad.dev/crumb-tester";),
+             ("Series test",
               "http://translations.launchpad.dev/crumb-tester/test";),
              (smartquote('Template "test-template"'),
               "http://translations.launchpad.dev/crumb-tester/test";

=== modified file 'lib/lp/translations/stories/importqueue/xx-entry-details.txt'
--- lib/lp/translations/stories/importqueue/xx-entry-details.txt	2012-10-09 10:28:02 +0000
+++ lib/lp/translations/stories/importqueue/xx-entry-details.txt	2014-11-27 00:36:30 +0000
@@ -74,7 +74,7 @@
 
     >>> admin_browser.getLink('1 template').click()
     >>> print admin_browser.title
-    All templates : Translations : Series trunk : ...
+    All templates : Series trunk : Translations : ...
 
 In that case, the product is also shown to have translatable series.
 

=== modified file 'lib/lp/translations/stories/navigation-links/pofile.txt'
--- lib/lp/translations/stories/navigation-links/pofile.txt	2011-05-13 03:26:21 +0000
+++ lib/lp/translations/stories/navigation-links/pofile.txt	2014-11-27 00:36:30 +0000
@@ -11,15 +11,15 @@
     >>> print admin_browser.url
     http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2/es
 
-The Application tabs should point to IProductSeries URLs.
+The Application tabs should point to IProduct URLs.
 
     >>> print_location_apps(admin_browser.contents)
-    * Overview - http://launchpad.dev/evolution/trunk
+    * Overview - http://launchpad.dev/evolution
     * Code - http://code.launchpad.dev/evolution
-    * Bugs - http://bugs.launchpad.dev/evolution/trunk
-    * Blueprints - http://blueprints.launchpad.dev/evolution/trunk
-    * Translations (selected) - http://translations.launchpad.dev/evolution/trunk
-    * Answers - not linked
+    * Bugs - http://bugs.launchpad.dev/evolution
+    * Blueprints - http://blueprints.launchpad.dev/evolution
+    * Translations (selected) - http://translations.launchpad.dev/evolution
+    * Answers - http://answers.launchpad.dev/evolution
 
 Taking an IPOFile for ISourcePackage context:
 
@@ -29,13 +29,13 @@
     >>> print admin_browser.url
     http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/es
 
-The Application tabs should point to ISourcePackage URLs.
+The Application tabs should point to IDistributionSourcePackage URLs.
 
     >>> print_location_apps(admin_browser.contents)
-    * Overview - http://launchpad.dev/ubuntu/hoary/+source/evolution
-    * Code - http://code.launchpad.dev/ubuntu/hoary/+source/evolution
-    * Bugs - http://bugs.launchpad.dev/ubuntu/hoary/+source/evolution
+    * Overview - http://launchpad.dev/ubuntu/+source/evolution
+    * Code - http://code.launchpad.dev/ubuntu/+source/evolution
+    * Bugs - http://bugs.launchpad.dev/ubuntu/+source/evolution
     * Blueprints - not linked
-    * Translations (selected) - http://translations.launchpad.dev/ubuntu/hoary/+source/evolution
-    * Answers - not linked
+    * Translations (selected) - http://translations.launchpad.dev/ubuntu/+source/evolution
+    * Answers - http://answers.launchpad.dev/ubuntu/+source/evolution
 

=== modified file 'lib/lp/translations/stories/navigation-links/pomsgset.txt'
--- lib/lp/translations/stories/navigation-links/pomsgset.txt	2011-05-13 03:26:21 +0000
+++ lib/lp/translations/stories/navigation-links/pomsgset.txt	2014-11-27 00:36:30 +0000
@@ -16,12 +16,12 @@
 The Application tabs should point to IProductSeries URLs.
 
     >>> print_location_apps(browser.contents)
-    * Overview - http://launchpad.dev/evolution/trunk
+    * Overview - http://launchpad.dev/evolution
     * Code - http://code.launchpad.dev/evolution
-    * Bugs - http://bugs.launchpad.dev/evolution/trunk
-    * Blueprints - http://blueprints.launchpad.dev/evolution/trunk
-    * Translations (selected) - http://translations.launchpad.dev/evolution/trunk
-    * Answers - not linked
+    * Bugs - http://bugs.launchpad.dev/evolution
+    * Blueprints - http://blueprints.launchpad.dev/evolution
+    * Translations (selected) - http://translations.launchpad.dev/evolution
+    * Answers - http://answers.launchpad.dev/evolution
 
 Taking an IPOMsgSet for ISourcePackage context:
 
@@ -38,9 +38,9 @@
 The Application tabs should point to ISourcePackage URLs.
 
     >>> print_location_apps(browser.contents)
-    * Overview - http://launchpad.dev/ubuntu/hoary/+source/evolution
-    * Code - http://code.launchpad.dev/ubuntu/hoary/+source/evolution
-    * Bugs - http://bugs.launchpad.dev/ubuntu/hoary/+source/evolution
+    * Overview - http://launchpad.dev/ubuntu/+source/evolution
+    * Code - http://code.launchpad.dev/ubuntu/+source/evolution
+    * Bugs - http://bugs.launchpad.dev/ubuntu/+source/evolution
     * Blueprints - not linked
-    * Translations (selected) - http://translations.launchpad.dev/ubuntu/hoary/+source/evolution
-    * Answers - not linked
+    * Translations (selected) - http://translations.launchpad.dev/ubuntu/+source/evolution
+    * Answers - http://answers.launchpad.dev/ubuntu/+source/evolution

=== modified file 'lib/lp/translations/stories/navigation-links/potemplate.txt'
--- lib/lp/translations/stories/navigation-links/potemplate.txt	2011-05-13 03:26:21 +0000
+++ lib/lp/translations/stories/navigation-links/potemplate.txt	2014-11-27 00:36:30 +0000
@@ -9,15 +9,15 @@
   >>> print admin_browser.url
   http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2
 
-The Application tabs should point to IProductSeries URLs.
+The Application tabs should point to IProduct URLs.
 
     >>> print_location_apps(admin_browser.contents)
-    * Overview - http://launchpad.dev/evolution/trunk
+    * Overview - http://launchpad.dev/evolution
     * Code - http://code.launchpad.dev/evolution
-    * Bugs - http://bugs.launchpad.dev/evolution/trunk
-    * Blueprints - http://blueprints.launchpad.dev/evolution/trunk
-    * Translations (selected) - http://translations.launchpad.dev/evolution/trunk
-    * Answers - not linked
+    * Bugs - http://bugs.launchpad.dev/evolution
+    * Blueprints - http://blueprints.launchpad.dev/evolution
+    * Translations (selected) - http://translations.launchpad.dev/evolution
+    * Answers - http://answers.launchpad.dev/evolution
 
 Taking an IPOTemplate for ISourcePackage context:
 
@@ -27,12 +27,12 @@
   >>> print admin_browser.url
   http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2
 
-The Application tabs should point to ISourcePackage URLs.
+The Application tabs should point to IDistributionSourcePackage URLs.
 
     >>> print_location_apps(admin_browser.contents)
-    * Overview - http://launchpad.dev/ubuntu/hoary/+source/evolution
-    * Code - http://code.launchpad.dev/ubuntu/hoary/+source/evolution
-    * Bugs - http://bugs.launchpad.dev/ubuntu/hoary/+source/evolution
+    * Overview - http://launchpad.dev/ubuntu/+source/evolution
+    * Code - http://code.launchpad.dev/ubuntu/+source/evolution
+    * Bugs - http://bugs.launchpad.dev/ubuntu/+source/evolution
     * Blueprints - not linked
-    * Translations (selected) - http://translations.launchpad.dev/ubuntu/hoary/+source/evolution
-    * Answers - not linked
+    * Translations (selected) - http://translations.launchpad.dev/ubuntu/+source/evolution
+    * Answers - http://answers.launchpad.dev/ubuntu/+source/evolution

=== modified file 'lib/lp/translations/stories/productseries/xx-productseries-translation-export.txt'
--- lib/lp/translations/stories/productseries/xx-productseries-translation-export.txt	2013-09-27 04:13:23 +0000
+++ lib/lp/translations/stories/productseries/xx-productseries-translation-export.txt	2014-11-27 00:36:30 +0000
@@ -45,7 +45,7 @@
 request the download.
 
     >>> print user_browser.title
-    Download : Translations...
+    Download : Series trunk : Translations...
 
 
 === File format ===

=== modified file 'lib/lp/translations/stories/productseries/xx-productseries-translations.txt'
--- lib/lp/translations/stories/productseries/xx-productseries-translations.txt	2012-09-19 01:19:35 +0000
+++ lib/lp/translations/stories/productseries/xx-productseries-translations.txt	2014-11-27 00:36:30 +0000
@@ -47,7 +47,7 @@
 
     >>> anon_browser.open(frobnicator_trunk_url)
     >>> print anon_browser.title
-    Translations : Series trunk : Frobnicator
+    Series trunk : Translations : Frobnicator
 
     >>> main_content = find_main_content(anon_browser.contents)
     >>> print extract_text(main_content.findAll('h1')[0])

=== modified file 'lib/lp/translations/stories/standalone/xx-licensing.txt'
--- lib/lp/translations/stories/standalone/xx-licensing.txt	2013-09-27 04:13:23 +0000
+++ lib/lp/translations/stories/standalone/xx-licensing.txt	2014-11-27 00:36:30 +0000
@@ -85,8 +85,8 @@
     >>> browser.url
     'http://.../alsa-utils/trunk/+pots/alsa-utils/es/+translate'
     >>> print browser.title
-    Spanish (es) : Template ...alsa-utils... : Translations :
-    Series trunk : alsa-utils
+    Spanish (es) : Template ...alsa-utils... : Series trunk :
+    Translations : alsa-utils
 
 
 Permissions

=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-export.txt'
--- lib/lp/translations/stories/standalone/xx-pofile-export.txt	2014-11-24 01:25:09 +0000
+++ lib/lp/translations/stories/standalone/xx-pofile-export.txt	2014-11-27 00:36:30 +0000
@@ -19,8 +19,8 @@
     >>> user_browser.getLink('Download').click()
 
     >>> print user_browser.title
-    Download translation : Spanish (es)... : Translations :
-    ...evolution... package : Hoary (5.04) : Ubuntu
+    Download translation : Spanish (es)... : Hoary (5.04) :
+    Translations : ...evolution... package : Ubuntu
 
     >>> print find_main_content(user_browser.contents)
     <...

=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt'
--- lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt	2014-11-24 01:25:09 +0000
+++ lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt	2014-11-27 00:36:30 +0000
@@ -48,8 +48,8 @@
     ...     'http://translations.launchpad.dev/ubuntu/hoary/'
     ...     '+source/evolution/+pots/evolution-2.2/es/+translate')
     >>> print user_browser.title
-    Spanish (es) : Template ...evolution-2.2... : Translations :
-    ...evolution... package : Hoary (5.04) : Ubuntu
+    Spanish (es) : Template ...evolution-2.2... :
+    Hoary (5.04) : Translations : ...evolution... package : Ubuntu
 
 He can see that there are 22 messages.
 
@@ -126,7 +126,7 @@
     >>> user_browser.getControl('Change').click()
     >>> print user_browser.title
     English (Australia) (en_AU) : Template ...evolution-2.2... :
-    Translations : ...evolution... package : Hoary (5.04) : Ubuntu
+    Hoary (5.04) : Translations : ...evolution... package : Ubuntu
 
     >>> contents = find_main_content(user_browser.contents)
     >>> print_batch_header(contents)
@@ -194,7 +194,7 @@
     >>> user_browser.getControl('Change').click()
     >>> print user_browser.title
     English (Australia) (en_AU) : Template ...evolution-2.2... :
-    Translations : Series trunk : Evolution
+    Series trunk : Translations : Evolution
 
     >>> contents = find_main_content(user_browser.contents)
     >>> print_batch_header(contents)

=== modified file 'lib/lp/translations/stories/standalone/xx-potemplate-index.txt'
--- lib/lp/translations/stories/standalone/xx-potemplate-index.txt	2014-11-24 01:25:09 +0000
+++ lib/lp/translations/stories/standalone/xx-potemplate-index.txt	2014-11-27 00:36:30 +0000
@@ -12,8 +12,8 @@
     >>> anon_browser.open("http://translations.launchpad.dev/";
     ...     "ubuntu/hoary/+source/evolution/+pots/evolution-2.2/")
     >>> print anon_browser.title
-    Template ...evolution-2.2... : Translations :
-    ...evolution... package : Hoary (5.04) : Ubuntu
+    Template ...evolution-2.2... : Hoary (5.04) :
+    Translations : ...evolution... package : Ubuntu
 
 The owner of the template is diplayed.
 

=== modified file 'lib/lp/translations/stories/standalone/xx-product-export.txt'
--- lib/lp/translations/stories/standalone/xx-product-export.txt	2013-09-27 04:13:23 +0000
+++ lib/lp/translations/stories/standalone/xx-product-export.txt	2014-11-27 00:36:30 +0000
@@ -26,7 +26,7 @@
 it for source packages (tested and documented separately).
 
     >>> print user_browser.title
-    Download : Translations...
+    Download : Series trunk : Translations...
 
     >>> user_browser.getControl('Request Download').click()
     >>> print_feedback_messages(user_browser.contents)

=== modified file 'lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt'
--- lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt	2014-11-24 01:25:09 +0000
+++ lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt	2014-11-27 00:36:30 +0000
@@ -8,7 +8,7 @@
     ...     'http://translations.launchpad.dev/ubuntu/hoary/'
     ...     '+source/evolution')
     >>> anon_browser.title
-    'Translations : ...evolution...package : Hoary (5.04) : Ubuntu'
+    'Hoary (5.04) : Translations : ...evolution...package : Ubuntu'
 
     >>> content = find_main_content(anon_browser.contents)
     >>> print extract_text(content.findAll('h1')[0]).encode(

=== modified file 'lib/lp/translations/stories/standalone/xx-serieslanguage-index.txt'
--- lib/lp/translations/stories/standalone/xx-serieslanguage-index.txt	2012-05-24 20:25:54 +0000
+++ lib/lp/translations/stories/standalone/xx-serieslanguage-index.txt	2014-11-27 00:36:30 +0000
@@ -14,7 +14,7 @@
     http://translations.launchpad.dev/evolution/trunk/+lang/pt_BR
 
     >>> print browser.title
-    Portuguese (Brazil) (pt_BR) : Translations : Series trunk : Evolution
+    Portuguese (Brazil) (pt_BR) : Series trunk : Translations : Evolution
 
 Since there is no translation team to manage Portuguese (Brazil) language
 in the Evolution's translation group, all users will be informed about it

=== modified file 'lib/lp/translations/stories/standalone/xx-sourcepackage-export.txt'
--- lib/lp/translations/stories/standalone/xx-sourcepackage-export.txt	2014-11-24 01:25:09 +0000
+++ lib/lp/translations/stories/standalone/xx-sourcepackage-export.txt	2014-11-27 00:36:30 +0000
@@ -166,7 +166,7 @@
     ...     'http://translations.launchpad.dev/'
     ...     'ubuntu/hoary/+source/mozilla/+export')
     >>> browser.title
-    'Download : Translations : \xe2\x80\x9cmozilla...
+    'Download : Hoary (5.04) : Translations : \xe2\x80\x9cmozilla...
 
     >>> browser.getControl('Request Download').click()
 


Follow ups