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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
|
# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
# pylint: disable-msg=E0211,E0213
from lazr.enum import (
DBEnumeratedType,
DBItem,
)
from zope.interface import (
Attribute,
Interface,
)
from zope.schema import (
Bool,
Choice,
Datetime,
Int,
List,
Object,
Text,
)
from canonical.launchpad import _
from lp.registry.interfaces.person import IPerson
from lp.translations.interfaces.pofile import IPOFile
from lp.translations.interfaces.potemplate import IPOTemplate
from lp.translations.interfaces.potmsgset import IPOTMsgSet
from lp.translations.interfaces.potranslation import IPOTranslation
__metaclass__ = type
__all__ = [
'ITranslationMessage',
'ITranslationMessageSet',
'ITranslationMessageSuggestions',
'RosettaTranslationOrigin',
'TranslationConflict',
'TranslationValidationStatus',
]
class TranslationConflict(Exception):
"""Someone updated the translation we are trying to update."""
class RosettaTranslationOrigin(DBEnumeratedType):
"""Rosetta Translation Origin
Translation sightings in Rosetta can come from a variety
of sources. We might see a translation for the first time
in CVS, or we might get it through the web, for example.
This schema documents those options.
"""
SCM = DBItem(1, """
Source Control Management Source
This translation sighting came from a PO File we
analysed in a source control managements sytem first.
""")
ROSETTAWEB = DBItem(2, """
Rosetta Web Source
This translation was presented to Rosetta via
the community web site.
""")
LAUNCHPAD_GENERATED = DBItem(3, """
Generated by Launchpad itself.
This is used for messages like generated translation
credits messages.
""")
class TranslationValidationStatus(DBEnumeratedType):
"""Translation Validation Status
Every time a translation is added to Rosetta we should checked that
follows all rules to be a valid translation inside a .po file.
This schema documents the status of that validation.
"""
UNKNOWN = DBItem(0, """
Unknown
This translation has not been validated yet.
""")
OK = DBItem(1, """
Ok
This translation has been validated and no errors were discovered.
""")
UNKNOWNERROR = DBItem(2, """
Unknown Error
This translation has an unknown error.
""")
class ITranslationMessage(Interface):
"""A translation message in a translation file."""
id = Int(
title=_("The ID for this translation message"),
readonly=True, required=True)
browser_pofile = Object(
title=_("The translation file from where this translation comes"),
readonly=False, required=False, schema=IPOFile)
potemplate = Object(
title=_("The template this translation is in"),
readonly=False, required=False, schema=IPOTemplate)
language = Choice(
title=_('Language of this translation message.'),
vocabulary='Language', required=False)
potmsgset = Object(
title=_("The template message that this translation is for"),
readonly=False, required=True, schema=IPOTMsgSet)
date_created = Datetime(
title=_("The date we saw this translation first"),
readonly=True, required=True)
submitter = Object(
title=_("The submitter of this translation"),
readonly=True, required=True, schema=IPerson)
date_reviewed = Datetime(
title=_("The date when this message was reviewed for last time"),
readonly=False, required=False)
reviewer = Object(
title=_("The person who reviewed and accepted this translation"),
readonly=False, required=False, schema=IPerson)
# Message references for up to TranslationConstants.MAX_PLURAL_FORMS
# plural forms.
msgstr0 = Object(
title=_("Translation for plural form 0 (if any)"),
required=False, schema=IPOTranslation)
msgstr1 = Object(
title=_("Translation for plural form 1 (if any)"),
required=False, schema=IPOTranslation)
msgstr2 = Object(
title=_("Translation for plural form 2 (if any)"),
required=False, schema=IPOTranslation)
msgstr3 = Object(
title=_("Translation for plural form 3 (if any)"),
required=False, schema=IPOTranslation)
msgstr4 = Object(
title=_("Translation for plural form 4 (if any)"),
required=False, schema=IPOTranslation)
msgstr5 = Object(
title=_("Translation for plural form 5 (if any)"),
required=False, schema=IPOTranslation)
all_msgstrs = List(
title=_("All msgstr attributes"),
description=_("""
All translations [msgstr0, msgstr1, ...] for this message,
including any empty ones.
"""), readonly=True, required=True)
translations = List(
title=_("Translations for this message"),
description=_("""
All translations for this message, its number will depend on the
number of plural forms available for its language.
"""), readonly=True, required=True)
comment = Text(
title=_("Text of translator comment from the translation file"),
readonly=False, required=False)
origin = Choice(
title=_("Where the submission originally came from"),
values=RosettaTranslationOrigin,
readonly=True, required=True)
validation_status = Choice(
title=_("The status of the validation of the translation"),
values=TranslationValidationStatus,
readonly=False, required=True)
is_current_ubuntu = Bool(
title=_("Whether this translation is being used in Ubuntu"),
readonly=False, default=False, required=True)
is_complete = Bool(
title=_("Whether the translation has all needed plural forms or not"),
readonly=True, required=True)
is_current_upstream = Bool(
title=_(
"Whether this translation is being used in latest imported file"),
readonly=False, default=False, required=True)
was_obsolete_in_last_import = Bool(
title=_(
"Whether this translation was obsolete in last imported file"),
readonly=False, default=False, required=True)
is_empty = Bool(
title=_("Whether this message has any translation"),
readonly=True, required=True)
plural_forms = Int(
title=_("Number of plural form translations in this translation."),
readonly=True, required=True)
is_diverged = Bool(
title=_("Is this message diverged?"), readonly=True, required=True)
def setPOFile(pofile):
"""Set a POFile for use in views."""
def getOnePOFile():
"""Get any POFile containing this translation."""
def ensureBrowserPOFile():
"""Assign the result of getOnePOFile to browser_pofile.
If browser_pofile is already set, it is left unchanged.
"""
def getSharedEquivalent():
"""Find shared message that otherwise exactly matches this one."""
def shareIfPossible():
"""Make this message shared, if possible.
If there is already a similar message that is shared, this
message's information is merged into that of the existing one,
and self is deleted.
"""
def isHidden(pofile):
"""Whether this is an unused, hidden suggestion in `pofile`.
A suggestion is hidden if it's older than the current translation.
"""
# Used in a script to remove upstream translations.
def destroySelf():
"""Remove this object.
It must not be referenced by any other object.
"""
def clone(potmsgset):
"""Create a copy of this message associated with a different MsgSet.
potemplate of the clone is always None. Aside from this, all values
should be the same.
"""
def approve(pofile, reviewer, share_with_other_side=False,
lock_timestamp=None):
"""Approve this suggestion, making it a current translation."""
def approveAsDiverged(pofile, reviewer, lock_timestamp=None):
"""Approve this suggestion, as a diverged translation."""
def acceptFromImport(pofile, share_with_other_side=False,
lock_timestamp=None):
"""Accept a suggestion coming from a translation import."""
def acceptFromUpstreamImportOnPackage(pofile, lock_timestamp=None):
"""Accept a suggestion coming from a translation import.
This method allows to mark a translation as being current in
upstream even though there is no upstream template.
"""
# XXX CarlosPerelloMarin 20071022: We should move this into browser code.
def makeHTMLID(description):
"""Unique identifier for self, suitable for use in HTML element ids.
Constructs an identifier for use in HTML. This identifier matches the
format parsed by `BaseTranslationView`.
:param description: a keyword to be embedded in the id string, e.g.
"suggestion" or "translation." Must be suitable for use in an
HTML element id.
"""
def markReviewed(reviewer, timestamp=None):
"""Mark this message as reviewed.
Sets the reviewer and review date for this message.
:param reviewer: the person who reviewed the message.
:param timestamp: optional timestamp indicating when the review
happened. Defaults to "now."
"""
class ITranslationMessageSuggestions(Interface):
"""Suggested `ITranslationMessage`s for a `POTMsgSet`.
When displaying `POTMsgSet`s in `CurrentTranslationMessageView`
we display different types of suggestions: non-reviewer translations,
translations that occur in other contexts, and translations in
alternate languages. See
`CurrentTranslationMessageView._buildAllSuggestions` for details.
"""
title = Attribute("The name displayed next to the suggestion, "
"indicating where it came from.")
submissions = Attribute("An iterable of submissions.")
user_is_official_translator = Bool(
title=(u'Whether the user is an official translator.'),
required=True)
class ITranslationMessageSet(Interface):
"""Getting to TranslationMessages from the view code."""
def getByID(id):
"""Return the TranslationMessage with the given ID or None."""
def selectDirect(where=None, order_by=None):
"""Return sequence of `TranslationMessage`s matching arguments.
This is meant for maintenance use. If you find yourself using
it anywhere except in a manually-run script, try something else.
:param where: An SQL WHERE clause describing which messages to
return.
:param order_by: An SQL ORDER BY clause.
"""
|