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 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
- - Quick fixes: add missing / remove unused interpolation params on supported i18n calls, and create a missing key in every locale file that lacks it
12
- - Completion: suggest existing i18n keys with default locale text
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 key in a locale file (or a source usage), find every place the key is used across the project's source code
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
- | `packages` | array | `[]` | Optional monorepo package contexts. Each item needs a workspace-relative `root` and can override `defaultLocale`, `localeDirs`, and `inlayHints`. The language server picks the longest package root matching the currently edited file. |
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 `inlayHints` unless they override them.
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.11.1",
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
  }