mirror of https://github.com/OCA/web.git
[CHG] rename web_translate_dialog_page to web_translate_dialog
parent
6357dd36b6
commit
3d51c256e0
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import orm
|
|
@ -0,0 +1,45 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{"name": "Web Translate Dialog",
|
||||
"category": "Hidden",
|
||||
"description": """
|
||||
Replace the standard translation view by an alternative one:
|
||||
|
||||
* Add a "Translate" button item in the "More" menu
|
||||
* The translations are displayed in a dialog (much like the OpenERP
|
||||
6.1's one)
|
||||
* The translation dialog displays empty fields for the untranslated fields,
|
||||
instead of the source values.
|
||||
* Support HTML fields
|
||||
|
||||
""",
|
||||
"version": "1.0",
|
||||
"depends": ['web',
|
||||
],
|
||||
'js': ['static/src/js/web_translate_dialog.js',
|
||||
],
|
||||
'css': ['static/src/css/base.css',
|
||||
],
|
||||
'qweb': ["static/src/xml/base.xml",
|
||||
],
|
||||
'auto_install': False,
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Guewen Baconnier
|
||||
# Copyright 2012-2013 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import openerp.osv.orm
|
||||
|
||||
|
||||
# add the method in the orm so we can use it from the TranslateDialog of the
|
||||
# webclient instead of the normal read
|
||||
def read_translations(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
|
||||
""" Read records with given ids with the given fields, if a field is not
|
||||
translated, its value will be False instead of the source language's value.
|
||||
|
||||
:param fields: optional list of field names to return (default: all fields would be returned)
|
||||
:type fields: list (example ['field_name_1', ...])
|
||||
:return: list of dictionaries((dictionary per record asked)) with requested field values
|
||||
:rtype: [{‘name_of_the_field’: value, ...}, ...]
|
||||
:raise AccessError: * if user has no read rights on the requested object
|
||||
* if user tries to bypass access rules for read on the requested object
|
||||
|
||||
"""
|
||||
|
||||
if context is None:
|
||||
context = {}
|
||||
self.check_access_rights(cr, user, 'read')
|
||||
fields = self.check_field_access_rights(cr, user, 'read', fields)
|
||||
if isinstance(ids, (int, long)):
|
||||
select = [ids]
|
||||
else:
|
||||
select = ids
|
||||
select = map(lambda x: isinstance(x, dict) and x['id'] or x, select)
|
||||
result = self._read_flat(cr, user, select, fields, context, load)
|
||||
|
||||
if context.get('lang') and context['lang'] != 'en_US':
|
||||
fields_pre = [f for f in fields if
|
||||
(f in self._columns and
|
||||
getattr(self._columns[f], '_classic_write'))] + \
|
||||
self._inherits.values()
|
||||
|
||||
for f in fields_pre:
|
||||
if self._columns[f].translate:
|
||||
res_ids = [x['id'] for x in result]
|
||||
res_trans = self.pool.get('ir.translation')._get_ids(
|
||||
cr, user,
|
||||
self._name + ',' + f,
|
||||
'model',
|
||||
context['lang'],
|
||||
res_ids)
|
||||
for r in result:
|
||||
if not res_trans.get(r['id']):
|
||||
r[f] = None
|
||||
|
||||
for r in result:
|
||||
for key, v in r.iteritems():
|
||||
if v is None:
|
||||
r[key] = False
|
||||
|
||||
if isinstance(ids, (int, long, dict)):
|
||||
return result and result[0] or False
|
||||
return result
|
||||
|
||||
openerp.osv.orm.BaseModel.read_translations = read_translations
|
|
@ -0,0 +1,6 @@
|
|||
.openerp .oe_trad_field {
|
||||
width: 95%;
|
||||
}
|
||||
.openerp .oe_trad_field.touched {
|
||||
border: 1px solid green !important;
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
openerp.web_translate_dialog = function (instance) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var QWeb = instance.web.qweb,
|
||||
_t = instance.web._t,
|
||||
_lt = instance.web._lt;
|
||||
|
||||
instance.web.FormView.include({
|
||||
load_form: function(data) {
|
||||
var self = this;
|
||||
this._super(data);
|
||||
this.sidebar.add_items('other', _.compact([
|
||||
self.is_action_enabled('edit') && { label: _t('Translate'), callback: self.on_button_translate },
|
||||
]));
|
||||
},
|
||||
on_button_translate: function() {
|
||||
var self = this;
|
||||
$.when(this.has_been_loaded).then(function() {
|
||||
self.open_translate_dialog(this);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.View.include({
|
||||
open_translate_dialog: function() {
|
||||
new instance.web_translate_dialog.TranslateDialog(this).open();
|
||||
}
|
||||
});
|
||||
|
||||
instance.web_translate_dialog.TranslateDialog = instance.web.Dialog.extend({
|
||||
template: "TranslateDialog",
|
||||
dialog_title: {toString: function () { return _t("Translations"); }},
|
||||
init: function(parent, options, content) {
|
||||
this._super(parent,
|
||||
{width: '90%',
|
||||
height: '80%'},
|
||||
content);
|
||||
this.view_language = this.session.user_context.lang;
|
||||
this.view = parent;
|
||||
this.view_type = parent.fields_view.type || '';
|
||||
this.$view_form = null;
|
||||
this.$sidebar_form = null;
|
||||
this.translatable_fields_keys = _.map(this.view.translatable_fields || [], function(i) { return i.name;});
|
||||
this.languages = null;
|
||||
this.languages_loaded = $.Deferred();
|
||||
(new instance.web.DataSetSearch(this,
|
||||
'res.lang',
|
||||
this.view.dataset.get_context(),
|
||||
[['translatable', '=', '1']]))
|
||||
.read_slice(['code', 'name'], { sort: 'id' })
|
||||
.then(this.on_languages_loaded);
|
||||
},
|
||||
on_languages_loaded: function(langs) {
|
||||
this.languages = langs;
|
||||
this.languages_loaded.resolve();
|
||||
},
|
||||
open: function() {
|
||||
var self = this,
|
||||
sup = this._super;
|
||||
// the template needs the languages
|
||||
$.when(this.languages_loaded).then(function() {
|
||||
// if (self.view.translatable_fields && self.view.translatable_fields.length) {
|
||||
return sup.call(self);
|
||||
});
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this.$el.find('.oe_trad_field').change(function() {
|
||||
$(this).toggleClass('touched', ($(this).val() != $(this).attr('data-value')));
|
||||
});
|
||||
this.$buttons.html(QWeb.render("TranslateDialog.buttons"));
|
||||
this.$buttons.find(".oe_form_translate_dialog_save_button").click(function(){
|
||||
self.on_button_save();
|
||||
self.on_button_close();
|
||||
});
|
||||
this.$buttons.find(".oe_form_translate_dialog_cancel_button").click(function(){
|
||||
self.on_button_close();
|
||||
});
|
||||
var $textarea = self.$el.find('textarea.oe_trad_field');
|
||||
$textarea.css({minHeight:'100px'});
|
||||
$textarea.autosize();
|
||||
this.initialize_html_fields();
|
||||
|
||||
this.do_load_fields_values();
|
||||
},
|
||||
initialize_html_fields: function() {
|
||||
this.$el.find('.oe_form_field_html textarea').each(function() {
|
||||
var $textarea = $(this);
|
||||
var width = 100; // forced to fixed size on initialization
|
||||
// will be changed to percentage right after
|
||||
// the creation
|
||||
var height = 250;
|
||||
$textarea.cleditor({
|
||||
width: width, // width not including margins, borders or padding
|
||||
height: height, // height not including margins, borders or padding
|
||||
controls: // controls to add to the toolbar
|
||||
"bold italic underline strikethrough " +
|
||||
"| removeformat | bullets numbering | outdent " +
|
||||
"indent | link unlink | source",
|
||||
bodyStyle: // style to assign to document body contained within the editor
|
||||
"margin:4px; color:#4c4c4c; font-size:13px; font-family:'Lucida Grande',Helvetica,Verdana,Arial,sans-serif; cursor:text"
|
||||
});
|
||||
|
||||
var $cleditor = $textarea.cleditor()[0];
|
||||
// Down to -- end, this is a workaround for the bug
|
||||
// https://bugs.launchpad.net/openerp-web/+bug/1258463
|
||||
// The editor is initially created with a fixed size so
|
||||
// the buggy event is not bound to $(window), then we restore
|
||||
// a percentage width and bind the "normal" event without the
|
||||
// CHM's buggy change.
|
||||
$cleditor.$main.width('95%');
|
||||
$cleditor.options.width = '95%';
|
||||
$(window).resize(function() {
|
||||
//Forcefully blurred iframe contentWindow, chrome, IE, safari doesn't trigger blur on window resize and due to which text disappears
|
||||
var contentWindow = $cleditor.$frame[0].contentWindow;
|
||||
if(!$.browser.mozilla && contentWindow){
|
||||
$(contentWindow).trigger('blur');
|
||||
}
|
||||
});
|
||||
$cleditor.refresh();
|
||||
// -- end
|
||||
|
||||
$cleditor.change(function() {
|
||||
this.updateTextArea();
|
||||
this.$area.toggleClass('touched',
|
||||
(this.$area.val() != this.$area.attr('data-value')));
|
||||
});
|
||||
});
|
||||
},
|
||||
// use a `read_translations` method instead of a `read`
|
||||
// this latter leave the fields empty if there is no
|
||||
// translation for a field instead of taking the src field
|
||||
do_load_fields_values: function(callback) {
|
||||
var self = this,
|
||||
deferred = [];
|
||||
|
||||
this.$el.find('.oe_trad_field').val('').removeClass('touched');
|
||||
_.each(self.languages, function(lg) {
|
||||
var deff = $.Deferred();
|
||||
deferred.push(deff);
|
||||
var callback = function(values) {
|
||||
};
|
||||
self.view.dataset.call(
|
||||
'read_translations',
|
||||
[[self.view.datarecord.id],
|
||||
self.translatable_fields_keys,
|
||||
self.view.dataset.get_context({
|
||||
'lang': lg.code
|
||||
})]).done(function (values) {
|
||||
_.each(self.translatable_fields_keys, function(f) {
|
||||
self.$el.find('.oe_trad_field[name="' + lg.code + '-' + f + '"]')
|
||||
.val(values[0][f] || '')
|
||||
.attr('data-value', values[0][f] || '');
|
||||
|
||||
var $tarea = self.$el.find('.oe_form_field_html .oe_trad_field[name="' + lg.code + '-' + f + '"]');
|
||||
if ($tarea.length) {
|
||||
$tarea.cleditor()[0].updateFrame();
|
||||
}
|
||||
});
|
||||
deff.resolve();
|
||||
});
|
||||
});
|
||||
return deferred;
|
||||
},
|
||||
on_button_save: function() {
|
||||
var trads = {},
|
||||
self = this,
|
||||
trads_mutex = new $.Mutex();
|
||||
self.$el.find('.oe_trad_field.touched').each(function() {
|
||||
var field = $(this).attr('name').split('-');
|
||||
if (!trads[field[0]]) {
|
||||
trads[field[0]] = {};
|
||||
}
|
||||
trads[field[0]][field[1]] = $(this).val();
|
||||
});
|
||||
_.each(trads, function(data, code) {
|
||||
if (code === self.view_language) {
|
||||
_.each(data, function(value, field) {
|
||||
self.view.fields[field].set_value(value);
|
||||
});
|
||||
}
|
||||
trads_mutex.exec(function() {
|
||||
return new instance.web.DataSet(self, self.view.dataset.model, self.view.dataset.get_context()).write(self.view.datarecord.id, data, { context : { 'lang': code }});
|
||||
});
|
||||
});
|
||||
this.close();
|
||||
},
|
||||
on_button_close: function() {
|
||||
this.close();
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
instance.web.form.AbstractField.include({
|
||||
on_translate: function() {
|
||||
// the image next to the fields opens the translate dialog
|
||||
this.view.open_translate_dialog();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<templates>
|
||||
|
||||
<t t-name="TranslateDialog">
|
||||
<table t-if="widget.view.translatable_fields" class="oe_frame oe_forms oe_translation_form" border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td class="oe_form_separator" width="1%" nowrap="nowrap">
|
||||
<div class="separator horizontal">Field</div>
|
||||
</td>
|
||||
<th t-foreach="widget.languages" align="left">
|
||||
<div class="separator horizontal"><t t-esc="name"/></div>
|
||||
</th>
|
||||
</tr>
|
||||
<tr t-foreach="widget.view.translatable_fields" t-as="field" t-att-data-field="field.name">
|
||||
<td class="oe_form_frame_cell" width="1%" nowrap="nowrap">
|
||||
<label class="oe_label"><t t-esc="field.string"/>:</label>
|
||||
</td>
|
||||
<td t-foreach="widget.languages" t-as="lg" class="oe_form_frame_cell">
|
||||
<input t-if="field.field.type == 'char' || field.field.type == 'url'" type="text" t-attf-name="#{lg.code}-#{field.name}" value="" data-value="" class="oe_trad_field"/>
|
||||
<textarea t-if="field.field.type == 'text'" t-attf-name="#{lg.code}-#{field.name}" data-value="" class="oe_trad_field" ></textarea>
|
||||
<div t-if="field.field.type == 'html'" class="oe_form_field_html">
|
||||
<textarea class="oe_trad_field oe_form_field" t-attf-name="#{lg.code}-#{field.name}" data-value=""/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<t t-name="TranslateDialog.buttons">
|
||||
<button class="oe_form_translate_dialog_save_button oe_button oe_highlight">Save</button>
|
||||
<button class="oe_form_translate_dialog_cancel_button oe_button">Cancel</button>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
Loading…
Reference in New Issue