~launchpad-pqm/launchpad/devel

11666.3.7 by Curtis Hovey
Hushed lint.
1
POFile
2
======
1891 by Canonical.com Patch Queue Manager
[trivial] Fixed bug #838 + test added
3
4
Get evolution template for Ubuntu Hoary
5
4335.1.74 by Carlos Perello Marin
Applied more review comments
6
    >>> import datetime
7
    >>> import pytz
8
    >>> from zope.component import getUtility
5126.2.7 by Francis J. Lacoste
Use verifyObject from webapp.testing.
9
    >>> from canonical.launchpad.webapp.testing import verifyObject
11716.1.12 by Curtis Hovey
Sorted imports in doctests.
10
    >>> from lp.registry.interfaces.distribution import IDistributionSet
11
    >>> from lp.registry.interfaces.person import IPersonSet
10409.5.2 by Curtis Hovey
Removed glob imports from translations.
12
    >>> from lp.services.worlddata.interfaces.language import ILanguageSet
13
    >>> from lp.registry.interfaces.sourcepackagename import (
8751.1.10 by Danilo Šegan
Remove dependency on glob imports from most of the stuff.
14
    ...     ISourcePackageNameSet)
15
    >>> from lp.translations.interfaces.pofile import IPOFile
16
    >>> from lp.translations.interfaces.potemplate import IPOTemplateSet
4335.1.74 by Carlos Perello Marin
Applied more review comments
17
    >>> sourcepackagenameset = getUtility(ISourcePackageNameSet)
18
    >>> sourcepackagename = sourcepackagenameset['evolution']
19
    >>> distributionset = getUtility(IDistributionSet)
20
    >>> distribution = distributionset['ubuntu']
21
    >>> series = distribution['hoary']
22
    >>> potemplateset = getUtility(IPOTemplateSet)
23
    >>> potemplatesubset = potemplateset.getSubset(
24
    ...     distroseries=series, sourcepackagename=sourcepackagename)
25
    >>> potemplate = potemplatesubset['evolution-2.2']
26
    >>> UTC = pytz.timezone('UTC')
1891 by Canonical.com Patch Queue Manager
[trivial] Fixed bug #838 + test added
27
28
Get Xhosa translation
29
4335.1.74 by Carlos Perello Marin
Applied more review comments
30
    >>> pofile = potemplate.getPOFileByLang('xh')
11196.4.1 by Danilo Šegan
Change getDummyPOFile to accept actual language as the parameter instead of language code.
31
    >>> language_pt_BR = getUtility(
32
    ...     ILanguageSet).getLanguageByCode('pt_BR')
33
    >>> dummy_pofile = potemplate.getDummyPOFile(language_pt_BR)
3997.5.4 by Carlos Perello Marin
Applied review comments
34
35
Both implement the IPOFile interface:
36
4335.1.74 by Carlos Perello Marin
Applied more review comments
37
    >>> verifyObject(IPOFile, pofile)
38
    True
3997.5.4 by Carlos Perello Marin
Applied review comments
39
4335.1.74 by Carlos Perello Marin
Applied more review comments
40
    >>> verifyObject(IPOFile, dummy_pofile)
41
    True
1891 by Canonical.com Patch Queue Manager
[trivial] Fixed bug #838 + test added
42
4230.4.4 by Danilo Šegan
Return empty SelectResults on DummyPOFile methods, updated pagetest, removed IPOFile.changedInLaunchpadCount method, improved doctest.
43
DummyPOFile returns empty SelectResults for getPOTMsgSet* methods,
44
except for untranslated messages.
45
4335.1.74 by Carlos Perello Marin
Applied more review comments
46
    >>> dummy_pofile.getPOTMsgSetTranslated().count()
47
    0
11666.3.7 by Curtis Hovey
Hushed lint.
48
7675.1003.4 by Henning Eggers
Renamed getPOTMsgSetChangedInUbuntu to getPOTMsgSetDifferentTranslations.
49
    >>> dummy_pofile.getPOTMsgSetDifferentTranslations().count()
4335.1.74 by Carlos Perello Marin
Applied more review comments
50
    0
11666.3.7 by Curtis Hovey
Hushed lint.
51
4335.1.74 by Carlos Perello Marin
Applied more review comments
52
    >>> dummy_pofile.getPOTMsgSetWithNewSuggestions().count()
53
    0
11666.3.7 by Curtis Hovey
Hushed lint.
54
4335.1.74 by Carlos Perello Marin
Applied more review comments
55
    >>> dummy_pofile.getPOTMsgSetUntranslated().count()
5106.2.67 by Carlos Perello Marin
Fixed more tests, in concrete, deprecation of messages from imported sources
56
    22
4230.4.4 by Danilo Šegan
Return empty SelectResults on DummyPOFile methods, updated pagetest, removed IPOFile.changedInLaunchpadCount method, improved doctest.
57
1891 by Canonical.com Patch Queue Manager
[trivial] Fixed bug #838 + test added
58
Get the set of POTMsgSets that are untranslated.
59
4335.1.74 by Carlos Perello Marin
Applied more review comments
60
    >>> potmsgsets = list(pofile.getPOTMsgSetUntranslated())
61
    >>> len(potmsgsets)
62
    22
1891 by Canonical.com Patch Queue Manager
[trivial] Fixed bug #838 + test added
63
64
Get Spanish translation
65
4335.1.74 by Carlos Perello Marin
Applied more review comments
66
    >>> pofile = potemplate.getPOFileByLang('es')
1891 by Canonical.com Patch Queue Manager
[trivial] Fixed bug #838 + test added
67
68
Get the set of POTMsgSets that are untranslated.
69
4335.1.74 by Carlos Perello Marin
Applied more review comments
70
    >>> potmsgsets = list(pofile.getPOTMsgSetUntranslated())
71
    >>> len(potmsgsets)
6891.2.1 by Danilo Šegan
Exports and remaining test updates for fuzzy flag removal.
72
    15
4335.1.74 by Carlos Perello Marin
Applied more review comments
73
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
74
We need a helper method to better display test results.
75
14097.2.2 by Danilo Segan
Apply the fixes from old Jeroen's branch.
76
    >>> def print_potmsgsets(potmsgsets, pofile):
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
77
    ...     for potmsgset in potmsgsets:
78
    ...         singular = plural = None
79
    ...         translation = ""
80
    ...         if potmsgset.singular_text:
81
    ...             singular = potmsgset.singular_text
5956.8.7 by Danilo Šegan
Implement comments from Tom.
82
    ...             if len(singular) > 20:
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
83
    ...                singular = singular[:17] + "..."
84
    ...         if potmsgset.plural_text:
85
    ...             plural = potmsgset.plural_text
5956.8.7 by Danilo Šegan
Implement comments from Tom.
86
    ...             if len(plural) > 20:
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
87
    ...                plural = plural[:17] + "..."
88
    ...         if pofile is not None:
14097.2.4 by Danilo Segan
Fix the failing test.
89
    ...             message = potmsgset.getCurrentTranslation(
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
90
    ...                 pofile.potemplate, pofile.language,
14097.2.4 by Danilo Segan
Fix the failing test.
91
    ...                 pofile.potemplate.translation_side)
92
    ...             if message is not None:
93
    ...                translation = message.translations[0]
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
94
    ...             if len(translation) > 20:
95
    ...                 translation = translation[:17] + "..."
96
    ...         print "%2d. %-20s   %-20s   %-20s" % (
14097.2.3 by Danilo Segan
More removals of potmsgset.sequence use.
97
    ...             potmsgset.getSequence(pofile.potemplate),
98
    ...             singular, plural, translation)
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
99
100
11666.3.7 by Curtis Hovey
Hushed lint.
101
getFullLanguageCode
102
-------------------
7675.190.6 by Jeroen Vermeulen
Review change: test new Language methods.
103
11122.3.4 by Danilo Šegan
Get rid of the remaining variant usage.
104
Returns the complete code for this POFile's language.
7675.190.6 by Jeroen Vermeulen
Review change: test new Language methods.
105
7675.190.7 by Jeroen Vermeulen
Fixed test setup.
106
    >>> print potemplate.getPOFileByLang('es').getFullLanguageCode()
107
    es
7675.190.6 by Jeroen Vermeulen
Review change: test new Language methods.
108
11122.3.10 by Danilo Šegan
Fix the mv_pofiletranslator trigger and a few tests.
109
    >>> sr_latin = factory.makeLanguage('sr@latin', 'Serbian Latin')
11122.3.19 by Danilo Segan
More test fixes.
110
    >>> print potemplate.getDummyPOFile(sr_latin).getFullLanguageCode()
11122.3.4 by Danilo Šegan
Get rid of the remaining variant usage.
111
    sr@latin
7675.190.6 by Jeroen Vermeulen
Review change: test new Language methods.
112
113
11666.3.7 by Curtis Hovey
Hushed lint.
114
getFullLanguageName
115
-------------------
7675.190.6 by Jeroen Vermeulen
Review change: test new Language methods.
116
11122.3.4 by Danilo Šegan
Get rid of the remaining variant usage.
117
Returns the complete English name for this POFile's language.
7675.190.6 by Jeroen Vermeulen
Review change: test new Language methods.
118
7675.190.7 by Jeroen Vermeulen
Fixed test setup.
119
    >>> print potemplate.getPOFileByLang('es').getFullLanguageName()
120
    Spanish
7675.190.6 by Jeroen Vermeulen
Review change: test new Language methods.
121
11122.3.19 by Danilo Segan
More test fixes.
122
    >>> print potemplate.getDummyPOFile(sr_latin).getFullLanguageName()
11122.3.4 by Danilo Šegan
Get rid of the remaining variant usage.
123
    Serbian Latin
7675.190.6 by Jeroen Vermeulen
Review change: test new Language methods.
124
125
11666.3.7 by Curtis Hovey
Hushed lint.
126
findPOTMsgSetsContaining
127
------------------------
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
128
129
It is common to want to find those POTMsgSets which contain a certain
130
substring in their original English string.
131
5956.8.7 by Danilo Šegan
Implement comments from Tom.
132
    >>> found_potmsgsets = (
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
133
    ...     dummy_pofile.findPOTMsgSetsContaining(u"contact"))
5956.8.7 by Danilo Šegan
Implement comments from Tom.
134
    >>> found_potmsgsets.count()
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
135
    4
11666.3.7 by Curtis Hovey
Hushed lint.
136
14097.2.3 by Danilo Segan
More removals of potmsgset.sequence use.
137
    >>> print_potmsgsets(found_potmsgsets, dummy_pofile)
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
138
     7. contact's header:      None
139
    14. The location and ...   None
140
    15. %d contact             %d contacts
141
    16. Opening %d contac...   Opening %d contac...
142
143
Search is case-insensitive.
144
5956.8.7 by Danilo Šegan
Implement comments from Tom.
145
    >>> found_potmsgsets = (
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
146
    ...     dummy_pofile.findPOTMsgSetsContaining(u"CONTact"))
5956.8.7 by Danilo Šegan
Implement comments from Tom.
147
    >>> found_potmsgsets.count()
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
148
    4
11666.3.7 by Curtis Hovey
Hushed lint.
149
14097.2.3 by Danilo Segan
More removals of potmsgset.sequence use.
150
    >>> print_potmsgsets(found_potmsgsets, dummy_pofile)
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
151
     7. contact's header:      None
152
    14. The location and ...   None
153
    15. %d contact             %d contacts
154
    16. Opening %d contac...   Opening %d contac...
155
156
Search will look through plural msgids as well.
157
5956.8.7 by Danilo Šegan
Implement comments from Tom.
158
    >>> found_potmsgsets = (
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
159
    ...     dummy_pofile.findPOTMsgSetsContaining(u"contacts"))
5956.8.7 by Danilo Šegan
Implement comments from Tom.
160
    >>> found_potmsgsets.count()
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
161
    2
11666.3.7 by Curtis Hovey
Hushed lint.
162
14097.2.3 by Danilo Segan
More removals of potmsgset.sequence use.
163
    >>> print_potmsgsets(found_potmsgsets, dummy_pofile)
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
164
    15. %d contact             %d contacts
165
    16. Opening %d contac...   Opening %d contac...
166
167
Looking for a non-existing string returns an empty SelectResults.
168
5956.8.7 by Danilo Šegan
Implement comments from Tom.
169
    >>> found_potmsgsets = (
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
170
    ...     dummy_pofile.findPOTMsgSetsContaining(u"non-existing-string"))
5956.8.7 by Danilo Šegan
Implement comments from Tom.
171
    >>> found_potmsgsets.count()
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
172
    0
173
174
Trying to find a string shorter than two characters doesn't work.
175
5956.8.7 by Danilo Šegan
Implement comments from Tom.
176
    >>> found_potmsgsets = (
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
177
    ...     dummy_pofile.findPOTMsgSetsContaining(u"a"))
178
    Traceback (most recent call last):
179
    ...
180
    AssertionError: You can not search for strings shorter than 2 characters.
181
182
In a Spanish translation, you will also get matching translations.
183
5956.8.7 by Danilo Šegan
Implement comments from Tom.
184
    >>> found_potmsgsets = (
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
185
    ...     pofile.findPOTMsgSetsContaining(u"ventana"))
5956.8.7 by Danilo Šegan
Implement comments from Tom.
186
    >>> found_potmsgsets.count()
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
187
    1
11666.3.7 by Curtis Hovey
Hushed lint.
188
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
189
    >>> print_potmsgsets(found_potmsgsets, pofile)
190
    16. Opening %d contac...   Opening %d contac...   Abrir %d contacto...
191
192
Searching for translations is case insensitive.
193
5956.8.7 by Danilo Šegan
Implement comments from Tom.
194
    >>> found_potmsgsets = (
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
195
    ...     pofile.findPOTMsgSetsContaining(u"VENTANA"))
5956.8.7 by Danilo Šegan
Implement comments from Tom.
196
    >>> found_potmsgsets.count()
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
197
    1
11666.3.7 by Curtis Hovey
Hushed lint.
198
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
199
    >>> print_potmsgsets(found_potmsgsets, pofile)
200
    16. Opening %d contac...   Opening %d contac...   Abrir %d contacto...
201
6341.3.1 by Danilo Šegan
Implement searching through all plural forms.
202
Searching for plural forms other than the first one also works.
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
203
5956.8.7 by Danilo Šegan
Implement comments from Tom.
204
    >>> found_potmsgsets = (
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
205
    ...     pofile.findPOTMsgSetsContaining(u"estos"))
5956.8.7 by Danilo Šegan
Implement comments from Tom.
206
    >>> found_potmsgsets.count()
6341.3.1 by Danilo Šegan
Implement searching through all plural forms.
207
    1
11666.3.7 by Curtis Hovey
Hushed lint.
208
6341.3.1 by Danilo Šegan
Implement searching through all plural forms.
209
    >>> print_potmsgsets(found_potmsgsets, pofile)
210
    16. Opening %d contac...   Opening %d contac...   Abrir %d contacto...
5956.8.3 by Danilo Šegan
Implement translation search, cleanup, and mpts comments.
211
11666.3.7 by Curtis Hovey
Hushed lint.
212
One can find a message by looking for a suggestion (non-current
213
translation).
5956.8.4 by Danilo Šegan
Add a warning about a string too long, another test for suggestion search.
214
5956.8.7 by Danilo Šegan
Implement comments from Tom.
215
    >>> found_potmsgsets = (
5956.8.4 by Danilo Šegan
Add a warning about a string too long, another test for suggestion search.
216
    ...     pofile.findPOTMsgSetsContaining(u"tarjetas"))
5956.8.7 by Danilo Šegan
Implement comments from Tom.
217
    >>> found_potmsgsets.count()
5956.8.4 by Danilo Šegan
Add a warning about a string too long, another test for suggestion search.
218
    1
11666.3.7 by Curtis Hovey
Hushed lint.
219
5956.8.4 by Danilo Šegan
Add a warning about a string too long, another test for suggestion search.
220
    >>> print_potmsgsets(found_potmsgsets, pofile)
221
     5.  cards                 None                    caratas
1998 by Canonical.com Patch Queue Manager
TranslationValidation implementation for .po imports r=spiv
222
11666.3.7 by Curtis Hovey
Hushed lint.
223
224
path
225
----
5311.2.1 by Jeroen Vermeulen
Make changes to POFile path check for local uniqueness.
226
227
A PO file has a storage path that determines where the file is to be
11666.3.7 by Curtis Hovey
Hushed lint.
228
stored in a filesystem tree (such as an export tarball).  The path ends
229
with the actual file name and should include a language code.
5311.2.1 by Jeroen Vermeulen
Make changes to POFile path check for local uniqueness.
230
231
    >>> pofile_xh = potemplate.getPOFileByLang('xh')
232
    >>> pofile_xh.path
233
    u'xh.po'
234
235
To change this path, use setPathIfUnique().
236
237
    >>> pofile_xh.setPathIfUnique('xh2.po')
238
    >>> pofile_xh.path
239
    u'xh2.po'
240
241
The path must be unique within its distribution series package or
242
product release series, so that a single file system tree can contain
243
all translations found there.
244
245
If the given path is not locally unique, setPathIfUnique() simply does
246
nothing.  There can be no naming conflict in that case because the PO
247
file's existing path is already supposed to be unique.
248
249
Here we try to copy the path of another translation of the same template
250
but the PO file correctly retains its original path.
251
252
    >>> pofile_xh.setPathIfUnique(pofile.path)
253
    >>> pofile_xh.path
254
    u'xh2.po'
255
256
11666.3.7 by Curtis Hovey
Hushed lint.
257
updateHeader()
258
--------------
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
259
11666.3.7 by Curtis Hovey
Hushed lint.
260
This method is used to update the header of the POFile to a newer
261
version.
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
262
263
This is the new header we are going to apply.
264
265
    >>> new_header_string = '''Project-Id-Version: es
266
    ... POT-Creation-Date: 2004-08-18 11:10+0200
267
    ... PO-Revision-Date: 2005-08-18 13:22+0000
7675.1000.1 by Jeroen Vermeulen
More test fixups. Filters still broken.
268
    ... Last-Translator: Carlos Perell\xc3\xb3 Mar\xc3\xadn
269
    ... <carlos@canonical.com>
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
270
    ... Language-Team: Spanish <traductores@es.gnome.org>
271
    ... MIME-Version: 1.0
272
    ... Content-Type: text/plain; charset=UTF-8
273
    ... Content-Transfer-Encoding: 8bit
274
    ... Report-Msgid-Bugs-To: serrador@hispalinux.es'''
275
5084.8.2 by Jeroen Vermeulen
Renamed TranslationFile to TranslationFileData, TranslationHeader to TranslationHeaderData. POFile-to-TranslationFile adapter class changes name accordingly.
276
We can get an ITranslationHeaderData from the file format importer.
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
277
8751.1.10 by Danilo Šegan
Remove dependency on glob imports from most of the stuff.
278
    >>> from lp.translations.interfaces.translationimporter import (
279
    ...     ITranslationImporter)
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
280
    >>> translation_importer = getUtility(ITranslationImporter)
281
    >>> format_importer = translation_importer.getTranslationFormatImporter(
282
    ...     pofile.potemplate.source_file_format)
283
    >>> new_header = format_importer.getHeaderFromString(new_header_string)
284
    >>> new_header.comment = ' This is the top comment.'
285
286
Before doing any change, we can see what's right now in the database:
287
288
    >>> pofile.topcomment.splitlines()[:2]
289
    [u' traducci\xf3n de es.po al Spanish',
290
     u' translation of es.po to Spanish']
291
292
    >>> print pofile.header
293
    Project-Id-Version: es
294
    POT-Creation-Date: 2004-08-17 11:10+0200
295
    PO-Revision-Date: 2005-04-07 13:22+0000
296
    ...
297
    Plural-Forms: nplurals=2; plural=(n != 1);
298
299
Let's update the header with the new one.
300
301
    >>> pofile.updateHeader(new_header)
302
303
The new comment is now applied.
304
305
    >>> pofile.topcomment
306
    u' This is the top comment.'
307
308
And the new header contains the new string.
309
310
    >>> print pofile.header
311
    Project-Id-Version: es
312
    Report-Msgid-Bugs-To: serrador@hispalinux.es
313
    POT-Creation-Date: 2004-08-18 11:10+0200
314
    PO-Revision-Date: 2005-08-18 13:22+0000
315
    ...
2459 by Canonical.com Patch Queue Manager
[trivial] Fix for bug 2296: Broken LInk (system error); the problem was that browser.pofile.POFileView.getPluralFormExpression was fragile. I moved the code to POHeader(), added tests and added an XXX to ensure we keep track of bugs
316
2536 by Canonical.com Patch Queue Manager
Reject onlly the pofiles that have dates older than last import and accept the ones that are equal or newer. Also, we give karma only to translations done inside Rosetta. r=SteveA
317
11666.3.7 by Curtis Hovey
Hushed lint.
318
isTranslationRevisionDateOlder
319
------------------------------
320
321
This method helps to compare two PO files header and decide if the given
322
one is older than the one we have in the IPOFile object. We are using
323
this method, for instance, to know if a new imported PO file should be
324
ignored because we already have a newer one.
325
326
This test is to be sure that the date comparation is working and that
327
two headers with the same date will always be set as newer, because lazy
328
translators forget to update that field from time to time and sometimes,
329
we were losing translations because we were ignoring those imports too.
2536 by Canonical.com Patch Queue Manager
Reject onlly the pofiles that have dates older than last import and accept the ones that are equal or newer. Also, we give karma only to translations done inside Rosetta. r=SteveA
330
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
331
    >>> print pofile.header
2536 by Canonical.com Patch Queue Manager
Reject onlly the pofiles that have dates older than last import and accept the ones that are equal or newer. Also, we give karma only to translations done inside Rosetta. r=SteveA
332
    Project-Id-Version: es
333
    ...
334
    PO-Revision-Date: 2005-08-18 13:22+0000
335
    ...
11666.3.7 by Curtis Hovey
Hushed lint.
336
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
337
    >>> header = pofile.getHeader()
338
339
First, with the same date, we don't consider it older.
340
4335.1.57 by Carlos Perello Marin
Fixed imports to use the new translationfile class
341
    >>> pofile.isTranslationRevisionDateOlder(header)
2536 by Canonical.com Patch Queue Manager
Reject onlly the pofiles that have dates older than last import and accept the ones that are equal or newer. Also, we give karma only to translations done inside Rosetta. r=SteveA
342
    False
343
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
344
Now, we can see how we detect that it's older with an older date.
2536 by Canonical.com Patch Queue Manager
Reject onlly the pofiles that have dates older than last import and accept the ones that are equal or newer. Also, we give karma only to translations done inside Rosetta. r=SteveA
345
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
346
    >>> header.translation_revision_date = datetime.datetime(
347
    ...     2005, 8, 18, 13, 21, tzinfo=UTC)
4335.1.57 by Carlos Perello Marin
Fixed imports to use the new translationfile class
348
    >>> pofile.isTranslationRevisionDateOlder(header)
2536 by Canonical.com Patch Queue Manager
Reject onlly the pofiles that have dates older than last import and accept the ones that are equal or newer. Also, we give karma only to translations done inside Rosetta. r=SteveA
349
    True
350
5509.2.2 by Jeroen Vermeulen
Test that with the POHeader fix, translation files without revision date never supersede a new upload.
351
If the revision date of the stored translation file is missing, the new
352
one is considered an update.
353
354
    >>> from zope.security.proxy import removeSecurityProxy
8751.1.1 by Danilo Šegan
Store migration changes so far.
355
    >>> from lp.translations.utilities.gettext_po_parser import (
5509.2.2 by Jeroen Vermeulen
Test that with the POHeader fix, translation files without revision date never supersede a new upload.
356
    ...     POHeader)
357
358
    >>> old_pofile = removeSecurityProxy(potemplate.newPOFile('tl'))
359
    >>> old_pofile.header = """
360
    ...     Project-Id-Version: foo
361
    ...     MIME-Version: 1.0
362
    ...     Content-Type: text/plain; charset=UTF-8
363
    ...     Content-Transfer-Encoding: 8bit
364
    ...     """
365
    >>> new_header = POHeader("""
366
    ...     Project-Id-Version: foo
367
    ...     PO-Revision-Date: 2007-05-03 14:00+0200
368
    ...     MIME-Version: 1.0
369
    ...     Content-Type: text/plain; charset=UTF-8
370
    ...     Content-Transfer-Encoding: 8bit
371
    ...     """)
372
373
    >>> old_pofile.isTranslationRevisionDateOlder(new_header)
374
    False
375
376
This even goes if the new file also omits the revision date.
377
5509.2.4 by Jeroen Vermeulen
Improvement suggested in review.
378
    >>> new_header = POHeader("""
379
    ...     Project-Id-Version: foo
380
    ...     MIME-Version: 1.0
381
    ...     Content-Type: text/plain; charset=UTF-8
382
    ...     Content-Transfer-Encoding: 8bit
383
    ...     """)
5509.2.2 by Jeroen Vermeulen
Test that with the POHeader fix, translation files without revision date never supersede a new upload.
384
    >>> old_pofile.isTranslationRevisionDateOlder(new_header)
385
    False
386
387
11666.3.7 by Curtis Hovey
Hushed lint.
388
plural_forms
389
------------
390
391
This method returns a number of plural forms for the language of the
392
POFile, or a default of 2 when language doesn't specify it: 2 is the
393
most common value for number of plural forms, so most likely to be
394
correct for any new language.  Even if the default value is incorrect,
395
it is handled gracefully by the rest of the system (see doc/poimport.txt
396
for example).
397
398
When the language has number of plural forms defined, that value is
399
used.
5220.3.3 by Danilo Šegan
Implement comments from Bjorn.
400
11860.2.3 by Jeroen Vermeulen
Test fixups.
401
    >>> from lp.registry.interfaces.product import IProductSet
5220.3.3 by Danilo Šegan
Implement comments from Bjorn.
402
    >>> evolution = getUtility(IProductSet).getByName('evolution')
403
    >>> evolution_trunk = evolution.getSeries('trunk')
404
    >>> evolution_pot = evolution_trunk.getPOTemplate('evolution-2.2')
5220.3.1 by Danilo Šegan
Add plural_forms property to IPOFile.
405
    >>> serbian = getUtility(ILanguageSet)['sr']
406
    >>> serbian.pluralforms
407
    3
11666.3.7 by Curtis Hovey
Hushed lint.
408
11196.4.1 by Danilo Šegan
Change getDummyPOFile to accept actual language as the parameter instead of language code.
409
    >>> evolution_sr = evolution_pot.getDummyPOFile(serbian)
5220.3.3 by Danilo Šegan
Implement comments from Bjorn.
410
    >>> evolution_sr.plural_forms
411
    3
5220.3.1 by Danilo Šegan
Add plural_forms property to IPOFile.
412
5220.3.3 by Danilo Šegan
Implement comments from Bjorn.
413
And when a language has no plural forms defined, a POFile defaults to 2,
414
the most common number of plural forms:
5220.3.1 by Danilo Šegan
Add plural_forms property to IPOFile.
415
416
    >>> divehi = getUtility(ILanguageSet)['dv']
417
    >>> print divehi.pluralforms
418
    None
11666.3.7 by Curtis Hovey
Hushed lint.
419
11196.4.1 by Danilo Šegan
Change getDummyPOFile to accept actual language as the parameter instead of language code.
420
    >>> evolution_dv = evolution_pot.getDummyPOFile(divehi)
5220.3.1 by Danilo Šegan
Add plural_forms property to IPOFile.
421
    >>> evolution_dv.plural_forms
422
    2
4335.1.74 by Carlos Perello Marin
Applied more review comments
423
11666.3.7 by Curtis Hovey
Hushed lint.
424
425
export
426
------
2976.9.6 by Carlos Perello Marin
Fixed code and added tests
427
428
This method serializes an IPOFile as a .po file.
429
430
Get a concrete POFile we know doesn't have a UTF-8 encoding.
431
11860.2.3 by Jeroen Vermeulen
Test fixups.
432
    >>> from lp.translations.model.pofile import POFile
2976.9.6 by Carlos Perello Marin
Fixed code and added tests
433
    >>> pofile = POFile.get(24)
434
    >>> print pofile.header
435
    Project-Id-Version: PACKAGE VERSION
436
    ...
437
    Content-Type: text/plain; charset=EUC-JP
438
    ...
439
440
Now, let's export it with its default encoding.
441
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
442
    >>> stream = pofile.export()
2976.9.6 by Carlos Perello Marin
Fixed code and added tests
443
    >>> stream_list = stream.splitlines()
444
445
The header is not changed.
446
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
447
    >>> for i in range(len(stream_list)):
448
    ...     if stream_list[i].startswith('"Content-Type:'):
449
    ...         print stream_list[i]
450
    "Content-Type: text/plain; charset=EUC-JP\n"
2976.9.6 by Carlos Perello Marin
Fixed code and added tests
451
11666.3.7 by Curtis Hovey
Hushed lint.
452
And checking one of the translations, we can see that it's using the
453
EUC-JP encoding.
2976.9.6 by Carlos Perello Marin
Fixed code and added tests
454
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
455
    >>> for i in range(len(stream_list)):
456
    ...     if (stream_list[i].startswith('msgstr') and
457
    ...         'prefs.js' in stream_list[i]):
458
    ...         break
459
    >>> stream_list[i]
7675.1000.1 by Jeroen Vermeulen
More test fixups. Filters still broken.
460
    'msgstr "\xc0\xdf\xc4\xea\xa4\xce\xa5\xab...\xa5\xba\xa4\xcb
461
    /etc/mozilla/prefs.js
462
    \xa4\xac\xcd\xf8\xcd\xd1\xa4\xc7\xa4\xad\xa4\xde\xa4\xb9\xa1\xa3"'
2976.9.6 by Carlos Perello Marin
Fixed code and added tests
463
464
Now, let's force the UTF-8 encoding.
465
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
466
    >>> stream = pofile.export(force_utf8=True)
2976.9.6 by Carlos Perello Marin
Fixed code and added tests
467
    >>> stream_list = stream.splitlines()
468
469
We can see that the header has been updated to have UTF-8
470
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
471
    >>> for i in range(len(stream_list)):
472
    ...     if stream_list[i].startswith('"Content-Type:'):
473
    ...         print stream_list[i]
474
    "Content-Type: text/plain; charset=UTF-8\n"
2976.9.6 by Carlos Perello Marin
Fixed code and added tests
475
476
And the encoding used is also using UTF-8 chars.
477
4335.1.63 by Carlos Perello Marin
Ported pofile.txt to the new infrastructure
478
    >>> for i in range(len(stream_list)):
479
    ...     if (stream_list[i].startswith('msgstr') and
480
    ...         'prefs.js' in stream_list[i]):
481
    ...         break
482
    >>> stream_list[i]
7675.1000.1 by Jeroen Vermeulen
More test fixups. Filters still broken.
483
    'msgstr "\xe8\xa8\xad\xe5\xae\x9a\xe3\x81...\xba\xe3\x81\xab
484
    /etc/mozilla/prefs.js
485
    \xe3\x81\x8c\xe5\x88\xa9\xe7\x94\xa8\xe3...\x99\xe3\x80\x82"'
2976.9.6 by Carlos Perello Marin
Fixed code and added tests
486
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
487
There are some situations when a msgid_plural changes, while the msgid
488
singular remains unchanged.
489
490
So for a concrete export, we have a message like:
491
11860.2.3 by Jeroen Vermeulen
Test fixups.
492
    >>> pofile_es = potemplate.getPOFileByLang('es')
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
493
    >>> print pofile_es.export(force_utf8=True).decode('utf8')
11860.2.3 by Jeroen Vermeulen
Test fixups.
494
    # ...
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
495
    ...
496
    #: addressbook/gui/widgets/foo.c:345
6891.2.1 by Danilo Šegan
Exports and remaining test updates for fuzzy flag removal.
497
    #, c-format
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
498
    msgid "%d foo"
499
    msgid_plural "%d bars"
6891.2.1 by Danilo Šegan
Exports and remaining test updates for fuzzy flag removal.
500
    msgstr[0] ""
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
501
    ...
502
503
When it changes...
504
505
    >>> potmsgset = potemplate.getPOTMsgSetByMsgIDText(
6253.3.5 by Danilo Šegan
Fix remaining failing tests.
506
    ...     u'%d foo', u'%d bars')
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
507
508
    # It has plural forms.
11666.3.7 by Curtis Hovey
Hushed lint.
509
5084.14.113 by Danilo Šegan
Fix imports in vpoexport, pofile.txt.
510
    >>> print potmsgset.plural_text
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
511
    %d bars
512
513
    # We change the plural form.
11666.3.7 by Curtis Hovey
Hushed lint.
514
5106.2.14 by Carlos Perello Marin
More test fixes
515
    >>> potmsgset.updatePluralForm(u'something else')
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
516
    >>> from canonical.database.sqlbase import flush_database_updates
517
    >>> flush_database_updates()
5084.14.113 by Danilo Šegan
Fix imports in vpoexport, pofile.txt.
518
    >>> print potmsgset.plural_text
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
519
    something else
520
521
...the export reflects that change.
522
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
523
    >>> print pofile_es.export(force_utf8=True).decode('utf8')
11860.2.3 by Jeroen Vermeulen
Test fixups.
524
    # ...
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
525
    ...
526
    #: addressbook/gui/widgets/foo.c:345
6891.2.1 by Danilo Šegan
Exports and remaining test updates for fuzzy flag removal.
527
    #, c-format
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
528
    msgid "%d foo"
529
    msgid_plural "something else"
6891.2.1 by Danilo Šegan
Exports and remaining test updates for fuzzy flag removal.
530
    msgstr[0] ""
5110.1.1 by Carlos Perello Marin
Fixed the out of memory issue by reducing the time the export script is running, improved our test to detect database breakages and added a workaround for a cherry pick
531
    ...
532
4335.1.74 by Carlos Perello Marin
Applied more review comments
533
11666.3.7 by Curtis Hovey
Hushed lint.
534
createMessageSetFromText
535
------------------------
3691.122.4 by Carlos Perello Marin
Fixed a corner case when we could reach a situation where we are not able to find POTMsgSet rows that already exist
536
537
This method returns a new IPOMsgSet for the associated text.
538
539
Let's get the IPOFile we are going to use for this test.
540
4335.1.74 by Carlos Perello Marin
Applied more review comments
541
    >>> pofile_sr = potemplate.newPOFile('sr')
3691.122.4 by Carlos Perello Marin
Fixed a corner case when we could reach a situation where we are not able to find POTMsgSet rows that already exist
542
543
And the msgid we are looking for.
544
4335.1.74 by Carlos Perello Marin
Applied more review comments
545
    >>> msgid = u'Found %i invalid file.'
6253.3.5 by Danilo Šegan
Fix remaining failing tests.
546
    >>> msgid_plural = u'Found %i invalid files.'
3691.122.4 by Carlos Perello Marin
Fixed a corner case when we could reach a situation where we are not able to find POTMsgSet rows that already exist
547
548
Now, just to be sure that this entry doesn't exist yet:
549
7519.2.51 by Danilo Šegan
Fix a few tests.
550
    >>> potmsgset = pofile_sr.potemplate.getOrCreateSharedPOTMsgSet(
6253.3.5 by Danilo Šegan
Fix remaining failing tests.
551
    ...     singular_text=msgid, plural_text=msgid_plural)
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
552
    >>> print potmsgset.getCurrentTranslation(
553
    ...     pofile_sr.potemplate, pofile_sr.language,
554
    ...     pofile_sr.potemplate.translation_side)
6253.3.5 by Danilo Šegan
Fix remaining failing tests.
555
    None
3691.122.4 by Carlos Perello Marin
Fixed a corner case when we could reach a situation where we are not able to find POTMsgSet rows that already exist
556
11860.2.3 by Jeroen Vermeulen
Test fixups.
557
Is time to create it.  We need some extra privileges here.
3691.122.4 by Carlos Perello Marin
Fixed a corner case when we could reach a situation where we are not able to find POTMsgSet rows that already exist
558
13130.1.6 by Curtis Hovey
Move ILaunchpadCelebrity to lp.app.
559
    >>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
11860.2.3 by Jeroen Vermeulen
Test fixups.
560
    >>> login('carlos@canonical.com')
561
    >>> rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts
5084.14.83 by Carlos Perelló Marín
More test fixes
562
    >>> translations = {0: u''}
7675.916.98 by Henning Eggers
Merged db-stable at r10026 (recife roll-back) but without accepting the changes.
563
    >>> is_current_upstream = False
5084.14.83 by Carlos Perelló Marín
More test fixes
564
    >>> lock_timestamp = datetime.datetime.now(UTC)
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
565
    >>> translation_message = factory.makeCurrentTranslationMessage(
566
    ...     pofile_sr, potmsgset, rosetta_experts, translations=translations,
567
    ...     current_other=is_current_upstream)
3691.122.4 by Carlos Perello Marin
Fixed a corner case when we could reach a situation where we are not able to find POTMsgSet rows that already exist
568
569
As we can see, is the msgid we were looking for.
570
5084.14.83 by Carlos Perelló Marín
More test fixes
571
    >>> print translation_message.potmsgset.msgid_singular.msgid
4335.1.74 by Carlos Perello Marin
Applied more review comments
572
    Found %i invalid file.
11666.3.7 by Curtis Hovey
Hushed lint.
573
5084.14.83 by Carlos Perelló Marín
More test fixes
574
    >>> print pofile_sr.language.code
575
    sr
11666.3.7 by Curtis Hovey
Hushed lint.
576
11472.1.3 by Henning Eggers
Fixed some tests.
577
    >>> print translation_message.language.code
5084.14.83 by Carlos Perelló Marín
More test fixes
578
    sr
3691.122.4 by Carlos Perello Marin
Fixed a corner case when we could reach a situation where we are not able to find POTMsgSet rows that already exist
579
11860.2.3 by Jeroen Vermeulen
Test fixups.
580
We created it without translations.
5084.14.83 by Carlos Perelló Marín
More test fixes
581
582
    >>> translation_message.translations
583
    [None, None, None]
584
585
11666.3.7 by Curtis Hovey
Hushed lint.
586
People who contributed translations
587
-----------------------------------
7675.112.1 by Guilherme Salgado
Move some methods from IPersonSet to more appropriate places.
588
11666.3.7 by Curtis Hovey
Hushed lint.
589
The 'contributors' property of a POFile returns all the people who
590
contributed translations to it.
7675.112.1 by Guilherme Salgado
Move some methods from IPersonSet to more appropriate places.
591
9942.3.1 by Jeroen Vermeulen
Don't list rosetta_experts as contributor, and always make it the translator of credits messages.
592
    >>> def print_names(persons):
593
    ...     """Print name for each of `persons`."""
594
    ...     for person in persons:
595
    ...         print person.name
596
    ...     print "--"
597
7675.1000.1 by Jeroen Vermeulen
More test fixups. Filters still broken.
598
    >>> evolution = getUtility(IProductSet).getByName('evolution')
599
    >>> evolution_trunk = evolution.getSeries('trunk')
600
    >>> potemplatesubset = potemplateset.getSubset(
601
    ...     productseries=evolution_trunk)
602
    >>> evolution_template = potemplatesubset['evolution-2.2']
603
    >>> evolution_es = evolution_template.getPOFileByLang('es')
9942.3.1 by Jeroen Vermeulen
Don't list rosetta_experts as contributor, and always make it the translator of credits messages.
604
    >>> print_names(evolution_es.contributors)
605
    carlos
606
    mark
607
    no-priv
608
    --
7675.112.1 by Guilherme Salgado
Move some methods from IPersonSet to more appropriate places.
609
11666.3.7 by Curtis Hovey
Hushed lint.
610
If you have a distroseries and want to know all the people who
611
contributed translations on a given language for that distroseries, you
612
can use the getPOFileContributorsByLanguage() method of IDistroSeries.
7675.112.1 by Guilherme Salgado
Move some methods from IPersonSet to more appropriate places.
613
8971.22.2 by Guilherme Salgado
Fix a bunch of tests to import registry model classes from lp.registry.model instead of from canonical.launchpad.database
614
    >>> from lp.registry.model.distroseries import DistroSeries
11869.8.7 by Jonathan Lange
Don't import anything from c.l.database directly
615
    >>> from lp.services.worlddata.model.language import Language
7675.112.1 by Guilherme Salgado
Move some methods from IPersonSet to more appropriate places.
616
    >>> hoary = DistroSeries.selectOneBy(name="hoary")
617
    >>> spanish = Language.selectOneBy(code="es")
9942.3.1 by Jeroen Vermeulen
Don't list rosetta_experts as contributor, and always make it the translator of credits messages.
618
    >>> print_names(hoary.getPOFileContributorsByLanguage(spanish))
619
    jorge-gonzalez-gonzalez
620
    carlos
621
    valyag
622
    name16
623
    name12
624
    tsukimi
625
    --
7675.112.1 by Guilherme Salgado
Move some methods from IPersonSet to more appropriate places.
626
627
    # We can see that there is another translator that doesn't appear in
628
    # previous list because the template he translated is not current.
11666.3.7 by Curtis Hovey
Hushed lint.
629
7675.112.1 by Guilherme Salgado
Move some methods from IPersonSet to more appropriate places.
630
    >>> non_current_pofile = POFile.get(31)
631
    >>> non_current_pofile.potemplate.iscurrent
632
    False
633
9942.3.1 by Jeroen Vermeulen
Don't list rosetta_experts as contributor, and always make it the translator of credits messages.
634
    >>> print_names(non_current_pofile.contributors)
635
    jordi
636
    --
7675.112.1 by Guilherme Salgado
Move some methods from IPersonSet to more appropriate places.
637
638
    >>> non_current_pofile.potemplate.distroseries == hoary
639
    True
640
641
    >>> non_current_pofile.language == spanish
642
    True
643
9942.3.1 by Jeroen Vermeulen
Don't list rosetta_experts as contributor, and always make it the translator of credits messages.
644
The rosetta_experts team is special: it never shows up in contributors
645
lists.
646
647
    >>> experts_pofile = factory.makePOFile('nl')
7675.1004.5 by Henning Eggers
Some test fixes.
648
    >>> experts_message = factory.makeCurrentTranslationMessage(
9942.3.1 by Jeroen Vermeulen
Don't list rosetta_experts as contributor, and always make it the translator of credits messages.
649
    ...     pofile=experts_pofile, translator=rosetta_experts,
650
    ...     reviewer=rosetta_experts, translations=['hi'])
651
652
    >>> print_names(experts_pofile.contributors)
653
    --
654
7675.112.1 by Guilherme Salgado
Move some methods from IPersonSet to more appropriate places.
655
11666.3.7 by Curtis Hovey
Hushed lint.
656
getPOTMsgSetTranslated
657
----------------------
5217.2.1 by Carlos Perelló Marín
Fixed getPOTMsgSetFuzzy and getPOTMsgSetTranslated
658
659
With this method we can get all POTMsgSet objects that are fully
660
translated for a given POFile.
661
7519.2.51 by Danilo Šegan
Fix a few tests.
662
    >>> def print_message_status(potmsgsets, pofile):
6891.2.1 by Danilo Šegan
Exports and remaining test updates for fuzzy flag removal.
663
    ...     print "%-10s %-5s %-10s %-11s" % (
664
    ...         "msgid", "form", "translat.", "Has plurals")
5217.2.1 by Carlos Perelló Marín
Fixed getPOTMsgSetFuzzy and getPOTMsgSetTranslated
665
    ...     for potmsgset in potmsgsets:
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
666
    ...         translationmessage = potmsgset.getCurrentTranslation(
667
    ...             pofile.potemplate, pofile.language,
668
    ...             pofile.potemplate.translation_side)
7675.1004.5 by Henning Eggers
Some test fixes.
669
    ...         msgid = potmsgset.msgid_singular.msgid
670
    ...         if len(msgid) > 10:
671
    ...             msgid = msgid[:7] + '...'
5217.2.3 by Carlos Perello Marin
Applied review comments from Danilo
672
    ...         for index in range(len(translationmessage.translations)):
673
    ...             if translationmessage.translations[index] is None:
5217.2.1 by Carlos Perelló Marín
Fixed getPOTMsgSetFuzzy and getPOTMsgSetTranslated
674
    ...                 translation = 'None'
675
    ...             else:
5217.2.3 by Carlos Perello Marin
Applied review comments from Danilo
676
    ...                 translation = translationmessage.translations[index]
5217.2.1 by Carlos Perelló Marín
Fixed getPOTMsgSetFuzzy and getPOTMsgSetTranslated
677
    ...                 if len(translation) > 10:
678
    ...                     translation = translation[:7] + '...'
7675.1004.5 by Henning Eggers
Some test fixes.
679
    ...             print "%-10s %-5s %-10s %s" % (
5217.2.1 by Carlos Perelló Marín
Fixed getPOTMsgSetFuzzy and getPOTMsgSetTranslated
680
    ...                 msgid, index, translation,
681
    ...                 potmsgset.msgid_plural is not None)
682
5217.2.3 by Carlos Perello Marin
Applied review comments from Danilo
683
    >>> potmsgsets_translated = evolution_es.getPOTMsgSetTranslated()
684
    >>> print_message_status(
7519.2.51 by Danilo Šegan
Fix a few tests.
685
    ...     potmsgsets_translated, evolution_es)
6891.2.1 by Danilo Šegan
Exports and remaining test updates for fuzzy flag removal.
686
    msgid      form  translat.  Has plurals
687
    evoluti... 0     libreta... False
688
    current... 0     carpeta... False
689
    have       0     tiene      False
690
     cards     0      tarjetas  False
691
    The loc... 0     La ubic... False
692
    %d contact 0     %d cont... True
693
    %d contact 1     %d cont... True
694
    Opening... 0     Abrir %... True
695
    Opening... 1     Abrir %... True
696
    EncFS P... 0     Contras... False
697
5217.2.1 by Carlos Perelló Marín
Fixed getPOTMsgSetFuzzy and getPOTMsgSetTranslated
698
11666.3.7 by Curtis Hovey
Hushed lint.
699
getTranslationsFilteredBy
700
-------------------------
5613.2.9 by Danilo Šegan
Implement review comments from sinzui.
701
702
This method returns a list of TranslationMessages in a given POFile
703
created by a certain person.
704
7675.1000.1 by Jeroen Vermeulen
More test fixups. Filters still broken.
705
    >>> person_set = getUtility(IPersonSet)
5613.2.9 by Danilo Šegan
Implement review comments from sinzui.
706
    >>> carlos = person_set.getByName('carlos')
707
    >>> translationmessages = evolution_es.getTranslationsFilteredBy(carlos)
708
    >>> for translationmessage in translationmessages:
709
    ...     print translationmessage.translations
710
    [u'libreta de direcciones de Evolution']
711
    [u'carpeta de libretas de direcciones actual']
712
    [u'lalalala']
713
    [u'tiene ']
714
    [u' tarjetas']
7675.1000.1 by Jeroen Vermeulen
More test fixups. Filters still broken.
715
    [u'La ubicaci\xf3n y jerarqu\xeda de las carpetas de contactos de
716
    Evolution ha cambiado desde Evolution 1.x.\n\nTenga paciencia mientras
717
    Evolution migra sus carpetas...']
5613.2.9 by Danilo Šegan
Implement review comments from sinzui.
718
    [u'%d contacto', u'%d contactos']
7675.1000.1 by Jeroen Vermeulen
More test fixups. Filters still broken.
719
    [u'Abrir %d contacto abrir\xe1 %d ventanas nuevas tambi\xe9n.\n\xbfQuiere
720
    realmente mostrar este contacto?',
721
    u'Abrir %d contactos abrir\xe1 %d ventanas nuevas tambi\xe9n.\n\xbfQuiere
722
    realmente mostrar todos estos contactos?']
5613.2.9 by Danilo Šegan
Implement review comments from sinzui.
723
    [u'Contrase\xf1a de EncFS: ']
724
725
If the passed person is None, the call fails with an assertion.
726
727
    >>> translationmessages = evolution_es.getTranslationsFilteredBy(None)
728
    Traceback (most recent call last):
729
    ...
730
    AssertionError: You must provide a person to filter by.
5217.2.1 by Carlos Perelló Marín
Fixed getPOTMsgSetFuzzy and getPOTMsgSetTranslated
731
11666.3.7 by Curtis Hovey
Hushed lint.
732
733
Translation credits
734
-------------------
735
7675.916.98 by Henning Eggers
Merged db-stable at r10026 (recife roll-back) but without accepting the changes.
736
Translation credits are handled automatically, and cannot be
737
translated in any other way except through an upload from upstream.
4353.3.5 by Danilo Šegan
Add test for locked-down translation-credits.
738
739
Lets get Spanish translation for alsa-utils.
740
4335.1.74 by Carlos Perello Marin
Applied more review comments
741
    >>> alsautils = getUtility(IProductSet).getByName('alsa-utils')
742
    >>> alsa_trunk = alsautils.getSeries('trunk')
743
    >>> alsa_template = alsa_trunk.getPOTemplate('alsa-utils')
5084.14.98 by Danilo Šegan
Port translation-credits tests.
744
    >>> alsa_translation = alsa_template.newPOFile('sr')
4353.3.5 by Danilo Šegan
Add test for locked-down translation-credits.
745
11666.3.7 by Curtis Hovey
Hushed lint.
746
This translation file contains a translation-credits message. By default
747
it is created with a dummy translation
4353.3.5 by Danilo Šegan
Add test for locked-down translation-credits.
748
5084.14.98 by Danilo Šegan
Port translation-credits tests.
749
    >>> potmsgset = alsa_template.getPOTMsgSetByMsgIDText(
750
    ...     u'translation-credits')
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
751
    >>> current = potmsgset.getCurrentTranslation(
752
    ...     alsa_template, alsa_translation.language,
753
    ...     alsa_template.translation_side)
9775.1.5 by Henning Eggers
Fixed tests.
754
    >>> print current.translations
755
    [u'This is a dummy translation so that
756
    the credits are counted as translated.']
4353.3.5 by Danilo Šegan
Add test for locked-down translation-credits.
757
7675.916.98 by Henning Eggers
Merged db-stable at r10026 (recife roll-back) but without accepting the changes.
758
If we submit an upstream translation, the translation for this message
4353.3.5 by Danilo Šegan
Add test for locked-down translation-credits.
759
is updated.
760
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
761
    >>> new_credits = factory.makeCurrentTranslationMessage(
762
    ...     alsa_translation, potmsgset, alsa_translation.owner,
763
    ...     translations={0: u'Happy translator'}, current_other=True)
5084.14.98 by Danilo Šegan
Port translation-credits tests.
764
    >>> flush_database_updates()
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
765
    >>> current = potmsgset.getCurrentTranslation(
766
    ...     alsa_template, alsa_translation.language,
767
    ...     alsa_template.translation_side)
5084.14.98 by Danilo Šegan
Port translation-credits tests.
768
    >>> print current.translations
4335.1.74 by Carlos Perello Marin
Applied more review comments
769
    [u'Happy translator']
4353.3.5 by Danilo Šegan
Add test for locked-down translation-credits.
770
7675.916.98 by Henning Eggers
Merged db-stable at r10026 (recife roll-back) but without accepting the changes.
771
If we submit non-upstream translation, it's rejected.
4353.3.5 by Danilo Šegan
Add test for locked-down translation-credits.
772
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
773
    >>> no_credits = potmsgset.submitSuggestion(
5084.14.98 by Danilo Šegan
Port translation-credits tests.
774
    ...     alsa_translation, alsa_translation.owner,
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
775
    ...     {0: u'Unhappy translator'})
5272.1.1 by Jeroen Vermeulen
Ignore translation-credits translations when importing non-upstream PO files.
776
    >>> print no_credits
777
    None
11666.3.7 by Curtis Hovey
Hushed lint.
778
5084.14.98 by Danilo Šegan
Port translation-credits tests.
779
    >>> flush_database_updates()
7675.1017.4 by Danilo Segan
Migrate doc/pofile.txt.
780
    >>> current = potmsgset.getCurrentTranslation(
781
    ...     alsa_template, alsa_translation.language,
782
    ...     alsa_template.translation_side)
5084.14.98 by Danilo Šegan
Port translation-credits tests.
783
    >>> print current.translations
4335.1.74 by Carlos Perello Marin
Applied more review comments
784
    [u'Happy translator']
4353.3.5 by Danilo Šegan
Add test for locked-down translation-credits.
785
4353.3.18 by Danilo Šegan
Rename methods, add pagetest, code cleanup: resulting from review.
786
11666.3.7 by Curtis Hovey
Hushed lint.
787
POFileToTranslationFileDataAdapter
788
----------------------------------
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
789
790
POFileToTranslationFileDataAdapter is an adapter to export a POFile
791
object. It implements the ITranslationFileData interface which is a
11666.3.7 by Curtis Hovey
Hushed lint.
792
common file format in-memory to convert from one file format to another.
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
793
8751.1.10 by Danilo Šegan
Remove dependency on glob imports from most of the stuff.
794
    >>> from lp.translations.interfaces.translationcommonformat import (
795
    ...     ITranslationFileData)
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
796
    >>> evolution_sourcepackagename = sourcepackagenameset['evolution']
797
    >>> ubuntu = distributionset['ubuntu']
798
    >>> hoary = ubuntu['hoary']
799
    >>> potemplatesubset = potemplateset.getSubset(
800
    ...     distroseries=hoary, sourcepackagename=evolution_sourcepackagename)
801
    >>> evolution_22 = potemplatesubset['evolution-2.2']
802
    >>> evolution_ja = evolution_22.getPOFileByLang('ja')
803
5628.4.2 by Carlos Perello Marin
Applied review comments
804
Getting the translation file data is just a matter of adapting the
11666.3.7 by Curtis Hovey
Hushed lint.
805
object to the ITranslationFileData interface. Since there are multiple
806
adapters for differnt purposes, this adapter is named.
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
807
7587.1.1 by Henning Eggers
Implemented stage 1 of export-changed-in-launchpad.
808
    >>> from zope.component import getAdapter
809
    >>> translation_file_data = getAdapter(
810
    ...     evolution_ja, ITranslationFileData, 'all_messages')
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
811
11666.3.7 by Curtis Hovey
Hushed lint.
812
We get an updated header based on some metadata in our database instead
813
of the imported one stored in POFile.header.
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
814
815
    >>> print evolution_ja.header
816
    Project-Id-Version: evolution
817
    Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>
818
    POT-Creation-Date: 2005-05-06 20:39:27.778946+00:00
819
    PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
820
    Last-Translator: FULL NAME <EMAIL@ADDRESS>
821
    Language-Team: Japanese <ja@li.org>
822
    MIME-Version: 1.0
823
    Content-Type: text/plain; charset=UTF-8
824
    Content-Transfer-Encoding: 8bit
825
    Plural-Forms: nplurals=1; plural=0
826
827
    >>> print translation_file_data.header.getRawContent()
828
    Project-Id-Version: evolution
829
    Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>
830
    POT-Creation-Date: 2005-04-07 14:10+0200
831
    PO-Revision-Date: 2005-10-11 23:08+0000
832
    Last-Translator: Carlos Perell... <carlos@canonical.com>
833
    Language-Team: Japanese <ja@li.org>
834
    MIME-Version: 1.0
835
    Content-Type: text/plain; charset=UTF-8
836
    Content-Transfer-Encoding: 8bit
837
    Plural-Forms: nplurals=1; plural=0;
838
    X-Launchpad-Export-Date: ...-...-... ...:...+...
839
    X-Generator: Launchpad (build ...)
840
5628.4.2 by Carlos Perello Marin
Applied review comments
841
We can see that last translator is Carlos, just like the updated header
842
says:
5628.4.1 by Carlos Perello Marin
Removed export cache that is not used and fixed the export to update last translator field and when was it last updated
843
844
    >>> evolution_ja.lasttranslator.displayname
845
    u'Carlos Perell\xf3 Mar\xedn'
846
847
And the PO Revision Date matches when was the PO file last changed.
848
849
    >>> print evolution_ja.date_changed
850
    2005-10-11 23:08:01.899322+00:00
851
852
11666.3.7 by Curtis Hovey
Hushed lint.
853
POFileToChangedFromPackagedAdapter
854
----------------------------------
7587.1.1 by Henning Eggers
Implemented stage 1 of export-changed-in-launchpad.
855
11666.3.7 by Curtis Hovey
Hushed lint.
856
Another adapter to the ITranslationFileData interface includes only
857
those messages that were changed from their packaged version. The class
858
is called POFileToChangedFromPackagedAdapter and it is registered as a
859
named adapter, too.
7587.1.1 by Henning Eggers
Implemented stage 1 of export-changed-in-launchpad.
860
861
    >>> translation_file_data = getAdapter(
862
    ...     evolution_ja, ITranslationFileData, 'changed_messages')
863
    >>> ITranslationFileData.providedBy(translation_file_data)
864
    True
865
11666.3.7 by Curtis Hovey
Hushed lint.
866
867
POFile Security tests
868
=====================
2840.2.25 by Carlos Perelló Marín
Applied comments after the initial review
869
870
Import the function that will help us to do this test.
871
3691.373.6 by Christian Reis
Move check_permission into webapp.authorization
872
    >>> from canonical.launchpad.webapp.authorization import check_permission
2840.2.25 by Carlos Perelló Marín
Applied comments after the initial review
873
874
A Launchpad admin must have permission to edit an IPOFile always.
5628.4.2 by Carlos Perello Marin
Applied review comments
875
2840.2.25 by Carlos Perelló Marín
Applied comments after the initial review
876
    >>> login('foo.bar@canonical.com')
877
    >>> check_permission('launchpad.Edit', pofile)
878
    True
879
880
And a Rosetta Expert too.
881
882
    >>> login('jordi@ubuntu.com')
883
    >>> check_permission('launchpad.Edit', pofile)
884
    True
885
2880.2.18 by Carlos Perelló Marín
Improved the translation form parser with SteveA's suggestions and fixed all tests
886
And that's all, folks!