diff --git a/odoo/addons/test_translation_import/i18n/dot.csv b/odoo/addons/test_translation_import/i18n/dot.csv new file mode 100644 index 00000000000..5c4fc6ae34d --- /dev/null +++ b/odoo/addons/test_translation_import/i18n/dot.csv @@ -0,0 +1,2 @@ +module,type,name,res_id,src,value,comments +test_translation_import,code,addons/test_translation_import/models.py,20,Accounting,samva, diff --git a/odoo/addons/test_translation_import/i18n/tlh.po b/odoo/addons/test_translation_import/i18n/tlh.po new file mode 100644 index 00000000000..758a27ffa08 --- /dev/null +++ b/odoo/addons/test_translation_import/i18n/tlh.po @@ -0,0 +1,20 @@ +# This is a test PO file, not a complete one. It is manually maintained +# to test the import translation behavior of Odoo. +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server saas~11.4\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-09-18 13:20+0000\n" +"PO-Revision-Date: 2018-09-18 13:20+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: test_translation_import +#: code:addons/test_translation_import/models.py:18 +#, python-format +msgid "Klingon" +msgstr "tlhIngan" diff --git a/odoo/addons/test_translation_import/models.py b/odoo/addons/test_translation_import/models.py index 5cfa59d990c..294f4eb7e85 100644 --- a/odoo/addons/test_translation_import/models.py +++ b/odoo/addons/test_translation_import/models.py @@ -14,3 +14,7 @@ class m(models.TransientModel): # With the name label above, this source string should be generated twice. _('1XBUO5PUYH2RYZSA1FTLRYS8SPCNU1UYXMEYMM25ASV7JC2KTJZQESZYRV9L8CGB') + + _('Klingon') + + _('Accounting') diff --git a/odoo/addons/test_translation_import/tests/test_term_count.py b/odoo/addons/test_translation_import/tests/test_term_count.py index c89bf44ed25..7e224bfdd7b 100644 --- a/odoo/addons/test_translation_import/tests/test_term_count.py +++ b/odoo/addons/test_translation_import/tests/test_term_count.py @@ -1,10 +1,13 @@ # -*- coding: utf-8 -*- from contextlib import closing +import base64 import io import odoo from odoo.tests import common +from odoo.tools.misc import file_open, mute_logger +from odoo.tools.translate import _ class TestTermCount(common.TransactionCase): @@ -79,3 +82,49 @@ class TestTermCount(common.TransactionCase): menu.with_context(lang='fr_FR').name = "Nouveau nom" update_translations() self.assertEqual(menu.with_context(lang='fr_FR').name, "Nouveau nom", 'The translation of "New Name" should be "Nouveau nom"') + + def test_import_from_po_file(self): + """Test the import from a single po file works""" + with file_open('test_translation_import/i18n/tlh.po', 'rb') as f: + po_file = base64.encodestring(f.read()) + + import_tlh = self.env["base.language.import"].create({ + 'name': 'Klingon', + 'code': 'tlh', + 'data': po_file, + 'filename': 'tlh.po', + }) + with mute_logger('odoo.addons.base.models.res_lang'): + import_tlh.import_lang() + + lang_count = self.env['res.lang'].search_count([('code', '=', 'tlh')]) + self.assertEqual(lang_count, 1, "The imported language was not creates") + + trans_count = self.env['ir.translation'].search_count([('lang', '=', 'tlh')]) + self.assertEqual(trans_count, 1, "The imported translations were not created") + + self.env.context = dict(self.env.context, lang="tlh") + self.assertEqual(_("Klingon"), "tlhIngan", "The code translation was not applied") + + def test_import_from_csv_file(self): + """Test the import from a single CSV file works""" + with file_open('test_translation_import/i18n/dot.csv', 'rb') as f: + po_file = base64.encodestring(f.read()) + + import_tlh = self.env["base.language.import"].create({ + 'name': 'Dothraki', + 'code': 'dot', + 'data': po_file, + 'filename': 'dot.csv', + }) + with mute_logger('odoo.addons.base.models.res_lang'): + import_tlh.import_lang() + + lang_count = self.env['res.lang'].search_count([('code', '=', 'dot')]) + self.assertEqual(lang_count, 1, "The imported language was not creates") + + trans_count = self.env['ir.translation'].search_count([('lang', '=', 'dot')]) + self.assertEqual(trans_count, 1, "The imported translations were not created") + + self.env.context = dict(self.env.context, lang="dot") + self.assertEqual(_("Accounting"), "samva", "The code translation was not applied") diff --git a/odoo/tools/translate.py b/odoo/tools/translate.py index 4533c8a9bc7..59d882d84e6 100644 --- a/odoo/tools/translate.py +++ b/odoo/tools/translate.py @@ -1037,6 +1037,7 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, # (Because the POT comments are correct on Launchpad but not the # PO comments due to a Launchpad limitation. See LP bug 933496.) pot_reader = [] + use_pot_reference = False # now, the serious things: we read the language file fileobj.seek(0) @@ -1065,6 +1066,7 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, pot_handle = file_open(os.path.join( addons, module, i18n_dir, module + '.pot'), mode='rb') pot_reader = PoFile(pot_handle) + use_pot_reference = True except: pass @@ -1099,17 +1101,18 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, dic['lang'] = lang dic.update(pycompat.izip(fields, row)) - # discard the target from the POT targets. - src = dic['src'] - target_key = (dic['type'], dic['name'], dic['type'] != 'code' and dic['res_id'] or 0) - target = pot_targets.get(src) - if not target or target_key not in target.targets: - _logger.info("Translation '%s' (%s, %s, %s) not found in reference pot, skipping", - src[:60], dic['type'], dic['name'], dic['res_id']) - return + if use_pot_reference: + # discard the target from the POT targets. + src = dic['src'] + target_key = (dic['type'], dic['name'], dic['type'] != 'code' and dic['res_id'] or 0) + target = pot_targets.get(src) + if not target or target_key not in target.targets: + _logger.info("Translation '%s' (%s, %s, %s) not found in reference pot, skipping", + src[:60], dic['type'], dic['name'], dic['res_id']) + return - target.value = dic['value'] - target.targets.discard(target_key) + target.value = dic['value'] + target.targets.discard(target_key) # This would skip terms that fail to specify a res_id res_id = dic['res_id'] @@ -1137,15 +1140,16 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, for row in reader: process_row(row) - # Then process the entries implied by the POT file (which is more - # correct w.r.t. the targets) if some of them remain. - pot_rows = [] - for src, target in pot_targets.items(): - if target.value: - for type, name, res_id in target.targets: - pot_rows.append((type, name, res_id, src, target.value, target.comments)) - for row in pot_rows: - process_row(row) + if use_pot_reference: + # Then process the entries implied by the POT file (which is more + # correct w.r.t. the targets) if some of them remain. + pot_rows = [] + for src, target in pot_targets.items(): + if target.value: + for type, name, res_id in target.targets: + pot_rows.append((type, name, res_id, src, target.value, target.comments)) + for row in pot_rows: + process_row(row) irt_cursor.finish() Translation.clear_caches()