@intlify/core-base 10.0.6 → 10.0.8

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * core-base v10.0.6
2
+ * core-base v10.0.8
3
3
  * (c) 2025 kazuya kawaguchi
4
4
  * Released under the MIT License.
5
5
  */
@@ -8,6 +8,80 @@
8
8
  var messageCompiler = require('@intlify/message-compiler');
9
9
  var shared = require('@intlify/shared');
10
10
 
11
+ function isMessageAST(val) {
12
+ return (shared.isObject(val) &&
13
+ resolveType(val) === 0 &&
14
+ (shared.hasOwn(val, 'b') || shared.hasOwn(val, 'body')));
15
+ }
16
+ const PROPS_BODY = ['b', 'body'];
17
+ function resolveBody(node) {
18
+ return resolveProps(node, PROPS_BODY);
19
+ }
20
+ const PROPS_CASES = ['c', 'cases'];
21
+ function resolveCases(node) {
22
+ return resolveProps(node, PROPS_CASES, []);
23
+ }
24
+ const PROPS_STATIC = ['s', 'static'];
25
+ function resolveStatic(node) {
26
+ return resolveProps(node, PROPS_STATIC);
27
+ }
28
+ const PROPS_ITEMS = ['i', 'items'];
29
+ function resolveItems(node) {
30
+ return resolveProps(node, PROPS_ITEMS, []);
31
+ }
32
+ const PROPS_TYPE = ['t', 'type'];
33
+ function resolveType(node) {
34
+ return resolveProps(node, PROPS_TYPE);
35
+ }
36
+ const PROPS_VALUE = ['v', 'value'];
37
+ function resolveValue$1(node, type) {
38
+ const resolved = resolveProps(node, PROPS_VALUE);
39
+ if (resolved != null) {
40
+ return resolved;
41
+ }
42
+ else {
43
+ throw createUnhandleNodeError(type);
44
+ }
45
+ }
46
+ const PROPS_MODIFIER = ['m', 'modifier'];
47
+ function resolveLinkedModifier(node) {
48
+ return resolveProps(node, PROPS_MODIFIER);
49
+ }
50
+ const PROPS_KEY = ['k', 'key'];
51
+ function resolveLinkedKey(node) {
52
+ const resolved = resolveProps(node, PROPS_KEY);
53
+ if (resolved) {
54
+ return resolved;
55
+ }
56
+ else {
57
+ throw createUnhandleNodeError(6 /* NodeTypes.Linked */);
58
+ }
59
+ }
60
+ function resolveProps(node, props, defaultValue) {
61
+ for (let i = 0; i < props.length; i++) {
62
+ const prop = props[i];
63
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
+ if (shared.hasOwn(node, prop) && node[prop] != null) {
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ return node[prop];
67
+ }
68
+ }
69
+ return defaultValue;
70
+ }
71
+ const AST_NODE_PROPS_KEYS = [
72
+ ...PROPS_BODY,
73
+ ...PROPS_CASES,
74
+ ...PROPS_STATIC,
75
+ ...PROPS_ITEMS,
76
+ ...PROPS_KEY,
77
+ ...PROPS_MODIFIER,
78
+ ...PROPS_VALUE,
79
+ ...PROPS_TYPE
80
+ ];
81
+ function createUnhandleNodeError(type) {
82
+ return new Error(`unhandled node type: ${type}`);
83
+ }
84
+
11
85
  function format(ast) {
12
86
  const msg = (ctx) => formatParts(ctx, ast);
13
87
  return msg;
@@ -30,14 +104,6 @@ function formatParts(ctx, ast) {
30
104
  return formatMessageParts(ctx, body);
31
105
  }
32
106
  }
33
- const PROPS_BODY = ['b', 'body'];
34
- function resolveBody(node) {
35
- return resolveProps(node, PROPS_BODY);
36
- }
37
- const PROPS_CASES = ['c', 'cases'];
38
- function resolveCases(node) {
39
- return resolveProps(node, PROPS_CASES, []);
40
- }
41
107
  function formatMessageParts(ctx, node) {
42
108
  const static_ = resolveStatic(node);
43
109
  if (static_ != null) {
@@ -50,14 +116,6 @@ function formatMessageParts(ctx, node) {
50
116
  return ctx.normalize(messages);
51
117
  }
52
118
  }
53
- const PROPS_STATIC = ['s', 'static'];
54
- function resolveStatic(node) {
55
- return resolveProps(node, PROPS_STATIC);
56
- }
57
- const PROPS_ITEMS = ['i', 'items'];
58
- function resolveItems(node) {
59
- return resolveProps(node, PROPS_ITEMS, []);
60
- }
61
119
  function formatMessagePart(ctx, node) {
62
120
  const type = resolveType(node);
63
121
  switch (type) {
@@ -103,48 +161,6 @@ function formatMessagePart(ctx, node) {
103
161
  throw new Error(`unhandled node on format message part: ${type}`);
104
162
  }
105
163
  }
106
- const PROPS_TYPE = ['t', 'type'];
107
- function resolveType(node) {
108
- return resolveProps(node, PROPS_TYPE);
109
- }
110
- const PROPS_VALUE = ['v', 'value'];
111
- function resolveValue$1(node, type) {
112
- const resolved = resolveProps(node, PROPS_VALUE);
113
- if (resolved) {
114
- return resolved;
115
- }
116
- else {
117
- throw createUnhandleNodeError(type);
118
- }
119
- }
120
- const PROPS_MODIFIER = ['m', 'modifier'];
121
- function resolveLinkedModifier(node) {
122
- return resolveProps(node, PROPS_MODIFIER);
123
- }
124
- const PROPS_KEY = ['k', 'key'];
125
- function resolveLinkedKey(node) {
126
- const resolved = resolveProps(node, PROPS_KEY);
127
- if (resolved) {
128
- return resolved;
129
- }
130
- else {
131
- throw createUnhandleNodeError(6 /* NodeTypes.Linked */);
132
- }
133
- }
134
- function resolveProps(node, props, defaultValue) {
135
- for (let i = 0; i < props.length; i++) {
136
- const prop = props[i];
137
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
- if (shared.hasOwn(node, prop) && node[prop] != null) {
139
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
140
- return node[prop];
141
- }
142
- }
143
- return defaultValue;
144
- }
145
- function createUnhandleNodeError(type) {
146
- return new Error(`unhandled node type: ${type}`);
147
- }
148
164
 
149
165
  const WARN_MESSAGE = `Detected HTML in '{source}' message. Recommend not using HTML messages to avoid XSS.`;
150
166
  function checkHtmlMessage(source, warnHtmlMessage) {
@@ -157,11 +173,6 @@ let compileCache = shared.create();
157
173
  function clearCompileCache() {
158
174
  compileCache = shared.create();
159
175
  }
160
- function isMessageAST(val) {
161
- return (shared.isObject(val) &&
162
- resolveType(val) === 0 &&
163
- (shared.hasOwn(val, 'b') || shared.hasOwn(val, 'body')));
164
- }
165
176
  function baseCompile(message, options = {}) {
166
177
  // error detecting on compile
167
178
  let detectError = false;
@@ -674,7 +685,16 @@ function resolveValue(obj, path) {
674
685
  let last = obj;
675
686
  let i = 0;
676
687
  while (i < len) {
677
- const val = last[hit[i]];
688
+ const key = hit[i];
689
+ /**
690
+ * NOTE:
691
+ * if `key` is intlify message format AST node key and `last` is intlify message format AST, skip it.
692
+ * because the AST node is not a key-value structure.
693
+ */
694
+ if (AST_NODE_PROPS_KEYS.includes(key) && isMessageAST(last)) {
695
+ return null;
696
+ }
697
+ const val = last[key];
678
698
  if (val === undefined) {
679
699
  return null;
680
700
  }
@@ -716,7 +736,7 @@ function getWarnMessage(code, ...args) {
716
736
  * Intlify core-base version
717
737
  * @internal
718
738
  */
719
- const VERSION = '10.0.6';
739
+ const VERSION = '10.0.8';
720
740
  const NOT_REOSLVED = -1;
721
741
  const DEFAULT_LOCALE = 'en-US';
722
742
  const MISSING_RESOLVE_VALUE = '';
@@ -1508,9 +1528,13 @@ function translate(context, ...args) {
1508
1528
  const msgContext = createMessageContext(ctxOptions);
1509
1529
  const messaged = evaluateMessage(context, msg, msgContext);
1510
1530
  // if use post translation option, proceed it with handler
1511
- const ret = postTranslation
1531
+ let ret = postTranslation
1512
1532
  ? postTranslation(messaged, key)
1513
1533
  : messaged;
1534
+ // apply HTML sanitization for security
1535
+ if (escapeParameter && shared.isString(ret)) {
1536
+ ret = shared.sanitizeTranslatedHtml(ret);
1537
+ }
1514
1538
  // NOTE: experimental !!
1515
1539
  {
1516
1540
  // prettier-ignore
@@ -1835,6 +1859,7 @@ function getMessageContextOptions(context, locale, message, options) {
1835
1859
 
1836
1860
  exports.CompileErrorCodes = messageCompiler.CompileErrorCodes;
1837
1861
  exports.createCompileError = messageCompiler.createCompileError;
1862
+ exports.AST_NODE_PROPS_KEYS = AST_NODE_PROPS_KEYS;
1838
1863
  exports.CORE_ERROR_CODES_EXTEND_POINT = CORE_ERROR_CODES_EXTEND_POINT;
1839
1864
  exports.CORE_WARN_CODES_EXTEND_POINT = CORE_WARN_CODES_EXTEND_POINT;
1840
1865
  exports.CoreErrorCodes = CoreErrorCodes;
@@ -13,6 +13,8 @@ declare type __ResourceFormatPath<T, Key extends keyof T> = Key extends string ?
13
13
 
14
14
  export declare type __ResourcePath<T, Key extends keyof T> = Key extends string ? T[Key] extends Record<string, any> ? `${Key}.${__ResourcePath<T[Key], Exclude<keyof T[Key], keyof any[]>> & string}` | `${Key}.${Exclude<keyof T[Key], keyof any[]> & string}` : never : never;
15
15
 
16
+ export declare const AST_NODE_PROPS_KEYS: string[];
17
+
16
18
  export declare function clearCompileCache(): void;
17
19
 
18
20
  /* Excluded from this release type: clearDateTimeFormat */
@@ -1190,7 +1192,16 @@ export declare interface TranslateOptions<Locales = Locale> extends LocaleOption
1190
1192
  fallbackWarn?: boolean;
1191
1193
  /**
1192
1194
  * @remarks
1193
- * Whether do escape parameter for list or named interpolation values
1195
+ * Whether to escape parameters for list or named interpolation values.
1196
+ * When enabled, this option:
1197
+ * - Escapes HTML special characters (`<`, `>`, `"`, `'`, `&`, `/`, `=`) in interpolation parameters
1198
+ * - Sanitizes the final translated HTML to prevent XSS attacks by:
1199
+ * - Escaping dangerous characters in HTML attribute values
1200
+ * - Neutralizing event handler attributes (onclick, onerror, etc.)
1201
+ * - Disabling javascript: URLs in href, src, action, formaction, and style attributes
1202
+ *
1203
+ * @defaultValue false
1204
+ * @see [HTML Message - Using the escapeParameter option](https://vue-i18n.intlify.dev/guide/essentials/syntax.html#using-the-escapeparameter-option)
1194
1205
  */
1195
1206
  escapeParameter?: boolean;
1196
1207
  /**
@@ -1,8 +1,25 @@
1
1
  /*!
2
- * core-base v10.0.6
2
+ * core-base v10.0.8
3
3
  * (c) 2025 kazuya kawaguchi
4
4
  * Released under the MIT License.
5
5
  */
6
+ function warn(msg, err) {
7
+ if (typeof console !== 'undefined') {
8
+ console.warn(`[intlify] ` + msg);
9
+ /* istanbul ignore if */
10
+ if (err) {
11
+ console.warn(err.stack);
12
+ }
13
+ }
14
+ }
15
+ const hasWarned = {};
16
+ function warnOnce(msg) {
17
+ if (!hasWarned[msg]) {
18
+ hasWarned[msg] = true;
19
+ warn(msg);
20
+ }
21
+ }
22
+
6
23
  /**
7
24
  * Original Utilities
8
25
  * written by kazuya kawaguchi
@@ -55,10 +72,49 @@ const _create = Object.create;
55
72
  const create = (obj = null) => _create(obj);
56
73
  function escapeHtml(rawText) {
57
74
  return rawText
75
+ .replace(/&/g, '&amp;') // escape `&` first to avoid double escaping
58
76
  .replace(/</g, '&lt;')
59
77
  .replace(/>/g, '&gt;')
60
78
  .replace(/"/g, '&quot;')
61
- .replace(/'/g, '&apos;');
79
+ .replace(/'/g, '&apos;')
80
+ .replace(/\//g, '&#x2F;') // escape `/` to prevent closing tags or JavaScript URLs
81
+ .replace(/=/g, '&#x3D;'); // escape `=` to prevent attribute injection
82
+ }
83
+ function escapeAttributeValue(value) {
84
+ return value
85
+ .replace(/&(?![a-zA-Z0-9#]{2,6};)/g, '&amp;') // escape unescaped `&`
86
+ .replace(/"/g, '&quot;')
87
+ .replace(/'/g, '&apos;')
88
+ .replace(/</g, '&lt;')
89
+ .replace(/>/g, '&gt;');
90
+ }
91
+ function sanitizeTranslatedHtml(html) {
92
+ // Escape dangerous characters in attribute values
93
+ // Process attributes with double quotes
94
+ html = html.replace(/(\w+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${escapeAttributeValue(attrValue)}"`);
95
+ // Process attributes with single quotes
96
+ html = html.replace(/(\w+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${escapeAttributeValue(attrValue)}'`);
97
+ // Detect and neutralize event handler attributes
98
+ const eventHandlerPattern = /\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi;
99
+ if (eventHandlerPattern.test(html)) {
100
+ {
101
+ warn('Potentially dangerous event handlers detected in translation. ' +
102
+ 'Consider removing onclick, onerror, etc. from your translation messages.');
103
+ }
104
+ // Neutralize event handler attributes by escaping 'on'
105
+ html = html.replace(/(\s+)(on)(\w+\s*=)/gi, '$1&#111;n$3');
106
+ }
107
+ // Disable javascript: URLs in various contexts
108
+ const javascriptUrlPattern = [
109
+ // In href, src, action, formaction attributes
110
+ /(\s+(?:href|src|action|formaction)\s*=\s*["']?)\s*javascript:/gi,
111
+ // In style attributes within url()
112
+ /(style\s*=\s*["'][^"']*url\s*\(\s*)javascript:/gi
113
+ ];
114
+ javascriptUrlPattern.forEach(pattern => {
115
+ html = html.replace(pattern, '$1javascript&#58;');
116
+ });
117
+ return html;
62
118
  }
63
119
  const hasOwnProperty = Object.prototype.hasOwnProperty;
64
120
  function hasOwn(obj, key) {
@@ -130,23 +186,6 @@ function generateCodeFrame(source, start = 0, end = source.length) {
130
186
  return res.join('\n');
131
187
  }
132
188
 
133
- function warn(msg, err) {
134
- if (typeof console !== 'undefined') {
135
- console.warn(`[intlify] ` + msg);
136
- /* istanbul ignore if */
137
- if (err) {
138
- console.warn(err.stack);
139
- }
140
- }
141
- }
142
- const hasWarned = {};
143
- function warnOnce(msg) {
144
- if (!hasWarned[msg]) {
145
- hasWarned[msg] = true;
146
- warn(msg);
147
- }
148
- }
149
-
150
189
  function createPosition(line, column, offset) {
151
190
  return { line, column, offset };
152
191
  }
@@ -1649,6 +1688,80 @@ function baseCompile$1(source, options = {}) {
1649
1688
  }
1650
1689
  }
1651
1690
 
1691
+ function isMessageAST(val) {
1692
+ return (isObject(val) &&
1693
+ resolveType(val) === 0 &&
1694
+ (hasOwn(val, 'b') || hasOwn(val, 'body')));
1695
+ }
1696
+ const PROPS_BODY = ['b', 'body'];
1697
+ function resolveBody(node) {
1698
+ return resolveProps(node, PROPS_BODY);
1699
+ }
1700
+ const PROPS_CASES = ['c', 'cases'];
1701
+ function resolveCases(node) {
1702
+ return resolveProps(node, PROPS_CASES, []);
1703
+ }
1704
+ const PROPS_STATIC = ['s', 'static'];
1705
+ function resolveStatic(node) {
1706
+ return resolveProps(node, PROPS_STATIC);
1707
+ }
1708
+ const PROPS_ITEMS = ['i', 'items'];
1709
+ function resolveItems(node) {
1710
+ return resolveProps(node, PROPS_ITEMS, []);
1711
+ }
1712
+ const PROPS_TYPE = ['t', 'type'];
1713
+ function resolveType(node) {
1714
+ return resolveProps(node, PROPS_TYPE);
1715
+ }
1716
+ const PROPS_VALUE = ['v', 'value'];
1717
+ function resolveValue$1(node, type) {
1718
+ const resolved = resolveProps(node, PROPS_VALUE);
1719
+ if (resolved != null) {
1720
+ return resolved;
1721
+ }
1722
+ else {
1723
+ throw createUnhandleNodeError(type);
1724
+ }
1725
+ }
1726
+ const PROPS_MODIFIER = ['m', 'modifier'];
1727
+ function resolveLinkedModifier(node) {
1728
+ return resolveProps(node, PROPS_MODIFIER);
1729
+ }
1730
+ const PROPS_KEY = ['k', 'key'];
1731
+ function resolveLinkedKey(node) {
1732
+ const resolved = resolveProps(node, PROPS_KEY);
1733
+ if (resolved) {
1734
+ return resolved;
1735
+ }
1736
+ else {
1737
+ throw createUnhandleNodeError(6 /* NodeTypes.Linked */);
1738
+ }
1739
+ }
1740
+ function resolveProps(node, props, defaultValue) {
1741
+ for (let i = 0; i < props.length; i++) {
1742
+ const prop = props[i];
1743
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1744
+ if (hasOwn(node, prop) && node[prop] != null) {
1745
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1746
+ return node[prop];
1747
+ }
1748
+ }
1749
+ return defaultValue;
1750
+ }
1751
+ const AST_NODE_PROPS_KEYS = [
1752
+ ...PROPS_BODY,
1753
+ ...PROPS_CASES,
1754
+ ...PROPS_STATIC,
1755
+ ...PROPS_ITEMS,
1756
+ ...PROPS_KEY,
1757
+ ...PROPS_MODIFIER,
1758
+ ...PROPS_VALUE,
1759
+ ...PROPS_TYPE
1760
+ ];
1761
+ function createUnhandleNodeError(type) {
1762
+ return new Error(`unhandled node type: ${type}`);
1763
+ }
1764
+
1652
1765
  function format(ast) {
1653
1766
  const msg = (ctx) => formatParts(ctx, ast);
1654
1767
  return msg;
@@ -1671,14 +1784,6 @@ function formatParts(ctx, ast) {
1671
1784
  return formatMessageParts(ctx, body);
1672
1785
  }
1673
1786
  }
1674
- const PROPS_BODY = ['b', 'body'];
1675
- function resolveBody(node) {
1676
- return resolveProps(node, PROPS_BODY);
1677
- }
1678
- const PROPS_CASES = ['c', 'cases'];
1679
- function resolveCases(node) {
1680
- return resolveProps(node, PROPS_CASES, []);
1681
- }
1682
1787
  function formatMessageParts(ctx, node) {
1683
1788
  const static_ = resolveStatic(node);
1684
1789
  if (static_ != null) {
@@ -1691,14 +1796,6 @@ function formatMessageParts(ctx, node) {
1691
1796
  return ctx.normalize(messages);
1692
1797
  }
1693
1798
  }
1694
- const PROPS_STATIC = ['s', 'static'];
1695
- function resolveStatic(node) {
1696
- return resolveProps(node, PROPS_STATIC);
1697
- }
1698
- const PROPS_ITEMS = ['i', 'items'];
1699
- function resolveItems(node) {
1700
- return resolveProps(node, PROPS_ITEMS, []);
1701
- }
1702
1799
  function formatMessagePart(ctx, node) {
1703
1800
  const type = resolveType(node);
1704
1801
  switch (type) {
@@ -1744,48 +1841,6 @@ function formatMessagePart(ctx, node) {
1744
1841
  throw new Error(`unhandled node on format message part: ${type}`);
1745
1842
  }
1746
1843
  }
1747
- const PROPS_TYPE = ['t', 'type'];
1748
- function resolveType(node) {
1749
- return resolveProps(node, PROPS_TYPE);
1750
- }
1751
- const PROPS_VALUE = ['v', 'value'];
1752
- function resolveValue$1(node, type) {
1753
- const resolved = resolveProps(node, PROPS_VALUE);
1754
- if (resolved) {
1755
- return resolved;
1756
- }
1757
- else {
1758
- throw createUnhandleNodeError(type);
1759
- }
1760
- }
1761
- const PROPS_MODIFIER = ['m', 'modifier'];
1762
- function resolveLinkedModifier(node) {
1763
- return resolveProps(node, PROPS_MODIFIER);
1764
- }
1765
- const PROPS_KEY = ['k', 'key'];
1766
- function resolveLinkedKey(node) {
1767
- const resolved = resolveProps(node, PROPS_KEY);
1768
- if (resolved) {
1769
- return resolved;
1770
- }
1771
- else {
1772
- throw createUnhandleNodeError(6 /* NodeTypes.Linked */);
1773
- }
1774
- }
1775
- function resolveProps(node, props, defaultValue) {
1776
- for (let i = 0; i < props.length; i++) {
1777
- const prop = props[i];
1778
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1779
- if (hasOwn(node, prop) && node[prop] != null) {
1780
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1781
- return node[prop];
1782
- }
1783
- }
1784
- return defaultValue;
1785
- }
1786
- function createUnhandleNodeError(type) {
1787
- return new Error(`unhandled node type: ${type}`);
1788
- }
1789
1844
 
1790
1845
  const WARN_MESSAGE = `Detected HTML in '{source}' message. Recommend not using HTML messages to avoid XSS.`;
1791
1846
  function checkHtmlMessage(source, warnHtmlMessage) {
@@ -1798,11 +1853,6 @@ let compileCache = create();
1798
1853
  function clearCompileCache() {
1799
1854
  compileCache = create();
1800
1855
  }
1801
- function isMessageAST(val) {
1802
- return (isObject(val) &&
1803
- resolveType(val) === 0 &&
1804
- (hasOwn(val, 'b') || hasOwn(val, 'body')));
1805
- }
1806
1856
  function baseCompile(message, options = {}) {
1807
1857
  // error detecting on compile
1808
1858
  let detectError = false;
@@ -2315,7 +2365,16 @@ function resolveValue(obj, path) {
2315
2365
  let last = obj;
2316
2366
  let i = 0;
2317
2367
  while (i < len) {
2318
- const val = last[hit[i]];
2368
+ const key = hit[i];
2369
+ /**
2370
+ * NOTE:
2371
+ * if `key` is intlify message format AST node key and `last` is intlify message format AST, skip it.
2372
+ * because the AST node is not a key-value structure.
2373
+ */
2374
+ if (AST_NODE_PROPS_KEYS.includes(key) && isMessageAST(last)) {
2375
+ return null;
2376
+ }
2377
+ const val = last[key];
2319
2378
  if (val === undefined) {
2320
2379
  return null;
2321
2380
  }
@@ -2357,7 +2416,7 @@ function getWarnMessage(code, ...args) {
2357
2416
  * Intlify core-base version
2358
2417
  * @internal
2359
2418
  */
2360
- const VERSION = '10.0.6';
2419
+ const VERSION = '10.0.8';
2361
2420
  const NOT_REOSLVED = -1;
2362
2421
  const DEFAULT_LOCALE = 'en-US';
2363
2422
  const MISSING_RESOLVE_VALUE = '';
@@ -3149,9 +3208,13 @@ function translate(context, ...args) {
3149
3208
  const msgContext = createMessageContext(ctxOptions);
3150
3209
  const messaged = evaluateMessage(context, msg, msgContext);
3151
3210
  // if use post translation option, proceed it with handler
3152
- const ret = postTranslation
3211
+ let ret = postTranslation
3153
3212
  ? postTranslation(messaged, key)
3154
3213
  : messaged;
3214
+ // apply HTML sanitization for security
3215
+ if (escapeParameter && isString(ret)) {
3216
+ ret = sanitizeTranslatedHtml(ret);
3217
+ }
3155
3218
  // NOTE: experimental !!
3156
3219
  {
3157
3220
  // prettier-ignore
@@ -3474,4 +3537,4 @@ function getMessageContextOptions(context, locale, message, options) {
3474
3537
  return ctxOptions;
3475
3538
  }
3476
3539
 
3477
- export { CORE_ERROR_CODES_EXTEND_POINT, CORE_WARN_CODES_EXTEND_POINT, CompileErrorCodes, CoreErrorCodes, CoreWarnCodes, DATETIME_FORMAT_OPTIONS_KEYS, DEFAULT_LOCALE, DEFAULT_MESSAGE_DATA_TYPE, MISSING_RESOLVE_VALUE, NOT_REOSLVED, NUMBER_FORMAT_OPTIONS_KEYS, VERSION, clearCompileCache, clearDateTimeFormat, clearNumberFormat, compile, createCompileError, createCoreContext, createCoreError, createMessageContext, datetime, fallbackWithLocaleChain, fallbackWithSimple, getAdditionalMeta, getDevToolsHook, getFallbackContext, getLocale, getWarnMessage, handleMissing, initI18nDevTools, isAlmostSameLocale, isImplicitFallback, isMessageAST, isMessageFunction, isTranslateFallbackWarn, isTranslateMissingWarn, number, parse, parseDateTimeArgs, parseNumberArgs, parseTranslateArgs, registerLocaleFallbacker, registerMessageCompiler, registerMessageResolver, resolveLocale, resolveValue, resolveWithKeyValue, setAdditionalMeta, setDevToolsHook, setFallbackContext, translate, translateDevTools, updateFallbackLocale };
3540
+ export { AST_NODE_PROPS_KEYS, CORE_ERROR_CODES_EXTEND_POINT, CORE_WARN_CODES_EXTEND_POINT, CompileErrorCodes, CoreErrorCodes, CoreWarnCodes, DATETIME_FORMAT_OPTIONS_KEYS, DEFAULT_LOCALE, DEFAULT_MESSAGE_DATA_TYPE, MISSING_RESOLVE_VALUE, NOT_REOSLVED, NUMBER_FORMAT_OPTIONS_KEYS, VERSION, clearCompileCache, clearDateTimeFormat, clearNumberFormat, compile, createCompileError, createCoreContext, createCoreError, createMessageContext, datetime, fallbackWithLocaleChain, fallbackWithSimple, getAdditionalMeta, getDevToolsHook, getFallbackContext, getLocale, getWarnMessage, handleMissing, initI18nDevTools, isAlmostSameLocale, isImplicitFallback, isMessageAST, isMessageFunction, isTranslateFallbackWarn, isTranslateMissingWarn, number, parse, parseDateTimeArgs, parseNumberArgs, parseTranslateArgs, registerLocaleFallbacker, registerMessageCompiler, registerMessageResolver, resolveLocale, resolveValue, resolveWithKeyValue, setAdditionalMeta, setDevToolsHook, setFallbackContext, translate, translateDevTools, updateFallbackLocale };