11411.7.24
by j.c.sackett
Merged from devel. |
1 |
# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
|
8687.15.18
by Karl Fogel
Add the copyright header block to files under lib/canonical/. |
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
10744.6.3
by Adi Roiban
Add a fueld error message containing a real sentence. |
3 |
# pylint: disable-msg=F0401
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
4 |
|
1988
by Canonical.com Patch Queue Manager
[r=salgado] RosettaMultipleFormatExports |
5 |
"""Browser code for PO templates."""
|
6 |
||
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
7 |
__metaclass__ = type |
8 |
||
1988
by Canonical.com Patch Queue Manager
[r=salgado] RosettaMultipleFormatExports |
9 |
__all__ = [ |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
10 |
'POTemplateAdminView', |
9483.1.1
by Danilo Šegan
Re-revert 9477 minus branch-links update. |
11 |
'POTemplateBreadcrumb', |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
12 |
'POTemplateEditView', |
13 |
'POTemplateFacets', |
|
14 |
'POTemplateExportView', |
|
8255.12.1
by Henning Eggers
Moved POTemplate pages to NavigationMenu. |
15 |
'POTemplateMenu', |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
16 |
'POTemplateNavigation', |
17 |
'POTemplateSetNavigation', |
|
18 |
'POTemplateSubsetNavigation', |
|
19 |
'POTemplateSubsetURL', |
|
20 |
'POTemplateSubsetView', |
|
21 |
'POTemplateURL', |
|
9264.2.5
by Danilo Šegan
Migrate potemplate-upload.pt and move page_title for pofile-upload.pt into view as well. |
22 |
'POTemplateUploadView', |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
23 |
'POTemplateView', |
24 |
'POTemplateViewPreferred', |
|
10095.5.1
by Adi Roiban
Initial fix. Pagetests needs to be updated. |
25 |
'BaseSeriesTemplatesView', |
1716.1.190
by Christian Reis
Merge from RF, again, this time for real |
26 |
]
|
1988
by Canonical.com Patch Queue Manager
[r=salgado] RosettaMultipleFormatExports |
27 |
|
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
28 |
import cgi |
5548.2.2
by Carlos Perello Marin
Improved test to confirm that translation domain is changed when the form is submitted and also, that we update the potemplate's date_last_changed |
29 |
import datetime |
3691.93.33
by Christian Reis
Various random cleanups, including swapping lambdas for operator.attrgetter |
30 |
import operator |
3691.457.39
by Carlos Perello Marin
Removed more format dependent code from browser code |
31 |
import os.path |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
32 |
|
13931.2.1
by Steve Kowalik
Chip away at canonical.lazr a little more. |
33 |
from lazr.restful.utils import smartquote |
14550.1.1
by Steve Kowalik
Run format-imports over lib/lp and lib/canonical/launchpad |
34 |
import pytz |
13378.3.12
by Benji York
checkpoint |
35 |
from storm.expr import ( |
36 |
And, |
|
37 |
Or, |
|
38 |
)
|
|
14550.1.1
by Steve Kowalik
Run format-imports over lib/lp and lib/canonical/launchpad |
39 |
from storm.info import ClassAlias |
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
40 |
from zope.component import getUtility |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
41 |
from zope.interface import implements |
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
42 |
from zope.publisher.browser import FileUpload |
10180.3.3
by Adi Roiban
Fix date_last_update permission. |
43 |
from zope.security.proxy import removeSecurityProxy |
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
44 |
|
14600.1.12
by Curtis Hovey
Move i18n to lp. |
45 |
from lp import _ |
14612.2.1
by William Grant
format-imports on lib/. So many imports. |
46 |
from lp.app.browser.launchpadform import ReturnToReferrerMixin |
47 |
from lp.app.browser.tales import DateTimeFormatterAPI |
|
48 |
from lp.app.enums import ( |
|
49 |
service_uses_launchpad, |
|
50 |
ServiceUsage, |
|
51 |
)
|
|
52 |
from lp.app.errors import NotFoundError |
|
53 |
from lp.app.validators.name import valid_name |
|
54 |
from lp.registry.browser.productseries import ProductSeriesFacets |
|
55 |
from lp.registry.browser.sourcepackage import SourcePackageFacets |
|
56 |
from lp.registry.interfaces.productseries import IProductSeries |
|
57 |
from lp.registry.interfaces.role import IPersonRoles |
|
58 |
from lp.registry.interfaces.sourcepackage import ISourcePackage |
|
59 |
from lp.registry.model.packaging import Packaging |
|
60 |
from lp.registry.model.product import Product |
|
61 |
from lp.registry.model.productseries import ProductSeries |
|
62 |
from lp.registry.model.sourcepackagename import SourcePackageName |
|
63 |
from lp.services.helpers import is_tar_filename |
|
14600.2.2
by Curtis Hovey
Moved webapp to lp.services. |
64 |
from lp.services.webapp import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
65 |
action, |
66 |
canonical_url, |
|
67 |
enabled_with_permission, |
|
68 |
GetitemNavigation, |
|
69 |
LaunchpadEditFormView, |
|
70 |
LaunchpadView, |
|
71 |
Link, |
|
72 |
Navigation, |
|
73 |
NavigationMenu, |
|
74 |
StandardLaunchpadFacets, |
|
75 |
)
|
|
14600.2.2
by Curtis Hovey
Moved webapp to lp.services. |
76 |
from lp.services.webapp.authorization import check_permission |
77 |
from lp.services.webapp.breadcrumb import Breadcrumb |
|
78 |
from lp.services.webapp.interfaces import ( |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
79 |
ICanonicalUrlData, |
80 |
ILaunchBag, |
|
81 |
)
|
|
14600.2.2
by Curtis Hovey
Moved webapp to lp.services. |
82 |
from lp.services.webapp.menu import structured |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
83 |
from lp.services.worlddata.interfaces.language import ILanguageSet |
84 |
from lp.translations.browser.poexportrequest import BaseExportView |
|
85 |
from lp.translations.browser.translations import TranslationsMixin |
|
12428.4.32
by Henning Eggers
Implemented for potemplate but still failing for sourcepackage. |
86 |
from lp.translations.browser.translationsharing import ( |
87 |
TranslationSharingDetailsMixin, |
|
88 |
)
|
|
8751.1.1
by Danilo Šegan
Store migration changes so far. |
89 |
from lp.translations.interfaces.pofile import IPOFileSet |
90 |
from lp.translations.interfaces.potemplate import ( |
|
8751.1.8
by Danilo Šegan
Fix most lint warnings. |
91 |
IPOTemplate, |
92 |
IPOTemplateSet, |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
93 |
IPOTemplateSubset, |
94 |
)
|
|
12428.4.11
by Henning Eggers
Removed lint. |
95 |
from lp.translations.interfaces.side import TranslationSide |
8751.1.8
by Danilo Šegan
Fix most lint warnings. |
96 |
from lp.translations.interfaces.translationimporter import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
97 |
ITranslationImporter, |
98 |
)
|
|
8751.1.8
by Danilo Šegan
Fix most lint warnings. |
99 |
from lp.translations.interfaces.translationimportqueue import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
100 |
ITranslationImportQueue, |
101 |
)
|
|
14550.1.1
by Steve Kowalik
Run format-imports over lib/lp and lib/canonical/launchpad |
102 |
from lp.translations.model.potemplate import POTemplate |
1716.1.190
by Christian Reis
Merge from RF, again, this time for real |
103 |
|
104 |
||
105 |
class POTemplateNavigation(Navigation): |
|
106 |
||
107 |
usedfor = IPOTemplate |
|
108 |
||
109 |
def traverse(self, name): |
|
3452.1.1
by Carlos Perello Marin
Restructured the way we create pofiles and fixed the security problem raised by bug #2529 |
110 |
"""Return the IPOFile associated with the given name."""
|
111 |
||
112 |
assert self.request.method in ['GET', 'HEAD', 'POST'], ( |
|
113 |
'We only know about GET, HEAD, and POST') |
|
114 |
||
1716.1.190
by Christian Reis
Merge from RF, again, this time for real |
115 |
user = getUtility(ILaunchBag).user |
3504.3.5
by Carlos Perello Marin
Improved the way we use DummyPOMsgSet |
116 |
|
4452.4.1
by Curtis Hovey
Added a pair of rules to not permit users to see the English list of translations, and for the SQL to not return English in the list of translations. Revised the tests. |
117 |
# We do not want users to see the 'en' potemplate because
|
118 |
# we store the messages we want to translate as English.
|
|
119 |
if name == 'en': |
|
120 |
raise NotFoundError(name) |
|
121 |
||
3504.3.5
by Carlos Perello Marin
Improved the way we use DummyPOMsgSet |
122 |
pofile = self.context.getPOFileByLang(name) |
123 |
||
124 |
if pofile is not None: |
|
125 |
# Already have a valid POFile entry, just return it.
|
|
3452.1.1
by Carlos Perello Marin
Restructured the way we create pofiles and fixed the security problem raised by bug #2529 |
126 |
return pofile |
3504.3.5
by Carlos Perello Marin
Improved the way we use DummyPOMsgSet |
127 |
elif self.request.method in ['GET', 'HEAD']: |
128 |
# It's just a query, get a fake one so we don't create new
|
|
129 |
# POFiles just because someone is browsing the web.
|
|
11196.4.1
by Danilo Šegan
Change getDummyPOFile to accept actual language as the parameter instead of language code. |
130 |
language = getUtility(ILanguageSet).getLanguageByCode(name) |
11411.7.24
by j.c.sackett
Merged from devel. |
131 |
if language is None: |
132 |
raise NotFoundError(name) |
|
133 |
return self.context.getDummyPOFile( |
|
134 |
language, requester=user, check_for_existing=False) |
|
1716.1.190
by Christian Reis
Merge from RF, again, this time for real |
135 |
else: |
3452.1.2
by Carlos Perello Marin
Added a migration script and a test |
136 |
# It's a POST.
|
9953.1.2
by Jeroen Vermeulen
Lift conditional setting of POFile.owner out of newPOFile. |
137 |
# XXX CarlosPerelloMarin 2006-04-20 bug=40275: We should
|
138 |
# check the kind of POST we got. A logout will also be a
|
|
139 |
# POST and we should not create a POFile in that case.
|
|
7675.916.98
by Henning Eggers
Merged db-stable at r10026 (recife roll-back) but without accepting the changes. |
140 |
return self.context.newPOFile(name, owner=user) |
2148
by Canonical.com Patch Queue Manager
[r=SteveA] menus for Rosetta |
141 |
|
142 |
||
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
143 |
class POTemplateFacets(StandardLaunchpadFacets): |
144 |
usedfor = IPOTemplate |
|
145 |
||
146 |
def __init__(self, context): |
|
147 |
StandardLaunchpadFacets.__init__(self, context) |
|
148 |
target = context.translationtarget |
|
149 |
if IProductSeries.providedBy(target): |
|
7847.1.42
by Jonathan Lange
Make all the pagetests pass. |
150 |
self._is_product_series = True |
4055.2.10
by Carlos Perello Marin
Applied review comments |
151 |
self.target_facets = ProductSeriesFacets(target) |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
152 |
elif ISourcePackage.providedBy(target): |
7847.1.42
by Jonathan Lange
Make all the pagetests pass. |
153 |
self._is_product_series = False |
4055.2.10
by Carlos Perello Marin
Applied review comments |
154 |
self.target_facets = SourcePackageFacets(target) |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
155 |
else: |
156 |
# We don't know yet how to handle this target.
|
|
157 |
raise NotImplementedError |
|
158 |
||
159 |
# Enable only the menus that the translation target uses.
|
|
4055.2.10
by Carlos Perello Marin
Applied review comments |
160 |
self.enable_only = self.target_facets.enable_only |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
161 |
|
162 |
# From an IPOTemplate URL, we reach its translationtarget (either
|
|
163 |
# ISourcePackage or IProductSeries using self.target.
|
|
4055.2.3
by Carlos Perello Marin
Fixed page title and heading for IProductSeries and ISourcePackage +translations pages and moved to use a shared template. Fixed Structural Object heading for IPOMsgSet |
164 |
self.target = '../../' |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
165 |
|
166 |
def overview(self): |
|
4055.2.10
by Carlos Perello Marin
Applied review comments |
167 |
overview_link = self.target_facets.overview() |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
168 |
overview_link.target = self.target |
169 |
return overview_link |
|
170 |
||
171 |
def translations(self): |
|
4055.2.10
by Carlos Perello Marin
Applied review comments |
172 |
translations_link = self.target_facets.translations() |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
173 |
translations_link.target = self.target |
174 |
return translations_link |
|
175 |
||
176 |
def bugs(self): |
|
4055.2.10
by Carlos Perello Marin
Applied review comments |
177 |
bugs_link = self.target_facets.bugs() |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
178 |
bugs_link.target = self.target |
179 |
return bugs_link |
|
180 |
||
181 |
def answers(self): |
|
4055.2.10
by Carlos Perello Marin
Applied review comments |
182 |
answers_link = self.target_facets.answers() |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
183 |
answers_link.target = self.target |
184 |
return answers_link |
|
185 |
||
186 |
def specifications(self): |
|
4055.2.10
by Carlos Perello Marin
Applied review comments |
187 |
specifications_link = self.target_facets.specifications() |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
188 |
specifications_link.target = self.target |
189 |
return specifications_link |
|
190 |
||
191 |
def branches(self): |
|
4055.2.10
by Carlos Perello Marin
Applied review comments |
192 |
branches_link = self.target_facets.branches() |
7847.1.42
by Jonathan Lange
Make all the pagetests pass. |
193 |
if not self._is_product_series: |
194 |
branches_link.target = self.target |
|
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
195 |
return branches_link |
196 |
||
197 |
||
8255.12.1
by Henning Eggers
Moved POTemplate pages to NavigationMenu. |
198 |
class POTemplateMenu(NavigationMenu): |
199 |
"""Navigation menus for `IPOTemplate` objects."""
|
|
2148
by Canonical.com Patch Queue Manager
[r=SteveA] menus for Rosetta |
200 |
usedfor = IPOTemplate |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
201 |
facet = 'translations' |
8255.12.1
by Henning Eggers
Moved POTemplate pages to NavigationMenu. |
202 |
# XXX: henninge 2009-04-22 bug=365112: The order in this list was
|
203 |
# rearranged so that the last item is public. The desired order is:
|
|
204 |
# links = ['overview', 'upload', 'download', 'edit', 'administer']
|
|
205 |
links = ['overview', 'edit', 'administer', 'upload', 'download'] |
|
2548
by Canonical.com Patch Queue Manager
r=bjornt, plus some [trivial], lots of menus work, special error page for request timeouts. |
206 |
|
8255.12.1
by Henning Eggers
Moved POTemplate pages to NavigationMenu. |
207 |
def overview(self): |
208 |
text = 'Overview' |
|
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
209 |
return Link('', text) |
210 |
||
6691.3.1
by Jeroen Vermeulen
Prospective fix. Commit so I can merge RF. |
211 |
@enabled_with_permission('launchpad.Edit') |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
212 |
def upload(self): |
8255.12.1
by Henning Eggers
Moved POTemplate pages to NavigationMenu. |
213 |
text = 'Upload' |
10095.5.7
by Adi Roiban
Use link formatter for actions |
214 |
return Link('+upload', text, icon='add') |
4055.2.2
by Carlos Perello Marin
Fixed Tabs and Structural Objects info as agreed with mpt. Moved BaseExportView from IPOFile to IPOTemplate to prevent an inline import |
215 |
|
2548
by Canonical.com Patch Queue Manager
r=bjornt, plus some [trivial], lots of menus work, special error page for request timeouts. |
216 |
def download(self): |
8255.12.1
by Henning Eggers
Moved POTemplate pages to NavigationMenu. |
217 |
text = 'Download' |
10095.5.7
by Adi Roiban
Use link formatter for actions |
218 |
return Link('+export', text, icon='download') |
2548
by Canonical.com Patch Queue Manager
r=bjornt, plus some [trivial], lots of menus work, special error page for request timeouts. |
219 |
|
6691.3.5
by Jeroen Vermeulen
Made options-printing test helper a bit more flexible. |
220 |
@enabled_with_permission('launchpad.Edit') |
2880.2.6
by Carlos Perelló Marín
Fixes for the translation form |
221 |
def edit(self): |
10095.5.7
by Adi Roiban
Use link formatter for actions |
222 |
text = 'Edit' |
223 |
return Link('+edit', text, icon='edit') |
|
2880.2.6
by Carlos Perelló Marín
Fixes for the translation form |
224 |
|
9962.8.2
by Adi Roiban
Instead of launchpad.Admin, use launchpad.TranslationsAdmin as it is more specific |
225 |
@enabled_with_permission('launchpad.TranslationsAdmin') |
2548
by Canonical.com Patch Queue Manager
r=bjornt, plus some [trivial], lots of menus work, special error page for request timeouts. |
226 |
def administer(self): |
3847.2.15
by Mark Shuttleworth
Consistency in menu text and capitalisation |
227 |
text = 'Administer' |
10095.5.7
by Adi Roiban
Use link formatter for actions |
228 |
return Link('+admin', text, icon='edit') |
2148
by Canonical.com Patch Queue Manager
[r=SteveA] menus for Rosetta |
229 |
|
1715
by Canonical.com Patch Queue Manager
Moved the translation form from potemplate context into pofile context. r=SteveA |
230 |
|
231 |
class POTemplateSubsetView: |
|
1501
by Canonical.com Patch Queue Manager
First merge of POTemplateLinkages |
232 |
|
233 |
def __init__(self, context, request): |
|
234 |
self.context = context |
|
235 |
self.request = request |
|
1561
by Canonical.com Patch Queue Manager
Rosetta Polish about portlets and URLs |
236 |
|
237 |
def __call__(self): |
|
238 |
# We are not using this context directly, only for traversals.
|
|
3618.1.43
by Steve Alexander
add note about response.redirect() semantics and fix some trivially failing page tests. |
239 |
self.request.response.redirect('../+translations') |
1528
by Canonical.com Patch Queue Manager
DistroReleaseTranslationList implementation |
240 |
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
241 |
|
12428.4.32
by Henning Eggers
Implemented for potemplate but still failing for sourcepackage. |
242 |
class POTemplateView(LaunchpadView, |
243 |
TranslationsMixin, TranslationSharingDetailsMixin): |
|
1706
by Canonical.com Patch Queue Manager
fixrosettatemplateviews |
244 |
|
9483.1.1
by Danilo Šegan
Re-revert 9477 minus branch-links update. |
245 |
SHOW_RELATED_TEMPLATES = 4 |
246 |
||
9481.2.2
by Henning Eggers
Fixed labels and page_titles on pofile and potemplate pages. |
247 |
label = "Translation status" |
248 |
||
2570.1.39
by Carlos Perelló Marín
Fixed many tests |
249 |
def initialize(self): |
5512.2.5
by Matthew Paul Thomas
Reverts accidental changes from the rocketfuel merge. |
250 |
"""Get the requested languages and submit the form."""
|
3531.1.15
by Carlos Perello Marin
Restored something I shouldn't remove... |
251 |
self.description = self.context.description |
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
252 |
|
3348.1.25
by Mark Shuttleworth
Test fixes and productseries page cleanup. |
253 |
def requestPoFiles(self): |
254 |
"""Yield a POFile or DummyPOFile for each of the languages in the
|
|
255 |
request, which includes country languages from the request IP,
|
|
256 |
browser preferences, and/or personal Launchpad language prefs.
|
|
257 |
"""
|
|
4346.7.2
by Curtis Hovey
Added a mixin class to provide the Person's translatable_languages. |
258 |
for language in self._sortLanguages(self.translatable_languages): |
3691.93.33
by Christian Reis
Various random cleanups, including swapping lambdas for operator.attrgetter |
259 |
yield self._getPOFileOrDummy(language) |
3348.1.25
by Mark Shuttleworth
Test fixes and productseries page cleanup. |
260 |
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
261 |
def num_messages(self): |
262 |
N = self.context.messageCount() |
|
263 |
if N == 0: |
|
264 |
return "no messages at all" |
|
265 |
elif N == 1: |
|
266 |
return "1 message" |
|
267 |
else: |
|
268 |
return "%s messages" % N |
|
269 |
||
3691.95.1
by Danilo Šegan
Fix bug #2237: simplify potemplate views and review responses. |
270 |
def pofiles(self, preferred_only=False): |
1706
by Canonical.com Patch Queue Manager
fixrosettatemplateviews |
271 |
"""Iterate languages shown when viewing this PO template.
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
272 |
|
1818
by Canonical.com Patch Queue Manager
[r=spiv] teams of translators to be organised as groups by language |
273 |
Yields a POFileView object for each language this template has
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
274 |
been translated into, and for each of the user's languages.
|
1706
by Canonical.com Patch Queue Manager
fixrosettatemplateviews |
275 |
Where the template has no POFile for that language, we use
|
276 |
a DummyPOFile.
|
|
277 |
"""
|
|
4055.2.10
by Carlos Perello Marin
Applied review comments |
278 |
# This inline import is needed to workaround a circular import problem
|
8751.1.1
by Danilo Šegan
Store migration changes so far. |
279 |
# because lp.translations.browser.pofile imports
|
280 |
# lp.translations.browser.potemplate.
|
|
281 |
from lp.translations.browser.pofile import POFileView |
|
3691.95.1
by Danilo Šegan
Fix bug #2237: simplify potemplate views and review responses. |
282 |
|
4346.7.2
by Curtis Hovey
Added a mixin class to provide the Person's translatable_languages. |
283 |
languages = self.translatable_languages |
3691.93.33
by Christian Reis
Various random cleanups, including swapping lambdas for operator.attrgetter |
284 |
if not preferred_only: |
3691.95.1
by Danilo Šegan
Fix bug #2237: simplify potemplate views and review responses. |
285 |
# Union the languages the template has been translated into with
|
286 |
# the user's selected languages.
|
|
3691.93.33
by Christian Reis
Various random cleanups, including swapping lambdas for operator.attrgetter |
287 |
languages = set(self.context.languages()) | set(languages) |
3691.95.1
by Danilo Šegan
Fix bug #2237: simplify potemplate views and review responses. |
288 |
|
3691.93.33
by Christian Reis
Various random cleanups, including swapping lambdas for operator.attrgetter |
289 |
for language in self._sortLanguages(languages): |
290 |
pofile = self._getPOFileOrDummy(language) |
|
2570.1.39
by Carlos Perelló Marín
Fixed many tests |
291 |
pofileview = POFileView(pofile, self.request) |
292 |
# Initialize the view.
|
|
293 |
pofileview.initialize() |
|
294 |
yield pofileview |
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
295 |
|
4147.1.2
by Danilo Šegan
Improve test, fix remaining cases. |
296 |
@property
|
9483.1.1
by Danilo Šegan
Re-revert 9477 minus branch-links update. |
297 |
def group_parent(self): |
10089.2.6
by Adi Roiban
Change translations admin for product/project/distro |
298 |
"""Return a parent object implementing `ITranslationPolicy`."""
|
9483.1.1
by Danilo Šegan
Re-revert 9477 minus branch-links update. |
299 |
if self.context.productseries is not None: |
300 |
return self.context.productseries.product |
|
301 |
else: |
|
302 |
return self.context.distroseries.distribution |
|
303 |
||
304 |
@property
|
|
305 |
def has_translation_documentation(self): |
|
306 |
"""Are there translation instructions for this project."""
|
|
307 |
translation_group = self.group_parent.translationgroup |
|
308 |
return (translation_group is not None and |
|
309 |
translation_group.translation_guide_url is not None) |
|
310 |
||
311 |
@property
|
|
312 |
def related_templates_by_source(self): |
|
313 |
by_source = list( |
|
314 |
self.context.relatives_by_source[:self.SHOW_RELATED_TEMPLATES]) |
|
315 |
return by_source |
|
316 |
||
317 |
@property
|
|
10008.1.7
by Adi Roiban
Fix typos. Rename more_templates_by_source_link. |
318 |
def more_templates_by_source_link(self): |
9483.1.1
by Danilo Šegan
Re-revert 9477 minus branch-links update. |
319 |
by_source_count = self.context.relatives_by_source.count() |
10008.1.1
by Adi Roiban
Initial implementation. New stories required. |
320 |
if (by_source_count > self.SHOW_RELATED_TEMPLATES): |
10008.1.2
by Adi Roiban
Add test stories for covering new functionalities. |
321 |
other = by_source_count - self.SHOW_RELATED_TEMPLATES |
10008.1.4
by Adi Roiban
Fix issues raised during the review. |
322 |
if (self.context.distroseries): |
13715.1.2
by Danilo Segan
Drive-by cleanup to remove an irrelevant XXX. |
323 |
sourcepackage = self.context.distroseries.getSourcePackage( |
324 |
self.context.sourcepackagename) |
|
325 |
url = canonical_url( |
|
326 |
sourcepackage, rootsite="translations", |
|
327 |
view_name='+translations') |
|
10008.1.4
by Adi Roiban
Fix issues raised during the review. |
328 |
else: |
329 |
url = canonical_url( |
|
330 |
self.context.productseries, |
|
331 |
rootsite="translations", |
|
332 |
view_name="+templates") |
|
10008.1.1
by Adi Roiban
Initial implementation. New stories required. |
333 |
if other == 1: |
10008.1.9
by Adi Roiban
Fix the dot. |
334 |
return " and <a href=\"%s\">one other template</a>" % url |
10008.1.1
by Adi Roiban
Initial implementation. New stories required. |
335 |
else: |
10008.1.9
by Adi Roiban
Fix the dot. |
336 |
return " and <a href=\"%s\">%d other templates</a>" % ( |
10008.1.4
by Adi Roiban
Fix issues raised during the review. |
337 |
url, other) |
10008.1.1
by Adi Roiban
Initial implementation. New stories required. |
338 |
else: |
10008.1.4
by Adi Roiban
Fix issues raised during the review. |
339 |
return "" |
9483.1.1
by Danilo Šegan
Re-revert 9477 minus branch-links update. |
340 |
|
341 |
@property
|
|
4147.1.3
by Danilo Šegan
Implement salgado's review suggestions: cleanup test mostly. |
342 |
def has_pofiles(self): |
4346.7.4
by Curtis Hovey
Fixed formatting. |
343 |
languages = set( |
344 |
self.context.languages()).union(self.translatable_languages) |
|
4147.1.3
by Danilo Šegan
Implement salgado's review suggestions: cleanup test mostly. |
345 |
return len(languages) > 0 |
4147.1.2
by Danilo Šegan
Improve test, fix remaining cases. |
346 |
|
3691.93.33
by Christian Reis
Various random cleanups, including swapping lambdas for operator.attrgetter |
347 |
def _sortLanguages(self, languages): |
348 |
return sorted(languages, key=operator.attrgetter('englishname')) |
|
349 |
||
350 |
def _getPOFileOrDummy(self, language): |
|
351 |
pofile = self.context.getPOFileByLang(language.code) |
|
352 |
if pofile is None: |
|
353 |
pofileset = getUtility(IPOFileSet) |
|
354 |
pofile = pofileset.getDummy(self.context, language) |
|
355 |
return pofile |
|
356 |
||
12428.4.8
by Henning Eggers
Works for Ubuntu templates. |
357 |
@property
|
358 |
def is_upstream_template(self): |
|
359 |
return self.context.translation_side == TranslationSide.UPSTREAM |
|
360 |
||
12428.4.6
by Henning Eggers
Implemented for templates in productseries. |
361 |
def is_sharing(self): |
12622.6.26
by Henning Eggers
Removed lint. |
362 |
potemplate = self.context.getOtherSidePOTemplate() |
12622.6.20
by Henning Eggers
Removed all uses of collections outside of HasTranslationTemplates. |
363 |
return potemplate is not None |
12428.4.6
by Henning Eggers
Implemented for templates in productseries. |
364 |
|
365 |
@property
|
|
366 |
def sharing_template(self): |
|
12622.6.10
by Henning Eggers
Removed call sites for get_*_sharing_info. |
367 |
return self.context.getOtherSidePOTemplate() |
12428.4.6
by Henning Eggers
Implemented for templates in productseries. |
368 |
|
12622.9.7
by Henning Eggers
Restrict display of links to sourcepacakge pages. |
369 |
def getTranslationSourcePackage(self): |
12428.4.32
by Henning Eggers
Implemented for potemplate but still failing for sourcepackage. |
370 |
"""See `TranslationSharingDetailsMixin`."""
|
371 |
if self.is_upstream_template: |
|
12622.9.7
by Henning Eggers
Restrict display of links to sourcepacakge pages. |
372 |
productseries = self.context.productseries |
373 |
return productseries.getUbuntuTranslationFocusPackage() |
|
12428.4.32
by Henning Eggers
Implemented for potemplate but still failing for sourcepackage. |
374 |
else: |
375 |
return self.context.sourcepackage |
|
376 |
||
9264.2.10
by Danilo Šegan
Fix up whitespace and most of the review comments. |
377 |
|
9264.2.5
by Danilo Šegan
Migrate potemplate-upload.pt and move page_title for pofile-upload.pt into view as well. |
378 |
class POTemplateUploadView(LaunchpadView, TranslationsMixin): |
379 |
"""Upload translations and updated template."""
|
|
380 |
||
9481.2.2
by Henning Eggers
Fixed labels and page_titles on pofile and potemplate pages. |
381 |
label = "Upload translations" |
382 |
page_title = "Upload translations" |
|
383 |
||
9264.2.5
by Danilo Šegan
Migrate potemplate-upload.pt and move page_title for pofile-upload.pt into view as well. |
384 |
@property
|
9264.2.10
by Danilo Šegan
Fix up whitespace and most of the review comments. |
385 |
def cancel_url(self): |
386 |
return canonical_url(self.context) |
|
387 |
||
9264.2.5
by Danilo Šegan
Migrate potemplate-upload.pt and move page_title for pofile-upload.pt into view as well. |
388 |
def initialize(self): |
389 |
"""Get the requested languages and submit the form."""
|
|
390 |
self.submitForm() |
|
9264.2.10
by Danilo Šegan
Fix up whitespace and most of the review comments. |
391 |
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
392 |
def submitForm(self): |
9264.2.10
by Danilo Šegan
Fix up whitespace and most of the review comments. |
393 |
"""Process any uploaded files."""
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
394 |
|
395 |
if self.request.method == 'POST': |
|
1789
by Canonical.com Patch Queue Manager
PoTemplateAdmin implementation (finally) r=jamesh,mpt |
396 |
if 'UPLOAD' in self.request.form: |
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
397 |
self.upload() |
398 |
||
399 |
def upload(self): |
|
7326.1.6
by Henning Eggers
Added some changes during review. |
400 |
"""Handle a form submission to change the contents of the template.
|
401 |
||
402 |
Uploads may fail if there are already entries with the same path name
|
|
403 |
and uploader (importer) in the queue and the new upload cannot be
|
|
404 |
safely matched to any of them. The user will be informed about the
|
|
405 |
failure with a warning message."""
|
|
406 |
# XXX henninge 20008-12-03 bug=192925: This code is duplicated for
|
|
407 |
# productseries and pofile and should be unified.
|
|
3691.134.4
by kiko
Fix for OOPS-256B785 and friends: avoid crashing in upload handler when invalid form arguments are provided. Give a decent error message instead by simply making the logic in the potemplate view code more robust. |
408 |
file = self.request.form.get('file') |
1818
by Canonical.com Patch Queue Manager
[r=spiv] teams of translators to be organised as groups by language |
409 |
if not isinstance(file, FileUpload): |
3691.134.4
by kiko
Fix for OOPS-256B785 and friends: avoid crashing in upload handler when invalid form arguments are provided. Give a decent error message instead by simply making the logic in the potemplate view code more robust. |
410 |
if not file: |
2570.1.37
by Carlos Perelló Marín
More review comments applied |
411 |
self.request.response.addErrorNotification( |
3691.134.4
by kiko
Fix for OOPS-256B785 and friends: avoid crashing in upload handler when invalid form arguments are provided. Give a decent error message instead by simply making the logic in the potemplate view code more robust. |
412 |
"Your upload was ignored because you didn't select a "
|
413 |
"file. Please select a file and try again.") |
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
414 |
else: |
6912.5.21
by Curtis Hovey
Updated the XXX comment's metadata using the bug found in the comment text. |
415 |
# XXX: Carlos Perello Marin 2004-12-30 bug=116:
|
2570.1.37
by Carlos Perelló Marín
More review comments applied |
416 |
# Epiphany seems to have an unpredictable bug with upload
|
417 |
# forms (or perhaps it's launchpad because I never had
|
|
418 |
# problems with bugzilla). The fact is that some uploads don't
|
|
419 |
# work and we get a unicode object instead of a file-like
|
|
420 |
# object in "file". We show an error if we see that behaviour.
|
|
421 |
self.request.response.addErrorNotification( |
|
3691.134.4
by kiko
Fix for OOPS-256B785 and friends: avoid crashing in upload handler when invalid form arguments are provided. Give a decent error message instead by simply making the logic in the potemplate view code more robust. |
422 |
"Your upload failed because there was a problem receiving"
|
423 |
" data. Please try again.") |
|
1789
by Canonical.com Patch Queue Manager
PoTemplateAdmin implementation (finally) r=jamesh,mpt |
424 |
return
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
425 |
|
426 |
filename = file.filename |
|
2570.1.7
by Carlos Perello Marin
Lots of fixes + new code + tests updates |
427 |
content = file.read() |
428 |
||
429 |
if len(content) == 0: |
|
2570.1.37
by Carlos Perelló Marín
More review comments applied |
430 |
self.request.response.addWarningNotification( |
431 |
"Ignored your upload because the uploaded file is empty.") |
|
2570.1.7
by Carlos Perello Marin
Lots of fixes + new code + tests updates |
432 |
return
|
433 |
||
2570.1.37
by Carlos Perelló Marín
More review comments applied |
434 |
translation_import_queue = getUtility(ITranslationImportQueue) |
3691.457.39
by Carlos Perello Marin
Removed more format dependent code from browser code |
435 |
root, ext = os.path.splitext(filename) |
436 |
translation_importer = getUtility(ITranslationImporter) |
|
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
437 |
if ext in translation_importer.supported_file_extensions: |
2570.1.7
by Carlos Perello Marin
Lots of fixes + new code + tests updates |
438 |
# Add it to the queue.
|
7326.1.2
by Henning Eggers
Added support to handle translation file upload conflicts nicely. |
439 |
entry = translation_import_queue.addOrUpdateEntry( |
3691.457.39
by Carlos Perello Marin
Removed more format dependent code from browser code |
440 |
filename, content, True, self.user, |
2570.1.7
by Carlos Perello Marin
Lots of fixes + new code + tests updates |
441 |
sourcepackagename=self.context.sourcepackagename, |
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
442 |
distroseries=self.context.distroseries, |
3200.1.1
by Carlos Perello Marin
Changed the way the import queue works and removed the old rawimports from POFile and POTemplate. Now we have just one place with all imports + a ton of tests fixes |
443 |
productseries=self.context.productseries, |
3691.457.39
by Carlos Perello Marin
Removed more format dependent code from browser code |
444 |
potemplate=self.context) |
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
445 |
|
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
446 |
if entry is None: |
7326.1.2
by Henning Eggers
Added support to handle translation file upload conflicts nicely. |
447 |
self.request.response.addWarningNotification( |
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
448 |
"Upload failed. The name of the file you "
|
449 |
"uploaded matched multiple existing "
|
|
450 |
"uploads, for different templates. This makes it "
|
|
451 |
"impossible to determine which template the new "
|
|
452 |
"upload was for. Try uploading to a specific "
|
|
453 |
"template: visit the page for the template that you "
|
|
454 |
"want to upload to, and select the upload option "
|
|
455 |
"from there.") |
|
456 |
else: |
|
457 |
self.request.response.addInfoNotification( |
|
458 |
structured( |
|
459 |
'Thank you for your upload. It will be automatically '
|
|
7326.1.5
by Henning Eggers
Small fixes. |
460 |
'reviewed in the next few hours. If that is not '
|
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
461 |
'enough to determine whether and where your file '
|
462 |
'should be imported, it will be reviewed manually by an '
|
|
463 |
'administrator in the coming few days. You can track '
|
|
464 |
'your upload\'s status in the ' |
|
12696.1.1
by Henning Eggers
Fixed all structured calls in translations. |
465 |
'<a href="%s/+imports">Translation Import Queue</a>', |
466 |
canonical_url(self.context.translationtarget))) |
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
467 |
|
14593.2.15
by Curtis Hovey
Moved helpers to lp.services. |
468 |
elif is_tar_filename(filename): |
2570.1.7
by Carlos Perello Marin
Lots of fixes + new code + tests updates |
469 |
# Add the whole tarball to the import queue.
|
7326.1.2
by Henning Eggers
Added support to handle translation file upload conflicts nicely. |
470 |
(num, conflicts) = ( |
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
471 |
translation_import_queue.addOrUpdateEntriesFromTarball( |
7326.1.2
by Henning Eggers
Added support to handle translation file upload conflicts nicely. |
472 |
content, True, self.user, |
473 |
sourcepackagename=self.context.sourcepackagename, |
|
474 |
distroseries=self.context.distroseries, |
|
475 |
productseries=self.context.productseries, |
|
476 |
potemplate=self.context)) |
|
2570.1.7
by Carlos Perello Marin
Lots of fixes + new code + tests updates |
477 |
|
478 |
if num > 0: |
|
7326.1.7
by Henning Eggers
* Added wording for singular cases. |
479 |
if num == 1: |
480 |
plural_s = '' |
|
481 |
itthey = 'it' |
|
482 |
else: |
|
483 |
plural_s = 's' |
|
484 |
itthey = 'they' |
|
5594.1.11
by Maris Fogels
Beautified the addNotification(structured(...)) construct. |
485 |
self.request.response.addInfoNotification( |
486 |
structured( |
|
12696.1.1
by Henning Eggers
Fixed all structured calls in translations. |
487 |
'Thank you for your upload. %s file%s from the tarball ' |
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
488 |
'will be automatically '
|
7326.1.5
by Henning Eggers
Small fixes. |
489 |
'reviewed in the next few hours. If that is not enough '
|
7326.1.7
by Henning Eggers
* Added wording for singular cases. |
490 |
'to determine whether and where your file%s should ' |
491 |
'be imported, %s will be reviewed manually by an ' |
|
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
492 |
'administrator in the coming few days. You can track '
|
493 |
'your upload\'s status in the ' |
|
13515.3.11
by Henning Eggers
Removed lots of lint. |
494 |
'<a href="%s/+imports">Translation Import Queue</a>' % ( |
7326.1.7
by Henning Eggers
* Added wording for singular cases. |
495 |
num, plural_s, plural_s, itthey, |
7440.1.1
by Henning Eggers
Corrected URL for translation import queue. |
496 |
canonical_url(self.context.translationtarget)))) |
7326.1.2
by Henning Eggers
Added support to handle translation file upload conflicts nicely. |
497 |
if len(conflicts) > 0: |
7326.1.7
by Henning Eggers
* Added wording for singular cases. |
498 |
if len(conflicts) == 1: |
499 |
warning = ( |
|
500 |
"A file could not be uploaded because its "
|
|
501 |
"name matched multiple existing uploads, for "
|
|
10008.1.2
by Adi Roiban
Add test stories for covering new functionalities. |
502 |
"different templates.") |
12696.1.1
by Henning Eggers
Fixed all structured calls in translations. |
503 |
ul_conflicts = structured( |
7326.1.7
by Henning Eggers
* Added wording for singular cases. |
504 |
"The conflicting file name was:<br /> "
|
12696.1.1
by Henning Eggers
Fixed all structured calls in translations. |
505 |
"<ul><li>%s</li></ul>", conflicts[0]) |
7326.1.7
by Henning Eggers
* Added wording for singular cases. |
506 |
else: |
12696.1.1
by Henning Eggers
Fixed all structured calls in translations. |
507 |
warning = structured( |
508 |
"%s files could not be uploaded because their " |
|
7326.1.7
by Henning Eggers
* Added wording for singular cases. |
509 |
"names matched multiple existing uploads, for "
|
12696.1.1
by Henning Eggers
Fixed all structured calls in translations. |
510 |
"different templates.", len(conflicts)) |
511 |
ul_conflicts = structured( |
|
7326.1.7
by Henning Eggers
* Added wording for singular cases. |
512 |
"The conflicting file names were:<br /> "
|
513 |
"<ul><li>%s</li></ul>" % ( |
|
514 |
"</li><li>".join(map(cgi.escape, conflicts)))) |
|
7326.1.2
by Henning Eggers
Added support to handle translation file upload conflicts nicely. |
515 |
self.request.response.addWarningNotification( |
516 |
structured( |
|
12696.1.1
by Henning Eggers
Fixed all structured calls in translations. |
517 |
"%s This makes it " |
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
518 |
"impossible to determine which template the new "
|
519 |
"upload was for. Try uploading to a specific "
|
|
520 |
"template: visit the page for the template that you "
|
|
521 |
"want to upload to, and select the upload option "
|
|
12696.1.1
by Henning Eggers
Fixed all structured calls in translations. |
522 |
"from there.<br />%s", warning, ul_conflicts)) |
2570.1.7
by Carlos Perello Marin
Lots of fixes + new code + tests updates |
523 |
else: |
7326.1.2
by Henning Eggers
Added support to handle translation file upload conflicts nicely. |
524 |
if len(conflicts) == 0: |
525 |
self.request.response.addWarningNotification( |
|
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
526 |
"Upload ignored. The tarball you uploaded did not "
|
527 |
"contain any files that the system recognized as "
|
|
528 |
"translation files.") |
|
7326.1.2
by Henning Eggers
Added support to handle translation file upload conflicts nicely. |
529 |
else: |
530 |
self.request.response.addWarningNotification( |
|
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
531 |
"Upload failed. One or more of the files you "
|
532 |
"uploaded had names that matched multiple existing "
|
|
533 |
"uploads, for different templates. This makes it "
|
|
534 |
"impossible to determine which template the new "
|
|
535 |
"upload was for. Try uploading to a specific "
|
|
536 |
"template: visit the page for the template that you "
|
|
537 |
"want to upload to, and select the upload option "
|
|
538 |
"from there.") |
|
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
539 |
else: |
2570.1.37
by Carlos Perelló Marín
More review comments applied |
540 |
self.request.response.addWarningNotification( |
7326.1.3
by Henning Eggers
Improved handling of conflicting file names in translation uploads. |
541 |
"Upload failed because the file you uploaded was not"
|
2570.1.37
by Carlos Perelló Marín
More review comments applied |
542 |
" recognised as a file that can be imported.") |
1646
by Canonical.com Patch Queue Manager
Rosetta source code follows now the Launchpad standard layout rs=SteveA |
543 |
|
544 |
||
3691.95.1
by Danilo Šegan
Fix bug #2237: simplify potemplate views and review responses. |
545 |
class POTemplateViewPreferred(POTemplateView): |
10008.1.2
by Adi Roiban
Add test stories for covering new functionalities. |
546 |
"""View class that shows only users preferred templates."""
|
547 |
||
3691.95.1
by Danilo Šegan
Fix bug #2237: simplify potemplate views and review responses. |
548 |
def pofiles(self): |
3691.95.4
by Danilo Šegan
Minor PEP-8 bit. |
549 |
return POTemplateView.pofiles(self, preferred_only=True) |
550 |
||
10008.1.2
by Adi Roiban
Add test stories for covering new functionalities. |
551 |
|
10513.1.1
by Adi Roiban
Implement a more elegant solution for next_url redirection. |
552 |
class POTemplateEditView(ReturnToReferrerMixin, LaunchpadEditFormView): |
1789
by Canonical.com Patch Queue Manager
PoTemplateAdmin implementation (finally) r=jamesh,mpt |
553 |
"""View class that lets you edit a POTemplate object."""
|
2043
by Canonical.com Patch Queue Manager
PoTemplateAdmin changes r=spiv,bjornt |
554 |
|
7182.6.2
by Guilherme Salgado
Convert POTemplateEditView into a LaunchpadEditFormView |
555 |
schema = IPOTemplate |
9264.3.1
by Danilo Šegan
Replace potemplate edit and admin forms with generic-edit.pt. |
556 |
label = 'Edit translation template details' |
9481.2.2
by Henning Eggers
Fixed labels and page_titles on pofile and potemplate pages. |
557 |
page_title = 'Edit details' |
10744.6.2
by Adi Roiban
Add pagetest. |
558 |
PRIORITY_MIN_VALUE = 0 |
559 |
PRIORITY_MAX_VALUE = 100000 |
|
7182.6.2
by Guilherme Salgado
Convert POTemplateEditView into a LaunchpadEditFormView |
560 |
|
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
561 |
@property
|
562 |
def field_names(self): |
|
563 |
field_names = [ |
|
564 |
'name', 'translation_domain', 'description', 'priority', |
|
565 |
'path', 'iscurrent'] |
|
566 |
if self.context.distroseries: |
|
567 |
field_names.extend([ |
|
568 |
'sourcepackagename', |
|
569 |
'languagepack', |
|
570 |
])
|
|
13715.1.13
by Danilo Segan
Fix test failures. |
571 |
else: |
572 |
field_names.append('owner') |
|
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
573 |
return field_names |
574 |
||
13715.1.9
by Danilo Segan
Provide a correct return URL. |
575 |
@property
|
576 |
def _return_url(self): |
|
13715.1.10
by Danilo Segan
Improve comments for _return_url override. |
577 |
# We override the ReturnToReferrerMixin _return_url because it might
|
578 |
# change when any of the productseries, distroseries,
|
|
579 |
# sourcepackagename or name attributes change, and the basic version
|
|
580 |
# only supports watching changes to a single attribute.
|
|
581 |
||
582 |
# The referer header is a hidden input in the form.
|
|
13715.1.9
by Danilo Segan
Provide a correct return URL. |
583 |
referrer = self.request.form.get('_return_url') |
584 |
returnChanged = False |
|
585 |
if referrer is None: |
|
586 |
# "referer" is misspelled in the HTTP specification.
|
|
587 |
referrer = self.request.getHeader('referer') |
|
13715.1.10
by Danilo Segan
Improve comments for _return_url override. |
588 |
# If we were looking at the actual template, we want a new
|
589 |
# URL constructed.
|
|
13715.1.9
by Danilo Segan
Provide a correct return URL. |
590 |
if referrer is not None and '/+pots/' in referrer: |
591 |
returnChanged = True |
|
592 |
||
593 |
if (referrer is not None |
|
594 |
and not returnChanged |
|
595 |
and referrer.startswith(self.request.getApplicationURL()) |
|
596 |
and referrer != self.request.getHeader('location')): |
|
597 |
return referrer |
|
598 |
else: |
|
599 |
return canonical_url(self.context) |
|
600 |
||
7182.6.2
by Guilherme Salgado
Convert POTemplateEditView into a LaunchpadEditFormView |
601 |
@action(_('Change'), name='change') |
602 |
def change_action(self, action, data): |
|
3691.27.8
by Guilherme Salgado
Update all Person.assignKarma() callsites to pass the product/distribution as the method wants |
603 |
context = self.context |
13515.3.9
by Henning Eggers
Use setActive in browser code. |
604 |
iscurrent = data.get('iscurrent', context.iscurrent) |
605 |
context.setActive(iscurrent) |
|
7182.6.2
by Guilherme Salgado
Convert POTemplateEditView into a LaunchpadEditFormView |
606 |
old_description = context.description |
607 |
old_translation_domain = context.translation_domain |
|
608 |
self.updateContextFromData(data) |
|
609 |
if old_description != context.description: |
|
3691.27.8
by Guilherme Salgado
Update all Person.assignKarma() callsites to pass the product/distribution as the method wants |
610 |
self.user.assignKarma( |
611 |
'translationtemplatedescriptionchanged', |
|
3691.27.9
by Guilherme Salgado
Add POTemplate.product and POTemplate.distribution, to avoid having to check if productseries/distrorelease is None on Person.assignKarma() callsites |
612 |
product=context.product, distribution=context.distribution, |
3691.27.8
by Guilherme Salgado
Update all Person.assignKarma() callsites to pass the product/distribution as the method wants |
613 |
sourcepackagename=context.sourcepackagename) |
7182.6.2
by Guilherme Salgado
Convert POTemplateEditView into a LaunchpadEditFormView |
614 |
if old_translation_domain != context.translation_domain: |
10180.3.5
by Adi Roiban
Add test for template update date. |
615 |
# We only change date_last_updated when the translation_domain
|
616 |
# field is changed because it is the only relevant field we
|
|
617 |
# care about regarding the date of last update.
|
|
10180.3.4
by Adi Roiban
Make proper use of removeSecurityProxy. |
618 |
naked_context = removeSecurityProxy(context) |
10180.3.6
by Adi Roiban
Fix syntax formating. |
619 |
naked_context.date_last_updated = datetime.datetime.now(pytz.UTC) |
1789
by Canonical.com Patch Queue Manager
PoTemplateAdmin implementation (finally) r=jamesh,mpt |
620 |
|
13715.1.4
by Danilo Segan
Rename the method _getTemplateSet. |
621 |
def _validateTargetAndGetTemplates(self, data): |
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
622 |
"""Return a POTemplateSubset corresponding to the chosen target."""
|
623 |
sourcepackagename = data.get('sourcepackagename', |
|
624 |
self.context.sourcepackagename) |
|
625 |
return getUtility(IPOTemplateSet).getSubset( |
|
626 |
distroseries=self.context.distroseries, |
|
627 |
sourcepackagename=sourcepackagename, |
|
628 |
productseries=self.context.productseries) |
|
629 |
||
10744.6.1
by Adi Roiban
Allow priority values between 0 and 10000. |
630 |
def validate(self, data): |
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
631 |
name = data.get('name', None) |
632 |
if name is None or not valid_name(name): |
|
633 |
self.setFieldError( |
|
634 |
'name', |
|
635 |
'Template name can only start with lowercase letters a-z '
|
|
636 |
'or digits 0-9, and other than those characters, can only '
|
|
637 |
'contain "-", "+" and "." characters.') |
|
638 |
||
13715.1.9
by Danilo Segan
Provide a correct return URL. |
639 |
distroseries = data.get('distroseries', self.context.distroseries) |
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
640 |
sourcepackagename = data.get( |
641 |
'sourcepackagename', self.context.sourcepackagename) |
|
642 |
productseries = data.get('productseries', None) |
|
643 |
sourcepackage_changed = ( |
|
644 |
distroseries is not None and |
|
645 |
(distroseries != self.context.distroseries or |
|
646 |
sourcepackagename != self.context.sourcepackagename)) |
|
647 |
productseries_changed = (productseries is not None and |
|
648 |
productseries != self.context.productseries) |
|
13715.1.4
by Danilo Segan
Rename the method _getTemplateSet. |
649 |
similar_templates = self._validateTargetAndGetTemplates(data) |
13715.1.6
by Danilo Segan
Conditionalise use of similar_templates. |
650 |
if similar_templates is not None: |
651 |
self.validateName( |
|
652 |
name, similar_templates, sourcepackage_changed, |
|
653 |
productseries_changed) |
|
654 |
self.validateDomain( |
|
655 |
data.get('translation_domain'), similar_templates, |
|
656 |
sourcepackage_changed, productseries_changed) |
|
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
657 |
|
10744.6.1
by Adi Roiban
Allow priority values between 0 and 10000. |
658 |
priority = data.get('priority') |
10744.6.2
by Adi Roiban
Add pagetest. |
659 |
if priority is None: |
660 |
return
|
|
661 |
||
662 |
if (priority < self.PRIORITY_MIN_VALUE or |
|
663 |
priority > self.PRIORITY_MAX_VALUE): |
|
10744.6.3
by Adi Roiban
Add a fueld error message containing a real sentence. |
664 |
self.setFieldError( |
665 |
'priority', |
|
666 |
'The priority value must be between %s and %s.' % ( |
|
10744.6.2
by Adi Roiban
Add pagetest. |
667 |
self.PRIORITY_MIN_VALUE, self.PRIORITY_MAX_VALUE)) |
3691.102.1
by Danilo Šegan
Fix bug #3986: redirect when potemplate name is changed by admin. |
668 |
|
13161.1.6
by Henning Eggers
First try at fixing for name. |
669 |
def validateName(self, name, similar_templates, |
670 |
sourcepackage_changed, productseries_changed): |
|
671 |
"""Check that the name does not clash with an existing template."""
|
|
10224.9.1
by Jeroen Vermeulen
Check for name/domain uniqueness on template. |
672 |
if similar_templates.getPOTemplateByName(name) is not None: |
13161.1.6
by Henning Eggers
First try at fixing for name. |
673 |
if sourcepackage_changed: |
674 |
self.setFieldError( |
|
675 |
'sourcepackagename', |
|
676 |
"Source package already has a template with "
|
|
13161.1.8
by Henning Eggers
Fix the bug. |
677 |
"that same name.") |
13161.1.6
by Henning Eggers
First try at fixing for name. |
678 |
elif productseries_changed: |
679 |
self.setFieldError( |
|
680 |
'productseries', |
|
13161.1.8
by Henning Eggers
Fix the bug. |
681 |
"Series already has a template with that same name.") |
682 |
elif name != self.context.name: |
|
13161.1.6
by Henning Eggers
First try at fixing for name. |
683 |
self.setFieldError('name', "Name is already in use.") |
10224.9.1
by Jeroen Vermeulen
Check for name/domain uniqueness on template. |
684 |
|
13161.1.8
by Henning Eggers
Fix the bug. |
685 |
def validateDomain(self, domain, similar_templates, |
686 |
sourcepackage_changed, productseries_changed): |
|
13957.3.1
by Jeroen Vermeulen
Register approval conflicts in error_output. |
687 |
clashes = similar_templates.getPOTemplatesByTranslationDomain(domain) |
688 |
if not clashes.is_empty(): |
|
13161.1.8
by Henning Eggers
Fix the bug. |
689 |
if sourcepackage_changed: |
690 |
self.setFieldError( |
|
691 |
'sourcepackagename', |
|
692 |
"Source package already has a template with "
|
|
693 |
"that same domain.") |
|
694 |
elif productseries_changed: |
|
695 |
self.setFieldError( |
|
696 |
'productseries', |
|
697 |
"Series already has a template with that same domain.") |
|
698 |
elif domain != self.context.translation_domain: |
|
699 |
self.setFieldError( |
|
700 |
'translation_domain', "Domain is already in use.") |
|
10224.9.1
by Jeroen Vermeulen
Check for name/domain uniqueness on template. |
701 |
|
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
702 |
@property
|
703 |
def _return_attribute_name(self): |
|
704 |
"""See 'ReturnToReferrerMixin'."""
|
|
705 |
return "name" |
|
706 |
||
707 |
||
708 |
class POTemplateAdminView(POTemplateEditView): |
|
709 |
"""View class that lets you admin a POTemplate object."""
|
|
710 |
field_names = [ |
|
711 |
'name', 'translation_domain', 'description', 'header', 'iscurrent', |
|
712 |
'owner', 'productseries', 'distroseries', 'sourcepackagename', |
|
713 |
'from_sourcepackagename', 'sourcepackageversion', 'binarypackagename', |
|
714 |
'languagepack', 'path', 'source_file_format', 'priority', |
|
715 |
'date_last_updated'] |
|
716 |
label = 'Administer translation template' |
|
717 |
page_title = "Administer" |
|
718 |
||
13715.1.4
by Danilo Segan
Rename the method _getTemplateSet. |
719 |
def _validateTargetAndGetTemplates(self, data): |
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
720 |
"""Return a POTemplateSubset corresponding to the chosen target."""
|
10224.9.1
by Jeroen Vermeulen
Check for name/domain uniqueness on template. |
721 |
distroseries = data.get('distroseries') |
722 |
sourcepackagename = data.get('sourcepackagename') |
|
723 |
productseries = data.get('productseries') |
|
724 |
||
10212.2.1
by Jeroen Vermeulen
Validate input to POTemplate admin form. |
725 |
if distroseries is not None and productseries is not None: |
726 |
message = ("Choose a distribution release series or a project " |
|
727 |
"release series, but not both.") |
|
728 |
elif distroseries is None and productseries is None: |
|
729 |
message = ("Choose either a distribution release series or a " |
|
730 |
"project release series.") |
|
731 |
else: |
|
732 |
message = None |
|
733 |
||
734 |
if message is not None: |
|
735 |
self.addError(message) |
|
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
736 |
return None |
737 |
return getUtility(IPOTemplateSet).getSubset( |
|
10224.9.1
by Jeroen Vermeulen
Check for name/domain uniqueness on template. |
738 |
distroseries=distroseries, sourcepackagename=sourcepackagename, |
739 |
productseries=productseries) |
|
10212.2.1
by Jeroen Vermeulen
Validate input to POTemplate admin form. |
740 |
|
1789
by Canonical.com Patch Queue Manager
PoTemplateAdmin implementation (finally) r=jamesh,mpt |
741 |
|
1988
by Canonical.com Patch Queue Manager
[r=salgado] RosettaMultipleFormatExports |
742 |
class POTemplateExportView(BaseExportView): |
9264.2.10
by Danilo Šegan
Fix up whitespace and most of the review comments. |
743 |
"""Request downloads of a `POTemplate` and its translations."""
|
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
744 |
|
9481.2.2
by Henning Eggers
Fixed labels and page_titles on pofile and potemplate pages. |
745 |
label = "Download translations" |
746 |
page_title = "Download translations" |
|
9264.2.10
by Danilo Šegan
Fix up whitespace and most of the review comments. |
747 |
|
748 |
@property
|
|
749 |
def cancel_url(self): |
|
750 |
return canonical_url(self.context) |
|
751 |
||
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
752 |
def processForm(self): |
1988
by Canonical.com Patch Queue Manager
[r=salgado] RosettaMultipleFormatExports |
753 |
"""Process a form submission requesting a translation export."""
|
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
754 |
what = self.request.form.get('what') |
755 |
if what == 'all': |
|
756 |
export_potemplate = True |
|
757 |
||
10008.1.2
by Adi Roiban
Add test stories for covering new functionalities. |
758 |
pofiles = self.context.pofiles |
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
759 |
elif what == 'some': |
3691.134.1
by kiko
Fix OOPS-257C588 and friends, which are crashes when submitting an incomplete potemplate/+export form (via curl, for instance). Reenable and update the pagetest for it, which Carlos and I have no idea about |
760 |
pofiles = [] |
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
761 |
export_potemplate = 'potemplate' in self.request.form |
762 |
||
11122.3.17
by Danilo Segan
Apply review comments from jtv as well. |
763 |
for code in self.request.form: |
11122.3.4
by Danilo Šegan
Get rid of the remaining variant usage. |
764 |
pofile = self.context.getPOFileByLang(code) |
2570.1.37
by Carlos Perelló Marín
More review comments applied |
765 |
if pofile is not None: |
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
766 |
pofiles.append(pofile) |
767 |
else: |
|
3691.178.2
by Diogo Matsubara
fix bug 1558, 44837 and 63236 |
768 |
self.request.response.addErrorNotification( |
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
769 |
'Please choose whether you would like all files or only some '
|
770 |
'of them.') |
|
771 |
return
|
|
772 |
||
773 |
if export_potemplate: |
|
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
774 |
requested_templates = [self.context] |
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
775 |
else: |
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
776 |
requested_templates = None |
3691.178.2
by Diogo Matsubara
fix bug 1558, 44837 and 63236 |
777 |
|
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
778 |
return (requested_templates, pofiles) |
3691.178.2
by Diogo Matsubara
fix bug 1558, 44837 and 63236 |
779 |
|
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
780 |
def pofiles(self): |
1988
by Canonical.com Patch Queue Manager
[r=salgado] RosettaMultipleFormatExports |
781 |
"""Return a list of PO files available for export."""
|
782 |
||
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
783 |
class BrowserPOFile: |
10008.1.2
by Adi Roiban
Add test stories for covering new functionalities. |
784 |
|
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
785 |
def __init__(self, value, browsername): |
786 |
self.value = value |
|
787 |
self.browsername = browsername |
|
788 |
||
1892
by Canonical.com Patch Queue Manager
workaround for PO export problem [r=JamesH] |
789 |
def pofile_sort_key(pofile): |
790 |
return pofile.language.englishname |
|
791 |
||
792 |
for pofile in sorted(self.context.pofiles, key=pofile_sort_key): |
|
8636.4.2
by Jeroen Vermeulen
Removed other pointless string decode as well. |
793 |
value = pofile.getFullLanguageCode() |
8636.4.1
by Jeroen Vermeulen
Keep non-ascii language names as unicode in POFile descriptions. |
794 |
browsername = pofile.getFullLanguageName() |
1875
by Canonical.com Patch Queue Manager
TranslationFileDownloading [r=Guilherme] |
795 |
|
796 |
yield BrowserPOFile(value, browsername) |
|
797 |
||
4673.6.1
by Jeroen Vermeulen
Provide download of all translations for a productseries. |
798 |
def getDefaultFormat(self): |
799 |
return self.context.source_file_format |
|
800 |
||
1715
by Canonical.com Patch Queue Manager
Moved the translation form from potemplate context into pofile context. r=SteveA |
801 |
|
1988
by Canonical.com Patch Queue Manager
[r=salgado] RosettaMultipleFormatExports |
802 |
class POTemplateSubsetURL: |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
803 |
implements(ICanonicalUrlData) |
804 |
||
3618.1.45
by Steve Alexander
refactor virtual hosting |
805 |
rootsite = 'mainsite' |
3691.3.2
by Steve Alexander
set up new host header based virtual hosting, make canonical_url able to be configured with a rootsite, removal of unused IDefaultViewDirective, fix race condition in request publication factory. |
806 |
|
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
807 |
def __init__(self, context): |
808 |
self.context = context |
|
809 |
||
810 |
@property
|
|
811 |
def path(self): |
|
812 |
potemplatesubset = self.context |
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
813 |
if potemplatesubset.distroseries is not None: |
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
814 |
assert potemplatesubset.productseries is None |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
815 |
assert potemplatesubset.sourcepackagename is not None |
2705
by Canonical.com Patch Queue Manager
r=spiv, mark's soyuz loving. |
816 |
return '+source/%s/+pots' % ( |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
817 |
potemplatesubset.sourcepackagename.name) |
818 |
else: |
|
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
819 |
assert potemplatesubset.productseries is not None |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
820 |
return '+pots' |
821 |
||
822 |
@property
|
|
823 |
def inside(self): |
|
824 |
potemplatesubset = self.context |
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
825 |
if potemplatesubset.distroseries is not None: |
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
826 |
assert potemplatesubset.productseries is None |
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
827 |
return potemplatesubset.distroseries |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
828 |
else: |
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
829 |
assert potemplatesubset.productseries is not None |
830 |
return potemplatesubset.productseries |
|
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
831 |
|
832 |
||
1988
by Canonical.com Patch Queue Manager
[r=salgado] RosettaMultipleFormatExports |
833 |
class POTemplateURL: |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
834 |
implements(ICanonicalUrlData) |
835 |
||
9483.1.1
by Danilo Šegan
Re-revert 9477 minus branch-links update. |
836 |
rootsite = 'translations' |
3691.3.2
by Steve Alexander
set up new host header based virtual hosting, make canonical_url able to be configured with a rootsite, removal of unused IDefaultViewDirective, fix race condition in request publication factory. |
837 |
|
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
838 |
def __init__(self, context): |
839 |
self.context = context |
|
840 |
potemplate = self.context |
|
841 |
potemplateset = getUtility(IPOTemplateSet) |
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
842 |
if potemplate.distroseries is not None: |
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
843 |
assert potemplate.productseries is None |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
844 |
self.potemplatesubset = potemplateset.getSubset( |
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
845 |
distroseries=potemplate.distroseries, |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
846 |
sourcepackagename=potemplate.sourcepackagename) |
847 |
else: |
|
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
848 |
assert potemplate.productseries is not None |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
849 |
self.potemplatesubset = potemplateset.getSubset( |
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
850 |
productseries=potemplate.productseries) |
1955
by Canonical.com Patch Queue Manager
menus. [r=spiv] |
851 |
|
852 |
@property
|
|
853 |
def path(self): |
|
854 |
potemplate = self.context |
|
855 |
return potemplate.name |
|
856 |
||
857 |
@property
|
|
858 |
def inside(self): |
|
859 |
return self.potemplatesubset |
|
1840
by Canonical.com Patch Queue Manager
restructure translation storage, allowing for wiki mode, non-editor translation, accurate statistics and fewer bugs |
860 |
|
2630
by Canonical.com Patch Queue Manager
[trivial] lots of tidying up. converting all database classes to use NotFoundError consistently, and to import it from launchpad.interfaces in preparation for the move to a new zope3. Also, introduced a NameNotAvailable error. removed browser:traverse rdirective. commented out shipit test that fails sometimes. |
861 |
|
862 |
class POTemplateSetNavigation(GetitemNavigation): |
|
863 |
||
864 |
usedfor = IPOTemplateSet |
|
865 |
||
866 |
||
4767.9.1
by Carlos Perello Marin
Improved POTemplate navigation so we only traverse to active templates for normal users and all available templates for admins |
867 |
class POTemplateSubsetNavigation(Navigation): |
2630
by Canonical.com Patch Queue Manager
[trivial] lots of tidying up. converting all database classes to use NotFoundError consistently, and to import it from launchpad.interfaces in preparation for the move to a new zope3. Also, introduced a NameNotAvailable error. removed browser:traverse rdirective. commented out shipit test that fails sometimes. |
868 |
|
869 |
usedfor = IPOTemplateSubset |
|
870 |
||
4767.9.1
by Carlos Perello Marin
Improved POTemplate navigation so we only traverse to active templates for normal users and all available templates for admins |
871 |
def traverse(self, name): |
872 |
"""Return the IPOTemplate associated with the given name."""
|
|
873 |
||
10355.4.14
by Adi Roiban
Make entry names less gettextish. Export translation templates using a method. Allow PATCH-ing POTemplates. |
874 |
assert self.request.method in ['GET', 'HEAD', 'PATCH', 'POST'], ( |
875 |
'We only know about GET, HEAD, PATCH and POST') |
|
4767.9.1
by Carlos Perello Marin
Improved POTemplate navigation so we only traverse to active templates for normal users and all available templates for admins |
876 |
|
877 |
# Get the requested potemplate.
|
|
878 |
potemplate = self.context.getPOTemplateByName(name) |
|
879 |
if potemplate is None: |
|
880 |
# The template doesn't exist.
|
|
881 |
raise NotFoundError(name) |
|
882 |
||
883 |
# Get whether the target for the requested template is officially
|
|
884 |
# using Launchpad Translations.
|
|
10355.4.15
by Adi Roiban
Remove shortlist and return the POTemplateSubset as Storm results. |
885 |
if potemplate.distribution is None: |
886 |
product_or_distro = potemplate.productseries.product |
|
4767.9.1
by Carlos Perello Marin
Improved POTemplate navigation so we only traverse to active templates for normal users and all available templates for admins |
887 |
else: |
10355.4.15
by Adi Roiban
Remove shortlist and return the POTemplateSubset as Storm results. |
888 |
product_or_distro = potemplate.distroseries.distribution |
11472.3.1
by j.c.sackett
Updated all nontest callsites in the code. |
889 |
translations_usage = product_or_distro.translations_usage |
4767.9.1
by Carlos Perello Marin
Improved POTemplate navigation so we only traverse to active templates for normal users and all available templates for admins |
890 |
|
11472.3.1
by j.c.sackett
Updated all nontest callsites in the code. |
891 |
if (service_uses_launchpad(translations_usage) and |
892 |
potemplate.iscurrent): |
|
10355.4.15
by Adi Roiban
Remove shortlist and return the POTemplateSubset as Storm results. |
893 |
# This template is available for translation.
|
894 |
return potemplate |
|
13715.1.13
by Danilo Segan
Fix test failures. |
895 |
elif check_permission('launchpad.TranslationsAdmin', potemplate): |
10355.4.15
by Adi Roiban
Remove shortlist and return the POTemplateSubset as Storm results. |
896 |
# User has Edit privileges for this template and can access it.
|
4767.9.1
by Carlos Perello Marin
Improved POTemplate navigation so we only traverse to active templates for normal users and all available templates for admins |
897 |
return potemplate |
898 |
else: |
|
899 |
raise NotFoundError(name) |
|
9483.1.1
by Danilo Šegan
Re-revert 9477 minus branch-links update. |
900 |
|
901 |
||
902 |
class POTemplateBreadcrumb(Breadcrumb): |
|
903 |
"""Breadcrumb for `IPOTemplate`."""
|
|
10008.1.2
by Adi Roiban
Add test stories for covering new functionalities. |
904 |
|
9483.1.1
by Danilo Šegan
Re-revert 9477 minus branch-links update. |
905 |
@property
|
906 |
def text(self): |
|
907 |
return smartquote('Template "%s"' % self.context.name) |
|
10095.5.1
by Adi Roiban
Initial fix. Pagetests needs to be updated. |
908 |
|
909 |
||
910 |
class BaseSeriesTemplatesView(LaunchpadView): |
|
911 |
"""Show a list of all templates for the Series."""
|
|
912 |
||
913 |
is_distroseries = True |
|
914 |
distroseries = None |
|
915 |
productseries = None |
|
916 |
label = "Translation templates" |
|
917 |
page_title = "All templates" |
|
11128.4.3
by Adi Roiban
Fix problems raised during the previous review. Language counts are not added. |
918 |
can_edit = None |
919 |
can_admin = None |
|
10095.5.1
by Adi Roiban
Initial fix. Pagetests needs to be updated. |
920 |
|
921 |
def initialize(self, series, is_distroseries=True): |
|
13378.3.11
by Benji York
checkpoint |
922 |
self._template_name_cache = {} |
923 |
self._packaging_cache = {} |
|
10095.5.1
by Adi Roiban
Initial fix. Pagetests needs to be updated. |
924 |
self.is_distroseries = is_distroseries |
925 |
if is_distroseries: |
|
926 |
self.distroseries = series |
|
927 |
else: |
|
928 |
self.productseries = series |
|
13814.2.1
by Danilo Segan
Fix the wrongly displayed link for project admins. |
929 |
user = IPersonRoles(self.user, None) |
930 |
self.can_admin = (user is not None and |
|
931 |
(user.in_admin or user.in_rosetta_experts)) |
|
11128.4.3
by Adi Roiban
Fix problems raised during the previous review. Language counts are not added. |
932 |
self.can_edit = ( |
13715.1.3
by Danilo Segan
Improve the division between POTemplate:+edit and +admin pages. |
933 |
self.can_admin or |
934 |
check_permission('launchpad.TranslationsAdmin', series)) |
|
10095.5.1
by Adi Roiban
Initial fix. Pagetests needs to be updated. |
935 |
|
11532.6.1
by Jeroen Vermeulen
Render template column entirely in the view. |
936 |
self.user_is_logged_in = (self.user is not None) |
937 |
||
13378.3.12
by Benji York
checkpoint |
938 |
def iter_data(self): |
13378.3.23
by Benji York
Fix failing tests (and work less) by using the original query when not rendering a distroseries. |
939 |
# If this is not a distroseries, then the query is much simpler.
|
940 |
if not self.is_distroseries: |
|
941 |
potemplateset = getUtility(IPOTemplateSet) |
|
942 |
# The "shape" of the data returned by POTemplateSubset isn't quite
|
|
943 |
# right so we have to run it through zip first.
|
|
944 |
return zip(potemplateset.getSubset( |
|
945 |
productseries=self.productseries, |
|
946 |
distroseries=self.distroseries, |
|
947 |
ordered_by_names=True)) |
|
948 |
||
949 |
# Otherwise we have to do more work, primarily for the "sharing"
|
|
950 |
# column.
|
|
13378.3.14
by Benji York
checkpoint |
951 |
OtherTemplate = ClassAlias(POTemplate) |
13378.3.20
by Benji York
add joinInner and joinOuter to ITranslationTemplatesCollection |
952 |
join = (self.context.getTemplatesCollection() |
13378.3.12
by Benji York
checkpoint |
953 |
.joinOuter(Packaging, And( |
954 |
Packaging.distroseries == self.context.id, |
|
13378.3.18
by Benji York
fix lint and tweak some comments |
955 |
Packaging.sourcepackagename == |
956 |
POTemplate.sourcepackagenameID)) |
|
13378.3.12
by Benji York
checkpoint |
957 |
.joinOuter(ProductSeries, |
13378.3.15
by Benji York
I think it's working. |
958 |
ProductSeries.id == Packaging.productseriesID) |
13378.3.12
by Benji York
checkpoint |
959 |
.joinOuter(Product, And( |
960 |
Product.id == ProductSeries.productID, |
|
961 |
Or( |
|
14120.2.4
by Danilo Segan
Replace all references to _translation_usage with translation_usage. |
962 |
Product.translations_usage == ServiceUsage.LAUNCHPAD, |
963 |
Product.translations_usage == ServiceUsage.EXTERNAL))) |
|
13378.3.14
by Benji York
checkpoint |
964 |
.joinOuter(OtherTemplate, And( |
965 |
OtherTemplate.productseriesID == ProductSeries.id, |
|
13378.3.15
by Benji York
I think it's working. |
966 |
OtherTemplate.name == POTemplate.name)) |
967 |
.joinInner(SourcePackageName, |
|
968 |
SourcePackageName.id == POTemplate.sourcepackagenameID)) |
|
13378.3.14
by Benji York
checkpoint |
969 |
|
13378.3.15
by Benji York
I think it's working. |
970 |
return join.select(POTemplate, Packaging, ProductSeries, Product, |
971 |
OtherTemplate, SourcePackageName) |
|
10095.5.1
by Adi Roiban
Initial fix. Pagetests needs to be updated. |
972 |
|
973 |
def rowCSSClass(self, template): |
|
11128.4.2
by Adi Roiban
Reduce the usage of URL formaters. |
974 |
if template.iscurrent: |
10095.5.1
by Adi Roiban
Initial fix. Pagetests needs to be updated. |
975 |
return "active-template" |
976 |
else: |
|
977 |
return "inactive-template" |
|
11532.6.1
by Jeroen Vermeulen
Render template column entirely in the view. |
978 |
|
979 |
def _renderSourcePackage(self, template): |
|
980 |
"""Render the `SourcePackageName` for `template`."""
|
|
981 |
if self.is_distroseries: |
|
982 |
return cgi.escape(template.sourcepackagename.name) |
|
983 |
else: |
|
984 |
return None |
|
985 |
||
986 |
def _renderTemplateLink(self, template, url): |
|
987 |
"""Render a link to `template`.
|
|
988 |
||
989 |
:param template: The target `POTemplate`.
|
|
990 |
:param url: The cached URL for `template`.
|
|
991 |
:return: HTML for a link to `template`.
|
|
992 |
"""
|
|
993 |
text = '<a href="%s">%s</a>' % (url, cgi.escape(template.name)) |
|
994 |
if not template.iscurrent: |
|
995 |
text += ' (inactive)' |
|
996 |
return text |
|
997 |
||
13378.3.14
by Benji York
checkpoint |
998 |
def _renderSharing(self, template, packaging, productseries, upstream, |
13378.3.15
by Benji York
I think it's working. |
999 |
other_template, sourcepackagename): |
13378.3.3
by Benji York
checkpoint |
1000 |
"""Render a link to `template`.
|
1001 |
||
1002 |
:param template: The target `POTemplate`.
|
|
1003 |
:return: HTML for the "sharing" status of `template`.
|
|
1004 |
"""
|
|
13378.3.16
by Benji York
checkpoint |
1005 |
# Testing is easier if we are willing to extract the sourcepackagename
|
1006 |
# from the template.
|
|
1007 |
if sourcepackagename is None: |
|
1008 |
sourcepackagename = template.sourcepackagename |
|
13378.3.8
by Benji York
add edit link for non-shared templates |
1009 |
# Build the edit link.
|
13378.3.15
by Benji York
I think it's working. |
1010 |
escaped_source = cgi.escape(sourcepackagename.name) |
13378.3.8
by Benji York
add edit link for non-shared templates |
1011 |
source_url = '+source/%s' % escaped_source |
1012 |
details_url = source_url + '/+sharing-details' |
|
1013 |
edit_link = '<a class="sprite edit" href="%s"></a>' % details_url |
|
13378.3.11
by Benji York
checkpoint |
1014 |
|
13378.3.7
by Benji York
made changes suggested by Danilo |
1015 |
# If all the conditions are met for sharing...
|
13378.3.14
by Benji York
checkpoint |
1016 |
if packaging and upstream and other_template is not None: |
13378.3.15
by Benji York
I think it's working. |
1017 |
escaped_series = cgi.escape(productseries.name) |
13378.3.7
by Benji York
made changes suggested by Danilo |
1018 |
escaped_template = cgi.escape(template.name) |
1019 |
pot_url = ('/%s/%s/+pots/%s' % |
|
1020 |
(escaped_source, escaped_series, escaped_template)) |
|
13378.3.8
by Benji York
add edit link for non-shared templates |
1021 |
return (edit_link + '<a href="%s">%s/%s</a>' |
1022 |
% (pot_url, escaped_source, escaped_series)) |
|
13378.3.3
by Benji York
checkpoint |
1023 |
else: |
13378.3.8
by Benji York
add edit link for non-shared templates |
1024 |
# Otherwise just say that the template isn't shared and give them
|
1025 |
# a link to change the sharing.
|
|
1026 |
return edit_link + 'not shared' |
|
13378.3.3
by Benji York
checkpoint |
1027 |
|
11532.6.1
by Jeroen Vermeulen
Render template column entirely in the view. |
1028 |
def _renderLastUpdateDate(self, template): |
1029 |
"""Render a template's "last updated" column."""
|
|
1030 |
formatter = DateTimeFormatterAPI(template.date_last_updated) |
|
1031 |
full_time = formatter.datetime() |
|
1032 |
date = formatter.approximatedate() |
|
1033 |
return ''.join([ |
|
1034 |
'<span class="sortkey">%s</span>' % full_time, |
|
1035 |
'<span class="lastupdate_column" title="%s">%s</span>' % ( |
|
1036 |
full_time, date), |
|
1037 |
])
|
|
1038 |
||
1039 |
def _renderAction(self, base_url, name, path, sprite, enabled): |
|
1040 |
"""Render an action for the "actions" column.
|
|
1041 |
||
1042 |
:param base_url: The cached URL for `template`.
|
|
1043 |
:param name: Action name for display in the UI.
|
|
1044 |
:param path: Path suffix for the action (relative to `base_url`).
|
|
1045 |
:param sprite: Sprite class for the action.
|
|
1046 |
:param enabled: Show this action? If not, return empty string.
|
|
1047 |
:return: HTML for the contents of the "actions" column.
|
|
1048 |
"""
|
|
1049 |
if not enabled: |
|
1050 |
return '' |
|
1051 |
||
1052 |
parameters = { |
|
1053 |
'base_url': base_url, |
|
1054 |
'name': name, |
|
1055 |
'path': path, |
|
1056 |
'sprite': sprite, |
|
1057 |
}
|
|
1058 |
return ( |
|
1059 |
'<a class="sprite %(sprite)s" href="%(base_url)s/%(path)s">' |
|
1060 |
'%(name)s' |
|
1061 |
'</a>') % parameters |
|
1062 |
||
1063 |
def _renderActionsColumn(self, template, base_url): |
|
1064 |
"""Render a template's "actions" column."""
|
|
1065 |
if not self.user_is_logged_in: |
|
1066 |
return None |
|
1067 |
||
1068 |
actions = [ |
|
1069 |
('Edit', '+edit', 'edit', self.can_edit), |
|
1070 |
('Upload', '+upload', 'add', self.can_edit), |
|
1071 |
('Download', '+export', 'download', self.user_is_logged_in), |
|
1072 |
('Administer', '+admin', 'edit', self.can_admin), |
|
1073 |
]
|
|
1074 |
links = [ |
|
1075 |
self._renderAction(base_url, *action) for action in actions] |
|
1076 |
html = '<div class="template_links">\n%s</div>' |
|
1077 |
return html % '\n'.join(links) |
|
1078 |
||
1079 |
def _renderField(self, column_class, content, tag='td'): |
|
1080 |
"""Create a table field of the given class and contents.
|
|
1081 |
||
1082 |
:param column_class: CSS class for this column.
|
|
1083 |
:param content: HTML to go into the column. If None, the field
|
|
1084 |
will be omitted entirely. (To produce an empty column, pass
|
|
1085 |
the empty string instead.)
|
|
1086 |
:param tag: The HTML tag to surround the field in.
|
|
1087 |
:return: HTML for the entire table field, or the empty string if
|
|
1088 |
`content` was None.
|
|
1089 |
"""
|
|
1090 |
if content is None: |
|
1091 |
return '' |
|
1092 |
else: |
|
1093 |
return '<%s class="%s">%s</%s>' % ( |
|
1094 |
tag, column_class, content, tag) |
|
1095 |
||
1096 |
def constructTemplateURL(self, template): |
|
1097 |
"""Build the URL for `template`.
|
|
1098 |
||
1099 |
Since this is performance-critical, views are allowed to
|
|
1100 |
override it with optimized implementations.
|
|
1101 |
"""
|
|
1102 |
return canonical_url(template) |
|
1103 |
||
1104 |
def renderTemplatesHeader(self): |
|
1105 |
"""Render HTML for the templates table header."""
|
|
1106 |
if self.is_distroseries: |
|
1107 |
sourcepackage_header = "Source package" |
|
1108 |
else: |
|
1109 |
sourcepackage_header = None |
|
1110 |
if self.user_is_logged_in: |
|
1111 |
actions_header = "Actions" |
|
1112 |
else: |
|
1113 |
actions_header = None |
|
13378.3.3
by Benji York
checkpoint |
1114 |
|
11532.6.1
by Jeroen Vermeulen
Render template column entirely in the view. |
1115 |
columns = [ |
1116 |
('priority_column', "Priority"), |
|
1117 |
('sourcepackage_column', sourcepackage_header), |
|
1118 |
('template_column', "Template name"), |
|
1119 |
('length_column', "Length"), |
|
1120 |
('lastupdate_column', "Updated"), |
|
1121 |
('actions_column', actions_header), |
|
1122 |
]
|
|
13378.3.3
by Benji York
checkpoint |
1123 |
|
13378.3.6
by Benji York
checkpoint |
1124 |
if self.is_distroseries: |
13378.3.7
by Benji York
made changes suggested by Danilo |
1125 |
columns[3:3] = [('sharing', "Shared with")] |
13378.3.3
by Benji York
checkpoint |
1126 |
|
11532.6.1
by Jeroen Vermeulen
Render template column entirely in the view. |
1127 |
return '\n'.join([ |
11542.2.1
by Jeroen Vermeulen
Python 2.6-ism. |
1128 |
self._renderField(css, text, tag='th') |
1129 |
for (css, text) in columns]) |
|
11532.6.1
by Jeroen Vermeulen
Render template column entirely in the view. |
1130 |
|
13378.3.12
by Benji York
checkpoint |
1131 |
def renderTemplateRow(self, template, packaging=None, productseries=None, |
13378.3.15
by Benji York
I think it's working. |
1132 |
upstream=None, other_template=None, sourcepackagename=None): |
11532.6.1
by Jeroen Vermeulen
Render template column entirely in the view. |
1133 |
"""Render HTML for an entire template row."""
|
1134 |
if not self.can_edit and not template.iscurrent: |
|
1135 |
return "" |
|
1136 |
||
1137 |
# Cached URL for template.
|
|
1138 |
base_url = self.constructTemplateURL(template) |
|
1139 |
||
1140 |
fields = [ |
|
1141 |
('priority_column', template.priority), |
|
1142 |
('sourcepackage_column', self._renderSourcePackage(template)), |
|
1143 |
('template_column', self._renderTemplateLink(template, base_url)), |
|
1144 |
('length_column', template.messagecount), |
|
1145 |
('lastupdate_column', self._renderLastUpdateDate(template)), |
|
1146 |
('actions_column', self._renderActionsColumn(template, base_url)), |
|
1147 |
]
|
|
1148 |
||
13378.3.6
by Benji York
checkpoint |
1149 |
if self.is_distroseries: |
13378.3.15
by Benji York
I think it's working. |
1150 |
fields[3:3] = [( |
1151 |
'sharing', self._renderSharing(template, packaging, |
|
1152 |
productseries, upstream, other_template, |
|
1153 |
sourcepackagename) |
|
1154 |
)]
|
|
13378.3.3
by Benji York
checkpoint |
1155 |
|
11532.6.1
by Jeroen Vermeulen
Render template column entirely in the view. |
1156 |
tds = [self._renderField(*field) for field in fields] |
1157 |
||
1158 |
css = self.rowCSSClass(template) |
|
1159 |
return '<tr class="template_row %s">\n%s</tr>\n' % ( |
|
1160 |
css, '\n'.join(tds)) |