summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/widgets/translation_dialog.js
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/src/js/widgets/translation_dialog.js
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/web/static/src/js/widgets/translation_dialog.js')
-rw-r--r--addons/web/static/src/js/widgets/translation_dialog.js183
1 files changed, 183 insertions, 0 deletions
diff --git a/addons/web/static/src/js/widgets/translation_dialog.js b/addons/web/static/src/js/widgets/translation_dialog.js
new file mode 100644
index 00000000..efdba7b3
--- /dev/null
+++ b/addons/web/static/src/js/widgets/translation_dialog.js
@@ -0,0 +1,183 @@
+odoo.define('web.TranslationDialog', function (require) {
+ 'use strict';
+
+ var core = require('web.core');
+ var Dialog = require('web.Dialog');
+ var session = require('web.session');
+
+ var _t = core._t;
+
+ var TranslationDialog = Dialog.extend({
+ xmlDependencies: (Dialog.prototype.xmlDependencies || [])
+ .concat(['/web/static/src/xml/translation_dialog.xml']),
+ template: 'TranslationDialog',
+
+ /**
+ * @constructor
+ * @param {Widget} parent
+ * @param {Object} [options]
+ * @param {string} [options.domain] the domain needed to get the translation terms
+ * @param {string} [options.fieldName] the name of the field currently translated (from the model of the form view)
+ * @param {string} [options.searchName] the name of the actual field that is the reference for translation (in the form of model,field)
+ * @param {string} [options.userLanguageValue] the value of the translation in the language of the user, as seen in the from view (might be empty)
+ * @param {string} [options.dataPointID] the data point id of the record for which we do the translations
+ * @param {boolean} [options.isComingFromTranslationAlert] the initiator of the dialog, might be a link on a field or the translation alert on top of the form
+ * @param {boolean} [options.isText] is the field a text field (multiline) or char (single line)
+ * @param {boolean} [options.showSrc] is the source of the translation should be rendered (for partial translations, i.e. XML content)
+ *
+ */
+ init: function (parent, options) {
+ options = options || {};
+
+ this.fieldName = options.fieldName;
+ this.domain = options.domain;
+ this.searchName = options.searchName;
+ this.userLanguageValue = options.userLanguageValue;
+ this.domain.push(['name', "=", `${this.searchName}`]);
+ this.dataPointID = options.dataPointID;
+ this.isComingFromTranslationAlert = options.isComingFromTranslationAlert;
+ this.currentInterfaceLanguage = session.user_context.lang;
+ this.isText = options.isText;
+ this.showSrc = options.showSrc;
+
+ this._super(parent, _.extend({
+ size: 'large',
+ title: _t('Translate: ') + `${this.fieldName}`,
+ buttons: [
+ { text: _t('Save'), classes: 'btn-primary', close: true, click: this._onSave.bind(this) },
+ { text: _t('Discard'), close: true },
+ ],
+ }, options));
+ },
+ /**
+ * @override
+ */
+ willStart: function () {
+ return Promise.all([
+ this._super(),
+ this._loadLanguages().then((l) => {
+ this.languages = l;
+ return this._loadTranslations().then((t) => {
+ this.translations = t;
+ });
+ }),
+ ]).then(() => {
+ this.data = this.translations.map((term) => {
+ let relatedLanguage = this.languages.find((language) => language[0] === term.lang);
+ if (!term.value && !this.showSrc) {
+ term.value = term.src;
+ }
+ return {
+ id: term.id,
+ lang: term.lang,
+ langName: relatedLanguage[1],
+ source: term.src,
+ // we set the translation value coming from the database, except for the language
+ // the user is currently utilizing. Then we set the translation value coming
+ // from the value of the field in the form
+ value: (term.lang === this.currentInterfaceLanguage &&
+ !this.showSrc &&
+ !this.isComingFromTranslationAlert) ?
+ this.userLanguageValue : term.value || ''
+ };
+ });
+ this.data.sort((left, right) =>
+ (left.langName < right.langName || (left.langName === right.langName && left.source < right.source)) ? -1 : 1);
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+ /**
+ * Load the translation terms for the installed language, for the current model and res_id
+ * @private
+ */
+ _loadTranslations: function () {
+ const domain = [...this.domain, ['lang', 'in', this.languages.map(l => l[0])]];
+ return this._rpc({
+ model: 'ir.translation',
+ method: 'search_read',
+ fields: ['lang', 'src', 'value'],
+ domain: domain,
+ });
+ },
+ /**
+ * Load the installed languages long names and code
+ *
+ * The result of the call is put in cache on the prototype of this dialog.
+ * If any new language is installed, a full page refresh will happen,
+ * so there is no need invalidate it.
+ * @private
+ */
+ _loadLanguages: function () {
+ if (TranslationDialog.prototype.installedLanguagesCache)
+ return Promise.resolve(TranslationDialog.prototype.installedLanguagesCache);
+
+ return this._rpc({
+ model: 'res.lang',
+ method: 'get_installed',
+ fields: ['code', 'name', 'iso_code'],
+ }).then((installedLanguages) => {
+ TranslationDialog.prototype.installedLanguagesCache = installedLanguages;
+ return TranslationDialog.prototype.installedLanguagesCache
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+ /**
+ * Save all the terms that have been updated
+ * @private
+ * @returns a promise that is resolved when all the save have occured
+ */
+ _onSave: function () {
+ var updatedTerm = {};
+ var updateFormViewField;
+
+ this.el.querySelectorAll('input[type=text],textarea').forEach((t) => {
+ var initialValue = this.data.find((d) => d.id == t.dataset.id);
+ if (initialValue.value !== t.value) {
+ updatedTerm[t.dataset.id] = t.value;
+
+ if (initialValue.lang === this.currentInterfaceLanguage && !this.showSrc) {
+ // when the user has changed the term for the language he is
+ // using in the interface, this change should be reflected
+ // in the form view
+ // partial translations being handled server side are
+ // also ignored
+ var changes = {};
+ changes[this.fieldName] = updatedTerm[initialValue.id];
+ updateFormViewField = {
+ dataPointID: this.dataPointID,
+ changes: changes,
+ doNotSetDirty: false,
+ };
+ }
+ }
+ });
+
+ // updatedTerm only contains the id and values of the terms that
+ // have been updated by the user
+ var saveUpdatedTermsProms = Object.keys(updatedTerm).map((id) => {
+ var writeTranslation = {
+ model: 'ir.translation',
+ method: 'write',
+ context: this.context,
+ args: [[parseInt(id, 10)], { value: updatedTerm[id] }]
+ };
+ return this._rpc(writeTranslation);
+ });
+ return Promise.all(saveUpdatedTermsProms).then(() => {
+ // we might have to update the value of the field on the form
+ // view that opened the translation dialog
+ if (updateFormViewField) {
+ this.trigger_up('field_changed', updateFormViewField);
+ }
+ });
+ }
+ });
+
+ return TranslationDialog;
+});