@atlassian/i18n-properties-loader 1.1.7 → 2.0.1-8db0611

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/CHANGELOG.md CHANGED
@@ -3,7 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## <small>1.1.7 (2026-04-09)</small>
6
+ ## [2.0.1](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@2.0.1..@atlassian/i18n-properties-loader@2.0.0) (2026-05-12)
7
+
8
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
9
+
10
+
11
+
12
+
13
+
14
+ ## [2.0.0](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@2.0.0..@atlassian/i18n-properties-loader@1.1.7) (2026-04-29)
15
+
16
+
17
+ ### ⚠ BREAKING CHANGES
18
+
19
+ * drop webpack 4 support
20
+
21
+ ### [1.1.7](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.1.7..@atlassian/i18n-properties-loader@1.1.6) (2026-04-09)
7
22
 
8
23
  * [Renovate] Update frontend - webpack ([b693f8c](https://bitbucket.org/atlassianlabs/fe-server/commits/b693f8c))
9
24
 
@@ -11,7 +26,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
11
26
 
12
27
 
13
28
 
14
- ## <small>1.1.6 (2026-02-23)</small>
29
+ ### [1.1.6](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.1.6..@atlassian/i18n-properties-loader@1.1.5) (2026-02-23)
15
30
 
16
31
  **Note:** Version bump only for package @atlassian/i18n-properties-loader
17
32
 
@@ -19,7 +34,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
19
34
 
20
35
 
21
36
 
22
- ## <small>1.1.5 (2026-02-21)</small>
37
+ ### [1.1.5](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.1.5..@atlassian/i18n-properties-loader@1.1.4) (2026-02-21)
23
38
 
24
39
  **Note:** Version bump only for package @atlassian/i18n-properties-loader
25
40
 
@@ -27,7 +42,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
27
42
 
28
43
 
29
44
 
30
- ## <small>1.1.4 (2026-02-20)</small>
45
+ ### [1.1.4](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.1.4..@atlassian/i18n-properties-loader@1.1.3) (2026-02-20)
31
46
 
32
47
  **Note:** Version bump only for package @atlassian/i18n-properties-loader
33
48
 
package/README.md CHANGED
@@ -123,5 +123,10 @@ You can check the package description for more details and learn how to integrat
123
123
 
124
124
  This plugin is compatible with:
125
125
 
126
- - webpack 4.0+ and 5.0+
126
+ - webpack 5.0+
127
127
  - Node 12+
128
+
129
+ > **Note:** Starting with version `2.0.0`, support for webpack 4 has been dropped. If you still need to use webpack 4,
130
+ > please install version `1.0.9` of this package, which is the last version where webpack 4 was tested. Versions
131
+ > `1.0.10` and later (including all `1.1.x` releases) silently removed webpack 4 tests and are not guaranteed to work
132
+ > with webpack 4.
package/index.js CHANGED
@@ -97,6 +97,29 @@ const clearCacheWhenIdle = debounce(() => {
97
97
  i18nCache = new Map();
98
98
  }, accessThreshold);
99
99
 
100
+ // Returns the quote character (' or ") enclosing `offset` in `source`, or null if not in a string literal.
101
+ function getEnclosingStringQuote(source, offset) {
102
+ let openQuote = null; // currently open string delimiter, or null
103
+ let escaped = false;
104
+ for (let i = 0; i < offset; i++) {
105
+ const ch = source[i];
106
+ if (escaped) {
107
+ escaped = false;
108
+ } else if (ch === '\\') {
109
+ escaped = true;
110
+ } else if (openQuote) {
111
+ if (ch === openQuote) openQuote = null;
112
+ } else if (ch === "'" || ch === '"') {
113
+ openQuote = ch;
114
+ }
115
+ }
116
+ return openQuote;
117
+ }
118
+
119
+ function escapeForStringLiteral(value, quote) {
120
+ return value.split(quote).join('\\' + quote);
121
+ }
122
+
100
123
  function processI18nFiles(i18nFiles) {
101
124
  clearCacheWhenIdle();
102
125
 
@@ -152,8 +175,18 @@ module.exports = function (source, map) {
152
175
 
153
176
  // Replace "I18n.getText('some.translation.key', [param1], [paramN])" with the real translation string
154
177
  const properties = processI18nFiles(i18nFiles);
155
- const newSource = source.replace(i18nRegExp, (...args) => {
156
- const { namespace, key, endParam } = args.pop();
178
+ const newSource = source.replace(i18nRegExp, (match, ...args) => {
179
+ // replace() callback: (match, ...captures, offset, source, groups)
180
+ const groups = args[args.length - 1];
181
+ const matchSource = args[args.length - 2];
182
+ const offset = args[args.length - 3];
183
+
184
+ // Escape substitutions inside string literals (e.g. babel-plugin-istanbul's
185
+ // embedded inputSourceMap.sourcesContent) to avoid breaking the surrounding
186
+ // literal with unescaped quotes from JSON.stringify(message). See: DCA11Y-3344
187
+ const enclosingQuote = getEnclosingStringQuote(matchSource, offset);
188
+
189
+ const { namespace, key, endParam } = groups;
157
190
  const escapedKey = key.replace(/\s/g, '\\ ');
158
191
 
159
192
  let message = properties.get(escapedKey);
@@ -171,12 +204,10 @@ module.exports = function (source, map) {
171
204
  // Output string
172
205
  const escapedMessage = JSON.stringify(message);
173
206
 
174
- if (endParam === ',') {
175
- // We don't need to unquote the string since the WRM.format function has all the logic to do that
176
- return `${formatFunctionCall}(${escapedMessage},`;
177
- }
207
+ // For endParam === ',' we don't unquote — WRM.format handles unquoting
208
+ const result = endParam === ',' ? `${formatFunctionCall}(${escapedMessage},` : unquoteMessage(escapedMessage);
178
209
 
179
- return unquoteMessage(escapedMessage);
210
+ return enclosingQuote ? escapeForStringLiteral(result, enclosingQuote) : result;
180
211
  });
181
212
 
182
213
  callback(null, newSource, map);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlassian/i18n-properties-loader",
3
- "version": "1.1.7",
3
+ "version": "2.0.1-8db0611",
4
4
  "description": "A webpack loader for i18n *.properties files that can be used in Atlassian Server products",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -46,12 +46,12 @@
46
46
  "webpack": "^5.0.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@atlassian/webresource-webpack-plugin": "^7.1.7",
49
+ "@atlassian/webresource-webpack-plugin": "^7.1.8",
50
50
  "jest": "30.2.0",
51
- "webpack": "5.105.2"
51
+ "webpack": "5.105.4"
52
52
  },
53
53
  "engines": {
54
54
  "node": ">=12"
55
55
  },
56
- "gitHead": "7d591c8de01b67345c2632277440b43788089d9c"
56
+ "gitHead": "ddd662a8e9aa2d54c2c3bc086f1a32874e325594"
57
57
  }