Merge lp:~jtv/launchpad/bug-423705 into lp:launchpad
- bug-423705
- Merge into devel
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | not available | ||||
Proposed branch: | lp:~jtv/launchpad/bug-423705 | ||||
Merge into: | lp:launchpad | ||||
Diff against target: | None lines | ||||
To merge this branch: | bzr merge lp:~jtv/launchpad/bug-423705 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Nelson (community) | ui | Approve | |
Abel Deuring (community) | Approve | ||
Review via email: mp+11519@code.launchpad.net |
Commit message
Description of the change
Jeroen T. Vermeulen (jtv) wrote : | # |
Abel Deuring (adeuring) wrote : | # |
Hi Jeroen,
a very nice branch. We discussed two minor changes in IRC, please apply them
Michael Nelson (michael.nelson) wrote : | # |
Great work Jeroen!
The index page looks great!
Note: RE the icons not displaying, I'd say you just need to add icon='info' to your menu 'Link's.
We agreed it would be good to perhaps not include the edit translation guidelines here on the index page, but are not including it as part of this update.
<jtv> Anyone free to give me a UI review for https:/
<noodles775> jtv: I could - but I just saw that barry will be around on ocr soon - would you mind if I leave it to him?
<jtv> noodles775: I _hate_ to nag (well, except end-users) but this branch has been sitting on the review queue for a while, been accidentally removed from it, put back etc. If barry has no time, that pushes this to next week.
* jtv bats eyelids at noodles
<noodles775> jtv: ah, do you need to leave soon?
<jtv> noodles775: ideally, yes, though I don't think it's particularly likely :-)
<noodles775> OK, looking now...
<jtv> noodles775: great, thanks!
<noodles775> jtv: just noticed that I think you're doing something similar to https:/
<noodles775> with the 'sub-menu'...
<noodles775> The only difference being the icons?
<noodles775> jtv: btw, the index page looks great!
<jtv> noodles775: actually I copied the whole idea from there. :) _Keine_ _blasse_ _Ahnung_ why those icons don't appear for me. :(
<noodles775> heh
<jtv> noodles775: (glad you like the page btw)
<noodles775> jtv: I'm not sure about having the full translation groups table there? Well, at least the edit translation guidelines link... what do you think? I just noticed if you edit the translation guideline you obviously don't end up back on the same page...
<noodles775> But then again, I guess that's similar to clicking on the needs [link]2 strings reviewed[/link]
<jtv> noodles775: it's one of those things I would've liked to update, but avoided on the "timely and within the review limit beats perfect" principle.
<noodles775> jtv: yep, sure.
<jtv> noodles775: I do agree it can do with a makeover though
<jtv> (Or since this is all just outward appearance, is it really a combover?)
Preview Diff
1 | === modified file 'lib/canonical/launchpad/pagetitles.py' | |||
2 | --- lib/canonical/launchpad/pagetitles.py 2009-09-10 01:35:03 +0000 | |||
3 | +++ lib/canonical/launchpad/pagetitles.py 2009-09-10 10:09:18 +0000 | |||
4 | @@ -739,8 +739,6 @@ | |||
5 | 739 | 739 | ||
6 | 740 | person_specworkload = ContextDisplayName('Blueprint workload for %s') | 740 | person_specworkload = ContextDisplayName('Blueprint workload for %s') |
7 | 741 | 741 | ||
8 | 742 | person_translations = ContextDisplayName('Translations related to %s') | ||
9 | 743 | |||
10 | 744 | person_translations_to_review = ContextDisplayName( | 742 | person_translations_to_review = ContextDisplayName( |
11 | 745 | 'Translations for review by %s') | 743 | 'Translations for review by %s') |
12 | 746 | 744 | ||
13 | 747 | 745 | ||
14 | === modified file 'lib/canonical/launchpad/webapp/configure.zcml' | |||
15 | --- lib/canonical/launchpad/webapp/configure.zcml 2009-09-01 08:37:31 +0000 | |||
16 | +++ lib/canonical/launchpad/webapp/configure.zcml 2009-09-09 11:45:55 +0000 | |||
17 | @@ -513,6 +513,12 @@ | |||
18 | 513 | name="fmt" | 513 | name="fmt" |
19 | 514 | /> | 514 | /> |
20 | 515 | <adapter | 515 | <adapter |
21 | 516 | for="lp.translations.interfaces.pofile.IPOFile" | ||
22 | 517 | provides="zope.traversing.interfaces.IPathAdapter" | ||
23 | 518 | factory="canonical.launchpad.webapp.tales.POFileFormatterAPI" | ||
24 | 519 | name="fmt" | ||
25 | 520 | /> | ||
26 | 521 | <adapter | ||
27 | 516 | for="*" | 522 | for="*" |
28 | 517 | provides="zope.traversing.interfaces.IPathAdapter" | 523 | provides="zope.traversing.interfaces.IPathAdapter" |
29 | 518 | factory="canonical.launchpad.webapp.tales.PermissionRequiredQuery" | 524 | factory="canonical.launchpad.webapp.tales.PermissionRequiredQuery" |
30 | 519 | 525 | ||
31 | === modified file 'lib/canonical/launchpad/webapp/tales.py' | |||
32 | --- lib/canonical/launchpad/webapp/tales.py 2009-09-07 12:16:29 +0000 | |||
33 | +++ lib/canonical/launchpad/webapp/tales.py 2009-09-09 11:45:55 +0000 | |||
34 | @@ -3181,3 +3181,27 @@ | |||
35 | 3181 | def displayname(self, view_name, rootsite=None): | 3181 | def displayname(self, view_name, rootsite=None): |
36 | 3182 | """Return the displayname as a string.""" | 3182 | """Return the displayname as a string.""" |
37 | 3183 | return self._context.title | 3183 | return self._context.title |
38 | 3184 | |||
39 | 3185 | |||
40 | 3186 | class POFileFormatterAPI(ObjectFormatterAPI): | ||
41 | 3187 | """Adapter for `IPOFile` objects to a formatted string.""" | ||
42 | 3188 | |||
43 | 3189 | traversable_names = { | ||
44 | 3190 | 'link': 'link', | ||
45 | 3191 | 'url': 'url', | ||
46 | 3192 | 'displayname': 'displayname', | ||
47 | 3193 | } | ||
48 | 3194 | |||
49 | 3195 | def url(self, view_name=None, rootsite='translations'): | ||
50 | 3196 | """See `ObjectFormatterAPI`.""" | ||
51 | 3197 | return super(POFileFormatterAPI, self).url(view_name, rootsite) | ||
52 | 3198 | |||
53 | 3199 | def link(self, view_name, rootsite='translations'): | ||
54 | 3200 | """See `ObjectFormatterAPI`.""" | ||
55 | 3201 | pofile = self._context | ||
56 | 3202 | url = self.url(view_name, rootsite) | ||
57 | 3203 | return u'<a href="%s">%s</a>' % (url, cgi.escape(pofile.title)) | ||
58 | 3204 | |||
59 | 3205 | def displayname(self, view_name, rootsite=None): | ||
60 | 3206 | """Return the displayname as a string.""" | ||
61 | 3207 | return self._context.title | ||
62 | 3184 | 3208 | ||
63 | === modified file 'lib/lp/translations/browser/configure.zcml' | |||
64 | --- lib/lp/translations/browser/configure.zcml 2009-09-01 11:09:53 +0000 | |||
65 | +++ lib/lp/translations/browser/configure.zcml 2009-09-10 10:09:18 +0000 | |||
66 | @@ -709,7 +709,6 @@ | |||
67 | 709 | <browser:page | 709 | <browser:page |
68 | 710 | for="lp.registry.interfaces.person.IPerson" | 710 | for="lp.registry.interfaces.person.IPerson" |
69 | 711 | name="+licensing" | 711 | name="+licensing" |
70 | 712 | facet="translations" | ||
71 | 713 | class=" | 712 | class=" |
72 | 714 | lp.translations.browser.person.PersonTranslationRelicensingView" | 713 | lp.translations.browser.person.PersonTranslationRelicensingView" |
73 | 715 | permission="launchpad.Edit" | 714 | permission="launchpad.Edit" |
74 | @@ -719,12 +718,24 @@ | |||
75 | 719 | for="lp.registry.interfaces.person.IPerson" | 718 | for="lp.registry.interfaces.person.IPerson" |
76 | 720 | name="+imports" | 719 | name="+imports" |
77 | 721 | class="lp.translations.browser.hastranslationimports.HasTranslationImportsView" | 720 | class="lp.translations.browser.hastranslationimports.HasTranslationImportsView" |
78 | 722 | facet="translations" | ||
79 | 723 | permission="zope.Public" | 721 | permission="zope.Public" |
80 | 724 | template="../templates/hastranslationimports-index.pt" | 722 | template="../templates/hastranslationimports-index.pt" |
81 | 725 | layer="canonical.launchpad.layers.TranslationsLayer"/> | 723 | layer="canonical.launchpad.layers.TranslationsLayer"/> |
82 | 726 | <browser:page | 724 | <browser:page |
83 | 727 | for="lp.registry.interfaces.person.IPerson" | 725 | for="lp.registry.interfaces.person.IPerson" |
84 | 726 | class="lp.translations.browser.person.PersonTranslationView" | ||
85 | 727 | permission="zope.Public" | ||
86 | 728 | name="+person-navlinks" | ||
87 | 729 | template="../templates/person-navlinks.pt"/> | ||
88 | 730 | <browser:page | ||
89 | 731 | for="lp.registry.interfaces.person.IPerson" | ||
90 | 732 | name="+activity" | ||
91 | 733 | class="lp.translations.browser.person.TranslationActivityView" | ||
92 | 734 | permission="zope.Public" | ||
93 | 735 | template="../templates/person-translation-activity.pt" | ||
94 | 736 | layer="canonical.launchpad.layers.TranslationsLayer"/> | ||
95 | 737 | <browser:page | ||
96 | 738 | for="lp.registry.interfaces.person.IPerson" | ||
97 | 728 | name="+translations-to-review" | 739 | name="+translations-to-review" |
98 | 729 | class="lp.translations.browser.person.PersonTranslationView" | 740 | class="lp.translations.browser.person.PersonTranslationView" |
99 | 730 | permission="zope.Public" | 741 | permission="zope.Public" |
100 | 731 | 742 | ||
101 | === modified file 'lib/lp/translations/browser/person.py' | |||
102 | --- lib/lp/translations/browser/person.py 2009-09-09 16:49:35 +0000 | |||
103 | +++ lib/lp/translations/browser/person.py 2009-09-10 11:56:21 +0000 | |||
104 | @@ -8,13 +8,16 @@ | |||
105 | 8 | __all__ = [ | 8 | __all__ = [ |
106 | 9 | 'PersonTranslationView', | 9 | 'PersonTranslationView', |
107 | 10 | 'PersonTranslationRelicensingView', | 10 | 'PersonTranslationRelicensingView', |
108 | 11 | 'TranslationActivityView', | ||
109 | 11 | ] | 12 | ] |
110 | 12 | 13 | ||
111 | 13 | from datetime import datetime, timedelta | 14 | from datetime import datetime, timedelta |
112 | 14 | import pytz | 15 | import pytz |
113 | 15 | import urllib | 16 | import urllib |
114 | 17 | |||
115 | 16 | from zope.app.form.browser import TextWidget | 18 | from zope.app.form.browser import TextWidget |
116 | 17 | from zope.component import getUtility | 19 | from zope.component import getUtility |
117 | 20 | from zope.interface import implements, Interface | ||
118 | 18 | 21 | ||
119 | 19 | from canonical.launchpad import _ | 22 | from canonical.launchpad import _ |
120 | 20 | from canonical.launchpad.webapp.interfaces import ILaunchBag | 23 | from canonical.launchpad.webapp.interfaces import ILaunchBag |
121 | @@ -25,7 +28,6 @@ | |||
122 | 25 | from canonical.launchpad.webapp.batching import BatchNavigator | 28 | from canonical.launchpad.webapp.batching import BatchNavigator |
123 | 26 | from canonical.launchpad.webapp.publisher import LaunchpadView | 29 | from canonical.launchpad.webapp.publisher import LaunchpadView |
124 | 27 | from canonical.widgets import LaunchpadRadioWidget | 30 | from canonical.widgets import LaunchpadRadioWidget |
125 | 28 | from lp.registry.interfaces.person import IPerson | ||
126 | 29 | from lp.registry.interfaces.sourcepackage import ISourcePackage | 31 | from lp.registry.interfaces.sourcepackage import ISourcePackage |
127 | 30 | from lp.translations.browser.translationlinksaggregator import ( | 32 | from lp.translations.browser.translationlinksaggregator import ( |
128 | 31 | TranslationLinksAggregator) | 33 | TranslationLinksAggregator) |
129 | @@ -89,18 +91,56 @@ | |||
130 | 89 | return pofile.untranslatedCount() | 91 | return pofile.untranslatedCount() |
131 | 90 | 92 | ||
132 | 91 | 93 | ||
133 | 94 | def compose_pofile_filter_url(pofile, person): | ||
134 | 95 | """Compose URL for `Person`'s contributions to `POFile`.""" | ||
135 | 96 | person_name = urllib.urlencode({'person': person.name}) | ||
136 | 97 | return canonical_url(pofile) + "/+filter?%s" % person_name | ||
137 | 98 | |||
138 | 99 | |||
139 | 100 | class ActivityDescriptor: | ||
140 | 101 | """Description of a past translation activity.""" | ||
141 | 102 | |||
142 | 103 | date = None | ||
143 | 104 | title = None | ||
144 | 105 | url = None | ||
145 | 106 | |||
146 | 107 | def __init__(self, person, pofiletranslator): | ||
147 | 108 | """Describe a past translation activity by `person`. | ||
148 | 109 | |||
149 | 110 | :param person: The `Person` whose activity is being described. | ||
150 | 111 | :param pofiletranslator: A `POFileTranslator` record for | ||
151 | 112 | `person`. | ||
152 | 113 | """ | ||
153 | 114 | assert person == pofiletranslator.person, ( | ||
154 | 115 | "This POFileTranslator record is for the wrong person.") | ||
155 | 116 | |||
156 | 117 | self.date = pofiletranslator.date_last_touched | ||
157 | 118 | |||
158 | 119 | pofile = pofiletranslator.pofile | ||
159 | 120 | |||
160 | 121 | self.title = pofile.potemplate.translationtarget.title | ||
161 | 122 | self.url = compose_pofile_filter_url(pofile, person) | ||
162 | 123 | |||
163 | 124 | |||
164 | 92 | def person_is_reviewer(person): | 125 | def person_is_reviewer(person): |
165 | 93 | """Is `person` a translations reviewer?""" | 126 | """Is `person` a translations reviewer?""" |
166 | 94 | groups = ITranslationsPerson(person).translation_groups | 127 | groups = ITranslationsPerson(person).translation_groups |
167 | 95 | return groups.any() is not None | 128 | return groups.any() is not None |
168 | 96 | 129 | ||
169 | 97 | 130 | ||
170 | 131 | class IPersonTranslationsMenu(Interface): | ||
171 | 132 | """Marker interface for `Person` Translations navigation menu.""" | ||
172 | 133 | |||
173 | 134 | |||
174 | 98 | class PersonTranslationsMenu(NavigationMenu): | 135 | class PersonTranslationsMenu(NavigationMenu): |
175 | 99 | 136 | ||
177 | 100 | usedfor = IPerson | 137 | usedfor = IPersonTranslationsMenu |
178 | 101 | facet = 'translations' | 138 | facet = 'translations' |
179 | 102 | links = ('overview', 'licensing', 'imports', 'translations_to_review') | 139 | links = ('overview', 'licensing', 'imports', 'translations_to_review') |
181 | 103 | title = "Related pages" | 140 | |
182 | 141 | @property | ||
183 | 142 | def person(self): | ||
184 | 143 | return self.context.context | ||
185 | 104 | 144 | ||
186 | 105 | def overview(self): | 145 | def overview(self): |
187 | 106 | text = 'Overview' | 146 | text = 'Overview' |
188 | @@ -112,37 +152,45 @@ | |||
189 | 112 | 152 | ||
190 | 113 | def licensing(self): | 153 | def licensing(self): |
191 | 114 | text = 'Translations licensing' | 154 | text = 'Translations licensing' |
193 | 115 | enabled = (self.context == self.user) | 155 | enabled = (self.person == self.user) |
194 | 116 | return Link('+licensing', text, enabled=enabled) | 156 | return Link('+licensing', text, enabled=enabled) |
195 | 117 | 157 | ||
196 | 118 | def translations_to_review(self): | 158 | def translations_to_review(self): |
197 | 119 | text = 'Translations to review' | 159 | text = 'Translations to review' |
199 | 120 | enabled = person_is_reviewer(self.context) | 160 | enabled = person_is_reviewer(self.person) |
200 | 121 | return Link('+translations-to-review', text, enabled=enabled) | 161 | return Link('+translations-to-review', text, enabled=enabled) |
201 | 122 | 162 | ||
202 | 123 | 163 | ||
203 | 124 | class PersonTranslationView(LaunchpadView): | 164 | class PersonTranslationView(LaunchpadView): |
204 | 125 | """View for translation-related Person pages.""" | 165 | """View for translation-related Person pages.""" |
205 | 166 | implements(IPersonTranslationsMenu) | ||
206 | 126 | 167 | ||
208 | 127 | _pofiletranslator_cache = None | 168 | reviews_to_show = 10 |
209 | 128 | 169 | ||
210 | 129 | def __init__(self, *args, **kwargs): | 170 | def __init__(self, *args, **kwargs): |
211 | 130 | super(PersonTranslationView, self).__init__(*args, **kwargs) | 171 | super(PersonTranslationView, self).__init__(*args, **kwargs) |
212 | 131 | now = datetime.now(pytz.timezone('UTC')) | 172 | now = datetime.now(pytz.timezone('UTC')) |
213 | 132 | self.history_horizon = now - timedelta(90, 0, 0) | 173 | self.history_horizon = now - timedelta(90, 0, 0) |
214 | 133 | 174 | ||
217 | 134 | @cachedproperty | 175 | @property |
218 | 135 | def batchnav(self): | 176 | def page_title(self): |
219 | 177 | return "Translations related to %s" % self.context.displayname | ||
220 | 178 | |||
221 | 179 | @cachedproperty | ||
222 | 180 | def recent_activity(self): | ||
223 | 181 | """Recent translation activity by this person.""" | ||
224 | 182 | entries = ITranslationsPerson(self.context).translation_history[:10] | ||
225 | 183 | return [ActivityDescriptor(self.context, entry) for entry in entries] | ||
226 | 184 | |||
227 | 185 | @cachedproperty | ||
228 | 186 | def latest_activity(self): | ||
229 | 187 | """Single latest translation activity by this person.""" | ||
230 | 136 | translations_person = ITranslationsPerson(self.context) | 188 | translations_person = ITranslationsPerson(self.context) |
240 | 137 | batchnav = BatchNavigator( | 189 | latest = list(translations_person.translation_history[:1]) |
241 | 138 | translations_person.translation_history, self.request) | 190 | if len(latest) == 0: |
242 | 139 | 191 | return None | |
243 | 140 | pofiletranslatorset = getUtility(IPOFileTranslatorSet) | 192 | else: |
244 | 141 | batch = batchnav.currentBatch() | 193 | return ActivityDescriptor(self.context, latest[0]) |
236 | 142 | self._pofiletranslator_cache = ( | ||
237 | 143 | pofiletranslatorset.prefetchPOFileTranslatorRelations(batch)) | ||
238 | 144 | |||
239 | 145 | return batchnav | ||
245 | 146 | 194 | ||
246 | 147 | @cachedproperty | 195 | @cachedproperty |
247 | 148 | def translation_groups(self): | 196 | def translation_groups(self): |
248 | @@ -156,11 +204,6 @@ | |||
249 | 156 | translations_person = ITranslationsPerson(self.context) | 204 | translations_person = ITranslationsPerson(self.context) |
250 | 157 | return list(translations_person.translators) | 205 | return list(translations_person.translators) |
251 | 158 | 206 | ||
252 | 159 | @cachedproperty | ||
253 | 160 | def person_filter_querystring(self): | ||
254 | 161 | """Return person's name appropriate for including in links.""" | ||
255 | 162 | return urllib.urlencode({'person': self.context.name}) | ||
256 | 163 | |||
257 | 164 | @property | 207 | @property |
258 | 165 | def person_is_reviewer(self): | 208 | def person_is_reviewer(self): |
259 | 166 | """Is this person in a translation group?""" | 209 | """Is this person in a translation group?""" |
260 | @@ -429,3 +472,29 @@ | |||
261 | 429 | "Unknown allow_relicensing value: %r" % allow_relicensing) | 472 | "Unknown allow_relicensing value: %r" % allow_relicensing) |
262 | 430 | self.next_url = self.getSafeRedirectURL(data['back_to']) | 473 | self.next_url = self.getSafeRedirectURL(data['back_to']) |
263 | 431 | 474 | ||
264 | 475 | |||
265 | 476 | class TranslationActivityView(LaunchpadView): | ||
266 | 477 | """View for person's activity listing.""" | ||
267 | 478 | |||
268 | 479 | _pofiletranslator_cache = None | ||
269 | 480 | |||
270 | 481 | @property | ||
271 | 482 | def page_title(self): | ||
272 | 483 | return "Translation activity by %s" % self.context.displayname | ||
273 | 484 | |||
274 | 485 | @cachedproperty | ||
275 | 486 | def batchnav(self): | ||
276 | 487 | """Iterate over person's translation_history.""" | ||
277 | 488 | translations_person = ITranslationsPerson(self.context) | ||
278 | 489 | batchnav = BatchNavigator( | ||
279 | 490 | translations_person.translation_history, self.request) | ||
280 | 491 | |||
281 | 492 | pofiletranslatorset = getUtility(IPOFileTranslatorSet) | ||
282 | 493 | batch = batchnav.currentBatch() | ||
283 | 494 | self._pofiletranslator_cache = ( | ||
284 | 495 | pofiletranslatorset.prefetchPOFileTranslatorRelations(batch)) | ||
285 | 496 | |||
286 | 497 | return batchnav | ||
287 | 498 | |||
288 | 499 | def composeURL(self, pofile): | ||
289 | 500 | return compose_pofile_filter_url(pofile, self.context) | ||
290 | 432 | 501 | ||
291 | === renamed file 'lib/lp/translations/stories/standalone/xx-person-translations.txt' => 'lib/lp/translations/stories/standalone/xx-person-activity.txt' | |||
292 | --- lib/lp/translations/stories/standalone/xx-person-translations.txt 2009-09-01 09:51:12 +0000 | |||
293 | +++ lib/lp/translations/stories/standalone/xx-person-activity.txt 2009-09-10 11:56:21 +0000 | |||
294 | @@ -1,13 +1,13 @@ | |||
297 | 1 | Test that the person's translation history page displays the latest | 1 | Person's translation activity |
298 | 2 | translations and translation groups related to the person in question. | 2 | ============================= |
299 | 3 | |||
300 | 4 | A person's translation activity page displays the translations that the | ||
301 | 5 | person has contributed to. | ||
302 | 6 | |||
303 | 7 | Here the person whose activity we're going to look at is Carlos. | ||
304 | 3 | 8 | ||
305 | 4 | >>> anon_browser.open( | 9 | >>> anon_browser.open( |
312 | 5 | ... "http://translations.launchpad.dev/people/carlos/+translations") | 10 | ... "http://translations.launchpad.dev/people/carlos/+activity") |
307 | 6 | |||
308 | 7 | >>> header = find_tag_by_id( | ||
309 | 8 | ... anon_browser.contents, 'translation-history-header') | ||
310 | 9 | >>> print extract_text(header) | ||
311 | 10 | Applications and packages translated | ||
313 | 11 | 11 | ||
314 | 12 | The user can see in the page navigation that Carlos has so far worked | 12 | The user can see in the page navigation that Carlos has so far worked |
315 | 13 | on six files, five of which are shown on this page. | 13 | on six files, five of which are shown on this page. |
316 | @@ -20,74 +20,60 @@ | |||
317 | 20 | 20 | ||
318 | 21 | # Prints a heading and formatted list of POFiles and latest submissions. | 21 | # Prints a heading and formatted list of POFiles and latest submissions. |
319 | 22 | >>> import re | 22 | >>> import re |
353 | 23 | >>> def print_list_of_contributions(listing): | 23 | >>> def print_activity_list(listing): |
354 | 24 | ... listing_head = listing.findAll('thead')[0].findAll('tr')[0] | 24 | ... for row in listing.findAll('tr'): |
355 | 25 | ... heading_cells = listing_head.findAll('th') | 25 | ... print extract_text(row) |
356 | 26 | ... print "%-24s %-8s %-8s %-26s" % ( | 26 | |
357 | 27 | ... extract_text(heading_cells[0]), | 27 | >>> listing = find_tag_by_id(anon_browser.contents, 'activity-table') |
358 | 28 | ... extract_text(heading_cells[1])[:6] + '...', | 28 | >>> print_activity_list(listing) |
359 | 29 | ... extract_text(heading_cells[2])[:6] + '...', | 29 | 2007-07-12 |
360 | 30 | ... extract_text(heading_cells[3])) | 30 | English (en) translation of pkgconf-mozilla in Ubuntu Hoary package |
361 | 31 | ... listing_body = listing.find('tbody') | 31 | "mozilla" |
362 | 32 | ... for row in listing_body.findAll('tr'): | 32 | 2007-04-07 |
363 | 33 | ... cells = row.findAll('td') | 33 | Spanish (es) translation of alsa-utils in alsa-utils trunk |
364 | 34 | ... pofile = extract_text(cells[0]) | 34 | 2007-01-24 |
365 | 35 | ... if len(pofile) > 24: | 35 | Spanish (es) translation of man in Ubuntu Hoary package "evolution" |
366 | 36 | ... pofile = pofile[:21] + '...' | 36 | 2006-12-22 |
367 | 37 | ... untranslated = extract_text(cells[1]) | 37 | Spanish (es) translation of evolution-2.2 in Evolution trunk |
368 | 38 | ... needs_review = extract_text(cells[2]) | 38 | 2005-10-11 |
369 | 39 | ... message = re.sub(' +', ' ', extract_text(cells[3])) | 39 | Japanese (ja) translation of evolution-2.2 in Ubuntu Hoary package |
370 | 40 | ... if len(message) > 26: | 40 | "evolution" |
371 | 41 | ... message = message[:23] + '...' | 41 | |
372 | 42 | ... print "%-24s %-10s %-10s %-26s" % ( | 42 | Clicking one of the entries takes you to a page listing all of Carlos' |
373 | 43 | ... pofile, untranslated, needs_review, message) | 43 | contributions to the selected translation. |
341 | 44 | |||
342 | 45 | >>> listing = find_tags_by_class(anon_browser.contents, 'listing')[0] | ||
343 | 46 | >>> print_list_of_contributions(listing) | ||
344 | 47 | Translation file Untra... Need... Latest translation | ||
345 | 48 | English (en) translat... 6 0 2007-07-12 auto, esddsp... | ||
346 | 49 | Spanish (es) translat... 3 0 2007-04-07 _: EMAIL OF ... | ||
347 | 50 | Spanish (es) translat... 0 0 2007-01-24 test man pag... | ||
348 | 51 | Spanish (es) translat... 14 2 2006-12-22 have lalalala | ||
349 | 52 | Japanese (ja) transla... 21 0 2005-10-11 %d contact %... | ||
350 | 53 | |||
351 | 54 | When the user clicks one of the entries, he is shown a page listing | ||
352 | 55 | all translations done by Carlos in this file. | ||
374 | 56 | 44 | ||
375 | 57 | >>> alsa_utils_link = 'Spanish (es) translation of alsa-utils in alsa-utils trunk' | 45 | >>> alsa_utils_link = 'Spanish (es) translation of alsa-utils in alsa-utils trunk' |
376 | 58 | >>> anon_browser.getLink(alsa_utils_link).click() | 46 | >>> anon_browser.getLink(alsa_utils_link).click() |
396 | 59 | >>> anon_browser.title | 47 | >>> print anon_browser.title |
397 | 60 | 'Translations by Carlos...of alsa-utils...' | 48 | Translations by Carlos...of alsa-utils... |
398 | 61 | 49 | ||
399 | 62 | From the full listing of all contributions, Carlos can jump to the pages | 50 | |
400 | 63 | containing only untranslated or only translations that need reviewing. | 51 | URL-escaped user names |
401 | 64 | 52 | ---------------------- | |
402 | 65 | >>> anon_browser.goBack() | 53 | |
403 | 66 | >>> untranslated_link = find_tags_by_class(anon_browser.contents, | 54 | Since the user's name is included in the URL, and user names can contain |
404 | 67 | ... 'untranslated-count')[1] | 55 | some slightly weird characters, it is escaped especially for this usage. |
405 | 68 | >>> extract_link_from_tag(untranslated_link) | 56 | |
406 | 69 | u'/alsa-utils/trunk/+pots/alsa-utils/es/+translate?show=untranslated' | 57 | For instance, here's a user called a+b. |
388 | 70 | |||
389 | 71 | >>> unreviewed_link = find_tags_by_class(anon_browser.contents, | ||
390 | 72 | ... 'unreviewed-count')[1] | ||
391 | 73 | >>> extract_link_from_tag(unreviewed_link) | ||
392 | 74 | u'/alsa-utils/trunk/+pots/alsa-utils/es/+translate?show=new_suggestions' | ||
393 | 75 | |||
394 | 76 | A person is created with a name containing characters that need escaping | ||
395 | 77 | before being used in query strings. | ||
407 | 78 | 58 | ||
408 | 79 | >>> login('carlos@canonical.com') | 59 | >>> login('carlos@canonical.com') |
412 | 80 | >>> foobar = factory.makePerson(name='foo+bar', email='blah@test.com') | 60 | >>> ab = factory.makePerson(name='a+b') |
413 | 81 | >>> message = factory.makeTranslationMessage(translator=foobar) | 61 | >>> message = factory.makeTranslationMessage(translator=ab) |
414 | 82 | >>> person_url = canonical_url(foobar, rootsite='translations') | 62 | >>> person_url = canonical_url(ab, rootsite='translations') |
415 | 83 | >>> logout() | 63 | >>> logout() |
416 | 84 | 64 | ||
426 | 85 | When that person goes to see the translations she has done, she sees | 65 | When a+b goes to see the translations she has done, she sees a correctly |
427 | 86 | a correctly encoded link to a filtered PO file page. | 66 | encoded link to a filtered PO file page. |
428 | 87 | 67 | ||
429 | 88 | >>> user_browser.open(person_url) | 68 | >>> user_browser.open(person_url + '/+activity') |
430 | 89 | >>> table = first_tag_by_class(user_browser.contents, 'listing') | 69 | >>> table = find_tag_by_id(user_browser.contents, 'activity-table') |
431 | 90 | >>> tbody = table.find('tbody') | 70 | >>> link = table.find('a') |
432 | 91 | >>> link = tbody.find('a') | 71 | >>> url = link['href'] |
433 | 92 | >>> link['href'].split('/')[-1] | 72 | >>> print url.split('/')[-1] |
434 | 93 | u'+filter?person=foo%2Bbar' | 73 | +filter?person=a%2Bb |
435 | 74 | |||
436 | 75 | Because of this, the link actually works. | ||
437 | 76 | |||
438 | 77 | >>> user_browser.open(url.encode('ascii')) | ||
439 | 78 | >>> print user_browser.title | ||
440 | 79 | Translations by ... | ||
441 | 94 | 80 | ||
442 | === added file 'lib/lp/translations/templates/person-navlinks.pt' | |||
443 | --- lib/lp/translations/templates/person-navlinks.pt 1970-01-01 00:00:00 +0000 | |||
444 | +++ lib/lp/translations/templates/person-navlinks.pt 2009-09-10 11:56:21 +0000 | |||
445 | @@ -0,0 +1,21 @@ | |||
446 | 1 | <tal:root | ||
447 | 2 | xmlns:tal="http://xml.zope.org/namespaces/tal" | ||
448 | 3 | xmlns:metal="http://xml.zope.org/namespaces/metal" | ||
449 | 4 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" | ||
450 | 5 | omit-tag=""> | ||
451 | 6 | |||
452 | 7 | <ul id="navlinks" class="horizontal"> | ||
453 | 8 | <li> | ||
454 | 9 | <a tal:replace="structure view/menu:navigation/overview/render"/> | ||
455 | 10 | </li> | ||
456 | 11 | <li> | ||
457 | 12 | <a tal:replace="structure view/menu:navigation/licensing/render"/> | ||
458 | 13 | </li> | ||
459 | 14 | <li> | ||
460 | 15 | <a tal:replace="structure view/menu:navigation/imports/render"/> | ||
461 | 16 | </li> | ||
462 | 17 | <li> | ||
463 | 18 | <a tal:replace="structure view/menu:navigation/translations_to_review/render"/> | ||
464 | 19 | </li> | ||
465 | 20 | </ul> | ||
466 | 21 | </tal:root> | ||
467 | 0 | 22 | ||
468 | === added file 'lib/lp/translations/templates/person-translation-activity.pt' | |||
469 | --- lib/lp/translations/templates/person-translation-activity.pt 1970-01-01 00:00:00 +0000 | |||
470 | +++ lib/lp/translations/templates/person-translation-activity.pt 2009-09-10 11:53:09 +0000 | |||
471 | @@ -0,0 +1,41 @@ | |||
472 | 1 | <html | ||
473 | 2 | xmlns="http://www.w3.org/1999/xhtml" | ||
474 | 3 | xmlns:tal="http://xml.zope.org/namespaces/tal" | ||
475 | 4 | xmlns:metal="http://xml.zope.org/namespaces/metal" | ||
476 | 5 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" | ||
477 | 6 | metal:use-macro="view/macro:page/main_only" | ||
478 | 7 | > | ||
479 | 8 | <body> | ||
480 | 9 | <div metal:fill-slot="main"> | ||
481 | 10 | <div class="top-portlet" style="max-width: 800px"> | ||
482 | 11 | <p> | ||
483 | 12 | <tal:person replace="structure context/fmt:link">R. Viewer</tal:person> | ||
484 | 13 | has contributed to the following translations. | ||
485 | 14 | </p> | ||
486 | 15 | |||
487 | 16 | <div class="lesser" id="top-navigation"> | ||
488 | 17 | <tal:navigation content="structure view/batchnav/@@+navigation-links-upper" /> | ||
489 | 18 | </div> | ||
490 | 19 | |||
491 | 20 | <table class="listing" id="activity-table"> | ||
492 | 21 | <tr tal:repeat="record view/batchnav/currentBatch"> | ||
493 | 22 | <td tal:attributes="title record/date_last_touched/fmt:datetime" | ||
494 | 23 | tal:content="record/date_last_touched/fmt:approximatedate"> | ||
495 | 24 | 2009-10-28 | ||
496 | 25 | </td> | ||
497 | 26 | <td> | ||
498 | 27 | <a tal:attributes="href python:view.composeURL(record.pofile)" | ||
499 | 28 | tal:content="record/pofile/title"> | ||
500 | 29 | Greek (el) translations of alsa-utils in alsa-utils trunk | ||
501 | 30 | </a> | ||
502 | 31 | </td> | ||
503 | 32 | </tr> | ||
504 | 33 | </table> | ||
505 | 34 | |||
506 | 35 | <div class="lesser"> | ||
507 | 36 | <tal:navigation content="structure view/batchnav/@@+navigation-links-lower" /> | ||
508 | 37 | </div> | ||
509 | 38 | </div> | ||
510 | 39 | </div> | ||
511 | 40 | </body> | ||
512 | 41 | </html> | ||
513 | 0 | 42 | ||
514 | === modified file 'lib/lp/translations/templates/person-translations-to-complete-table.pt' | |||
515 | --- lib/lp/translations/templates/person-translations-to-complete-table.pt 2009-08-28 09:44:31 +0000 | |||
516 | +++ lib/lp/translations/templates/person-translations-to-complete-table.pt 2009-09-09 09:51:14 +0000 | |||
517 | @@ -4,7 +4,7 @@ | |||
518 | 4 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" | 4 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
519 | 5 | omit-tag=""> | 5 | omit-tag=""> |
520 | 6 | 6 | ||
522 | 7 | <table class="listing" id="translations-to-complete-table"> | 7 | <table class="summary" id="translations-to-complete-table"> |
523 | 8 | <tr tal:repeat="target_info view/top_projects_and_packages_to_translate"> | 8 | <tr tal:repeat="target_info view/top_projects_and_packages_to_translate"> |
524 | 9 | <td> | 9 | <td> |
525 | 10 | <tal:product condition="target_info/is_product" | 10 | <tal:product condition="target_info/is_product" |
526 | 11 | 11 | ||
527 | === modified file 'lib/lp/translations/templates/person-translations-to-review-table.pt' | |||
528 | --- lib/lp/translations/templates/person-translations-to-review-table.pt 2009-08-12 07:59:37 +0000 | |||
529 | +++ lib/lp/translations/templates/person-translations-to-review-table.pt 2009-09-09 09:51:14 +0000 | |||
530 | @@ -4,7 +4,7 @@ | |||
531 | 4 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" | 4 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
532 | 5 | omit-tag=""> | 5 | omit-tag=""> |
533 | 6 | 6 | ||
535 | 7 | <table class="listing" id="translations-to-review-table"> | 7 | <table class="summary" id="translations-to-review-table"> |
536 | 8 | <tr tal:repeat="target_info view/top_projects_and_packages_to_review"> | 8 | <tr tal:repeat="target_info view/top_projects_and_packages_to_review"> |
537 | 9 | <td> | 9 | <td> |
538 | 10 | <tal:product condition="target_info/is_product" | 10 | <tal:product condition="target_info/is_product" |
539 | 11 | 11 | ||
540 | === modified file 'lib/lp/translations/templates/person-translations.pt' | |||
541 | --- lib/lp/translations/templates/person-translations.pt 2009-09-09 16:49:35 +0000 | |||
542 | +++ lib/lp/translations/templates/person-translations.pt 2009-09-10 11:53:09 +0000 | |||
543 | @@ -3,35 +3,56 @@ | |||
544 | 3 | xmlns:tal="http://xml.zope.org/namespaces/tal" | 3 | xmlns:tal="http://xml.zope.org/namespaces/tal" |
545 | 4 | xmlns:metal="http://xml.zope.org/namespaces/metal" | 4 | xmlns:metal="http://xml.zope.org/namespaces/metal" |
546 | 5 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" | 5 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
547 | 6 | metal:use-macro="view/macro:page/main_only" | ||
548 | 6 | i18n:domain="launchpad" | 7 | i18n:domain="launchpad" |
549 | 7 | xml:lang="en" | ||
550 | 8 | lang="en" | ||
551 | 9 | dir="ltr" | ||
552 | 10 | metal:use-macro="view/macro:page/onecolumn" | ||
553 | 11 | > | 8 | > |
554 | 12 | 9 | ||
555 | 13 | <body> | 10 | <body> |
556 | 14 | 11 | ||
558 | 15 | <h1>Translations related to <tal:name content="context/displayname" /></h1> | 12 | <div metal:fill-slot="heading"> |
559 | 13 | <h1 tal:content="view/page_title" /> | ||
560 | 14 | </div> | ||
561 | 16 | 15 | ||
562 | 17 | <div metal:fill-slot="main"> | 16 | <div metal:fill-slot="main"> |
563 | 17 | <div class="top-portlet"> | ||
564 | 18 | <tal:navlinks replace="structure context/@@+person-navlinks" /> | ||
565 | 19 | </div> | ||
566 | 18 | 20 | ||
567 | 19 | <tal:me condition="view/person_includes_me"> | 21 | <tal:me condition="view/person_includes_me"> |
569 | 20 | <p tal:condition="view/requires_preferred_languages" id="no-languages"> | 22 | <div tal:condition="view/requires_preferred_languages" |
570 | 23 | class="portlet" | ||
571 | 24 | id="no-languages"> | ||
572 | 21 | You have not selected your preferred languages. Please | 25 | You have not selected your preferred languages. Please |
573 | 22 | <a href="/+editmylanguages" id="set-languages">set them now</a>. | 26 | <a href="/+editmylanguages" id="set-languages">set them now</a>. |
575 | 23 | </p> | 27 | </div> |
576 | 28 | </tal:me> | ||
577 | 29 | |||
578 | 30 | <div class="portlet"> | ||
579 | 31 | <tal:active tal:condition="view/latest_activity"> | ||
580 | 32 | Last translation activity by | ||
581 | 33 | <tal:name replace="context/displayname">Foo Bar</tal:name> | ||
582 | 34 | was | ||
583 | 35 | <tal:date replace="view/latest_activity/date/fmt:displaydate"> | ||
584 | 36 | on 2009-10-12</tal:date>. | ||
585 | 37 | </tal:active> | ||
586 | 38 | <tal:inactive tal:condition="not: view/latest_activity"> | ||
587 | 39 | No translation activities recorded for | ||
588 | 40 | <tal:name replace="context/displayname">Foo Bar</tal:name>. | ||
589 | 41 | </tal:inactive> | ||
590 | 42 | </div> | ||
591 | 43 | |||
592 | 44 | <tal:me condition="view/person_includes_me"> | ||
593 | 24 | <tal:reviewer condition="view/person_is_reviewer"> | 45 | <tal:reviewer condition="view/person_is_reviewer"> |
600 | 25 | <div id="translations-to-review-section" style="max-width:800px"> | 46 | <div id="translations-to-review-section" class="portlet"> |
595 | 26 | <span style="float:right"> | ||
596 | 27 | <a href="http://help.launchpad.net/Translations/Reviewing"> | ||
597 | 28 | Why is this important? | ||
598 | 29 | </a> | ||
599 | 30 | </span> | ||
601 | 31 | <h2>Translations you need to review</h2> | 47 | <h2>Translations you need to review</h2> |
602 | 48 | <span style="display:block; text-align:right"> | ||
603 | 49 | <a href="http://help.launchpad.net/Translations/Reviewing"> | ||
604 | 50 | Why is this important? | ||
605 | 51 | </a> | ||
606 | 52 | </span> | ||
607 | 32 | <metal:translations-to-review | 53 | <metal:translations-to-review |
608 | 33 | tal:replace="structure context/@@+translations-to-review-table" /> | 54 | tal:replace="structure context/@@+translations-to-review-table" /> |
610 | 34 | <span style="float:right" | 55 | <span style="display:block; text-align:right" |
611 | 35 | tal:condition="python: view.num_projects_and_packages_to_review > 1"> | 56 | tal:condition="python: view.num_projects_and_packages_to_review > 1"> |
612 | 36 | <a href="+translations-to-review" id="translations-to-review-link"> | 57 | <a href="+translations-to-review" id="translations-to-review-link"> |
613 | 37 | See all | 58 | See all |
614 | @@ -42,9 +63,11 @@ | |||
615 | 42 | </span> | 63 | </span> |
616 | 43 | </div> | 64 | </div> |
617 | 44 | </tal:reviewer> | 65 | </tal:reviewer> |
618 | 66 | </tal:me> | ||
619 | 45 | 67 | ||
620 | 68 | <tal:me condition="view/person_includes_me"> | ||
621 | 46 | <tal:translator condition="view/person_is_translator"> | 69 | <tal:translator condition="view/person_is_translator"> |
623 | 47 | <div id="translations-to-complete-section" style="max-width:800px"> | 70 | <div id="translations-to-complete-section" class="portlet"> |
624 | 48 | <h2>Translations you can help complete</h2> | 71 | <h2>Translations you can help complete</h2> |
625 | 49 | <metal:translations-to-complete | 72 | <metal:translations-to-complete |
626 | 50 | tal:replace="structure context/@@+translations-to-complete-table" /> | 73 | tal:replace="structure context/@@+translations-to-complete-table" /> |
627 | @@ -52,87 +75,40 @@ | |||
628 | 52 | </tal:translator> | 75 | </tal:translator> |
629 | 53 | </tal:me> | 76 | </tal:me> |
630 | 54 | 77 | ||
699 | 55 | 78 | <tal:block tal:define="activities view/recent_activity"> | |
700 | 56 | <h2 id="translation-history-header">Applications and packages translated</h2> | 79 | <tal:block condition="activities"> |
701 | 57 | 80 | <div class="portlet"> | |
702 | 58 | <tal:block define="history view/batchnav/currentBatch"> | 81 | <h2>Activity</h2> |
703 | 59 | 82 | <p> | |
704 | 60 | <tal:block condition="history"> | 83 | These are the translations that |
705 | 61 | 84 | <tal:name replace="context/displayname">Foo Bar</tal:name> | |
706 | 62 | <div class="lesser" id="top-navigation"> | 85 | last worked on: |
707 | 63 | <tal:navigation content="structure view/batchnav/@@+navigation-links-upper" /> | 86 | </p> |
708 | 64 | </div> | 87 | <table class="summary"> |
709 | 65 | 88 | <tr tal:repeat="activity activities"> | |
710 | 66 | <table class="listing" style="max-width:800px"> | 89 | <td tal:attributes="title activity/date/fmt:datetime" |
711 | 67 | <thead> | 90 | tal:content="activity/date/fmt:approximatedate"> |
712 | 68 | <tr> | 91 | 2009-08-15 |
713 | 69 | <th>Translation file</th> | 92 | </td> |
714 | 70 | <th>Untranslated</th> | 93 | <td> |
715 | 71 | <th>Need review</th> | 94 | <a tal:content="activity/title" |
716 | 72 | <th>Latest translation</th> | 95 | tal:attributes="href activity/url">foo bar in package bla</a> |
717 | 73 | </tr> | 96 | </td> |
718 | 74 | </thead> | 97 | </tr> |
719 | 75 | <tbody> | 98 | </table> |
720 | 76 | <tr tal:repeat="record history"> | 99 | <span style="display:block; text-align:right"> |
721 | 77 | <tal:block define="translationmessage record/latest_message"> | 100 | <a href="+activity">See all</a> |
722 | 78 | <td><a tal:content="record/pofile/title" | 101 | </span> |
723 | 79 | tal:attributes="href string:${record/pofile/fmt:url}/+filter?${view/person_filter_querystring}">foo bar in package bla</a> | 102 | </div> |
656 | 80 | </td> | ||
657 | 81 | <td><a tal:content="record/pofile/untranslatedCount" | ||
658 | 82 | tal:attributes="href string:${record/pofile/fmt:url}/+translate?show=untranslated" | ||
659 | 83 | class="untranslated-count" | ||
660 | 84 | >17</a> | ||
661 | 85 | </td> | ||
662 | 86 | <td><a tal:content="record/pofile/unreviewedCount" | ||
663 | 87 | tal:attributes="href string:${record/pofile/fmt:url}/+translate?show=new_suggestions" | ||
664 | 88 | class="unreviewed-count" | ||
665 | 89 | >17</a> | ||
666 | 90 | </td> | ||
667 | 91 | <td style="padding-left: 2em;"> | ||
668 | 92 | <em | ||
669 | 93 | tal:attributes="title record/date_last_touched/fmt:datetime" | ||
670 | 94 | tal:content="record/date_last_touched/fmt:approximatedate" | ||
671 | 95 | style="margin-left: -2em;" /> | ||
672 | 96 | <div tal:content="translationmessage/potmsgset/singular_text" /> | ||
673 | 97 | <div | ||
674 | 98 | tal:condition="python:not(view.should_display_message(translationmessage))"> | ||
675 | 99 | <strong>For privacy reasons this translation is not visible to | ||
676 | 100 | anonymous visitors. To see it, | ||
677 | 101 | <a href="+login">log in</a> first.</strong></div> | ||
678 | 102 | <div | ||
679 | 103 | tal:condition="python:view.should_display_message(translationmessage)"> | ||
680 | 104 | <tal:block | ||
681 | 105 | tal:condition="translationmessage/msgstr0" | ||
682 | 106 | tal:content="translationmessage/msgstr0/translation" /> | ||
683 | 107 | </div> | ||
684 | 108 | </td> | ||
685 | 109 | </tal:block> | ||
686 | 110 | </tr> | ||
687 | 111 | </tbody> | ||
688 | 112 | </table> | ||
689 | 113 | |||
690 | 114 | <div class="lesser"> | ||
691 | 115 | <tal:navigation content="structure view/batchnav/@@+navigation-links-lower" /> | ||
692 | 116 | </div> | ||
693 | 117 | |||
694 | 118 | </tal:block> | ||
695 | 119 | |||
696 | 120 | <tal:block condition="not: history"> | ||
697 | 121 | <p><i>No translations recorded from | ||
698 | 122 | <span tal:replace="context/displayname">Foo Bar</span>.</i></p> | ||
724 | 123 | </tal:block> | 103 | </tal:block> |
725 | 124 | </tal:block> | 104 | </tal:block> |
726 | 125 | 105 | ||
729 | 126 | <tal:block condition="view/translation_groups"> | 106 | <div tal:condition="view/translation_groups" class="portlet"> |
728 | 127 | |||
730 | 128 | <h2>Translation Groups</h2> | 107 | <h2>Translation Groups</h2> |
731 | 129 | |||
732 | 130 | <span tal:replace="context/displayname">Mark Shuttleworth</span> is | 108 | <span tal:replace="context/displayname">Mark Shuttleworth</span> is |
733 | 131 | a member of the following translation groups: | 109 | a member of the following translation groups: |
734 | 132 | 110 | ||
738 | 133 | <table class="listing" | 111 | <table class="listing" id="translation-group-memberships"> |
736 | 134 | id="translation-group-memberships" | ||
737 | 135 | style="max-width:800px"> | ||
739 | 136 | <thead> | 112 | <thead> |
740 | 137 | <tr> | 113 | <tr> |
741 | 138 | <th>Translation group</th> | 114 | <th>Translation group</th> |
742 | @@ -158,9 +134,7 @@ | |||
743 | 158 | </tr> | 134 | </tr> |
744 | 159 | </tbody> | 135 | </tbody> |
745 | 160 | </table> | 136 | </table> |
749 | 161 | 137 | </div> | |
747 | 162 | </tal:block> | ||
748 | 163 | |||
750 | 164 | </div> | 138 | </div> |
751 | 165 | </body> | 139 | </body> |
752 | 166 | </html> | 140 | </html> |
= Bug 423705: 3.0 Person Translations page =
This branch converts the Person page in Translations to the 3.0 style.
It also transforms the translation activity (previously "history")
listing on that page into something more like what we drew up in Buenos
Aires (minus the squiggles where the straight lines were supposed to be
:-)
The activity listing no longer floods the page with your complete
translation history; the full list has moved to a new "activity" page.
The person page now only shows the latest 10 entries.
What you see on the new page is a bit more detailed than the short list,
but also less detailed than what the existing Person page shows. The
reason is that it originally had a mixed bag of purposes, including
helping people reach the translations they've been working on. But for
that we now have the "translations you need to review" and "translations
you can help complete" listings.
I tried to get a two-column layout working for this page, but couldn't
because the elements on the page are much too variable. Each of the
portlets is conditional, all with different conditions. No static
layout is going to make that work well for even a reasonable number of
cases.
== Test ==
Best to run all Translations stories, as I did, but in particular:
{{{
./bin/test -vv -t xx-person-activity
}}}
== Demo and Q/A ==
For a nicely filled example, go to Carlos' home page:
https:/ /translations. launchpad. dev/~carlos
It gets better if you look at the same page but logged in as Carlos
(<email address hidden> / test).
From there, click on the "See all" link on the right, at the bottom of
the activity list. That takes you to the new, batched full activity
listing.
Also look at an empty page:
https:/ /translations. launchpad. dev/~salgado
And finally, there's the warning if you haven't set your preferred
languages. Log in as Brad (<email address hidden> / test) and visit Brad's
Translations page:
https:/ /translations. launchpad. dev/~bac
The "Please set them now" link will take you to the settings page where
you can select preferred languages.
== Lint ==
{{{
Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.
Linting changed files: /launchpad/ pagetitles. py /launchpad/ webapp/ configure. zcml /launchpad/ webapp/ tales.py translations/ browser/ configure. zcml translations/ browser/ person. py translations/ stories/ standalone/ xx-person- activity. txt translations/ templates/ person- navlinks. pt translations/ templates/ person- translation- activity. pt translations/ templates/ person- translations- to-complete- table.pt translations/ templates/ person- translations- to-review- table.pt translations/ templates/ person- translations. pt
lib/canonical
lib/canonical
lib/canonical
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
=== Pylint notices ===
lib/canonical/ launchpad/ webapp/ tales.py
21: [F0401] Unable to import 'lazr.enum' (No module named enum)
}}}
I'm not planning to do anything about that last one.
Jeroen