Mercurial > babel > old > babel-test
annotate babel/messages/pofile.py @ 379:1c0915da48c6 stable-0.9.x
Ported [407:415/trunk] back to 0.9.x branch.
author | cmlenz |
---|---|
date | Tue, 08 Jul 2008 21:01:28 +0000 |
parents | c2ae38340540 |
children | c6babc3bbc10 |
rev | line source |
---|---|
1 | 1 # -*- coding: utf-8 -*- |
2 # | |
3 # Copyright (C) 2007 Edgewall Software | |
4 # All rights reserved. | |
5 # | |
6 # This software is licensed as described in the file COPYING, which | |
7 # you should have received as part of this distribution. The terms | |
8 # are also available at http://babel.edgewall.org/wiki/License. | |
9 # | |
10 # This software consists of voluntary contributions made by many | |
11 # individuals. For the exact contribution history, see the revision | |
12 # history and logs, available at http://babel.edgewall.org/log/. | |
13 | |
14 """Reading and writing of files in the ``gettext`` PO (portable object) | |
15 format. | |
16 | |
17 :see: `The Format of PO Files | |
18 <http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files>`_ | |
19 """ | |
20 | |
5
50ad95bee876
* The creation-date header in generated PO files now includes the timezone offset.
cmlenz
parents:
1
diff
changeset
|
21 from datetime import date, datetime |
134 | 22 import os |
1 | 23 import re |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
24 try: |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
25 set |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
26 except NameError: |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
27 from sets import Set as set |
1 | 28 |
29 from babel import __version__ as VERSION | |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
30 from babel.messages.catalog import Catalog, Message |
316 | 31 from babel.util import wraptext, LOCALTZ |
1 | 32 |
178
4407c6d1b7d7
Minor change to what symbols are ?exported?, primarily for the generated docs.
cmlenz
parents:
175
diff
changeset
|
33 __all__ = ['read_po', 'write_po'] |
161 | 34 __docformat__ = 'restructuredtext en' |
158 | 35 |
36 def unescape(string): | |
37 r"""Reverse `escape` the given string. | |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
38 |
158 | 39 >>> print unescape('"Say:\\n \\"hello, world!\\"\\n"') |
40 Say: | |
41 "hello, world!" | |
42 <BLANKLINE> | |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
43 |
158 | 44 :param string: the string to unescape |
45 :return: the unescaped string | |
46 :rtype: `str` or `unicode` | |
47 """ | |
48 return string[1:-1].replace('\\\\', '\\') \ | |
49 .replace('\\t', '\t') \ | |
50 .replace('\\r', '\r') \ | |
51 .replace('\\n', '\n') \ | |
52 .replace('\\"', '\"') | |
53 | |
54 def denormalize(string): | |
55 r"""Reverse the normalization done by the `normalize` function. | |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
56 |
158 | 57 >>> print denormalize(r'''"" |
58 ... "Say:\n" | |
59 ... " \"hello, world!\"\n"''') | |
60 Say: | |
61 "hello, world!" | |
62 <BLANKLINE> | |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
63 |
158 | 64 >>> print denormalize(r'''"" |
65 ... "Say:\n" | |
66 ... " \"Lorem ipsum dolor sit " | |
67 ... "amet, consectetur adipisicing" | |
68 ... " elit, \"\n"''') | |
69 Say: | |
70 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " | |
71 <BLANKLINE> | |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
72 |
158 | 73 :param string: the string to denormalize |
74 :return: the denormalized string | |
75 :rtype: `unicode` or `str` | |
76 """ | |
77 if string.startswith('""'): | |
78 lines = [] | |
79 for line in string.splitlines()[1:]: | |
80 lines.append(unescape(line)) | |
81 return ''.join(lines) | |
82 else: | |
83 return unescape(string) | |
1 | 84 |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
85 def read_po(fileobj, locale=None, domain=None, ignore_obsolete=False): |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
86 """Read messages from a ``gettext`` PO (portable object) file from the given |
64 | 87 file-like object and return a `Catalog`. |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
88 |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
89 >>> from StringIO import StringIO |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
90 >>> buf = StringIO(''' |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
91 ... #: main.py:1 |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
92 ... #, fuzzy, python-format |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
93 ... msgid "foo %(name)s" |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
94 ... msgstr "" |
21
ddfac856c34f
Change pot header's first line, "Translations Template for %%(project)s." instead of "SOME DESCRIPTIVE TITLE.". '''`project`''' and '''`version`''' now default to '''PROJECT''' and '''VERSION''' respectively. Fixed a bug regarding '''Content-Transfer-Encoding''', it shouldn't be the charset, and we're defaulting to `8bit` untill someone complains.
palgarvio
parents:
17
diff
changeset
|
95 ... |
94
b176f325d127
Updated `read_po` to add user comments besides just auto comments.
palgarvio
parents:
84
diff
changeset
|
96 ... # A user comment |
b176f325d127
Updated `read_po` to add user comments besides just auto comments.
palgarvio
parents:
84
diff
changeset
|
97 ... #. An auto comment |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
98 ... #: main.py:3 |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
99 ... msgid "bar" |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
100 ... msgid_plural "baz" |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
101 ... msgstr[0] "" |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
102 ... msgstr[1] "" |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
103 ... ''') |
64 | 104 >>> catalog = read_po(buf) |
104
22f222e23b86
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:
103
diff
changeset
|
105 >>> catalog.revision_date = datetime(2007, 04, 01) |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
106 |
64 | 107 >>> for message in catalog: |
67 | 108 ... if message.id: |
109 ... print (message.id, message.string) | |
105
f744dd56573d
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
104
diff
changeset
|
110 ... print ' ', (message.locations, message.flags) |
f744dd56573d
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
104
diff
changeset
|
111 ... print ' ', (message.user_comments, message.auto_comments) |
149
ba5150e9544e
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
134
diff
changeset
|
112 (u'foo %(name)s', '') |
ba5150e9544e
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
134
diff
changeset
|
113 ([(u'main.py', 1)], set([u'fuzzy', u'python-format'])) |
105
f744dd56573d
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
104
diff
changeset
|
114 ([], []) |
149
ba5150e9544e
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
134
diff
changeset
|
115 ((u'bar', u'baz'), ('', '')) |
ba5150e9544e
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
134
diff
changeset
|
116 ([(u'main.py', 3)], set([])) |
ba5150e9544e
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
134
diff
changeset
|
117 ([u'A user comment'], [u'An auto comment']) |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
118 |
1 | 119 :param fileobj: the file-like object to read the PO file from |
196
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
120 :param locale: the locale identifier or `Locale` object, or `None` |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
121 if the catalog is not bound to a locale (which basically |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
122 means it's a template) |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
123 :param domain: the message domain |
227 | 124 :param ignore_obsolete: whether to ignore obsolete messages in the input |
1 | 125 :return: an iterator over ``(message, translation, location)`` tuples |
126 :rtype: ``iterator`` | |
127 """ | |
196
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
128 catalog = Catalog(locale=locale, domain=domain) |
64 | 129 |
196
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
130 counter = [0] |
220
677147547e2d
Added infrastructure for adding catalog checkers, and implement a checker that validations Python format parameters in translations, closing #19.
cmlenz
parents:
203
diff
changeset
|
131 offset = [0] |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
132 messages = [] |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
133 translations = [] |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
134 locations = [] |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
135 flags = [] |
105
f744dd56573d
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
104
diff
changeset
|
136 user_comments = [] |
f744dd56573d
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
104
diff
changeset
|
137 auto_comments = [] |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
138 obsolete = [False] |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
139 in_msgid = [False] |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
140 in_msgstr = [False] |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
141 |
64 | 142 def _add_message(): |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
143 translations.sort() |
64 | 144 if len(messages) > 1: |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
145 msgid = tuple([denormalize(m) for m in messages]) |
64 | 146 else: |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
147 msgid = denormalize(messages[0]) |
379 | 148 if isinstance(msgid, (list, tuple)): |
149 string = [] | |
150 for idx in range(catalog.num_plurals): | |
151 try: | |
152 string.append(translations[idx]) | |
153 except IndexError: | |
154 string.append((idx, '')) | |
155 string = tuple([denormalize(t[1]) for t in string]) | |
64 | 156 else: |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
157 string = denormalize(translations[0][1]) |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
158 message = Message(msgid, string, list(locations), set(flags), |
227 | 159 auto_comments, user_comments, lineno=offset[0] + 1) |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
160 if obsolete[0]: |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
161 if not ignore_obsolete: |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
162 catalog.obsolete[msgid] = message |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
163 else: |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
164 catalog[msgid] = message |
84
4ff9cc26c11b
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
80
diff
changeset
|
165 del messages[:]; del translations[:]; del locations[:]; |
105
f744dd56573d
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
104
diff
changeset
|
166 del flags[:]; del auto_comments[:]; del user_comments[:] |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
167 obsolete[0] = False |
196
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
168 counter[0] += 1 |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
169 |
220
677147547e2d
Added infrastructure for adding catalog checkers, and implement a checker that validations Python format parameters in translations, closing #19.
cmlenz
parents:
203
diff
changeset
|
170 def _process_message_line(lineno, line): |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
171 if line.startswith('msgid_plural'): |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
172 in_msgid[0] = True |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
173 msg = line[12:].lstrip() |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
174 messages.append(msg) |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
175 elif line.startswith('msgid'): |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
176 in_msgid[0] = True |
220
677147547e2d
Added infrastructure for adding catalog checkers, and implement a checker that validations Python format parameters in translations, closing #19.
cmlenz
parents:
203
diff
changeset
|
177 offset[0] = lineno |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
178 txt = line[5:].lstrip() |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
179 if messages: |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
180 _add_message() |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
181 messages.append(txt) |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
182 elif line.startswith('msgstr'): |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
183 in_msgid[0] = False |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
184 in_msgstr[0] = True |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
185 msg = line[6:].lstrip() |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
186 if msg.startswith('['): |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
187 idx, msg = msg[1:].split(']') |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
188 translations.append([int(idx), msg.lstrip()]) |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
189 else: |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
190 translations.append([0, msg]) |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
191 elif line.startswith('"'): |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
192 if in_msgid[0]: |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
193 messages[-1] += u'\n' + line.rstrip() |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
194 elif in_msgstr[0]: |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
195 translations[-1][1] += u'\n' + line.rstrip() |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
196 |
220
677147547e2d
Added infrastructure for adding catalog checkers, and implement a checker that validations Python format parameters in translations, closing #19.
cmlenz
parents:
203
diff
changeset
|
197 for lineno, line in enumerate(fileobj.readlines()): |
149
ba5150e9544e
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
134
diff
changeset
|
198 line = line.strip().decode(catalog.charset) |
1 | 199 if line.startswith('#'): |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
200 in_msgid[0] = in_msgstr[0] = False |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
201 if messages and translations: |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
202 _add_message() |
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
203 if line[1:].startswith(':'): |
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
204 for location in line[2:].lstrip().split(): |
369 | 205 pos = location.rfind(':') |
206 if pos >= 0: | |
207 try: | |
208 lineno = int(location[pos + 1:]) | |
209 except ValueError: | |
210 continue | |
211 locations.append((location[:pos], lineno)) | |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
212 elif line[1:].startswith(','): |
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
213 for flag in line[2:].lstrip().split(','): |
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
214 flags.append(flag.strip()) |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
215 elif line[1:].startswith('~'): |
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
216 obsolete[0] = True |
220
677147547e2d
Added infrastructure for adding catalog checkers, and implement a checker that validations Python format parameters in translations, closing #19.
cmlenz
parents:
203
diff
changeset
|
217 _process_message_line(lineno, line[2:].lstrip()) |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
218 elif line[1:].startswith('.'): |
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
219 # These are called auto-comments |
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
220 comment = line[2:].strip() |
199
ace575fff5ac
Handle obsolete messages when parsing catalogs. Closes #32.
cmlenz
parents:
196
diff
changeset
|
221 if comment: # Just check that we're not adding empty comments |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
222 auto_comments.append(comment) |
120 | 223 else: |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
224 # These are called user comments |
120 | 225 user_comments.append(line[1:].strip()) |
104
22f222e23b86
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:
103
diff
changeset
|
226 else: |
220
677147547e2d
Added infrastructure for adding catalog checkers, and implement a checker that validations Python format parameters in translations, closing #19.
cmlenz
parents:
203
diff
changeset
|
227 _process_message_line(lineno, line) |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
228 |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
229 if messages: |
64 | 230 _add_message() |
196
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
231 |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
232 # No actual messages found, but there was some info in comments, from which |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
233 # we'll construct an empty header message |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
234 elif not counter[0] and (flags or user_comments or auto_comments): |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
235 messages.append(u'') |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
236 translations.append([0, u'']) |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
237 _add_message() |
93a922d31eca
Fix for #35, and a minor improvement to how we parse the catalog fuzzy bit.
cmlenz
parents:
191
diff
changeset
|
238 |
64 | 239 return catalog |
1 | 240 |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
241 WORD_SEP = re.compile('(' |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
242 r'\s+|' # any whitespace |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
243 r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
244 r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w)' # em-dash |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
245 ')') |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
246 |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
247 def escape(string): |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
248 r"""Escape the given string so that it can be included in double-quoted |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
249 strings in ``PO`` files. |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
250 |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
251 >>> escape('''Say: |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
252 ... "hello, world!" |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
253 ... ''') |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
254 '"Say:\\n \\"hello, world!\\"\\n"' |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
255 |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
256 :param string: the string to escape |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
257 :return: the escaped string |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
258 :rtype: `str` or `unicode` |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
259 """ |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
260 return '"%s"' % string.replace('\\', '\\\\') \ |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
261 .replace('\t', '\\t') \ |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
262 .replace('\r', '\\r') \ |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
263 .replace('\n', '\\n') \ |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
264 .replace('\"', '\\"') |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
265 |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
266 def normalize(string, prefix='', width=76): |
106
9b22b36066f6
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
105
diff
changeset
|
267 r"""Convert a string into a format that is appropriate for .po files. |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
268 |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
269 >>> print normalize('''Say: |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
270 ... "hello, world!" |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
271 ... ''', width=None) |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
272 "" |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
273 "Say:\n" |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
274 " \"hello, world!\"\n" |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
275 |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
276 >>> print normalize('''Say: |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
277 ... "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
278 ... ''', width=32) |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
279 "" |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
280 "Say:\n" |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
281 " \"Lorem ipsum dolor sit " |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
282 "amet, consectetur adipisicing" |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
283 " elit, \"\n" |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
284 |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
285 :param string: the string to normalize |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
286 :param prefix: a string that should be prepended to every line |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
287 :param width: the maximum line width; use `None`, 0, or a negative number |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
288 to completely disable line wrapping |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
289 :return: the normalized string |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
290 :rtype: `unicode` |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
291 """ |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
292 if width and width > 0: |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
293 prefixlen = len(prefix) |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
294 lines = [] |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
295 for idx, line in enumerate(string.splitlines(True)): |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
296 if len(escape(line)) + prefixlen > width: |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
297 chunks = WORD_SEP.split(line) |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
298 chunks.reverse() |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
299 while chunks: |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
300 buf = [] |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
301 size = 2 |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
302 while chunks: |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
303 l = len(escape(chunks[-1])) - 2 + prefixlen |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
304 if size + l < width: |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
305 buf.append(chunks.pop()) |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
306 size += l |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
307 else: |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
308 if not buf: |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
309 # handle long chunks by putting them on a |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
310 # separate line |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
311 buf.append(chunks.pop()) |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
312 break |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
313 lines.append(u''.join(buf)) |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
314 else: |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
315 lines.append(line) |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
316 else: |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
317 lines = string.splitlines(True) |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
318 |
67 | 319 if len(lines) <= 1: |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
320 return escape(string) |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
321 |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
322 # Remove empty trailing line |
67 | 323 if lines and not lines[-1]: |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
324 del lines[-1] |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
325 lines[-1] += '\n' |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
326 return u'""\n' + u'\n'.join([(prefix + escape(l)) for l in lines]) |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
327 |
104
22f222e23b86
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:
103
diff
changeset
|
328 def write_po(fileobj, catalog, width=76, no_location=False, omit_header=False, |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
329 sort_output=False, sort_by_file=False, ignore_obsolete=False, |
203 | 330 include_previous=False): |
56
27fba894d3ca
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
55
diff
changeset
|
331 r"""Write a ``gettext`` PO (portable object) template file for a given |
27fba894d3ca
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
55
diff
changeset
|
332 message catalog to the provided file-like object. |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
333 |
56
27fba894d3ca
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
55
diff
changeset
|
334 >>> catalog = Catalog() |
27fba894d3ca
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
55
diff
changeset
|
335 >>> catalog.add(u'foo %(name)s', locations=[('main.py', 1)], |
27fba894d3ca
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
55
diff
changeset
|
336 ... flags=('fuzzy',)) |
27fba894d3ca
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
55
diff
changeset
|
337 >>> catalog.add((u'bar', u'baz'), locations=[('main.py', 3)]) |
1 | 338 >>> from StringIO import StringIO |
339 >>> buf = StringIO() | |
104
22f222e23b86
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:
103
diff
changeset
|
340 >>> write_po(buf, catalog, omit_header=True) |
1 | 341 >>> print buf.getvalue() |
342 #: main.py:1 | |
6
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
343 #, fuzzy, python-format |
1801bc2b60ca
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
5
diff
changeset
|
344 msgid "foo %(name)s" |
1 | 345 msgstr "" |
346 <BLANKLINE> | |
347 #: main.py:3 | |
348 msgid "bar" | |
349 msgid_plural "baz" | |
350 msgstr[0] "" | |
351 msgstr[1] "" | |
352 <BLANKLINE> | |
353 <BLANKLINE> | |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
354 |
1 | 355 :param fileobj: the file-like object to write to |
67 | 356 :param catalog: the `Catalog` instance |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
357 :param width: the maximum line width for the generated output; use `None`, |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
358 0, or a negative number to completely disable line wrapping |
1 | 359 :param no_location: do not emit a location comment for every message |
360 :param omit_header: do not include the ``msgid ""`` entry at the top of the | |
361 output | |
227 | 362 :param sort_output: whether to sort the messages in the output by msgid |
363 :param sort_by_file: whether to sort the messages in the output by their | |
364 locations | |
365 :param ignore_obsolete: whether to ignore obsolete messages and not include | |
366 them in the output; by default they are included as | |
367 comments | |
203 | 368 :param include_previous: include the old msgid as a comment when |
229 | 369 updating the catalog |
1 | 370 """ |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
371 def _normalize(key, prefix=''): |
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
372 return normalize(key, prefix=prefix, width=width) \ |
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
373 .encode(catalog.charset, 'backslashreplace') |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
374 |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
375 def _write(text): |
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
376 if isinstance(text, unicode): |
102
eb0d9591d555
Project name and version, and the charset are available via the `Catalog` object, and do not need to be passed to `write_pot()`.
cmlenz
parents:
97
diff
changeset
|
377 text = text.encode(catalog.charset) |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
378 fileobj.write(text) |
1 | 379 |
181
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
380 def _write_comment(comment, prefix=''): |
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
381 lines = comment |
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
382 if width and width > 0: |
316 | 383 lines = wraptext(comment, width) |
181
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
384 for line in lines: |
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
385 _write('#%s %s\n' % (prefix, line.strip())) |
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
386 |
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
387 def _write_message(message, prefix=''): |
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
388 if isinstance(message.id, (list, tuple)): |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
389 _write('%smsgid %s\n' % (prefix, _normalize(message.id[0], prefix))) |
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
390 _write('%smsgid_plural %s\n' % ( |
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
391 prefix, _normalize(message.id[1], prefix) |
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
392 )) |
379 | 393 |
394 for idx in range(catalog.num_plurals): | |
395 try: | |
396 string = message.string[idx] | |
397 except IndexError: | |
398 string = '' | |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
399 _write('%smsgstr[%d] %s\n' % ( |
379 | 400 prefix, idx, _normalize(string, prefix) |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
401 )) |
181
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
402 else: |
190
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
403 _write('%smsgid %s\n' % (prefix, _normalize(message.id, prefix))) |
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
404 _write('%smsgstr %s\n' % ( |
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
405 prefix, _normalize(message.string or '', prefix) |
84193e6612f8
Correctly write out obsolete messages spanning multiple lines. Fixes #33.
cmlenz
parents:
181
diff
changeset
|
406 )) |
181
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
407 |
104
22f222e23b86
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:
103
diff
changeset
|
408 messages = list(catalog) |
71 | 409 if sort_output: |
248
bedaaeadc1db
add a __cmp__ to Message that correctly sorts by id, taking into account plurals
pjenvey
parents:
229
diff
changeset
|
410 messages.sort() |
71 | 411 elif sort_by_file: |
412 messages.sort(lambda x,y: cmp(x.locations, y.locations)) | |
68 | 413 |
71 | 414 for message in messages: |
67 | 415 if not message.id: # This is the header "message" |
416 if omit_header: | |
417 continue | |
104
22f222e23b86
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:
103
diff
changeset
|
418 comment_header = catalog.header_comment |
103
7cdf89eb9007
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
102
diff
changeset
|
419 if width and width > 0: |
7cdf89eb9007
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
102
diff
changeset
|
420 lines = [] |
104
22f222e23b86
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:
103
diff
changeset
|
421 for line in comment_header.splitlines(): |
316 | 422 lines += wraptext(line, width=width, |
423 subsequent_indent='# ') | |
104
22f222e23b86
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:
103
diff
changeset
|
424 comment_header = u'\n'.join(lines) + u'\n' |
22f222e23b86
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:
103
diff
changeset
|
425 _write(comment_header) |
102
eb0d9591d555
Project name and version, and the charset are available via the `Catalog` object, and do not need to be passed to `write_pot()`.
cmlenz
parents:
97
diff
changeset
|
426 |
227 | 427 for comment in message.user_comments: |
181
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
428 _write_comment(comment) |
227 | 429 for comment in message.auto_comments: |
181
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
430 _write_comment(comment, prefix='.') |
1 | 431 |
432 if not no_location: | |
134 | 433 locs = u' '.join([u'%s:%d' % (filename.replace(os.sep, '/'), lineno) |
434 for filename, lineno in message.locations]) | |
181
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
435 _write_comment(locs, prefix=':') |
56
27fba894d3ca
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
55
diff
changeset
|
436 if message.flags: |
27fba894d3ca
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
55
diff
changeset
|
437 _write('#%s\n' % ', '.join([''] + list(message.flags))) |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
438 |
203 | 439 if message.previous_id and include_previous: |
310 | 440 _write_comment('msgid %s' % _normalize(message.previous_id[0]), |
203 | 441 prefix='|') |
442 if len(message.previous_id) > 1: | |
310 | 443 _write_comment('msgid_plural %s' % _normalize( |
203 | 444 message.previous_id[1] |
445 ), prefix='|') | |
200
2983c718f6e2
Added `--no-fuzzy-matching` to the frontends and also `--previous` which adds the old msgid's as comments. The latest closes #31.
palgarvio
parents:
199
diff
changeset
|
446 |
181
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
447 _write_message(message) |
24
4fad20ab7cca
Reimplement line wrapping for PO writing (as the `textwrap` module is too destructive with white space) and move it to the `normalize` function (which was already doing some handling of line breaks).
cmlenz
parents:
23
diff
changeset
|
448 _write('\n') |
181
9a1acb41e7dd
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
178
diff
changeset
|
449 |
191
cf09490f22b3
Add an option to the frontend commands for catalog updating that removes completely any obsolete messages, instead of putting them comments.
cmlenz
parents:
190
diff
changeset
|
450 if not ignore_obsolete: |
cf09490f22b3
Add an option to the frontend commands for catalog updating that removes completely any obsolete messages, instead of putting them comments.
cmlenz
parents:
190
diff
changeset
|
451 for message in catalog.obsolete.values(): |
227 | 452 for comment in message.user_comments: |
191
cf09490f22b3
Add an option to the frontend commands for catalog updating that removes completely any obsolete messages, instead of putting them comments.
cmlenz
parents:
190
diff
changeset
|
453 _write_comment(comment) |
cf09490f22b3
Add an option to the frontend commands for catalog updating that removes completely any obsolete messages, instead of putting them comments.
cmlenz
parents:
190
diff
changeset
|
454 _write_message(message, prefix='#~ ') |
cf09490f22b3
Add an option to the frontend commands for catalog updating that removes completely any obsolete messages, instead of putting them comments.
cmlenz
parents:
190
diff
changeset
|
455 _write('\n') |