[IMP] *: unify sprintf and gettext
Improve gettext to directly handle value injection within translations, removing the need for sprintf. closes odoo/odoo#123932 Related: odoo/enterprise#45370 Signed-off-by: Samuel Degueldre (sad) <sad@odoo.com>
This commit is contained in:
@@ -12,7 +12,6 @@ import {OptimizeSEODialog} from '@website/components/dialog/seo';
|
||||
import { WebsiteDialog } from "@website/components/dialog/dialog";
|
||||
import { routeToUrl } from "@web/core/browser/router_service";
|
||||
import { getActiveHotkey } from "@web/core/hotkeys/hotkey_service";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import wUtils from '@website/js/utils';
|
||||
import config from "@web/legacy/js/services/config";
|
||||
|
||||
@@ -70,10 +69,7 @@ export class WebsitePreview extends Component {
|
||||
// same session and CORS errors won't be a thing in such a case)
|
||||
this.dialogService.add(WebsiteDialog, {
|
||||
title: this.env._t("Redirecting..."),
|
||||
body: sprintf(this.env._t(
|
||||
"You are about to be redirected to the domain configured for your website ( %s ). " +
|
||||
"This is necessary to edit or view your website from the Website app. You might need to log back in."
|
||||
), this.websiteDomain),
|
||||
body: this.env._t("You are about to be redirected to the domain configured for your website ( %s ). This is necessary to edit or view your website from the Website app. You might need to log back in.", this.websiteDomain),
|
||||
showSecondaryButton: false,
|
||||
}, {
|
||||
onClose: () => {
|
||||
|
||||
@@ -5,7 +5,6 @@ import {registry} from '@web/core/registry';
|
||||
import {listView} from '@web/views/list/list_view';
|
||||
import {ConfirmationDialog} from "@web/core/confirmation_dialog/confirmation_dialog";
|
||||
import {useService} from "@web/core/utils/hooks";
|
||||
import {sprintf} from "@web/core/utils/strings";
|
||||
import {DeletePageDialog} from '@website/components/dialog/page_properties';
|
||||
import {SearchDropdownItem} from "@web/search/search_dropdown_item/search_dropdown_item";
|
||||
|
||||
@@ -44,12 +43,7 @@ export class PageListController extends PageControllerMixin(listView.Controller)
|
||||
callback: async () => {
|
||||
this.dialogService.add(ConfirmationDialog, {
|
||||
title: this.env._t("Publish Website Content"),
|
||||
body: sprintf(
|
||||
this.env._t(
|
||||
"%s record(s) selected, are you sure you want to publish them all?"
|
||||
),
|
||||
this.model.root.selection.length
|
||||
),
|
||||
body: this.env._t("%s record(s) selected, are you sure you want to publish them all?", this.model.root.selection.length),
|
||||
confirm: () => this.togglePublished(true),
|
||||
});
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import core from "@web/legacy/js/services/core";
|
||||
import { loadBundle, loadCSS } from "@web/core/assets";
|
||||
import Dialog from "@web/legacy/js/core/dialog";
|
||||
import { Markup, sprintf } from "@web/legacy/js/core/utils";
|
||||
import { Markup } from "@web/legacy/js/core/utils";
|
||||
import weUtils from "@web_editor/js/common/utils";
|
||||
import options from "@web_editor/js/editor/snippets.options";
|
||||
import { NavbarLinkPopoverWidget } from "@website/js/widgets/link_popover_widget";
|
||||
@@ -2807,7 +2807,7 @@ options.registry.anchor = options.Class.extend({
|
||||
_buildClipboard(buttonEl) {
|
||||
const clipboard = new ClipboardJS(buttonEl, {text: () => this._getAnchorLink()});
|
||||
clipboard.on("success", () => {
|
||||
const message = sprintf(Markup(_t("Anchor copied to clipboard<br>Link: %s")), this._getAnchorLink());
|
||||
const message = Markup(_t("Anchor copied to clipboard<br>Link: %s", this._getAnchorLink()));
|
||||
this.displayNotification({
|
||||
type: "success",
|
||||
message: message,
|
||||
|
||||
@@ -4,7 +4,6 @@ import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
import { Markup } from "@web/legacy/js/core/utils";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
function addMedia(position = "right") {
|
||||
return {
|
||||
@@ -106,7 +105,7 @@ function changeOption(optionName, weName = '', optionTooltipLabel = '', position
|
||||
const option_block = `${noPalette} we-customizeblock-option[class='snippet-option-${optionName}']`;
|
||||
return {
|
||||
trigger: `${option_block} ${weName}, ${option_block} [title='${weName}']`,
|
||||
content: Markup(sprintf(_t("<b>Click</b> on this option to change the %s of the block."), optionTooltipLabel)),
|
||||
content: Markup(_t("<b>Click</b> on this option to change the %s of the block.", optionTooltipLabel)),
|
||||
position: position,
|
||||
in_modal: false,
|
||||
run: "click",
|
||||
@@ -118,7 +117,7 @@ function selectNested(trigger, optionName, alt_trigger = null, optionTooltipLabe
|
||||
const option_block = `${noPalette} we-customizeblock-option[class='snippet-option-${optionName}']`;
|
||||
return {
|
||||
trigger: trigger,
|
||||
content: Markup(sprintf(_t("<b>Select</b> a %s."), optionTooltipLabel)),
|
||||
content: Markup(_t("<b>Select</b> a %s.", optionTooltipLabel)),
|
||||
alt_trigger: alt_trigger == null ? undefined : `${option_block} ${alt_trigger}`,
|
||||
position: position,
|
||||
run: 'click',
|
||||
@@ -135,7 +134,7 @@ function changePaddingSize(direction) {
|
||||
}
|
||||
return {
|
||||
trigger: `iframe .oe_overlay.ui-draggable.o_we_overlay_sticky.oe_active .o_handle.${paddingDirection}`,
|
||||
content: Markup(sprintf(_t("<b>Slide</b> this button to change the %s padding"), direction)),
|
||||
content: Markup(_t("<b>Slide</b> this button to change the %s padding", direction)),
|
||||
consumeEvent: 'mousedown',
|
||||
position: position,
|
||||
};
|
||||
@@ -235,7 +234,7 @@ function dragNDrop(snippet, position = "bottom") {
|
||||
return {
|
||||
trigger: `#oe_snippets .oe_snippet[name="${snippet.name}"] .oe_snippet_thumbnail:not(.o_we_already_dragging)`,
|
||||
extra_trigger: ".o_website_preview.editor_enable.editor_has_snippets",
|
||||
content: Markup(sprintf(_t("Drag the <b>%s</b> building block and drop it at the bottom of the page."), snippet.name)),
|
||||
content: Markup(_t("Drag the <b>%s</b> building block and drop it at the bottom of the page.", snippet.name)),
|
||||
position: position,
|
||||
// Normally no main snippet can be dropped in the default footer but
|
||||
// targeting it allows to force "dropping at the end of the page".
|
||||
|
||||
@@ -4,7 +4,6 @@ import { registry } from "@web/core/registry";
|
||||
import { EditMenuDialog } from '@website/components/dialog/edit_menu';
|
||||
import { OptimizeSEODialog } from '@website/components/dialog/seo';
|
||||
import {PagePropertiesDialog} from '@website/components/dialog/page_properties';
|
||||
import {sprintf} from '@web/core/utils/strings';
|
||||
|
||||
/**
|
||||
* This service displays contextual menus, depending of the state of the
|
||||
@@ -53,7 +52,7 @@ export const websiteCustomMenus = {
|
||||
// 'navbar menus' display system.
|
||||
filteredSections.push(...website.currentWebsite.metadata.contentMenus.map((menu, index) => ({
|
||||
...section,
|
||||
name: sprintf(env._t("Edit %s"), menu[0]),
|
||||
name: env._t("Edit %s", menu[0]),
|
||||
dynamicProps: {rootID: parseInt(menu[1], 10)},
|
||||
// Prevent a 't-foreach' duplicate key on menus template.
|
||||
id: `${section.id}-${index}`,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import publicWidget from "@web/legacy/js/public/public_widget";
|
||||
import dom from "@web/legacy/js/core/dom";
|
||||
import concurrency from "@web/legacy/js/core/concurrency";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { debounce } from "@web/core/utils/timing";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
@@ -284,12 +283,15 @@
|
||||
if (!self.check_error_fields({})) {
|
||||
if (this.fileInputError) {
|
||||
const errorMessage = this.fileInputError.type === "number"
|
||||
? sprintf(_t(
|
||||
"Please fill in the form correctly. You uploaded too many files. (Maximum %s files)"
|
||||
), this.fileInputError.limit)
|
||||
: sprintf(_t(
|
||||
"Please fill in the form correctly. The file \"%s\" is too big. (Maximum %s MB)"
|
||||
), this.fileInputError.fileName, this.fileInputError.limit);
|
||||
? _t(
|
||||
"Please fill in the form correctly. You uploaded too many files. (Maximum %s files)",
|
||||
this.fileInputError.limit
|
||||
)
|
||||
: _t(
|
||||
"Please fill in the form correctly. The file \"%s\" is too big. (Maximum %s MB)",
|
||||
this.fileInputError.fileName,
|
||||
this.fileInputError.limit
|
||||
);
|
||||
this.update_status("error", errorMessage);
|
||||
delete this.fileInputError;
|
||||
} else {
|
||||
@@ -580,13 +582,13 @@
|
||||
if (datetime.isValid()) {
|
||||
return time.datetime_to_str(datetime.toDate());
|
||||
}
|
||||
throw new Error(sprintf(_t("'%s' is not a correct datetime"), value));
|
||||
throw new Error(_t("'%s' is not a correct datetime", value));
|
||||
case 'date':
|
||||
var date = moment(value, [date_pattern, date_pattern_wo_zero], true);
|
||||
if (date.isValid()) {
|
||||
return time.date_to_str(date.toDate());
|
||||
}
|
||||
throw new Error(sprintf(_t("'%s' is not a correct date"), value));
|
||||
throw new Error(_t("'%s' is not a correct date", value));
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
@@ -7,7 +7,6 @@ import Dialog from "@web/legacy/js/core/dialog";
|
||||
import dom from "@web/legacy/js/core/dom";
|
||||
import weUtils from "@web_editor/js/common/utils";
|
||||
import "@website/js/editor/snippets.options";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { unique } from "@web/core/utils/arrays";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
@@ -1370,7 +1369,7 @@ options.registry.WebsiteFieldEditor = FieldEditor.extend({
|
||||
const list = document.createElement('we-list');
|
||||
const optionText = select ? 'Option' : type === 'selection' ? 'Radio' : 'Checkbox';
|
||||
list.setAttribute('string', `${optionText} List`);
|
||||
list.dataset.addItemTitle = sprintf(_t("Add new %s"), optionText);
|
||||
list.dataset.addItemTitle = _t("Add new %s", optionText);
|
||||
list.dataset.renderListItems = '';
|
||||
|
||||
list.dataset.hasDefault = ['one2many', 'many2many'].includes(type) ? 'multiple' : 'unique';
|
||||
@@ -1586,8 +1585,7 @@ options.registry.WebsiteFormFieldRequired = DisableOverlayButtonOption.extend({
|
||||
const fieldName = this.$target[0]
|
||||
.querySelector("input.s_website_form_input").getAttribute("name");
|
||||
const spanEl = document.createElement("span");
|
||||
spanEl.innerText = sprintf(_t(
|
||||
"The field '%s' is mandatory for the action '%s'."), fieldName, currentActionName);
|
||||
spanEl.innerText = _t("The field '%s' is mandatory for the action '%s'.", fieldName, currentActionName);
|
||||
uiFragment.querySelector("we-alert").appendChild(spanEl);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -216,9 +216,7 @@ export class NewContentModal extends Component {
|
||||
}
|
||||
return el;
|
||||
});
|
||||
this.website.showLoader({
|
||||
title: sprintf(this.env._t("Building your %s"), name),
|
||||
});
|
||||
this.website.showLoader({ title: this.env._t("Building your %s", name) });
|
||||
try {
|
||||
await this.installModule(id, element.redirectUrl);
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user