diff --git a/conformance/fixtures/v1/68-locale-param.json b/conformance/fixtures/v1/68-locale-param.json new file mode 100644 index 0000000..c3dd027 --- /dev/null +++ b/conformance/fixtures/v1/68-locale-param.json @@ -0,0 +1,12 @@ +{ + "name": "locale-param", + "description": "check and compile accept an optional string locale. The demo language has no locale-dependent text, so the result equals the no-locale result; a provider with locale-dependent text may differ. A locale that is not a string is rejected with -32602.", + "scope": "semantics", + "session": "1.0", + "steps": [ + {"request":{"id":2,"method":"lpp/check","params":{"documents":{"file:///project/puzzle.xdl":{"uri":"file:///project/puzzle.xdl","languageId":"x-demo-lang","version":3,"text":"puzzle clean {\n target = 40\n start = 10\n ops {\n double: x => x * 2\n plus1: x => x + 1\n }\n solution = [ double, double ]\n}"}},"locale":"en-US","projectRoot":"file:///project"}},"expectResponse":{"result":{"documents":[{"uri":"file:///project/puzzle.xdl","version":3,"diagnostics":[]}]}}}, + {"request":{"id":3,"method":"lpp/compile","params":{"documents":{"file:///project/puzzle.xdl":{"uri":"file:///project/puzzle.xdl","languageId":"x-demo-lang","version":3,"text":"puzzle clean {\n target = 40\n start = 10\n ops {\n double: x => x * 2\n plus1: x => x + 1\n }\n solution = [ double, double ]\n}"}},"locale":"zh-CN"}},"expectResponse":{"result":{"diagnostics":[{"uri":"file:///project/puzzle.xdl","version":3,"diagnostics":[]}],"artifact":{"format":"x-demo/puzzle-eval-v1","content":"{\"name\":\"clean\",\"ops\":[{\"arg\":2,\"name\":\"double\",\"op\":\"*\"},{\"arg\":1,\"name\":\"plus1\",\"op\":\"+\"}],\"solution\":[\"double\",\"double\"],\"start\":10,\"target\":40,\"value\":40}"}}}}, + {"request":{"id":4,"method":"lpp/check","params":{"documents":{"file:///project/puzzle.xdl":{"uri":"file:///project/puzzle.xdl","languageId":"x-demo-lang","version":3,"text":"puzzle clean {\n target = 40\n start = 10\n ops {\n double: x => x * 2\n plus1: x => x + 1\n }\n solution = [ double, double ]\n}"}},"locale":5}},"expectResponse":{"error":{"code":-32602,"message":{"$provider":"nonEmptyString"}}}}, + {"request":{"id":5,"method":"lpp/compile","params":{"documents":{"file:///project/puzzle.xdl":{"uri":"file:///project/puzzle.xdl","languageId":"x-demo-lang","version":3,"text":"puzzle clean {\n target = 40\n start = 10\n ops {\n double: x => x * 2\n plus1: x => x + 1\n }\n solution = [ double, double ]\n}"}},"locale":["en-US"]}},"expectResponse":{"error":{"code":-32602,"message":{"$provider":"nonEmptyString"}}}} + ] +} diff --git a/conformance/mock-provider/src/wire.rs b/conformance/mock-provider/src/wire.rs index 19347a4..bb09ef3 100644 --- a/conformance/mock-provider/src/wire.rs +++ b/conformance/mock-provider/src/wire.rs @@ -48,6 +48,9 @@ pub(crate) struct DocsParams { pub entry: Option, #[allow(dead_code)] pub project_root: Option, + /// Validated as a string; the demo language has no locale-dependent text. + #[allow(dead_code)] + pub locale: Option, } #[derive(Deserialize)] diff --git a/docs/spec/analysis-and-compilation.md b/docs/spec/analysis-and-compilation.md index 59435d8..de3ec5e 100644 --- a/docs/spec/analysis-and-compilation.md +++ b/docs/spec/analysis-and-compilation.md @@ -21,6 +21,8 @@ analyze every document in the set and MUST report all diagnostics found. } ``` +`locale` is OPTIONAL; see [Section 8.3](project-loading.md#83-locale). + ### 9.2 Result ```json @@ -68,6 +70,7 @@ document-supplied request that contains more than one document. } ``` +* `locale`: OPTIONAL; see [Section 8.3](project-loading.md#83-locale). * `acceptedArtifactFormats`: OPTIONAL, defined in LPP 1.4 and later. A non-empty array of artifact format id strings, ordered from most to least preferred. It states which formats the client can consume; see diff --git a/docs/spec/conformance.md b/docs/spec/conformance.md index b5ec173..af29be9 100644 --- a/docs/spec/conformance.md +++ b/docs/spec/conformance.md @@ -80,8 +80,8 @@ Methods: | --- | --- | --- | --- | | `lpp/initialize` | none | `{ protocolVersion, clientInfo? }` | `{ protocolVersion, serverInfo, languages, capabilities }` | | `lpp/shutdown` | none | `{}` | `null` | -| `lpp/check` | `check`; plus `projectLoading` for an LPP 1.1+ `entry` request | `{ documents, projectRoot? }` or `{ entry, projectRoot? }` | `{ documents: [{ uri, version, diagnostics }] }` | -| `lpp/compile` | `compile`; plus `projectLoading` for an LPP 1.1+ `entry` request and `sourceIdentity` for an LPP 1.3+ entry result | `{ documents, projectRoot?, acceptedArtifactFormats? }` or `{ entry, projectRoot?, acceptedArtifactFormats? }` (`acceptedArtifactFormats`: LPP 1.4+) | `{ diagnostics: [{ uri, version, diagnostics }], sourceIdentity?, artifact }` | +| `lpp/check` | `check`; plus `projectLoading` for an LPP 1.1+ `entry` request | `{ documents, projectRoot?, locale? }` or `{ entry, projectRoot?, locale? }` | `{ documents: [{ uri, version, diagnostics }] }` | +| `lpp/compile` | `compile`; plus `projectLoading` for an LPP 1.1+ `entry` request and `sourceIdentity` for an LPP 1.3+ entry result | `{ documents, projectRoot?, locale?, acceptedArtifactFormats? }` or `{ entry, projectRoot?, locale?, acceptedArtifactFormats? }` (`acceptedArtifactFormats`: LPP 1.4+) | `{ diagnostics: [{ uri, version, diagnostics }], sourceIdentity?, artifact }` | | `lpp/reconstruct` | `reconstruct` | `{ artifact }` | `{ source, uri? }` | | `lpp/symbols` | `symbols` | `{ documents, projectRoot? }` | `{ documents: [{ uri, version, symbols }] }` | | `lpp/definition` | `definition` | `{ document, position }` | `{ locations }` | diff --git a/docs/spec/project-loading.md b/docs/spec/project-loading.md index ae7c0c1..d70f32b 100644 --- a/docs/spec/project-loading.md +++ b/docs/spec/project-loading.md @@ -133,6 +133,7 @@ Document-scoped methods share this parameter shape: | `entry` | Project entry | `check`, `compile` in LPP 1.1 and later | Alternative to `documents`; asks the provider to load the source closure from the selected entry or directory target. | | `document` | Document | `definition`, `references`, `validateEdits` | The single document to operate on. | | `projectRoot` | string, OPTIONAL | `check`, `compile`, `symbols`, `rename` | URI identifying the project the documents belong to. Purely informational in v1; providers MUST accept and MAY use it. | +| `locale` | string, OPTIONAL | `check`, `compile` | The Workshop client locale (for example `en-US` or `zh-CN`) for locale-dependent Workshop text. See [Section 8.3](#83-locale). | ### 8.1 Entry-based project requests (LPP 1.1 and later) @@ -215,3 +216,40 @@ MUST be rejected as `invalidEntry`; the provider MUST NOT perform directory entry selection. Any other `kind` value MUST also be rejected as `invalidEntry`. +### 8.3 Locale + +`locale` is an OPTIONAL string on `lpp/check` and `lpp/compile`, in both +`documents` and `entry` requests and in every protocol version. It names the +Workshop client locale (for example `"en-US"` or `"zh-CN"`) that selects the +spelling of locale-dependent Workshop text: the provider reads such spellings +in the source under that locale and writes them into the compile artifact under +that locale. It does not select the source language, which `languageId` +identifies. A provider without locale-dependent text MAY ignore the field. +`locale` follows the unknown-field rules of +[Section 19.1](errors-and-versioning.md#191-versioning-scheme) and needs no +capability. + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "method": "lpp/check", + "params": { + "entry": { "uri": "file:///project/main.opy", "languageId": "opy", "version": 7 }, + "locale": "zh-CN" + } +} +``` + +* A request without `locale` uses the provider's default locale. A client + with no locale to state SHOULD omit the field. The default is + provider-defined (the `opy` provider uses `en-US`). +* A `locale` value that is not a string is a schema violation and MUST produce + JSON-RPC `-32602`. +* The behavior for a locale string that the provider does not serve is + provider-defined, and this specification requires no specific outcome. The + `opy` provider reports an error-severity `locale-unsupported` diagnostic from + `lpp/compile`, with a `null` artifact. +* Non-normative: the `opy` provider judges locale-dependent spellings the same + way in `check` and `compile` for the same source and `locale`, and matches + locale tags case-insensitively. Matching rules are otherwise provider-defined.