Mercurial and Git clients can push and pull from this alias URL to interact with this repository. You can change to which repository an alias points by going to the Aliases link on the project page.
#! /usr/bin/env python# -*- coding: iso-8859-1 -*-# Written by Martin v. Loewis <loewis@informatik.hu-berlin.de>## Changed by Christian 'Tiran' Heimes <tiran@cheimes.de> for the placeless# translation service (PTS) of Zope## Fixed some bugs and updated to support msgctxt# by Hanno Schlichting <hanno@hannosch.info>"""Generate binary message catalog from textual translation description.This program converts a textual Uniforum-style message catalog (.po file) intoa binary GNU catalog (.mo file). This is essentially the same function as theGNU msgfmt program, however, it is a simpler implementation.This file was taken from Python-2.3.2/Tools/i18n and altered in several ways.Now you can simply use it from another python module: from msgfmt import Msgfmt mo = Msgfmt(po).get()where po is path to a po file as string, an opened po file ready for reading ora list of strings (readlines of a po file) and mo is the compiled mo file asbinary string.Exceptions: * IOError if the file couldn't be read * msgfmt.PoSyntaxError if the po file has syntax errors"""importstructimportarrayfromcStringIOimportStringIO__version__="1.1-pythongettext"classPoSyntaxError(Exception):""" Syntax error in a po file """def__init__(self,msg):self.msg=msgdef__str__(self):return'Po file syntax error: %s'%self.msgclassMsgfmt:""" """def__init__(self,po,name='unknown'):self.po=poself.name=nameself.messages={}self.openfile=FalsedefreadPoData(self):""" read po data from self.po and return an iterator """output=[]ifisinstance(self.po,str):output=open(self.po,'rb')elifisinstance(self.po,file):self.po.seek(0)self.openfile=Trueoutput=self.poelifisinstance(self.po,list):output=self.poifnotoutput:raiseValueError,"self.po is invalid! %s"%type(self.po)returnoutputdefadd(self,context,id,str,fuzzy):"Add a non-empty and non-fuzzy translation to the dictionary."ifstrandnotfuzzy:# The context is put before the id and separated by a EOT char.ifcontext:id=context+'\x04'+idself.messages[id]=strdefgenerate(self):"Return the generated output."keys=self.messages.keys()# the keys are sorted in the .mo filekeys.sort()offsets=[]ids=strs=''foridinkeys:# For each string, we need size and file offset. Each string is# NUL terminated; the NUL does not count into the size.offsets.append((len(ids),len(id),len(strs),len(self.messages[id])))ids+=id+'\0'strs+=self.messages[id]+'\0'output=''# The header is 7 32-bit unsigned integers. We don't use hash tables,# so the keys start right after the index tables.keystart=7*4+16*len(keys)# and the values start after the keysvaluestart=keystart+len(ids)koffsets=[]voffsets=[]# The string table first has the list of keys, then the list of values.# Each entry has first the size of the string, then the file offset.foro1,l1,o2,l2inoffsets:koffsets+=[l1,o1+keystart]voffsets+=[l2,o2+valuestart]offsets=koffsets+voffsets# Even though we don't use a hashtable, we still set its offset to be# binary compatible with the gnu gettext format produced by:# msgfmt file.po --no-hashoutput=struct.pack("Iiiiiii",0x950412deL,# Magic0,# Versionlen(keys),# # of entries7*4,# start of key index7*4+len(keys)*8,# start of value index0,keystart)# size and offset of hash tableoutput+=array.array("i",offsets).tostring()output+=idsoutput+=strsreturnoutputdefget(self):""" """self.read()# Compute outputreturnself.generate()defread(self,header_only=False):""" """ID=1STR=2CTXT=3section=Nonefuzzy=0msgid=msgstr=msgctxt=''# Parse the cataloglno=0forlinself.readPoData():lno+=1# If we get a comment line after a msgstr or a line starting with# msgid or msgctxt, this is a new entryifsection==STRand(l[0]=='#'or(l[0]=='m'and(l.startswith('msgctxt')orl.startswith('msgid')))):self.add(msgctxt,msgid,msgstr,fuzzy)section=Nonemsgctxt=''fuzzy=0# If we only want the header we stop after the first messageifheader_only:break# Record a fuzzy markifl[:2]=='#,'and'fuzzy'inl:fuzzy=1# Skip commentsifl[0]=='#':continue# Now we are in a msgctxt sectionelifl[0]=='m':ifl.startswith('msgctxt'):section=CTXTl=l[7:]msgctxt='' # Now we are in a msgid section, output previous section
elif l.startswith('msgid') and not l.startswith('msgid_plural'):
if section == STR:
- add(msgid, msgstr, fuzzy)
+self.add(msgid, msgstr, fuzzy)
section = ID
l = l[5:]
msgid = msgstr = ''
is_plural=False# This is a message with plural formselifl.startswith('msgid_plural'):ifsection!=ID:print>>sys.stderr,'msgid_plural not preceeded by msgid on %s:%d'%\
(infile,lno)sys.exit(1)l=l[12:]msgid+='\0'# separator of singular and pluralis_plural=True# Now we are in a msgstr sectionelifl.startswith('msgstr'):section=STRifl.startswith('msgstr['):ifnotis_plural:print>>sys.stderr,'plural without msgid_plural on %s:%d'%\
(infile,lno)sys.exit(1)l=l.split(']',1)[1]ifmsgstr:msgstr+='\0'# Separator of the various plural formselse:ifis_plural:print>>sys.stderr,'indexed msgstr required for plural on %s:%d'%\
(infile,lno)sys.exit(1)l=l[6:]# Skip empty linesl=l.strip()ifnotl:continue# XXX: Does this always follow Python escape semantics?try:l=eval(l)exceptException,msg:raisePoSyntaxError('%s (line %d of po file %s): \n%s'%(msg,lno,self.name,l))ifsection==CTXT:msgctxt+=lelifsection==ID:msgid+=lelifsection==STR:msgstr+=lelse:raisePoSyntaxError('error in line %d of po file %s'%(lno,self.name))# Add last entryifsection==STR:self.add(msgctxt,msgid,msgstr,fuzzy)ifself.openfile:self.po.close()defgetAsFile(self):returnStringIO(self.get())
Attach a Trello Card
Add a tag
Your session has expired
You are no longer logged in. Please log in and try your request again.
Filter RSS Feed
This RSS feed URL allows you to see the contents of your current filter using any feed reader.
This link includes a special authentication token. If you share the URL with anyone else, they can see this RSS feed's activity. You can disable these tokens when needed.
Your current filter is unsaved; changing it won't affect this RSS feed.