[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:
Lucas Perais
2022-08-03 06:34:12 +02:00
parent a3f6712951
commit 8fc7aa4ff1
7 changed files with 87 additions and 16 deletions
@@ -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"]);
}
+8
View File
@@ -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;