LSP protocol

The x18n language server: standard features, settings and the custom x18n/* protocol.

@x18n/lsp is the language server that the VS Code extension uses. Any editor with an LSP client can run it:

pnpx x18n-lsp --stdio

The server also accepts --node-ipc and --socket=<port>. It loads the projects of each workspace folder, the same way the CLI does.

Standard features

The server treats keys as symbols. It supports go to definition, go to implementation, references, rename (with prepare), hover, inlay hints, completion of keys, code actions (quick fixes and extraction), document symbols, workspace symbols, code lenses and diagnostics. Diagnostics are the same as the ones from x18n check.

Initialization options

The client passes these fields in initializationOptions. Each one is optional.

interface Settings {
  annotationMaxLength: number
  displayLocale: string | undefined
  codeLens: boolean
}

Custom methods

Shapes follow the JSON contract version. Positions and ranges use LSP conventions: zero-based lines and UTF-16 characters.

MethodKindParamsResultDescription
x18n/projectsrequestProjectInfo[]The projects of the workspace.
x18n/keyAtrequestPositionParamsKeyAtResult | nullThe key or key prefix at a position, in code or in a locale file.
x18n/treerequestTreeParamsTreeNode[]One level of the key tree, with translation counts.
x18n/progressrequestProgressResultTranslation progress per project and locale.
x18n/fileKeysrequestDocumentParamsFileKeysResultThe keys and hard strings of one file.
x18n/usageReportrequestUsageReportResultUnused keys, and used keys that are not defined.
x18n/decorationsrequestDocumentParamsDecorationsResultThe ranges and values for in-place annotations in a source file.
x18n/setDisplayLocalenotification (client to server)SetDisplayLocaleParamsChanges the display locale. The server refreshes the inlay hints.
x18n/openUirequestOpenUiParamsOpenUiResultStarts the UI server for a project on loopback and returns its URL and a one-time auth token.
x18n/translatePromptrequestTranslatePromptParamsstringThe translate prompt for a locale, as markdown.
x18n/changednotification (server to client)ChangedParamsA project changed. keys lists the keys that changed.

Commands

The server runs these through workspace/executeCommand. The argument is one object. project defaults to the first project.

CommandArgumentDescription
x18n.set{ project?, key, locale?, value }Sets one value. locale defaults to the source locale.
x18n.delete{ project?, key, locale? }Deletes a key in one locale, or in all locales.
x18n.renamePrefix{ project?, key, to }Renames every key under a prefix, in locale files and code.
x18n.extract{ uri }Extracts every hard string of a file.
x18n.migrateI18nAlly{ uri }Returns the files that the migration from i18n-ally writes, as MigrationResult. Nothing is written.

Types

export interface Position {
  readonly line: number
  readonly character: number
}

export interface Range {
  readonly start: Position
  readonly end: Position
}

export interface Location {
  readonly uri: string
  readonly range: Range
}

export interface DocumentParams {
  readonly uri: string
}

export interface PositionParams extends DocumentParams {
  readonly position: Position
}

export interface ProjectInfo {
  readonly name: string
  readonly root: string
  readonly sourceLocale: string
  readonly locales: readonly { readonly code: string, readonly displayName: string | undefined, readonly flag: string | undefined }[]
  readonly displayLocale: string
  readonly keys: number
}

export interface KeyAtResult {
  readonly project: string
  readonly key: string
  readonly type: 'key' | 'subtree'
  readonly range: Range
}

export interface TreeParams {
  readonly project?: string | undefined
  /** Parent key; omitted for the roots. */
  readonly parent?: string | undefined
}

export interface TreeNode {
  readonly key: string
  readonly label: string
  readonly leaf: boolean
  readonly translated: number
  readonly total: number
  /** Display-locale value for leaves. */
  readonly value: string | undefined
}

export interface LocaleProgress {
  readonly locale: string
  readonly translated: number
  readonly total: number
  readonly missing: readonly string[]
  readonly empty: readonly string[]
}

export interface ProgressResult {
  readonly projects: readonly { readonly name: string, readonly locales: readonly LocaleProgress[] }[]
}

export interface FileKey {
  readonly key: string
  readonly range: Range
  readonly value: string | undefined
  readonly missing: boolean
  readonly dynamic: boolean
}

export interface FileKeysResult {
  readonly keys: readonly FileKey[]
  readonly hardStrings: readonly { readonly text: string, readonly range: Range }[]
}

export interface UsageReportResult {
  readonly unused: readonly { readonly project: string, readonly key: string, readonly location: Location | undefined }[]
  readonly missing: readonly { readonly project: string, readonly key: string, readonly locations: readonly Location[] }[]
}

export interface Decoration {
  readonly range: Range
  readonly key: string
  readonly value: string | undefined
  readonly state: 'ok' | 'missing' | 'dynamic'
}

export interface DecorationsResult {
  readonly locale: string
  readonly decorations: readonly Decoration[]
}

export interface SetDisplayLocaleParams {
  readonly locale: string | undefined
}

export interface OpenUiParams {
  readonly project?: string | undefined
}

export interface OpenUiResult {
  readonly url: string
  readonly token: string
}

export interface TranslatePromptParams {
  readonly project?: string | undefined
  readonly locale: string
  readonly keys?: readonly string[] | undefined
}

export interface ChangedParams {
  readonly project: string
  readonly revision: number
  readonly keys: readonly string[]
}

export interface MigrationResult {
  readonly files: readonly MigrationFile[]
  /** What was dropped or needs attention, for the report. */
  readonly notes: readonly string[]
  /** i18n-ally settings that can be removed after the migration. */
  readonly removable: readonly string[]
}

export interface MigrationFile {
  /** Path relative to the project root. */
  readonly path: string
  readonly content: string
}