monaco-editor-nls-adapter 2.1.1 → 2.2.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/README.md CHANGED
@@ -113,14 +113,34 @@ export default defineConfig({
113
113
  });
114
114
  ```
115
115
 
116
- ### 4. Bundle Optimization (Optional)
116
+ ### 4. On-demand Packaging (Recommended)
117
117
 
118
- If you are concerned about bundle size or the "Stat size" reported by bundle analyzers, you can use the **Lite Version**.
118
+ By default, the adapter's entry point contains dynamic references that may cause bundlers to include all available locales (~13MB total stat size).
119
119
 
120
- The default entry point uses dynamic `require`/`import` with template strings, which may cause build tools (Webpack/Vite) to scan and include all available locales or report a large "original size." The Lite version eliminates this by providing only the core logic.
120
+ You can use the `languages` option to specify **only** the languages you need. This is easier than the Lite version because it retains the full automation of `init()` and `initAsync()` while significantly reducing the bundle size.
121
121
 
122
+ #### Vite Configuration (`vite.config.js`)
122
123
  ```javascript
123
- // 1. Import from /lite
124
+ vitePlugin({
125
+ languages: ['zh-hans', 'en'] // Only include Simplified Chinese and English
126
+ })
127
+ ```
128
+
129
+ #### Webpack Configuration (`webpack.config.js`)
130
+ ```javascript
131
+ {
132
+ loader: loader,
133
+ options: {
134
+ languages: ['zh-hans', 'ja'] // Only include Simplified Chinese and Japanese
135
+ }
136
+ }
137
+ ```
138
+
139
+ > [!TIP]
140
+ > **Extreme Optimization (Lite Version)**: If you want zero code injection, you can bypass the main entry point entirely and use the Lite version. See below:
141
+
142
+ ```javascript
143
+ // 1. Import from /lite (No dynamic loading logic included)
124
144
  import { setMessages } from 'monaco-editor-nls-adapter/lite';
125
145
 
126
146
  // 2. Manually import ONLY the language you need
@@ -128,9 +148,6 @@ import zhHans from 'monaco-editor-nls-adapter/locales/zh-hans.json';
128
148
 
129
149
  // 3. Initialize BEFORE monaco-editor loads
130
150
  setMessages(zhHans, 'zh-hans');
131
-
132
- // 4. Import monaco-editor as usual
133
- import * as monaco from 'monaco-editor';
134
151
  ```
135
152
 
136
153
  ## 📖 Usage
package/README_zh.md CHANGED
@@ -114,24 +114,41 @@ export default defineConfig({
114
114
  });
115
115
  ```
116
116
 
117
- ### 4. 极致体积优化 (可选)
117
+ ### 4. 语言包按需打包 (推荐优化方案)
118
118
 
119
- 如果你对打包后的 JS 文件体积非常敏感,或者 bundle analyzer 显示 `monaco-editor-nls-adapter` `Stat size` 过大(这是由于默认入口包含所有语言包的动态引用导致的),可以使用 **Lite 版本**。
119
+ 默认情况下,由于 `index.js` 包含动态引用,构建工具可能会扫描并打包 `./locales` 目录下的所有语言文件(Stat size 较大)。
120
120
 
121
- Lite 版本不具备内置的语言包发现逻辑,需要你手动导入所需的语言 JSON。这样构建工具(Webpack/Vite)只会打包你真正使用的那门语言,而不会扫描整个 `./locales` 目录。
121
+ 你可以通过 `languages` 配置项来指定**仅打包**需要的语言。这比手动使用 Lite 版本更方便,因为它依然保留了 `init()` `initAsync()` 的全自动加载能力,同时大幅减少产物体积。
122
122
 
123
+ #### Vite 配置 (`vite.config.js`)
123
124
  ```javascript
124
- // 1. 从 /lite 入口导入
125
+ vitePlugin({
126
+ languages: ['zh-hans', 'en'] // 最终产物仅包含中、英语言包
127
+ })
128
+ ```
129
+
130
+ #### Webpack 配置 (`webpack.config.js`)
131
+ ```javascript
132
+ {
133
+ loader: loader,
134
+ options: {
135
+ languages: ['zh-hans', 'ja'] // 最终产物仅包含中、日语言包
136
+ }
137
+ }
138
+ ```
139
+
140
+ > [!TIP]
141
+ > **极致优化 (Lite 版本)**: 如果你连按需打包的代码注入也不想要,可以完全绕过 `index.js`,手动导入 JSON 并调用 `setMessages`。详见下文:
142
+
143
+ ```javascript
144
+ // 1. 从 /lite 入口导入 (不含任何动态加载逻辑)
125
145
  import { setMessages } from 'monaco-editor-nls-adapter/lite';
126
146
 
127
- // 2. 手动导入特定的语言 JSON (由你自己决定包含哪门语言)
147
+ // 2. 手动导入特定的语言 JSON
128
148
  import zhHans from 'monaco-editor-nls-adapter/locales/zh-hans.json';
129
149
 
130
150
  // 3. 初始化 (必须要在 monaco 加载前运行)
131
151
  setMessages(zhHans, 'zh-hans');
132
-
133
- // 4. 正常使用 monaco-editor
134
- import * as monaco from 'monaco-editor';
135
152
  ```
136
153
 
137
154
  ## 📖 使用指南
package/loader.js CHANGED
@@ -1,11 +1,16 @@
1
1
  const { transform } = require('./transform')
2
+ const { generateLocalesCode } = require('./codegen')
2
3
 
3
4
  /**
4
5
  * Webpack Loader for Monaco Editor NLS Adapter
5
6
  */
6
7
  module.exports = function (source) {
7
- // 极致性能优化:第一层极速过滤
8
- if (!this.resourcePath.endsWith('.js') || this.resourcePath.indexOf('monaco-editor') === -1) {
8
+ const resourcePath = this.resourcePath.replace(/\\/g, '/')
9
+ const isAdapter = resourcePath.endsWith('monaco-editor-nls-adapter/index.js') || resourcePath.endsWith('monaco-editor-nls-adapter/index.ts')
10
+ const isMonaco = resourcePath.indexOf('monaco-editor') !== -1
11
+
12
+ // 1. 第一层过滤:仅处理 monaco-editor 或 适配器自身入口
13
+ if (!isAdapter && !isMonaco) {
9
14
  return source
10
15
  }
11
16
 
@@ -13,18 +18,41 @@ module.exports = function (source) {
13
18
 
14
19
  // 获取 loader options
15
20
  const options = (typeof this.getOptions === 'function') ? this.getOptions() : this.query
16
-
17
- // 使用共享的 transform 逻辑
18
- const result = transform(source, this.resourcePath, options || {})
19
-
20
- // 如果返回包含 SourceMap 的对象,则使用 this.callback 提示 Webpack
21
- if (result && typeof result === 'object') {
22
- if (this.callback) {
23
- this.callback(null, result.code, result.map)
24
- return
21
+ const languages = (options && Array.isArray(options.languages)) ? options.languages : null
22
+
23
+ // 2. 处理适配器自身的 index.js (按需打包语言包)
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
40
+ }
41
+
42
+ // 3. 处理 Monaco Editor 源代码 (注入本地化逻辑)
43
+ if (isMonaco) {
44
+ const result = transform(source, this.resourcePath, options || {})
45
+
46
+ // 如果返回包含 SourceMap 的对象,则使用 this.callback 提示 Webpack
47
+ if (result && typeof result === 'object') {
48
+ if (this.callback) {
49
+ this.callback(null, result.code, result.map)
50
+ return
51
+ }
52
+ return result.code
25
53
  }
26
- return result.code
54
+ return result
27
55
  }
28
56
 
29
- return result
57
+ return source
30
58
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monaco-editor-nls-adapter",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "description": "Multi-language NLS adapter for Monaco Editor 0.50.0+ (Self-hosted)",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
package/vite-plugin.js CHANGED
@@ -1,25 +1,50 @@
1
1
  const { transform } = require('./transform')
2
+ const { generateLocalesCode } = require('./codegen')
2
3
 
3
4
  /**
4
5
  * Vite Plugin for Monaco Editor NLS Adapter
5
6
  * @param {Object} options 插件配置
6
7
  * @param {string} options.monacoPath 匹配 Monaco Editor ESM 路径的特征字符串,默认为 'monaco-editor/esm'
8
+ * @param {string[]} options.languages 需要包含的语言包列表 (如 ['zh-hans', 'en'])。不传则全量打包。
7
9
  */
8
10
  function monacoNlsPlugin(options = {}) {
9
11
  const monacoRoot = options.monacoPath || 'monaco-editor/esm'
10
-
12
+ const languages = Array.isArray(options.languages) ? options.languages : null
13
+
11
14
  return {
12
15
  name: 'vite-plugin-monaco-nls-adapter',
13
16
  enforce: 'pre',
14
17
  transform(code, id) {
15
- // 极致性能优化:第一层极速过滤,避免非目标文件的正则与替换开销
16
- if (!id.endsWith('.js') || id.indexOf('monaco-editor') === -1) return
18
+ if (!id.endsWith('.js')) return
17
19
 
18
20
  // 统一路径格式
19
21
  const normalizedId = id.replace(/\\/g, '/')
20
-
21
- // 快速过滤非目标文件 (进一步细化)
22
- if (normalizedId.includes(monacoRoot)) {
22
+
23
+ // 1. 处理适配器自身的 index.js (按需打包语言包)
24
+ if (languages && (normalizedId.endsWith('monaco-editor-nls-adapter/index.js') || normalizedId.endsWith('monaco-editor-nls-adapter/index.ts'))) {
25
+ let newCode = code
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
+ // 注意:index.js 中的 import 是带注释的: import(/* webpackChunkName: "nls-[request]" */ `./locales/${targetLocale}.json`)
37
+ newCode = newCode.replace(/import\(.*?\`\.\/locales\/\$\{targetLocale\}\.json\`\)/g, asyncCode)
38
+ }
39
+
40
+ return {
41
+ code: newCode,
42
+ map: null // 对于这种简单的替换,暂不生成 sourcemap 以保持性能
43
+ }
44
+ }
45
+
46
+ // 2. 处理 Monaco Editor 源代码 (注入本地化逻辑)
47
+ if (normalizedId.indexOf('monaco-editor') !== -1 && normalizedId.includes(monacoRoot)) {
23
48
  const result = transform(code, id, options)
24
49
 
25
50
  // 如果 transform 返回的是对象 ({ code, map }),直接返回