webpack-easyi18n 0.5.0 → 0.5.2
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/package.json +1 -1
- package/src/index.js +73 -2
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -39,6 +39,73 @@ class EasyI18nPlugin {
|
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Decode (a small subset of) JavaScript-style escape sequences from *bundle text* into
|
|
44
|
+
* their real runtime characters.
|
|
45
|
+
*
|
|
46
|
+
* Why this exists:
|
|
47
|
+
* - When targeting older environments, Babel/minifiers sometimes emit non-ASCII
|
|
48
|
+
* characters using unicode escapes, e.g. "don\u2019t" instead of "don’t".
|
|
49
|
+
* - If we then call escapeNuggets(), it will escape backslashes, turning "\u2019" into
|
|
50
|
+
* "\\u2019".
|
|
51
|
+
* - In the final JS bundle, "\\u2019" is *not* a unicode escape anymore; it becomes a
|
|
52
|
+
* literal backslash-u sequence and the browser renders "don\u2019t".
|
|
53
|
+
*
|
|
54
|
+
* Example:
|
|
55
|
+
* - Bundle text contains: "don\u2019t"
|
|
56
|
+
* - Without decode: escapeNuggets => "don\\u2019t" (renders as don\u2019t)
|
|
57
|
+
* - With decode first: unescapeJsLike => "don’t"; then escapeNuggets keeps it as don’t
|
|
58
|
+
*
|
|
59
|
+
* Notes:
|
|
60
|
+
* - This intentionally decodes only "\uXXXX" and "\xXX" sequences.
|
|
61
|
+
* - It avoids decoding when the backslash itself is escaped (e.g. "\\u2019"), because
|
|
62
|
+
* that usually means the author intended a literal "\u2019" to be displayed.
|
|
63
|
+
*/
|
|
64
|
+
const unescapeJsLike = (value) => {
|
|
65
|
+
if (typeof value !== 'string') return value;
|
|
66
|
+
|
|
67
|
+
const isHex = (c) => (c >= '0' && c <= '9')
|
|
68
|
+
|| (c >= 'a' && c <= 'f')
|
|
69
|
+
|| (c >= 'A' && c <= 'F');
|
|
70
|
+
|
|
71
|
+
let out = '';
|
|
72
|
+
for (let i = 0; i < value.length; i++) {
|
|
73
|
+
const ch = value[i];
|
|
74
|
+
if (ch !== '\\') {
|
|
75
|
+
out += ch;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// If we have an escaped backslash ("\\u...." in text), do not decode.
|
|
80
|
+
if (i > 0 && value[i - 1] === '\\') {
|
|
81
|
+
out += ch;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const next = value[i + 1];
|
|
86
|
+
if (next === 'u') {
|
|
87
|
+
const a = value[i + 2], b = value[i + 3], c = value[i + 4], d = value[i + 5];
|
|
88
|
+
if (isHex(a) && isHex(b) && isHex(c) && isHex(d)) {
|
|
89
|
+
out += String.fromCharCode(parseInt(`${a}${b}${c}${d}`, 16));
|
|
90
|
+
i += 5;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
} else if (next === 'x') {
|
|
94
|
+
const a = value[i + 2], b = value[i + 3];
|
|
95
|
+
if (isHex(a) && isHex(b)) {
|
|
96
|
+
out += String.fromCharCode(parseInt(`${a}${b}`, 16));
|
|
97
|
+
i += 3;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Not a recognized escape; keep the backslash.
|
|
103
|
+
out += ch;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return out;
|
|
107
|
+
};
|
|
108
|
+
|
|
42
109
|
compiler.hooks.thisCompilation.tap('EasyI18nPlugin', (compilation) => {
|
|
43
110
|
compilation.hooks.processAssets.tapPromise(
|
|
44
111
|
{
|
|
@@ -100,10 +167,14 @@ class EasyI18nPlugin {
|
|
|
100
167
|
}
|
|
101
168
|
} else {
|
|
102
169
|
// .po files use \n notation for line breaks
|
|
103
|
-
const
|
|
170
|
+
const translationKeyRaw = nuggetSyntaxRemoved.replace(/\r\n/g, '\n');
|
|
171
|
+
const translationKey = unescapeJsLike(translationKeyRaw);
|
|
104
172
|
|
|
105
173
|
// find this nugget in the locale's array of translations
|
|
106
174
|
replacement = translationLookup[translationKey];
|
|
175
|
+
if (typeof (replacement) === "undefined") {
|
|
176
|
+
replacement = translationLookup[translationKeyRaw];
|
|
177
|
+
}
|
|
107
178
|
if (typeof (replacement) === "undefined" || replacement === "") {
|
|
108
179
|
if (this.options.warnOnMissingTranslations) {
|
|
109
180
|
compilation.warnings.push(
|
|
@@ -119,7 +190,7 @@ class EasyI18nPlugin {
|
|
|
119
190
|
}
|
|
120
191
|
|
|
121
192
|
// Escape the translated text BEFORE formatting/splicing
|
|
122
|
-
replacement = EasyI18nPlugin.escapeNuggets(replacement);
|
|
193
|
+
replacement = EasyI18nPlugin.escapeNuggets(unescapeJsLike(replacement));
|
|
123
194
|
|
|
124
195
|
// format nuggets
|
|
125
196
|
var formatItemsMatch = originalText.match(/\|\|\|(.+?)(?:\/\/\/.+?)?\]\]\]/s)
|