[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:
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user