xshell 0.0.18 → 0.0.23

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.
Files changed (49) hide show
  1. package/file.js +1 -2
  2. package/file.js.map +1 -1
  3. package/i18n/README.md +275 -0
  4. package/i18n/dict.d.ts +30 -0
  5. package/i18n/dict.js +34 -0
  6. package/i18n/dict.js.map +1 -0
  7. package/i18n/i18n-scan.d.ts +2 -0
  8. package/i18n/i18n-scan.js +21 -0
  9. package/i18n/i18n-scan.js.map +1 -0
  10. package/i18n/i18n.ico +0 -0
  11. package/i18n/index.d.ts +65 -0
  12. package/i18n/index.js +118 -0
  13. package/i18n/index.js.map +1 -0
  14. package/i18n/rwdict.d.ts +42 -0
  15. package/i18n/rwdict.js +110 -0
  16. package/i18n/rwdict.js.map +1 -0
  17. package/i18n/scanner/checker.d.ts +5 -0
  18. package/i18n/scanner/checker.js +73 -0
  19. package/i18n/scanner/checker.js.map +1 -0
  20. package/i18n/scanner/index.d.ts +52 -0
  21. package/i18n/scanner/index.js +319 -0
  22. package/i18n/scanner/index.js.map +1 -0
  23. package/i18n/scanner/parser.d.ts +3 -0
  24. package/i18n/scanner/parser.js +154 -0
  25. package/i18n/scanner/parser.js.map +1 -0
  26. package/i18n/utils.d.ts +1 -0
  27. package/i18n/utils.js +14 -0
  28. package/i18n/utils.js.map +1 -0
  29. package/myfont.sass +3 -0
  30. package/net.d.ts +4 -4
  31. package/net.js +18 -20
  32. package/net.js.map +1 -1
  33. package/package.json +38 -11
  34. package/process.d.ts +4 -4
  35. package/process.js +4 -4
  36. package/process.js.map +1 -1
  37. package/prototype.browser.js +25 -24
  38. package/prototype.browser.js.map +1 -1
  39. package/prototype.js +27 -26
  40. package/prototype.js.map +1 -1
  41. package/repl.d.ts +1 -2
  42. package/repl.js +4 -8
  43. package/repl.js.map +1 -1
  44. package/server.d.ts +2 -3
  45. package/server.js +12 -13
  46. package/server.js.map +1 -1
  47. package/tsconfig.json +1 -1
  48. package/ufs.js +3 -3
  49. package/ufs.js.map +1 -1
package/i18n/index.js ADDED
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.I18N = exports.LANGUAGES = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const qs_1 = (0, tslib_1.__importDefault)(require("qs"));
6
+ const js_cookie_1 = (0, tslib_1.__importDefault)(require("js-cookie"));
7
+ const i18next_1 = (0, tslib_1.__importDefault)(require("i18next"));
8
+ const dict_1 = require("./dict");
9
+ exports.LANGUAGES = ['zh', 'en', 'ja', 'ko'];
10
+ /**
11
+ 提供翻译文本功能,在浏览器环境下自动解析当前语言、国际/国内用户
12
+ @see https://github.com/ShenHongFei/xshell/tree/master/i18n
13
+ */
14
+ class I18N {
15
+ /** ```ts
16
+ import dict from './dict.json' // { "添加": { "en": "Add", "ja": "追加", "ko": "추가" } }
17
+
18
+ const i18n = new I18N(dict, 'zh') // 创建实例,传入词典 dict 并指定语言(NodeJS 环境),
19
+ const i18n = new I18N(dict) // 创建实例,传入词典 dict 并自动判断当前语言(浏览器环境),
20
+ const i18n = new I18N({ }) // 创建实例,传入空词典
21
+ ```
22
+ @see https://github.com/ShenHongFei/xshell/tree/master/i18n
23
+ */
24
+ constructor(_dict, language) {
25
+ /** react-i18next <Trans/> 组件 */
26
+ this.Trans = ({ children }) => children;
27
+ const is_browser = typeof document !== 'undefined' && typeof window !== 'undefined';
28
+ const dict = new dict_1.Dict(_dict);
29
+ // --- if in bowser then detect language & intl
30
+ if (is_browser) {
31
+ const { search = '' } = document.location || {};
32
+ const queries = qs_1.default.parse(search, { ignoreQueryPrefix: true });
33
+ if (!language) {
34
+ const lquery = (queries.language || queries.lang); // 暂时不考虑是数组的情况
35
+ const lwindow = window.language;
36
+ const lbrowser = typeof navigator !== 'undefined' && navigator.language.slice(0, 2);
37
+ language = (lquery || lwindow || js_cookie_1.default.get('language') || lbrowser || 'en');
38
+ }
39
+ if (!I18N.LANGUAGE_REGEXP.test(language))
40
+ language = 'en';
41
+ // console.log(`language = ${language}`)
42
+ }
43
+ language || (language = 'en');
44
+ this.language = language;
45
+ this.t = (text, options) => {
46
+ options = options || {};
47
+ const language = options.language || this.language;
48
+ return this.i18next.t(text, { ...options, lng: language, defaultValue: text });
49
+ };
50
+ this.r = (field) => field ?
51
+ field[this.language] || field.en || field.zh || field || ''
52
+ :
53
+ field || '';
54
+ // --- init i18next
55
+ this.i18next = i18next_1.default.createInstance();
56
+ if (is_browser)
57
+ try {
58
+ // 在无 React 的浏览器环境下避免 react-i18next 中执行 React.createContext() 报错
59
+ // const React = require('react') as typeof import('react')
60
+ const { initReactI18next, Trans: I18NextTrans } = require('react-i18next');
61
+ this.i18next.use(initReactI18next);
62
+ const _i18next = this.i18next;
63
+ // 绑定 Trans 组件的 i18n 到 this.i18next, 解决多个 i18next 冲突的问题
64
+ // react-i18next/context.js 中 i18n 实例只在模块级别维护,多次 this.i18next.use(initReactI18next) 会覆盖前面的 i18n,导致 Trans 无法翻译
65
+ // https://github.com/i18next/react-i18next/issues/726
66
+ this.Trans = function Trans({ i18n = _i18next, ...others }) {
67
+ // 简单转发,性能更好
68
+ return I18NextTrans({ i18n, ...others });
69
+ // return React.createElement(I18NextTrans, { i18n, ...others } as any, children)
70
+ // return <I18NextTrans {...{ i18n, ...others } }>{children}</I18NextTrans>
71
+ };
72
+ }
73
+ catch { }
74
+ this.i18next.init({
75
+ lng: this.language,
76
+ // LOCAL
77
+ // debug: true,
78
+ debug: false,
79
+ fallbackLng: {
80
+ en: ['zh'],
81
+ ja: ['en', 'zh'],
82
+ ko: ['en', 'zh'],
83
+ },
84
+ // 禁用 : 和 . 作为 seperator
85
+ keySeparator: false,
86
+ nsSeparator: false,
87
+ resources: dict.to_resources(),
88
+ interpolation: {
89
+ escapeValue: false
90
+ },
91
+ react: {
92
+ transKeepBasicHtmlNodesFor: []
93
+ },
94
+ });
95
+ if (typeof window !== 'undefined' && window && !('i18n' in window))
96
+ window.i18n = this;
97
+ }
98
+ /** 加载词典文件 (需要将这两行单独放一个文件里,以保证在 import 其他文件之前执行)
99
+
100
+ @example
101
+ import dict from './dict.json' // { "添加": { "en": "Add", "ja": "追加", "ko": "추가" } }
102
+ i18n.init(dict)
103
+ */
104
+ init(dict) {
105
+ Object.entries(new dict_1.Dict(dict).to_resources()).forEach(([language, { translation }]) => {
106
+ this.i18next.addResources(language, 'translation', translation);
107
+ });
108
+ }
109
+ toJSON() {
110
+ return {
111
+ language: this.language,
112
+ };
113
+ }
114
+ }
115
+ exports.I18N = I18N;
116
+ I18N.LANGUAGE_REGEXP = /^(zh|en|ja|jp|ko)$/;
117
+ exports.default = I18N;
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import qs from 'qs'\nimport Cookies from 'js-cookie'\nimport i18next from 'i18next'\nimport type { i18n as I18Next } from 'i18next'\nimport type { Trans } from 'react-i18next'\n\nimport { Dict } from './dict'\nimport type { _Dict, Item } from './dict'\n\n\nexport type Language = 'zh' | 'en' | 'ja' | 'ko'\n\nexport const LANGUAGES = ['zh', 'en', 'ja', 'ko'] as const\n\ndeclare global {\n interface Window {\n language: Language\n }\n}\n\n\n/**\n 提供翻译文本功能,在浏览器环境下自动解析当前语言、国际/国内用户\n @see https://github.com/ShenHongFei/xshell/tree/master/i18n\n*/\nexport class I18N {\n static LANGUAGE_REGEXP = /^(zh|en|ja|jp|ko)$/\n \n \n /** (ISO 639-1 标准语言代码) 可能取 zh, en, ja, ko */\n language: Language\n \n /** hostname shortcuts */\n hosts: Hosts\n \n /** url prefix shortcuts */\n roots: Roots\n \n /** 标记静态文本,以便扫描词条,并在运行时根据当前语言获取翻译 */\n t : (text: string, options?: { language?: Language, context?: string, count?: number, [key: string]: any }) => string\n \n /** render: 翻译配置字段 */\n r : (field: Item | undefined | null) => string\n \n i18next: I18Next\n \n /** react-i18next <Trans/> 组件 */\n Trans: typeof Trans = ({ children }) => children as any\n \n \n /** ```ts\n import dict from './dict.json' // { \"添加\": { \"en\": \"Add\", \"ja\": \"追加\", \"ko\": \"추가\" } }\n \n const i18n = new I18N(dict, 'zh') // 创建实例,传入词典 dict 并指定语言(NodeJS 环境),\n const i18n = new I18N(dict) // 创建实例,传入词典 dict 并自动判断当前语言(浏览器环境),\n const i18n = new I18N({ }) // 创建实例,传入空词典\n ```\n @see https://github.com/ShenHongFei/xshell/tree/master/i18n\n */\n constructor (_dict: _Dict, language?: Language) {\n const is_browser = typeof document !== 'undefined' && typeof window !== 'undefined'\n \n const dict = new Dict(_dict)\n \n // --- if in bowser then detect language & intl\n if (is_browser) {\n const { search = '' } = document.location || { }\n const queries = qs.parse(search, { ignoreQueryPrefix: true })\n \n if (!language) {\n const lquery = (queries.language || queries.lang) as string // 暂时不考虑是数组的情况\n const lwindow = window.language\n const lbrowser = typeof navigator !== 'undefined' && navigator.language.slice(0, 2)\n \n language = (lquery || lwindow || Cookies.get('language') || lbrowser || 'en') as Language\n }\n \n if (!I18N.LANGUAGE_REGEXP.test(language))\n language = 'en'\n \n // console.log(`language = ${language}`)\n }\n \n language ||= 'en'\n \n this.language = language\n \n this.t = (text, options) => {\n options = options || { }\n \n const language = options.language || this.language\n \n return this.i18next.t(text, { ...options, lng: language, defaultValue: text })\n }\n \n this.r = (field) => \n field ?\n field[this.language] || field.en || field.zh || field as any || ''\n :\n field || ''\n \n // --- init i18next\n this.i18next = i18next.createInstance()\n \n if (is_browser)\n try {\n // 在无 React 的浏览器环境下避免 react-i18next 中执行 React.createContext() 报错\n // const React = require('react') as typeof import('react')\n const { initReactI18next, Trans: I18NextTrans } = require('react-i18next') as typeof import('react-i18next')\n this.i18next.use(initReactI18next)\n const _i18next = this.i18next\n // 绑定 Trans 组件的 i18n 到 this.i18next, 解决多个 i18next 冲突的问题\n // react-i18next/context.js 中 i18n 实例只在模块级别维护,多次 this.i18next.use(initReactI18next) 会覆盖前面的 i18n,导致 Trans 无法翻译\n // https://github.com/i18next/react-i18next/issues/726\n this.Trans = function Trans ({ i18n = _i18next, ...others }) {\n // 简单转发,性能更好\n return I18NextTrans({ i18n, ...others })\n // return React.createElement(I18NextTrans, { i18n, ...others } as any, children)\n // return <I18NextTrans {...{ i18n, ...others } }>{children}</I18NextTrans>\n }\n } catch { }\n \n this.i18next.init({\n lng: this.language,\n // LOCAL\n // debug: true,\n debug: false,\n fallbackLng: {\n en: ['zh'],\n ja: ['en', 'zh'],\n ko: ['en', 'zh'],\n },\n // 禁用 : 和 . 作为 seperator\n keySeparator: false,\n nsSeparator: false,\n resources: dict.to_resources(),\n interpolation: {\n escapeValue: false\n },\n react: {\n transKeepBasicHtmlNodesFor: []\n },\n })\n \n \n if (typeof window !== 'undefined' && window && !('i18n' in window))\n (window as any).i18n = this\n }\n \n \n /** 加载词典文件 (需要将这两行单独放一个文件里,以保证在 import 其他文件之前执行) \n \n @example\n import dict from './dict.json' // { \"添加\": { \"en\": \"Add\", \"ja\": \"追加\", \"ko\": \"추가\" } }\n i18n.init(dict)\n */\n init (dict: _Dict) {\n Object.entries(\n new Dict(dict).to_resources()\n ).forEach(([language, { translation }]) => {\n this.i18next.addResources(language, 'translation', translation)\n })\n }\n \n toJSON () {\n return {\n language: this.language,\n }\n }\n}\n\n\nexport interface Hosts {\n \n}\n\n\nexport interface Roots {\n \n}\n\nexport type { _Dict, Item }\n\nexport interface I18NBasic {\n intl: boolean\n language: Language\n}\n\nexport default I18N\n"]}
@@ -0,0 +1,42 @@
1
+ import '../prototype.js';
2
+ import type { Language } from './index';
3
+ import Dict from './dict';
4
+ import type { Item, _Dict } from './dict';
5
+ /** read write Dict for scanner */
6
+ export declare class RWDict extends Dict {
7
+ /** 更新词条 */
8
+ set_item(key: string, item: Item, { print, placeholder, overwrite, dryrun, create }?: {
9
+ print?: boolean;
10
+ placeholder?: boolean;
11
+ overwrite?: boolean;
12
+ dryrun?: boolean;
13
+ create?: boolean;
14
+ }): void;
15
+ /** 更新词条翻译 */
16
+ set_translation(key: string, language: Language, translation: string, {
17
+ /** 允许新增词条 */
18
+ create,
19
+ /** 允许更新翻译 */
20
+ overwrite, print, placeholder, dryrun }?: {
21
+ create?: boolean;
22
+ overwrite?: boolean;
23
+ print?: boolean;
24
+ placeholder?: boolean;
25
+ dryrun?: boolean;
26
+ }): void;
27
+ /** 合并、更新词典
28
+ print?: true
29
+ dryrun?: false
30
+ overwrite?: false
31
+ create?: true
32
+ */
33
+ merge(_dict: _Dict, { print, overwrite, dryrun, create }?: {
34
+ print?: boolean;
35
+ overwrite?: boolean;
36
+ dryrun?: boolean;
37
+ create?: boolean;
38
+ }): this;
39
+ /** trim?: [true] 是否过滤掉空词条及空翻译 */
40
+ to_json(trim?: boolean): string;
41
+ }
42
+ export default RWDict;
package/i18n/rwdict.js ADDED
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RWDict = void 0;
4
+ const tslib_1 = require("tslib");
5
+ require("../prototype.js");
6
+ const dict_1 = (0, tslib_1.__importDefault)(require("./dict"));
7
+ /** read write Dict for scanner */
8
+ class RWDict extends dict_1.default {
9
+ /** 更新词条 */
10
+ set_item(key, item, { print = true, placeholder = false, overwrite = false, dryrun = false, create = false } = {}) {
11
+ if (!key || !item || typeof item !== 'object')
12
+ throw new Error('key/item 错误');
13
+ if (!item.zh && !item.en && !item.ja && !item.ko) {
14
+ if (placeholder) {
15
+ const empty_item = { en: '', ja: '', ko: '' };
16
+ if (!dryrun && create)
17
+ this._dict[key] = empty_item;
18
+ if (print)
19
+ console.log(`${'+ '.green + key}: ${JSON.stringify(empty_item)}`);
20
+ }
21
+ else if (print)
22
+ console.log(`${'! 未翻译:'.red}${key}`);
23
+ return;
24
+ }
25
+ Object.entries(item).forEach(([language, translation]) => {
26
+ this.set_translation(key, language, translation, { print, overwrite, dryrun, create });
27
+ });
28
+ }
29
+ /** 更新词条翻译 */
30
+ set_translation(key, language, translation, {
31
+ /** 允许新增词条 */
32
+ create = true,
33
+ /** 允许更新翻译 */
34
+ overwrite = false, print = true, placeholder = false, dryrun = false } = {}) {
35
+ if (!key || !language)
36
+ throw new Error('key/language 不能为空');
37
+ if (!translation)
38
+ return;
39
+ // --- add item
40
+ let item = this._dict[key];
41
+ const id = `(${key.replace(/\n/g, '\\n')}).${language}`;
42
+ if (!item) {
43
+ if (!create) {
44
+ console.log(`${'+ '.red + id} ${translation.replace(/\n/g, '\\n')}`);
45
+ return;
46
+ }
47
+ if (print)
48
+ console.log(`${'+ '.green}${key.replace(/\n/g, '\\n')}`);
49
+ item = {};
50
+ if (!dryrun)
51
+ this._dict[key] = item;
52
+ }
53
+ // --- update translation
54
+ const _translation = item[language];
55
+ // add
56
+ if (!_translation) {
57
+ if (print)
58
+ console.log(`${'+ '.green + id}: ${translation.replace(/\n/g, '\\n')}`);
59
+ if (!dryrun)
60
+ item[language] = translation;
61
+ return;
62
+ }
63
+ // modify
64
+ if (_translation !== translation)
65
+ if (!overwrite) {
66
+ console.error(`${`已存在 ${id} 词条:`.red} ${JSON.stringify(item)}`);
67
+ console.error(`${'M? '.yellow}${_translation.replace(/\n/g, '\\n')} → ${translation.replace(/\n/g, '\\n')}`);
68
+ if (!dryrun)
69
+ console.error(`如要更新翻译请设置 { overwrite: true },否则使用 i18n.t('text', { context: 'xxx' }) 标记文本以区分。\n`);
70
+ return;
71
+ }
72
+ else {
73
+ if (print)
74
+ console.log(`${'M '.yellow}${_translation.replace(/\n/g, '\\n')} → ${translation.replace(/\n/g, '\\n')}`);
75
+ if (!dryrun)
76
+ item[language] = translation;
77
+ }
78
+ }
79
+ /** 合并、更新词典
80
+ print?: true
81
+ dryrun?: false
82
+ overwrite?: false
83
+ create?: true
84
+ */
85
+ merge(_dict, { print = true, overwrite = false, dryrun = false, create = true } = {}) {
86
+ Object.entries(_dict).forEach(([key, item]) => {
87
+ this.set_item(key, item, { print, overwrite, dryrun, create });
88
+ });
89
+ if (dryrun) {
90
+ console.log('dry run completed'.green);
91
+ return;
92
+ }
93
+ if (print)
94
+ console.log('词典合并完成'.green);
95
+ return this;
96
+ }
97
+ /** trim?: [true] 是否过滤掉空词条及空翻译 */
98
+ to_json(trim = true) {
99
+ if (trim)
100
+ this._dict = Object.fromEntries((Object.entries(this._dict)
101
+ .map(([key, item]) => ([
102
+ key,
103
+ Object.fromEntries(Object.entries(item).filter(([language, translation]) => translation))
104
+ ])).filter(([key, item]) => Object.keys(item).length)));
105
+ return JSON.stringify(this._dict, null, 4);
106
+ }
107
+ }
108
+ exports.RWDict = RWDict;
109
+ exports.default = RWDict;
110
+ //# sourceMappingURL=rwdict.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rwdict.js","sourceRoot":"","sources":["rwdict.ts"],"names":[],"mappings":"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","sourcesContent":["import '../prototype.js'\n\nimport type { Language } from './index'\nimport Dict from './dict'\nimport type { Item, _Dict } from './dict'\n\n\n/** read write Dict for scanner */\nexport class RWDict extends Dict {\n /** 更新词条 */\n set_item (key: string, item: Item, { print = true, placeholder = false, overwrite = false, dryrun = false, create = false } = { }) {\n if (!key || !item || typeof item !== 'object') throw new Error('key/item 错误')\n \n if (!item.zh && !item.en && !item.ja && !item.ko) {\n if (placeholder) {\n const empty_item = { en: '', ja: '', ko: '' }\n if (!dryrun && create)\n this._dict[key] = empty_item\n if (print)\n console.log(`${'+ '.green + key}: ${JSON.stringify(empty_item)}`)\n } else\n if (print)\n console.log(`${'! 未翻译:'.red}${key}`)\n \n return\n }\n \n Object.entries(item).forEach( ([language, translation]: [Language, string]) => {\n this.set_translation(key, language, translation, { print, overwrite, dryrun, create })\n })\n }\n \n \n /** 更新词条翻译 */\n set_translation (key: string, language: Language, translation: string, {\n /** 允许新增词条 */\n create = true, \n /** 允许更新翻译 */\n overwrite = false,\n print = true, \n placeholder = false, \n dryrun = false\n } = { }) {\n if (!key || !language) throw new Error('key/language 不能为空')\n if (!translation) return\n \n // --- add item\n let item = this._dict[key]\n \n const id = `(${key.replace(/\\n/g, '\\\\n')}).${language}`\n \n if (!item) {\n if (!create) {\n console.log(`${'+ '.red + id} ${translation.replace(/\\n/g, '\\\\n')}`)\n return\n }\n if (print)\n console.log(`${'+ '.green}${key.replace(/\\n/g, '\\\\n')}`)\n \n item = { }\n \n if (!dryrun)\n this._dict[key] = item\n }\n \n \n // --- update translation\n const _translation = item[language]\n \n \n // add\n if (!_translation) {\n if (print)\n console.log(`${'+ '.green + id}: ${translation.replace(/\\n/g, '\\\\n')}`)\n if (!dryrun)\n item[language] = translation\n return\n }\n \n // modify\n if (_translation !== translation)\n if (!overwrite) {\n console.error(`${`已存在 ${id} 词条:`.red} ${JSON.stringify(item)}`)\n console.error(`${'M? '.yellow}${_translation.replace(/\\n/g, '\\\\n')} → ${translation.replace(/\\n/g, '\\\\n')}`)\n if (!dryrun)\n console.error(`如要更新翻译请设置 { overwrite: true },否则使用 i18n.t('text', { context: 'xxx' }) 标记文本以区分。\\n`)\n return\n } else {\n if (print)\n console.log(`${'M '.yellow}${_translation.replace(/\\n/g, '\\\\n')} → ${translation.replace(/\\n/g, '\\\\n')}`)\n if (!dryrun)\n item[language] = translation\n }\n }\n \n /** 合并、更新词典 \n print?: true \n dryrun?: false \n overwrite?: false \n create?: true \n */\n merge (_dict: _Dict, { print = true, overwrite = false, dryrun = false, create = true } = { }) {\n Object.entries(_dict).forEach( ([key, item]) => {\n this.set_item(key, item, { print, overwrite, dryrun, create })\n })\n \n if (dryrun) {\n console.log('dry run completed'.green)\n return\n }\n \n if (print)\n console.log('词典合并完成'.green)\n \n return this\n }\n \n \n \n /** trim?: [true] 是否过滤掉空词条及空翻译 */ \n to_json (trim: boolean = true) {\n if (trim)\n this._dict = Object.fromEntries(\n (Object.entries(this._dict)\n .map( ([key, item]) => ([\n key,\n Object.fromEntries(\n Object.entries(item).filter( ([ language, translation ]) => translation )\n )\n ])\n ).filter( ([ key, item ]: [string, Item]) => Object.keys(item).length )\n )\n )\n \n return JSON.stringify(this._dict, null, 4)\n }\n}\n\nexport default RWDict\n"]}
@@ -0,0 +1,5 @@
1
+ declare let unmarkeds: any[];
2
+ declare const Checker: ({ filepath }: {
3
+ filepath: any;
4
+ }) => PluginItem;
5
+ export { Checker, unmarkeds };
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unmarkeds = exports.Checker = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const types = (0, tslib_1.__importStar)(require("@babel/types"));
6
+ let unmarkeds = [];
7
+ exports.unmarkeds = unmarkeds;
8
+ let t = 0;
9
+ let Trans = 0;
10
+ function is_t(node) {
11
+ if (types.isCallExpression(node)) {
12
+ // t('chtext')
13
+ if (types.isIdentifier(node.callee) && node.callee.name === "t")
14
+ return true;
15
+ // i18n.t('chtext') | i18n.__('chtext')
16
+ if (types.isMemberExpression(node.callee) &&
17
+ types.isIdentifier(node.callee.object) &&
18
+ types.isIdentifier(node.callee.property) &&
19
+ node.callee.object.name === "i18n" &&
20
+ (node.callee.property.name === "t" || node.callee.property.name === '__'))
21
+ return true;
22
+ }
23
+ return false;
24
+ }
25
+ function is_trans(node) {
26
+ // <Trans>
27
+ if (types.isJSXElement(node) &&
28
+ types.isJSXOpeningElement(node.openingElement) &&
29
+ types.isJSXIdentifier(node.openingElement.name) &&
30
+ node.openingElement.name.name === "Trans")
31
+ return true;
32
+ return false;
33
+ }
34
+ const has_unmarked_chinese_characters = (str) => !t && !Trans && /[\u4e00-\u9fa5]/.test(str);
35
+ const Checker = ({ filepath }) => {
36
+ const visitor = {
37
+ CallExpression: {
38
+ enter({ node }) {
39
+ if (is_t(node))
40
+ t++;
41
+ },
42
+ exit({ node }) {
43
+ if (is_t(node))
44
+ t--;
45
+ },
46
+ },
47
+ JSXElement: {
48
+ enter({ node }) {
49
+ if (is_trans(node))
50
+ Trans++;
51
+ },
52
+ exit({ node }) {
53
+ if (is_trans(node))
54
+ Trans--;
55
+ },
56
+ },
57
+ JSXText: ({ node }) => {
58
+ if (has_unmarked_chinese_characters(node.value))
59
+ unmarkeds.push({ filepath, loc: node.loc, value: node.value });
60
+ },
61
+ StringLiteral: ({ node }) => {
62
+ if (has_unmarked_chinese_characters(node.value))
63
+ unmarkeds.push({ filepath, loc: node.loc, value: node.value });
64
+ },
65
+ TemplateElement: ({ node }) => {
66
+ if (has_unmarked_chinese_characters(node.value.raw))
67
+ unmarkeds.push({ filepath, loc: node.loc, value: node.value.cooked });
68
+ },
69
+ };
70
+ return visitor;
71
+ };
72
+ exports.Checker = Checker;
73
+ //# sourceMappingURL=checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker.js","sourceRoot":"","sources":["checker.ts"],"names":[],"mappings":";;;;AAAA,iEAAqC;AAGrC,IAAI,SAAS,GAAG,EAAE,CAAA;AA+EA,8BAAS;AA7E3B,IAAI,CAAC,GAAG,CAAC,CAAA;AACT,IAAI,KAAK,GAAG,CAAC,CAAA;AAEb,SAAS,IAAI,CAAC,IAAI;IACd,IAAI,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE;QAC9B,cAAc;QACd,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,GAAG;YAC3D,OAAO,IAAI,CAAA;QAEf,uCAAuC;QACvC,IACI,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;YACrC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACtC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM;YAClC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC;YAEzE,OAAO,IAAI,CAAA;KAClB;IACD,OAAO,KAAK,CAAA;AAChB,CAAC;AAED,SAAS,QAAQ,CAAC,IAAI;IAClB,UAAU;IACV,IACI,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC;QACxB,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,cAAc,CAAC;QAC9C,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;QAC/C,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO;QAEzC,OAAO,IAAI,CAAA;IAEf,OAAO,KAAK,CAAA;AAChB,CAAC;AAED,MAAM,+BAA+B,GAAG,CAAC,GAAW,EAAE,EAAE,CACpD,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAG/C,MAAM,OAAO,GAAG,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC7B,MAAM,OAAO,GAAe;QACxB,cAAc,EAAE;YACZ,KAAK,CAAC,EAAE,IAAI,EAAE;gBACV,IAAI,IAAI,CAAC,IAAI,CAAC;oBACV,CAAC,EAAE,CAAA;YACX,CAAC;YACD,IAAI,CAAC,EAAE,IAAI,EAAE;gBACT,IAAI,IAAI,CAAC,IAAI,CAAC;oBACV,CAAC,EAAE,CAAA;YACX,CAAC;SACJ;QACD,UAAU,EAAE;YACR,KAAK,CAAC,EAAE,IAAI,EAAE;gBACV,IAAI,QAAQ,CAAC,IAAI,CAAC;oBACd,KAAK,EAAE,CAAA;YACf,CAAC;YACD,IAAI,CAAC,EAAE,IAAI,EAAE;gBACT,IAAI,QAAQ,CAAC,IAAI,CAAC;oBACd,KAAK,EAAE,CAAA;YACf,CAAC;SACJ;QACD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;YAClB,IAAI,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC;gBAC3C,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QACtE,CAAC;QACD,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;YACxB,IAAI,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC;gBAC3C,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QACtE,CAAC;QACD,eAAe,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;YAC1B,IAAI,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;gBAC/C,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;QAC7E,CAAC;KACJ,CAAA;IACD,OAAO,OAAO,CAAA;AAClB,CAAC,CAAA;AAEQ,0BAAO","sourcesContent":["import * as types from '@babel/types'\nimport { PluginItem } from '@babel/core'\n\nlet unmarkeds = []\n\nlet t = 0\nlet Trans = 0\n\nfunction is_t(node) {\n if (types.isCallExpression(node)) {\n // t('chtext')\n if (types.isIdentifier(node.callee) && node.callee.name === \"t\")\n return true\n \n // i18n.t('chtext') | i18n.__('chtext')\n if (\n types.isMemberExpression(node.callee) &&\n types.isIdentifier(node.callee.object) &&\n types.isIdentifier(node.callee.property) &&\n node.callee.object.name === \"i18n\" &&\n (node.callee.property.name === \"t\" || node.callee.property.name === '__')\n )\n return true\n }\n return false\n}\n\nfunction is_trans(node) {\n // <Trans>\n if (\n types.isJSXElement(node) &&\n types.isJSXOpeningElement(node.openingElement) &&\n types.isJSXIdentifier(node.openingElement.name) &&\n node.openingElement.name.name === \"Trans\"\n )\n return true\n \n return false\n}\n\nconst has_unmarked_chinese_characters = (str: string) => \n !t && !Trans && /[\\u4e00-\\u9fa5]/.test(str)\n\n\nconst Checker = ({ filepath }) => {\n const visitor: PluginItem = {\n CallExpression: {\n enter({ node }) {\n if (is_t(node))\n t++\n },\n exit({ node }) {\n if (is_t(node))\n t--\n },\n },\n JSXElement: {\n enter({ node }) {\n if (is_trans(node))\n Trans++\n },\n exit({ node }) {\n if (is_trans(node))\n Trans--\n },\n },\n JSXText: ({ node }) => {\n if (has_unmarked_chinese_characters(node.value))\n unmarkeds.push({ filepath, loc: node.loc, value: node.value })\n },\n StringLiteral: ({ node }) => {\n if (has_unmarked_chinese_characters(node.value))\n unmarkeds.push({ filepath, loc: node.loc, value: node.value })\n },\n TemplateElement: ({ node }) => {\n if (has_unmarked_chinese_characters(node.value.raw))\n unmarkeds.push({ filepath, loc: node.loc, value: node.value.cooked })\n },\n }\n return visitor\n}\n\nexport { Checker, unmarkeds }\n"]}
@@ -0,0 +1,52 @@
1
+ import '../../prototype.js';
2
+ /** 默认 i18next 扫描配置 */
3
+ declare const DEFAULT_CONFIG: {
4
+ debug: boolean;
5
+ input: string[];
6
+ output: string;
7
+ dict: string[];
8
+ lngs: string[];
9
+ ns: string[];
10
+ defaultLng: string;
11
+ defaultNs: string;
12
+ func: {
13
+ list: string[];
14
+ extensions: any[];
15
+ };
16
+ trans: {
17
+ extensions: any[];
18
+ fallbackKey: boolean;
19
+ babylon: import("@babel/parser").ParserOptions;
20
+ acorn: {
21
+ ecmaVersion: string;
22
+ sourceType: string;
23
+ };
24
+ };
25
+ keySeparator: boolean;
26
+ nsSeparator: boolean;
27
+ context: boolean;
28
+ contextFallback: boolean;
29
+ contextSeparator: string;
30
+ plural(language: string, ns: string, key: string, options: any /** Config */): boolean;
31
+ pluralFallback: boolean;
32
+ pluralSeparator: string;
33
+ interpolation: {
34
+ prefix: string;
35
+ suffix: string;
36
+ };
37
+ };
38
+ export declare type Config = Partial<(typeof DEFAULT_CONFIG) & {
39
+ defaultValue?: string;
40
+ resource?: {
41
+ loadPath?: string;
42
+ savePath?: string;
43
+ jsonIndent?: number;
44
+ lineEnding?: '\n';
45
+ };
46
+ }>;
47
+ /** 扫描源码中的词条,以及收集未翻译的词条。生成 scanneds.json 和 untranslateds.json
48
+ * rootdir 要扫描根目录 [ process.cwd() ]
49
+ * config 配置信息
50
+ */
51
+ export declare function scanner(rootdir?: string, config?: Config): void;
52
+ export default scanner;