webpack-easyi18n 0.4.0 → 0.5.1
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 +72 -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,7 +167,7 @@ class EasyI18nPlugin {
|
|
|
100
167
|
}
|
|
101
168
|
} else {
|
|
102
169
|
// .po files use \n notation for line breaks
|
|
103
|
-
const translationKey = nuggetSyntaxRemoved.replace(
|
|
170
|
+
const translationKey = nuggetSyntaxRemoved.replace(/\r\n/g, '\n');
|
|
104
171
|
|
|
105
172
|
// find this nugget in the locale's array of translations
|
|
106
173
|
replacement = translationLookup[translationKey];
|
|
@@ -118,6 +185,9 @@ class EasyI18nPlugin {
|
|
|
118
185
|
}
|
|
119
186
|
}
|
|
120
187
|
|
|
188
|
+
// Escape the translated text BEFORE formatting/splicing
|
|
189
|
+
replacement = EasyI18nPlugin.escapeNuggets(unescapeJsLike(replacement));
|
|
190
|
+
|
|
121
191
|
// format nuggets
|
|
122
192
|
var formatItemsMatch = originalText.match(/\|\|\|(.+?)(?:\/\/\/.+?)?\]\]\]/s)
|
|
123
193
|
if (formatItemsMatch) {
|
|
@@ -134,7 +204,7 @@ class EasyI18nPlugin {
|
|
|
134
204
|
});
|
|
135
205
|
}
|
|
136
206
|
|
|
137
|
-
return
|
|
207
|
+
return replacement;
|
|
138
208
|
});
|
|
139
209
|
|
|
140
210
|
compilation.updateAsset(filename, new SourceMapSource(
|