Mercurial > babel > old > mirror
annotate babel/messages/catalog.py @ 165:eafaa302dde1
Added preliminary catalog updating/merging functionality.
author | cmlenz |
---|---|
date | Fri, 22 Jun 2007 00:33:22 +0000 |
parents | 12e5f21dfcda |
children | 533baef258bb |
rev | line source |
---|---|
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
1 # -*- coding: utf-8 -*- |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
2 # |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
3 # Copyright (C) 2007 Edgewall Software |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
4 # All rights reserved. |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
5 # |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
6 # This software is licensed as described in the file COPYING, which |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
7 # you should have received as part of this distribution. The terms |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
8 # are also available at http://babel.edgewall.org/wiki/License. |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
9 # |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
10 # This software consists of voluntary contributions made by many |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
11 # individuals. For the exact contribution history, see the revision |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
12 # history and logs, available at http://babel.edgewall.org/log/. |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
13 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
14 """Data structures for message catalogs.""" |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
15 |
151
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
133
diff
changeset
|
16 from cgi import parse_header |
69 | 17 from datetime import datetime |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
18 from email import message_from_string |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
19 import re |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
20 try: |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
21 set |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
22 except NameError: |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
23 from sets import Set as set |
69 | 24 import time |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
25 |
69 | 26 from babel import __version__ as VERSION |
66 | 27 from babel.core import Locale |
133
9d58665d134c
Use `dates.format_datetime` for dates in PO(T) header, as `datetime.strftime` produces wrong results on windows.
cmlenz
parents:
123
diff
changeset
|
28 from babel.dates import format_datetime |
69 | 29 from babel.messages.plurals import PLURALS |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
30 from babel.util import odict, LOCALTZ, UTC, FixedOffsetTimezone |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
31 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
32 __all__ = ['Message', 'Catalog'] |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
33 __docformat__ = 'restructuredtext en' |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
34 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
35 PYTHON_FORMAT = re.compile(r'\%(\([\w]+\))?[diouxXeEfFgGcrs]').search |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
36 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
37 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
38 class Message(object): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
39 """Representation of a single message in a catalog.""" |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
40 |
151
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
133
diff
changeset
|
41 def __init__(self, id, string=u'', locations=(), flags=(), auto_comments=(), |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
42 user_comments=()): |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
43 """Create the message object. |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
44 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
45 :param id: the message ID, or a ``(singular, plural)`` tuple for |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
46 pluralizable messages |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
47 :param string: the translated message string, or a |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
48 ``(singular, plural)`` tuple for pluralizable messages |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
49 :param locations: a sequence of ``(filenname, lineno)`` tuples |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
50 :param flags: a set or sequence of flags |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
51 :param auto_comments: a sequence of automatic comments for the message |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
52 :param user_comments: a sequence of user comments for the message |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
53 """ |
109 | 54 self.id = id #: The message ID |
70 | 55 if not string and self.pluralizable: |
56 string = (u'', u'') | |
109 | 57 self.string = string #: The message translation |
72
f5a6bf38df89
Fix for mixed singular/plural messages, follow-up to [70].
cmlenz
parents:
71
diff
changeset
|
58 self.locations = list(locations) |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
59 self.flags = set(flags) |
69 | 60 if id and self.python_format: |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
61 self.flags.add('python-format') |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
62 else: |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
63 self.flags.discard('python-format') |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
64 self.auto_comments = list(auto_comments) |
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
65 self.user_comments = list(user_comments) |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
66 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
67 def __repr__(self): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
68 return '<%s %r>' % (type(self).__name__, self.id) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
69 |
69 | 70 def fuzzy(self): |
71 return 'fuzzy' in self.flags | |
72 fuzzy = property(fuzzy, doc="""\ | |
73 Whether the translation is fuzzy. | |
74 | |
75 >>> Message('foo').fuzzy | |
76 False | |
77 >>> Message('foo', 'foo', flags=['fuzzy']).fuzzy | |
78 True | |
79 | |
80 :type: `bool` | |
81 """) | |
82 | |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
83 def pluralizable(self): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
84 return isinstance(self.id, (list, tuple)) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
85 pluralizable = property(pluralizable, doc="""\ |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
86 Whether the message is plurizable. |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
87 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
88 >>> Message('foo').pluralizable |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
89 False |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
90 >>> Message(('foo', 'bar')).pluralizable |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
91 True |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
92 |
63
a60ecd4a4954
Move `Translations` and `LazyProxy` to new `babel.support` module, which should contain any convenience code that is useful for applications using Babel/I18n, but not used by Babel itself.
cmlenz
parents:
58
diff
changeset
|
93 :type: `bool` |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
94 """) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
95 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
96 def python_format(self): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
97 ids = self.id |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
98 if not isinstance(ids, (list, tuple)): |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
99 ids = [ids] |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
100 return bool(filter(None, [PYTHON_FORMAT(id) for id in ids])) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
101 python_format = property(python_format, doc="""\ |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
102 Whether the message contains Python-style parameters. |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
103 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
104 >>> Message('foo %(name)s bar').python_format |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
105 True |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
106 >>> Message(('foo %(name)s', 'foo %(name)s')).python_format |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
107 True |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
108 |
63
a60ecd4a4954
Move `Translations` and `LazyProxy` to new `babel.support` module, which should contain any convenience code that is useful for applications using Babel/I18n, but not used by Babel itself.
cmlenz
parents:
58
diff
changeset
|
109 :type: `bool` |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
110 """) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
111 |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
112 |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
113 DEFAULT_HEADER = u"""\ |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
114 # Translations template for PROJECT. |
122 | 115 # Copyright (C) YEAR ORGANIZATION |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
116 # This file is distributed under the same license as the PROJECT project. |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
117 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
118 #""" |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
119 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
120 class Catalog(object): |
80
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
121 """Representation of a message catalog.""" |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
122 |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
123 def __init__(self, locale=None, domain=None, header_comment=DEFAULT_HEADER, |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
124 project=None, version=None, copyright_holder=None, |
80
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
125 msgid_bugs_address=None, creation_date=None, |
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
126 revision_date=None, last_translator=None, charset='utf-8'): |
66 | 127 """Initialize the catalog object. |
128 | |
129 :param locale: the locale identifier or `Locale` object, or `None` | |
130 if the catalog is not bound to a locale (which basically | |
131 means it's a template) | |
80
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
132 :param domain: the message domain |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
133 :param header_comment: the header comment as string, or `None` for the |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
134 default header |
80
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
135 :param project: the project's name |
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
136 :param version: the project's version |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
137 :param copyright_holder: the copyright holder of the catalog |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
138 :param msgid_bugs_address: the email address or URL to submit bug |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
139 reports to |
80
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
140 :param creation_date: the date the catalog was created |
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
141 :param revision_date: the date the catalog was revised |
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
142 :param last_translator: the name and email of the last translator |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
143 :param charset: the encoding to use in the output |
66 | 144 """ |
109 | 145 self.domain = domain #: The message domain |
66 | 146 if locale: |
147 locale = Locale.parse(locale) | |
109 | 148 self.locale = locale #: The locale or `None` |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
149 self._header_comment = header_comment |
69 | 150 self._messages = odict() |
151 | |
109 | 152 self.project = project or 'PROJECT' #: The project name |
153 self.version = version or 'VERSION' #: The project version | |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
154 self.copyright_holder = copyright_holder or 'ORGANIZATION' |
80
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
155 self.msgid_bugs_address = msgid_bugs_address or 'EMAIL@ADDRESS' |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
156 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
157 self.last_translator = last_translator or 'FULL NAME <EMAIL@ADDRESS>' |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
158 """Name and email address of the last translator.""" |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
159 |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
89
diff
changeset
|
160 self.charset = charset or 'utf-8' |
86
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
161 |
69 | 162 if creation_date is None: |
99 | 163 creation_date = datetime.now(LOCALTZ) |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
89
diff
changeset
|
164 elif isinstance(creation_date, datetime) and not creation_date.tzinfo: |
99 | 165 creation_date = creation_date.replace(tzinfo=LOCALTZ) |
109 | 166 self.creation_date = creation_date #: Creation date of the template |
69 | 167 if revision_date is None: |
99 | 168 revision_date = datetime.now(LOCALTZ) |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
89
diff
changeset
|
169 elif isinstance(revision_date, datetime) and not revision_date.tzinfo: |
99 | 170 revision_date = revision_date.replace(tzinfo=LOCALTZ) |
109 | 171 self.revision_date = revision_date #: Last revision date of the catalog |
69 | 172 |
109 | 173 def _get_header_comment(self): |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
174 comment = self._header_comment |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
175 comment = comment.replace('PROJECT', self.project) \ |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
176 .replace('VERSION', self.version) \ |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
177 .replace('YEAR', self.revision_date.strftime('%Y')) \ |
122 | 178 .replace('ORGANIZATION', self.copyright_holder) |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
179 if self.locale: |
109 | 180 comment = comment.replace('Translations template', '%s translations' |
181 % self.locale.english_name) | |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
182 return comment |
122 | 183 |
109 | 184 def _set_header_comment(self, string): |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
185 self._header_comment = string |
109 | 186 |
187 header_comment = property(_get_header_comment, _set_header_comment, doc="""\ | |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
188 The header comment for the catalog. |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
189 |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
190 >>> catalog = Catalog(project='Foobar', version='1.0', |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
191 ... copyright_holder='Foo Company') |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
192 >>> print catalog.header_comment |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
193 # Translations template for Foobar. |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
194 # Copyright (C) 2007 Foo Company |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
195 # This file is distributed under the same license as the Foobar project. |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
196 # FIRST AUTHOR <EMAIL@ADDRESS>, 2007. |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
197 # |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
198 |
122 | 199 The header can also be set from a string. Any known upper-case variables |
200 will be replaced when the header is retrieved again: | |
201 | |
202 >>> catalog = Catalog(project='Foobar', version='1.0', | |
203 ... copyright_holder='Foo Company') | |
204 >>> catalog.header_comment = '''\\ | |
205 ... # The POT for my really cool PROJECT project. | |
206 ... # Copyright (C) 1990-2003 ORGANIZATION | |
207 ... # This file is distributed under the same license as the PROJECT | |
208 ... # project. | |
209 ... #''' | |
210 >>> print catalog.header_comment | |
211 # The POT for my really cool Foobar project. | |
212 # Copyright (C) 1990-2003 Foo Company | |
213 # This file is distributed under the same license as the Foobar | |
214 # project. | |
215 # | |
216 | |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
217 :type: `unicode` |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
218 """) |
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
219 |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
220 def _get_mime_headers(self): |
69 | 221 headers = [] |
222 headers.append(('Project-Id-Version', | |
223 '%s %s' % (self.project, self.version))) | |
80
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
224 headers.append(('Report-Msgid-Bugs-To', self.msgid_bugs_address)) |
69 | 225 headers.append(('POT-Creation-Date', |
133
9d58665d134c
Use `dates.format_datetime` for dates in PO(T) header, as `datetime.strftime` produces wrong results on windows.
cmlenz
parents:
123
diff
changeset
|
226 format_datetime(self.creation_date, 'yyyy-MM-dd HH:mmZ', |
9d58665d134c
Use `dates.format_datetime` for dates in PO(T) header, as `datetime.strftime` produces wrong results on windows.
cmlenz
parents:
123
diff
changeset
|
227 locale='en'))) |
69 | 228 if self.locale is None: |
229 headers.append(('PO-Revision-Date', 'YEAR-MO-DA HO:MI+ZONE')) | |
230 headers.append(('Last-Translator', 'FULL NAME <EMAIL@ADDRESS>')) | |
231 headers.append(('Language-Team', 'LANGUAGE <LL@li.org>')) | |
232 else: | |
233 headers.append(('PO-Revision-Date', | |
133
9d58665d134c
Use `dates.format_datetime` for dates in PO(T) header, as `datetime.strftime` produces wrong results on windows.
cmlenz
parents:
123
diff
changeset
|
234 format_datetime(self.revision_date, |
9d58665d134c
Use `dates.format_datetime` for dates in PO(T) header, as `datetime.strftime` produces wrong results on windows.
cmlenz
parents:
123
diff
changeset
|
235 'yyyy-MM-dd HH:mmZ', locale='en'))) |
69 | 236 headers.append(('Last-Translator', self.last_translator)) |
237 headers.append(('Language-Team', '%s <LL@li.org>' % self.locale)) | |
86
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
238 headers.append(('Plural-Forms', self.plural_forms)) |
69 | 239 headers.append(('MIME-Version', '1.0')) |
70 | 240 headers.append(('Content-Type', |
241 'text/plain; charset=%s' % self.charset)) | |
69 | 242 headers.append(('Content-Transfer-Encoding', '8bit')) |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
243 headers.append(('Generated-By', 'Babel %s\n' % VERSION)) |
69 | 244 return headers |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
245 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
246 def _set_mime_headers(self, headers): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
247 for name, value in headers: |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
248 name = name.lower() |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
249 if name == 'project-id-version': |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
250 parts = value.split(' ') |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
251 self.project = ' '.join(parts[:-1]) |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
252 self.version = parts[-1] |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
253 elif name == 'report-msgid-bugs-to': |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
254 self.msgid_bugs_address = value |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
255 elif name == 'last-translator': |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
256 self.last_translator = value |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
257 elif name == 'pot-creation-date': |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
258 # FIXME: this should use dates.parse_datetime as soon as that |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
259 # is ready |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
260 value, tzoffset, _ = re.split('[+-](\d{4})$', value, 1) |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
261 tt = time.strptime(value, '%Y-%m-%d %H:%M') |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
262 ts = time.mktime(tt) |
122 | 263 tzoffset = FixedOffsetTimezone(int(tzoffset[:2]) * 60 + |
264 int(tzoffset[2:])) | |
123 | 265 dt = datetime.fromtimestamp(ts) |
266 self.creation_date = dt.replace(tzinfo=tzoffset) | |
151
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
133
diff
changeset
|
267 elif name == 'content-type': |
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
133
diff
changeset
|
268 mimetype, params = parse_header(value) |
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
133
diff
changeset
|
269 if 'charset' in params: |
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
133
diff
changeset
|
270 self.charset = params['charset'].lower() |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
271 |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
272 mime_headers = property(_get_mime_headers, _set_mime_headers, doc="""\ |
69 | 273 The MIME headers of the catalog, used for the special ``msgid ""`` entry. |
274 | |
275 The behavior of this property changes slightly depending on whether a locale | |
276 is set or not, the latter indicating that the catalog is actually a template | |
277 for actual translations. | |
278 | |
279 Here's an example of the output for such a catalog template: | |
280 | |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
89
diff
changeset
|
281 >>> created = datetime(1990, 4, 1, 15, 30, tzinfo=UTC) |
69 | 282 >>> catalog = Catalog(project='Foobar', version='1.0', |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
89
diff
changeset
|
283 ... creation_date=created) |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
284 >>> for name, value in catalog.mime_headers: |
69 | 285 ... print '%s: %s' % (name, value) |
286 Project-Id-Version: Foobar 1.0 | |
80
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
287 Report-Msgid-Bugs-To: EMAIL@ADDRESS |
69 | 288 POT-Creation-Date: 1990-04-01 15:30+0000 |
289 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE | |
290 Last-Translator: FULL NAME <EMAIL@ADDRESS> | |
291 Language-Team: LANGUAGE <LL@li.org> | |
292 MIME-Version: 1.0 | |
293 Content-Type: text/plain; charset=utf-8 | |
294 Content-Transfer-Encoding: 8bit | |
295 Generated-By: Babel ... | |
296 | |
297 And here's an example of the output when the locale is set: | |
298 | |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
89
diff
changeset
|
299 >>> revised = datetime(1990, 8, 3, 12, 0, tzinfo=UTC) |
69 | 300 >>> catalog = Catalog(locale='de_DE', project='Foobar', version='1.0', |
97
debd9ac3bb4d
Fix for #11 (use local timezone in timestamps of generated POT).
cmlenz
parents:
89
diff
changeset
|
301 ... creation_date=created, revision_date=revised, |
69 | 302 ... last_translator='John Doe <jd@example.com>') |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
303 >>> for name, value in catalog.mime_headers: |
69 | 304 ... print '%s: %s' % (name, value) |
305 Project-Id-Version: Foobar 1.0 | |
80
8e2e9d549693
Fixed the plurals header on `Catalog` which should only be written if it's not a catalog template.
palgarvio
parents:
72
diff
changeset
|
306 Report-Msgid-Bugs-To: EMAIL@ADDRESS |
69 | 307 POT-Creation-Date: 1990-04-01 15:30+0000 |
308 PO-Revision-Date: 1990-08-03 12:00+0000 | |
309 Last-Translator: John Doe <jd@example.com> | |
310 Language-Team: de_DE <LL@li.org> | |
86
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
311 Plural-Forms: nplurals=2; plural=(n != 1) |
69 | 312 MIME-Version: 1.0 |
313 Content-Type: text/plain; charset=utf-8 | |
314 Content-Transfer-Encoding: 8bit | |
315 Generated-By: Babel ... | |
316 | |
317 :type: `list` | |
318 """) | |
319 | |
70 | 320 def num_plurals(self): |
321 num = 2 | |
322 if self.locale: | |
323 if str(self.locale) in PLURALS: | |
324 num = PLURALS[str(self.locale)][0] | |
325 elif self.locale.language in PLURALS: | |
326 num = PLURALS[self.locale.language][0] | |
327 return num | |
86
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
328 num_plurals = property(num_plurals, doc="""\ |
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
329 The number of plurals used by the locale. |
105
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
99
diff
changeset
|
330 |
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
99
diff
changeset
|
331 >>> Catalog(locale='en').num_plurals |
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
99
diff
changeset
|
332 2 |
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
99
diff
changeset
|
333 >>> Catalog(locale='cs_CZ').num_plurals |
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
99
diff
changeset
|
334 3 |
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
99
diff
changeset
|
335 |
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
99
diff
changeset
|
336 :type: `int` |
86
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
337 """) |
70 | 338 |
69 | 339 def plural_forms(self): |
340 num, expr = ('INTEGER', 'EXPRESSION') | |
341 if self.locale: | |
342 if str(self.locale) in PLURALS: | |
343 num, expr = PLURALS[str(self.locale)] | |
344 elif self.locale.language in PLURALS: | |
345 num, expr = PLURALS[self.locale.language] | |
346 return 'nplurals=%s; plural=%s' % (num, expr) | |
347 plural_forms = property(plural_forms, doc="""\ | |
348 Return the plural forms declaration for the locale. | |
349 | |
105
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
99
diff
changeset
|
350 >>> Catalog(locale='en').plural_forms |
69 | 351 'nplurals=2; plural=(n != 1)' |
352 >>> Catalog(locale='pt_BR').plural_forms | |
353 'nplurals=2; plural=(n > 1)' | |
354 | |
355 :type: `str` | |
356 """) | |
357 | |
358 def __contains__(self, id): | |
359 """Return whether the catalog has a message with the specified ID.""" | |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
360 return self._key_for(id) in self._messages |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
361 |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
362 def __len__(self): |
86
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
363 """The number of messages in the catalog. |
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
364 |
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
365 This does not include the special ``msgid ""`` entry. |
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
366 """ |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
367 return len(self._messages) |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
368 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
369 def __iter__(self): |
66 | 370 """Iterates through all the entries in the catalog, in the order they |
371 were added, yielding a `Message` object for every entry. | |
372 | |
373 :rtype: ``iterator`` | |
374 """ | |
69 | 375 buf = [] |
106
2a00e352c986
Merged `write_pot` and `write_po` functions by moving more functionality to the `Catalog` class. This is certainly not perfect yet, but moves us in the right direction.
cmlenz
parents:
105
diff
changeset
|
376 for name, value in self.mime_headers: |
69 | 377 buf.append('%s: %s' % (name, value)) |
378 yield Message('', '\n'.join(buf), flags=set(['fuzzy'])) | |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
379 for key in self._messages: |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
380 yield self._messages[key] |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
381 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
382 def __repr__(self): |
66 | 383 locale = '' |
384 if self.locale: | |
385 locale = ' %s' % self.locale | |
386 return '<%s %r%s>' % (type(self).__name__, self.domain, locale) | |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
387 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
388 def __delitem__(self, id): |
66 | 389 """Delete the message with the specified ID.""" |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
390 key = self._key_for(id) |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
391 if key in self._messages: |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
392 del self._messages[key] |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
393 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
394 def __getitem__(self, id): |
66 | 395 """Return the message with the specified ID. |
396 | |
397 :param id: the message ID | |
398 :return: the message with the specified ID, or `None` if no such message | |
399 is in the catalog | |
69 | 400 :rtype: `Message` |
66 | 401 """ |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
402 return self._messages.get(self._key_for(id)) |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
403 |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
404 def __setitem__(self, id, message): |
66 | 405 """Add or update the message with the specified ID. |
406 | |
407 >>> catalog = Catalog() | |
408 >>> catalog[u'foo'] = Message(u'foo') | |
409 >>> catalog[u'foo'] | |
410 <Message u'foo'> | |
411 | |
412 If a message with that ID is already in the catalog, it is updated | |
413 to include the locations and flags of the new message. | |
414 | |
415 >>> catalog = Catalog() | |
416 >>> catalog[u'foo'] = Message(u'foo', locations=[('main.py', 1)]) | |
417 >>> catalog[u'foo'].locations | |
418 [('main.py', 1)] | |
419 >>> catalog[u'foo'] = Message(u'foo', locations=[('utils.py', 5)]) | |
420 >>> catalog[u'foo'].locations | |
421 [('main.py', 1), ('utils.py', 5)] | |
422 | |
423 :param id: the message ID | |
424 :param message: the `Message` object | |
425 """ | |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
426 assert isinstance(message, Message), 'expected a Message object' |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
427 key = self._key_for(id) |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
428 current = self._messages.get(key) |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
429 if current: |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
430 if message.pluralizable and not current.pluralizable: |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
431 # The new message adds pluralization |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
432 current.id = message.id |
72
f5a6bf38df89
Fix for mixed singular/plural messages, follow-up to [70].
cmlenz
parents:
71
diff
changeset
|
433 current.string = message.string |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
434 current.locations.extend(message.locations) |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
435 current.auto_comments.extend(message.auto_comments) |
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
436 current.user_comments.extend(message.user_comments) |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
437 current.flags |= message.flags |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
438 message = current |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
439 elif id == '': |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
440 # special treatment for the header message |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
441 headers = message_from_string(message.string.encode(self.charset)) |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
442 self.mime_headers = headers.items() |
122 | 443 self.header_comment = '\n'.join(['# %s' % comment for comment |
444 in message.user_comments]) | |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
445 else: |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
446 if isinstance(id, (list, tuple)): |
70 | 447 assert isinstance(message.string, (list, tuple)) |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
448 self._messages[key] = message |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
diff
changeset
|
449 |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
450 def add(self, id, string=None, locations=(), flags=(), auto_comments=(), |
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
451 user_comments=()): |
66 | 452 """Add or update the message with the specified ID. |
453 | |
454 >>> catalog = Catalog() | |
455 >>> catalog.add(u'foo') | |
456 >>> catalog[u'foo'] | |
457 <Message u'foo'> | |
458 | |
459 This method simply constructs a `Message` object with the given | |
460 arguments and invokes `__setitem__` with that object. | |
461 | |
462 :param id: the message ID, or a ``(singular, plural)`` tuple for | |
463 pluralizable messages | |
464 :param string: the translated message string, or a | |
465 ``(singular, plural)`` tuple for pluralizable messages | |
466 :param locations: a sequence of ``(filenname, lineno)`` tuples | |
467 :param flags: a set or sequence of flags | |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
468 :param auto_comments: a sequence of automatic comments |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
469 :param user_comments: a sequence of user comments |
66 | 470 """ |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
471 self[id] = Message(id, string, list(locations), flags, auto_comments, |
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
472 user_comments) |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
473 |
165
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
474 def update(self, template): |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
475 """Update the catalog based on the given template catalog. |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
476 |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
477 >>> from babel.messages import Catalog |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
478 >>> template = Catalog() |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
479 >>> template.add('blue', locations=[('main.py', 100)]) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
480 >>> template.add(('salad', 'salads'), locations=[('util.py', 42)]) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
481 >>> catalog = Catalog(locale='de_DE') |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
482 >>> catalog.add('blue', u'blau', locations=[('main.py', 98)]) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
483 >>> catalog.add('head', u'Kopf', locations=[('util.py', 33)]) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
484 >>> catalog.add(('salad', 'salads'), (u'Salat', u'Salate'), |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
485 ... locations=[('util.py', 38)]) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
486 |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
487 >>> rest = catalog.update(template) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
488 >>> len(catalog) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
489 2 |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
490 |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
491 >>> msg1 = catalog['blue'] |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
492 >>> msg1.string |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
493 u'blau' |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
494 >>> msg1.locations |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
495 [('main.py', 100)] |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
496 |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
497 >>> msg2 = catalog['salad'] |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
498 >>> msg2.string |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
499 (u'Salat', u'Salate') |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
500 >>> msg2.locations |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
501 [('util.py', 42)] |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
502 |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
503 >>> 'head' in catalog |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
504 False |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
505 >>> rest |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
506 [<Message 'head'>] |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
507 |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
508 :param template: the reference catalog, usually read from a POT file |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
509 :return: a list of `Message` objects that the catalog contained before |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
510 the updated, but couldn't be found in the template |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
511 """ |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
512 rest = odict([(message.id, message) for message in self if message.id]) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
513 messages = self._messages |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
514 self._messages = odict() |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
515 |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
516 for message in template: |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
517 if message.id: |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
518 key = self._key_for(message.id) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
519 if key in messages: |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
520 oldmsg = messages.pop(key) |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
521 message.string = oldmsg.string |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
522 message.flags |= oldmsg.flags |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
523 self[message.id] = message |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
524 del rest[message.id] |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
525 else: |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
526 for oldmsg in messages: |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
527 # TODO: fuzzy matching |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
528 pass |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
529 else: |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
530 self[message.id] = message |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
531 |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
532 return rest.values() |
eafaa302dde1
Added preliminary catalog updating/merging functionality.
cmlenz
parents:
151
diff
changeset
|
533 |
71
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
534 def _key_for(self, id): |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
535 """The key for a message is just the singular ID even for pluralizable |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
536 messages. |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
537 """ |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
538 key = id |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
539 if isinstance(key, (list, tuple)): |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
540 key = id[0] |
b260ffa01a2d
Message catalogs can have multiple messages with the same ID, where some of them have plural strings, and others don't. Still the same message.
cmlenz
parents:
70
diff
changeset
|
541 return key |