@chaoswise/intl 2.1.9 → 3.0.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/bin/scripts/addLocale.js
CHANGED
|
@@ -5,11 +5,16 @@ const getWordsByIds = require('./util/getWordsByIds');
|
|
|
5
5
|
const log = require('./util/log');
|
|
6
6
|
const genXlsx = require('./util/genXlsx');
|
|
7
7
|
const service = require('./service');
|
|
8
|
+
const file = require('./util/file');
|
|
9
|
+
const getGroupName = require('./util/getGroupName');
|
|
10
|
+
const getPkgJson = require('./util/getPkgJson');
|
|
8
11
|
|
|
9
12
|
async function update() {
|
|
10
13
|
log.info('收集全部词条...');
|
|
11
14
|
const conf = getConf();
|
|
12
15
|
const files = targetOutputFiles(conf);
|
|
16
|
+
const newWordsFileType = conf.newWordsFileType || 'excel';
|
|
17
|
+
const isJson = newWordsFileType === 'json';
|
|
13
18
|
|
|
14
19
|
const info = transformAst('update', files, conf, {});
|
|
15
20
|
const _downloadIds = [...new Set(info.downloadIds.filter(Boolean))];
|
|
@@ -26,7 +31,9 @@ async function update() {
|
|
|
26
31
|
const mainLanguage = languages.filter((l) => l.isMain)[0];
|
|
27
32
|
|
|
28
33
|
const localeKeys = Object.keys(allWords);
|
|
29
|
-
|
|
34
|
+
|
|
35
|
+
// 构建词条数据的通用函数
|
|
36
|
+
const buildLocaleObj = (id) => {
|
|
30
37
|
const localeObj = {};
|
|
31
38
|
localeKeys.forEach((key) => {
|
|
32
39
|
if (mainLanguage && key === mainLanguage.key) {
|
|
@@ -36,13 +43,30 @@ async function update() {
|
|
|
36
43
|
localeObj[key] = allWords[key][id] || '待翻译';
|
|
37
44
|
}
|
|
38
45
|
});
|
|
39
|
-
return
|
|
46
|
+
return localeObj;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
if (isJson) {
|
|
50
|
+
// 生成 JSON 格式
|
|
51
|
+
const jsonData = {};
|
|
52
|
+
_downloadIds.forEach((id) => {
|
|
53
|
+
jsonData[id] = buildLocaleObj(id);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const groupName = getGroupName();
|
|
57
|
+
const package = getPkgJson();
|
|
58
|
+
const fileName = `${groupName}_${package.version}.json`;
|
|
59
|
+
file.write(fileName, JSON.stringify(jsonData, null, 2));
|
|
60
|
+
log.info(`全部词条请查看: ${fileName}中`);
|
|
61
|
+
} else {
|
|
62
|
+
// 生成 Excel 格式
|
|
63
|
+
const xlsxData = _downloadIds.map((id) => ({
|
|
40
64
|
id,
|
|
41
|
-
...
|
|
42
|
-
};
|
|
43
|
-
});
|
|
65
|
+
...buildLocaleObj(id),
|
|
66
|
+
}));
|
|
44
67
|
|
|
45
|
-
|
|
68
|
+
await genXlsx(xlsxData);
|
|
69
|
+
}
|
|
46
70
|
}
|
|
47
71
|
|
|
48
72
|
module.exports = update;
|
|
@@ -159,19 +159,27 @@ module.exports = function (
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
// XXX: [TRICKY] 防止中文转码为 unicode
|
|
162
|
+
// 注意:recast 打印 StringLiteral 时直接使用 node.value,而不是 extra.raw
|
|
163
|
+
// 所以需要直接创建值为 id 的字符串节点,同时保留原始中文在 extra 中
|
|
162
164
|
function hackValue(value, id) {
|
|
163
|
-
|
|
165
|
+
// 如果 id 未定义,使用 value 作为回退(用于第一次收集阶段)
|
|
166
|
+
const actualId = id || value;
|
|
167
|
+
if (actualId) hacked[actualId] = true;
|
|
164
168
|
|
|
165
169
|
// 字符串默认是单引号,如果模板字符串中出现单引号,需要转义,把 ' 换成 \'
|
|
166
170
|
// 就算用户自定配置字符串为双引号,也没事,默认会转义双引号,但是默认不会处理单引号,所以自己手动处理
|
|
167
|
-
|
|
168
|
-
|
|
171
|
+
let rawValue = actualId;
|
|
172
|
+
if (/\'/.test(actualId)) {
|
|
173
|
+
rawValue = actualId.replace(/\'/g, "\\'");
|
|
169
174
|
}
|
|
170
175
|
|
|
171
|
-
|
|
176
|
+
// 直接创建值为 actualId 的字符串节点,recast 会使用 node.value 作为输出
|
|
177
|
+
return Object.assign(t.StringLiteral(actualId), {
|
|
172
178
|
extra: {
|
|
173
|
-
raw: `'${
|
|
174
|
-
rawValue:
|
|
179
|
+
raw: `'${rawValue}'`,
|
|
180
|
+
rawValue: actualId,
|
|
181
|
+
// 保存原始中文,用于后续需要时使用
|
|
182
|
+
originalValue: value,
|
|
175
183
|
},
|
|
176
184
|
});
|
|
177
185
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
2
|
const path = require("path");
|
|
3
|
-
const
|
|
3
|
+
const recast = require("recast");
|
|
4
4
|
const babel = require("@babel/core");
|
|
5
|
-
const generate = require("@babel/generator").default;
|
|
6
5
|
const traverse = require("@babel/traverse").default;
|
|
7
6
|
const pluginSyntaxJSX = require("@babel/plugin-syntax-jsx");
|
|
8
7
|
const pluginSyntaxProposalOptionalChaining = require("@babel/plugin-proposal-optional-chaining");
|
|
@@ -23,7 +22,9 @@ const log = require("./log");
|
|
|
23
22
|
// 获取文件中需要忽略转化通用国际化API规范的所有行号
|
|
24
23
|
function getIgnoreLines(ast) {
|
|
25
24
|
const ignoreBlocks = [];
|
|
26
|
-
|
|
25
|
+
|
|
26
|
+
// 收集注释的辅助函数
|
|
27
|
+
function processComment(comment) {
|
|
27
28
|
const { type, value, loc } = comment;
|
|
28
29
|
const last = ignoreBlocks.length - 1;
|
|
29
30
|
|
|
@@ -50,9 +51,25 @@ function getIgnoreLines(ast) {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
// 从 ast.comments 获取注释(Babel 格式)
|
|
55
|
+
if (ast.comments && Array.isArray(ast.comments)) {
|
|
56
|
+
for (const comment of ast.comments) {
|
|
57
|
+
processComment(comment);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 从 ast.tokens 获取注释(recast 格式)
|
|
62
|
+
if (ast.tokens && Array.isArray(ast.tokens)) {
|
|
63
|
+
for (const token of ast.tokens) {
|
|
64
|
+
if (token.type === "CommentLine" || token.type === "CommentBlock") {
|
|
65
|
+
processComment(token);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
53
70
|
// 如果缺少 disable-enable,直接作用到最后一行
|
|
54
71
|
const len = ignoreBlocks.length;
|
|
55
|
-
if (len > 0 && !ignoreBlocks[len - 1].end) {
|
|
72
|
+
if (len > 0 && !ignoreBlocks[len - 1].end && ast.loc && ast.loc.end) {
|
|
56
73
|
ignoreBlocks[len - 1].end = ast.loc.end.line;
|
|
57
74
|
}
|
|
58
75
|
|
|
@@ -89,6 +106,7 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
89
106
|
sourceType: "module",
|
|
90
107
|
ast: true,
|
|
91
108
|
configFile: false,
|
|
109
|
+
parserOpts: { tokens: true },
|
|
92
110
|
presets: [
|
|
93
111
|
...babelPresets,
|
|
94
112
|
[presetTypescript, { isTSX: true, allExtensions: true }],
|
|
@@ -116,14 +134,14 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
116
134
|
specialFileReg.some((item) => {
|
|
117
135
|
if (typeof item === "string") {
|
|
118
136
|
return item === filePath;
|
|
119
|
-
} else {
|
|
137
|
+
} else if (item instanceof RegExp) {
|
|
120
138
|
return item.test(filePath);
|
|
121
139
|
}
|
|
140
|
+
return false;
|
|
122
141
|
})
|
|
123
142
|
) {
|
|
124
143
|
file.special = true;
|
|
125
144
|
}
|
|
126
|
-
const isTSX = [".ts", ".tsx"].includes(path.extname(filePath));
|
|
127
145
|
|
|
128
146
|
const r = {
|
|
129
147
|
allWords,
|
|
@@ -137,8 +155,17 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
137
155
|
const sourceCode = fs.readFileSync(filePath, "utf8");
|
|
138
156
|
|
|
139
157
|
let ast;
|
|
158
|
+
let recastAst;
|
|
140
159
|
try {
|
|
141
|
-
|
|
160
|
+
// 使用 recast 解析,内部委托给 babel,保留原始格式信息
|
|
161
|
+
recastAst = recast.parse(sourceCode, {
|
|
162
|
+
parser: {
|
|
163
|
+
parse(source) {
|
|
164
|
+
return babel.parseSync(source, transformOptions);
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
ast = recastAst.program;
|
|
142
169
|
} catch (error) {
|
|
143
170
|
replaceWords &&
|
|
144
171
|
log.error(`文件解析出错:${file.filePath}
|
|
@@ -146,7 +173,7 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
146
173
|
return;
|
|
147
174
|
}
|
|
148
175
|
|
|
149
|
-
opts.ignoreLines = getIgnoreLines(
|
|
176
|
+
opts.ignoreLines = getIgnoreLines(recastAst);
|
|
150
177
|
|
|
151
178
|
let makeVisitor = makeVisitorCollect;
|
|
152
179
|
if (type === "update") {
|
|
@@ -155,7 +182,7 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
155
182
|
|
|
156
183
|
try {
|
|
157
184
|
const visitor = makeVisitor(opts, r, file);
|
|
158
|
-
traverse(
|
|
185
|
+
traverse(recastAst, visitor);
|
|
159
186
|
} catch (e) {
|
|
160
187
|
replaceWords &&
|
|
161
188
|
log.error(`文件解析出错:${file.filePath}
|
|
@@ -167,11 +194,8 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
167
194
|
// 在只需要提取中文词条的情况下不传入replaceWords
|
|
168
195
|
if (!replaceWords) return;
|
|
169
196
|
|
|
170
|
-
//
|
|
171
|
-
let
|
|
172
|
-
retainLines: true,
|
|
173
|
-
decoratorsBeforeExport: true,
|
|
174
|
-
});
|
|
197
|
+
// 使用 recast 输出代码,仅重新打印被修改的 AST 节点,保留原始格式
|
|
198
|
+
let code = recast.print(recastAst).code;
|
|
175
199
|
|
|
176
200
|
if (!r.hasTouch) {
|
|
177
201
|
code = sourceCode;
|
|
@@ -184,13 +208,7 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
184
208
|
code = `${importCode}\n${code}`;
|
|
185
209
|
}
|
|
186
210
|
|
|
187
|
-
// 自定义格式化代码
|
|
188
211
|
if (r.hasTouch) {
|
|
189
|
-
if (conf.prettier) {
|
|
190
|
-
const parser = isTSX ? "typescript" : "babel";
|
|
191
|
-
code = prettier.format(code, { ...conf.prettier, parser });
|
|
192
|
-
}
|
|
193
|
-
|
|
194
212
|
const target = file.currentOutput
|
|
195
213
|
? filePath.replace(file.currentEntry, file.currentOutput)
|
|
196
214
|
: filePath;
|
|
@@ -24,8 +24,7 @@ var _cookie = _interopRequireDefault(require("cookie"));
|
|
|
24
24
|
var _invariant = _interopRequireDefault(require("invariant"));
|
|
25
25
|
var constants = _interopRequireWildcard(require("./constants"));
|
|
26
26
|
var _lodash = _interopRequireDefault(require("lodash.merge"));
|
|
27
|
-
function
|
|
28
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = _Object$defineProperty && _Object$getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? _Object$getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? _Object$defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
|
|
27
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof _WeakMap) var r = new _WeakMap(), n = new _WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = _Object$defineProperty) && _Object$getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
29
28
|
String.prototype.defaultMessage = String.prototype.d = function (msg) {
|
|
30
29
|
return this || msg || "";
|
|
31
30
|
};
|
|
@@ -14,7 +14,7 @@ _Object$defineProperty(exports, "ReactIntlUniversal", {
|
|
|
14
14
|
exports.load = exports.init = exports.getLocaleFromURL = exports.getLocaleFromLocalStorage = exports.getLocaleFromCookie = exports.getLocaleFromBrowser = exports.getInitOptions = exports.getHTML = exports.getDescendantProp = exports.get = exports.formatMessage = exports.formatHTMLMessage = exports.determineLocale = exports["default"] = void 0;
|
|
15
15
|
var _bind = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/bind"));
|
|
16
16
|
var _ReactIntlUniversal = _interopRequireDefault(require("./ReactIntlUniversal"));
|
|
17
|
-
var _context, _context2, _context3, _context4, _context5, _context6, _context7, _context8, _context9,
|
|
17
|
+
var _context, _context2, _context3, _context4, _context5, _context6, _context7, _context8, _context9, _context0, _context1, _context10, _context11;
|
|
18
18
|
var defaultInstance = exports["default"] = new _ReactIntlUniversal["default"]();
|
|
19
19
|
// resolved by CommonJS module loader
|
|
20
20
|
defaultInstance.ReactIntlUniversal = _ReactIntlUniversal["default"];
|
|
@@ -28,8 +28,8 @@ var init = exports.init = (0, _bind["default"])(_context6 = defaultInstance.init
|
|
|
28
28
|
var getInitOptions = exports.getInitOptions = (0, _bind["default"])(_context7 = defaultInstance.getInitOptions).call(_context7, defaultInstance);
|
|
29
29
|
var load = exports.load = (0, _bind["default"])(_context8 = defaultInstance.load).call(_context8, defaultInstance);
|
|
30
30
|
var getLocaleFromCookie = exports.getLocaleFromCookie = (0, _bind["default"])(_context9 = defaultInstance.getLocaleFromCookie).call(_context9, defaultInstance);
|
|
31
|
-
var getLocaleFromLocalStorage = exports.getLocaleFromLocalStorage = (0, _bind["default"])(
|
|
32
|
-
var getLocaleFromURL = exports.getLocaleFromURL = (0, _bind["default"])(
|
|
33
|
-
var getDescendantProp = exports.getDescendantProp = (0, _bind["default"])(
|
|
34
|
-
var getLocaleFromBrowser = exports.getLocaleFromBrowser = (0, _bind["default"])(
|
|
31
|
+
var getLocaleFromLocalStorage = exports.getLocaleFromLocalStorage = (0, _bind["default"])(_context0 = defaultInstance.getLocaleFromLocalStorage).call(_context0, defaultInstance);
|
|
32
|
+
var getLocaleFromURL = exports.getLocaleFromURL = (0, _bind["default"])(_context1 = defaultInstance.getLocaleFromURL).call(_context1, defaultInstance);
|
|
33
|
+
var getDescendantProp = exports.getDescendantProp = (0, _bind["default"])(_context10 = defaultInstance.getDescendantProp).call(_context10, defaultInstance);
|
|
34
|
+
var getLocaleFromBrowser = exports.getLocaleFromBrowser = (0, _bind["default"])(_context11 = defaultInstance.getLocaleFromBrowser).call(_context11, defaultInstance);
|
|
35
35
|
// resolved by ECMAScript module loader
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chaoswise/intl",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"author": "cloudwiser",
|
|
5
5
|
"description": "intl",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
"object-keys": "^1.0.11",
|
|
78
78
|
"prettier": "^2.8.1",
|
|
79
79
|
"react-intl-universal": "^2.6.11",
|
|
80
|
+
"recast": "^0.23.11",
|
|
80
81
|
"uuid": "^9.0.0",
|
|
81
82
|
"xlsx": "^0.18.5"
|
|
82
83
|
},
|
|
@@ -89,6 +90,5 @@
|
|
|
89
90
|
"react": "^16.13.1",
|
|
90
91
|
"react-dom": "^16.13.1"
|
|
91
92
|
},
|
|
92
|
-
"license": "MIT"
|
|
93
|
-
"gitHead": "ec323ae8b78cc39ac089839b300f6789272ef6ae"
|
|
93
|
+
"license": "MIT"
|
|
94
94
|
}
|