@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.
package/dist/owl.es.js CHANGED
@@ -3738,6 +3738,7 @@ function createContext(parentCtx, params) {
3738
3738
  index: 0,
3739
3739
  forceNewBlock: true,
3740
3740
  translate: parentCtx.translate,
3741
+ translationCtx: parentCtx.translationCtx,
3741
3742
  tKeyExpr: null,
3742
3743
  nameSpace: parentCtx.nameSpace,
3743
3744
  tModelSelectedExpr: parentCtx.tModelSelectedExpr,
@@ -3840,6 +3841,7 @@ class CodeGenerator {
3840
3841
  forceNewBlock: false,
3841
3842
  isLast: true,
3842
3843
  translate: true,
3844
+ translationCtx: "",
3843
3845
  tKeyExpr: null,
3844
3846
  });
3845
3847
  // define blocks and utility functions
@@ -3977,9 +3979,9 @@ class CodeGenerator {
3977
3979
  })
3978
3980
  .join("");
3979
3981
  }
3980
- translate(str) {
3982
+ translate(str, translationCtx) {
3981
3983
  const match = translationRE.exec(str);
3982
- return match[1] + this.translateFn(match[2]) + match[3];
3984
+ return match[1] + this.translateFn(match[2], translationCtx) + match[3];
3983
3985
  }
3984
3986
  /**
3985
3987
  * @returns the newly created block name, if any
@@ -4020,7 +4022,9 @@ class CodeGenerator {
4020
4022
  return this.compileTSlot(ast, ctx);
4021
4023
  case 16 /* TTranslation */:
4022
4024
  return this.compileTTranslation(ast, ctx);
4023
- case 17 /* TPortal */:
4025
+ case 17 /* TTranslationContext */:
4026
+ return this.compileTTranslationContext(ast, ctx);
4027
+ case 18 /* TPortal */:
4024
4028
  return this.compileTPortal(ast, ctx);
4025
4029
  }
4026
4030
  }
@@ -4058,7 +4062,7 @@ class CodeGenerator {
4058
4062
  let { block, forceNewBlock } = ctx;
4059
4063
  let value = ast.value;
4060
4064
  if (value && ctx.translate !== false) {
4061
- value = this.translate(value);
4065
+ value = this.translate(value, ctx.translationCtx);
4062
4066
  }
4063
4067
  if (!ctx.inPreTag) {
4064
4068
  value = value.replace(whitespaceRE, " ");
@@ -4093,6 +4097,7 @@ class CodeGenerator {
4093
4097
  return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
4094
4098
  }
4095
4099
  compileTDomNode(ast, ctx) {
4100
+ var _a;
4096
4101
  let { block, forceNewBlock } = ctx;
4097
4102
  const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
4098
4103
  let codeIdx = this.target.code.length;
@@ -4148,7 +4153,8 @@ class CodeGenerator {
4148
4153
  }
4149
4154
  }
4150
4155
  else if (this.translatableAttributes.includes(key)) {
4151
- attrs[key] = this.translateFn(ast.attrs[key]);
4156
+ const attrTranslationCtx = ((_a = ast.attrsTranslationCtx) === null || _a === void 0 ? void 0 : _a[key]) || ctx.translationCtx;
4157
+ attrs[key] = this.translateFn(ast.attrs[key], attrTranslationCtx);
4152
4158
  }
4153
4159
  else {
4154
4160
  expr = `"${ast.attrs[key]}"`;
@@ -4592,7 +4598,7 @@ class CodeGenerator {
4592
4598
  else {
4593
4599
  let value;
4594
4600
  if (ast.defaultValue) {
4595
- const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue);
4601
+ const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue, ctx.translationCtx) : ast.defaultValue);
4596
4602
  if (ast.value) {
4597
4603
  value = `withDefault(${expr}, ${defaultValue})`;
4598
4604
  }
@@ -4626,9 +4632,10 @@ class CodeGenerator {
4626
4632
  * "some-prop" "state" "'some-prop': ctx['state']"
4627
4633
  * "onClick.bind" "onClick" "onClick: bind(ctx, ctx['onClick'])"
4628
4634
  */
4629
- formatProp(name, value) {
4635
+ formatProp(name, value, attrsTranslationCtx, translationCtx) {
4630
4636
  if (name.endsWith(".translate")) {
4631
- value = toStringExpression(this.translateFn(value));
4637
+ const attrTranslationCtx = (attrsTranslationCtx === null || attrsTranslationCtx === void 0 ? void 0 : attrsTranslationCtx[name]) || translationCtx;
4638
+ value = toStringExpression(this.translateFn(value, attrTranslationCtx));
4632
4639
  }
4633
4640
  else {
4634
4641
  value = this.captureExpression(value);
@@ -4650,8 +4657,8 @@ class CodeGenerator {
4650
4657
  name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
4651
4658
  return `${name}: ${value || undefined}`;
4652
4659
  }
4653
- formatPropObject(obj) {
4654
- return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
4660
+ formatPropObject(obj, attrsTranslationCtx, translationCtx) {
4661
+ return Object.entries(obj).map(([k, v]) => this.formatProp(k, v, attrsTranslationCtx, translationCtx));
4655
4662
  }
4656
4663
  getPropString(props, dynProps) {
4657
4664
  let propString = `{${props.join(",")}}`;
@@ -4664,7 +4671,9 @@ class CodeGenerator {
4664
4671
  let { block } = ctx;
4665
4672
  // props
4666
4673
  const hasSlotsProp = "slots" in (ast.props || {});
4667
- const props = ast.props ? this.formatPropObject(ast.props) : [];
4674
+ const props = ast.props
4675
+ ? this.formatPropObject(ast.props, ast.propsTranslationCtx, ctx.translationCtx)
4676
+ : [];
4668
4677
  // slots
4669
4678
  let slotDef = "";
4670
4679
  if (ast.slots) {
@@ -4687,7 +4696,7 @@ class CodeGenerator {
4687
4696
  params.push(`__scope: "${scope}"`);
4688
4697
  }
4689
4698
  if (ast.slots[slotName].attrs) {
4690
- params.push(...this.formatPropObject(ast.slots[slotName].attrs));
4699
+ params.push(...this.formatPropObject(ast.slots[slotName].attrs, ast.slots[slotName].attrsTranslationCtx, ctx.translationCtx));
4691
4700
  }
4692
4701
  const slotInfo = `{${params.join(", ")}}`;
4693
4702
  slotStr.push(`'${slotName}': ${slotInfo}`);
@@ -4800,7 +4809,9 @@ class CodeGenerator {
4800
4809
  if (isMultiple) {
4801
4810
  key = this.generateComponentKey(key);
4802
4811
  }
4803
- const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
4812
+ const props = ast.attrs
4813
+ ? this.formatPropObject(ast.attrs, ast.attrsTranslationCtx, ctx.translationCtx)
4814
+ : [];
4804
4815
  const scope = this.getPropString(props, dynProps);
4805
4816
  if (ast.defaultContent) {
4806
4817
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
@@ -4833,6 +4844,12 @@ class CodeGenerator {
4833
4844
  }
4834
4845
  return null;
4835
4846
  }
4847
+ compileTTranslationContext(ast, ctx) {
4848
+ if (ast.content) {
4849
+ return this.compileAST(ast.content, Object.assign({}, ctx, { translationCtx: ast.translationCtx }));
4850
+ }
4851
+ return null;
4852
+ }
4836
4853
  compileTPortal(ast, ctx) {
4837
4854
  if (!this.staticDefs.find((d) => d.id === "Portal")) {
4838
4855
  this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
@@ -4902,6 +4919,7 @@ function parseNode(node, ctx) {
4902
4919
  parseTOutNode(node, ctx) ||
4903
4920
  parseTKey(node, ctx) ||
4904
4921
  parseTTranslation(node, ctx) ||
4922
+ parseTTranslationContext(node, ctx) ||
4905
4923
  parseTSlot(node, ctx) ||
4906
4924
  parseComponent(node, ctx) ||
4907
4925
  parseDOMNode(node, ctx) ||
@@ -5010,6 +5028,7 @@ function parseDOMNode(node, ctx) {
5010
5028
  node.removeAttribute("t-ref");
5011
5029
  const nodeAttrsNames = node.getAttributeNames();
5012
5030
  let attrs = null;
5031
+ let attrsTranslationCtx = null;
5013
5032
  let on = null;
5014
5033
  let model = null;
5015
5034
  for (let attr of nodeAttrsNames) {
@@ -5070,6 +5089,11 @@ function parseDOMNode(node, ctx) {
5070
5089
  else if (attr === "xmlns") {
5071
5090
  ns = value;
5072
5091
  }
5092
+ else if (attr.startsWith("t-translation-context-")) {
5093
+ const attrName = attr.slice(22);
5094
+ attrsTranslationCtx = attrsTranslationCtx || {};
5095
+ attrsTranslationCtx[attrName] = value;
5096
+ }
5073
5097
  else if (attr !== "t-name") {
5074
5098
  if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
5075
5099
  throw new OwlError(`Unknown QWeb directive: '${attr}'`);
@@ -5091,6 +5115,7 @@ function parseDOMNode(node, ctx) {
5091
5115
  tag: tagName,
5092
5116
  dynamicTag,
5093
5117
  attrs,
5118
+ attrsTranslationCtx,
5094
5119
  on,
5095
5120
  ref,
5096
5121
  content: children,
@@ -5231,7 +5256,15 @@ function parseTCall(node, ctx) {
5231
5256
  if (ast && ast.type === 11 /* TComponent */) {
5232
5257
  return {
5233
5258
  ...ast,
5234
- slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
5259
+ slots: {
5260
+ default: {
5261
+ content: tcall,
5262
+ scope: null,
5263
+ on: null,
5264
+ attrs: null,
5265
+ attrsTranslationCtx: null,
5266
+ },
5267
+ },
5235
5268
  };
5236
5269
  }
5237
5270
  }
@@ -5346,9 +5379,15 @@ function parseComponent(node, ctx) {
5346
5379
  node.removeAttribute("t-slot-scope");
5347
5380
  let on = null;
5348
5381
  let props = null;
5382
+ let propsTranslationCtx = null;
5349
5383
  for (let name of node.getAttributeNames()) {
5350
5384
  const value = node.getAttribute(name);
5351
- if (name.startsWith("t-")) {
5385
+ if (name.startsWith("t-translation-context-")) {
5386
+ const attrName = name.slice(22);
5387
+ propsTranslationCtx = propsTranslationCtx || {};
5388
+ propsTranslationCtx[attrName] = value;
5389
+ }
5390
+ else if (name.startsWith("t-")) {
5352
5391
  if (name.startsWith("t-on-")) {
5353
5392
  on = on || {};
5354
5393
  on[name.slice(5)] = value;
@@ -5392,6 +5431,7 @@ function parseComponent(node, ctx) {
5392
5431
  const slotAst = parseNode(slotNode, ctx);
5393
5432
  let on = null;
5394
5433
  let attrs = null;
5434
+ let attrsTranslationCtx = null;
5395
5435
  let scope = null;
5396
5436
  for (let attributeName of slotNode.getAttributeNames()) {
5397
5437
  const value = slotNode.getAttribute(attributeName);
@@ -5399,6 +5439,11 @@ function parseComponent(node, ctx) {
5399
5439
  scope = value;
5400
5440
  continue;
5401
5441
  }
5442
+ else if (attributeName.startsWith("t-translation-context-")) {
5443
+ const attrName = attributeName.slice(22);
5444
+ attrsTranslationCtx = attrsTranslationCtx || {};
5445
+ attrsTranslationCtx[attrName] = value;
5446
+ }
5402
5447
  else if (attributeName.startsWith("t-on-")) {
5403
5448
  on = on || {};
5404
5449
  on[attributeName.slice(5)] = value;
@@ -5409,17 +5454,32 @@ function parseComponent(node, ctx) {
5409
5454
  }
5410
5455
  }
5411
5456
  slots = slots || {};
5412
- slots[name] = { content: slotAst, on, attrs, scope };
5457
+ slots[name] = { content: slotAst, on, attrs, attrsTranslationCtx, scope };
5413
5458
  }
5414
5459
  // default slot
5415
5460
  const defaultContent = parseChildNodes(clone, ctx);
5416
5461
  slots = slots || {};
5417
5462
  // t-set-slot="default" has priority over content
5418
5463
  if (defaultContent && !slots.default) {
5419
- slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
5464
+ slots.default = {
5465
+ content: defaultContent,
5466
+ on,
5467
+ attrs: null,
5468
+ attrsTranslationCtx: null,
5469
+ scope: defaultSlotScope,
5470
+ };
5420
5471
  }
5421
5472
  }
5422
- return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots, on };
5473
+ return {
5474
+ type: 11 /* TComponent */,
5475
+ name,
5476
+ isDynamic,
5477
+ dynamicProps,
5478
+ props,
5479
+ propsTranslationCtx,
5480
+ slots,
5481
+ on,
5482
+ };
5423
5483
  }
5424
5484
  // -----------------------------------------------------------------------------
5425
5485
  // Slots
@@ -5431,6 +5491,7 @@ function parseTSlot(node, ctx) {
5431
5491
  const name = node.getAttribute("t-slot");
5432
5492
  node.removeAttribute("t-slot");
5433
5493
  let attrs = null;
5494
+ let attrsTranslationCtx = null;
5434
5495
  let on = null;
5435
5496
  for (let attributeName of node.getAttributeNames()) {
5436
5497
  const value = node.getAttribute(attributeName);
@@ -5438,6 +5499,11 @@ function parseTSlot(node, ctx) {
5438
5499
  on = on || {};
5439
5500
  on[attributeName.slice(5)] = value;
5440
5501
  }
5502
+ else if (attributeName.startsWith("t-translation-context-")) {
5503
+ const attrName = attributeName.slice(22);
5504
+ attrsTranslationCtx = attrsTranslationCtx || {};
5505
+ attrsTranslationCtx[attrName] = value;
5506
+ }
5441
5507
  else {
5442
5508
  attrs = attrs || {};
5443
5509
  attrs[attributeName] = value;
@@ -5447,10 +5513,14 @@ function parseTSlot(node, ctx) {
5447
5513
  type: 14 /* TSlot */,
5448
5514
  name,
5449
5515
  attrs,
5516
+ attrsTranslationCtx,
5450
5517
  on,
5451
5518
  defaultContent: parseChildNodes(node, ctx),
5452
5519
  };
5453
5520
  }
5521
+ // -----------------------------------------------------------------------------
5522
+ // Translation
5523
+ // -----------------------------------------------------------------------------
5454
5524
  function parseTTranslation(node, ctx) {
5455
5525
  if (node.getAttribute("t-translation") !== "off") {
5456
5526
  return null;
@@ -5462,6 +5532,21 @@ function parseTTranslation(node, ctx) {
5462
5532
  };
5463
5533
  }
5464
5534
  // -----------------------------------------------------------------------------
5535
+ // Translation Context
5536
+ // -----------------------------------------------------------------------------
5537
+ function parseTTranslationContext(node, ctx) {
5538
+ const translationCtx = node.getAttribute("t-translation-context");
5539
+ if (!translationCtx) {
5540
+ return null;
5541
+ }
5542
+ node.removeAttribute("t-translation-context");
5543
+ return {
5544
+ type: 17 /* TTranslationContext */,
5545
+ content: parseNode(node, ctx),
5546
+ translationCtx,
5547
+ };
5548
+ }
5549
+ // -----------------------------------------------------------------------------
5465
5550
  // Portal
5466
5551
  // -----------------------------------------------------------------------------
5467
5552
  function parseTPortal(node, ctx) {
@@ -5478,7 +5563,7 @@ function parseTPortal(node, ctx) {
5478
5563
  };
5479
5564
  }
5480
5565
  return {
5481
- type: 17 /* TPortal */,
5566
+ type: 18 /* TPortal */,
5482
5567
  target,
5483
5568
  content,
5484
5569
  };
@@ -5620,7 +5705,7 @@ function compile(template, options = {
5620
5705
  }
5621
5706
 
5622
5707
  // do not modify manually. This file is generated by the release script.
5623
- const version = "2.5.3";
5708
+ const version = "2.6.0";
5624
5709
 
5625
5710
  // -----------------------------------------------------------------------------
5626
5711
  // Scheduler
@@ -6098,6 +6183,6 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
6098
6183
  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 };
6099
6184
 
6100
6185
 
6101
- __info__.date = '2025-01-10T10:10:53.709Z';
6102
- __info__.hash = 'b31fa81';
6186
+ __info__.date = '2025-01-15T10:40:24.184Z';
6187
+ __info__.hash = 'a9be149';
6103
6188
  __info__.url = 'https://github.com/odoo/owl';
package/dist/owl.iife.js CHANGED
@@ -3741,6 +3741,7 @@
3741
3741
  index: 0,
3742
3742
  forceNewBlock: true,
3743
3743
  translate: parentCtx.translate,
3744
+ translationCtx: parentCtx.translationCtx,
3744
3745
  tKeyExpr: null,
3745
3746
  nameSpace: parentCtx.nameSpace,
3746
3747
  tModelSelectedExpr: parentCtx.tModelSelectedExpr,
@@ -3843,6 +3844,7 @@
3843
3844
  forceNewBlock: false,
3844
3845
  isLast: true,
3845
3846
  translate: true,
3847
+ translationCtx: "",
3846
3848
  tKeyExpr: null,
3847
3849
  });
3848
3850
  // define blocks and utility functions
@@ -3980,9 +3982,9 @@
3980
3982
  })
3981
3983
  .join("");
3982
3984
  }
3983
- translate(str) {
3985
+ translate(str, translationCtx) {
3984
3986
  const match = translationRE.exec(str);
3985
- return match[1] + this.translateFn(match[2]) + match[3];
3987
+ return match[1] + this.translateFn(match[2], translationCtx) + match[3];
3986
3988
  }
3987
3989
  /**
3988
3990
  * @returns the newly created block name, if any
@@ -4023,7 +4025,9 @@
4023
4025
  return this.compileTSlot(ast, ctx);
4024
4026
  case 16 /* TTranslation */:
4025
4027
  return this.compileTTranslation(ast, ctx);
4026
- case 17 /* TPortal */:
4028
+ case 17 /* TTranslationContext */:
4029
+ return this.compileTTranslationContext(ast, ctx);
4030
+ case 18 /* TPortal */:
4027
4031
  return this.compileTPortal(ast, ctx);
4028
4032
  }
4029
4033
  }
@@ -4061,7 +4065,7 @@
4061
4065
  let { block, forceNewBlock } = ctx;
4062
4066
  let value = ast.value;
4063
4067
  if (value && ctx.translate !== false) {
4064
- value = this.translate(value);
4068
+ value = this.translate(value, ctx.translationCtx);
4065
4069
  }
4066
4070
  if (!ctx.inPreTag) {
4067
4071
  value = value.replace(whitespaceRE, " ");
@@ -4096,6 +4100,7 @@
4096
4100
  return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
4097
4101
  }
4098
4102
  compileTDomNode(ast, ctx) {
4103
+ var _a;
4099
4104
  let { block, forceNewBlock } = ctx;
4100
4105
  const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
4101
4106
  let codeIdx = this.target.code.length;
@@ -4151,7 +4156,8 @@
4151
4156
  }
4152
4157
  }
4153
4158
  else if (this.translatableAttributes.includes(key)) {
4154
- attrs[key] = this.translateFn(ast.attrs[key]);
4159
+ const attrTranslationCtx = ((_a = ast.attrsTranslationCtx) === null || _a === void 0 ? void 0 : _a[key]) || ctx.translationCtx;
4160
+ attrs[key] = this.translateFn(ast.attrs[key], attrTranslationCtx);
4155
4161
  }
4156
4162
  else {
4157
4163
  expr = `"${ast.attrs[key]}"`;
@@ -4595,7 +4601,7 @@
4595
4601
  else {
4596
4602
  let value;
4597
4603
  if (ast.defaultValue) {
4598
- const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue);
4604
+ const defaultValue = toStringExpression(ctx.translate ? this.translate(ast.defaultValue, ctx.translationCtx) : ast.defaultValue);
4599
4605
  if (ast.value) {
4600
4606
  value = `withDefault(${expr}, ${defaultValue})`;
4601
4607
  }
@@ -4629,9 +4635,10 @@
4629
4635
  * "some-prop" "state" "'some-prop': ctx['state']"
4630
4636
  * "onClick.bind" "onClick" "onClick: bind(ctx, ctx['onClick'])"
4631
4637
  */
4632
- formatProp(name, value) {
4638
+ formatProp(name, value, attrsTranslationCtx, translationCtx) {
4633
4639
  if (name.endsWith(".translate")) {
4634
- value = toStringExpression(this.translateFn(value));
4640
+ const attrTranslationCtx = (attrsTranslationCtx === null || attrsTranslationCtx === void 0 ? void 0 : attrsTranslationCtx[name]) || translationCtx;
4641
+ value = toStringExpression(this.translateFn(value, attrTranslationCtx));
4635
4642
  }
4636
4643
  else {
4637
4644
  value = this.captureExpression(value);
@@ -4653,8 +4660,8 @@
4653
4660
  name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
4654
4661
  return `${name}: ${value || undefined}`;
4655
4662
  }
4656
- formatPropObject(obj) {
4657
- return Object.entries(obj).map(([k, v]) => this.formatProp(k, v));
4663
+ formatPropObject(obj, attrsTranslationCtx, translationCtx) {
4664
+ return Object.entries(obj).map(([k, v]) => this.formatProp(k, v, attrsTranslationCtx, translationCtx));
4658
4665
  }
4659
4666
  getPropString(props, dynProps) {
4660
4667
  let propString = `{${props.join(",")}}`;
@@ -4667,7 +4674,9 @@
4667
4674
  let { block } = ctx;
4668
4675
  // props
4669
4676
  const hasSlotsProp = "slots" in (ast.props || {});
4670
- const props = ast.props ? this.formatPropObject(ast.props) : [];
4677
+ const props = ast.props
4678
+ ? this.formatPropObject(ast.props, ast.propsTranslationCtx, ctx.translationCtx)
4679
+ : [];
4671
4680
  // slots
4672
4681
  let slotDef = "";
4673
4682
  if (ast.slots) {
@@ -4690,7 +4699,7 @@
4690
4699
  params.push(`__scope: "${scope}"`);
4691
4700
  }
4692
4701
  if (ast.slots[slotName].attrs) {
4693
- params.push(...this.formatPropObject(ast.slots[slotName].attrs));
4702
+ params.push(...this.formatPropObject(ast.slots[slotName].attrs, ast.slots[slotName].attrsTranslationCtx, ctx.translationCtx));
4694
4703
  }
4695
4704
  const slotInfo = `{${params.join(", ")}}`;
4696
4705
  slotStr.push(`'${slotName}': ${slotInfo}`);
@@ -4803,7 +4812,9 @@
4803
4812
  if (isMultiple) {
4804
4813
  key = this.generateComponentKey(key);
4805
4814
  }
4806
- const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
4815
+ const props = ast.attrs
4816
+ ? this.formatPropObject(ast.attrs, ast.attrsTranslationCtx, ctx.translationCtx)
4817
+ : [];
4807
4818
  const scope = this.getPropString(props, dynProps);
4808
4819
  if (ast.defaultContent) {
4809
4820
  const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
@@ -4836,6 +4847,12 @@
4836
4847
  }
4837
4848
  return null;
4838
4849
  }
4850
+ compileTTranslationContext(ast, ctx) {
4851
+ if (ast.content) {
4852
+ return this.compileAST(ast.content, Object.assign({}, ctx, { translationCtx: ast.translationCtx }));
4853
+ }
4854
+ return null;
4855
+ }
4839
4856
  compileTPortal(ast, ctx) {
4840
4857
  if (!this.staticDefs.find((d) => d.id === "Portal")) {
4841
4858
  this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
@@ -4905,6 +4922,7 @@
4905
4922
  parseTOutNode(node, ctx) ||
4906
4923
  parseTKey(node, ctx) ||
4907
4924
  parseTTranslation(node, ctx) ||
4925
+ parseTTranslationContext(node, ctx) ||
4908
4926
  parseTSlot(node, ctx) ||
4909
4927
  parseComponent(node, ctx) ||
4910
4928
  parseDOMNode(node, ctx) ||
@@ -5013,6 +5031,7 @@
5013
5031
  node.removeAttribute("t-ref");
5014
5032
  const nodeAttrsNames = node.getAttributeNames();
5015
5033
  let attrs = null;
5034
+ let attrsTranslationCtx = null;
5016
5035
  let on = null;
5017
5036
  let model = null;
5018
5037
  for (let attr of nodeAttrsNames) {
@@ -5073,6 +5092,11 @@
5073
5092
  else if (attr === "xmlns") {
5074
5093
  ns = value;
5075
5094
  }
5095
+ else if (attr.startsWith("t-translation-context-")) {
5096
+ const attrName = attr.slice(22);
5097
+ attrsTranslationCtx = attrsTranslationCtx || {};
5098
+ attrsTranslationCtx[attrName] = value;
5099
+ }
5076
5100
  else if (attr !== "t-name") {
5077
5101
  if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
5078
5102
  throw new OwlError(`Unknown QWeb directive: '${attr}'`);
@@ -5094,6 +5118,7 @@
5094
5118
  tag: tagName,
5095
5119
  dynamicTag,
5096
5120
  attrs,
5121
+ attrsTranslationCtx,
5097
5122
  on,
5098
5123
  ref,
5099
5124
  content: children,
@@ -5234,7 +5259,15 @@
5234
5259
  if (ast && ast.type === 11 /* TComponent */) {
5235
5260
  return {
5236
5261
  ...ast,
5237
- slots: { default: { content: tcall, scope: null, on: null, attrs: null } },
5262
+ slots: {
5263
+ default: {
5264
+ content: tcall,
5265
+ scope: null,
5266
+ on: null,
5267
+ attrs: null,
5268
+ attrsTranslationCtx: null,
5269
+ },
5270
+ },
5238
5271
  };
5239
5272
  }
5240
5273
  }
@@ -5349,9 +5382,15 @@
5349
5382
  node.removeAttribute("t-slot-scope");
5350
5383
  let on = null;
5351
5384
  let props = null;
5385
+ let propsTranslationCtx = null;
5352
5386
  for (let name of node.getAttributeNames()) {
5353
5387
  const value = node.getAttribute(name);
5354
- if (name.startsWith("t-")) {
5388
+ if (name.startsWith("t-translation-context-")) {
5389
+ const attrName = name.slice(22);
5390
+ propsTranslationCtx = propsTranslationCtx || {};
5391
+ propsTranslationCtx[attrName] = value;
5392
+ }
5393
+ else if (name.startsWith("t-")) {
5355
5394
  if (name.startsWith("t-on-")) {
5356
5395
  on = on || {};
5357
5396
  on[name.slice(5)] = value;
@@ -5395,6 +5434,7 @@
5395
5434
  const slotAst = parseNode(slotNode, ctx);
5396
5435
  let on = null;
5397
5436
  let attrs = null;
5437
+ let attrsTranslationCtx = null;
5398
5438
  let scope = null;
5399
5439
  for (let attributeName of slotNode.getAttributeNames()) {
5400
5440
  const value = slotNode.getAttribute(attributeName);
@@ -5402,6 +5442,11 @@
5402
5442
  scope = value;
5403
5443
  continue;
5404
5444
  }
5445
+ else if (attributeName.startsWith("t-translation-context-")) {
5446
+ const attrName = attributeName.slice(22);
5447
+ attrsTranslationCtx = attrsTranslationCtx || {};
5448
+ attrsTranslationCtx[attrName] = value;
5449
+ }
5405
5450
  else if (attributeName.startsWith("t-on-")) {
5406
5451
  on = on || {};
5407
5452
  on[attributeName.slice(5)] = value;
@@ -5412,17 +5457,32 @@
5412
5457
  }
5413
5458
  }
5414
5459
  slots = slots || {};
5415
- slots[name] = { content: slotAst, on, attrs, scope };
5460
+ slots[name] = { content: slotAst, on, attrs, attrsTranslationCtx, scope };
5416
5461
  }
5417
5462
  // default slot
5418
5463
  const defaultContent = parseChildNodes(clone, ctx);
5419
5464
  slots = slots || {};
5420
5465
  // t-set-slot="default" has priority over content
5421
5466
  if (defaultContent && !slots.default) {
5422
- slots.default = { content: defaultContent, on, attrs: null, scope: defaultSlotScope };
5467
+ slots.default = {
5468
+ content: defaultContent,
5469
+ on,
5470
+ attrs: null,
5471
+ attrsTranslationCtx: null,
5472
+ scope: defaultSlotScope,
5473
+ };
5423
5474
  }
5424
5475
  }
5425
- return { type: 11 /* TComponent */, name, isDynamic, dynamicProps, props, slots, on };
5476
+ return {
5477
+ type: 11 /* TComponent */,
5478
+ name,
5479
+ isDynamic,
5480
+ dynamicProps,
5481
+ props,
5482
+ propsTranslationCtx,
5483
+ slots,
5484
+ on,
5485
+ };
5426
5486
  }
5427
5487
  // -----------------------------------------------------------------------------
5428
5488
  // Slots
@@ -5434,6 +5494,7 @@
5434
5494
  const name = node.getAttribute("t-slot");
5435
5495
  node.removeAttribute("t-slot");
5436
5496
  let attrs = null;
5497
+ let attrsTranslationCtx = null;
5437
5498
  let on = null;
5438
5499
  for (let attributeName of node.getAttributeNames()) {
5439
5500
  const value = node.getAttribute(attributeName);
@@ -5441,6 +5502,11 @@
5441
5502
  on = on || {};
5442
5503
  on[attributeName.slice(5)] = value;
5443
5504
  }
5505
+ else if (attributeName.startsWith("t-translation-context-")) {
5506
+ const attrName = attributeName.slice(22);
5507
+ attrsTranslationCtx = attrsTranslationCtx || {};
5508
+ attrsTranslationCtx[attrName] = value;
5509
+ }
5444
5510
  else {
5445
5511
  attrs = attrs || {};
5446
5512
  attrs[attributeName] = value;
@@ -5450,10 +5516,14 @@
5450
5516
  type: 14 /* TSlot */,
5451
5517
  name,
5452
5518
  attrs,
5519
+ attrsTranslationCtx,
5453
5520
  on,
5454
5521
  defaultContent: parseChildNodes(node, ctx),
5455
5522
  };
5456
5523
  }
5524
+ // -----------------------------------------------------------------------------
5525
+ // Translation
5526
+ // -----------------------------------------------------------------------------
5457
5527
  function parseTTranslation(node, ctx) {
5458
5528
  if (node.getAttribute("t-translation") !== "off") {
5459
5529
  return null;
@@ -5465,6 +5535,21 @@
5465
5535
  };
5466
5536
  }
5467
5537
  // -----------------------------------------------------------------------------
5538
+ // Translation Context
5539
+ // -----------------------------------------------------------------------------
5540
+ function parseTTranslationContext(node, ctx) {
5541
+ const translationCtx = node.getAttribute("t-translation-context");
5542
+ if (!translationCtx) {
5543
+ return null;
5544
+ }
5545
+ node.removeAttribute("t-translation-context");
5546
+ return {
5547
+ type: 17 /* TTranslationContext */,
5548
+ content: parseNode(node, ctx),
5549
+ translationCtx,
5550
+ };
5551
+ }
5552
+ // -----------------------------------------------------------------------------
5468
5553
  // Portal
5469
5554
  // -----------------------------------------------------------------------------
5470
5555
  function parseTPortal(node, ctx) {
@@ -5481,7 +5566,7 @@
5481
5566
  };
5482
5567
  }
5483
5568
  return {
5484
- type: 17 /* TPortal */,
5569
+ type: 18 /* TPortal */,
5485
5570
  target,
5486
5571
  content,
5487
5572
  };
@@ -5623,7 +5708,7 @@
5623
5708
  }
5624
5709
 
5625
5710
  // do not modify manually. This file is generated by the release script.
5626
- const version = "2.5.3";
5711
+ const version = "2.6.0";
5627
5712
 
5628
5713
  // -----------------------------------------------------------------------------
5629
5714
  // Scheduler
@@ -6138,8 +6223,8 @@ See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration
6138
6223
  Object.defineProperty(exports, '__esModule', { value: true });
6139
6224
 
6140
6225
 
6141
- __info__.date = '2025-01-10T10:10:53.709Z';
6142
- __info__.hash = 'b31fa81';
6226
+ __info__.date = '2025-01-15T10:40:24.184Z';
6227
+ __info__.hash = 'a9be149';
6143
6228
  __info__.url = 'https://github.com/odoo/owl';
6144
6229
 
6145
6230