Merge lp:~henninge/launchpad/devel-705176-sharing-info-on-page into lp:launchpad

Proposed by Henning Eggers
Status: Merged
Approved by: Henning Eggers
Approved revision: no longer in the source branch.
Merged at revision: 12510
Proposed branch: lp:~henninge/launchpad/devel-705176-sharing-info-on-page
Merge into: lp:launchpad
Diff against target: 824 lines (+472/-124)
15 files modified
lib/lp/services/features/flags.py (+4/-0)
lib/lp/translations/browser/pofile.py (+40/-0)
lib/lp/translations/browser/potemplate.py (+36/-17)
lib/lp/translations/browser/productseries.py (+15/-0)
lib/lp/translations/browser/sourcepackage.py (+17/-0)
lib/lp/translations/browser/tests/test_sharing_information.py (+215/-0)
lib/lp/translations/doc/potemplate.txt (+0/-18)
lib/lp/translations/interfaces/potemplate.py (+0/-3)
lib/lp/translations/model/potemplate.py (+0/-7)
lib/lp/translations/stories/standalone/xx-potemplate-index.txt (+36/-26)
lib/lp/translations/templates/pofile-translate.pt (+25/-0)
lib/lp/translations/templates/potemplate-index.pt (+49/-50)
lib/lp/translations/templates/productseries-translations.pt (+15/-0)
lib/lp/translations/templates/sourcepackage-translations.pt (+16/-0)
lib/lp/translations/utilities/translationsharinginfo.py (+4/-3)
To merge this branch: bzr merge lp:~henninge/launchpad/devel-705176-sharing-info-on-page
Reviewer Review Type Date Requested Status
Curtis Hovey (community) ui Approve
Abel Deuring (community) code Approve
Review via email: mp+51283@code.launchpad.net

Commit message

[r=adeuring][ui=sinzui][bug=705176][incr] Display sharing information on translation pages.

Description of the change

= Summary =

First step: display sharing information on translation pages. This
makes it easy for translators to go to the "other side" of a
translation link (i.e. a packaging link).

The next step will be to add a link to a page where more detail about
translation sharing can be found and which also allows to setup
sharing.

For the UI review, here are some screenshots of how the information appears in the UI:
http://people.canonical.com/~henninge/screenshots/sharing-information-productseries.png
http://people.canonical.com/~henninge/screenshots/sharing-information-template.png
http://people.canonical.com/~henninge/screenshots/sharing-information-pofile.png

== Proposed fix ==

Use the functions provided in translationsharinginfo to display the
correct text and link on the pages.

== Pre-implementation notes ==

I discussed this with Maris at the Thunderdome. We agreed that the "Templates with the same name elsewhere" section had to go away since that information would now be provided through the sharing information.

I chatted with Deryck about this. We weren't entirely sure, where
exactly to place the information on the pages. At least I was, so this
is still up to UI discussion.

== Implementation details ==

Pretty straight forward implementation of test, view class attributes
and templates.

I changed the get_ubuntu_sharing_info to return a list instead of a
generator. This was easier to handle and is also symmetric to
get_upstream_translation_info.

The new UI elements are hidden behind a feature flag. Actually, the elements from this branch could go live immediately but subsequent branches will need to be hidden until the feature is complete.

== Tests ==

bin/test -vvcm lp.translations.browser.test.test_sharing_information

== Demo and Q/A ==

You will have to enable the feature:
translations.sharing_information.enabled

View sharing information for a product series here:
http://translations.launchpad.dev/evolution/trunk

View sharing information for a template here:
http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2

View sharing information for a pofile here:
http://translations.launchpad.dev/evolution/trunk/+pots/evolution-2.2/es

Once on the other side, you'll see the equivalent links there.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/services/features/flags.py
  lib/lp/translations/browser/pofile.py
  lib/lp/translations/browser/potemplate.py
  lib/lp/translations/browser/productseries.py
  lib/lp/translations/browser/sourcepackage.py
  lib/lp/translations/browser/tests/test_sharing_information.py
  lib/lp/translations/templates/pofile-translate.pt
  lib/lp/translations/templates/potemplate-index.pt
  lib/lp/translations/templates/productseries-translations.pt
  lib/lp/translations/templates/sourcepackage-translations.pt
  lib/lp/translations/utilities/translationsharinginfo.py

./lib/lp/translations/browser/pofile.py
     794: E301 expected 1 blank line, found 2
     910: E301 expected 1 blank line, found 2

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Hi Henning.

These images look good. I have questions though about consistency with other parts of Lp.

We show the package icon next to package on several pages where we tell users about Ubuntu. eg. <https://bugs.launchpad.net/evolution>. Why should <http://people.canonical.com/~henninge/screenshots/sharing-information-productseries.png> be different? Does
    [%] evolution in Ubuntu Hoary
make it easier to understand that the package is a separate thing?

The phrasing for this changes on other pages. I believe they are using an established convention. The package is in quotes and follows the distro and series names:
    Template "evolution-2.2" in Ubuntu Hoary package "evolution"
could be
    [%] evolution in Ubuntu Hoary Template "evolution-2.2"

review: Needs Information (ui)
Revision history for this message
Henning Eggers (henninge) wrote :

Hi Curtis!

For the source packages I used fmt:link, so I guess that formatter needs to be fixed. I now copied the code from the product home page. I will look at doing something similar for the templates and such. I like the version with icon better myself although it looks a bit crooked at the moment which is probably due to the UbuntuBeta Mono font.

I will come back with new screenshots but may have to wait until Monday.

Henning

Revision history for this message
Abel Deuring (adeuring) wrote :
Download full text (6.8 KiB)

Hi Henning,

overall, nice work. I have just a few minor suggestions, see below.
Nothing serious, so feel free to land the branch as it is.

> === modified file 'lib/lp/translations/browser/pofile.py'
> --- lib/lp/translations/browser/pofile.py 2011-01-24 15:51:18 +0000
> +++ lib/lp/translations/browser/pofile.py 2011-02-25 16:16:52 +0000
> @@ -59,6 +59,12 @@
> ITranslationImportQueue,
> )
> from lp.translations.interfaces.translationsperson import ITranslationsPerson
> +from lp.translations.utilities.translationsharinginfo import (
> + has_ubuntu_template,
> + has_upstream_template,
> + get_ubuntu_sharing_info,
> + get_upstream_sharing_info,
> + )
>
>
> class POFileNavigation(Navigation):
> @@ -986,6 +992,36 @@
> def translations_order(self):
> return ' '.join(self._messages_html_id())
>
> + @property
> + def is_upstream_pofile(self):
> + potemplate = self.context.potemplate
> + return potemplate.translation_side == TranslationSide.UPSTREAM
> +
> + def is_sharing(self):
> + if self.is_upstream_pofile:
> + return has_ubuntu_template(
> + productseries=self.context.potemplate.productseries,
> + templatename=self.context.potemplate.name)
> + else:
> + return has_upstream_template(
> + sourcepackage=self.context.potemplate.sourcepackage,
> + templatename=self.context.potemplate.name)
> +
> + @property
> + def sharing_pofile(self):
> + if self.is_upstream_pofile:
> + infos = get_ubuntu_sharing_info(
> + productseries=self.context.potemplate.productseries,
> + templatename=self.context.potemplate.name)
> + else:
> + infos = get_upstream_sharing_info(
> + sourcepackage=self.context.potemplate.sourcepackage,
> + templatename=self.context.potemplate.name)
> + if len(infos) == 0:
> + return None
> + obj, potemplate = infos[0]
> + return potemplate.getPOFileByLang(self.context.language.code)

The three properties defined above...

> +
>
> class POExportView(BaseExportView):
>
>
> === modified file 'lib/lp/translations/browser/potemplate.py'
> --- lib/lp/translations/browser/potemplate.py 2010-12-02 16:13:51 +0000
> +++ lib/lp/translations/browser/potemplate.py 2011-02-25 16:16:52 +0000
> @@ -77,12 +77,19 @@
> IPOTemplateSet,
> IPOTemplateSubset,
> )
> +from lp.translations.interfaces.side import TranslationSide
> from lp.translations.interfaces.translationimporter import (
> ITranslationImporter,
> )
> from lp.translations.interfaces.translationimportqueue import (
> ITranslationImportQueue,
> )
> +from lp.translations.utilities.translationsharinginfo import (
> + has_ubuntu_template,
> + get_ubuntu_sharing_info,
> + has_upstream_template,
> + get_upstream_sharing_info,
> + )
>
>
> class POTemplateNavigation(Navigation):
> @@ -354,6 +361,35 @@
> pofile = pofileset.getDummy(self.context, language)
> return pofile
>
> + @property
> + def is_upstream_template(self):
> ...

Read more...

review: Approve (code)
Revision history for this message
Curtis Hovey (sinzui) wrote :

> Hi Curtis!
>
> For the source packages I used fmt:link, so I guess that formatter needs to be
> fixed. I now copied the code from the product home page. I will look at doing
> something similar for the templates and such. I like the version with icon
> better myself although it looks a bit crooked at the moment which is probably
> due to the UbuntuBeta Mono font.

I thought the Icon issue in the formatter was fixed. Maybe ISourcePackage and IDistributionSourcePackage are different. I will let you sort that out.

I know the pain of the beta fonts. I have decided to not design for them yet.

> I will come back with new screenshots but may have to wait until Monday.

I am marking the UI as approved.

review: Approve (ui)
Revision history for this message
Henning Eggers (henninge) wrote :

Hi Curtis!

Here are some screenshots of how it looks now:
http://people.canonical.com/~henninge/screenshots/sharing-information/

I really would have liked to avoid presenting two links in the statement. Since the sharing template always has the name as the one currently in view, that information is kind of redundant. So the text could just be "This template is sharing translations with [*]_Evolution_trunk_series_" but the link would have to be to the template, not the product series. I find it a bit misleading to use an icon for a product series and let it lead you to a template. So I did not do that. Maybe this is just missing an icon for "POTemplate"?

Having said that, I did something similar on the POFile view because the name of the template links to the sharing POFile (i.e. the specific language) but I think that's expected. Also, there is no icon.

For the link tests I had to use "displayname" for source packages and "title" for product series because "title" would only give me "trunk" for the latter. Maybe these properties need to be more conforming to conventions?

Revision history for this message
Curtis Hovey (sinzui) wrote :

I completely agree that we are missing icons that would make this clear. I think we should treat this as a separate issue. At least, do not block this branch from landing. We do need better conventions here. I think we can solve that separately, and update several pages.

I know how to make icons, but I do not know what they could look like. Maybe something in the style of http://design.canonical.com/brand/8.%20Pictograms.pdf
I think we want to add some formatters so that we do not need to craft these links.

Revision history for this message
Henning Eggers (henninge) wrote :

Hi Abel,
thank you for your review. I was able to remove some redundancy from the test and also fixed the misplaced tal:condition in the page template. Thanks for spotting that!

I have already contemplated that it might be possible to put the "sharing information" portlet in a makro or subview to reduce redundancy but like you I see too many subtle differences that might make this more complex than is good. I might give it a try in a later branch, though.

I also took William's remarks on the mailing list to heart and removed cruft right here where I created it, namely "relatives_by_name" and some related stuff. This is now gone from the template index because that information is in the sharing information. I am sure I would not have remembered to remove it later but it bloats the diff to almost 800 lines. Oh well. ;-)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/services/features/flags.py'
2--- lib/lp/services/features/flags.py 2011-02-24 19:59:45 +0000
3+++ lib/lp/services/features/flags.py 2011-03-02 09:23:15 +0000
4@@ -73,6 +73,10 @@
5 'boolean',
6 'Enables derivative distributions pages.',
7 ''),
8+ ('translations.sharing_information.enabled',
9+ 'boolean',
10+ 'Enables display of sharing information on translation pages.',
11+ ''),
12 ('visible_render_time',
13 'boolean',
14 'Shows the server-side page render time in the login widget.',
15
16=== modified file 'lib/lp/translations/browser/pofile.py'
17--- lib/lp/translations/browser/pofile.py 2011-01-24 15:51:18 +0000
18+++ lib/lp/translations/browser/pofile.py 2011-03-02 09:23:15 +0000
19@@ -59,6 +59,12 @@
20 ITranslationImportQueue,
21 )
22 from lp.translations.interfaces.translationsperson import ITranslationsPerson
23+from lp.translations.utilities.translationsharinginfo import (
24+ has_ubuntu_template,
25+ has_upstream_template,
26+ get_ubuntu_sharing_info,
27+ get_upstream_sharing_info,
28+ )
29
30
31 class POFileNavigation(Navigation):
32@@ -986,6 +992,40 @@
33 def translations_order(self):
34 return ' '.join(self._messages_html_id())
35
36+ @property
37+ def is_upstream_pofile(self):
38+ potemplate = self.context.potemplate
39+ return potemplate.translation_side == TranslationSide.UPSTREAM
40+
41+ def is_sharing(self):
42+ if self.is_upstream_pofile:
43+ return has_ubuntu_template(
44+ productseries=self.context.potemplate.productseries,
45+ templatename=self.context.potemplate.name)
46+ else:
47+ return has_upstream_template(
48+ sourcepackage=self.context.potemplate.sourcepackage,
49+ templatename=self.context.potemplate.name)
50+
51+ @property
52+ def sharing_pofile(self):
53+ if self.is_upstream_pofile:
54+ infos = get_ubuntu_sharing_info(
55+ productseries=self.context.potemplate.productseries,
56+ templatename=self.context.potemplate.name)
57+ else:
58+ infos = get_upstream_sharing_info(
59+ sourcepackage=self.context.potemplate.sourcepackage,
60+ templatename=self.context.potemplate.name)
61+ if len(infos) == 0:
62+ return None
63+ obj, potemplate = infos[0]
64+ pofile = potemplate.getPOFileByLang(self.context.language.code)
65+ if pofile is None:
66+ pofile = potemplate.getDummyPOFile(
67+ self.context.language, check_for_existing=False)
68+ return pofile
69+
70
71 class POExportView(BaseExportView):
72
73
74=== modified file 'lib/lp/translations/browser/potemplate.py'
75--- lib/lp/translations/browser/potemplate.py 2010-12-02 16:13:51 +0000
76+++ lib/lp/translations/browser/potemplate.py 2011-03-02 09:23:15 +0000
77@@ -77,12 +77,19 @@
78 IPOTemplateSet,
79 IPOTemplateSubset,
80 )
81+from lp.translations.interfaces.side import TranslationSide
82 from lp.translations.interfaces.translationimporter import (
83 ITranslationImporter,
84 )
85 from lp.translations.interfaces.translationimportqueue import (
86 ITranslationImportQueue,
87 )
88+from lp.translations.utilities.translationsharinginfo import (
89+ has_ubuntu_template,
90+ get_ubuntu_sharing_info,
91+ has_upstream_template,
92+ get_upstream_sharing_info,
93+ )
94
95
96 class POTemplateNavigation(Navigation):
97@@ -291,12 +298,6 @@
98 translation_group.translation_guide_url is not None)
99
100 @property
101- def has_related_templates(self):
102- by_source = self.context.relatives_by_source
103- by_name = self.context.relatives_by_name
104- return bool(by_source) or bool(by_name)
105-
106- @property
107 def related_templates_by_source(self):
108 by_source = list(
109 self.context.relatives_by_source[:self.SHOW_RELATED_TEMPLATES])
110@@ -328,17 +329,6 @@
111 return ""
112
113 @property
114- def related_templates_by_name(self):
115- by_name = list(
116- self.context.relatives_by_name[:self.SHOW_RELATED_TEMPLATES])
117- return by_name
118-
119- @property
120- def has_more_templates_by_name(self):
121- by_name_count = self.context.relatives_by_name.count()
122- return by_name_count > self.SHOW_RELATED_TEMPLATES
123-
124- @property
125 def has_pofiles(self):
126 languages = set(
127 self.context.languages()).union(self.translatable_languages)
128@@ -354,6 +344,35 @@
129 pofile = pofileset.getDummy(self.context, language)
130 return pofile
131
132+ @property
133+ def is_upstream_template(self):
134+ return self.context.translation_side == TranslationSide.UPSTREAM
135+
136+ def is_sharing(self):
137+ if self.is_upstream_template:
138+ return has_ubuntu_template(
139+ productseries=self.context.productseries,
140+ templatename=self.context.name)
141+ else:
142+ return has_upstream_template(
143+ sourcepackage=self.context.sourcepackage,
144+ templatename=self.context.name)
145+
146+ @property
147+ def sharing_template(self):
148+ if self.is_upstream_template:
149+ infos = get_ubuntu_sharing_info(
150+ productseries=self.context.productseries,
151+ templatename=self.context.name)
152+ else:
153+ infos = get_upstream_sharing_info(
154+ sourcepackage=self.context.sourcepackage,
155+ templatename=self.context.name)
156+ if len(infos) == 0:
157+ return None
158+ obj, template = infos[0]
159+ return template
160+
161
162 class POTemplateUploadView(LaunchpadView, TranslationsMixin):
163 """Upload translations and updated template."""
164
165=== modified file 'lib/lp/translations/browser/productseries.py'
166--- lib/lp/translations/browser/productseries.py 2011-02-02 15:43:31 +0000
167+++ lib/lp/translations/browser/productseries.py 2011-03-02 09:23:15 +0000
168@@ -61,6 +61,10 @@
169 from lp.translations.interfaces.translations import (
170 TranslationsBranchImportMode,
171 )
172+from lp.translations.utilities.translationsharinginfo import (
173+ has_ubuntu_template,
174+ get_ubuntu_sharing_info,
175+ )
176
177
178 class ProductSeriesTranslationsMenuMixIn:
179@@ -447,6 +451,17 @@
180 """Whether or not the user is a translations admin."""
181 return check_permission("launchpad.TranslationsAdmin", self.context)
182
183+ def is_sharing(self):
184+ return has_ubuntu_template(productseries=self.context)
185+
186+ @property
187+ def sharing_sourcepackage(self):
188+ infos = get_ubuntu_sharing_info(productseries=self.context)
189+ if len(infos) == 0:
190+ return None
191+ sourcepackage, template = infos[0]
192+ return sourcepackage
193+
194
195 class SettingsRadioWidget(LaunchpadRadioWidgetWithDescription):
196 """Remove the confusing hint under the widget."""
197
198=== modified file 'lib/lp/translations/browser/sourcepackage.py'
199--- lib/lp/translations/browser/sourcepackage.py 2010-08-20 20:31:18 +0000
200+++ lib/lp/translations/browser/sourcepackage.py 2011-03-02 09:23:15 +0000
201@@ -19,9 +19,14 @@
202 from lp.registry.interfaces.sourcepackage import ISourcePackage
203 from lp.translations.browser.poexportrequest import BaseExportView
204 from lp.translations.browser.translations import TranslationsMixin
205+from lp.translations.utilities.translationsharinginfo import (
206+ has_upstream_template,
207+ get_upstream_sharing_info,
208+ )
209
210
211 class SourcePackageTranslationsView(TranslationsMixin):
212+
213 @property
214 def potemplates(self):
215 return list(self.context.getCurrentTranslationTemplates())
216@@ -30,6 +35,18 @@
217 def label(self):
218 return "Translations for %s" % self.context.displayname
219
220+ def is_sharing(self):
221+ return has_upstream_template(self.context)
222+
223+ @property
224+ def sharing_productseries(self):
225+ infos = get_upstream_sharing_info(self.context)
226+ if len(infos) == 0:
227+ return None
228+
229+ productseries, template = infos[0]
230+ return productseries
231+
232
233 class SourcePackageTranslationsMenu(NavigationMenu):
234 usedfor = ISourcePackage
235
236=== added file 'lib/lp/translations/browser/tests/test_sharing_information.py'
237--- lib/lp/translations/browser/tests/test_sharing_information.py 1970-01-01 00:00:00 +0000
238+++ lib/lp/translations/browser/tests/test_sharing_information.py 2011-03-02 09:23:15 +0000
239@@ -0,0 +1,215 @@
240+# Copyright 2010 Canonical Ltd. This software is licensed under the
241+# GNU Affero General Public License version 3 (see the file LICENSE).
242+
243+"""Tests for the POTemplate recipe view classes and templates."""
244+
245+__metaclass__ = type
246+
247+from canonical.testing.layers import DatabaseFunctionalLayer
248+from canonical.launchpad.testing.pages import (
249+ extract_text,
250+ find_tag_by_id,
251+ )
252+from lp.app.enums import ServiceUsage
253+from lp.services.features.testing import FeatureFixture
254+from lp.testing import (
255+ BrowserTestCase,
256+ celebrity_logged_in,
257+ )
258+from lp.translations.interfaces.side import TranslationSide
259+
260+
261+def set_translations_usage(obj):
262+ """Set the translations_usage to LAUNCHPAD."""
263+ with celebrity_logged_in('admin'):
264+ obj.translations_usage = ServiceUsage.LAUNCHPAD
265+
266+
267+def enable_translations_on_distroseries(distroseries):
268+ with celebrity_logged_in('admin'):
269+ distroseries.hide_all_translations = False
270+
271+
272+class TestSharingInfoMixin:
273+ """Test display of sharing info."""
274+
275+ def _makePackagingAndTemplates(self, side):
276+ """Create a packaging links and the templates on each side of it.
277+
278+ Returns the template for the requested side.
279+ """
280+ upstream_template = self.factory.makePOTemplate()
281+ packaging = self.factory.makePackagingLink(
282+ productseries=upstream_template.productseries, in_ubuntu=True)
283+ ubuntu_template = self.factory.makePOTemplate(
284+ distroseries=packaging.distroseries,
285+ sourcepackagename=packaging.sourcepackagename,
286+ name=upstream_template.name)
287+ if side == TranslationSide.UPSTREAM:
288+ return upstream_template
289+ else:
290+ return ubuntu_template
291+
292+ def makeNotSharingObject(self):
293+ """Create an object that is not sharing."""
294+ raise NotImplementedError
295+
296+ NOT_SHARING_TEXT = None
297+
298+ def makeSharingObject(self):
299+ """Create an object that is sharing."""
300+ raise NotImplementedError
301+
302+ SHARING_TEXT = None
303+
304+ def _test_sharing_information(self, obj, expected_text):
305+ self.useFixture(FeatureFixture(
306+ {'translations.sharing_information.enabled': 'on'}))
307+ browser = self.getViewBrowser(
308+ obj, no_login=True, rootsite="translations")
309+ sharing_info = find_tag_by_id(browser.contents, 'sharing-information')
310+ if expected_text is None:
311+ self.assertIs(None, sharing_info)
312+ else:
313+ self.assertIsNot(None, sharing_info)
314+ self.assertTextMatchesExpressionIgnoreWhitespace(
315+ expected_text, extract_text(sharing_info))
316+
317+ def test_not_sharing(self):
318+ self._test_sharing_information(
319+ self.makeNotSharingObject(), self.NOT_SHARING_TEXT)
320+
321+ def test_sharing(self):
322+ self._test_sharing_information(
323+ self.makeSharingObject(), self.SHARING_TEXT)
324+
325+
326+class TestUpstreamPOTemplateSharingInfo(BrowserTestCase,
327+ TestSharingInfoMixin):
328+ """Test display of template sharing info."""
329+
330+ layer = DatabaseFunctionalLayer
331+
332+ def makeNotSharingObject(self):
333+ return self.factory.makePOTemplate()
334+
335+ NOT_SHARING_TEXT = """
336+ This template is not sharing translations with a template in an
337+ Ubuntu source package."""
338+
339+ def makeSharingObject(self):
340+ template = self._makePackagingAndTemplates(TranslationSide.UPSTREAM)
341+ return template
342+
343+ SHARING_TEXT = """
344+ This template is sharing translations with .*"""
345+
346+
347+class TestPOFileSharingInfo(BrowserTestCase, TestSharingInfoMixin):
348+ """Test display of POFile sharing info."""
349+
350+ layer = DatabaseFunctionalLayer
351+
352+ def makeNotSharingObject(self):
353+ return self.factory.makePOFile()
354+
355+ NOT_SHARING_TEXT = None
356+
357+ def makeSharingObject(self):
358+ template = self._makePackagingAndTemplates(TranslationSide.UPSTREAM)
359+ # This will also create a copy of pofile in the sharing template.
360+ pofile = self.factory.makePOFile(
361+ potemplate=template, create_sharing=True)
362+ return pofile
363+
364+ SHARING_TEXT = """
365+ These translations are shared with .*"""
366+
367+
368+class TestDummyPOFileSharingInfo(BrowserTestCase, TestSharingInfoMixin):
369+ """Test display of DummyPOFile sharing info."""
370+
371+ layer = DatabaseFunctionalLayer
372+
373+ def makeNotSharingObject(self):
374+ template = self.factory.makePOTemplate()
375+ return template.getDummyPOFile(self.factory.makeLanguage())
376+
377+ NOT_SHARING_TEXT = None
378+
379+ def makeSharingObject(self):
380+ template = self._makePackagingAndTemplates(TranslationSide.UPSTREAM)
381+ # This will also create a copy of pofile in the sharing template.
382+ return template.getDummyPOFile(self.factory.makeLanguage())
383+
384+ SHARING_TEXT = """
385+ These translations are shared with .*"""
386+
387+
388+class TestUpstreamSharingInfo(BrowserTestCase, TestSharingInfoMixin):
389+ """Test display of product series sharing info."""
390+
391+ layer = DatabaseFunctionalLayer
392+
393+ def makeNotSharingObject(self):
394+ productseries = self.factory.makeProductSeries()
395+ set_translations_usage(productseries.product)
396+ return productseries
397+
398+ NOT_SHARING_TEXT = """
399+ This project series is not sharing translations with an Ubuntu source
400+ package."""
401+
402+ def makeSharingObject(self):
403+ template = self._makePackagingAndTemplates(TranslationSide.UPSTREAM)
404+ return template.productseries
405+
406+ SHARING_TEXT = """
407+ This project series is sharing translations with .*"""
408+
409+
410+class TestUbuntuPOTemplateSharingInfo(BrowserTestCase, TestSharingInfoMixin):
411+ """Test display of template sharing info in an Ubuntu source package."""
412+
413+ layer = DatabaseFunctionalLayer
414+
415+ def makeNotSharingObject(self):
416+ template = self.factory.makePOTemplate(side=TranslationSide.UBUNTU)
417+ enable_translations_on_distroseries(template.distroseries)
418+ return template
419+
420+ NOT_SHARING_TEXT = """
421+ This template is not sharing translations with a template in an
422+ upstream project."""
423+
424+ def makeSharingObject(self):
425+ template = self._makePackagingAndTemplates(TranslationSide.UBUNTU)
426+ enable_translations_on_distroseries(template.distroseries)
427+ return template
428+
429+ SHARING_TEXT = """
430+ This template is sharing translations with .*"""
431+
432+
433+class TestUbuntuSharingInfo(BrowserTestCase, TestSharingInfoMixin):
434+ """Test display of source package sharing info."""
435+
436+ layer = DatabaseFunctionalLayer
437+
438+ def makeNotSharingObject(self):
439+ sourcepackage = self.factory.makeSourcePackage(
440+ distroseries=self.factory.makeUbuntuDistroSeries())
441+ enable_translations_on_distroseries(sourcepackage.distroseries)
442+ return sourcepackage
443+
444+ NOT_SHARING_TEXT = """
445+ This source package is not sharing translations with an upstream
446+ project."""
447+
448+ def makeSharingObject(self):
449+ template = self._makePackagingAndTemplates(TranslationSide.UBUNTU)
450+ enable_translations_on_distroseries(template.distroseries)
451+ return template.sourcepackage
452+
453+ SHARING_TEXT = """
454+ This source package is sharing translations with .*"""
455
456=== modified file 'lib/lp/translations/doc/potemplate.txt'
457--- lib/lp/translations/doc/potemplate.txt 2010-12-02 16:13:51 +0000
458+++ lib/lp/translations/doc/potemplate.txt 2011-03-02 09:23:15 +0000
459@@ -273,24 +273,6 @@
460 >>> len(potmsgsets)
461 0
462
463-== relatives_by_name ==
464-
465-This property gives us an iterator of IPOTemplate objects that have the
466-same name and are 'current'.
467-
468-This is the template we are working with:
469-
470- >>> potemplate.title
471- u'Template "evolution-2.2" in Evolution trunk'
472-
473-And this is the list of templates related with this one based on its
474-name:
475-
476- >>> for relative_potemplate in potemplate.relatives_by_name:
477- ... assert relative_potemplate.iscurrent
478- ... print relative_potemplate.title
479- Template "evolution-2.2" in Ubuntu Hoary package "evolution"
480-
481 == relatives_by_source ==
482
483 This property gives us an iterator of IPOTemplate objects that are in the
484
485=== modified file 'lib/lp/translations/interfaces/potemplate.py'
486--- lib/lp/translations/interfaces/potemplate.py 2011-02-14 17:14:17 +0000
487+++ lib/lp/translations/interfaces/potemplate.py 2011-03-02 09:23:15 +0000
488@@ -256,9 +256,6 @@
489 value_type=Reference(schema=Interface)),
490 exported_as='translation_files')
491
492- relatives_by_name = Attribute(
493- _('All `IPOTemplate` objects that have the same name asa this one.'))
494-
495 relatives_by_source = Attribute(
496 _('''All `IPOTemplate` objects that have the same source.
497 For example those that came from the same productseries or the
498
499=== modified file 'lib/lp/translations/model/potemplate.py'
500--- lib/lp/translations/model/potemplate.py 2011-02-24 14:57:45 +0000
501+++ lib/lp/translations/model/potemplate.py 2011-03-02 09:23:15 +0000
502@@ -351,13 +351,6 @@
503 return self.getTranslationPolicy().getEffectiveTranslationPermission()
504
505 @property
506- def relatives_by_name(self):
507- """See `IPOTemplate`."""
508- return POTemplate.select(
509- 'id <> %s AND name = %s AND iscurrent' % sqlvalues(
510- self, self.name), orderBy=['datecreated'])
511-
512- @property
513 def relatives_by_source(self):
514 """See `IPOTemplate`."""
515 if self.productseries is not None:
516
517=== modified file 'lib/lp/translations/stories/standalone/xx-potemplate-index.txt'
518--- lib/lp/translations/stories/standalone/xx-potemplate-index.txt 2010-12-30 12:50:16 +0000
519+++ lib/lp/translations/stories/standalone/xx-potemplate-index.txt 2011-03-02 09:23:15 +0000
520@@ -63,6 +63,42 @@
521 Finnish ... ... ... ... P\xf6ll\xe4
522
523
524+Sharing information
525+-------------------
526+
527+The template is sharing translations with the template of the same name in
528+the Ubuntu source package. This information is displayed on the page.
529+
530+ >>> from lp.services.features.testing import FeatureFixture
531+ >>> feature_flag = {'translations.sharing_information.enabled': 'on'}
532+ >>> with FeatureFixture(feature_flag):
533+ ... anon_browser.open('http://translations.launchpad.dev/evolution'
534+ ... '/trunk/+pots/evolution-2.2')
535+ >>> sharing_info = find_tag_by_id(
536+ ... anon_browser.contents, 'sharing-information')
537+ >>> print extract_text(sharing_info)
538+ Sharing Information
539+ This template is sharing translations with
540+ evolution in Ubuntu Hoary template evolution-2.2.
541+ >>> print sharing_info
542+ <div...<a href="/ubuntu/hoary/+source/evolution/+pots/evolution-2.2"...
543+
544+Likewise, the Ubuntu template gives information about how it is sharing
545+translations with the upstream project.
546+
547+ >>> with FeatureFixture(feature_flag):
548+ ... anon_browser.open('http://translations.launchpad.dev/ubuntu'
549+ ... '/hoary/+source/evolution/+pots/evolution-2.2')
550+ >>> sharing_info = find_tag_by_id(
551+ ... anon_browser.contents, 'sharing-information')
552+ >>> print extract_text(sharing_info)
553+ Sharing Information
554+ This template is sharing translations with
555+ Evolution trunk series template evolution-2.2.
556+ >>> print sharing_info
557+ <div...<a href="/evolution/trunk/+pots/evolution-2.2"...
558+
559+
560 Finding related templates
561 -------------------------
562
563@@ -85,32 +121,6 @@
564 </p>
565
566
567-DistroSeries and ProductSeries links to related templates
568----------------------------------------------------------
569-
570-We are presented not only with links to alternate templates from the same
571-source, but also with links to the same template in (other) distroseries.
572-
573- >>> anon_browser.open('http://translations.launchpad.dev/evolution'
574- ... '/trunk/+pots/evolution-2.2')
575- >>> alternate_notice = find_tag_by_id(anon_browser.contents,
576- ... 'potemplate-rel-by-name')
577- >>> print extract_text(alternate_notice)
578- Templates with the same name elsewhere: Ubuntu Hoary
579- >>> print alternate_notice
580- <p...<a href="/ubuntu/hoary/+source/evolution/+pots/evolution-2.2"...
581-
582-The template in the other distroseries links back to this one.
583-
584- >>> anon_browser.open('http://translations.launchpad.dev/ubuntu'
585- ... '/hoary/+source/evolution/+pots/evolution-2.2')
586- >>> alternate_notice = find_tag_by_id(anon_browser.contents,
587- ... 'potemplate-rel-by-name')
588- >>> print extract_text(alternate_notice)
589- Templates with the same name elsewhere: Evolution trunk
590- >>> print alternate_notice
591- <p...<a href="/evolution/trunk/+pots/evolution-2.2"...
592-
593 When the branch or the source package contains less than five templates
594 they are all displayed on the template page.
595
596
597=== modified file 'lib/lp/translations/templates/pofile-translate.pt'
598--- lib/lp/translations/templates/pofile-translate.pt 2010-12-02 16:13:51 +0000
599+++ lib/lp/translations/templates/pofile-translate.pt 2011-03-02 09:23:15 +0000
600@@ -60,6 +60,31 @@
601 <metal:nav-pofile-subpages
602 use-macro="context/@@+translations-macros/nav-pofile-subpages" />
603
604+ <!-- Sharing information -->
605+ <div tal:condition="features/translations.sharing_information.enabled">
606+ <div id="sharing-information"
607+ tal:condition="view/is_sharing">
608+ <p tal:define="sharing_pofile view/sharing_pofile;
609+ template sharing_pofile/potemplate">
610+ These translations are shared with
611+ <a class="sprite package-source"
612+ tal:condition="view/is_upstream_pofile"
613+ tal:content="template/sourcepackage/displayname"
614+ tal:attributes="href template/sourcepackage/fmt:url">
615+ apache in Ubuntu Hoary
616+ </a><a class="sprite product"
617+ tal:condition="not:view/is_upstream_pofile"
618+ tal:content="template/productseries/title"
619+ tal:attributes="href template/productseries/fmt:url">
620+ Evolution trunk
621+ </a> template
622+ <a tal:attributes="href sharing_pofile/fmt:url"
623+ tal:content="template/name"
624+ >evolution-2.2</a>.
625+ </p>
626+ </div>
627+ </div>
628+
629 <!-- View filter and suggestions from alternative language. -->
630 <form method="get" style="text-align: left;" action="+translate">
631 <!-- the hidden elements -->
632
633=== modified file 'lib/lp/translations/templates/potemplate-index.pt'
634--- lib/lp/translations/templates/potemplate-index.pt 2010-10-10 21:54:16 +0000
635+++ lib/lp/translations/templates/potemplate-index.pt 2011-03-02 09:23:15 +0000
636@@ -35,54 +35,6 @@
637 </div>
638
639 <div class="yui-g">
640- <div class="yui-b portlet">
641- <h3>Related templates</h3>
642- </div>
643- <div class="yui-u first">
644- <p tal:condition="context/relatives_by_source" id="potemplate-relatives">
645- <span>Other templates here:</span>
646- <tal:relatives_by_source repeat="pot view/related_templates_by_source">
647- <a href=""
648- tal:attributes="href pot/fmt:url"
649- tal:content="pot/name">A POTemplate
650- </a><tal:comma condition="not: repeat/pot/end">,
651- </tal:comma></tal:relatives_by_source><!--
652- --><tal:more-templates replace="structure view/more_templates_by_source_link">
653- and <a href="#">17 other templates</a>
654- </tal:more-templates>.
655- </p>
656- </div>
657-
658- <div class="yui-u">
659- <p tal:condition="context/relatives_by_name"
660- id="potemplate-rel-by-name">
661- <span>Templates with the same name elsewhere:</span>
662- <tal:relatives_by_name repeat="pot view/related_templates_by_name">
663- <tal:product condition="pot/productseries">
664- <a href=""
665- tal:attributes="href pot/fmt:url"
666- tal:content="string:${pot/productseries/product/displayname}
667- ${pot/productseries/displayname}">
668- A Product and ProductSeries
669- </a>
670- </tal:product><!--
671- --><tal:distro condition="pot/distroseries">
672- <a href=""
673- tal:attributes="href pot/fmt:url">
674- <tal:distro_name content="pot/distroseries/distribution/displayname">
675- A Distribution
676- </tal:distro_name>
677- <tal:distroseries_name content="pot/distroseries/displayname">
678- and DistroSeries</tal:distroseries_name></a><!--
679- --></tal:distro><tal:comma condition="not: repeat/pot/end">,
680- </tal:comma></tal:relatives_by_name><!--
681- --><tal:more condition="view/has_more_templates_by_name"
682- >...</tal:more>
683- </p>
684- </div>
685- </div>
686-
687- <div class="yui-g">
688 <div class="yui-u first">
689 <div class="portlet">
690 <h3>Permissions</h3>
691@@ -99,11 +51,58 @@
692 ">translation instructions</a>.
693 </p>
694 </div>
695+ <div class="portlet" id="sharing-information"
696+ tal:condition="features/translations.sharing_information.enabled">
697+ <h3>Sharing Information</h3>
698+ <p tal:condition="not:view/is_sharing">
699+ This template is not sharing translations with
700+ a template in an
701+ <span tal:condition="view/is_upstream_template">
702+ Ubuntu source package</span>
703+ <span tal:condition="not:view/is_upstream_template">
704+ upstream project</span>.
705+ </p>
706+ <p tal:condition="view/is_sharing"
707+ tal:define="template view/sharing_template">
708+ This template is sharing translations with
709+ <a class="sprite package-source"
710+ tal:condition="view/is_upstream_template"
711+ tal:content="template/sourcepackage/displayname"
712+ tal:attributes="href template/sourcepackage/fmt:url">
713+ apache in Ubuntu Hoary
714+ </a><a class="sprite product"
715+ tal:condition="not:view/is_upstream_template"
716+ tal:content="template/productseries/title"
717+ tal:attributes="href template/productseries/fmt:url">
718+ Evolution trunk
719+ </a> template
720+ <a tal:attributes="href template/fmt:url"
721+ tal:content="template/name"
722+ >evolution-2.2</a>.
723+ </p>
724+ </div>
725 </div>
726
727- <div class="yui-u"
728+ <div class="yui-u">
729+ <div class="portlet"
730+ tal:condition="context/relatives_by_source">
731+ <h3>Related templates</h3>
732+ <p id="potemplate-relatives">
733+ <span>Other templates here:</span>
734+ <tal:relatives_by_source repeat="pot view/related_templates_by_source">
735+ <a href=""
736+ tal:attributes="href pot/fmt:url"
737+ tal:content="pot/name">A POTemplate
738+ </a><tal:comma condition="not: repeat/pot/end">, </tal:comma
739+ ></tal:relatives_by_source><tal:more-templates
740+ replace="structure view/more_templates_by_source_link">
741+ and <a href="#">17 other templates</a>
742+ </tal:more-templates>.
743+ </p>
744+ </div>
745+
746+ <div class="portlet"
747 tal:condition="context/required:launchpad.AnyPerson">
748- <div class="portlet">
749 <h3>Administration</h3>
750 <p>If you want to synchronize these translations manually, you
751 can
752
753=== modified file 'lib/lp/translations/templates/productseries-translations.pt'
754--- lib/lp/translations/templates/productseries-translations.pt 2010-11-03 13:04:59 +0000
755+++ lib/lp/translations/templates/productseries-translations.pt 2011-03-02 09:23:15 +0000
756@@ -76,6 +76,21 @@
757 ">translation instructions</a> first.
758 </p>
759 </div>
760+ <div class="portlet" id="sharing-information"
761+ tal:condition="features/translations.sharing_information.enabled">
762+ <h3>Sharing Information</h3>
763+ <p tal:condition="not:view/is_sharing">
764+ This project series is not sharing translations with
765+ an Ubuntu source package.
766+ </p>
767+ <p tal:condition="view/is_sharing"
768+ tal:define="package view/sharing_sourcepackage">
769+ This project series is sharing translations with
770+ <a class="sprite package-source"
771+ tal:attributes="href package/fmt:url"
772+ tal:content="package/displayname">apache in ubuntu hoary</a>.
773+ </p>
774+ </div>
775 </div>
776
777 <div class="yui-u">
778
779=== modified file 'lib/lp/translations/templates/sourcepackage-translations.pt'
780--- lib/lp/translations/templates/sourcepackage-translations.pt 2010-12-21 15:13:17 +0000
781+++ lib/lp/translations/templates/sourcepackage-translations.pt 2011-03-02 09:23:15 +0000
782@@ -24,8 +24,24 @@
783 context/distroseries/distribution/@@+portlet-translation-groups-and-permission"/>
784 </p>
785 </div>
786+ <div class="portlet" id="sharing-information"
787+ tal:condition="features/translations.sharing_information.enabled">
788+ <h3>Sharing Information</h3>
789+ <p tal:condition="not:view/is_sharing">
790+ This source package is not sharing translations with
791+ an upstream project.
792+ </p>
793+ <p tal:condition="view/is_sharing"
794+ tal:define="productseries view/sharing_productseries">
795+ This source package is sharing translations with
796+ <a class="sprite product"
797+ tal:attributes="href productseries/fmt:url"
798+ tal:content="productseries/title">Evolution trunk</a>.
799+ </p>
800+ </div>
801 </div>
802 <div class="yui-u">
803+
804 <div class="portlet">
805 <h3>Administration</h3>
806 <p>Translation files that are waiting to be imported are shown in
807
808=== modified file 'lib/lp/translations/utilities/translationsharinginfo.py'
809--- lib/lp/translations/utilities/translationsharinginfo.py 2011-02-23 11:53:06 +0000
810+++ lib/lp/translations/utilities/translationsharinginfo.py 2011-03-02 09:23:15 +0000
811@@ -152,9 +152,10 @@
812
813 def get_ubuntu_sharing_info(productseries, templatename=None):
814 """Return a list of sharing information for the given target."""
815- for result in find_ubuntu_sharing_info(productseries, templatename):
816- distroseries, sourcepackagename, templatename = result
817- yield (SourcePackage(sourcepackagename, distroseries), templatename)
818+ return [
819+ (SourcePackage(packagename, series), name)
820+ for series, packagename, name in find_ubuntu_sharing_info(
821+ productseries, templatename)]
822
823
824 def get_upstream_sharing_info(sourcepackage, templatename=None):