Merge lang/i18nkeys (27024de) into lang/syntax: the vocabulary gains the text keys - the Key type, @TextKey (a registry's), the k"..." and kn"..." literals - and @Text's doc; docs/language pages for Key and @TextKey; ludic-dev syntax rewrote the grammars; reseeded, bootstrap-cfree fixpoint holds

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-30 00:02:48 +03:00
commit 9f8aec3bc1
63 changed files with 145288 additions and 114562 deletions

View file

@ -49,6 +49,7 @@ pack "assets"
| `app out` | where to write the bundle | `build/<name>.app` |
| `pack` | an asset root, repeatable | `assets/` if it exists |
| `maps` | where the maps' own tables are, one directory a map (`@PerMap` registries, LANGUAGE.md) - the compiler builds it into the program and `ludicc --check` reads every map under it | `assets/maps` |
| `lang` | the languages' directory and the source language (`lang "assets/lang" en`): the compiler checks every text key against `<dir>/<source>.po` (LANGUAGE.md, Text keys) | none: no key is checked |
Only `app name` is worth setting deliberately. The identifier is derived from the
package path when you omit it - `git.workshopsoft.io/workshopsoft/maroon-lake`

View file

@ -4,9 +4,9 @@ name: @Text
category: annotations
kind: annotation
tokens: @Text @Multiline
sig: @Text @Multiline field: string = ""
sig: @Text name: Key = null / @Text @Multiline blurb: string = ""
tip: Read by the player, so translated; and prose, edited over several lines.
order: 72
---
<code>@Text</code> marks a string the player reads, so it is translated; <code>@Multiline</code> says it is prose, edited as several lines rather than one.
<code>@Text</code> marks what the player reads, so it is translated. On a <code>Key</code> field a row that gives no value gets its derived key, <code>&lt;registry&gt;.&lt;row&gt;.&lt;field&gt;</code> (see <code>@TextKey</code>); English still written in a <code>@Text</code> row is counted as <code>english_left</code>. <code>@Multiline</code> says it is prose, edited as several lines rather than one.

View file

@ -0,0 +1,12 @@
---
id: annot-textkey
name: @TextKey
category: annotations
kind: annotation
tokens: @TextKey
sig: @TextKey("steps") registry StepKinds of StepKind from "steps.lres"
tip: The prefix of a registry's derived text keys, in place of its name in snake case.
order: 73
---
A registry's <code>@Text</code> fields are keyed <code>&lt;registry&gt;.&lt;row&gt;.&lt;field&gt;</code>, the registry's name in snake case (<code>GearKinds</code> is <code>gear_kinds</code>). <code>@TextKey("steps")</code> names the prefix instead, so its rows' keys are <code>steps.&lt;row&gt;.&lt;field&gt;</code>. Every derived key is checked against the source language's <code>.po</code> (LANGUAGE.md, Text keys).

View file

@ -0,0 +1,19 @@
---
id: type-key
name: Key
category: types
kind: type
tokens: Key
sig: k"module.purpose" / kn"module.purpose"
tip: A text key: it names a text and is not one - tr(key) makes the text.
order: 4
---
A `Key` names a text the player reads; its English lives in the source language's `.po`, like every other language's text. It is written `k"module.purpose"`, or `kn"..."` for a text with plural forms, against its quote. A `Key` is not a `string` and a `string` is not a `Key`: text is made with `tr(key)`, `trf(key, ...)` or, for a plural, `trn(kn"...", n, ...)`, and a key in a template literal's hole is an error. Keys compare with `==`, and with a `lang` line in `package.ludic` the compiler checks every one against the `.po`.
```ludic
# doc-check: skip — tr / trf / trn are ludic.i18n's
let title = tr(k"pause.resume")
let day = trf(k"hud.day", txt_num(n))
if key == k"pause.resume" { Screen.status(title) }
```