/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to tools/msgfmt.py

  • Committer: Martin Pool
  • Date: 2011-05-20 14:46:02 UTC
  • mto: This revision was merged to the branch mainline in revision 5923.
  • Revision ID: mbp@canonical.com-20110520144602-bqli0t6dj01gl0pv
Various pyflakes import fixes.

Some modules were used for subclassing or at module load time, so there is no
point loading them lazily.

Some were not imported when they should be.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env python
 
2
# -*- coding: utf-8 -*-
 
3
# Written by Martin v. Lowis <loewis@informatik.hu-berlin.de>
 
4
 
 
5
# This script is copied from Python/Tools/i18n/msgfmt.py
 
6
# It licensed under PSF license which compatible with GPL.
 
7
#
 
8
# ChangeLog
 
9
# * Convert encoding from iso-8859-1 to utf-8
 
10
# * Fix http://bugs.python.org/issue9741
 
11
 
 
12
"""Generate binary message catalog from textual translation description.
 
13
 
 
14
This program converts a textual Uniforum-style message catalog (.po file) into
 
15
a binary GNU catalog (.mo file).  This is essentially the same function as the
 
16
GNU msgfmt program, however, it is a simpler implementation.
 
17
 
 
18
Usage: msgfmt.py [OPTIONS] filename.po
 
19
 
 
20
Options:
 
21
    -o file
 
22
    --output-file=file
 
23
        Specify the output file to write to.  If omitted, output will go to a
 
24
        file named filename.mo (based off the input file name).
 
25
 
 
26
    -h
 
27
    --help
 
28
        Print this message and exit.
 
29
 
 
30
    -V
 
31
    --version
 
32
        Display version information and exit.
 
33
"""
 
34
 
 
35
import sys
 
36
import os
 
37
import getopt
 
38
import struct
 
39
import array
 
40
 
 
41
__version__ = "1.1"
 
42
 
 
43
MESSAGES = {}
 
44
 
 
45
 
 
46
def usage(code, msg=''):
 
47
    print >> sys.stderr, __doc__
 
48
    if msg:
 
49
        print >> sys.stderr, msg
 
50
    sys.exit(code)
 
51
 
 
52
 
 
53
def add(id, str, fuzzy):
 
54
    "Add a non-fuzzy translation to the dictionary."
 
55
    global MESSAGES
 
56
    if not fuzzy and str:
 
57
        MESSAGES[id] = str
 
58
 
 
59
 
 
60
def generate():
 
61
    "Return the generated output."
 
62
    global MESSAGES
 
63
    keys = MESSAGES.keys()
 
64
    # the keys are sorted in the .mo file
 
65
    keys.sort()
 
66
    offsets = []
 
67
    ids = strs = ''
 
68
    for id in keys:
 
69
        # For each string, we need size and file offset.  Each string is NUL
 
70
        # terminated; the NUL does not count into the size.
 
71
        offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id])))
 
72
        ids += id + '\0'
 
73
        strs += MESSAGES[id] + '\0'
 
74
    output = ''
 
75
    # The header is 7 32-bit unsigned integers.  We don't use hash tables, so
 
76
    # the keys start right after the index tables.
 
77
    # translated string.
 
78
    keystart = 7*4+16*len(keys)
 
79
    # and the values start after the keys
 
80
    valuestart = keystart + len(ids)
 
81
    koffsets = []
 
82
    voffsets = []
 
83
    # The string table first has the list of keys, then the list of values.
 
84
    # Each entry has first the size of the string, then the file offset.
 
85
    for o1, l1, o2, l2 in offsets:
 
86
        koffsets += [l1, o1+keystart]
 
87
        voffsets += [l2, o2+valuestart]
 
88
    offsets = koffsets + voffsets
 
89
    output = struct.pack("Iiiiiii",
 
90
                         0x950412deL,       # Magic
 
91
                         0,                 # Version
 
92
                         len(keys),         # # of entries
 
93
                         7*4,               # start of key index
 
94
                         7*4+len(keys)*8,   # start of value index
 
95
                         0, 0)              # size and offset of hash table
 
96
    output += array.array("i", offsets).tostring()
 
97
    output += ids
 
98
    output += strs
 
99
    return output
 
100
 
 
101
 
 
102
def make(filename, outfile):
 
103
    # Fix http://bugs.python.org/issue9741
 
104
    global MESSAGES
 
105
    MESSAGES.clear()
 
106
    ID = 1
 
107
    STR = 2
 
108
 
 
109
    # Compute .mo name from .po name and arguments
 
110
    if filename.endswith('.po'):
 
111
        infile = filename
 
112
    else:
 
113
        infile = filename + '.po'
 
114
    if outfile is None:
 
115
        outfile = os.path.splitext(infile)[0] + '.mo'
 
116
 
 
117
    try:
 
118
        lines = open(infile).readlines()
 
119
    except IOError, msg:
 
120
        print >> sys.stderr, msg
 
121
        sys.exit(1)
 
122
 
 
123
    section = None
 
124
    fuzzy = 0
 
125
 
 
126
    # Parse the catalog
 
127
    lno = 0
 
128
    for l in lines:
 
129
        lno += 1
 
130
        # If we get a comment line after a msgstr, this is a new entry
 
131
        if l[0] == '#' and section == STR:
 
132
            add(msgid, msgstr, fuzzy)
 
133
            section = None
 
134
            fuzzy = 0
 
135
        # Record a fuzzy mark
 
136
        if l[:2] == '#,' and 'fuzzy' in l:
 
137
            fuzzy = 1
 
138
        # Skip comments
 
139
        if l[0] == '#':
 
140
            continue
 
141
        # Now we are in a msgid section, output previous section
 
142
        if l.startswith('msgid'):
 
143
            if section == STR:
 
144
                add(msgid, msgstr, fuzzy)
 
145
            section = ID
 
146
            l = l[5:]
 
147
            msgid = msgstr = ''
 
148
        # Now we are in a msgstr section
 
149
        elif l.startswith('msgstr'):
 
150
            section = STR
 
151
            l = l[6:]
 
152
        # Skip empty lines
 
153
        l = l.strip()
 
154
        if not l:
 
155
            continue
 
156
        # XXX: Does this always follow Python escape semantics?
 
157
        l = eval(l)
 
158
        if section == ID:
 
159
            msgid += l
 
160
        elif section == STR:
 
161
            msgstr += l
 
162
        else:
 
163
            print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
 
164
                  'before:'
 
165
            print >> sys.stderr, l
 
166
            sys.exit(1)
 
167
    # Add last entry
 
168
    if section == STR:
 
169
        add(msgid, msgstr, fuzzy)
 
170
 
 
171
    # Compute output
 
172
    output = generate()
 
173
 
 
174
    try:
 
175
        open(outfile,"wb").write(output)
 
176
    except IOError,msg:
 
177
        print >> sys.stderr, msg
 
178
 
 
179
 
 
180
def main():
 
181
    try:
 
182
        opts, args = getopt.getopt(sys.argv[1:], 'hVo:',
 
183
                                   ['help', 'version', 'output-file='])
 
184
    except getopt.error, msg:
 
185
        usage(1, msg)
 
186
 
 
187
    outfile = None
 
188
    # parse options
 
189
    for opt, arg in opts:
 
190
        if opt in ('-h', '--help'):
 
191
            usage(0)
 
192
        elif opt in ('-V', '--version'):
 
193
            print >> sys.stderr, "msgfmt.py", __version__
 
194
            sys.exit(0)
 
195
        elif opt in ('-o', '--output-file'):
 
196
            outfile = arg
 
197
    # do it
 
198
    if not args:
 
199
        print >> sys.stderr, 'No input file given'
 
200
        print >> sys.stderr, "Try `msgfmt --help' for more information."
 
201
        return
 
202
 
 
203
    for filename in args:
 
204
        make(filename, outfile)
 
205
 
 
206
 
 
207
if __name__ == '__main__':
 
208
    main()