monaco-editor-nls-adapter 2.2.2 → 2.3.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/codegen.js CHANGED
@@ -1,3 +1,6 @@
1
+ const SYNC_LOCALE_LOADER_PATTERN = /function SYNC_LOCALE_LOADER\(locale\) \{\s*return require\(`\.\/locales\/\$\{locale\}\.json`\)\s*\}/
2
+ const ASYNC_LOCALE_LOADER_PATTERN = /function ASYNC_LOCALE_LOADER\(locale\) \{\s*return import\(\/\* webpackChunkName: "nls-\[request\]" \*\/ `\.\/locales\/\$\{locale\}\.json`\)\s*\}/
3
+
1
4
  /**
2
5
  * 生成按需加载语言包的代码片段
3
6
  * @param {string[]} languages 语言代码数组
@@ -6,32 +9,48 @@
6
9
  */
7
10
  function generateLocalesCode(languages, isAsync) {
8
11
  if (!languages || languages.length === 0) {
9
- return null;
12
+ return null
10
13
  }
11
14
 
12
15
  if (isAsync) {
13
16
  // 异步版本 (用于 initAsync)
14
- const map = languages.map(lang => ` '${lang}': () => import('./locales/${lang}.json')`).join(',\n');
17
+ const map = languages.map(lang => ` '${lang}': () => import('./locales/${lang}.json')`).join(',\n')
15
18
  return `(async (locale) => {
16
19
  const locales = {
17
20
  ${map}
18
21
  };
19
22
  if (locales[locale]) return await locales[locale]();
20
23
  throw new Error('[monaco-editor-nls-adapter] Locale not bundled: ' + locale);
21
- })(targetLocale)`;
24
+ })(targetLocale)`
22
25
  } else {
23
26
  // 同步版本 (用于 init)
24
- const map = languages.map(lang => ` '${lang}': () => require('./locales/${lang}.json')`).join(',\n');
27
+ const map = languages.map(lang => ` '${lang}': () => require('./locales/${lang}.json')`).join(',\n')
25
28
  return `((locale) => {
26
29
  const locales = {
27
30
  ${map}
28
31
  };
29
32
  if (locales[locale]) return locales[locale]();
30
33
  throw new Error('[monaco-editor-nls-adapter] Locale not bundled: ' + locale);
31
- })(targetLocale)`;
34
+ })(targetLocale)`
35
+ }
36
+ }
37
+
38
+ function replaceLocaleLoaders(source, languages) {
39
+ if (!languages || languages.length === 0) {
40
+ return source
32
41
  }
42
+
43
+ const syncCode = generateLocalesCode(languages, false)
44
+ const asyncCode = generateLocalesCode(languages, true)
45
+
46
+ return source
47
+ .replace(SYNC_LOCALE_LOADER_PATTERN, `function SYNC_LOCALE_LOADER(locale) {\n return ${syncCode}\n}`)
48
+ .replace(ASYNC_LOCALE_LOADER_PATTERN, `function ASYNC_LOCALE_LOADER(locale) {\n return ${asyncCode}\n}`)
33
49
  }
34
50
 
35
51
  module.exports = {
36
- generateLocalesCode
37
- };
52
+ generateLocalesCode,
53
+ replaceLocaleLoaders,
54
+ SYNC_LOCALE_LOADER_PATTERN,
55
+ ASYNC_LOCALE_LOADER_PATTERN
56
+ }
package/index.js CHANGED
@@ -31,6 +31,35 @@ const LOCALE_MAP = {
31
31
  }
32
32
 
33
33
  let IS_LOADING = false
34
+ let LOADING_PROMISE = null
35
+ let LOADING_LOCALE = ''
36
+
37
+ function SYNC_LOCALE_LOADER(locale) {
38
+ return require(`./locales/${locale}.json`)
39
+ }
40
+
41
+ function ASYNC_LOCALE_LOADER(locale) {
42
+ return import(/* webpackChunkName: "nls-[request]" */ `./locales/${locale}.json`)
43
+ }
44
+
45
+ function resolveLocale(locale) {
46
+ const isBrowser = typeof window !== 'undefined' && typeof navigator !== 'undefined'
47
+ let nextLocale = locale
48
+
49
+ if (!nextLocale && isBrowser) {
50
+ nextLocale = navigator.language || navigator.userLanguage
51
+ }
52
+
53
+ let targetLocale = (nextLocale || 'zh-hans').toLowerCase()
54
+ if (LOCALE_MAP[targetLocale]) {
55
+ targetLocale = LOCALE_MAP[targetLocale]
56
+ }
57
+
58
+ return {
59
+ isBrowser,
60
+ targetLocale
61
+ }
62
+ }
34
63
 
35
64
  /**
36
65
  * 使用指定的语言代码初始化 Monaco Editor 的本地化。
@@ -39,23 +68,15 @@ let IS_LOADING = false
39
68
  * @param {boolean} force 是否强制重新初始化
40
69
  */
41
70
  function init(locale, force = false) {
42
- const isBrowser = typeof window !== 'undefined' && typeof navigator !== 'undefined'
43
- if (!locale && isBrowser) {
44
- locale = navigator.language || navigator.userLanguage
45
- }
46
-
47
- let targetLocale = (locale || 'zh-hans').toLowerCase()
48
- if (LOCALE_MAP[targetLocale]) {
49
- targetLocale = LOCALE_MAP[targetLocale]
50
- }
71
+ const { isBrowser, targetLocale } = resolveLocale(locale)
51
72
 
52
73
  if (lite.getCurrentLocale() === targetLocale && !force) {
53
74
  return true
54
75
  }
55
76
 
56
77
  try {
57
- // 这里的动态 require 是导致全量打包的主要原因,若需精简请改用 lite.setMessages()
58
- const data = require(`./locales/${targetLocale}.json`)
78
+ // 这里的占位表达式会在构建期由 loader/plugin 替换为按需语言分发表。
79
+ const data = SYNC_LOCALE_LOADER(targetLocale)
59
80
  lite.setMessages(data, targetLocale)
60
81
  return true
61
82
  } catch (e) {
@@ -71,36 +92,37 @@ function init(locale, force = false) {
71
92
  * @param {string} locale 语言代码
72
93
  * @param {boolean} force 是否强制重新初始化
73
94
  */
74
- async function initAsync(locale, force = false) {
75
- const isBrowser = typeof window !== 'undefined' && typeof navigator !== 'undefined'
76
- if (!locale && isBrowser) {
77
- locale = navigator.language || navigator.userLanguage
78
- }
95
+ function initAsync(locale, force = false) {
96
+ const { isBrowser, targetLocale } = resolveLocale(locale)
79
97
 
80
- let targetLocale = (locale || 'zh-hans').toLowerCase()
81
- if (LOCALE_MAP[targetLocale]) {
82
- targetLocale = LOCALE_MAP[targetLocale]
98
+ if (lite.getCurrentLocale() === targetLocale && !force) {
99
+ return Promise.resolve(true)
83
100
  }
84
101
 
85
- if (lite.getCurrentLocale() === targetLocale && !force) {
86
- return true
102
+ if (IS_LOADING && !force && LOADING_LOCALE === targetLocale && LOADING_PROMISE) {
103
+ return LOADING_PROMISE
87
104
  }
88
105
 
89
- if (IS_LOADING && !force) return false
90
106
  IS_LOADING = true
107
+ LOADING_LOCALE = targetLocale
108
+ LOADING_PROMISE = ASYNC_LOCALE_LOADER(targetLocale)
109
+ .then((module) => {
110
+ lite.setMessages(module.default || module, targetLocale)
111
+ return true
112
+ })
113
+ .catch((e) => {
114
+ if (isBrowser) {
115
+ console.warn(`[monaco-editor-nls-adapter] 无法异步加载语言包: ${targetLocale}`, e)
116
+ }
117
+ return false
118
+ })
119
+ .finally(() => {
120
+ IS_LOADING = false
121
+ LOADING_PROMISE = null
122
+ LOADING_LOCALE = ''
123
+ })
91
124
 
92
- try {
93
- const module = await import(/* webpackChunkName: "nls-[request]" */ `./locales/${targetLocale}.json`)
94
- lite.setMessages(module.default || module, targetLocale)
95
- return true
96
- } catch (e) {
97
- if (isBrowser) {
98
- console.warn(`[monaco-editor-nls-adapter] 无法异步加载语言包: ${targetLocale}`, e)
99
- }
100
- return false
101
- } finally {
102
- IS_LOADING = false
103
- }
125
+ return LOADING_PROMISE
104
126
  }
105
127
 
106
128
  module.exports = {
package/lite.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ import { NLSProxy } from './proxy';
2
+ import monacoNlsPlugin from './vite-plugin';
3
+
4
+ /**
5
+ * 获取当前已生效的语言代码名称 / Get the current active locale name.
6
+ * @returns 语言代码 (如 'zh-hans')
7
+ */
8
+ export function getLocaleName(): string;
9
+
10
+ /**
11
+ * 获取当前已生效的语言代码名称 (同 getLocaleName) / Get current locale (alias for getLocaleName).
12
+ */
13
+ export function getCurrentLocale(): string;
14
+
15
+ /**
16
+ * 获取当前加载的原始翻译数据字典 / Get the raw translation dictionary data.
17
+ */
18
+ export function getLocaleData(): Record<string, any> | null;
19
+
20
+ /**
21
+ * 手动注入翻译数据字典 / Manually set the translation messages.
22
+ * @param messages 符合 Monaco NLS 格式的 JSON 字典对象 / Dictionary following Monaco NLS format.
23
+ * @param locale 语言代码名称标识符 (可选) / Locale code identifier (optional).
24
+ */
25
+ export function setMessages(messages: Record<string, any>, locale?: string): void;
26
+
27
+ /**
28
+ * 设置当前的本地化数据内容 / Directly set the locale data in the proxy.
29
+ */
30
+ export function setLocaleData(data: Record<string, any>, locale?: string): void;
31
+
32
+ /**
33
+ * NLS 代理对象实例 / The underlying NLS proxy instance.
34
+ */
35
+ export const proxy: NLSProxy;
36
+
37
+ /**
38
+ * Vite 插件导出 / Vite plugin for build-time transformation.
39
+ */
40
+ export const vitePlugin: typeof monacoNlsPlugin;
41
+
42
+ /**
43
+ * Webpack Loader 导出 (用于 webpack.config.js) / Webpack loader path and utility.
44
+ */
45
+ export const loader: string;
package/loader.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Webpack Loader 处理函数。
3
+ * 直接导出 Loader 的绝对路径。
4
+ * [Webpack Loader] Absolute path to the Webpack loader.
5
+ */
6
+ declare function monacoNlsLoader(this: any, source: string): string | void;
7
+
8
+ declare namespace monacoNlsLoader {
9
+ /** 插件配置项同 vitePlugin / Shared PluginOptions */
10
+ }
11
+
12
+ export = monacoNlsLoader;
package/loader.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const { transform } = require('./transform')
2
- const { generateLocalesCode } = require('./codegen')
2
+ const { replaceLocaleLoaders } = require('./codegen')
3
3
 
4
4
  /**
5
5
  * Webpack Loader for Monaco Editor NLS Adapter
@@ -22,21 +22,7 @@ module.exports = function (source) {
22
22
 
23
23
  // 2. 处理适配器自身的 index.js (按需打包语言包)
24
24
  if (isAdapter && languages) {
25
- let newCode = source
26
-
27
- // 替换同步 require
28
- const syncCode = generateLocalesCode(languages, false)
29
- if (syncCode) {
30
- newCode = newCode.replace(/require\(`\.\/locales\/\$\{targetLocale\}\.json`\)/g, syncCode)
31
- }
32
-
33
- // 替换异步 import
34
- const asyncCode = generateLocalesCode(languages, true)
35
- if (asyncCode) {
36
- newCode = newCode.replace(/import\(.*?\`\.\/locales\/\$\{targetLocale\}\.json\`\)/g, asyncCode)
37
- }
38
-
39
- return newCode
25
+ return replaceLocaleLoaders(source, languages)
40
26
  }
41
27
 
42
28
  // 3. 处理 Monaco Editor 源代码 (注入本地化逻辑)