[FIX] Gengo - Update modoel ir_translation for gengo and make it working. Works with...
[odoo/odoo.git] / addons / website / static / src / js / website.translator.js
1 (function () {
2     'use strict';
3
4     var website = openerp.website;
5     website.add_template_file('/website/static/src/xml/website.translator.xml');
6     var nodialog = 'website_translator_nodialog';
7
8     website.EditorBar.include({
9         do_not_translate : ['-','*','!'],
10         events: _.extend({}, website.EditorBar.prototype.events, {
11             'click a[data-action=edit_master]': 'edit_master',
12         }),
13         start: function () {
14             var self = this;
15             this.initial_content = {};
16             return this._super.apply(this, arguments).then(function () {
17                 self.$("button[data-action=edit]").removeClass("hidden");
18                 self.$('button[data-action=edit]')
19                     .text("Translate");
20                 if (website.is_editable_button) {
21                     self.$('button[data-action=edit]')
22                         .after(openerp.qweb.render('website.TranslatorAdditionalButtons'));
23                 }
24                 self.$('.js_hide_on_translate').hide();
25             });
26         },
27         edit: function () {
28             var self = this;
29             var mysuper = this._super;
30             if (!localStorage[nodialog]) {
31                 var dialog = new website.TranslatorDialog();
32                 dialog.appendTo($(document.body));
33                 dialog.on('activate', this, function () {
34                     localStorage[nodialog] = dialog.$('input[name=do_not_show]').prop('checked') || '';
35                     dialog.$el.modal('hide');
36                     self.translate().then(function () {
37                         mysuper.call(self);
38                         if(self.gengo_translate){
39                             self.translation_gengo_display()
40                         }
41                     });
42                 });
43             } else {
44                 this.translate().then(function () {
45                     mysuper.call(self);
46                     if(self.gengo_translate){
47                         self.translation_gengo_display()
48                     }
49                 });
50             }
51         },
52         edit_master: function (ev) {
53             ev.preventDefault();
54             var link = $('.js_language_selector a[data-default-lang]')[0];
55             if (link) {
56                 link.search += (link.search ? '&' : '?') + 'enable_editor=1';
57                 window.location = link.attributes.href.value;
58             }
59         },
60         translate: function () {
61             var self = this;
62             this.translations = null;
63             return openerp.jsonRpc('/website/get_view_translations', 'call', {
64                 'xml_id': $(document.documentElement).data('view-xmlid'),
65                 'lang': website.get_context().lang,
66             }).then(function (translations) {
67                 self.translations = translations;
68                 self.processTranslatableNodes();
69                 // Disable non translatable t-fields
70                 $('[data-oe-type][data-oe-translate="0"]').removeAttr('data-oe-type');
71             });
72         },
73         processTranslatableNodes: function () {
74             var self = this;
75             var source_attr = 'data-oe-source-id';
76             var $editables = $('[data-oe-model="ir.ui.view"]')
77                     .not('link, script')
78                     .not('.oe_snippets,.oe_snippet, .oe_snippet *, .navbar-toggle')
79                     .not('[data-oe-type]');
80
81             $editables.each(function () {
82                 var $node = $(this);
83                 var source_id = $node.parents('[' + source_attr + ']:first').attr(source_attr)|0;
84                 var view_id = $node.attr('data-oe-source-id') || source_id || $node.attr('data-oe-id');
85                 self.transNode(this, view_id|0);
86             });
87             $('.oe_translatable_text').on('paste', function () {
88                 var node = $(this);
89                 setTimeout(function () {
90                     self.sanitizeNode(node);
91                 }, 0);
92             });
93             $(document).on('blur keyup paste', '.oe_translatable_text[contenteditable]', function(ev) {
94                 var $node = $(this);
95                 setTimeout(function () {
96                     // Doing stuff next tick because paste and keyup events are
97                     // fired before the content is changed
98                     if (ev.type == 'paste') {
99                         self.sanitizeNode($node[0]);
100                     }
101                     if (self.getInitialContent($node[0]) !== $node.text()) {
102                         $node.addClass('oe_dirty').removeClass('oe_translatable_todo oe_translatable_inprogress');
103                     }
104                 }, 0);
105             });
106         },
107         getInitialContent: function (node) {
108             return this.initial_content[node.attributes['data-oe-nodeid'].value];
109         },
110         sanitizeNode: function (node) {
111             node.text(node.text());
112         },
113         isTextNode: function (node) {
114             return node.nodeType === 3 || node.nodeType === 4;
115         },
116         isTranslatable: function (text) {
117             return text && _.str.trim(text) !== '';
118         },
119         markTranslatableNode: function (node, view_id) {
120             // TODO: link nodes with same content
121             node.className += ' oe_translatable_text';
122             node.setAttribute('data-oe-translation-view-id', view_id);
123             var content = node.childNodes[0].data.trim();
124             var trans = this.translations.filter(function (t) {
125                 return t.res_id === view_id && t.value === content;
126             });
127             if (trans.length) {
128                 node.setAttribute('data-oe-translation-id', trans[0].id);
129                 if(trans[0].gengo_translation && (trans[0].state == 'inprogress' || trans[0].state == 'to_translate')){
130                         node.className += ' oe_translatable_inprogress';
131                 }
132             } else {
133                 node.className += this.do_not_translate.indexOf(node.textContent.trim()) ? ' oe_translatable_todo' : '';
134             }
135             node.contentEditable = true;
136             var nid = _.uniqueId();
137             $(node).attr('data-oe-nodeid', nid);
138             this.initial_content[nid] = content;
139         },
140         save: function () {
141             var self = this;
142             var mysuper = this._super;
143             var trans = {};
144             // this._super.apply(this, arguments);
145             $('.oe_translatable_text.oe_dirty').each(function () {
146                 var $node = $(this);
147                 var data = $node.data();
148                 if (!trans[data.oeTranslationViewId]) {
149                     trans[data.oeTranslationViewId] = [];
150                 }
151                 trans[data.oeTranslationViewId].push({
152                     initial_content: self.getInitialContent(this),
153                     new_content: $node.text(),
154                     translation_id: data.oeTranslationId || null
155                 });
156             });
157             openerp.jsonRpc('/website/set_translations', 'call', {
158                 'data': trans,
159                 'lang': website.get_context()['lang'],
160             }).then(function () {
161                 mysuper.call(self);
162             }).fail(function () {
163                 // TODO: bootstrap alert with error message
164                 alert("Could not save translation");
165             });
166         },
167         transNode: function (node, view_id) {
168             // Mostly handling text and cdata nodes here
169             // so avoid jquery usage in this function
170             if (node.attributes['data-oe-type']) {
171                 if (node.attributes['data-oe-translate'].value == '1') {
172                     node.className += ' oe_translatable_field';
173                 }
174             } else if (node.childNodes.length === 1
175                     && this.isTextNode(node.childNodes[0])
176                     && !node.getAttribute('data-oe-model')) {
177                 this.markTranslatableNode(node, view_id);
178             } else {
179                 for (var i = 0, l = node.childNodes.length; i < l; i ++) {
180                     var n = node.childNodes[i];
181                     if (this.isTextNode(n)) {
182                         if (this.isTranslatable(n.data)) {
183                             var container = document.createElement('span');
184                             node.insertBefore(container, n);
185                             container.appendChild(n);
186                             this.markTranslatableNode(container, view_id);
187                         }
188                     } else {
189                         this.transNode(n, view_id);
190                     }
191                 }
192             }
193         },
194     });
195
196     website.RTE.include({
197         start: function () {
198             this._super.apply(this, arguments);
199             this.$el.hide();
200         },
201         fetch_editables: function (root) {
202             $(root).click(function (ev) {
203                 ev.preventDefault();
204             });
205             return $('[data-oe-translate="1"]');
206         }
207     });
208
209     website.TranslatorDialog = openerp.Widget.extend({
210         events: _.extend({}, website.EditorBar.prototype.events, {
211             'hidden.bs.modal': 'destroy',
212             'click button[data-action=activate]': function (ev) {
213                 this.trigger('activate');
214             },
215         }),
216         template: 'website.TranslatorDialog',
217         start: function () {
218             this.$el.modal();
219         },
220     });
221 })();