4 if (!openerp.website.translatable) {
5 // Temporary hack until the editor bar is moved to the web client
9 var website = openerp.website;
10 website.add_template_file('/website/static/src/xml/website.translator.xml');
11 var nodialog = 'website_translator_nodialog';
13 website.EditorBar.include({
14 do_not_translate : ['-','*','!'],
15 events: _.extend({}, website.EditorBar.prototype.events, {
16 'click a[data-action=edit_master]': 'edit_master',
20 this.initial_content = {};
21 return this._super.apply(this, arguments).then(function () {
22 self.$("button[data-action=edit]").removeClass("hidden");
23 self.$('button[data-action=edit]')
25 if (website.is_editable_button) {
26 self.$('button[data-action=edit]')
27 .after(openerp.qweb.render('website.TranslatorAdditionalButtons'));
29 self.$('.js_hide_on_translate').hide();
34 var mysuper = this._super;
35 if (!localStorage[nodialog]) {
36 var dialog = new website.TranslatorDialog();
37 dialog.appendTo($(document.body));
38 dialog.on('activate', this, function () {
39 localStorage[nodialog] = dialog.$('input[name=do_not_show]').prop('checked') || '';
40 dialog.$el.modal('hide');
41 self.translate().then(function () {
43 if(self.gengo_translate){
44 self.translation_gengo_display()
49 this.translate().then(function () {
51 if(self.gengo_translate){
52 self.translation_gengo_display()
57 edit_master: function (ev) {
59 var link = $('.js_language_selector a[data-default-lang]')[0];
61 link.search += (link.search ? '&' : '?') + 'enable_editor=1';
62 window.location = link.attributes.href.value;
65 translate: function () {
67 this.translations = null;
68 return openerp.jsonRpc('/website/get_view_translations', 'call', {
69 'xml_id': $(document.documentElement).data('view-xmlid'),
70 'lang': website.get_context().lang,
71 }).then(function (translations) {
72 self.translations = translations;
73 self.processTranslatableNodes();
74 // Disable non translatable t-fields
75 $('[data-oe-type][data-oe-translate="0"]').removeAttr('data-oe-type');
78 processTranslatableNodes: function () {
80 var source_attr = 'data-oe-source-id';
81 var $editables = $('[data-oe-model="ir.ui.view"]')
83 .not('.oe_snippets,.oe_snippet, .oe_snippet *, .navbar-toggle')
84 .not('[data-oe-type]');
86 $editables.each(function () {
88 var source_id = $node.parents('[' + source_attr + ']:first').attr(source_attr)|0;
89 var view_id = $node.attr('data-oe-source-id') || source_id || $node.attr('data-oe-id');
90 self.transNode(this, view_id|0);
92 $('.oe_translatable_text').on('paste', function () {
94 setTimeout(function () {
95 self.sanitizeNode(node);
98 $(document).on('blur keyup paste', '.oe_translatable_text[contenteditable]', function(ev) {
100 setTimeout(function () {
101 // Doing stuff next tick because paste and keyup events are
102 // fired before the content is changed
103 if (ev.type == 'paste') {
104 self.sanitizeNode($node[0]);
106 if (self.getInitialContent($node[0]) !== $node.text()) {
107 $node.addClass('oe_dirty').removeClass('oe_translatable_todo oe_translatable_inprogress');
112 getInitialContent: function (node) {
113 return this.initial_content[node.attributes['data-oe-nodeid'].value];
115 sanitizeNode: function (node) {
116 node.text(node.text());
118 isTextNode: function (node) {
119 return node.nodeType === 3 || node.nodeType === 4;
121 isTranslatable: function (text) {
122 return text && _.str.trim(text) !== '';
124 markTranslatableNode: function (node, view_id) {
125 // TODO: link nodes with same content
126 node.className += ' oe_translatable_text';
127 node.setAttribute('data-oe-translation-view-id', view_id);
128 var content = node.childNodes[0].data.trim();
129 var trans = this.translations.filter(function (t) {
130 return t.res_id === view_id && t.value === content;
133 node.setAttribute('data-oe-translation-id', trans[0].id);
134 if(trans[0].gengo_translation && (trans[0].state == 'inprogress' || trans[0].state == 'to_translate')){
135 node.className += ' oe_translatable_inprogress';
138 node.className += this.do_not_translate.indexOf(node.textContent.trim()) ? ' oe_translatable_todo' : '';
140 node.contentEditable = true;
141 var nid = _.uniqueId();
142 $(node).attr('data-oe-nodeid', nid);
143 this.initial_content[nid] = content;
147 var mysuper = this._super;
149 // this._super.apply(this, arguments);
150 $('.oe_translatable_text.oe_dirty').each(function () {
152 var data = $node.data();
153 if (!trans[data.oeTranslationViewId]) {
154 trans[data.oeTranslationViewId] = [];
156 trans[data.oeTranslationViewId].push({
157 initial_content: self.getInitialContent(this),
158 new_content: $node.text(),
159 translation_id: data.oeTranslationId || null
162 openerp.jsonRpc('/website/set_translations', 'call', {
164 'lang': website.get_context()['lang'],
165 }).then(function () {
167 }).fail(function () {
168 // TODO: bootstrap alert with error message
169 alert("Could not save translation");
172 transNode: function (node, view_id) {
173 // Mostly handling text and cdata nodes here
174 // so avoid jquery usage in this function
175 if (node.attributes['data-oe-type']) {
176 if (node.attributes['data-oe-translate'].value == '1') {
177 node.className += ' oe_translatable_field';
179 } else if (node.childNodes.length === 1
180 && this.isTextNode(node.childNodes[0])
181 && !node.getAttribute('data-oe-model')) {
182 this.markTranslatableNode(node, view_id);
184 for (var i = 0, l = node.childNodes.length; i < l; i ++) {
185 var n = node.childNodes[i];
186 if (this.isTextNode(n)) {
187 if (this.isTranslatable(n.data)) {
188 var container = document.createElement('span');
189 node.insertBefore(container, n);
190 container.appendChild(n);
191 this.markTranslatableNode(container, view_id);
194 this.transNode(n, view_id);
201 website.RTE.include({
203 this._super.apply(this, arguments);
206 fetch_editables: function (root) {
207 $(root).click(function (ev) {
210 return $('[data-oe-translate="1"]');
214 website.TranslatorDialog = openerp.Widget.extend({
215 events: _.extend({}, website.EditorBar.prototype.events, {
216 'hidden.bs.modal': 'destroy',
217 'click button[data-action=activate]': function (ev) {
218 this.trigger('activate');
221 template: 'website.TranslatorDialog',