Skip to content

Commit

Permalink
[REL] v2.6.0
Browse files Browse the repository at this point in the history
# v2.6.0

 - [IMP] translation contexts
  • Loading branch information
rfr-odoo committed Jan 15, 2025
1 parent a9be149 commit aec2373
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 25 deletions.
129 changes: 107 additions & 22 deletions docs/owl.js
Original file line number Diff line number Diff line change
Expand Up @@ -3738,6 +3738,7 @@ function createContext(parentCtx, params) {
index: 0,
forceNewBlock: true,
translate: parentCtx.translate,
translationCtx: parentCtx.translationCtx,
tKeyExpr: null,
nameSpace: parentCtx.nameSpace,
tModelSelectedExpr: parentCtx.tModelSelectedExpr,
Expand Down Expand Up @@ -3840,6 +3841,7 @@ class CodeGenerator {
forceNewBlock: false,
isLast: true,
translate: true,
translationCtx: "",
tKeyExpr: null,
});
// define blocks and utility functions
Expand Down Expand Up @@ -3977,9 +3979,9 @@ class CodeGenerator {
})
.join("");
}
translate(str) {
translate(str, translationCtx) {
const match = translationRE.exec(str);
return match[1] + this.translateFn(match[2]) + match[3];
return match[1] + this.translateFn(match[2], translationCtx) + match[3];
}
/**
* @returns the newly created block name, if any
Expand Down Expand Up @@ -4020,7 +4022,9 @@ class CodeGenerator {
return this.compileTSlot(ast, ctx);
case 16 /* TTranslation */:
return this.compileTTranslation(ast, ctx);
case 17 /* TPortal */:
case 17 /* TTranslationContext */:
return this.compileTTranslationContext(ast, ctx);
case 18 /* TPortal */:
return this.compileTPortal(ast, ctx);
}
}
Expand Down Expand Up @@ -4058,7 +4062,7 @@ class CodeGenerator {
let { block, forceNewBlock } = ctx;
let value = ast.value;
if (value && ctx.translate !== false) {
value = this.translate(value);
value = this.translate(value, ctx.translationCtx);
}
if (!ctx.inPreTag) {
value = value.replace(whitespaceRE, " ");
Expand Down Expand Up @@ -4093,6 +4097,7 @@ class CodeGenerator {
return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
}
compileTDomNode(ast, ctx) {
var _a;
let { block, forceNewBlock } = ctx;
const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
let codeIdx = this.target.code.length;
Expand Down Expand Up @@ -4148,7 +4153,8 @@ class CodeGenerator {
}
}
else if (this.translatableAttributes.includes(key)) {
attrs[key] = this.translateFn(ast.attrs[key]);
const attrTranslationCtx = ((_a = ast.attrsTranslationCtx) === null || _a === void 0 ? void 0 : _a[key]) || ctx.translationCtx;
attrs[key] = this.translateFn(ast.attrs[key], attrTranslationCtx);
}
else {
expr = `"${ast.attrs[key]}"`;
Expand Down Expand Up @@ -4592,7 +4598,7 @@ class CodeGenerator {
else {
let value;
if (ast.defaultValue) {
const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue);
const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue, ctx.translationCtx) : ast.defaultValue);
if (ast.value) {
value = `withDefault(${expr}, ${defaultValue})`;
}
Expand Down Expand Up @@ -4626,9 +4632,10 @@ class CodeGenerator {
* "some-prop" "state" "'some-prop': ctx['state']"
* "onClick.bind" "onClick" "onClick: bind(ctx, ctx['onClick'])"
*/
formatProp(name, value) {
formatProp(name, value, attrsTranslationCtx, translationCtx) {
if (name.endsWith(".translate")) {
value = toStringExpression(this.translateFn(value));
const attrTranslationCtx = (attrsTranslationCtx === null || attrsTranslationCtx === void 0 ? void 0 : attrsTranslationCtx[name]) || translationCtx;
value = toStringExpression(this.translateFn(value, attrTranslationCtx));
}
else {
value = this.captureExpression(value);
Expand All @@ -4650,8 +4657,8 @@ class CodeGenerator {
name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
return `${name}: ${value || undefined}`;
}
formatPropObject(obj) {
return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
formatPropObject(obj, attrsTranslationCtx, translationCtx) {
return Object.entries(obj).map(([k, v]) => this.formatProp(k, v, attrsTranslationCtx, translationCtx));
}
getPropString(props, dynProps) {
let propString = `{${props.join(",")}}`;
Expand All @@ -4664,7 +4671,9 @@ class CodeGenerator {
let { block } = ctx;
// props
const hasSlotsProp = "slots" in (ast.props || {});
const props = ast.props ? this.formatPropObject(ast.props) : [];
const props = ast.props
? this.formatPropObject(ast.props, ast.propsTranslationCtx, ctx.translationCtx)
: [];
// slots
let slotDef = "";
if (ast.slots) {
Expand All @@ -4687,7 +4696,7 @@ class CodeGenerator {
params.push(`__scope: "${scope}"`);
}
if (ast.slots[slotName].attrs) {
params.push(...this.formatPropObject(ast.slots[slotName].attrs));
params.push(...this.formatPropObject(ast.slots[slotName].attrs, ast.slots[slotName].attrsTranslationCtx, ctx.translationCtx));
}
const slotInfo = `{${params.join(", ")}}`;
slotStr.push(`'${slotName}': ${slotInfo}`);
Expand Down Expand Up @@ -4800,7 +4809,9 @@ class CodeGenerator {
if (isMultiple) {
key = this.generateComponentKey(key);
}
const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
const props = ast.attrs
? this.formatPropObject(ast.attrs, ast.attrsTranslationCtx, ctx.translationCtx)
: [];
const scope = this.getPropString(props, dynProps);
if (ast.defaultContent) {
const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
Expand Down Expand Up @@ -4833,6 +4844,12 @@ class CodeGenerator {
}
return null;
}
compileTTranslationContext(ast, ctx) {
if (ast.content) {
return this.compileAST(ast.content, Object.assign({}, ctx, { translationCtx: ast.translationCtx }));
}
return null;
}
compileTPortal(ast, ctx) {
if (!this.staticDefs.find((d) => d.id === "Portal")) {
this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
Expand Down Expand Up @@ -4902,6 +4919,7 @@ function parseNode(node, ctx) {
parseTOutNode(node, ctx) ||
parseTKey(node, ctx) ||
parseTTranslation(node, ctx) ||
parseTTranslationContext(node, ctx) ||
parseTSlot(node, ctx) ||
parseComponent(node, ctx) ||
parseDOMNode(node, ctx) ||
Expand Down Expand Up @@ -5010,6 +5028,7 @@ function parseDOMNode(node, ctx) {
node.removeAttribute("t-ref");
const nodeAttrsNames = node.getAttributeNames();
let attrs = null;
let attrsTranslationCtx = null;
let on = null;
let model = null;
for (let attr of nodeAttrsNames) {
Expand Down Expand Up @@ -5070,6 +5089,11 @@ function parseDOMNode(node, ctx) {
else if (attr === "xmlns") {
ns = value;
}
else if (attr.startsWith("t-translation-context-")) {
const attrName = attr.slice(22);
attrsTranslationCtx = attrsTranslationCtx || {};
attrsTranslationCtx[attrName] = value;
}
else if (attr !== "t-name") {
if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
throw new OwlError(`Unknown QWeb directive: '${attr}'`);
Expand All @@ -5091,6 +5115,7 @@ function parseDOMNode(node, ctx) {
tag: tagName,
dynamicTag,
attrs,
attrsTranslationCtx,
on,
ref,
content: children,
Expand Down Expand Up @@ -5231,7 +5256,15 @@ function parseTCall(node, ctx) {
if (ast && ast.type === 11 /* TComponent */) {
return {
...ast,
slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
slots: {
default: {
content: tcall,
scope: null,
on: null,
attrs: null,
attrsTranslationCtx: null,
},
},
};
}
}
Expand Down Expand Up @@ -5346,9 +5379,15 @@ function parseComponent(node, ctx) {
node.removeAttribute("t-slot-scope");
let on = null;
let props = null;
let propsTranslationCtx = null;
for (let name of node.getAttributeNames()) {
const value = node.getAttribute(name);
if (name.startsWith("t-")) {
if (name.startsWith("t-translation-context-")) {
const attrName = name.slice(22);
propsTranslationCtx = propsTranslationCtx || {};
propsTranslationCtx[attrName] = value;
}
else if (name.startsWith("t-")) {
if (name.startsWith("t-on-")) {
on = on || {};
on[name.slice(5)] = value;
Expand Down Expand Up @@ -5392,13 +5431,19 @@ function parseComponent(node, ctx) {
const slotAst = parseNode(slotNode, ctx);
let on = null;
let attrs = null;
let attrsTranslationCtx = null;
let scope = null;
for (let attributeName of slotNode.getAttributeNames()) {
const value = slotNode.getAttribute(attributeName);
if (attributeName === "t-slot-scope") {
scope = value;
continue;
}
else if (attributeName.startsWith("t-translation-context-")) {
const attrName = attributeName.slice(22);
attrsTranslationCtx = attrsTranslationCtx || {};
attrsTranslationCtx[attrName] = value;
}
else if (attributeName.startsWith("t-on-")) {
on = on || {};
on[attributeName.slice(5)] = value;
Expand All @@ -5409,17 +5454,32 @@ function parseComponent(node, ctx) {
}
}
slots = slots || {};
slots[name] = { content: slotAst, on, attrs, scope };
slots[name] = { content: slotAst, on, attrs, attrsTranslationCtx, scope };
}
// default slot
const defaultContent = parseChildNodes(clone, ctx);
slots = slots || {};
// t-set-slot="default" has priority over content
if (defaultContent && !slots.default) {
slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
slots.default = {
content: defaultContent,
on,
attrs: null,
attrsTranslationCtx: null,
scope: defaultSlotScope,
};
}
}
return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots, on };
return {
type: 11 /* TComponent */,
name,
isDynamic,
dynamicProps,
props,
propsTranslationCtx,
slots,
on,
};
}
// -----------------------------------------------------------------------------
// Slots
Expand All @@ -5431,13 +5491,19 @@ function parseTSlot(node, ctx) {
const name = node.getAttribute("t-slot");
node.removeAttribute("t-slot");
let attrs = null;
let attrsTranslationCtx = null;
let on = null;
for (let attributeName of node.getAttributeNames()) {
const value = node.getAttribute(attributeName);
if (attributeName.startsWith("t-on-")) {
on = on || {};
on[attributeName.slice(5)] = value;
}
else if (attributeName.startsWith("t-translation-context-")) {
const attrName = attributeName.slice(22);
attrsTranslationCtx = attrsTranslationCtx || {};
attrsTranslationCtx[attrName] = value;
}
else {
attrs = attrs || {};
attrs[attributeName] = value;
Expand All @@ -5447,10 +5513,14 @@ function parseTSlot(node, ctx) {
type: 14 /* TSlot */,
name,
attrs,
attrsTranslationCtx,
on,
defaultContent: parseChildNodes(node, ctx),
};
}
// -----------------------------------------------------------------------------
// Translation
// -----------------------------------------------------------------------------
function parseTTranslation(node, ctx) {
if (node.getAttribute("t-translation") !== "off") {
return null;
Expand All @@ -5462,6 +5532,21 @@ function parseTTranslation(node, ctx) {
};
}
// -----------------------------------------------------------------------------
// Translation Context
// -----------------------------------------------------------------------------
function parseTTranslationContext(node, ctx) {
const translationCtx = node.getAttribute("t-translation-context");
if (!translationCtx) {
return null;
}
node.removeAttribute("t-translation-context");
return {
type: 17 /* TTranslationContext */,
content: parseNode(node, ctx),
translationCtx,
};
}
// -----------------------------------------------------------------------------
// Portal
// -----------------------------------------------------------------------------
function parseTPortal(node, ctx) {
Expand All @@ -5478,7 +5563,7 @@ function parseTPortal(node, ctx) {
};
}
return {
type: 17 /* TPortal */,
type: 18 /* TPortal */,
target,
content,
};
Expand Down Expand Up @@ -5620,7 +5705,7 @@ function compile(template, options = {
}

// do not modify manually. This file is generated by the release script.
const version = "2.5.3";
const version = "2.6.0";

// -----------------------------------------------------------------------------
// Scheduler
Expand Down Expand Up @@ -6098,6 +6183,6 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
export { App, Component, EventBus, OwlError, __info__, batched, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml };


__info__.date = '2025-01-10T10:10:53.709Z';
__info__.hash = 'b31fa81';
__info__.date = '2025-01-15T10:40:24.184Z';
__info__.hash = 'a9be149';
__info__.url = 'https://github.com/odoo/owl';
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@odoo/owl",
"version": "2.5.3",
"version": "2.6.0",
"description": "Odoo Web Library (OWL)",
"main": "dist/owl.cjs.js",
"module": "dist/owl.es.js",
Expand Down
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// do not modify manually. This file is generated by the release script.
export const version = "2.5.3";
export const version = "2.6.0";

0 comments on commit aec2373

Please sign in to comment.