Mercurial > babel > old > mirror
annotate babel/messages/pofile.py @ 183:e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
author | cmlenz |
---|---|
date | Thu, 28 Jun 2007 10:28:25 +0000 |
parents | 7e88950ab661 |
children | 8f5805197198 |
rev | line source |
---|---|
3 | 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 | |
7
8d7b3077e6d1
* The creation-date header in generated PO files now includes the timezone offset.
cmlenz
parents:
3
diff
changeset
|
21 from datetime import date, datetime |
136 | 22 import os |
3 | 23 import re |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
24 try: |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
25 set |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
26 except NameError: |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
27 from sets import Set as set |
105
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
104
diff
changeset
|
28 from textwrap import wrap |
3 | 29 |
30 from babel import __version__ as VERSION | |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
57
diff
changeset
|
31 from babel.messages.catalog import Catalog |
99 | 32 from babel.util import LOCALTZ |
3 | 33 |
180
7e88950ab661
Minor change to what symbols are ?exported?, primarily for the generated docs.
cmlenz
parents:
177
diff
changeset
|
34 __all__ = ['read_po', 'write_po'] |
163 | 35 __docformat__ = 'restructuredtext en' |
160 | 36 |
37 def unescape(string): | |
38 r"""Reverse `escape` the given string. | |
39 | |
40 >>> print unescape('"Say:\\n \\"hello, world!\\"\\n"') | |
41 Say: | |
42 "hello, world!" | |
43 <BLANKLINE> | |
44 | |
45 :param string: the string to unescape | |
46 :return: the unescaped string | |
47 :rtype: `str` or `unicode` | |
48 """ | |
49 return string[1:-1].replace('\\\\', '\\') \ | |
50 .replace('\\t', '\t') \ | |
51 .replace('\\r', '\r') \ | |
52 .replace('\\n', '\n') \ | |
53 .replace('\\"', '\"') | |
54 | |
55 def denormalize(string): | |
56 r"""Reverse the normalization done by the `normalize` function. | |
57 | |
58 >>> print denormalize(r'''"" | |
59 ... "Say:\n" | |
60 ... " \"hello, world!\"\n"''') | |
61 Say: | |
62 "hello, world!" | |
63 <BLANKLINE> | |
64 | |
65 >>> print denormalize(r'''"" | |
66 ... "Say:\n" | |
67 ... " \"Lorem ipsum dolor sit " | |
68 ... "amet, consectetur adipisicing" | |
69 ... " elit, \"\n"''') | |
70 Say: | |
71 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " | |
72 <BLANKLINE> | |
73 | |
74 :param string: the string to denormalize | |
75 :return: the denormalized string | |
76 :rtype: `unicode` or `str` | |
77 """ | |
78 if string.startswith('""'): | |
79 lines = [] | |
80 for line in string.splitlines()[1:]: | |
81 lines.append(unescape(line)) | |
82 return ''.join(lines) | |
83 else: | |
84 return unescape(string) | |
3 | 85 |
86 def read_po(fileobj): | |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
87 """Read messages from a ``gettext`` PO (portable object) file from the given |
66 | 88 file-like object and return a `Catalog`. |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
89 |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
90 >>> from StringIO import StringIO |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
91 >>> buf = StringIO(''' |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
92 ... #: main.py:1 |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
93 ... #, fuzzy, python-format |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
94 ... msgid "foo %(name)s" |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
95 ... msgstr "" |
23
f828705c3bce
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:
19
diff
changeset
|
96 ... |
96
6c07c38e23aa
Updated `read_po` to add user comments besides just auto comments.
palgarvio
parents:
86
diff
changeset
|
97 ... # A user comment |
6c07c38e23aa
Updated `read_po` to add user comments besides just auto comments.
palgarvio
parents:
86
diff
changeset
|
98 ... #. An auto comment |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
99 ... #: main.py:3 |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
100 ... msgid "bar" |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
101 ... msgid_plural "baz" |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
102 ... msgstr[0] "" |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
103 ... msgstr[1] "" |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
104 ... ''') |
66 | 105 >>> catalog = read_po(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
|
106 >>> catalog.revision_date = datetime(2007, 04, 01) |
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
|
107 |
66 | 108 >>> for message in catalog: |
69 | 109 ... if message.id: |
110 ... print (message.id, message.string) | |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
111 ... print ' ', (message.locations, message.flags) |
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
112 ... print ' ', (message.user_comments, message.auto_comments) |
151
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
136
diff
changeset
|
113 (u'foo %(name)s', '') |
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
136
diff
changeset
|
114 ([(u'main.py', 1)], set([u'fuzzy', u'python-format'])) |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
115 ([], []) |
151
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
136
diff
changeset
|
116 ((u'bar', u'baz'), ('', '')) |
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
136
diff
changeset
|
117 ([(u'main.py', 3)], set([])) |
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
136
diff
changeset
|
118 ([u'A user comment'], [u'An auto comment']) |
3 | 119 |
120 :param fileobj: the file-like object to read the PO file from | |
121 :return: an iterator over ``(message, translation, location)`` tuples | |
122 :rtype: ``iterator`` | |
123 """ | |
66 | 124 catalog = Catalog() |
125 | |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
126 messages = [] |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
127 translations = [] |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
128 locations = [] |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
129 flags = [] |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
130 user_comments = [] |
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
131 auto_comments = [] |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
132 in_msgid = in_msgstr = False |
177
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
133 fuzzy_header = False |
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
134 in_header = True |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
135 |
66 | 136 def _add_message(): |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
137 translations.sort() |
66 | 138 if len(messages) > 1: |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
139 msgid = tuple([denormalize(m) for m in messages]) |
66 | 140 else: |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
141 msgid = denormalize(messages[0]) |
66 | 142 if len(translations) > 1: |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
143 string = tuple([denormalize(t[1]) for t in translations]) |
66 | 144 else: |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
145 string = denormalize(translations[0][1]) |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
146 catalog.add(msgid, string, list(locations), set(flags), |
110 | 147 list(auto_comments), list(user_comments)) |
86
8a703ecdba91
Some cosmetic changes for the new translator comments support.
cmlenz
parents:
82
diff
changeset
|
148 del messages[:]; del translations[:]; del locations[:]; |
107
4b42e23644e5
`Message`, `read_po` and `write_po` now all handle user/auto comments correctly.
palgarvio
parents:
106
diff
changeset
|
149 del flags[:]; del auto_comments[:]; del user_comments[:] |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
150 |
3 | 151 for line in fileobj.readlines(): |
151
12e5f21dfcda
Respect charset specified in PO headers in `read_po()`. Fixes #17.
cmlenz
parents:
136
diff
changeset
|
152 line = line.strip().decode(catalog.charset) |
3 | 153 if line.startswith('#'): |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
154 in_msgid = in_msgstr = False |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
155 if messages: |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
156 _add_message() |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
157 if line[1:].startswith(':'): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
158 for location in line[2:].lstrip().split(): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
159 filename, lineno = location.split(':', 1) |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
160 locations.append((filename, int(lineno))) |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
161 elif line[1:].startswith(','): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
162 for flag in line[2:].lstrip().split(','): |
177
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
163 if in_header: |
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
164 if flag.strip() == 'fuzzy': |
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
165 fuzzy_header = True |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
166 flags.append(flag.strip()) |
177
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
167 |
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
168 |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
169 elif line[1:].startswith('.'): |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
170 # These are called auto-comments |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
171 comment = line[2:].strip() |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
172 if comment: |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
173 # Just check that we're not adding empty comments |
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
174 auto_comments.append(comment) |
122 | 175 else: |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
176 # These are called user comments |
122 | 177 user_comments.append(line[1:].strip()) |
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
|
178 else: |
3 | 179 if line.startswith('msgid_plural'): |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
180 in_msgid = True |
3 | 181 msg = line[12:].lstrip() |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
182 messages.append(msg) |
3 | 183 elif line.startswith('msgid'): |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
184 in_msgid = True |
177
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
185 txt = line[5:].lstrip() |
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
186 if txt == '""': |
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
187 in_header = True |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
188 if messages: |
66 | 189 _add_message() |
177
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
190 messages.append(txt) |
3 | 191 elif line.startswith('msgstr'): |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
192 in_msgid = False |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
193 in_msgstr = True |
3 | 194 msg = line[6:].lstrip() |
195 if msg.startswith('['): | |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
196 idx, msg = msg[1:].split(']') |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
197 translations.append([int(idx), msg.lstrip()]) |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
198 else: |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
199 translations.append([0, msg]) |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
200 elif line.startswith('"'): |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
201 if in_msgid: |
177
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
202 in_header = False |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
203 messages[-1] += u'\n' + line.rstrip() |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
204 elif in_msgstr: |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
205 translations[-1][1] += u'\n' + line.rstrip() |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
206 |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
207 if messages: |
66 | 208 _add_message() |
177
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
209 |
47f6c31e9a24
Changed the `__repr__` output to include the flags(it can be changed back, but it was usefull to implement the fuzzy header parsing).
palgarvio
parents:
163
diff
changeset
|
210 catalog.fuzzy = fuzzy_header |
66 | 211 return catalog |
3 | 212 |
26
93eaa2f4a0a2
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:
25
diff
changeset
|
213 WORD_SEP = re.compile('(' |
93eaa2f4a0a2
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:
25
diff
changeset
|
214 r'\s+|' # any whitespace |
93eaa2f4a0a2
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:
25
diff
changeset
|
215 r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words |
93eaa2f4a0a2
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:
25
diff
changeset
|
216 r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w)' # em-dash |
93eaa2f4a0a2
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:
25
diff
changeset
|
217 ')') |
93eaa2f4a0a2
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:
25
diff
changeset
|
218 |
93eaa2f4a0a2
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:
25
diff
changeset
|
219 def escape(string): |
93eaa2f4a0a2
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:
25
diff
changeset
|
220 r"""Escape the given string so that it can be included in double-quoted |
93eaa2f4a0a2
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:
25
diff
changeset
|
221 strings in ``PO`` files. |
93eaa2f4a0a2
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:
25
diff
changeset
|
222 |
93eaa2f4a0a2
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:
25
diff
changeset
|
223 >>> escape('''Say: |
93eaa2f4a0a2
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:
25
diff
changeset
|
224 ... "hello, world!" |
93eaa2f4a0a2
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:
25
diff
changeset
|
225 ... ''') |
93eaa2f4a0a2
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:
25
diff
changeset
|
226 '"Say:\\n \\"hello, world!\\"\\n"' |
93eaa2f4a0a2
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:
25
diff
changeset
|
227 |
93eaa2f4a0a2
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:
25
diff
changeset
|
228 :param string: the string to escape |
93eaa2f4a0a2
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:
25
diff
changeset
|
229 :return: the escaped string |
93eaa2f4a0a2
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:
25
diff
changeset
|
230 :rtype: `str` or `unicode` |
93eaa2f4a0a2
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:
25
diff
changeset
|
231 """ |
93eaa2f4a0a2
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:
25
diff
changeset
|
232 return '"%s"' % string.replace('\\', '\\\\') \ |
93eaa2f4a0a2
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:
25
diff
changeset
|
233 .replace('\t', '\\t') \ |
93eaa2f4a0a2
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:
25
diff
changeset
|
234 .replace('\r', '\\r') \ |
93eaa2f4a0a2
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:
25
diff
changeset
|
235 .replace('\n', '\\n') \ |
93eaa2f4a0a2
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:
25
diff
changeset
|
236 .replace('\"', '\\"') |
93eaa2f4a0a2
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:
25
diff
changeset
|
237 |
93eaa2f4a0a2
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:
25
diff
changeset
|
238 def normalize(string, width=76): |
108
8ea225f33f28
Fix for #16: the header message (`msgid = ""`) is now treated specially by `read_po` and `Catalog`.
cmlenz
parents:
107
diff
changeset
|
239 r"""Convert a string into a format that is appropriate for .po files. |
26
93eaa2f4a0a2
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:
25
diff
changeset
|
240 |
93eaa2f4a0a2
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:
25
diff
changeset
|
241 >>> print normalize('''Say: |
93eaa2f4a0a2
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:
25
diff
changeset
|
242 ... "hello, world!" |
93eaa2f4a0a2
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:
25
diff
changeset
|
243 ... ''', width=None) |
93eaa2f4a0a2
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:
25
diff
changeset
|
244 "" |
93eaa2f4a0a2
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:
25
diff
changeset
|
245 "Say:\n" |
93eaa2f4a0a2
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:
25
diff
changeset
|
246 " \"hello, world!\"\n" |
93eaa2f4a0a2
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:
25
diff
changeset
|
247 |
93eaa2f4a0a2
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:
25
diff
changeset
|
248 >>> print normalize('''Say: |
93eaa2f4a0a2
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:
25
diff
changeset
|
249 ... "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " |
93eaa2f4a0a2
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:
25
diff
changeset
|
250 ... ''', width=32) |
93eaa2f4a0a2
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:
25
diff
changeset
|
251 "" |
93eaa2f4a0a2
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:
25
diff
changeset
|
252 "Say:\n" |
93eaa2f4a0a2
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:
25
diff
changeset
|
253 " \"Lorem ipsum dolor sit " |
93eaa2f4a0a2
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:
25
diff
changeset
|
254 "amet, consectetur adipisicing" |
93eaa2f4a0a2
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:
25
diff
changeset
|
255 " elit, \"\n" |
93eaa2f4a0a2
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:
25
diff
changeset
|
256 |
93eaa2f4a0a2
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:
25
diff
changeset
|
257 :param string: the string to normalize |
93eaa2f4a0a2
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:
25
diff
changeset
|
258 :param width: the maximum line width; use `None`, 0, or a negative number |
93eaa2f4a0a2
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:
25
diff
changeset
|
259 to completely disable line wrapping |
93eaa2f4a0a2
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:
25
diff
changeset
|
260 :return: the normalized string |
93eaa2f4a0a2
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:
25
diff
changeset
|
261 :rtype: `unicode` |
93eaa2f4a0a2
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:
25
diff
changeset
|
262 """ |
93eaa2f4a0a2
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:
25
diff
changeset
|
263 if width and width > 0: |
93eaa2f4a0a2
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:
25
diff
changeset
|
264 lines = [] |
93eaa2f4a0a2
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:
25
diff
changeset
|
265 for idx, line in enumerate(string.splitlines(True)): |
93eaa2f4a0a2
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:
25
diff
changeset
|
266 if len(escape(line)) > width: |
93eaa2f4a0a2
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:
25
diff
changeset
|
267 chunks = WORD_SEP.split(line) |
93eaa2f4a0a2
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:
25
diff
changeset
|
268 chunks.reverse() |
93eaa2f4a0a2
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:
25
diff
changeset
|
269 while chunks: |
93eaa2f4a0a2
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:
25
diff
changeset
|
270 buf = [] |
93eaa2f4a0a2
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:
25
diff
changeset
|
271 size = 2 |
93eaa2f4a0a2
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:
25
diff
changeset
|
272 while chunks: |
93eaa2f4a0a2
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:
25
diff
changeset
|
273 l = len(escape(chunks[-1])) - 2 |
93eaa2f4a0a2
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:
25
diff
changeset
|
274 if size + l < width: |
93eaa2f4a0a2
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:
25
diff
changeset
|
275 buf.append(chunks.pop()) |
93eaa2f4a0a2
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:
25
diff
changeset
|
276 size += l |
93eaa2f4a0a2
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:
25
diff
changeset
|
277 else: |
93eaa2f4a0a2
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:
25
diff
changeset
|
278 if not buf: |
93eaa2f4a0a2
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:
25
diff
changeset
|
279 # handle long chunks by putting them on a |
93eaa2f4a0a2
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:
25
diff
changeset
|
280 # separate line |
93eaa2f4a0a2
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:
25
diff
changeset
|
281 buf.append(chunks.pop()) |
93eaa2f4a0a2
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:
25
diff
changeset
|
282 break |
93eaa2f4a0a2
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:
25
diff
changeset
|
283 lines.append(u''.join(buf)) |
93eaa2f4a0a2
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:
25
diff
changeset
|
284 else: |
93eaa2f4a0a2
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:
25
diff
changeset
|
285 lines.append(line) |
93eaa2f4a0a2
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:
25
diff
changeset
|
286 else: |
93eaa2f4a0a2
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:
25
diff
changeset
|
287 lines = string.splitlines(True) |
93eaa2f4a0a2
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:
25
diff
changeset
|
288 |
69 | 289 if len(lines) <= 1: |
26
93eaa2f4a0a2
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:
25
diff
changeset
|
290 return escape(string) |
93eaa2f4a0a2
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:
25
diff
changeset
|
291 |
93eaa2f4a0a2
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:
25
diff
changeset
|
292 # Remove empty trailing line |
69 | 293 if lines and not lines[-1]: |
26
93eaa2f4a0a2
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:
25
diff
changeset
|
294 del lines[-1] |
93eaa2f4a0a2
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:
25
diff
changeset
|
295 lines[-1] += '\n' |
93eaa2f4a0a2
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:
25
diff
changeset
|
296 return u'""\n' + u'\n'.join([escape(l) for l in lines]) |
93eaa2f4a0a2
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:
25
diff
changeset
|
297 |
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
|
298 def write_po(fileobj, catalog, width=76, no_location=False, omit_header=False, |
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
|
299 sort_output=False, sort_by_file=False): |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
57
diff
changeset
|
300 r"""Write a ``gettext`` PO (portable object) template file for a given |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
57
diff
changeset
|
301 message catalog to the provided file-like object. |
3 | 302 |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
57
diff
changeset
|
303 >>> catalog = Catalog() |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
57
diff
changeset
|
304 >>> catalog.add(u'foo %(name)s', locations=[('main.py', 1)], |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
57
diff
changeset
|
305 ... flags=('fuzzy',)) |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
57
diff
changeset
|
306 >>> catalog.add((u'bar', u'baz'), locations=[('main.py', 3)]) |
3 | 307 >>> from StringIO import StringIO |
308 >>> buf = StringIO() | |
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
|
309 >>> write_po(buf, catalog, omit_header=True) |
3 | 310 >>> print buf.getvalue() |
311 #: main.py:1 | |
8
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
312 #, fuzzy, python-format |
ff5481545bfd
Add basic PO file parsing, and change the PO writing procedure to also take flags (such as "python-format" or "fuzzy").
cmlenz
parents:
7
diff
changeset
|
313 msgid "foo %(name)s" |
3 | 314 msgstr "" |
315 <BLANKLINE> | |
316 #: main.py:3 | |
317 msgid "bar" | |
318 msgid_plural "baz" | |
319 msgstr[0] "" | |
320 msgstr[1] "" | |
321 <BLANKLINE> | |
322 <BLANKLINE> | |
323 | |
324 :param fileobj: the file-like object to write to | |
69 | 325 :param catalog: the `Catalog` instance |
26
93eaa2f4a0a2
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:
25
diff
changeset
|
326 :param width: the maximum line width for the generated output; use `None`, |
93eaa2f4a0a2
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:
25
diff
changeset
|
327 0, or a negative number to completely disable line wrapping |
3 | 328 :param no_location: do not emit a location comment for every message |
329 :param omit_header: do not include the ``msgid ""`` entry at the top of the | |
330 output | |
331 """ | |
332 def _normalize(key): | |
104
57d2f21a1fcc
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:
99
diff
changeset
|
333 return normalize(key, width=width).encode(catalog.charset, |
57d2f21a1fcc
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:
99
diff
changeset
|
334 'backslashreplace') |
26
93eaa2f4a0a2
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:
25
diff
changeset
|
335 |
93eaa2f4a0a2
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:
25
diff
changeset
|
336 def _write(text): |
93eaa2f4a0a2
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:
25
diff
changeset
|
337 if isinstance(text, unicode): |
104
57d2f21a1fcc
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:
99
diff
changeset
|
338 text = text.encode(catalog.charset) |
26
93eaa2f4a0a2
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:
25
diff
changeset
|
339 fileobj.write(text) |
3 | 340 |
183
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
341 def _write_comment(comment, prefix=''): |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
342 lines = comment |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
343 if width and width > 0: |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
344 lines = wrap(comment, width, break_long_words=False) |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
345 for line in lines: |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
346 _write('#%s %s\n' % (prefix, line.strip())) |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
347 |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
348 def _write_message(message, prefix=''): |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
349 if isinstance(message.id, (list, tuple)): |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
350 _write('%smsgid %s\n' % (prefix, _normalize(message.id[0]))) |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
351 _write('%smsgid_plural %s\n' % (prefix, _normalize(message.id[1]))) |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
352 for i, string in enumerate(message.string): |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
353 _write('%smsgstr[%d] %s\n' % (prefix, i, |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
354 _normalize(message.string[i]))) |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
355 else: |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
356 _write('%smsgid %s\n' % (prefix, _normalize(message.id))) |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
357 _write('%smsgstr %s\n' % (prefix, _normalize(message.string or ''))) |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
358 |
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
|
359 messages = list(catalog) |
73 | 360 if sort_output: |
361 messages.sort(lambda x,y: cmp(x.id, y.id)) | |
362 elif sort_by_file: | |
363 messages.sort(lambda x,y: cmp(x.locations, y.locations)) | |
70 | 364 |
73 | 365 for message in messages: |
69 | 366 if not message.id: # This is the header "message" |
367 if omit_header: | |
368 continue | |
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
|
369 comment_header = catalog.header_comment |
105
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
104
diff
changeset
|
370 if width and width > 0: |
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
104
diff
changeset
|
371 lines = [] |
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
|
372 for line in comment_header.splitlines(): |
105
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
104
diff
changeset
|
373 lines += wrap(line, width=width, subsequent_indent='# ', |
abd3a594dab4
Implement wrapping of header comments in PO(T) output. Related to #14.
cmlenz
parents:
104
diff
changeset
|
374 break_long_words=False) |
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
|
375 comment_header = u'\n'.join(lines) + u'\n' |
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 _write(comment_header) |
104
57d2f21a1fcc
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:
99
diff
changeset
|
377 |
183
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
378 for comment in message.user_comments: |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
379 _write_comment(comment) |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
380 for comment in message.auto_comments: |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
381 _write_comment(comment, prefix='.') |
3 | 382 |
383 if not no_location: | |
136 | 384 locs = u' '.join([u'%s:%d' % (filename.replace(os.sep, '/'), lineno) |
385 for filename, lineno in message.locations]) | |
183
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
386 _write_comment(locs, prefix=':') |
58
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
57
diff
changeset
|
387 if message.flags: |
068952b4d4c0
Add actual data structures for handling message catalogs, so that more code can be reused here between the frontends.
cmlenz
parents:
57
diff
changeset
|
388 _write('#%s\n' % ', '.join([''] + list(message.flags))) |
26
93eaa2f4a0a2
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:
25
diff
changeset
|
389 |
183
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
390 _write_message(message) |
26
93eaa2f4a0a2
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:
25
diff
changeset
|
391 _write('\n') |
183
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
392 |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
393 for message in catalog.obsolete.values(): |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
394 for comment in message.user_comments: |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
395 _write_comment(comment) |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
396 _write_message(message, prefix='#~ ') |
e927dffc9ab4
The frontends now provide ways to update existing translations catalogs from a template. Closes #22.
cmlenz
parents:
180
diff
changeset
|
397 _write('\n') |