[FIX] web: views: translate terms with right context and domain
Before this commit, when clicking on the translate button on a translatable field, the translate dialog had too much data, among them wrong data because the domain to fetch them was wrong. The context was also wrong. This lead to a crash in subsequent operations (modify and save) After this commit, the translate dialog is usable and fetches data with the right context and domain. closes odoo/odoo#97280 Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
This commit is contained in:
@@ -59,3 +59,17 @@ _lt("about a month ago");
|
||||
_lt("%d months ago");
|
||||
_lt("about a year ago");
|
||||
_lt("%d years ago");
|
||||
|
||||
/**
|
||||
* Load the installed languages long names and code
|
||||
*
|
||||
* The result of the call is put in cache.
|
||||
* If any new language is installed, a full page refresh will happen,
|
||||
* so there is no need invalidate it.
|
||||
*/
|
||||
export async function loadLanguages(orm) {
|
||||
if (!loadLanguages.installedLanguages) {
|
||||
loadLanguages.installedLanguages = await orm.call("res.lang", "get_installed");
|
||||
}
|
||||
return loadLanguages.installedLanguages;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
resModel="props.record.resModel"
|
||||
value="props.value"
|
||||
updateField="props.update"
|
||||
context="props.record.context"
|
||||
/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
resModel="props.record.resModel"
|
||||
value="props.value"
|
||||
updateField="props.update"
|
||||
context="props.record.context"
|
||||
/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
@@ -25,7 +25,7 @@ export class TranslationButton extends Component {
|
||||
model: "ir.translation",
|
||||
method: "translate_fields",
|
||||
args: [this.props.resModel, this.props.resId, this.props.fieldName],
|
||||
kwargs: {},
|
||||
kwargs: { context: this.props.context },
|
||||
});
|
||||
|
||||
this.dialog.add(TranslationDialog, {
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
import { Dialog } from "@web/core/dialog/dialog";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { loadLanguages } from "@web/core/l10n/translation";
|
||||
|
||||
const { Component, onWillStart } = owl;
|
||||
|
||||
let installedLanguages = null;
|
||||
|
||||
export class TranslationDialog extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
@@ -20,7 +19,7 @@ export class TranslationDialog extends Component {
|
||||
this.updatedTerms = {};
|
||||
|
||||
onWillStart(async () => {
|
||||
const languages = await this.loadLanguages();
|
||||
const languages = await loadLanguages(this.orm);
|
||||
const translations = await this.loadTranslations(languages);
|
||||
|
||||
this.terms = translations.map((term) => {
|
||||
@@ -52,24 +51,19 @@ export class TranslationDialog extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the installed languages long names and code
|
||||
*
|
||||
* The result of the call is put in cache.
|
||||
* If any new language is installed, a full page refresh will happen,
|
||||
* so there is no need invalidate it.
|
||||
*/
|
||||
async loadLanguages() {
|
||||
if (!installedLanguages) {
|
||||
installedLanguages = await this.orm.call("res.lang", "get_installed");
|
||||
get domain() {
|
||||
const domain = this.props.domain;
|
||||
if (this.props.searchName) {
|
||||
domain.push(["name", "=", `${this.props.searchName}`]);
|
||||
}
|
||||
return installedLanguages;
|
||||
return domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the translation terms for the installed language, for the current model and res_id
|
||||
*/
|
||||
async loadTranslations(languages) {
|
||||
const domain = [...this.props.domain, ["lang", "in", languages.map((l) => l[0])]];
|
||||
const domain = [...this.domain, ["lang", "in", languages.map((l) => l[0])]];
|
||||
return this.orm.searchRead("ir.translation", domain, ["lang", "src", "value"]);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { utils } from "./helpers/mock_env";
|
||||
import { session as sessionInfo } from "@web/session";
|
||||
import { prepareLegacyRegistriesWithCleanup } from "./helpers/legacy_env_utils";
|
||||
import { config as transitionConfig } from "@web/core/transition";
|
||||
import { loadLanguages } from "@web/core/l10n/translation";
|
||||
|
||||
transitionConfig.disabled = true;
|
||||
|
||||
@@ -186,6 +187,12 @@ function patchOdoo() {
|
||||
});
|
||||
}
|
||||
|
||||
function cleanLoadedLanguages() {
|
||||
registerCleanup(() => {
|
||||
loadLanguages.installedLanguages = null;
|
||||
});
|
||||
}
|
||||
|
||||
function patchSessionInfo() {
|
||||
patchWithCleanup(sessionInfo, {
|
||||
cache_hashes: {
|
||||
@@ -251,6 +258,7 @@ export async function setupTests() {
|
||||
prepareRegistriesWithCleanup();
|
||||
prepareLegacyRegistriesWithCleanup();
|
||||
forceLocaleAndTimezoneWithCleanup();
|
||||
cleanLoadedLanguages();
|
||||
patchBrowserWithCleanup();
|
||||
patchLegacyCoreBus();
|
||||
patchOdoo();
|
||||
|
||||
@@ -7880,6 +7880,59 @@ QUnit.module("Views", (hooks) => {
|
||||
assert.verifySteps([]);
|
||||
});
|
||||
|
||||
QUnit.test("translation dialog with right context and domain", async function (assert) {
|
||||
serverData.models.partner.fields.foo.translate = true;
|
||||
|
||||
patchWithCleanup(localization, {
|
||||
multiLang: true,
|
||||
});
|
||||
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="foo"/>
|
||||
</form>`,
|
||||
resId: 1,
|
||||
mockRPC(route, args) {
|
||||
if (args.method === "get_installed") {
|
||||
return [
|
||||
["CUST", "custom lang"],
|
||||
["CUST2", "second custom"],
|
||||
];
|
||||
}
|
||||
if (args.method === "translate_fields") {
|
||||
assert.step(`translate args ${JSON.stringify(args.args)}`);
|
||||
assert.step(`translate context ${JSON.stringify(args.kwargs.context)}`);
|
||||
return {
|
||||
domain: [["res_id", "=", args.args[1]]],
|
||||
context: { search_default_name: "partner_type,foo" },
|
||||
};
|
||||
}
|
||||
if (args.method === "search_read" && args.model === "ir.translation") {
|
||||
assert.step(
|
||||
`search_read translations args: ${JSON.stringify(
|
||||
args.args
|
||||
)} ; kwargs: ${JSON.stringify(args.kwargs)}`
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
await clickEdit(target);
|
||||
|
||||
await click(target, ".o_field_translate.btn-link");
|
||||
assert.verifySteps([
|
||||
`translate args ["partner",1,"foo"]`,
|
||||
`translate context {"lang":"en","uid":7,"tz":"taht"}`,
|
||||
`search_read translations args: [] ; kwargs: {"context":{"lang":"en","uid":7,"tz":"taht"},"domain":[["res_id","=",1],["name","=","partner_type,foo"],["lang","in",["CUST","CUST2"]]],"fields":["lang","src","value"]}`,
|
||||
]);
|
||||
|
||||
assert.containsOnce(target, ".modal");
|
||||
assert.strictEqual(target.querySelector(".modal-title").textContent, "Translate: foo");
|
||||
});
|
||||
|
||||
QUnit.test("translation alerts are preserved on pager change", async function (assert) {
|
||||
serverData.models.partner.fields.foo.translate = true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user