annotate babel/catalog/pofile.py @ 23:bd45ff425485

Added line-wrap support for `write_po`. Fixed bug on the distutils frontend regarding the `keywords`.
author palgarvio
date Thu, 31 May 2007 22:44:57 +0000
parents ddfac856c34f
children 4fad20ab7cca
rev   line source
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
2 #
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
3 # Copyright (C) 2007 Edgewall Software
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
4 # All rights reserved.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
5 #
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
8 # are also available at http://babel.edgewall.org/wiki/License.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
9 #
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://babel.edgewall.org/log/.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
13
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
14 """Reading and writing of files in the ``gettext`` PO (portable object)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
15 format.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
16
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
17 :see: `The Format of PO Files
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
18 <http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files>`_
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
19 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
20
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
21 # TODO: line wrapping
23
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
22 from textwrap import wrap
5
50ad95bee876 * The creation-date header in generated PO files now includes the timezone offset.
cmlenz
parents: 1
diff changeset
23 from datetime import date, datetime
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
24 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
25 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
26 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
27 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
28 from sets import Set as set
5
50ad95bee876 * The creation-date header in generated PO files now includes the timezone offset.
cmlenz
parents: 1
diff changeset
29 import time
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
30
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
31 from babel import __version__ as VERSION
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
32
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
33 __all__ = ['escape', 'normalize', 'read_po', 'write_po']
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
34
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
35 POT_HEADER = """\
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
36 # Translations Template for %%(project)s.
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
37 # Copyright (C) YEAR ORGANIZATION
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
38 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
39 #
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
40 msgid ""
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
41 msgstr ""
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
42 "Project-Id-Version: %%(project)s %%(version)s\\n"
5
50ad95bee876 * The creation-date header in generated PO files now includes the timezone offset.
cmlenz
parents: 1
diff changeset
43 "POT-Creation-Date: %%(creation_date)s\\n"
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
44 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
45 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
46 "Language-Team: LANGUAGE <LL@li.org>\\n"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
47 "MIME-Version: 1.0\\n"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
48 "Content-Type: text/plain; charset=%%(charset)s\\n"
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
49 "Content-Transfer-Encoding: 8bit\\n"
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
50 "Generated-By: Babel %s\\n"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
51
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
52 """ % VERSION
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
53
17
6aa4c4df8871 Recognize python-format messages also for unnamed parameters.
cmlenz
parents: 6
diff changeset
54 PYTHON_FORMAT = re.compile(r'\%(\([\w]+\))?[diouxXeEfFgGcrs]').search
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
55
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
56 def escape(string):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
57 r"""Escape the given string so that it can be included in double-quoted
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
58 strings in ``PO`` files.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
59
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
60 >>> escape('''Say:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
61 ... "hello, world!"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
62 ... ''')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
63 'Say:\\n \\"hello, world!\\"\\n'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
64
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
65 :param string: the string to escape
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
66 :return: the escaped string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
67 :rtype: `str` or `unicode`
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
68 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
69 return string.replace('\\', '\\\\') \
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
70 .replace('\t', '\\t') \
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
71 .replace('\r', '\\r') \
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
72 .replace('\n', '\\n') \
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
73 .replace('\"', '\\"')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
74
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
75 def normalize(string, charset='utf-8'):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
76 """This converts a string into a format that is appropriate for .po files,
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
77 namely much closer to C style.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
78
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
79 :param string: the string to normalize
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
80 :param charset: the encoding to use for `unicode` strings
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
81 :return: the normalized string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
82 :rtype: `str`
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
83 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
84 string = string.encode(charset, 'backslashreplace')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
85 lines = string.split('\n')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
86 if len(lines) == 1:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
87 string = '"' + escape(string) + '"'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
88 else:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
89 if not lines[-1]:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
90 del lines[-1]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
91 lines[-1] = lines[-1] + '\n'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
92 for i in range(len(lines)):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
93 lines[i] = escape(lines[i])
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
94 lineterm = '\\n"\n"'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
95 string = '""\n"' + lineterm.join(lines) + '"'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
96 return string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
97
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
98 def read_po(fileobj):
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
99 """Read messages from a ``gettext`` PO (portable object) file from the given
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 file-like object.
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
101
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
102 This function yields tuples of the form:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
103
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
104 ``(message, translation, locations, flags)``
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
105
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
106 where:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
107
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
108 * ``message`` is the original (untranslated) message, or a
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
109 ``(singular, plural)`` tuple for pluralizable messages
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
110 * ``translation`` is the translation of the message, or a tuple of
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
111 translations for pluralizable messages
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
112 * ``locations`` is a sequence of ``(filename, lineno)`` tuples
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
113 * ``flags`` is a set of strings (for exampe, "fuzzy")
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
114
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
115 >>> from StringIO import StringIO
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
116 >>> buf = StringIO('''
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
117 ... #: 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
118 ... #, 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
119 ... 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
120 ... 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
121 ...
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
122 ... #: 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
123 ... 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
124 ... 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
125 ... 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
126 ... 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
127 ... ''')
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
128 >>> for message, translation, locations, flags in read_po(buf):
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
129 ... print (message, translation)
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
130 ... print ' ', (locations, flags)
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
131 (('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
132 ((('main.py', 1),), set(['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
133 (('bar', '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
134 ((('main.py', 3),), set([]))
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
135
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
136 :param fileobj: the file-like object to read the PO file from
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
137 :return: an iterator over ``(message, translation, location)`` tuples
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
138 :rtype: ``iterator``
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
139 """
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
140 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
141 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
142 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
143 flags = []
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
144 in_msgid = in_msgstr = False
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
145
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
146 def pack():
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
147 translations.sort()
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
148 retval = (tuple(messages), tuple([t[1] for t in 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
149 tuple(locations), set(flags))
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
150 del 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
151 del 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
152 del 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
153 del flags[:]
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
154 return retval
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
155
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
156 for line in fileobj.readlines():
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
157 line = line.strip()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
158 if line.startswith('#'):
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
159 in_msgid = in_msgstr = False
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
160 if 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
161 yield pack()
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
162 if line[1:].startswith(':'):
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
163 for location in line[2:].lstrip().split():
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
164 filename, lineno = location.split(':', 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
165 locations.append((filename, int(lineno)))
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
166 elif line[1:].startswith(','):
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
167 for flag in line[2:].lstrip().split(','):
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
168 flags.append(flag.strip())
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 elif line:
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
170 if line.startswith('msgid_plural'):
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
171 in_msgid = True
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
172 msg = line[12:].lstrip()
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
173 messages.append(msg[1:-1])
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
174 elif line.startswith('msgid'):
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
175 in_msgid = True
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
176 if 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
177 yield pack()
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
178 msg = line[5:].lstrip()
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
179 messages.append(msg[1:-1])
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
180 elif line.startswith('msgstr'):
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
181 in_msgid = False
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
182 in_msgstr = True
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
183 msg = line[6:].lstrip()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
184 if msg.startswith('['):
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
185 idx, msg = msg[1:].split(']')
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
186 translations.append([int(idx), msg.lstrip()[1:-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
187 else:
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
188 translations.append([0, msg[1:-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
189 elif line.startswith('"'):
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
190 if in_msgid:
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
191 messages[-1] += line.rstrip()[1:-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
192 elif in_msgstr:
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
193 translations[-1][1] += line.rstrip()[1:-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
194
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
195 if 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
196 yield pack()
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
197
23
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
198 def write_po(fileobj, messages, project='PROJECT', version='VERSION', width=76,
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
199 charset='utf-8', no_location=False, omit_header=False):
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
200 r"""Write a ``gettext`` PO (portable object) file to the given file-like
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
201 object.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
202
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
203 The `messages` parameter is expected to be an iterable object producing
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
204 tuples of the form:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
205
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
206 ``(filename, lineno, funcname, message, flags)``
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
207
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
208 >>> from StringIO import StringIO
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
209 >>> buf = StringIO()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
210 >>> write_po(buf, [
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
211 ... ('main.py', 1, None, u'foo %(name)s', ('fuzzy',)),
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
212 ... ('main.py', 3, 'ngettext', (u'bar', u'baz'), None)
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
213 ... ], omit_header=True)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
214
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
215 >>> print buf.getvalue()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
216 #: 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
217 #, 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
218 msgid "foo %(name)s"
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
219 msgstr ""
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
220 <BLANKLINE>
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
221 #: main.py:3
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
222 msgid "bar"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
223 msgid_plural "baz"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
224 msgstr[0] ""
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
225 msgstr[1] ""
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
226 <BLANKLINE>
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
227 <BLANKLINE>
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
228
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
229 :param fileobj: the file-like object to write to
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
230 :param messages: an iterable over the messages
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
231 :param project: the project name
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
232 :param version: the project version
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
233 :param charset: the encoding
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
234 :param no_location: do not emit a location comment for every message
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
235 :param omit_header: do not include the ``msgid ""`` entry at the top of the
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
236 output
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
237 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
238 def _normalize(key):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
239 return normalize(key, charset=charset)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
240
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
241 if not omit_header:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
242 fileobj.write(POT_HEADER % {
5
50ad95bee876 * The creation-date header in generated PO files now includes the timezone offset.
cmlenz
parents: 1
diff changeset
243 'project': project,
50ad95bee876 * The creation-date header in generated PO files now includes the timezone offset.
cmlenz
parents: 1
diff changeset
244 'version': version,
50ad95bee876 * The creation-date header in generated PO files now includes the timezone offset.
cmlenz
parents: 1
diff changeset
245 'creation_date': time.strftime('%Y-%m-%d %H:%M%z'),
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
246 'charset': charset,
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
247 })
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
248
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
249 locations = {}
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
250 msgflags = {}
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
251 msgids = []
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
252
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
253 for filename, lineno, funcname, key, flags in 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
254 flags = set(flags or [])
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
255 if key in msgids:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
256 locations[key].append((filename, lineno))
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
257 msgflags[key] |= flags
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
258 else:
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
259 if (isinstance(key, (list, tuple)) and
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
260 filter(None, [PYTHON_FORMAT(k) for k in key])) or \
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
261 (isinstance(key, basestring) and PYTHON_FORMAT(key)):
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
262 flags.add('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
263 else:
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
264 flags.discard('python-format')
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
265 locations[key] = [(filename, lineno)]
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
266 msgflags[key] = flags
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
267 msgids.append(key)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
268
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
269 for msgid in msgids:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
270 if not no_location:
23
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
271 locs = [
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
272 u' %s:%s' % (fname, lineno) for
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
273 fname, lineno in locations[msgid]
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
274 ]
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
275 if width > 0:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
276 wrapped = wrap(u''.join(locs), width, break_long_words=False)
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
277 else:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
278 wrapped = locs
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
279 for line in wrapped:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
280 fileobj.write(u'#: %s\n' % line.strip())
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
281 flags = msgflags[msgid]
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
282 if flags:
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
283 fileobj.write('#%s\n' % ', '.join([''] + list(flags)))
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
284 if type(msgid) is tuple:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
285 assert len(msgid) == 2
23
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
286 if width > 0:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
287 wrapped = wrap(msgid[0], width, break_long_words=False)
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
288 else:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
289 wrapped = [msgid[0]]
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
290 if len(wrapped) == 1:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
291 fileobj.write('msgid ')
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
292 else:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
293 fileobj.write('msgid ""\n')
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
294 for line in wrapped:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
295 fileobj.write('%s\n' % normalize(line, charset))
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
296 if width > 0:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
297 wrapped = wrap(msgid[1], width, break_long_words=False)
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
298 else:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
299 wrapped = [msgid[1]]
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
300 if len(wrapped) == 1:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
301 fileobj.write('msgid_plural ')
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
302 else:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
303 fileobj.write('msgid_plural ""\n')
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
304 for line in wrapped:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
305 fileobj.write('%s\n' % normalize(line, charset))
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
306 fileobj.write('msgstr[0] ""\n')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
307 fileobj.write('msgstr[1] ""\n')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
308 else:
23
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
309 if width > 0:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
310 wrapped = wrap(msgid, width, break_long_words=False)
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
311 else:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
312 wrapped = [msgid]
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
313 if len(wrapped) == 1:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
314 fileobj.write('msgid ')
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
315 else:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
316 fileobj.write('msgid ""\n')
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
317 for line in wrapped:
bd45ff425485 Added line-wrap support for `write_po`.
palgarvio
parents: 21
diff changeset
318 fileobj.write('%s\n' % normalize(line, charset))
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
319 fileobj.write('msgstr ""\n')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
320 fileobj.write('\n')
Copyright (C) 2012-2017 Edgewall Software