* allow export of translation po files into a tgz archive.
authorChristophe Simonis <christophe@tinyerp.com>
Tue, 19 Aug 2008 13:10:16 +0000 (15:10 +0200)
committerChristophe Simonis <christophe@tinyerp.com>
Tue, 19 Aug 2008 13:10:16 +0000 (15:10 +0200)
 * allow export of a new language from the command line

bzr revid: christophe@tinyerp.com-20080819131016-nghtt1x274evlwi4

bin/addons/base/module/wizard/wizard_export_lang.py
bin/tinyerp-server.py
bin/tools/config.py
bin/tools/translate.py

index f5df075..dc28870 100644 (file)
@@ -37,81 +37,14 @@ import pooler
 
 from osv import fields,osv
 
-'''
-view_form_init="""<?xml version="1.0"?>
-<form string="Export language">
-    <image name="gtk-dialog-info" colspan="2"/>
-    <group colspan="2" col="4">
-        <separator string="Export translation file" colspan="4"/>
-        <label align="0.0" string="Choose a language to export:" colspan="4"/>
-        <field name="lang" colspan="4"/>
-    </group>
-</form>"""
-
-view_form_finish="""<?xml version="1.0"?>
-<form string="Export language">
-    <image name="gtk-dialog-info" colspan="2"/>
-    <group colspan="2" col="4">
-        <separator string="Export done" colspan="4"/>
-        <field name="data" readonly="1" colspan="3"/>
-        <label align="0.0" string="Save this document to a .CSV file and open it with\n your favourite spreadsheet software. The file\n encoding is UTF-8. You have to translate the latest\n column before reimporting it." colspan="4"/>
-    </group>
-</form>"""
-
-class wizard_export_lang(wizard.interface):
-    def _get_language(self, cr, uid, context):
-        lang_obj=pooler.get_pool(cr.dbname).get('res.lang')
-        ids=lang_obj.search(cr, uid, [('active', '=', True),])
-        langs=lang_obj.browse(cr, uid, ids)
-        return [(lang.code, lang.translatable and lang.name or _('New language')) for lang in langs]
-
-    def _get_file(self, cr, uid, data, context):
-        file=tools.trans_generate(data['form']['lang'], 'all', dbname=cr.dbname)
-        buf=StringIO.StringIO()
-        writer=csv.writer(buf, 'UNIX')
-        for row in file:
-            writer.writerow(row)
-        del file
-        out=base64.encodestring(buf.getvalue())
-        buf.close()
-        return {'data': out}
-
-    fields_form={
-        'lang': {'string':'Language', 'type':'selection', 'selection':_get_language,},
-    }
-    fields_form_finish={
-        'data': {'string':'File', 'type':'binary', 'readonly': True,},
-    }
-    states={
-        'init':{
-            'actions': [],
-            'result': {'type': 'form', 'arch': view_form_init, 'fields': fields_form,
-                'state': [
-                    ('end', 'Cancel', 'gtk-cancel'),
-                    ('finish', 'Ok', 'gtk-ok', True)
-                ]
-            }
-        },
-        'finish':{
-            'actions': [_get_file],
-            'result': {'type': 'form', 'arch': view_form_finish, 
-                'fields': fields_form_finish,
-                'state': [
-                    ('end', 'Close', 'gtk-cancel', True)
-                ]
-            }
-        },
-    }
-wizard_export_lang('module.lang.export')
-'''
 
 class wizard_export_lang(osv.osv_memory):
 
     def _get_languages(self, cr, uid, context):
         lang_obj=pooler.get_pool(cr.dbname).get('res.lang')
-        ids=lang_obj.search(cr, uid, [('active', '=', True),])
+        ids=lang_obj.search(cr, uid, ['&', ('active', '=', True), ('translatable', '=', True),])
         langs=lang_obj.browse(cr, uid, ids)
-        return [(lang.code, lang.translatable and lang.name or _('New language')) for lang in langs]
+        return [('', _('New language'))] + [(lang.code, lang.name) for lang in langs]
     
 
     def act_cancel(self, cr, uid, ids, context=None):
@@ -132,7 +65,11 @@ class wizard_export_lang(osv.osv_memory):
         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.")
         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.")
+            ext = this.lang and '.po' or '.pot'
+            this.advice = _("Save this document to a %s file and edit it with a specific software or a text editor. The file encoding is UTF-8." % (ext,))
+        elif this.format == 'tgz':
+            ext = this.lang and '.po' or '.pot'
+            this.advice = _('Save this document to a .tgz file. This archive containt UTF-8 %s files and may be uploaded to launchpad.' % (ext,))
         
         out=base64.encodestring(buf.getvalue())
         buf.close()
@@ -140,8 +77,8 @@ class wizard_export_lang(osv.osv_memory):
 
     _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),
+            'lang': fields.selection(_get_languages, 'Language'), # not required: unset = new language
+            'format': fields.selection( ( ('csv','CSV File'), ('po','PO File'), ('tgz', 'TGZ Archive')), 'File Format', required=True),
             'modules': fields.many2many('ir.module.module', 'rel_modules_langexport', 'wiz_id', 'module_id', 'Modules', domain=[('state','=','installed')]),
             'data': fields.binary('File', readonly=True),
             'advice': fields.text('', readonly=True),
index 969cd50..e5d9f26 100755 (executable)
@@ -184,7 +184,11 @@ if tools.config['init'] or tools.config['update']:
 if tools.config["translate_out"]:
     import csv
 
-    logger.notifyChannel("init", netsvc.LOG_INFO, 'writing translation file for language %s to %s' % (tools.config["language"], tools.config["translate_out"]))
+    if tools.config["language"]:
+        msg = "language %s" % (tools.config["language"],)
+    else:
+        msg = "new language"
+    logger.notifyChannel("init", netsvc.LOG_INFO, 'writing translation file for %s to %s' % (msg, tools.config["translate_out"]))
 
     fileformat = os.path.splitext(tools.config["translate_out"])[-1][1:].lower()
     buf = file(tools.config["translate_out"], "w")
index f4a3674..49993b2 100644 (file)
@@ -119,18 +119,21 @@ class configmanager(object):
 
         group = optparse.OptionGroup(parser, "Internationalisation options",
             "Use these options to translate Tiny ERP to another language."
-            "See i18n section of the user manual. Options '-l' and '-d' are mandatory.")
+            "See i18n section of the user manual. Option '-d' is mandatory."
+            "Option '-l' is mandatory in case of importation"
+            )
 
-        group.add_option('-l', "--language", dest="language", help="specify the language of the translation file. Use it with --i18n-export and --i18n-import")
-        group.add_option("--i18n-export", dest="translate_out", help="export all sentences to be translated to a CSV or a PO file and exit")
-        group.add_option("--i18n-import", dest="translate_in", help="import a CSV or a PO file with translations and exit")
+        group.add_option('-l', "--language", dest="language", help="specify the language of the translation file. Use it with --i18n-export or --i18n-import")
+        group.add_option("--i18n-export", dest="translate_out", help="export all sentences to be translated to a CSV file, a PO file or a TGZ archive and exit")
+        group.add_option("--i18n-import", dest="translate_in", help="import a CSV or a PO file with translations and exit. The '-l' option is required.")
         group.add_option("--modules", dest="translate_modules", help="specify modules to export. Use in combination with --i18n-export")
         group.add_option("--addons-path", dest="addons_path", help="specify an alternative addons path.")
         parser.add_option_group(group)
 
         (opt, args) = parser.parse_args()
 
-        assert not ((opt.translate_in or opt.translate_out) and (not opt.language or not opt.db_name)), "the i18n-import and i18n-export options cannot be used without the language (-l) and database (-d) options"
+        assert not (opt.translate_in and (not opt.language or not opt.db_name)), "the i18n-import option cannot be used without the language (-l) and the database (-d) options"
+        assert not (opt.translate_out and (not opt.db_name)), "the i18n-export option cannot be used without the database (-d) option"
 
         # place/search the config file on Win32 near the server installation
         # (../etc from the server)
index ac31af3..167a4ca 100644 (file)
@@ -37,6 +37,8 @@ import netsvc
 from tools.misc import UpdateableStr
 import inspect
 import mx.DateTime as mxdt
+import tempfile
+import tarfile
 
 class UNIX_LINE_TERMINATOR(csv.excel):
     lineterminator = '\n'
@@ -170,19 +172,45 @@ class TinyPoFile(object):
 # Methods to export the translation file
 
 def trans_export(lang, modules, buffer, format, dbname=None):
+
+    def _process(format, modules, rows, buffer, lang, newlang):
+        if format == 'csv':
+            writer=csv.writer(buffer, 'UNIX')
+            for row in rows:
+                writer.writerow(row)
+        elif format == 'po':
+            rows.pop(0)
+            writer = tools.TinyPoFile(buffer)
+            writer.write_infos(modules)
+            for module, type, name, res_id, src, trad in rows:
+                writer.write(module, type, name, res_id, src, trad)
+        elif format == 'tgz':
+            rows.pop(0)
+            rows_by_module = {}
+            for row in rows:
+                module = row[0]
+                rows_by_module.setdefault(module, []).append(row)
+            
+            tmpdir = tempfile.mkdtemp()
+            for mod, modrows in rows_by_module.items():
+                tmpmoddir = join(tmpdir, mod, 'i18n')
+                os.makedirs(tmpmoddir)
+                pofilename = (newlang and mod or lang) + ".po" + (newlang and 't' or '')
+                buf = open(join(tmpmoddir, pofilename), 'w')
+                _process('po', [mod], modrows, buf, lang, newlang)
+
+            tar = tarfile.open(fileobj=buffer, mode='w|gz')
+            tar.add(tmpdir, '/')
+            tar.close()
+
+        else:
+            raise Exception(_('Bad file format'))
+
+    newlang = not bool(lang)
+    if newlang:
+        lang = 'en_US'
     trans = trans_generate(lang, modules, dbname)
-    if format == 'csv':
-        writer=csv.writer(buffer, 'UNIX')
-        for row in trans:
-            writer.writerow(row)
-    elif format == 'po':
-        trans.pop(0)
-        writer = tools.TinyPoFile(buffer)
-        writer.write_infos(modules)
-        for module, type, name, res_id, src, trad in trans:
-            writer.write(module, type, name, res_id, src, trad)
-    else:
-        raise Exception(_('Bad file format'))
+    _process(format, modules, trans, buffer, lang, newlang)
     del trans