i18n-lens-language-server 0.11.1 → 0.13.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 +50 -5
- package/package.json +2 -1
- package/server/core.js +445 -104
- package/server/index.js +344 -73
package/README.md
CHANGED
|
@@ -8,10 +8,11 @@ Zed extension plus Language Server for Vue, TypeScript, TSX, JavaScript and JSX.
|
|
|
8
8
|
- Detect `$t`/`t`/`tc`/`$tc`/`i18n.t` calls, `v-t="'key'"`, `v-t="{ path: 'key' }"`, `<i18n-t keypath="key">` (Vue I18n), `<Trans i18nKey="key">` (react-i18next), and `formatMessage({ id: "key" })` (react-intl)
|
|
9
9
|
- Hover: show all locale values for a key
|
|
10
10
|
- Diagnostics: report missing keys, missing locale entries, mismatched interpolation params, and (on locale files) keys whose params differ across languages
|
|
11
|
-
-
|
|
12
|
-
-
|
|
11
|
+
- Optional raw-text diagnostics: flag likely untranslated Vue/HTML template text and selected user-facing attributes
|
|
12
|
+
- Quick fixes: add missing / remove unused interpolation params, and create missing keys in unambiguous JSON locale targets using versioned edits
|
|
13
|
+
- Completion: suggest existing i18n keys with default locale text only inside supported i18n key positions
|
|
13
14
|
- Definition: jump from a source key to its locale definition; when several locales define the key, pick which language file to open
|
|
14
|
-
- References: from a
|
|
15
|
+
- References: from a locale definition or source usage, find references within the same project/package context, including open source files not yet saved to disk
|
|
15
16
|
|
|
16
17
|
## Installation
|
|
17
18
|
|
|
@@ -68,6 +69,8 @@ To open a specific language file, use Go to Definition (Ctrl/Cmd+click or F12) o
|
|
|
68
69
|
|
|
69
70
|
Diagnostics refresh automatically when loaded locale files or locale directories change, so editing translation files should update warnings/errors without restarting the extension.
|
|
70
71
|
|
|
72
|
+
Open locale documents take precedence over disk contents. Opening, changing, or closing an existing locale file refreshes translations and diagnostics without requiring a save.
|
|
73
|
+
|
|
71
74
|
Diagnostics distinguish between these cases:
|
|
72
75
|
|
|
73
76
|
- If a key is missing from every loaded locale, it is reported as an error.
|
|
@@ -82,6 +85,41 @@ For example, if `order.pay_now` exists in `zh-CN` but is missing from `en-US`, t
|
|
|
82
85
|
Missing i18n key "order.pay_now" in locales: en-US
|
|
83
86
|
```
|
|
84
87
|
|
|
88
|
+
### Optional untranslated template text detection
|
|
89
|
+
|
|
90
|
+
Set `"rawTextDiagnostics": true` in `.zed/i18nlensrc.json` or under `lsp.i18n-lens.settings` to enable warnings with diagnostic code `raw-text`. It is **off by default**, works even without loaded locale files, and can be overridden per monorepo package.
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"rawTextDiagnostics": true
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
This first version uses `htmlparser2` to inspect HTML documents and the top-level HTML `<template>` of Vue single-file components:
|
|
99
|
+
|
|
100
|
+
- Literal text such as `<button>Save changes</button>`.
|
|
101
|
+
- Static `title`, `alt`, `placeholder`, `label`, and `aria-label` attributes.
|
|
102
|
+
- Whole, unescaped quoted literals on those bound attributes, such as `:placeholder="'Enter name'"` or `v-bind:title="'Helpful title'"`. Variables, translation calls, concatenations, template literals and other expressions are not evaluated.
|
|
103
|
+
|
|
104
|
+
The natural-language heuristics are inspired by i18n Ally's raw-string detection, but this is **not full Ally parity**. They recognize multi-word phrases, title-cased labels and non-Latin text, while ignoring numbers, punctuation, URLs, paths and obvious identifier-like tokens. Lowercase single words, acronyms, text split across elements and ambiguous labels may be missed; names or technical phrases can still produce false positives. Warnings are suggestions, not proof that text must be translated.
|
|
105
|
+
|
|
106
|
+
Comments, `script`/`style`, Vue custom blocks, interpolations (`{{ ... }}`), translation-component subtrees (`i18n-t`/`I18nT`, legacy `i18n`, `Trans`) and `v-t` elements are excluded. `code`/`pre`, `v-pre`, `v-html`, `v-text` and `translate="no"` subtrees are also skipped; use `translate="no"` to mark intentionally untranslated content. Vue templates using `src` or a non-HTML `lang` (such as Pug) are not inspected.
|
|
107
|
+
|
|
108
|
+
There is no Babel/JavaScript/TypeScript/JSX string analysis, workspace-wide scan, automatic extraction or raw-text quick fix. Only open Vue/HTML buffers receive these warnings. The parser is tolerant of incomplete markup, not a full Vue compiler; complex or malformed templates can be missed. Existing key/parameter diagnostics and quick fixes are unchanged.
|
|
109
|
+
|
|
110
|
+
For local development, HTML registration in `extension.toml` requires reinstalling the dev extension in Zed, then running `scripts/deploy-local.ps1` again and restarting the language server. Updating only the server does not register HTML buffers.
|
|
111
|
+
## Creating missing keys safely
|
|
112
|
+
|
|
113
|
+
The missing-key quick fix supports a single JSON file per locale and directory layouts such as `locales/en/common.json`. For `t('common.submit')`, it inserts `submit` into `common.json`, without duplicating the `common.` prefix. `index.json` has no file-stem prefix.
|
|
114
|
+
|
|
115
|
+
- Edits use the current open document text and version, preserve unrelated content and line endings, and change only the necessary text rather than replacing the entire file.
|
|
116
|
+
- If a target namespace file is missing, the server can create it when another locale establishes the corresponding JSON namespace layout. It does not invent an unknown namespace layout or overwrite a file that appears after the action was requested.
|
|
117
|
+
- Ambiguous layouts (for example, both `common.json` and `common.ts`, overlapping index/namespace ownership including empty namespace objects, or multiple backing directories) do not receive a guessed edit. Invalid JSON, duplicate properties, and scalar/object path conflicts are also refused.
|
|
118
|
+
- A multi-locale diagnostic receives a creation action only when all remaining missing locales can be repaired safely. TS/JS module writes and JSONC locale loading/writes are not supported.
|
|
119
|
+
- Quick fixes require LSP `workspace.workspaceEdit.documentChanges` support. Creating a file additionally requires the `create` resource operation. Existing-file edits use the open document version, or `null` for closed files; the server cannot version-check external changes to closed files.
|
|
120
|
+
|
|
121
|
+
Recognition skips calls inside comments and ordinary strings, and does not treat a concatenated key such as `t('prefix.' + name)` as a static key. Vue directive expressions, JSX expressions, and calls inside template-literal interpolations remain supported. Recognition is lexical, not full framework binding or scope analysis.
|
|
122
|
+
|
|
85
123
|
## Project configuration
|
|
86
124
|
|
|
87
125
|
I18n Lens supports two configuration sources:
|
|
@@ -155,7 +193,8 @@ Supported options:
|
|
|
155
193
|
| `localeDirs` | string[] | `src/locales`, `src/i18n`, `locales`, `i18n` | Workspace-relative directories to scan for locale files. In package configs, paths are relative to that package root. |
|
|
156
194
|
| `inlayHints.enabled` | boolean | `true` | Enables or disables inline translation hints from this language server. Hover, completion, definition, diagnostics, and quick fixes can still work when inline hints are disabled. |
|
|
157
195
|
| `inlayHints.maxLength` | number | `24` | Maximum inline hint label length before truncation. Hover still shows the full text. |
|
|
158
|
-
| `
|
|
196
|
+
| `rawTextDiagnostics` | boolean | `false` | Opt-in warnings for likely untranslated Vue/HTML template text and selected attributes. No automatic extraction. |
|
|
197
|
+
| `packages` | array | `[]` | Optional monorepo package contexts. Each item needs a workspace-relative `root` and can override `defaultLocale`, `localeDirs`, `inlayHints`, and `rawTextDiagnostics`. The language server picks the longest package root matching the currently edited file. |
|
|
159
198
|
|
|
160
199
|
Invalid or missing config values fall back to defaults. If `.zed/i18nlensrc.json` contains invalid JSON, the language server logs a warning and continues with the Zed settings or default config.
|
|
161
200
|
|
|
@@ -181,6 +220,8 @@ src/locales/ja-JP/common.json
|
|
|
181
220
|
|
|
182
221
|
A file named `common.json` contributes keys with the `common.` prefix. A file named `index.json` contributes keys without an `index.` prefix.
|
|
183
222
|
|
|
223
|
+
Top-level TS/JS modules such as `locales/en.ts` are also loaded, without adding an `en.` prefix. Directory modules such as `locales/en/common.ts` retain the `common.` prefix; `index.ts` has no file-stem prefix. Modules are parsed statically, never executed. Their definitions support Find References and cross-language parameter diagnostics, not source-code completions or inlay hints. TS/JS key positioning remains best-effort rather than a full syntax-tree analysis.
|
|
224
|
+
|
|
184
225
|
## Monorepo workspaces
|
|
185
226
|
|
|
186
227
|
For pnpm/turborepo and other monorepos, put `.zed/i18nlensrc.json` under the workspace root and add `packages` entries:
|
|
@@ -202,7 +243,9 @@ For pnpm/turborepo and other monorepos, put `.zed/i18nlensrc.json` under the wor
|
|
|
202
243
|
}
|
|
203
244
|
```
|
|
204
245
|
|
|
205
|
-
When a document is opened, I18n Lens selects the package whose `root` is the longest path prefix of that document. `localeDirs` inside a package are resolved relative to that package root, so `apps/web/src/locales` and `packages/admin/src/i18n` are indexed independently. Package entries inherit root-level `defaultLocale`, `localeDirs`, and `
|
|
246
|
+
When a document is opened, I18n Lens selects the package whose `root` is the longest path prefix of that document. `localeDirs` inside a package are resolved relative to that package root, so `apps/web/src/locales` and `packages/admin/src/i18n` are indexed independently. Package entries inherit root-level `defaultLocale`, `localeDirs`, `inlayHints`, and `rawTextDiagnostics` unless they override them.
|
|
247
|
+
|
|
248
|
+
Find References excludes separately configured nested package roots and locale modules, so identical keys in independent packages are not mixed. The existing source scanner is bounded at approximately 5,000 files; its results are not a project-wide completeness guarantee for larger workspaces.
|
|
206
249
|
|
|
207
250
|
## Local development
|
|
208
251
|
|
|
@@ -218,6 +261,8 @@ Run tests:
|
|
|
218
261
|
npm test
|
|
219
262
|
```
|
|
220
263
|
|
|
264
|
+
The suite covers pure-function behavior plus real stdio LSP sessions in temporary workspaces, including dirty locale buffers, namespace file creation, client capabilities, and package-isolated references.
|
|
265
|
+
|
|
221
266
|
The language server is published to npm as
|
|
222
267
|
[`i18n-lens-language-server`](https://www.npmjs.com/package/i18n-lens-language-server).
|
|
223
268
|
A Zed extension must not ship its language server, so the Rust shell installs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "i18n-lens-language-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Language server for configurable i18n inlay hints, hover, completion, diagnostics, definition, and references in Vue/TS/TSX/JS.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"start": "node server/index.js"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
+
"htmlparser2": "^10.1.0",
|
|
23
24
|
"vscode-languageserver": "^9.0.1",
|
|
24
25
|
"vscode-languageserver-textdocument": "^1.0.12"
|
|
25
26
|
}
|