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