ek9_edit_localized_text
Rewrites the `defines text for "<locale>"` blocks of one text type in every locale that defines it (one atomic edit, so E07150 locale-completeness holds) and answers the editor envelope: status (applied | ready | would-fail | conflicts | error), written, edits[], summary, and translationDebt[] naming each {textType, locale, method} left placeholder-stubbed.
When to use it
'Add / change / remove a translatable text method or locale' is one call: pick mode (create-text-type, add-text-method, add-locale, update-text-method, remove-text-method, remove-locale) and name the textTypeName.
When not to use it
- Promoting a hard-coded string literal in EK9 source into a text method - use
ek9_extract_to_localized_text(it rewrites the call site too). - Authoring a `defines class`/`record`/etc. - text is a distinct construct kind; use
ek9_new_constructinstead. - A regular method on a class/trait/component — text methods are localized-string bodies, structurally different; use
ek9_add_methodinstead. - Changing an existing translated method's SIGNATURE — update-text-method rejects it (signature-change-not-allowed); do remove-text-method + add-text-method instead (
ek9_change_signaturecascades over type hierarchies, not locale groups). - Non-uniform locale coverage (one locale needs different params) — EK9 rejects this via E07150; author two separate text types by hand instead.
Details
Enforcement of per-text-type locale completeness is the distinguishing trait: adding a method to one locale without the others fires E07150, so create / add-text-method / add-locale / remove-text-method succeed across every locale defining the text type or block entirely; update-text-method is the only per-locale-subset mode (signature immutable); remove-locale is module-wide, blocking on literal-locale constructor calls and on would-orphan-text-type (escalation — last defining locale). Text methods can overload - when methodName matches >1 overload you MUST supply parameters or it blocks with method-ambiguous-supply-params (candidateOverloads[] lists signatures); locale identifiers must match [a-z]+(_[A-Z]+)?. Auto-stubbed bodies emit a two-line placeholder (`//AI: translate the message` + empty `""`) surfaced in translationDebt[], and update-text-method rewrites the whole method block, discarding in-body comments.
Arguments
| Argument | Type | Required | What it is |
|---|---|---|---|
includeTextTypes | array of string | For add-locale: limit the clone to these text types; omit for every text type referenceLocale defines. | |
locale | string | For remove-locale: the locale code to discontinue module-wide (e.g. fr, fr_FR, ja_JP) - every `defines text for "<locale>"` block matching it goes. | |
methodBodies | object | For add-text-method and update-text-method: locale -> body, e.g. {en_GB:'`Goodbye ${name}`', de:'`Auf Wiedersehen ${name}`'}; add-text-method stubs any locale left out, update-text-method leaves it alone. | |
methodName | string | For add-text-method: the new method's name; for update-text-method and remove-text-method: the existing method (supply parameters when the name is overloaded). | |
methods | array of object | For create-text-type: the text methods to author, each {name, parameters, body}. | |
mode | string: create-text-type | add-text-method | add-locale | update-text-method | remove-text-method | remove-locale | yes | Which operation to perform. |
module | string | The module to operate on. Default: the first module that defines any text type; supply it when several modules carry i18n. Derived from targetFile when that is given. | |
newLocale | string | For add-locale: the locale to bring up (e.g. fr_FR) - every text type in referenceLocale gets a block, placeholder-stubbed. | |
parameters | array of any | For add-text-method: the new method's parameters, 'name as Type' each; for update/remove-text-method: the overload to pick when methodName is ambiguous. | |
primaryLocale | string | For create-text-type: the locale whose bodies are authored (e.g. en_GB); every other supportedLocale gets a placeholder-stubbed body listed in translationDebt[]. | |
referenceLocale | string | For add-locale: the existing locale whose text types and method signatures the new locale clones. | |
supportedLocales | array of string | For create-text-type: every locale to define the text type in, primaryLocale included (e.g. ['en_GB','de']). | |
targetFile | string | Destination: the workspace-relative file the new text type lands in - required for create-text-type when no locale block exists yet. Optional for every other mode (they are workspace-wide and find the existing blocks through the module catalogue); supply it, or `module`, when the workspace has more than one module. | |
textTypeName | string | The text type (PascalCase) - the one to create for create-text-type, the existing one for add/update/remove-text-method; for add-locale and remove-locale see includeTextTypes / locale. |
It also takes the arguments every tool takes.
Recorded calls
Real calls, recorded against small projects and checked on every build - a changed answer fails it. 3 of the 17 recorded are shown.
Conflict unknown reference locale
Request
{
"mode" : "add-locale",
"newLocale" : "fr",
"referenceLocale" : "es_ES",
"targetFile" : "text.ek9"
}
Response
{
"conflicts" : [ {
"kind" : "reference-missing",
"reason" : "reference-locale-missing",
"suggestedRepair" : "Pick a referenceLocale that already contains the text types you want to clone"
} ],
"edits" : [ ],
"meta" : {
"serverMs" : "<timing>"
},
"risk" : {
"crossesModuleBoundary" : false,
"estimatedSeverity" : "trivial",
"fileCount" : 0,
"lineCount" : 0,
"touchesPublicApi" : false,
"touchesTests" : false
},
"status" : "conflicts",
"summary" : "Reference locale 'es_ES' contains no text types",
"workspaceHash" : "<workspace-hash>",
"wouldBeDiagnostics" : [ ],
"written" : false
}
Dirty overlay honoured
Request
{
"dirtyOverlay" : {
"<workspace-root>/text.ek9" : "#!ek9\ndefines module com.example.i18n\n\n defines text for \"en_GB\"\n WelcomePageText\n mainWelcome()\n \"Hello World\"\n\n defines text for \"de\"\n WelcomePageText\n mainWelcome()\n \"Hallo Welt\"\n\n//EOF\n"
},
"dryRun" : true,
"methodBodies" : {
"de" : "\"Hallo, neue Welt\""
},
"methodName" : "mainWelcome",
"mode" : "update-text-method",
"targetFile" : "text.ek9",
"textTypeName" : "WelcomePageText"
}
Response
{
"conflicts" : [ {
"kind" : "locale-mismatch",
"reason" : "locale-not-defined-for-text-type",
"suggestedRepair" : "Remove 'de' from methodBodies, or use add-locale to bring the text type into that locale first"
} ],
"edits" : [ ],
"meta" : {
"serverMs" : "<timing>"
},
"risk" : {
"crossesModuleBoundary" : false,
"estimatedSeverity" : "trivial",
"fileCount" : 0,
"lineCount" : 0,
"touchesPublicApi" : false,
"touchesTests" : false
},
"status" : "conflicts",
"summary" : "Locale 'de' does not define text type 'WelcomePageText'",
"workspaceHash" : "<workspace-hash>",
"wouldBeDiagnostics" : [ ],
"written" : false
}
Update text method dry run
Request
{
"dryRun" : true,
"methodBodies" : {
"de" : "\"Hallo, neue Welt\""
},
"methodName" : "mainWelcome",
"mode" : "update-text-method",
"targetFile" : "text.ek9",
"textTypeName" : "WelcomePageText"
}
Response
{
"conflicts" : [ ],
"edits" : [ {
"endLine" : 12,
"file" : "text.ek9",
"startLine" : 12,
"type" : "delete"
}, {
"after" : "\n mainWelcome()\n \"Hallo, neue Welt\"",
"endLine" : 11,
"file" : "text.ek9",
"startLine" : 11,
"type" : "replace"
} ],
"meta" : {
"serverMs" : "<timing>"
},
"risk" : {
"crossesModuleBoundary" : false,
"estimatedSeverity" : "trivial",
"fileCount" : 1,
"lineCount" : 2,
"touchesPublicApi" : false,
"touchesTests" : false
...
Cut short here: 7 more lines. The whole recorded call.
See also
- Show me in the IDE: Chapter 8: a text type, built