mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-23 21:32:05 +02:00
Initial commit: Core packages
This commit is contained in:
commit
12c29a983b
9512 changed files with 8379910 additions and 0 deletions
|
|
@ -0,0 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import models
|
||||
from . import transifex_code_translation
|
||||
from . import transifex_translation
|
||||
31
odoo-bringout-oca-ocb-transifex/transifex/models/models.py
Normal file
31
odoo-bringout-oca-ocb-transifex/transifex/models/models.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models
|
||||
|
||||
class BaseModel(models.AbstractModel):
|
||||
_inherit = 'base'
|
||||
|
||||
def get_field_translations(self, field_name, langs=None):
|
||||
""" get model/model_term translations for records with transifex url
|
||||
:param str field_name: field name
|
||||
:param list langs: languages
|
||||
|
||||
:return: (translations, context) where
|
||||
translations: list of dicts like [{"lang": lang, "source": source_term, "value": value_term,
|
||||
"module": module, "transifexURL": transifex_url}]
|
||||
context: {"translation_type": "text"/"char", "translation_show_source": True/False}
|
||||
"""
|
||||
translations, context = super().get_field_translations(field_name, langs=langs)
|
||||
external_id = self.get_external_id().get(self.id)
|
||||
if not external_id:
|
||||
return translations, context
|
||||
|
||||
module = external_id.split('.')[0]
|
||||
if module not in self.pool._init_modules:
|
||||
return translations, context
|
||||
|
||||
for translation in translations:
|
||||
translation['module'] = module
|
||||
self.env['transifex.translation']._update_transifex_url(translations)
|
||||
return translations, context
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import psycopg2
|
||||
|
||||
from odoo import api, models, fields
|
||||
from odoo.tools.translate import CodeTranslations
|
||||
|
||||
|
||||
class TransifexCodeTranslation(models.Model):
|
||||
_name = "transifex.code.translation"
|
||||
_description = "Code Translation"
|
||||
_log_access = False
|
||||
|
||||
source = fields.Text(string='Code')
|
||||
value = fields.Text(string='Translation Value')
|
||||
module = fields.Char(help="Module this term belongs to")
|
||||
lang = fields.Selection(selection='_get_languages', string='Language', validate=False)
|
||||
transifex_url = fields.Char("Transifex URL", compute='_compute_transifex_url',
|
||||
help="Propose a modification in the official version of Odoo")
|
||||
|
||||
def _get_languages(self):
|
||||
return self.env['res.lang'].get_installed()
|
||||
|
||||
def _compute_transifex_url(self):
|
||||
self.transifex_url = False
|
||||
self.env['transifex.translation']._update_transifex_url(self)
|
||||
|
||||
def _load_code_translations(self, module_names=None, langs=None):
|
||||
try:
|
||||
# the table lock promises translations for a (module, language) will only be created once
|
||||
self.env.cr.execute(f'LOCK TABLE {self._table} IN EXCLUSIVE MODE NOWAIT')
|
||||
|
||||
if module_names is None:
|
||||
module_names = self.env['ir.module.module'].search([('state', '=', 'installed')]).mapped('name')
|
||||
if langs is None:
|
||||
langs = [lang for lang, _ in self._get_languages() if lang != 'en_US']
|
||||
self.env.cr.execute(f'SELECT DISTINCT module, lang FROM {self._table}')
|
||||
loaded_code_translations = set(self.env.cr.fetchall())
|
||||
create_value_list = [
|
||||
{
|
||||
'source': src,
|
||||
'value': value,
|
||||
'module': module_name,
|
||||
'lang': lang,
|
||||
}
|
||||
for module_name in module_names
|
||||
for lang in langs
|
||||
if (module_name, lang) not in loaded_code_translations
|
||||
for src, value in CodeTranslations._get_code_translations(module_name, lang, lambda x: True).items()
|
||||
]
|
||||
self.sudo().create(create_value_list)
|
||||
|
||||
except psycopg2.errors.LockNotAvailable:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _open_code_translations(self):
|
||||
self._load_code_translations()
|
||||
return {
|
||||
'name': 'Code Translations',
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'transifex.code.translation',
|
||||
'view_mode': 'list',
|
||||
}
|
||||
|
||||
@api.model
|
||||
def reload(self):
|
||||
self.env.cr.execute(f'DELETE FROM {self._table}')
|
||||
return self._load_code_translations()
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import werkzeug.urls
|
||||
from configparser import ConfigParser
|
||||
from os import pardir
|
||||
from os.path import isfile, join as opj
|
||||
|
||||
import odoo
|
||||
from odoo import models, tools
|
||||
|
||||
|
||||
class TransifexTranslation(models.AbstractModel):
|
||||
_name = "transifex.translation"
|
||||
_description = "Transifex Translation"
|
||||
|
||||
@tools.ormcache()
|
||||
def _get_transifex_projects(self):
|
||||
""" get the transifex project name for each module
|
||||
|
||||
.tx/config files contains the project reference
|
||||
first section is [main], after '[odoo-16.sale]'
|
||||
|
||||
:rtype: dict
|
||||
:return: {module_name: tx_project_name}
|
||||
"""
|
||||
tx_config_file = ConfigParser()
|
||||
projects = {}
|
||||
for addon_path in odoo.addons.__path__:
|
||||
for tx_path in (
|
||||
opj(addon_path, '.tx', 'config'),
|
||||
opj(addon_path, pardir, '.tx', 'config'),
|
||||
):
|
||||
if isfile(tx_path):
|
||||
tx_config_file.read(tx_path)
|
||||
for sec in tx_config_file.sections()[1:]:
|
||||
if len(sec.split(":")) != 6:
|
||||
# old format ['main', 'odoo-16.base', ...]
|
||||
tx_project, tx_mod = sec.split(".")
|
||||
else:
|
||||
# tx_config_file.sections(): ['main', 'o:odoo:p:odoo-16:r:base', ...]
|
||||
_, _, _, tx_project, _, tx_mod = sec.split(':')
|
||||
projects[tx_mod] = tx_project
|
||||
return projects
|
||||
|
||||
def _update_transifex_url(self, translations):
|
||||
""" Update translations' Transifex URL
|
||||
|
||||
:param translations: the translations to update, may be a recordset or a list of dicts.
|
||||
The elements of `translations` must have the fields/keys 'source', 'module', 'lang',
|
||||
and the field/key 'transifex_url' is updated on them.
|
||||
"""
|
||||
|
||||
# e.g. 'https://www.transifex.com/odoo/'
|
||||
base_url = self.env['ir.config_parameter'].sudo().get_param('transifex.project_url')
|
||||
if not base_url:
|
||||
return
|
||||
base_url = base_url.rstrip('/')
|
||||
|
||||
res_langs = self.env['res.lang'].search([])
|
||||
lang_to_iso = {l.code: l.iso_code for l in res_langs}
|
||||
if not lang_to_iso:
|
||||
return
|
||||
|
||||
projects = self._get_transifex_projects()
|
||||
if not projects:
|
||||
return
|
||||
|
||||
for translation in translations:
|
||||
if not translation['source'] or translation['lang'] == 'en_US':
|
||||
continue
|
||||
|
||||
lang_iso = lang_to_iso.get(translation['lang'])
|
||||
if not lang_iso:
|
||||
continue
|
||||
|
||||
project = projects.get(translation['module'])
|
||||
if not project:
|
||||
continue
|
||||
|
||||
# e.g. https://www.transifex.com/odoo/odoo-16/translate/#fr_FR/sale/42?q=text:'Sale+Order'
|
||||
# 42 is an arbitrary number to satisfy the transifex URL format
|
||||
source = werkzeug.urls.url_quote_plus(translation['source'][:50].replace("\n", "").replace("'", "\\'"))
|
||||
source = f"'{source}'" if "+" in source else source
|
||||
translation['transifex_url'] = f"{base_url}/{project}/translate/#{lang_iso}/{translation['module']}/42?q=text%3A{source}"
|
||||
Loading…
Add table
Add a link
Reference in a new issue