Merge lp:~henninge/launchpad/devel-bugjamming-2 into lp:launchpad

Proposed by Henning Eggers on 2010-12-23
Status: Merged
Approved by: Henning Eggers on 2010-12-23
Approved revision: no longer in the source branch.
Merged at revision: 12148
Proposed branch: lp:~henninge/launchpad/devel-bugjamming-2
Merge into: lp:launchpad
Diff against target: 327 lines (+95/-31)
8 files modified
lib/lp/translations/browser/person.py (+4/-0)
lib/lp/translations/browser/tests/test_persontranslationview.py (+45/-11)
lib/lp/translations/browser/translationmessage.py (+11/-5)
lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt (+21/-8)
lib/lp/translations/stories/standalone/xx-translations-to-review.txt (+2/-2)
lib/lp/translations/templates/person-translations-to-complete-table.pt (+4/-2)
lib/lp/translations/templates/person-translations-to-review-table.pt (+4/-2)
lib/lp/translations/templates/person-translations-to-review.pt (+4/-1)
To merge this branch: bzr merge lp:~henninge/launchpad/devel-bugjamming-2
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve on 2010-12-23
j.c.sackett (community) code* 2010-12-23 Approve on 2010-12-23
Curtis Hovey (community) ui 2010-12-23 Approve on 2010-12-23
Review via email: mp+44590@code.launchpad.net

Commit Message

[r=bac,jcsackett][ui=sinzui][bug=440406,560701] Help with alternate language usage. List languages on a persons translation dashboard.

Description of the Change

= Summary =

Fixes two bugs:

Bug 560701: "Not showing suggestions from selected alternative
language" warning should link to edit languages page

Bug 440406: Translations overview should state language code

== Proposed fix ==

Add a link to the user's +editlanguages page to the message.

List languages in person translation tables. The languages can be
extracted from the list of pofiles that is covered by the given
statistic.

== Pre-implementation notes ==

Trivial, no pre-imp.

== Implementation details ==

Pretty straightforward, not much to explain.

The _makePOFiles helper method in test_persontranslationview had to
be adapted to create files for multiple languages but in the same
POTemplate, so they can get aggretated into one.

In that file I also removed the references to the hard-coded language
(Dutch) and used generic languages, which is possible nowadays.

== Tests ==

bin/test -vvcm lp.translations \
  -t xx-pofile-translate-alternative-language \
  -t test_getTargetsForTranslation \
  -t xx-translations-to-review

== Demo and Q/A ==

For bug 560701:
Go to the page listed in the bug and verify that the message
contains a link to +editlanguages.

For bug 440406:
Got to https://translations.launchpad.net/people/+me and verify that
the languages are listed on each line on the table.

= Launchpad lint =

I removed some lint. Yeah!

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/translations/browser/tests/test_persontranslationview.py
  lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt
  lib/lp/translations/templates/person-translations-to-complete-table.pt
  lib/lp/translations/templates/person-translations-to-review.pt
  lib/lp/translations/browser/translationmessage.py
  lib/lp/translations/templates/person-translations-to-review-table.pt
  lib/lp/translations/browser/person.py

./lib/lp/translations/browser/translationmessage.py
     337: E301 expected 1 blank line, found 2
     365: E301 expected 1 blank line, found 2
     509: E301 expected 1 blank line, found 2
     744: E301 expected 1 blank line, found 2
     827: E301 expected 1 blank line, found 2
    1357: E301 expected 1 blank line, found 2
./lib/lp/translations/browser/person.py
     363: E202 whitespace before ']'

To post a comment you must log in.
Curtis Hovey (sinzui) wrote :

Thanks.

review: Approve (ui)
j.c.sackett (jcsackett) wrote :

Henninge--

This all looks good to me.

I do think the language shown to the user (which existed prior to this branch) is a little clunky. Maybe get Revell to take a look?

review: Approve (code*)
Brad Crittenden (bac) wrote :

Looks good Henning.

When sorting a set you do not need to call list() first.

Otherwise it looks good.

review: Approve (code)
Henning Eggers (henninge) wrote :

Thanks for the reviews. I agree that the page could possibly look and "sound" better but I am too tired to do anything about it now...
I removed the superfluous list().

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/translations/browser/person.py'
2--- lib/lp/translations/browser/person.py 2010-11-23 23:22:27 +0000
3+++ lib/lp/translations/browser/person.py 2010-12-24 13:33:43 +0000
4@@ -67,6 +67,9 @@
5 """See `TranslationLinksAggregator.describe`."""
6 strings_count = sum(
7 [self.countStrings(pofile) for pofile in covered_files])
8+ languages = set(
9+ [pofile.language.englishname for pofile in covered_files])
10+ languages_list = ", ".join(sorted(languages))
11
12 if strings_count == 1:
13 strings_wording = "%d string"
14@@ -79,6 +82,7 @@
15 'count_wording': strings_wording % strings_count,
16 'is_product': not ISourcePackage.providedBy(target),
17 'link': link,
18+ 'languages': languages_list,
19 }
20
21
22
23=== modified file 'lib/lp/translations/browser/tests/test_persontranslationview.py'
24--- lib/lp/translations/browser/tests/test_persontranslationview.py 2010-10-04 19:50:45 +0000
25+++ lib/lp/translations/browser/tests/test_persontranslationview.py 2010-12-24 13:33:43 +0000
26@@ -10,7 +10,6 @@
27 from canonical.launchpad.webapp import canonical_url
28 from canonical.launchpad.webapp.servers import LaunchpadTestRequest
29 from canonical.testing.layers import LaunchpadZopelessLayer
30-from lp.services.worlddata.model.language import LanguageSet
31 from lp.testing import TestCaseWithFactory
32 from lp.translations.browser.person import PersonTranslationView
33 from lp.translations.model.translator import TranslatorSet
34@@ -26,38 +25,52 @@
35 person = removeSecurityProxy(self.factory.makePerson())
36 self.view = PersonTranslationView(person, LaunchpadTestRequest())
37 self.translationgroup = None
38- self.dutch = LanguageSet().getLanguageByCode('nl')
39- self.view.context.addLanguage(self.dutch)
40+ self.language = self.factory.makeLanguage()
41+ self.view.context.addLanguage(self.language)
42
43 def _makeReviewer(self):
44- """Set up the person we're looking at as a Dutch reviewer."""
45+ """Set up the person we're looking at as a reviewer."""
46 owner = self.factory.makePerson()
47 self.translationgroup = self.factory.makeTranslationGroup(owner=owner)
48 TranslatorSet().new(
49- translationgroup=self.translationgroup, language=self.dutch,
50+ translationgroup=self.translationgroup, language=self.language,
51 translator=self.view.context)
52
53- def _makePOFiles(self, count, previously_worked_on):
54+ def _makePOFiles(self, count, previously_worked_on, languages=None):
55 """Create `count` `POFile`s that the view's person can review.
56
57 :param count: Number of POFiles to create.
58 :param previously_worked_on: Whether these should be POFiles
59 that the person has already worked on.
60+ :param languages: List of languages for each pofile. The length of
61+ the list must be the same as count. If None, all files will be
62+ created with self.language. Also, if languages is not None,
63+ all files will be created for the same template.
64 """
65 pofiles = []
66+ if languages is not None:
67+ potemplate = self.factory.makePOTemplate()
68 for counter in xrange(count):
69- pofile = self.factory.makePOFile(language_code='nl')
70+ if languages is None:
71+ pofile = self.factory.makePOFile(language=self.language)
72+ else:
73+ pofile = self.factory.makePOFile(
74+ potemplate=potemplate, language=languages[counter])
75
76 if self.translationgroup:
77 product = pofile.potemplate.productseries.product
78 product.translationgroup = self.translationgroup
79
80 if previously_worked_on:
81+ if languages is not None:
82+ sequence = counter+1
83+ else:
84+ sequence = 1
85 potmsgset = self.factory.makePOTMsgSet(
86- potemplate=pofile.potemplate, singular='x', sequence=1)
87+ potemplate=pofile.potemplate, sequence=sequence)
88 self.factory.makeTranslationMessage(
89 potmsgset=potmsgset, pofile=pofile,
90- translator=self.view.context, translations=['y'])
91+ translator=self.view.context)
92
93 removeSecurityProxy(pofile).unreviewed_count = 1
94 pofiles.append(pofile)
95@@ -210,11 +223,12 @@
96
97 self.assertTrue(self.view.person_is_translator)
98
99- def test_getTargetsForTranslation(self):
100+ def test_getTargetsForTranslation_nothing(self):
101 # If there's nothing to translate, _getTargetsForTranslation
102 # returns nothing.
103 self.assertEqual([], self.view._getTargetsForTranslation())
104
105+ def test_getTargetsForTranslation(self):
106 # If there's a translation that this person has worked on and
107 # is not a reviewer for, and it has untranslated strings, it
108 # shows up in _getTargetsForTranslation.
109@@ -228,6 +242,26 @@
110 description = descriptions[0]
111 self.assertEqual(product, description['target'])
112 self.assertTrue(description['link'].startswith(canonical_url(pofile)))
113+ self.assertEqual(
114+ pofile.language.englishname, description['languages'])
115+
116+ def test_getTargetsForTranslation_multiple_languages(self):
117+ # Translations in different languages are aggregated to one target
118+ # but the language names are listed.
119+ other_language = self.factory.makeLanguage()
120+ self.view.context.addLanguage(other_language)
121+ pofiles = self._makePOFiles(
122+ 2, previously_worked_on=True,
123+ languages=[self.language, other_language])
124+ for pofile in pofiles:
125+ self._addUntranslatedMessages(pofile, 1)
126+
127+ descriptions = self.view._getTargetsForTranslation()
128+ self.assertEqual(1, len(descriptions))
129+ description = descriptions[0]
130+ expected_languages = ', '.join(sorted([
131+ self.language.englishname, other_language.englishname]))
132+ self.assertContentEqual(expected_languages, description['languages'])
133
134 def test_getTargetsForTranslation_max_fetch(self):
135 # The max_fetch parameter limits how many POFiles are considered
136@@ -360,7 +394,7 @@
137
138 # But the answer is True if the person has no preferred
139 # languages.
140- self.view.context.removeLanguage(self.dutch)
141+ self.view.context.removeLanguage(self.language)
142 self.assertTrue(self.view.requires_preferred_languages)
143
144
145
146=== modified file 'lib/lp/translations/browser/translationmessage.py'
147--- lib/lp/translations/browser/translationmessage.py 2010-12-01 11:26:57 +0000
148+++ lib/lp/translations/browser/translationmessage.py 2010-12-24 13:33:43 +0000
149@@ -551,12 +551,18 @@
150 translations_person = ITranslationsPerson(user)
151 choices = set(translations_person.translatable_languages)
152 if choices and alternative_language not in choices:
153- self.request.response.addInfoNotification(
154+ editlanguages_url = canonical_url(
155+ self.user, view_name="+editlanguages")
156+ self.request.response.addInfoNotification(structured(
157 u"Not showing suggestions from selected alternative "
158- "language %s. If you wish to see suggestions from "
159- "this language, add it to your preferred languages "
160- "first."
161- % alternative_language.displayname)
162+ "language %(alternative)s. If you wish to see "
163+ "suggestions from this language, "
164+ '<a href="%(editlanguages_url)s">'
165+ "add it to your preferred languages</a> first."
166+ % dict(
167+ alternative=alternative_language.displayname,
168+ editlanguages_url=editlanguages_url,
169+ )))
170 alternative_language = None
171 second_lang_code = None
172
173
174=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt'
175--- lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt 2010-12-01 11:26:57 +0000
176+++ lib/lp/translations/stories/standalone/xx-pofile-translate-alternative-language.txt 2010-12-24 13:33:43 +0000
177@@ -1,4 +1,5 @@
178-= PO file alternative language selection =
179+PO file alternative language selection
180+======================================
181
182 The translation forms allow the user to select an alternative language. The
183 form will suggest translations from this alternative language as well as those
184@@ -70,7 +71,8 @@
185 ['']
186
187
188-=== Suggestions ===
189+Suggestions
190+-----------
191
192 Carlos also visits the Catalan equivalent of the same translation page, using
193 Spanish as an alternative language.
194@@ -104,7 +106,9 @@
195 Japanese (ja).
196
197 >>> browser.open(translate_page +
198- ... "?field.alternative_language=ja&field.alternative_language-empty-marker=1&select_alternate_language=Change")
199+ ... "?field.alternative_language=ja"
200+ ... "&field.alternative_language-empty-marker=1"
201+ ... "&select_alternate_language=Change")
202
203 This leads to a subtle technical problem as the alternative-language dropdown
204 would have to be initialized to a language that wasn't in its list of items.
205@@ -113,11 +117,16 @@
206 first.
207
208 >>> for message in get_feedback_messages(browser.contents):
209- ... print message
210+ ... print extract_text(message)
211 Not showing suggestions from selected alternative language Japanese (ja).
212 If you wish to see suggestions from this language, add it to your
213 preferred languages first.
214
215+It even presents a link to where the user can set the preferred languages.
216+
217+ >>> print browser.getLink("add it to your preferred languages").url
218+ http...~carlos/+editlanguages
219+
220 This distinction between alternative languages from the user's preferred set
221 and other alternative languages does not exist, of course, if no preferred
222 languages are defined. Suggestions just work for anonymous users.
223@@ -140,7 +149,8 @@
224 ...
225
226
227-== Filtering & Navigation ==
228+Filtering & Navigation
229+----------------------
230
231 The translate page also allows the user to filter the translatable strings to
232 show only the strings he is interested in.
233@@ -176,7 +186,8 @@
234 11 ... 15 of 15 results ...
235
236
237-== Language variants and alternative language ==
238+Language variants and alternative language
239+------------------------------------------
240
241 The language for the suggestions will be selected automatically when it
242 is not submitted by the user. If the language variant is not available
243@@ -215,7 +226,8 @@
244 ['(no value)']
245
246
247-== There is only one alternative language at a time ==
248+There is only one alternative language at a time
249+------------------------------------------------
250
251 If a user specifies more than one alternative language in the URL, he
252 gets an UnexpectedFormData exception:
253@@ -229,7 +241,8 @@
254 UnexpectedFormData: You specified...
255
256
257-== Requests for a non-translatable alternative language ==
258+Requests for a non-translatable alternative language
259+----------------------------------------------------
260
261 There are older URLs that contain non-translatable languages such as
262 English, or a non-visible language. Two example requests in OOPSes
263
264=== modified file 'lib/lp/translations/stories/standalone/xx-translations-to-review.txt'
265--- lib/lp/translations/stories/standalone/xx-translations-to-review.txt 2009-08-31 13:04:32 +0000
266+++ lib/lp/translations/stories/standalone/xx-translations-to-review.txt 2010-12-24 13:33:43 +0000
267@@ -90,8 +90,8 @@
268
269 >>> browser.open(homepage)
270 >>> list_reviewables(browser)
271- <a ...>...</a> needs <a ...> 1 string reviewed </a>
272- <a ...>...</a> needs <a ...> 1 string reviewed </a>
273+ <a ...>...</a> needs <a ...> 1 string reviewed </a> in Khmer
274+ <a ...>...</a> needs <a ...> 1 string reviewed </a> in Khmer
275 Listing contains 2 translation(s).
276
277 These are translations that xowxz has not worked on. They are not ones
278
279=== modified file 'lib/lp/translations/templates/person-translations-to-complete-table.pt'
280--- lib/lp/translations/templates/person-translations-to-complete-table.pt 2009-09-09 09:51:14 +0000
281+++ lib/lp/translations/templates/person-translations-to-complete-table.pt 2010-12-24 13:33:43 +0000
282@@ -26,8 +26,10 @@
283 <tal:stringcount replace="target_info/count_wording">
284 1 string
285 </tal:stringcount>
286- translated
287- </a>
288+ translated </a> in
289+ <tal:languages replace="target_info/languages">
290+ Spanish
291+ </tal:languages>
292 </td>
293 </tr>
294 </table>
295
296=== modified file 'lib/lp/translations/templates/person-translations-to-review-table.pt'
297--- lib/lp/translations/templates/person-translations-to-review-table.pt 2009-09-09 09:51:14 +0000
298+++ lib/lp/translations/templates/person-translations-to-review-table.pt 2010-12-24 13:33:43 +0000
299@@ -26,8 +26,10 @@
300 <tal:stringcount replace="target_info/count_wording">
301 1 string
302 </tal:stringcount>
303- reviewed
304- </a>
305+ reviewed </a> in
306+ <tal:languages replace="target_info/languages">
307+ Spanish
308+ </tal:languages>
309 </td>
310 </tr>
311 </table>
312
313=== modified file 'lib/lp/translations/templates/person-translations-to-review.pt'
314--- lib/lp/translations/templates/person-translations-to-review.pt 2009-09-17 20:11:48 +0000
315+++ lib/lp/translations/templates/person-translations-to-review.pt 2010-12-24 13:33:43 +0000
316@@ -39,7 +39,10 @@
317 1 string
318 </tal:stringcount>
319 reviewed
320- </a>
321+ </a> in
322+ <tal:languages replace="target_info/languages">
323+ Spanish
324+ </tal:languages>
325 </td>
326 </tr>
327 </table>