~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
Language Views
==============

Admin Language
--------------

    >>> from zope.component import getUtility
    >>> from lp.services.worlddata.interfaces.language import ILanguageSet
    >>> from lp.translations.publisher import TranslationsLayer

    >>> language_set = getUtility(ILanguageSet)
    >>> portuguese = language_set.getLanguageByCode('pt_BR')
    >>> language_admin_view = create_view(
    ...     portuguese, '+admin', layer=TranslationsLayer)
    >>> language_admin_view.initialize()

The language +admin view provides a label and a page_title for the page.

    >>> print language_admin_view.label
    Edit Portuguese (Brazil) in Launchpad

    >>> print language_admin_view.page_title
    Change details

The view provides also a cancel_url and a next_url, but they're the same
because the previous and next steps of editing a language are returning
to its index.

    >>> print language_admin_view.cancel_url
    http://translations.launchpad.dev/+languages/pt_BR

    >>> print language_admin_view.next_url
    http://translations.launchpad.dev/+languages/pt_BR


Validation
----------

Plural information entered on the admin page is checked for validity.

    >>> language_admin_view.validate({
    ...     'code': 'pt_BR',
    ...     'pluralforms': 2,
    ...     'pluralexpression': '1/n',
    ...     })
    >>> print language_admin_view.getFieldError('pluralexpression')
    Division by zero in plural expression for n = 0.


Add Language
------------

    >>> language_add_view = create_view(language_set, '+add',
    ...     layer=TranslationsLayer)

    >>> print language_add_view.label
    Register a language in Launchpad

    >>> print language_add_view.page_title
    Register a language

The view provides also a cancel_url and a next_url:

    >>> print language_add_view.cancel_url
    http://translations.launchpad.dev/+languages

    >>> print language_add_view.field_names
    ['code', 'englishname', 'nativename', 'pluralforms',
    'pluralexpression', 'visible', 'direction']

    >>> login("admin@canonical.com")
    >>> form = {
    ...     'field.code': 'lp_US',
    ...     'field.englishname': 'Launchpad English',
    ...     'field.nativename': '',
    ...     'field.pluralforms': '',
    ...     'field.pluralexpression': '',
    ...     'field.visible': True,
    ...     'field.direction': 'LTR',
    ...     'field.actions.add': 'Add',
    ...     }

    >>> language_add_view = create_initialized_view(
    ...     language_set, '+add', form=form,
    ...     layer=TranslationsLayer)
    >>> language_add_view.errors
    []

    >>> print language_add_view.next_url
    http://translations.launchpad.dev/+languages/lp_US


View Language
-------------

Translators lists for each language are computed using KarmaCache tables for
users which have configured their prefered language. Since KarmaCache tables
are generated using nightly builds, we will change Langauge.translators to
use the list of translators generated by this test.

Language.translators is deleted so that we can add our custom
implementation later.

    >>> from lp.services.worlddata.model.language import Language
    >>> translators_method = Language.translators
    >>> del Language.translators
    >>> serbian = language_set.getLanguageByCode('sr')
    >>> language_view = create_initialized_view(serbian, '+index',
    ...     layer=TranslationsLayer)

The 'friendly_plural_forms' function shows us a list of plural forms and
a set of examples for each one, so one won't need to understand the plural
formula expression to see how it works.

    >>> friendly_plural_forms = language_view.friendly_plural_forms

    >>> for form_dict in friendly_plural_forms:
    ...     print form_dict['form'], ':', form_dict['examples']
    0 : 1, 21, 31, 41, 51, 61...
    1 : 2, 3, 4, 22, 23, 24...
    2 : 0, 5, 6, 7, 8, 9...

The top contributors are listed on the language page, and for a merged account
we will see their targed account.

Create some translators and a merged account.

    >>> from zope.security.proxy import removeSecurityProxy
    >>> translators = []
    >>> translator_main = factory.makePerson(
    ...     name='translator-main',
    ...     displayname='Translator Main')
    >>> translators.append(translator_main)
    >>> translator_merged = removeSecurityProxy(factory.makePerson(
    ...     name='translator-merged',
    ...     displayname='Translator Merged'))
    >>> translators.append(translator_merged)
    >>> translator_merged.merged = translator_main
    >>> for translator_nr in range(22):
    ...     translators.append(factory.makePerson(
    ...         name='translator-' + str(translator_nr),
    ...         displayname='Translator No.' + str(translator_nr)))

Create a product, a template with one msgset and a pofile

    >>> from lp.app.enums import ServiceUsage

    >>> product = factory.makeProduct(
    ...     translations_usage=ServiceUsage.LAUNCHPAD)
    >>> template = factory.makePOTemplate(
    ...     productseries=product.getSeries('trunk'))
    >>> potmsgset = factory.makePOTMsgSet(template)
    >>> pofile = factory.makePOFile('sr', potemplate=template)

Add a translation for each translator and one more for main and merged
accounts.

    >>> for translator in translators:
    ...     translation = factory.makeCurrentTranslationMessage(
    ...         pofile=pofile, translator=translator, potmsgset=potmsgset)
    >>> translation = factory.makeCurrentTranslationMessage(
    ...     pofile=pofile, translator=translator_merged, potmsgset=potmsgset)
    >>> translation = factory.makeCurrentTranslationMessage(
    ...     pofile=pofile, translator=translator_main, potmsgset=potmsgset)

Langauge.translators is Monkey-patched to avoid fetching KarmaCache.
Language.translator is a list containing all contributors decreasingly sorted
according to their karma value.

    >>> serbian.translators = translators
    >>> language_view = create_initialized_view(serbian, '+index',
    ...     layer=TranslationsLayer)
    >>> top_contributors = language_view.top_contributors
    >>> translator_main in top_contributors
    True
    >>> translator_merged in top_contributors
    False
    >>> for translator in top_contributors:
    ...     print translator.name
    translator-main
    translator-0
    translator-1
    translator-2 ...

In the end, the changes done to Language class are reverted.

    >>> Language.translators = translators_method


View LanguageSet
------------------

    >>> login('carlos@canonical.com')
    >>> languageset_view = create_initialized_view(language_set, '+index',
    ...     layer=TranslationsLayer)

The user_languages property contains a list of the current user's preferred
languages formated as links.

    >>> print languageset_view.user_languages
    <a href=".../ca" ...>Catalan</a>,
    <a href=".../en" ...>English</a>,
    <a href=".../es" ...>Spanish</a>

For a user without any preferred languages, English will be returned.

    >>> person = factory.makePerson()
    >>> print person.languages
    []
    >>> login_person(person)
    >>> languageset_view = create_initialized_view(language_set, '+index',
    ...     layer=TranslationsLayer)
    >>> print languageset_view.user_languages
    <a href=".../en" ...>English</a>