Skip to content
Permalink
Browse files

[WIP] base: fetch translations online

TODO:
- double check not possible to change value of i18n_location for standard modules
- take care of warning https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extractall
- document how to generate translation files
- .tar.xz ?
  • Loading branch information...
mart-e committed Sep 20, 2018
1 parent 09fd667 commit db3016355c42e5d9b50c009a3348868aaf1a9ab1
@@ -19,6 +19,8 @@ status
odoo/filestore
# maintenance migration scripts
odoo/addons/base/maintenance
# translation files
*.po

# generated for windows installer?
install/win32/*.bat
@@ -244,6 +244,13 @@ def _get_icon_image(self):
with tools.file_open(path, 'rb') as image_file:
module.icon_image = base64.b64encode(image_file.read())

def _get_i18n_location(self):
# TODO fallback on config settings?
default = "https://nightly.odoo.com"
for module in self:
manifest_info = odoo.http.addons_manifest.get(module.name, {})
module.i18n_location = manifest_info.get('i18n_location', default)

name = fields.Char('Technical Name', readonly=True, required=True, index=True)
category_id = fields.Many2one('ir.module.category', string='Category', readonly=True, index=True)
shortdesc = fields.Char('Module Name', readonly=True, translate=True)
@@ -294,6 +301,10 @@ def _get_icon_image(self):
icon = fields.Char('Icon URL')
icon_image = fields.Binary(string='Icon', compute='_get_icon_image')
to_buy = fields.Boolean('Odoo Enterprise Module', default=False)
i18n_location = fields.Char("URL of the server hosting the translations",
compute='_get_i18n_location',
help="If specified, the fetch of translations will be made on the given server. "
"The translations are expected to be located at <i18n_location>/i18n/<version>/<lang>.tar.xz")

_sql_constraints = [
('name_uniq', 'UNIQUE (name)', 'The name of the module must be unique!'),
@@ -859,20 +870,24 @@ def _update_category(self, category='Uncategorized'):
self.write({'category_id': cat_id})

@api.multi
def _update_translations(self, filter_lang=None):
def _update_translations(self, filter_lang=None, overwrite=False):
"""
Load the translations files of the given installed modules
The translations files are expected to be already available
:param filter_lang: a list of res.lang to update (all active languages if not specified)
:param overwrite: overwrite the existing translations
"""
if not filter_lang:
langs = self.env['res.lang'].search([('translatable', '=', True)])
filter_lang = [lang.code for lang in langs]
elif not isinstance(filter_lang, (list, tuple)):
filter_lang = [filter_lang]
filter_lang = self.env['res.lang'].search([('translatable', '=', True)])

update_mods = self.filtered(lambda r: r.state in ('installed', 'to install', 'to upgrade'))
mod_dict = {
mod.name: mod.dependencies_id.mapped('name')
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=overwrite)

@api.multi
def _check(self):
@@ -737,51 +737,34 @@ def _get_import_cursor(self):
return IrTranslationImport(self)

@api.model_cr_context
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. """
# make sure the given languages are active
res_lang = self.env['res.lang'].sudo()
for lang in langs:
res_lang.load_lang(lang)
# load i18n files
po_read_method = self.env['res.lang']._get_po_read_method()
for module_name in modules:
modpath = get_module_path(module_name)
if not modpath:
continue
for lang in langs:
context = dict(self._context)
lang_code = tools.get_iso_codes(lang)
context = dict(self._context, overwrite=overwrite)
lang_code = tools.get_iso_codes(lang.code)
base_lang_code = None
if '_' in lang_code:
base_lang_code = lang_code.split('_')[0]

# Step 1: for sub-languages, load base language first (e.g. es_CL.po is loaded over es.po)
if base_lang_code:
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)
for po_file in po_read_method(module_name, base_lang_code):
_logger.info('module %s: loading base translation file %s for language %s', module_name, base_lang_code, lang.name)
tools.trans_load_data(self._cr, po_file, 'po', lang.code, verbose=False, module_name=module_name, context=context)
context['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
for po_file in po_read_method(module_name, lang_code):
_logger.info('module %s: loading base translation file %s for language %s', module_name, lang_code, lang.name)
tools.trans_load_data(self._cr, po_file, 'po', lang.code, verbose=False, module_name=module_name, context=context)
context['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)
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)
return True

@api.model
Oops, something went wrong.

0 comments on commit db30163

Please sign in to comment.
You can’t perform that action at this time.