@odoo/owl 2.5.3 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -428,6 +428,7 @@ function createContext(parentCtx, params) {
428
428
  index: 0,
429
429
  forceNewBlock: true,
430
430
  translate: parentCtx.translate,
431
+ translationCtx: parentCtx.translationCtx,
431
432
  tKeyExpr: null,
432
433
  nameSpace: parentCtx.nameSpace,
433
434
  tModelSelectedExpr: parentCtx.tModelSelectedExpr,
@@ -530,6 +531,7 @@ class CodeGenerator {
530
531
  forceNewBlock: false,
531
532
  isLast: true,
532
533
  translate: true,
534
+ translationCtx: "",
533
535
  tKeyExpr: null,
534
536
  });
535
537
  // define blocks and utility functions
@@ -667,9 +669,9 @@ class CodeGenerator {
667
669
  })
668
670
  .join("");
669
671
  }
670
- translate(str) {
672
+ translate(str, translationCtx) {
671
673
  const match = translationRE.exec(str);
672
- return match[1] + this.translateFn(match[2]) + match[3];
674
+ return match[1] + this.translateFn(match[2], translationCtx) + match[3];
673
675
  }
674
676
  /**
675
677
  * @returns the newly created block name, if any
@@ -710,7 +712,9 @@ class CodeGenerator {
710
712
  return this.compileTSlot(ast, ctx);
711
713
  case 16 /* TTranslation */:
712
714
  return this.compileTTranslation(ast, ctx);
713
- case 17 /* TPortal */:
715
+ case 17 /* TTranslationContext */:
716
+ return this.compileTTranslationContext(ast, ctx);
717
+ case 18 /* TPortal */:
714
718
  return this.compileTPortal(ast, ctx);
715
719
  }
716
720
  }
@@ -748,7 +752,7 @@ class CodeGenerator {
748
752
  let { block, forceNewBlock } = ctx;
749
753
  let value = ast.value;
750
754
  if (value && ctx.translate !== false) {
751
- value = this.translate(value);
755
+ value = this.translate(value, ctx.translationCtx);
752
756
  }
753
757
  if (!ctx.inPreTag) {
754
758
  value = value.replace(whitespaceRE, " ");
@@ -783,6 +787,7 @@ class CodeGenerator {
783
787
  return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
784
788
  }
785
789
  compileTDomNode(ast, ctx) {
790
+ var _a;
786
791
  let { block, forceNewBlock } = ctx;
787
792
  const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
788
793
  let codeIdx = this.target.code.length;
@@ -838,7 +843,8 @@ class CodeGenerator {
838
843
  }
839
844
  }
840
845
  else if (this.translatableAttributes.includes(key)) {
841
- attrs[key] = this.translateFn(ast.attrs[key]);
846
+ const attrTranslationCtx = ((_a = ast.attrsTranslationCtx) === null || _a === void 0 ? void 0 : _a[key]) || ctx.translationCtx;
847
+ attrs[key] = this.translateFn(ast.attrs[key], attrTranslationCtx);
842
848
  }
843
849
  else {
844
850
  expr = `"${ast.attrs[key]}"`;
@@ -1282,7 +1288,7 @@ class CodeGenerator {
1282
1288
  else {
1283
1289
  let value;
1284
1290
  if (ast.defaultValue) {
1285
- const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue);
1291
+ const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue, ctx.translationCtx) : ast.defaultValue);
1286
1292
  if (ast.value) {
1287
1293
  value = `withDefault(${expr}, ${defaultValue})`;
1288
1294
  }
@@ -1316,9 +1322,10 @@ class CodeGenerator {
1316
1322
  * "some-prop" "state" "'some-prop': ctx['state']"
1317
1323
  * "onClick.bind" "onClick" "onClick: bind(ctx, ctx['onClick'])"
1318
1324
  */
1319
- formatProp(name, value) {
1325
+ formatProp(name, value, attrsTranslationCtx, translationCtx) {
1320
1326
  if (name.endsWith(".translate")) {
1321
- value = toStringExpression(this.translateFn(value));
1327
+ const attrTranslationCtx = (attrsTranslationCtx === null || attrsTranslationCtx === void 0 ? void 0 : attrsTranslationCtx[name]) || translationCtx;
1328
+ value = toStringExpression(this.translateFn(value, attrTranslationCtx));
1322
1329
  }
1323
1330
  else {
1324
1331
  value = this.captureExpression(value);
@@ -1340,8 +1347,8 @@ class CodeGenerator {
1340
1347
  name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
1341
1348
  return `${name}: ${value || undefined}`;
1342
1349
  }
1343
- formatPropObject(obj) {
1344
- return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
1350
+ formatPropObject(obj, attrsTranslationCtx, translationCtx) {
1351
+ return Object.entries(obj).map(([k, v]) => this.formatProp(k, v, attrsTranslationCtx, translationCtx));
1345
1352
  }
1346
1353
  getPropString(props, dynProps) {
1347
1354
  let propString = `{${props.join(",")}}`;
@@ -1354,7 +1361,9 @@ class CodeGenerator {
1354
1361
  let { block } = ctx;
1355
1362
  // props
1356
1363
  const hasSlotsProp = "slots" in (ast.props || {});
1357
- const props = ast.props ? this.formatPropObject(ast.props) : [];
1364
+ const props = ast.props
1365
+ ? this.formatPropObject(ast.props, ast.propsTranslationCtx, ctx.translationCtx)
1366
+ : [];
1358
1367
  // slots
1359
1368
  let slotDef = "";
1360
1369
  if (ast.slots) {
@@ -1377,7 +1386,7 @@ class CodeGenerator {
1377
1386
  params.push(`__scope: "${scope}"`);
1378
1387
  }
1379
1388
  if (ast.slots[slotName].attrs) {
1380
- params.push(...this.formatPropObject(ast.slots[slotName].attrs));
1389
+ params.push(...this.formatPropObject(ast.slots[slotName].attrs, ast.slots[slotName].attrsTranslationCtx, ctx.translationCtx));
1381
1390
  }
1382
1391
  const slotInfo = `{${params.join(", ")}}`;
1383
1392
  slotStr.push(`'${slotName}': ${slotInfo}`);
@@ -1490,7 +1499,9 @@ class CodeGenerator {
1490
1499
  if (isMultiple) {
1491
1500
  key = this.generateComponentKey(key);
1492
1501
  }
1493
- const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
1502
+ const props = ast.attrs
1503
+ ? this.formatPropObject(ast.attrs, ast.attrsTranslationCtx, ctx.translationCtx)
1504
+ : [];
1494
1505
  const scope = this.getPropString(props, dynProps);
1495
1506
  if (ast.defaultContent) {
1496
1507
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
@@ -1523,6 +1534,12 @@ class CodeGenerator {
1523
1534
  }
1524
1535
  return null;
1525
1536
  }
1537
+ compileTTranslationContext(ast, ctx) {
1538
+ if (ast.content) {
1539
+ return this.compileAST(ast.content, Object.assign({}, ctx, { translationCtx: ast.translationCtx }));
1540
+ }
1541
+ return null;
1542
+ }
1526
1543
  compileTPortal(ast, ctx) {
1527
1544
  if (!this.staticDefs.find((d) => d.id === "Portal")) {
1528
1545
  this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
@@ -1628,6 +1645,7 @@ function parseNode(node, ctx) {
1628
1645
  parseTOutNode(node, ctx) ||
1629
1646
  parseTKey(node, ctx) ||
1630
1647
  parseTTranslation(node, ctx) ||
1648
+ parseTTranslationContext(node, ctx) ||
1631
1649
  parseTSlot(node, ctx) ||
1632
1650
  parseComponent(node, ctx) ||
1633
1651
  parseDOMNode(node, ctx) ||
@@ -1736,6 +1754,7 @@ function parseDOMNode(node, ctx) {
1736
1754
  node.removeAttribute("t-ref");
1737
1755
  const nodeAttrsNames = node.getAttributeNames();
1738
1756
  let attrs = null;
1757
+ let attrsTranslationCtx = null;
1739
1758
  let on = null;
1740
1759
  let model = null;
1741
1760
  for (let attr of nodeAttrsNames) {
@@ -1796,6 +1815,11 @@ function parseDOMNode(node, ctx) {
1796
1815
  else if (attr === "xmlns") {
1797
1816
  ns = value;
1798
1817
  }
1818
+ else if (attr.startsWith("t-translation-context-")) {
1819
+ const attrName = attr.slice(22);
1820
+ attrsTranslationCtx = attrsTranslationCtx || {};
1821
+ attrsTranslationCtx[attrName] = value;
1822
+ }
1799
1823
  else if (attr !== "t-name") {
1800
1824
  if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
1801
1825
  throw new OwlError(`Unknown QWeb directive: '${attr}'`);
@@ -1817,6 +1841,7 @@ function parseDOMNode(node, ctx) {
1817
1841
  tag: tagName,
1818
1842
  dynamicTag,
1819
1843
  attrs,
1844
+ attrsTranslationCtx,
1820
1845
  on,
1821
1846
  ref,
1822
1847
  content: children,
@@ -1957,7 +1982,15 @@ function parseTCall(node, ctx) {
1957
1982
  if (ast && ast.type === 11 /* TComponent */) {
1958
1983
  return {
1959
1984
  ...ast,
1960
- slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
1985
+ slots: {
1986
+ default: {
1987
+ content: tcall,
1988
+ scope: null,
1989
+ on: null,
1990
+ attrs: null,
1991
+ attrsTranslationCtx: null,
1992
+ },
1993
+ },
1961
1994
  };
1962
1995
  }
1963
1996
  }
@@ -2072,9 +2105,15 @@ function parseComponent(node, ctx) {
2072
2105
  node.removeAttribute("t-slot-scope");
2073
2106
  let on = null;
2074
2107
  let props = null;
2108
+ let propsTranslationCtx = null;
2075
2109
  for (let name of node.getAttributeNames()) {
2076
2110
  const value = node.getAttribute(name);
2077
- if (name.startsWith("t-")) {
2111
+ if (name.startsWith("t-translation-context-")) {
2112
+ const attrName = name.slice(22);
2113
+ propsTranslationCtx = propsTranslationCtx || {};
2114
+ propsTranslationCtx[attrName] = value;
2115
+ }
2116
+ else if (name.startsWith("t-")) {
2078
2117
  if (name.startsWith("t-on-")) {
2079
2118
  on = on || {};
2080
2119
  on[name.slice(5)] = value;
@@ -2118,6 +2157,7 @@ function parseComponent(node, ctx) {
2118
2157
  const slotAst = parseNode(slotNode, ctx);
2119
2158
  let on = null;
2120
2159
  let attrs = null;
2160
+ let attrsTranslationCtx = null;
2121
2161
  let scope = null;
2122
2162
  for (let attributeName of slotNode.getAttributeNames()) {
2123
2163
  const value = slotNode.getAttribute(attributeName);
@@ -2125,6 +2165,11 @@ function parseComponent(node, ctx) {
2125
2165
  scope = value;
2126
2166
  continue;
2127
2167
  }
2168
+ else if (attributeName.startsWith("t-translation-context-")) {
2169
+ const attrName = attributeName.slice(22);
2170
+ attrsTranslationCtx = attrsTranslationCtx || {};
2171
+ attrsTranslationCtx[attrName] = value;
2172
+ }
2128
2173
  else if (attributeName.startsWith("t-on-")) {
2129
2174
  on = on || {};
2130
2175
  on[attributeName.slice(5)] = value;
@@ -2135,17 +2180,32 @@ function parseComponent(node, ctx) {
2135
2180
  }
2136
2181
  }
2137
2182
  slots = slots || {};
2138
- slots[name] = { content: slotAst, on, attrs, scope };
2183
+ slots[name] = { content: slotAst, on, attrs, attrsTranslationCtx, scope };
2139
2184
  }
2140
2185
  // default slot
2141
2186
  const defaultContent = parseChildNodes(clone, ctx);
2142
2187
  slots = slots || {};
2143
2188
  // t-set-slot="default" has priority over content
2144
2189
  if (defaultContent && !slots.default) {
2145
- slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
2190
+ slots.default = {
2191
+ content: defaultContent,
2192
+ on,
2193
+ attrs: null,
2194
+ attrsTranslationCtx: null,
2195
+ scope: defaultSlotScope,
2196
+ };
2146
2197
  }
2147
2198
  }
2148
- return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots, on };
2199
+ return {
2200
+ type: 11 /* TComponent */,
2201
+ name,
2202
+ isDynamic,
2203
+ dynamicProps,
2204
+ props,
2205
+ propsTranslationCtx,
2206
+ slots,
2207
+ on,
2208
+ };
2149
2209
  }
2150
2210
  // -----------------------------------------------------------------------------
2151
2211
  // Slots
@@ -2157,6 +2217,7 @@ function parseTSlot(node, ctx) {
2157
2217
  const name = node.getAttribute("t-slot");
2158
2218
  node.removeAttribute("t-slot");
2159
2219
  let attrs = null;
2220
+ let attrsTranslationCtx = null;
2160
2221
  let on = null;
2161
2222
  for (let attributeName of node.getAttributeNames()) {
2162
2223
  const value = node.getAttribute(attributeName);
@@ -2164,6 +2225,11 @@ function parseTSlot(node, ctx) {
2164
2225
  on = on || {};
2165
2226
  on[attributeName.slice(5)] = value;
2166
2227
  }
2228
+ else if (attributeName.startsWith("t-translation-context-")) {
2229
+ const attrName = attributeName.slice(22);
2230
+ attrsTranslationCtx = attrsTranslationCtx || {};
2231
+ attrsTranslationCtx[attrName] = value;
2232
+ }
2167
2233
  else {
2168
2234
  attrs = attrs || {};
2169
2235
  attrs[attributeName] = value;
@@ -2173,10 +2239,14 @@ function parseTSlot(node, ctx) {
2173
2239
  type: 14 /* TSlot */,
2174
2240
  name,
2175
2241
  attrs,
2242
+ attrsTranslationCtx,
2176
2243
  on,
2177
2244
  defaultContent: parseChildNodes(node, ctx),
2178
2245
  };
2179
2246
  }
2247
+ // -----------------------------------------------------------------------------
2248
+ // Translation
2249
+ // -----------------------------------------------------------------------------
2180
2250
  function parseTTranslation(node, ctx) {
2181
2251
  if (node.getAttribute("t-translation") !== "off") {
2182
2252
  return null;
@@ -2188,6 +2258,21 @@ function parseTTranslation(node, ctx) {
2188
2258
  };
2189
2259
  }
2190
2260
  // -----------------------------------------------------------------------------
2261
+ // Translation Context
2262
+ // -----------------------------------------------------------------------------
2263
+ function parseTTranslationContext(node, ctx) {
2264
+ const translationCtx = node.getAttribute("t-translation-context");
2265
+ if (!translationCtx) {
2266
+ return null;
2267
+ }
2268
+ node.removeAttribute("t-translation-context");
2269
+ return {
2270
+ type: 17 /* TTranslationContext */,
2271
+ content: parseNode(node, ctx),
2272
+ translationCtx,
2273
+ };
2274
+ }
2275
+ // -----------------------------------------------------------------------------
2191
2276
  // Portal
2192
2277
  // -----------------------------------------------------------------------------
2193
2278
  function parseTPortal(node, ctx) {
@@ -2204,7 +2289,7 @@ function parseTPortal(node, ctx) {
2204
2289
  };
2205
2290
  }
2206
2291
  return {
2207
- type: 17 /* TPortal */,
2292
+ type: 18 /* TPortal */,
2208
2293
  target,
2209
2294
  content,
2210
2295
  };
Binary file
package/dist/owl.cjs.js CHANGED
@@ -3742,6 +3742,7 @@ function createContext(parentCtx, params) {
3742
3742
  index: 0,
3743
3743
  forceNewBlock: true,
3744
3744
  translate: parentCtx.translate,
3745
+ translationCtx: parentCtx.translationCtx,
3745
3746
  tKeyExpr: null,
3746
3747
  nameSpace: parentCtx.nameSpace,
3747
3748
  tModelSelectedExpr: parentCtx.tModelSelectedExpr,
@@ -3844,6 +3845,7 @@ class CodeGenerator {
3844
3845
  forceNewBlock: false,
3845
3846
  isLast: true,
3846
3847
  translate: true,
3848
+ translationCtx: "",
3847
3849
  tKeyExpr: null,
3848
3850
  });
3849
3851
  // define blocks and utility functions
@@ -3981,9 +3983,9 @@ class CodeGenerator {
3981
3983
  })
3982
3984
  .join("");
3983
3985
  }
3984
- translate(str) {
3986
+ translate(str, translationCtx) {
3985
3987
  const match = translationRE.exec(str);
3986
- return match[1] + this.translateFn(match[2]) + match[3];
3988
+ return match[1] + this.translateFn(match[2], translationCtx) + match[3];
3987
3989
  }
3988
3990
  /**
3989
3991
  * @returns the newly created block name, if any
@@ -4024,7 +4026,9 @@ class CodeGenerator {
4024
4026
  return this.compileTSlot(ast, ctx);
4025
4027
  case 16 /* TTranslation */:
4026
4028
  return this.compileTTranslation(ast, ctx);
4027
- case 17 /* TPortal */:
4029
+ case 17 /* TTranslationContext */:
4030
+ return this.compileTTranslationContext(ast, ctx);
4031
+ case 18 /* TPortal */:
4028
4032
  return this.compileTPortal(ast, ctx);
4029
4033
  }
4030
4034
  }
@@ -4062,7 +4066,7 @@ class CodeGenerator {
4062
4066
  let { block, forceNewBlock } = ctx;
4063
4067
  let value = ast.value;
4064
4068
  if (value && ctx.translate !== false) {
4065
- value = this.translate(value);
4069
+ value = this.translate(value, ctx.translationCtx);
4066
4070
  }
4067
4071
  if (!ctx.inPreTag) {
4068
4072
  value = value.replace(whitespaceRE, " ");
@@ -4097,6 +4101,7 @@ class CodeGenerator {
4097
4101
  return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
4098
4102
  }
4099
4103
  compileTDomNode(ast, ctx) {
4104
+ var _a;
4100
4105
  let { block, forceNewBlock } = ctx;
4101
4106
  const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
4102
4107
  let codeIdx = this.target.code.length;
@@ -4152,7 +4157,8 @@ class CodeGenerator {
4152
4157
  }
4153
4158
  }
4154
4159
  else if (this.translatableAttributes.includes(key)) {
4155
- attrs[key] = this.translateFn(ast.attrs[key]);
4160
+ const attrTranslationCtx = ((_a = ast.attrsTranslationCtx) === null || _a === void 0 ? void 0 : _a[key]) || ctx.translationCtx;
4161
+ attrs[key] = this.translateFn(ast.attrs[key], attrTranslationCtx);
4156
4162
  }
4157
4163
  else {
4158
4164
  expr = `"${ast.attrs[key]}"`;
@@ -4596,7 +4602,7 @@ class CodeGenerator {
4596
4602
  else {
4597
4603
  let value;
4598
4604
  if (ast.defaultValue) {
4599
- const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue);
4605
+ const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue, ctx.translationCtx) : ast.defaultValue);
4600
4606
  if (ast.value) {
4601
4607
  value = `withDefault(${expr}, ${defaultValue})`;
4602
4608
  }
@@ -4630,9 +4636,10 @@ class CodeGenerator {
4630
4636
  * "some-prop" "state" "'some-prop': ctx['state']"
4631
4637
  * "onClick.bind" "onClick" "onClick: bind(ctx, ctx['onClick'])"
4632
4638
  */
4633
- formatProp(name, value) {
4639
+ formatProp(name, value, attrsTranslationCtx, translationCtx) {
4634
4640
  if (name.endsWith(".translate")) {
4635
- value = toStringExpression(this.translateFn(value));
4641
+ const attrTranslationCtx = (attrsTranslationCtx === null || attrsTranslationCtx === void 0 ? void 0 : attrsTranslationCtx[name]) || translationCtx;
4642
+ value = toStringExpression(this.translateFn(value, attrTranslationCtx));
4636
4643
  }
4637
4644
  else {
4638
4645
  value = this.captureExpression(value);
@@ -4654,8 +4661,8 @@ class CodeGenerator {
4654
4661
  name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
4655
4662
  return `${name}: ${value || undefined}`;
4656
4663
  }
4657
- formatPropObject(obj) {
4658
- return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
4664
+ formatPropObject(obj, attrsTranslationCtx, translationCtx) {
4665
+ return Object.entries(obj).map(([k, v]) => this.formatProp(k, v, attrsTranslationCtx, translationCtx));
4659
4666
  }
4660
4667
  getPropString(props, dynProps) {
4661
4668
  let propString = `{${props.join(",")}}`;
@@ -4668,7 +4675,9 @@ class CodeGenerator {
4668
4675
  let { block } = ctx;
4669
4676
  // props
4670
4677
  const hasSlotsProp = "slots" in (ast.props || {});
4671
- const props = ast.props ? this.formatPropObject(ast.props) : [];
4678
+ const props = ast.props
4679
+ ? this.formatPropObject(ast.props, ast.propsTranslationCtx, ctx.translationCtx)
4680
+ : [];
4672
4681
  // slots
4673
4682
  let slotDef = "";
4674
4683
  if (ast.slots) {
@@ -4691,7 +4700,7 @@ class CodeGenerator {
4691
4700
  params.push(`__scope: "${scope}"`);
4692
4701
  }
4693
4702
  if (ast.slots[slotName].attrs) {
4694
- params.push(...this.formatPropObject(ast.slots[slotName].attrs));
4703
+ params.push(...this.formatPropObject(ast.slots[slotName].attrs, ast.slots[slotName].attrsTranslationCtx, ctx.translationCtx));
4695
4704
  }
4696
4705
  const slotInfo = `{${params.join(", ")}}`;
4697
4706
  slotStr.push(`'${slotName}': ${slotInfo}`);
@@ -4804,7 +4813,9 @@ class CodeGenerator {
4804
4813
  if (isMultiple) {
4805
4814
  key = this.generateComponentKey(key);
4806
4815
  }
4807
- const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
4816
+ const props = ast.attrs
4817
+ ? this.formatPropObject(ast.attrs, ast.attrsTranslationCtx, ctx.translationCtx)
4818
+ : [];
4808
4819
  const scope = this.getPropString(props, dynProps);
4809
4820
  if (ast.defaultContent) {
4810
4821
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
@@ -4837,6 +4848,12 @@ class CodeGenerator {
4837
4848
  }
4838
4849
  return null;
4839
4850
  }
4851
+ compileTTranslationContext(ast, ctx) {
4852
+ if (ast.content) {
4853
+ return this.compileAST(ast.content, Object.assign({}, ctx, { translationCtx: ast.translationCtx }));
4854
+ }
4855
+ return null;
4856
+ }
4840
4857
  compileTPortal(ast, ctx) {
4841
4858
  if (!this.staticDefs.find((d) => d.id === "Portal")) {
4842
4859
  this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
@@ -4906,6 +4923,7 @@ function parseNode(node, ctx) {
4906
4923
  parseTOutNode(node, ctx) ||
4907
4924
  parseTKey(node, ctx) ||
4908
4925
  parseTTranslation(node, ctx) ||
4926
+ parseTTranslationContext(node, ctx) ||
4909
4927
  parseTSlot(node, ctx) ||
4910
4928
  parseComponent(node, ctx) ||
4911
4929
  parseDOMNode(node, ctx) ||
@@ -5014,6 +5032,7 @@ function parseDOMNode(node, ctx) {
5014
5032
  node.removeAttribute("t-ref");
5015
5033
  const nodeAttrsNames = node.getAttributeNames();
5016
5034
  let attrs = null;
5035
+ let attrsTranslationCtx = null;
5017
5036
  let on = null;
5018
5037
  let model = null;
5019
5038
  for (let attr of nodeAttrsNames) {
@@ -5074,6 +5093,11 @@ function parseDOMNode(node, ctx) {
5074
5093
  else if (attr === "xmlns") {
5075
5094
  ns = value;
5076
5095
  }
5096
+ else if (attr.startsWith("t-translation-context-")) {
5097
+ const attrName = attr.slice(22);
5098
+ attrsTranslationCtx = attrsTranslationCtx || {};
5099
+ attrsTranslationCtx[attrName] = value;
5100
+ }
5077
5101
  else if (attr !== "t-name") {
5078
5102
  if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
5079
5103
  throw new OwlError(`Unknown QWeb directive: '${attr}'`);
@@ -5095,6 +5119,7 @@ function parseDOMNode(node, ctx) {
5095
5119
  tag: tagName,
5096
5120
  dynamicTag,
5097
5121
  attrs,
5122
+ attrsTranslationCtx,
5098
5123
  on,
5099
5124
  ref,
5100
5125
  content: children,
@@ -5235,7 +5260,15 @@ function parseTCall(node, ctx) {
5235
5260
  if (ast && ast.type === 11 /* TComponent */) {
5236
5261
  return {
5237
5262
  ...ast,
5238
- slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
5263
+ slots: {
5264
+ default: {
5265
+ content: tcall,
5266
+ scope: null,
5267
+ on: null,
5268
+ attrs: null,
5269
+ attrsTranslationCtx: null,
5270
+ },
5271
+ },
5239
5272
  };
5240
5273
  }
5241
5274
  }
@@ -5350,9 +5383,15 @@ function parseComponent(node, ctx) {
5350
5383
  node.removeAttribute("t-slot-scope");
5351
5384
  let on = null;
5352
5385
  let props = null;
5386
+ let propsTranslationCtx = null;
5353
5387
  for (let name of node.getAttributeNames()) {
5354
5388
  const value = node.getAttribute(name);
5355
- if (name.startsWith("t-")) {
5389
+ if (name.startsWith("t-translation-context-")) {
5390
+ const attrName = name.slice(22);
5391
+ propsTranslationCtx = propsTranslationCtx || {};
5392
+ propsTranslationCtx[attrName] = value;
5393
+ }
5394
+ else if (name.startsWith("t-")) {
5356
5395
  if (name.startsWith("t-on-")) {
5357
5396
  on = on || {};
5358
5397
  on[name.slice(5)] = value;
@@ -5396,6 +5435,7 @@ function parseComponent(node, ctx) {
5396
5435
  const slotAst = parseNode(slotNode, ctx);
5397
5436
  let on = null;
5398
5437
  let attrs = null;
5438
+ let attrsTranslationCtx = null;
5399
5439
  let scope = null;
5400
5440
  for (let attributeName of slotNode.getAttributeNames()) {
5401
5441
  const value = slotNode.getAttribute(attributeName);
@@ -5403,6 +5443,11 @@ function parseComponent(node, ctx) {
5403
5443
  scope = value;
5404
5444
  continue;
5405
5445
  }
5446
+ else if (attributeName.startsWith("t-translation-context-")) {
5447
+ const attrName = attributeName.slice(22);
5448
+ attrsTranslationCtx = attrsTranslationCtx || {};
5449
+ attrsTranslationCtx[attrName] = value;
5450
+ }
5406
5451
  else if (attributeName.startsWith("t-on-")) {
5407
5452
  on = on || {};
5408
5453
  on[attributeName.slice(5)] = value;
@@ -5413,17 +5458,32 @@ function parseComponent(node, ctx) {
5413
5458
  }
5414
5459
  }
5415
5460
  slots = slots || {};
5416
- slots[name] = { content: slotAst, on, attrs, scope };
5461
+ slots[name] = { content: slotAst, on, attrs, attrsTranslationCtx, scope };
5417
5462
  }
5418
5463
  // default slot
5419
5464
  const defaultContent = parseChildNodes(clone, ctx);
5420
5465
  slots = slots || {};
5421
5466
  // t-set-slot="default" has priority over content
5422
5467
  if (defaultContent && !slots.default) {
5423
- slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
5468
+ slots.default = {
5469
+ content: defaultContent,
5470
+ on,
5471
+ attrs: null,
5472
+ attrsTranslationCtx: null,
5473
+ scope: defaultSlotScope,
5474
+ };
5424
5475
  }
5425
5476
  }
5426
- return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots, on };
5477
+ return {
5478
+ type: 11 /* TComponent */,
5479
+ name,
5480
+ isDynamic,
5481
+ dynamicProps,
5482
+ props,
5483
+ propsTranslationCtx,
5484
+ slots,
5485
+ on,
5486
+ };
5427
5487
  }
5428
5488
  // -----------------------------------------------------------------------------
5429
5489
  // Slots
@@ -5435,6 +5495,7 @@ function parseTSlot(node, ctx) {
5435
5495
  const name = node.getAttribute("t-slot");
5436
5496
  node.removeAttribute("t-slot");
5437
5497
  let attrs = null;
5498
+ let attrsTranslationCtx = null;
5438
5499
  let on = null;
5439
5500
  for (let attributeName of node.getAttributeNames()) {
5440
5501
  const value = node.getAttribute(attributeName);
@@ -5442,6 +5503,11 @@ function parseTSlot(node, ctx) {
5442
5503
  on = on || {};
5443
5504
  on[attributeName.slice(5)] = value;
5444
5505
  }
5506
+ else if (attributeName.startsWith("t-translation-context-")) {
5507
+ const attrName = attributeName.slice(22);
5508
+ attrsTranslationCtx = attrsTranslationCtx || {};
5509
+ attrsTranslationCtx[attrName] = value;
5510
+ }
5445
5511
  else {
5446
5512
  attrs = attrs || {};
5447
5513
  attrs[attributeName] = value;
@@ -5451,10 +5517,14 @@ function parseTSlot(node, ctx) {
5451
5517
  type: 14 /* TSlot */,
5452
5518
  name,
5453
5519
  attrs,
5520
+ attrsTranslationCtx,
5454
5521
  on,
5455
5522
  defaultContent: parseChildNodes(node, ctx),
5456
5523
  };
5457
5524
  }
5525
+ // -----------------------------------------------------------------------------
5526
+ // Translation
5527
+ // -----------------------------------------------------------------------------
5458
5528
  function parseTTranslation(node, ctx) {
5459
5529
  if (node.getAttribute("t-translation") !== "off") {
5460
5530
  return null;
@@ -5466,6 +5536,21 @@ function parseTTranslation(node, ctx) {
5466
5536
  };
5467
5537
  }
5468
5538
  // -----------------------------------------------------------------------------
5539
+ // Translation Context
5540
+ // -----------------------------------------------------------------------------
5541
+ function parseTTranslationContext(node, ctx) {
5542
+ const translationCtx = node.getAttribute("t-translation-context");
5543
+ if (!translationCtx) {
5544
+ return null;
5545
+ }
5546
+ node.removeAttribute("t-translation-context");
5547
+ return {
5548
+ type: 17 /* TTranslationContext */,
5549
+ content: parseNode(node, ctx),
5550
+ translationCtx,
5551
+ };
5552
+ }
5553
+ // -----------------------------------------------------------------------------
5469
5554
  // Portal
5470
5555
  // -----------------------------------------------------------------------------
5471
5556
  function parseTPortal(node, ctx) {
@@ -5482,7 +5567,7 @@ function parseTPortal(node, ctx) {
5482
5567
  };
5483
5568
  }
5484
5569
  return {
5485
- type: 17 /* TPortal */,
5570
+ type: 18 /* TPortal */,
5486
5571
  target,
5487
5572
  content,
5488
5573
  };
@@ -5624,7 +5709,7 @@ function compile(template, options = {
5624
5709
  }
5625
5710
 
5626
5711
  // do not modify manually. This file is generated by the release script.
5627
- const version = "2.5.3";
5712
+ const version = "2.6.0";
5628
5713
 
5629
5714
  // -----------------------------------------------------------------------------
5630
5715
  // Scheduler
@@ -6137,6 +6222,6 @@ exports.whenReady = whenReady;
6137
6222
  exports.xml = xml;
6138
6223
 
6139
6224
 
6140
- __info__.date = '2025-01-10T10:10:53.709Z';
6141
- __info__.hash = 'b31fa81';
6225
+ __info__.date = '2025-01-15T10:40:24.184Z';
6226
+ __info__.hash = 'a9be149';
6142
6227
  __info__.url = 'https://github.com/odoo/owl';