[ADD] Translator

bzr revid: fme@openerp.com-20130923115417-bq20piq7f11pyjve
This commit is contained in:
Fabien Meghazi
2013-09-23 13:54:17 +02:00
parent 366843b002
commit b783cbf4a6
4 changed files with 241 additions and 0 deletions
+21
View File
@@ -107,6 +107,27 @@ table.editorbar-panel td.selected {
background-color: #b1c9d9;
}
.oe_translate_examples li {
margin: 10px;
padding: 4px;
}
.oe_translatable_text {
outline: 1px solid black;
}
.oe_translatable_field {
outline: 1px dashed black;
}
.oe_translatable_text.oe_dirty, .oe_translatable_field.oe_dirty {
outline-color: red;
}
.oe_translatable_todo {
background: #ffffb6;
}
/* ---- RTE ---- */
.oe_editable .btn {
-webkit-user-select: auto;
+16
View File
@@ -93,6 +93,20 @@ table.editorbar-panel
td.selected
background-color: #b1c9d9
// ---- TRANSLATIONS ---- {{{
.oe_translate_examples li
margin: 10px
padding: 4px
.oe_translatable_text
outline: 1px solid black
.oe_translatable_field
outline: 1px dashed black
.oe_translatable_text.oe_dirty, .oe_translatable_field.oe_dirty
outline-color: red
.oe_translatable_todo
background: rgb(255, 255, 182)
// }}}
/* ---- RTE ---- */
// bootstrap makes .btn elements unselectable -> RTE double-click can't know
@@ -481,3 +495,5 @@ $navbar_height: 51px
&.oe_ace_closed
width: 0
opacity: 0
// vim:tabstop=4:shiftwidth=4:softtabstop=4:fdm=marker:
@@ -0,0 +1,151 @@
(function () {
'use strict';
var website = openerp.website;
website.templates.push('/website/static/src/xml/website.translator.xml');
website.EditorBar.include({
events: _.extend({}, website.EditorBar.prototype.events, {
'click a[data-action=js_website_translator]': function (ev) {
var self = this;
ev.preventDefault();
if (!localStorage['website_translator_nodialog']) {
var dialog = new website.TranslatorDialog();
dialog.appendTo($(document.body));
dialog.on('activate', this, function () {
dialog.$el.modal('hide');
this.translateMode();
});
} else {
this.translateMode();
}
},
}),
temporaryHack: function() {
// TODO: refactor once xmo's feature branch is merged
debugger
this.$buttons.edit.prop('disabled', true);
this.$('#website-top-view').hide();
this.$('#website-top-edit').show();
$('.css_non_editable_mode_hidden').removeClass("css_non_editable_mode_hidden");
this.$el.find('[data-action=snippet]').hide();
this.save = this.saveTranslations;
},
translateMode: function () {
var self = this;
this.temporaryHack();
// this.edit(); -- Will need a translation mode
this.translations = null;
openerp.jsonRpc('/website/get_view_translations', 'call', {
'xml_id': $(document.documentElement).data('view-xmlid'),
'context': website.get_context(),
}).then(function (translations) {
self.translations = translations;
self.processTranslatableNodes();
});
},
processTranslatableNodes: function () {
var self = this;
var $editables = $('[data-oe-model]')
.not('link, script')
.not('.oe_snippets,.oe_snippet, .oe_snippet *')
.not('[data-oe-type]');
$editables.each(function () {
self.transNode(this);
});
$('.oe_translatable_text').prop('contenteditable', true).on('paste', function () {
var node = $(this);
setTimeout(function () {
self.sanitizeNode(node);
}, 0);
});
$(document).on('blur keyup paste', '.oe_translatable_text[contenteditable]', function(ev) {
var $node = $(this);
setTimeout(function () {
// Doing stuff next tick because past and keyup are
// fired before the content is changed
if (ev.type == 'paste') {
self.sanitizeNode($node[0]);
}
if ($node.data('initial_content') !== $node.text()) {
$node.addClass('oe_dirty').removeClass('oe_translatable_todo');
}
}, 0);
});
},
sanitizeNode: function (node) {
node.text(node.text());
},
isTextNode: function (node) {
return node.nodeType === 3 || node.nodeType === 4;
},
isTranslatable: function (text) {
return text && _.str.trim(text) !== '';
},
markTranslatableNode: function (node) {
// TODO: link nodes with same content
node.className += ' oe_translatable_text oe_translatable_todo';
node.contentEditable = true;
$(node).data('initial_content', node.childNodes[0].data);
},
saveTranslations: function () {
var trans = {};
$('.oe_translatable_text.oe_dirty').each(function () {
var $node = $(this);
var text = $node.text();
var view_id = $(this).parents('[data-oe-model="ir.ui.view"]')
.not('[data-oe-type]').first().data().oeId;
if (!trans[view_id]) {
trans[view_id] = [];
}
trans[view_id].push({
initial_content: $node.data('initial_content'),
new_content: text
});
});
openerp.jsonRpc('/website/set_translations', 'call', {
'data': trans,
'lang': website.get_context()['lang'],
}).then(function () {
website.reload();
}).fail(function () {
// TODO: bootstrap alert with error message
alert("Could not save translation");
});
},
transNode: function (node, context) {
if (node.childNodes.length === 1
&& this.isTextNode(node.childNodes[0])
&& !node.getAttribute('data-oe-model')) {
this.markTranslatableNode(node);
} else {
for (var i = 0, l = node.childNodes.length; i < l; i ++) {
var n = node.childNodes[i];
if (this.isTextNode(n)) {
if (this.isTranslatable(n.data)) {
var container = document.createElement('span');
node.insertBefore(container, n);
container.appendChild(n);
this.markTranslatableNode(container);
}
} else {
this.transNode(n);
}
}
}
},
});
website.TranslatorDialog = openerp.Widget.extend({
events: _.extend({}, website.EditorBar.prototype.events, {
'hidden.bs.modal': 'destroy',
'click button[data-action=activate]': function (ev) {
this.trigger('activate');
},
}),
template: 'website.TranslatorDialog',
start: function () {
this.$el.modal();
},
});
})();
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<templates id="template" xml:space="preserve">
<t t-name="website.TranslatorDialog">
<div class="modal fade oe_website_translator" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button title="Close" type="button" class="close" data-dismiss="modal">×</button>
<h2 class="modal-title">Translate this page</h2>
</div>
<div class="modal-body">
<section>
<p>
You are about to enter the translation mode.
</p>
<p>
In this mode you can not change the structure of the document, you can only translate text.
</p>
<p>
Here are the visuals used in order to help you in your translation flow:
<ul class="oe_translate_examples">
<li class="oe_translatable_text">
Normal translatable content
</li>
<li class="oe_translatable_field">
ERP translatable object data
</li>
<li class="oe_translatable_todo">
Translation TODO
</li>
</ul>
</p>
</section>
<hr/>
<section class="row">
<div class="col-md-6">
<button type="button" data-action="activate" class="btn btn-primary">Ok</button>
or
<a data-action="discard" data-dismiss="modal" href="#">Cancel</a>
</div>
<div class="col-md-6">
<label>
<input type="checkbox" name="do_not_show"/>
Do not show this dialog later.
</label>
</div>
</section>
</div>
</div>
</div>
</div>
</t>
</templates>