[IMP] base: explicitly pass parameters for translation methods

Instead of relying on the context content, pass explicit values for
overwrite and create_empty_translations
applu this to trans_load and trans_load_data
Adapt the test that was trying to create empty translations.
This commit is contained in:
Martin Trigaux
2019-11-19 10:37:07 +01:00
parent 49fbab5329
commit ac63556e23
8 changed files with 64 additions and 47 deletions
+2 -2
View File
@@ -873,7 +873,7 @@ class Module(models.Model):
cat_id = modules.db.create_categories(self._cr, categs)
self.write({'category_id': cat_id})
def _update_translations(self, filter_lang=None):
def _update_translations(self, filter_lang=None, overwrite=False):
if not filter_lang:
langs = self.env['res.lang'].get_installed()
filter_lang = [code for code, _ in langs]
@@ -886,7 +886,7 @@ class Module(models.Model):
for mod in update_mods
}
mod_names = topological_sort(mod_dict)
self.env['ir.translation']._load_module_terms(mod_names, filter_lang)
self.env['ir.translation']._load_module_terms(mod_names, filter_lang, overwrite)
def _check(self):
for module in self:
+13 -15
View File
@@ -27,15 +27,15 @@ class IrTranslationImport(object):
"""
_table = 'tmp_ir_translation_import'
def __init__(self, model):
def __init__(self, cr, overwrite=False):
""" Store some values, and also create a temporary SQL table to accept
the data.
:param model: the model to insert the data into (as a recordset)
"""
self._cr = model._cr
self._model_table = model._table
self._overwrite = model._context.get('overwrite', False)
self._cr = cr
self._model_table = "ir_translation"
self._overwrite = overwrite
self._debug = False
self._rows = []
@@ -774,12 +774,11 @@ class IrTranslation(models.Model):
return action
@api.model
def _get_import_cursor(self):
def _get_import_cursor(self, overwrite):
""" Return a cursor-like object for fast inserting translations """
return IrTranslationImport(self)
return IrTranslationImport(self._cr, overwrite)
def _load_module_terms(self, modules, langs):
def _load_module_terms(self, modules, langs, overwrite=False):
""" Load PO files of the given modules for the given languages. """
# load i18n files
for module_name in modules:
@@ -787,7 +786,6 @@ class IrTranslation(models.Model):
if not modpath:
continue
for lang in langs:
context = dict(self._context)
lang_code = tools.get_iso_codes(lang)
base_lang_code = None
if '_' in lang_code:
@@ -798,28 +796,28 @@ class IrTranslation(models.Model):
base_trans_file = get_module_resource(module_name, 'i18n', base_lang_code + '.po')
if base_trans_file:
_logger.info('module %s: loading base translation file %s for language %s', module_name, base_lang_code, lang)
tools.trans_load(self._cr, base_trans_file, lang, verbose=False, module_name=module_name, context=context)
context['overwrite'] = True # make sure the requested translation will override the base terms later
tools.trans_load(self._cr, base_trans_file, lang, verbose=False, module_name=module_name, overwrite=overwrite)
overwrite = True # make sure the requested translation will override the base terms later
# i18n_extra folder is for additional translations handle manually (eg: for l10n_be)
base_trans_extra_file = get_module_resource(module_name, 'i18n_extra', base_lang_code + '.po')
if base_trans_extra_file:
_logger.info('module %s: loading extra base translation file %s for language %s', module_name, base_lang_code, lang)
tools.trans_load(self._cr, base_trans_extra_file, lang, verbose=False, module_name=module_name, context=context)
context['overwrite'] = True # make sure the requested translation will override the base terms later
tools.trans_load(self._cr, base_trans_extra_file, lang, verbose=False, module_name=module_name, overwrite=overwrite)
overwrite = True # make sure the requested translation will override the base terms later
# Step 2: then load the main translation file, possibly overriding the terms coming from the base language
trans_file = get_module_resource(module_name, 'i18n', lang_code + '.po')
if trans_file:
_logger.info('module %s: loading translation file (%s) for language %s', module_name, lang_code, lang)
tools.trans_load(self._cr, trans_file, lang, verbose=False, module_name=module_name, context=context)
tools.trans_load(self._cr, trans_file, lang, verbose=False, module_name=module_name, overwrite=overwrite)
elif lang_code != 'en_US':
_logger.info('module %s: no translation for language %s', module_name, lang_code)
trans_extra_file = get_module_resource(module_name, 'i18n_extra', lang_code + '.po')
if trans_extra_file:
_logger.info('module %s: loading extra translation file (%s) for language %s', module_name, lang_code, lang)
tools.trans_load(self._cr, trans_extra_file, lang, verbose=False, module_name=module_name, context=context)
tools.trans_load(self._cr, trans_extra_file, lang, verbose=False, module_name=module_name, overwrite=overwrite)
return True
@api.model
@@ -28,7 +28,6 @@ class BaseLanguageImport(models.TransientModel):
def import_lang(self):
this = self[0]
this = this.with_context(overwrite=this.overwrite)
with TemporaryFile('wb+') as buf:
try:
buf.write(base64.decodebytes(this.data))
@@ -42,7 +41,9 @@ class BaseLanguageImport(models.TransientModel):
self.code, lang_name=self.name
)
tools.trans_load_data(this._cr, buf, fileformat, this.code, context=this._context)
tools.trans_load_data(
this._cr, buf, fileformat, this.code, overwrite=self.overwrite
)
except Exception as e:
_logger.exception('File unsuccessfully imported, due to format mismatch.')
raise UserError(
@@ -34,7 +34,7 @@ class BaseLanguageInstall(models.TransientModel):
self.ensure_one()
mods = self.env['ir.module.module'].search([('state', '=', 'installed')])
self.env['res.lang']._activate_lang(self.lang)
mods.with_context(overwrite=self.overwrite)._update_translations(self.lang)
mods._update_translations(self.lang, self.overwrite)
self.state = 'done'
self.env.cr.execute('ANALYZE ir_translation')
@@ -26,9 +26,7 @@ class BaseUpdateTranslations(models.TransientModel):
return lang.name
def act_update(self):
this = self[0]
with tempfile.NamedTemporaryFile() as buf:
tools.trans_export(this.lang, ['all'], buf, 'po', self._cr)
context = {'create_empty_translation': True}
tools.trans_load_data(self._cr, buf, 'po', this.lang, context=context)
tools.trans_export(self.lang, ['all'], buf, 'po', self._cr)
tools.trans_load_data(self._cr, buf, 'po', self.lang, create_empty_translation=True)
return {'type': 'ir.actions.act_window_close'}
@@ -62,7 +62,7 @@ class TestTermCount(common.TransactionCase):
odoo.tools.trans_load(self.cr, 'test_translation_import/i18n/fr.po', 'fr_FR', module_name='test_translation_import', verbose=False)
menu.with_context(lang='fr_FR').name = "Nouveau nom"
# reload with overwrite
odoo.tools.trans_load(self.cr, 'test_translation_import/i18n/fr.po', 'fr_FR', module_name='test_translation_import', verbose=False, context={'overwrite': True})
odoo.tools.trans_load(self.cr, 'test_translation_import/i18n/fr.po', 'fr_FR', module_name='test_translation_import', verbose=False, overwrite=True)
# trans_load invalidates ormcache but not record cache
menu.env.cache.invalidate()
@@ -72,7 +72,7 @@ class TestTermCount(common.TransactionCase):
def test_lang_with_base(self):
self.env['res.lang']._activate_lang('fr_BE')
odoo.tools.trans_load(self.cr, 'test_translation_import/i18n/fr.po', 'fr_BE', module_name='test_translation_import', verbose=False)
odoo.tools.trans_load(self.cr, 'test_translation_import/i18n/fr_BE.po', 'fr_BE', module_name='test_translation_import', verbose=False, context={'overwrite': True})
odoo.tools.trans_load(self.cr, 'test_translation_import/i18n/fr_BE.po', 'fr_BE', module_name='test_translation_import', verbose=False, overwrite=True)
# language override base language
translations = self.env['ir.translation'].search([
@@ -123,13 +123,15 @@ class TestTermCount(common.TransactionCase):
def test_export_empty_string(self):
"""When the string and the translation is equal the translation is empty"""
# Export the translations
def update_translations(context=None):
context = dict(context or {}, overwrite=True)
def update_translations(create_empty_translation=False):
self.env['res.lang']._activate_lang('fr_FR')
with closing(io.BytesIO()) as bufferobj:
odoo.tools.trans_export('fr_FR', ['test_translation_import'], bufferobj, 'po', self.cr)
bufferobj.name = 'test_translation_import/i18n/fr.po'
odoo.tools.trans_load_data(self.cr, bufferobj, 'po', 'fr_FR', verbose=False, context=context)
odoo.tools.trans_load_data(self.cr, bufferobj, 'po', 'fr_FR',
verbose=False,
create_empty_translation=create_empty_translation,
overwrite=True)
# Check that the not translated key is not created
update_translations()
@@ -137,7 +139,7 @@ class TestTermCount(common.TransactionCase):
self.assertFalse(translation, 'An empty translation is not imported')
# Check that "Generate Missing Terms" create empty string for not translated key
update_translations({'create_empty_translation': True})
update_translations(create_empty_translation=True)
translation = self.env['ir.translation'].search_count([('src', '=', 'Efgh'), ('value', '=', '')])
self.assertTrue(translation, 'The translation of "Efgh" should be empty')
@@ -238,7 +240,8 @@ class TestTranslationFlow(common.TransactionCase):
translations = self.env["ir.translation"].search([
('lang', '=', 'fr_FR'),
('module', '=', 'test_translation_import')
('module', '=', 'test_translation_import'),
('value', '!=', ''),
])
# minus 3 as the original fr.po contains 3 fake code translations (cf
@@ -265,10 +268,12 @@ class TestTranslationFlow(common.TransactionCase):
'overwrite': False,
})
with mute_logger('odoo.addons.base.models.res_lang'):
import_fr.with_context(create_empty_translation=True).import_lang()
import_fr.import_lang()
import_translation = self.env["ir.translation"].search([
('lang', '=', 'fr_FR'),
('module', '=', 'test_translation_import')
('module', '=', 'test_translation_import'),
('value', '!=', ''),
])
self.assertEqual(init_translation_count, len(import_translation))
+2 -2
View File
@@ -111,14 +111,14 @@ def export_translation():
def import_translation():
config = odoo.tools.config
context = {'overwrite': config["overwrite_existing_translations"]}
overwrite = config["overwrite_existing_translations"]
dbname = config['db_name']
registry = odoo.modules.registry.Registry.new(dbname)
with odoo.api.Environment.manage():
with registry.cursor() as cr:
odoo.tools.trans_load(
cr, config["translate_in"], config["language"], context=context,
cr, config["translate_in"], config["language"], overwrite=overwrite,
)
def main(args):
+27 -12
View File
@@ -1033,30 +1033,44 @@ def trans_generate(lang, modules, cr):
return out
def trans_load(cr, filename, lang, verbose=True, module_name=None, context=None):
def trans_load(cr, filename, lang, verbose=True, module_name=None, create_empty_translation=False, overwrite=False):
try:
with file_open(filename, mode='rb') as fileobj:
_logger.info("loading %s", filename)
fileformat = os.path.splitext(filename)[-1][1:].lower()
result = trans_load_data(cr, fileobj, fileformat, lang, verbose=verbose, module_name=module_name, context=context)
return result
return trans_load_data(cr, fileobj, fileformat, lang,
verbose=verbose,
module_name=module_name,
create_empty_translation=create_empty_translation,
overwrite=overwrite)
except IOError:
if verbose:
_logger.error("couldn't read translation file %s", filename)
return None
def trans_load_data(cr, fileobj, fileformat, lang, verbose=True, module_name=None, context=None):
"""Populates the ir_translation table."""
def trans_load_data(cr, fileobj, fileformat, lang,
verbose=True, module_name=None, create_empty_translation=False, overwrite=False):
"""Populates the ir_translation table.
:param fileobj: buffer open to a translation file
:param fileformat: format of the `fielobj` file, one of 'po' or 'csv'
:param lang: language code of the translations contained in `fileobj`
language must be present and activated in the database
:param verbose: increase log output
:param module_name: name of the module to use for created translations # TODO move to TranslationFileReader?
:param create_empty_translation: create an ir.translation record, even if no value
is provided in the translation entry
:param overwrite: if an ir.translation already exists for a term, replace it with
the one in `fileobj`
"""
if verbose:
_logger.info('loading translation file for language %s', lang)
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, context or {})
Lang = env['res.lang']
Translation = env['ir.translation']
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
try:
if not Lang._lang_get(lang):
if not env['res.lang']._lang_get(lang):
_logger.error("Couldn't read translation for lang '%s', language not found", lang)
return None
@@ -1064,8 +1078,9 @@ def trans_load_data(cr, fileobj, fileformat, lang, verbose=True, module_name=Non
fileobj.seek(0)
reader = TranslationFileReader(fileobj, fileformat=fileformat)
# read the rest of the file
irt_cursor = Translation._get_import_cursor()
# read the rest of the file with a cursor-like object for fast inserting translations"
Translation = env['ir.translation']
irt_cursor = Translation._get_import_cursor(overwrite)
def process_row(row):
"""Process a single PO (or POT) entry."""
@@ -1078,7 +1093,7 @@ def trans_load_data(cr, fileobj, fileformat, lang, verbose=True, module_name=Non
dic.update(row)
# do not import empty values
if not env.context.get('create_empty_translation', False) and not dic['value']:
if not create_empty_translation and not dic['value']:
return
if dic['type'] == 'code' and module_name: