summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Morel <xmo@odoo.com>2021-04-28 11:46:52 +0000
committerXavier Morel <xmo@odoo.com>2021-04-29 05:46:03 +0000
commit251b77c959af37fa0da6739ea978ca4f198414cb (patch)
tree4fdd9c7fa37aac07dc01b99e715cb9ec8f627086
parentdeaa4d7dd2690ce389be6709e1b387ae990b514f (diff)
[FIX] *: bunch of mismarked translation specifiers
`_(xyz)` will wrap them in an underscore.js object, which when used in a string context will just return the string. So it's basically a no-op, but it certainly doesn't translate the terms. closes odoo/odoo#70000 Related: odoo/enterprise#18001 Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
-rw-r--r--addons/point_of_sale/static/src/js/Screens/ClientListScreen/ClientDetailsEdit.js3
-rw-r--r--addons/pos_adyen/static/src/js/payment_adyen.js6
-rw-r--r--addons/survey/static/src/js/survey_session_manage.js2
-rw-r--r--addons/web/static/src/js/core/ajax.js2
-rw-r--r--odoo/addons/test_lint/tests/test_jstranslate.py68
5 files changed, 57 insertions, 24 deletions
diff --git a/addons/point_of_sale/static/src/js/Screens/ClientListScreen/ClientDetailsEdit.js b/addons/point_of_sale/static/src/js/Screens/ClientListScreen/ClientDetailsEdit.js
index 1ac4cf05077..facee796bed 100644
--- a/addons/point_of_sale/static/src/js/Screens/ClientListScreen/ClientDetailsEdit.js
+++ b/addons/point_of_sale/static/src/js/Screens/ClientListScreen/ClientDetailsEdit.js
@@ -1,6 +1,7 @@
odoo.define('point_of_sale.ClientDetailsEdit', function(require) {
'use strict';
+ const { _t } = require('web.core');
const { getDataURLFromFile } = require('web.utils');
const PosComponent = require('point_of_sale.PosComponent');
const Registries = require('point_of_sale.Registries');
@@ -47,7 +48,7 @@ odoo.define('point_of_sale.ClientDetailsEdit', function(require) {
if ((!this.props.partner.name && !processedChanges.name) ||
processedChanges.name === '' ){
return this.showPopup('ErrorPopup', {
- title: _('A Customer Name Is Required'),
+ title: _t('A Customer Name Is Required'),
});
}
processedChanges.id = this.props.partner.id || false;
diff --git a/addons/pos_adyen/static/src/js/payment_adyen.js b/addons/pos_adyen/static/src/js/payment_adyen.js
index 02a6afdc579..2d53c46146e 100644
--- a/addons/pos_adyen/static/src/js/payment_adyen.js
+++ b/addons/pos_adyen/static/src/js/payment_adyen.js
@@ -38,7 +38,7 @@ var PaymentAdyen = PaymentInterface.extend({
if (line) {
line.set_payment_status('retry');
}
- this._show_error(_('Could not connect to the Odoo server, please check your internet connection and try again.'));
+ this._show_error(_t('Could not connect to the Odoo server, please check your internet connection and try again.'));
return Promise.reject(data); // prevent subsequent onFullFilled's from being called
},
@@ -114,7 +114,7 @@ var PaymentAdyen = PaymentInterface.extend({
var self = this;
if (this.pos.get_order().selected_paymentline.amount < 0) {
- this._show_error(_('Cannot process transactions with negative amount.'));
+ this._show_error(_t('Cannot process transactions with negative amount.'));
return Promise.resolve();
}
@@ -150,7 +150,7 @@ var PaymentAdyen = PaymentInterface.extend({
// Only valid response is a 200 OK HTTP response which is
// represented by true.
if (! ignore_error && data !== "ok") {
- self._show_error(_('Cancelling the payment failed. Please cancel it manually on the payment terminal.'));
+ self._show_error(_t('Cancelling the payment failed. Please cancel it manually on the payment terminal.'));
}
});
},
diff --git a/addons/survey/static/src/js/survey_session_manage.js b/addons/survey/static/src/js/survey_session_manage.js
index 9af7e15d84d..dc9898e718d 100644
--- a/addons/survey/static/src/js/survey_session_manage.js
+++ b/addons/survey/static/src/js/survey_session_manage.js
@@ -330,7 +330,7 @@ publicWidget.registry.SurveySessionManage = publicWidget.Widget.extend({
// Display last screen if leaderboard activated
self.isLastQuestion = true;
self._setupLeaderboard().then(function () {
- self.$('.o_survey_session_leaderboard_title').text(_('Final Leaderboard'));
+ self.$('.o_survey_session_leaderboard_title').text(_t('Final Leaderboard'));
self.$('.o_survey_session_navigation_next').addClass('d-none');
self.$('.o_survey_leaderboard_buttons').removeClass('d-none');
self.leaderBoard.showLeaderboard(false, false);
diff --git a/addons/web/static/src/js/core/ajax.js b/addons/web/static/src/js/core/ajax.js
index a35c793e5c6..29321862d99 100644
--- a/addons/web/static/src/js/core/ajax.js
+++ b/addons/web/static/src/js/core/ajax.js
@@ -311,7 +311,7 @@ function get_file(options) {
xhr.onerror = function () {
if (options.error) {
options.error({
- message: _("Something happened while trying to contact the server, check that the server is online and that you still have a working network connection."),
+ message: _t("Something happened while trying to contact the server, check that the server is online and that you still have a working network connection."),
data: { title: _t("Could not connect to the server") }
});
}
diff --git a/odoo/addons/test_lint/tests/test_jstranslate.py b/odoo/addons/test_lint/tests/test_jstranslate.py
index 696b8bef62d..64a73a3d474 100644
--- a/odoo/addons/test_lint/tests/test_jstranslate.py
+++ b/odoo/addons/test_lint/tests/test_jstranslate.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+# pylint: disable=unbalanced-tuple-unpacking
import logging
import re
@@ -13,13 +14,16 @@ _logger = logging.getLogger(__name__)
TSTRING_RE = re.compile(r'_l?t\(\s*`.*?\s*`\s*\)', re.DOTALL)
EXPRESSION_RE = re.compile(r'\$\{.+?\}')
+UNDERSCORE_RE = re.compile(r'\b_\(\s*[\'"]')
class TestJsTranslations(lint_case.LintCase):
def check_text(self, text):
- """ Search for translated template strings that contains an expression
- :param text: The js text to search
- :return: A list of tuple with line number and invalid template string or an empty list
+ """ Search for translation errors in the text
+
+ :param text: The js text to search
+ :return: A list of tuple with line number and invalid template string,
+ or None for underscore errors
"""
error_list = list()
for m in TSTRING_RE.finditer(text):
@@ -27,6 +31,11 @@ class TestJsTranslations(lint_case.LintCase):
if EXPRESSION_RE.search(template_string):
line_nb = text[:m.start()].count('\n') + 1
error_list.append((line_nb, template_string))
+
+ for m in UNDERSCORE_RE.finditer(text):
+ lineno = text[:m.start()].count('\n') + 1
+ error_list.append((lineno, None))
+
return error_list
def test_regular_expression(self):
@@ -39,11 +48,10 @@ class TestJsTranslations(lint_case.LintCase):
"""
error_list = self.check_text(bad_js)
self.assertEqual(len(error_list), 1)
- for line, template_string in error_list:
- template_string = error_list[0][1]
- self.assertIn('invalid template-string', template_string)
- self.assertNotIn('but valid template-string', template_string)
- self.assertEqual(line, 4)
+ [(line, template_string)] = error_list
+ self.assertEqual(line, 4)
+ self.assertIn('invalid template-string', template_string)
+ self.assertNotIn('but valid template-string', template_string)
def test_regular_expression_long(self):
bad_js = """
@@ -54,25 +62,49 @@ class TestJsTranslations(lint_case.LintCase):
error_list = self.check_text(bad_js)
self.assertEqual(len(error_list), 1)
- for line, template_string in error_list:
- template_string = error_list[0][1]
- self.assertIn('foo ${this + is(a, very) - long == expression}', template_string)
- self.assertEqual(line, 2)
+ [(line, template_string)] = error_list
+ self.assertEqual(line, 2)
+ self.assertIn('foo ${this + is(a, very) - long == expression}', template_string)
+
+ def test_matches_underscore(self):
+ bad_js = """
+ const thing1 = _('literal0');
+ const thing0 = _([]);
+ const thing2 = _("literal1");
+ """
+ self.assertEqual(
+ self.check_text(bad_js),
+ [(2, None), (4, None)]
+ )
def test_js_translations(self):
- """ Test that there are no translation of JS template strings """
+ """ Test that there are no translation of JS template strings or underscore
+ calls misused as translation markers
+ """
counter = 0
failures = 0
for js_file in self.iter_module_files('*.js'):
+ # lodash has string methods and occurrences of `_('text')` in its comments
+ if js_file.endswith('/lodash.js'):
+ continue
+
counter += 1
with tools.file_open(js_file, 'r') as f:
js_txt = f.read()
- error_list = self.check_text(js_txt)
- for line_number, template_string in error_list:
- failures += 1
- mod, relative_path, _ = get_resource_from_path(js_file)
- _logger.error("Translation of a template string found in `%s/%s` at line %s: %s", mod, relative_path, line_number, template_string)
+
+ error_list = self.check_text(js_txt)
+ for line_number, template_string in error_list:
+ failures += 1
+ mod, relative_path, _ = get_resource_from_path(js_file)
+ if template_string:
+ prefix = "Translation of a template string"
+ suffix = template_string
+ else:
+ prefix = "underscore.js used as translation function"
+ suffix = "_t and _lt are the JS translation functions"
+
+ _logger.error("%s found in `%s/%s` at line %s: %s", prefix, mod, relative_path, line_number, suffix)
_logger.info('%s files tested', counter)
if failures > 0: