translation: allow export in .po format
authorChristophe Simonis <christophe@tinyerp.com>
Thu, 17 Jul 2008 10:22:36 +0000 (12:22 +0200)
committerChristophe Simonis <christophe@tinyerp.com>
Thu, 17 Jul 2008 10:22:36 +0000 (12:22 +0200)
bzr revid: christophe@tinyerp.com-20080717102236-iyx46ut1s3a9roos

bin/addons/base/ir/ir_translation.py
bin/addons/base/module/module_wizard.xml
bin/addons/base/module/wizard/wizard_export_lang.py
bin/tools/translate.py

index 6fc906d..ac87f08 100644 (file)
@@ -139,12 +139,10 @@ class ir_translation(osv.osv, Cacheable):
                                                'and name=%s',
                                        (lang, tt, str(name)))
                res = cr.fetchone()
-               if res:
-                       self.add((lang, tt, name, source), res[0])
-                       return res[0]
-               else:
-                       self.add((lang, tt, name, source), False)
-                       return False
+               
+               trad = res and res[0] or ''
+               self.add((lang, tt, name, source), trad)
+               return trad
 
        def unlink(self, cursor, user, ids, context=None):
                self.clear()
index df18b70..478dd78 100644 (file)
             <field name="model">wizard.module.lang.export</field>
             <field name="type">form</field>
                        <field name="arch" type="xml">
-                               <form col="4" string="Export language">
+                               <form col="3" string="Export language">
                                        <image name="gtk-dialog-info"/>
-                                       <group col="2" states="choose">
+                                       <group col="2" states="choose" fill="0" height="500">
                                                <separator string="Export translation file" colspan="2"/>
-                                               <label align="0.0" string="Choose a language to export:"/>
-                                               <field name="lang" nolabel="1"/>
-                        <button icon="gtk-cancel" name="act_cancel" special="cancel" string="Cancel" type="object"/>
-                        <button icon="gtk-ok" name="act_getfile" string="Get file" type="object"/>
+                                               <field name="lang" width="300"/>
+                                               <field name="format"/>
+                                               <field name="state" invisible="1"/>
+                                               <newline/><label/><newline/><label/>
                                        </group>
-                                       <group col="1" states="get">
-                                               <separator string="Export done" colspan="1"/>
-                                               <field name="data" readonly="1"/>
-                                               <label string="Save this document to a .CSV file and open it with your favourite spreadsheet software. The file encoding is UTF-8. You have to translate the latest column before reimporting it."/>
-                        <button icon="gtk-close" name="act_destroy" special="cancel" string="Close" type="object"/>
+                                       <group col="1" states="get" fill="0">
+                                               <separator string="Export done"/>
+                                               <field name="data" readonly="1" nolabel="1"/>
+                                               <field name="advice" nolabel="1" height="80"/>
+                                       </group>
+                                       <group col="2" colspan="3" fill="0">
+                                               <button states="choose" icon="gtk-cancel" name="act_cancel" special="cancel" string="Cancel" type="object"/>
+                           <button states="choose" icon="gtk-ok" name="act_getfile" string="Get file" type="object"/>
+                               <button states="get" icon="gtk-close" name="act_destroy" special="cancel" string="Close" type="object"/>
                                        </group>
-<field name="state" readonly="1"/>
                                </form>
                        </field>
         </record>
index ed7edbb..0bd589a 100644 (file)
@@ -122,36 +122,37 @@ class wizard_export_lang(osv.osv_memory):
                return {'type':'ir.actions.act_window_close' }
 
        def act_getfile(self, cr, uid, ids, context=None):
-               print "get filE"
                this = self.browse(cr, uid, ids)[0]
-               print this.lang
-               # set the data
                file=tools.trans_generate(this.lang, 'all', dbname=cr.dbname)
                buf=StringIO.StringIO()
-               writer=csv.writer(buf, 'UNIX')
-               for row in file:
-                       writer.writerow(row)
+               
+               if this.format == 'csv':
+                       this.advice = _("Save this document to a .CSV file and open it with your favourite spreadsheet software. The file encoding is UTF-8. You have to translate the latest column before reimporting it.")
+                       writer=csv.writer(buf, 'UNIX')
+                       for row in file:
+                               writer.writerow(row)
+               elif this.format == 'po':
+                       this.advice = _("Save this document to a .po file and edit it with a specific software or a text editor. The file encoding is UTF-8.")
+                       file.pop(0)
+                       writer = tools.TinyPoFile(buf)
+                       for module, type, name, res_id, src, trad in file:
+                               writer.write(type, name, res_id, src, trad)
+               else:
+                       raise osv_except(_('Bad file format'))
+
                del file
                out=base64.encodestring(buf.getvalue())
                buf.close()
-
-               self.write(cr, uid, ids, {'state':'get','data':out}, context=context)
-               
-               return {
-                               'view_type': 'form',
-                               "view_mode": 'form',
-                           'res_model': self._name,
-                           'type': 'ir.actions.act_window',
-                           'target':'new',
-                       }
+               return self.write(cr, uid, ids, {'state':'get', 'data':out, 'advice':this.advice}, context=context)
 
        _name = "wizard.module.lang.export"
        _columns = {
                        'lang': fields.selection(_get_languages, 'Language',required=True),
+                       'format': fields.selection( ( ('csv','CSV File'), ('po','PO File') ), 'File Format', required=True),
                        'data': fields.binary('File', readonly=True),
+                       'advice': fields.text('', readonly=True),
                        'state': fields.selection( ( ('choose','choose'),       # choose language
                                                         ('get','get'),                 # get the file
-                                                                                #('end','end'),                        # virtual state: unlink self
                                                   ) ),
                        }
        _defaults = { 'state': lambda *a: 'choose', }
index 2ccd458..d2389dc 100644 (file)
@@ -67,6 +67,56 @@ class GettextAlias(object):
 
 _ = GettextAlias()
 
+
+# class to handle po files
+class TinyPoFile(object):
+       def __init__(self, buffer):
+               self.buffer = buffer
+       
+       def __iter__(self):
+               self.buffer.seek(0)
+               return self
+       
+       def next(self):
+               type = name = res_id = source = trad = None
+               line = True
+                       
+               line = self.buffer.readline().strip()
+               while line.startswith('#') or line == '':
+                       if line.startwith('#:'):
+                               type, name, res_id = line[2:].strip().split(':')
+                       line = self.buffer.readline().strip()
+               if not line.startswith('msgid'):
+                       raise Exception("malformed file")
+               source = line[7:-1]
+               line = self.buffer.readline().strip()
+               while not line.startwith('msgstr'):
+                       if not line:
+                               raise Exception('malformed file')
+                       source += line[1:-1]
+                       line = self.buffer.readline().strip()
+
+               trad = line[8:-1]
+               line = self.buffer.readline().strip()
+               while line:
+                       trad += line[1:-1]
+                       line = self.buffer.readline().strip()
+               
+               return type, name, res_id, source, trad
+
+       def write(self, type, name, res_id, source, trad):
+               def quote(str):
+                       return '"%s"' % str.replace('"','\\"')
+
+               self.buffer.write("#, python-format\n"  \
+                                 "#: %s:%s:%s\n"       \
+                                 "msgid %s\n"          \
+                                 "msgstr %s\n\n"       \
+                                       % (type, name, str(res_id), quote(source), quote(trad))
+                               )
+       
+
+
 # Methods to export the translation file
 
 def trans_parse_xsl(de):
@@ -246,7 +296,8 @@ def trans_generate(lang, modules, dbname=None):
                for field_name,field_def in pool.get(model)._columns.items():
                        if field_def.translate:
                                name = model + "," + field_name
-                               push_translation(module, 'model', name, xml_name, getattr(obj, field_name))
+                               trad = getattr(obj, field_name) or ''
+                               push_translation(module, 'model', name, xml_name, trad.encode('utf8'))
 
        # parse source code for _() calls
        def get_module_from_path(path):