[MERGE] multilang

bzr revid: fme@openerp.com-20130926164950-n3j46k72j4bjtahw
This commit is contained in:
Fabien Meghazi 2013-09-26 18:49:50 +02:00
commit 2101023873
3 changed files with 77 additions and 38 deletions

View File

@ -294,7 +294,7 @@ class ir_translation(osv.osv):
return len(ids)
@tools.ormcache(skiparg=3)
def _get_source(self, cr, uid, name, types, lang, source=None):
def _get_source(self, cr, uid, name, types, lang, source=None, res_id=None):
"""
Returns the translation for the given combination of name, type, language
and source. All values passed to this method should be unicode (not byte strings),
@ -304,6 +304,7 @@ class ir_translation(osv.osv):
:param types: single string defining type of term to translate (see ``type`` field on ir.translation), or sequence of allowed types (strings)
:param lang: language code of the desired translation
:param source: optional source term to translate (should be unicode)
:param res_id: optional resource id to translate (if used, ``source`` should be set)
:rtype: unicode
:return: the request translation, or an empty unicode string if no translation was
found and `source` was not passed
@ -321,6 +322,9 @@ class ir_translation(osv.osv):
AND type in %s
AND src=%s"""
params = (lang or '', types, tools.ustr(source))
if res_id:
query += "AND res_id=%s"
params += (res_id,)
if name:
query += " AND name=%s"
params += (tools.ustr(name),)

View File

@ -26,6 +26,7 @@ import sys
import re
import time
import HTMLParser
from lxml import etree, html
from functools import partial
@ -253,13 +254,14 @@ class view(osv.osv):
return node
return None
def inherit_branding(self, specs_tree, view_id):
def inherit_branding(self, specs_tree, view_id, source_id):
for node in specs_tree.iterchildren(tag=etree.Element):
xpath = node.getroottree().getpath(node)
if node.tag == 'data' or node.tag == 'xpath':
self.inherit_branding(node, view_id)
self.inherit_branding(node, view_id, source_id)
else:
node.set('data-oe-id', str(view_id))
node.set('data-oe-source-id', str(source_id))
node.set('data-oe-xpath', xpath)
node.set('data-oe-model', 'ir.ui.view')
node.set('data-oe-field', 'arch')
@ -348,7 +350,7 @@ class view(osv.osv):
for (specs, view_id) in sql_inherit:
specs_tree = etree.fromstring(specs.encode('utf-8'))
if context.get('inherit_branding'):
self.inherit_branding(specs_tree, view_id)
self.inherit_branding(specs_tree, view_id, source_id)
source = self.apply_inheritance_specs(cr, uid, source, specs_tree, view_id, context=context)
source = self.apply_view_inheritance(cr, uid, source, view_id, model, context=context)
return source
@ -661,29 +663,21 @@ class view(osv.osv):
try:
id_ = int(id_)
except ValueError:
if '/' not in id_ and '.' not in id_:
if '.' not in id_:
raise ValueError('Invalid id: %r' % (id_,))
s = id_.find('/')
s = s if s >= 0 else sys.maxint
d = id_.find('.')
d = d if d >= 0 else sys.maxint
IMD = self.pool['ir.model.data']
m, _, n = id_.partition('.')
_, id_ = IMD.get_object_reference(cr, uid, m, n)
if d < s:
# xml id
IMD = self.pool['ir.model.data']
m, _, n = id_.partition('.')
_, id_ = IMD.get_object_reference(cr, uid, m, n)
else:
# path id => read directly on disk
# TODO apply inheritence
try:
with misc.file_open(id_) as f:
return f.read().decode('utf-8')
except Exception:
raise ValueError('Invalid id: %r' % (id_,))
r = self.read_combined(cr, uid, id_, fields=['arch'], context=context)
return r['arch']
arch = self.read_combined(cr, uid, id_, fields=['arch'], context=context)['arch']
arch_tree = etree.fromstring(arch)
if 'lang' in context:
arch_tree = self.translate_qweb(cr, uid, id_, arch_tree, context['lang'], context)
self.distribute_branding(arch_tree)
root = etree.Element('tpl')
root.append(arch_tree)
arch = etree.tostring(root, encoding='utf-8', xml_declaration=True)
return arch
def distribute_branding(self, e, branding=None, parent_xpath='',
index_map=misc.ConstantMapping(1)):
@ -733,15 +727,42 @@ class view(osv.osv):
for attr in node.attrib
)
def translate_qweb(self, cr, uid, id_, arch, lang, context=None):
# TODO: this should be moved in a place before inheritance is applied
# but process() is only called on fields_view_get()
Translations = self.pool['ir.translation']
h = HTMLParser.HTMLParser()
def get_trans(text):
if not text or not text.strip():
return None
text = h.unescape(text.strip())
if len(text) < 2 or (text.startswith('<!') and text.endswith('>')):
return None
# if text == 'Our Events':
# from pudb import set_trace;set_trace() ############################## Breakpoint ##############################
return Translations._get_source(cr, uid, 'website', 'view', lang, text, id_)
if arch.tag not in ['script']:
text = get_trans(arch.text)
if text:
arch.text = arch.text.replace(arch.text.strip(), text)
tail = get_trans(arch.tail)
if tail:
arch.tail = arch.tail.replace(arch.tail.strip(), tail)
for attr_name in ('title', 'alt', 'placeholder'):
attr = get_trans(arch.get(attr_name))
if attr:
arch.set(attr_name, attr)
for node in arch.iterchildren("*"):
self.translate_qweb(cr, uid, id_, node, lang, context)
return arch
def render(self, cr, uid, id_or_xml_id, values, context=None):
if not context:
context = {}
def loader(name):
arch = self.read_template(cr, uid, name, context=context)
arch_tree = etree.fromstring(arch)
self.distribute_branding(arch_tree)
root = etree.Element('tpl')
root.append(arch_tree)
arch = etree.tostring(root, encoding='utf-8', xml_declaration=True)
return arch
return self.read_template(cr, uid, name, context=context)
engine = qweb.QWebXml(loader=loader, undefined_handler=lambda key, v: None)
return engine.render(id_or_xml_id, values)

View File

@ -69,7 +69,7 @@ class QWebXml(object):
self.node = xml.dom.Node
self._t = {}
self._render_tag = {}
self._format_regex = re.compile('#\{(.*?)\}')
self._format_regex = re.compile('(#\{(.*?)\})|(\{\{(.*?)\}\})')
self._void_elements = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'])
prefix = 'render_tag_'
@ -130,7 +130,8 @@ class QWebXml(object):
use_native = True
for m in self._format_regex.finditer(expr):
use_native = False
expr = expr.replace(m.group(), self.eval_str(m.groups()[0], v))
expr = expr.replace(m.group(), self.eval_str(m.groups()[1] or m.groups()[3], v))
if not use_native:
return expr
else:
@ -236,6 +237,18 @@ class QWebXml(object):
att, val = self.eval_object(av, v)
return val and ' %s="%s"' % (att, cgi.escape(str(val), 1)) or " "
def render_att_href(self, e, an, av, v):
return self.url_for(e, an, av, v)
def render_att_src(self, e, an, av, v):
return self.url_for(e, an, av, v)
def render_att_action(self, e, an, av, v):
return self.url_for(e, an, av, v)
def url_for(self, e, an, av, v):
if 'url_for' not in v:
raise KeyError("qweb: no 'url_for' found in context")
path = str(v['url_for'](self.eval_format(av, v)))
return ' %s="%s"' % (an[2:], cgi.escape(path, 1))
# Tags
def render_tag_raw(self, e, t_att, g_att, v):
inner = self.eval_str(t_att["raw"], v)
@ -322,9 +335,9 @@ class QWebXml(object):
record = self.eval_object(record, v)
inner = None
field_type = record._model._all_columns[field].column._type
column = record._model._all_columns[field].column
try:
if field_type == 'many2one':
if column._type == 'many2one':
field_data = record.read([field])[0].get(field)
inner = field_data and field_data[1]
else:
@ -334,7 +347,7 @@ class QWebXml(object):
inner = inner.encode("utf8")
if node_name == 't':
e.nodeName = DEFAULT_TAG_BY_TYPE[field_type]
e.nodeName = DEFAULT_TAG_BY_TYPE[column._type]
g_att += ''.join(
' %s="%s"' % (name, cgi.escape(str(value), True))
@ -342,7 +355,8 @@ class QWebXml(object):
('data-oe-model', record._model._name),
('data-oe-id', str(record.id)),
('data-oe-field', field),
('data-oe-type', field_type),
('data-oe-type', column._type),
('data-oe-translate', '1' if column.translate else '0'),
('data-oe-expression', t_att['field']),
]
)