From 7e205ea6a980e4c50b9ca7c2347e1b49d71b2e48 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 9 Aug 2017 15:15:55 +0200 Subject: [PATCH] [ADD] transifex: integration module Create a new module to directly find a source term on Transifex This will not make translation easier but improve the collaboration and allow easily to find a source term. --- addons/transifex/__init__.py | 4 + addons/transifex/__manifest__.py | 28 ++++++ addons/transifex/data/ir_translation_view.xml | 28 ++++++ addons/transifex/data/transifex_data.xml | 9 ++ addons/transifex/models/__init__.py | 4 + addons/transifex/models/ir_translation.py | 84 ++++++++++++++++++ addons/transifex/static/description/icon.png | Bin 0 -> 3279 bytes 7 files changed, 157 insertions(+) create mode 100644 addons/transifex/__init__.py create mode 100644 addons/transifex/__manifest__.py create mode 100644 addons/transifex/data/ir_translation_view.xml create mode 100644 addons/transifex/data/transifex_data.xml create mode 100644 addons/transifex/models/__init__.py create mode 100644 addons/transifex/models/ir_translation.py create mode 100644 addons/transifex/static/description/icon.png diff --git a/addons/transifex/__init__.py b/addons/transifex/__init__.py new file mode 100644 index 00000000000..dc5e6b693d1 --- /dev/null +++ b/addons/transifex/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import models diff --git a/addons/transifex/__manifest__.py b/addons/transifex/__manifest__.py new file mode 100644 index 00000000000..98a1341bcec --- /dev/null +++ b/addons/transifex/__manifest__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Transifex integration', + 'version': '1.0', + 'summary': 'Add a link to edit a translation in Transifex', + 'category': 'Extra Tools', + 'description': + """ +Transifex integration +===================== +This module will add a link to the Transifex project in the translation view. +The purpose of this module is to speed up translations of the main modules. + +To work, Odoo uses Transifex configuration files `.tx/config` to detec the +project source. Custom modules will not be translated (as not published on +the main Transifex project). + +The language the user tries to translate must be activated on the Transifex +project. + """, + 'data': [ + 'data/transifex_data.xml', + 'data/ir_translation_view.xml', + ], + 'depends': ['base'], +} diff --git a/addons/transifex/data/ir_translation_view.xml b/addons/transifex/data/ir_translation_view.xml new file mode 100644 index 00000000000..bd6541b9567 --- /dev/null +++ b/addons/transifex/data/ir_translation_view.xml @@ -0,0 +1,28 @@ + + + + ir.translation.transifex + ir.translation + + + + + + + + + + ir.translation.transifex + ir.translation + + + + + + + + diff --git a/addons/transifex/data/transifex_data.xml b/addons/transifex/data/transifex_data.xml new file mode 100644 index 00000000000..a8faefd1661 --- /dev/null +++ b/addons/transifex/data/transifex_data.xml @@ -0,0 +1,9 @@ + + + + + transifex.project_url + https://www.transifex.com/odoo + + + diff --git a/addons/transifex/models/__init__.py b/addons/transifex/models/__init__.py new file mode 100644 index 00000000000..76fec4841b3 --- /dev/null +++ b/addons/transifex/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import ir_translation diff --git a/addons/transifex/models/ir_translation.py b/addons/transifex/models/ir_translation.py new file mode 100644 index 00000000000..7629ecaf835 --- /dev/null +++ b/addons/transifex/models/ir_translation.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from configparser import ConfigParser +from os.path import join as opj +import os +import werkzeug + +from odoo import models, fields +from odoo.modules.module import ad_paths + + +class IrTranslation(models.Model): + + _inherit = 'ir.translation' + + transifex_url = fields.Char("Transifex URL", compute='_get_transifex_url') + + def _get_transifex_url(self): + """ Construct transifex URL based on the module on configuration """ + # e.g. 'https://www.transifex.com/odoo/' + base_url = self.env['ir.config_parameter'].sudo().get_param('transifex.project_url') + + tx_config_file = ConfigParser() + tx_sections = [] + for addon_path in ad_paths: + tx_path = opj(addon_path, '.tx', 'config') + if os.path.isfile(tx_path): + tx_config_file.read(tx_path) + # first section is [main], after [odoo-11.sale] + tx_sections.extend(tx_config_file.sections()[1:]) + + # parent directory ad .tx/config is root directory in odoo/odoo + tx_path = opj(addon_path, os.pardir, '.tx', 'config') + if os.path.isfile(tx_path): + tx_config_file.read(tx_path) + tx_sections.extend(tx_config_file.sections()[1:]) + + if not base_url or not tx_sections: + self.transifex_url = False + else: + base_url = base_url.rstrip('/') + + # will probably be the same for all terms, avoid multiple searches + translation_languages = list(set(self.mapped('lang'))) + languages = self.env['res.lang'].with_context(active_test=False).search( + [('code', 'in', translation_languages)]) + + language_codes = dict((l.code, l.iso_code) for l in languages) + + # .tx/config files contains the project reference + # using ini files like '[odoo-master.website_sale]' + translation_modules = set(self.mapped('module')) + project_modules = {} + for module in translation_modules: + for section in tx_sections: + tx_project, tx_mod = section.split('.') + if tx_mod == module: + project_modules[module] = tx_project + + for translation in self: + if not translation.module or not translation.source or translation.lang == 'en_US': + # custom or source term + translation.transifex_url = False + continue + + lang_code = language_codes.get(translation.lang) + if not lang_code: + translation.transifex_url = False + continue + + project = project_modules.get(translation.module) + if not project: + translation.transifex_url = False + continue + + # e.g. 'https://www.transifex.com/odoo/odoo-10/translate/#fr/sale/42?q=Sale+Order' + translation.transifex_url = "%(url)s/%(project)s/translate/#%(lang)s/%(module)s/42?q=%(src)s" % { + 'url': base_url, + 'project': project, + 'lang': lang_code, + 'module': translation.module, + 'src': werkzeug.url_quote_plus(translation.source[:50]), + } diff --git a/addons/transifex/static/description/icon.png b/addons/transifex/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9da4be521b094105944ab15d2d6d55ec097267f4 GIT binary patch literal 3279 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 N002ovPDHLkV1k((6~O=i literal 0 HcmV?d00001