narraleaf-studio 1.2.0 → 1.3.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/dist/_api.d.ts CHANGED
@@ -1707,6 +1707,17 @@ type BlueprintDiagnostic = {
1707
1707
  /** Source span or module location; M1 opaque */
1708
1708
  location?: Record<string, unknown>;
1709
1709
  };
1710
+ type LocaleCode = string;
1711
+ type LocalizationUnitStatus = "untranslated" | "machine" | "translated" | "reviewed";
1712
+ type LocalizationUnit = {
1713
+ /** Translated text; `{n}` placeholders map to the source segment's inline interpolations. */
1714
+ target: string;
1715
+ /** Hash of the source text at translation time (see shared/utils/localizationText). */
1716
+ sourceHash: string;
1717
+ status: LocalizationUnitStatus;
1718
+ /** Optional translator note. */
1719
+ note?: string;
1720
+ };
1710
1721
  type BlueprintAssetPinKind = "image" | "audio" | "font";
1711
1722
  type BlueprintAssetPinRef = {
1712
1723
  kind: BlueprintAssetPinKind;
@@ -2113,7 +2124,7 @@ type PluginBuildConfigFieldContribution = {
2113
2124
  /** A build that would ship without a value for this field is refused. */
2114
2125
  required?: boolean;
2115
2126
  };
2116
- type PluginContributes = {
2127
+ export type PluginContributes = {
2117
2128
  /** Blueprint node types this plugin provides (editor def + runtime execute). */
2118
2129
  blueprintNodes?: string[];
2119
2130
  /** Widget element types this plugin provides (editor module + runtime renderer). */
@@ -2219,6 +2230,40 @@ type PluginContributes = {
2219
2230
  * install - and the list shows them attributed to this plugin rather than quietly making room.
2220
2231
  */
2221
2232
  network?: string[];
2233
+ /**
2234
+ * The props of a contributed widget that hold words a player reads, by widget type.
2235
+ *
2236
+ * Each type named here must also be in {@link widgets}. A declared prop is treated as Studio's own
2237
+ * text and button labels are: the properties panel offers its words written directly or read
2238
+ * from a translation key, the canvas draws a key's words, the words go into the project's
2239
+ * translation table and exports, the project checks report a missing translation or key, and
2240
+ * the glyph check reads them. In the game the widget's renderer is handed the words already in
2241
+ * the player's language, in the prop it declared - it never resolves a key itself.
2242
+ *
2243
+ * Declared in the manifest rather than at registration because both entries need it - the
2244
+ * studio entry's widget is edited by it and the runtime entry's is drawn by it - and a
2245
+ * declaration only one of them made would be the half that drifts.
2246
+ */
2247
+ widgetText?: Record<string, PluginWidgetTextContribution[]>;
2248
+ };
2249
+ /**
2250
+ * One prop of a contributed widget whose value is words a player reads.
2251
+ *
2252
+ * `keyProp` is the prop the widget's translation key is kept in when the author reads the words from
2253
+ * one. It defaults to `<prop>LocalizationKey`, and it is the host's to write: the widget never reads it
2254
+ * to draw, because the words in `prop` already come from the key when there is one.
2255
+ */
2256
+ export type PluginWidgetTextContribution = {
2257
+ /** The prop holding the words. */
2258
+ prop: string;
2259
+ /** The prop the translation key is kept in; `<prop>LocalizationKey` when not declared. */
2260
+ keyProp?: string;
2261
+ /** What the properties panel calls the words. The prop name when not declared. */
2262
+ label?: string;
2263
+ /** `label` per editor locale, matched exactly as `localized` names are. */
2264
+ localized?: Record<string, string>;
2265
+ /** Whether the words may run over several lines; one line when not declared. */
2266
+ multiline?: boolean;
2222
2267
  };
2223
2268
  /**
2224
2269
  * The plugin's name and description in one editor language. Either may be left out, and the plain
@@ -2336,6 +2381,7 @@ export type RuntimePluginDescriptor = {
2336
2381
  type GameMenuLabel = {
2337
2382
  readonly key?: string | null;
2338
2383
  readonly text: string;
2384
+ readonly words?: string | null;
2339
2385
  };
2340
2386
  declare const GAME_MENU_DYNAMIC_SOURCES: readonly [
2341
2387
  "textLanguage",
@@ -2738,10 +2784,15 @@ type UIComponentParam = {
2738
2784
  id: string;
2739
2785
  /** What the author called it, shown in the instance's inspector. */
2740
2786
  name: string;
2741
- type: "string";
2742
- /** Used by an instance that has not overridden it, and by the definition's own preview. */
2787
+ type: UIComponentParamType;
2788
+ /**
2789
+ * Used by an instance that has not overridden it, and by the definition's own preview. For a
2790
+ * `text` parameter these are words written directly, translated through the definition's own unit
2791
+ * (`uiComponentParamUnitId(componentId, paramId)`).
2792
+ */
2743
2793
  defaultValue: string;
2744
2794
  };
2795
+ type UIComponentParamType = "string" | "text";
2745
2796
  type UIElement = {
2746
2797
  id: UIElementId;
2747
2798
  type: string;
@@ -2801,6 +2852,20 @@ type UIElementValueBinding = {
2801
2852
  | {
2802
2853
  kind: "listItemField";
2803
2854
  fieldId: string;
2855
+ }
2856
+ /**
2857
+ * Show the value one placement gives a text parameter of the component this element is part of.
2858
+ *
2859
+ * The component's counterpart of `listItemField`, and the same kind of read: no graph, nothing
2860
+ * kept alive - the value is taken from the placement being drawn (`resolveUIComponentTextParams`),
2861
+ * so the editing canvas draws each placement with its own words, and the game translates each
2862
+ * through the placement's own unit or reads the key it names. Only a text parameter answers one,
2863
+ * and only a widget's words take one; outside a placement (the component's own editor) the
2864
+ * element's own words are drawn, as sample text.
2865
+ */
2866
+ | {
2867
+ kind: "componentParam";
2868
+ paramId: string;
2804
2869
  };
2805
2870
  type UILayout = {
2806
2871
  x: number;
@@ -3849,7 +3914,7 @@ declare const en: {
3849
3914
  readonly table: {
3850
3915
  readonly storyLabel: "Source";
3851
3916
  readonly sourceUi: "Interface text";
3852
- readonly sourceKeys: "Named keys";
3917
+ readonly sourceKeys: "Translation keys";
3853
3918
  readonly modeTranslate: "Translate";
3854
3919
  readonly modeReview: "Review";
3855
3920
  readonly filterAll: "All";
@@ -3870,11 +3935,12 @@ declare const en: {
3870
3935
  readonly removeKey: "Remove key";
3871
3936
  readonly removeKeyConfirm: "Remove {name}?";
3872
3937
  readonly removeKeyConfirmDetail: "Existing translations of this key stay in the language files.";
3873
- readonly removeKeyUsedBy: "Used by:";
3938
+ readonly removeKeyWidgets: "These widgets keep the key's words and translations as their own:";
3939
+ readonly removeKeyBlueprints: "Blueprints that use the key:";
3874
3940
  readonly removeKeyUsedByElement: "{owner} \u25B8 {element}";
3875
3941
  readonly removeKeyUsedByBlueprint: "Blueprint \u201C{name}\u201D";
3876
3942
  readonly removeKeyUsedByMore: "and {count} more";
3877
- readonly removeKeyUsedByAfter: "Once the key is removed, the project check reports each of them.";
3943
+ readonly removeKeyUsedByAfter: "Once the key is removed, the project check reports each of these blueprints.";
3878
3944
  readonly sourceColumn: "Source";
3879
3945
  readonly targetColumn: "Translation";
3880
3946
  readonly targetPlaceholder: "Translate\u2026";
@@ -3996,6 +4062,18 @@ declare const en: {
3996
4062
  readonly findPlaceholder: "Find in lines";
3997
4063
  };
3998
4064
  };
4065
+ readonly textSourceMigration: {
4066
+ readonly message: {
4067
+ readonly one: "Interface text was upgraded. The words of {count} widget now come from a different source.";
4068
+ readonly other: "Interface text was upgraded. The words of {count} widgets now come from a different source.";
4069
+ };
4070
+ readonly place: "{n}. {owner} \u25B8 {element}: {change}";
4071
+ readonly marksKept: "now Direct, keeping its marks, and no longer uses the key {key}";
4072
+ readonly bindingDropped: "a binding that never showed was removed, and the key {key} shows";
4073
+ readonly missingKey: "the key {key} does not exist, so it is now Direct, with the same words and translations";
4074
+ readonly keyDiffered: "now Direct, keeping the words it showed, and no longer uses the key {key}";
4075
+ readonly locate: "Locate {n}";
4076
+ };
3999
4077
  readonly recovery: {
4000
4078
  readonly enter: "Open in recovery mode";
4001
4079
  readonly enterFailed: "Could not open recovery mode: {error}";
@@ -4205,7 +4283,7 @@ declare const en: {
4205
4283
  readonly liveCheckpointNone: "There was nothing uncommitted to record.";
4206
4284
  readonly livePendingOne: "1 change is waiting for the host.";
4207
4285
  readonly livePendingMany: "{count} changes are waiting for the host.";
4208
- readonly liveFrozenWhat: "The stories, the cast, the translations, the whole asset library - files included - and the project's own tables (the dictionary, the audio tracks, the asset sets, the variables, the named strings, the build variants, the DLC and the palette) are saved. Everything else here is current and read-only until the session ends.";
4286
+ readonly liveFrozenWhat: "The stories, the cast, the translations, the whole asset library - files included - and the project's own tables (the dictionary, the audio tracks, the asset sets, the variables, the translation keys, the build variants, the DLC and the palette) are saved. Everything else here is current and read-only until the session ends.";
4209
4287
  readonly liveUnavailableHere: "Unavailable in a live session.";
4210
4288
  readonly liveClaimsLabel: "Lines being written";
4211
4289
  readonly liveClaimOne: "{name} is writing 1 line.";
@@ -4407,6 +4485,7 @@ declare const en: {
4407
4485
  readonly runStatus: "Run status";
4408
4486
  readonly projectTrust: "Project trust";
4409
4487
  readonly studioTasks: "Background work";
4488
+ readonly problems: "Problems";
4410
4489
  readonly unsavedChanges: "Unsaved changes";
4411
4490
  readonly wordCount: "Story stats";
4412
4491
  readonly shortcuts: "Shortcuts and mouse actions";
@@ -4941,7 +5020,7 @@ declare const en: {
4941
5020
  readonly placeholder: "Search project\u2026";
4942
5021
  readonly titleBarPlaceholder: "Search in {name}";
4943
5022
  readonly building: "Building search index\u2026";
4944
- readonly idle: "Search scenes, characters, story text, assets and blueprints.";
5023
+ readonly idle: "Search scenes, characters, story text, interface text, assets and blueprints.";
4945
5024
  readonly empty: "No results";
4946
5025
  readonly more: "{count} more";
4947
5026
  readonly caseSensitive: "Match case";
@@ -4961,8 +5040,9 @@ declare const en: {
4961
5040
  readonly blueprint: "Blueprints";
4962
5041
  readonly asset: "Assets";
4963
5042
  readonly storyText: "Story Text";
5043
+ readonly uiText: "Interface Text";
4964
5044
  readonly variable: "Variables";
4965
- readonly uiTextKey: "UI Text Keys";
5045
+ readonly uiTextKey: "Translation Keys";
4966
5046
  readonly blueprintNode: "Blueprint Nodes";
4967
5047
  };
4968
5048
  readonly occurrences: "\u00D7{count}";
@@ -5866,6 +5946,7 @@ declare const en: {
5866
5946
  readonly cutPointTitle: "The {name} build ends at this line. No other build contains this line.";
5867
5947
  readonly cutPointInactive: "variant deleted";
5868
5948
  readonly cutPointInactiveTitle: "The variant this line ended has been deleted, so it ends nothing.";
5949
+ readonly problem: "{message} ({rule})";
5869
5950
  readonly tempSpeaker: "name only";
5870
5951
  readonly createCharacter: "Create character \u201C{name}\u201D";
5871
5952
  readonly createCharacterUnavailable: "Unavailable in a live session. Choose an existing character.";
@@ -6646,7 +6727,7 @@ declare const en: {
6646
6727
  };
6647
6728
  };
6648
6729
  readonly storyInspector: {
6649
- readonly textId: "Localization key";
6730
+ readonly textId: "Unit ID";
6650
6731
  readonly advanced: "Advanced";
6651
6732
  readonly advancedParams: "Advanced params";
6652
6733
  readonly noVariablesDeclared: "No variables declared";
@@ -7864,6 +7945,7 @@ declare const en: {
7864
7945
  readonly goTo: "Go to {target}";
7865
7946
  readonly goToNth: "Go to {target} ({n})";
7866
7947
  readonly goToConnected: "Go to connected node";
7948
+ readonly name: "Wire from {from} to {to}";
7867
7949
  };
7868
7950
  readonly crossProject: {
7869
7951
  readonly pasted: {
@@ -7965,7 +8047,7 @@ declare const en: {
7965
8047
  readonly noRuntime: "Node \"{node}\": no runtime for type \"{type}\".";
7966
8048
  readonly inputMissing: "\"{node}\" has nothing connected to \"{pin}\".";
7967
8049
  readonly stepLimit: "\"{head}\" stopped at \"{node}\" after {steps} steps without a wait.";
7968
- readonly stepLimitGlobal: "\"{head}\" in the global blueprint stopped at \"{node}\" after {steps} steps without a wait.";
8050
+ readonly stepLimitGlobal: "\"{head}\" in App logic stopped at \"{node}\" after {steps} steps without a wait.";
7969
8051
  readonly unknownType: "Node \"{node}\": unknown type \"{type}\". Its plugin may be uninstalled or disabled.";
7970
8052
  readonly variableIdInvalid: "Node \"{node}\": pick a variable.";
7971
8053
  readonly persistentVariableIdInvalid: "Node \"{node}\": pick a persistent variable.";
@@ -9263,6 +9345,7 @@ declare const en: {
9263
9345
  readonly toggle: "Toggle";
9264
9346
  readonly toggleDialogDisplay: "Toggle Dialog Display";
9265
9347
  readonly toggleSwitch: "Toggle Switch";
9348
+ readonly translationKeyText: "Translation Key Text";
9266
9349
  readonly trim: "Trim";
9267
9350
  readonly trimEnd: "Trim End";
9268
9351
  readonly trimStart: "Trim Start";
@@ -9302,6 +9385,7 @@ declare const en: {
9302
9385
  readonly getTotalPlaytime: "Get Total Playtime";
9303
9386
  };
9304
9387
  readonly nodeDescription: {
9388
+ readonly getComponentParam: "The value this placement sets for the chosen parameter, or the parameter's default when it sets none. A Text parameter that reads from a translation key gives the key's name; Translation Key Text gives its words.";
9305
9389
  readonly compareEqual: "True when A and B are the same value of the same type. The number 1 and the text \"1\" are not equal.";
9306
9390
  readonly compareNotEqual: "True when A and B differ in value or in type. The number 1 and the text \"1\" count as different.";
9307
9391
  readonly compareGreaterThan: "True when A is greater than B. Both sides are compared as numbers; a side that cannot be read as a number gives false.";
@@ -9316,7 +9400,11 @@ declare const en: {
9316
9400
  readonly gameReady: "Runs when the game is ready, before any story starts and before the first screen shows; the screen waits for it to finish. Runs before App Boot, and can run again when a game is started or loaded.";
9317
9401
  readonly goBack: "Closes the current page and returns to the page beneath it. On the bottom page it does nothing.";
9318
9402
  readonly replacePage: "Opens a page in place of the current page, and closes the current page. Go back and Go Page set to None do not return to it.";
9319
- readonly isGameOverlay: "True when this page, layer or Game UI is shown over a running game. In the global blueprint, true while a page or a modal layer covers the story.";
9403
+ readonly isGameOverlay: "True when this page, layer or Game UI is shown over a running game. In App logic, true while a page or a modal layer covers the story.";
9404
+ readonly localizationGetText: "Gets a translation key's text in the player's current language, or its source text when that language has no translation. A key that does not exist gives its name. Translation Key Text gives the same text and can also be used in Blueprint Value and functions.";
9405
+ readonly translationKeyText: "A translation key's text in the player's current language, or its source text when that language has no translation. A key that does not exist gives its name. The same text as Get Text, and also usable in Blueprint Value and functions. A Blueprint Value that shows it updates when the player changes language.";
9406
+ readonly format: "Replaces the placeholders in Template with values: {0}, {1} and so on with the items of an array, {name} with the field of that name in an object. A placeholder with no value becomes empty. A translated template comes from Translation Key Text.";
9407
+ readonly formatText: "Replaces {0}, {1} and so on in Text with the items of Values. Format does the same, also fills {name} from an object, and can be used in Blueprint Value and functions.";
9320
9408
  };
9321
9409
  readonly live: {
9322
9410
  readonly nodeClaimed: "{name} is editing this node";
@@ -9721,6 +9809,12 @@ declare const en: {
9721
9809
  readonly remove: "Remove param";
9722
9810
  readonly namePlaceholder: "Name";
9723
9811
  readonly defaultPlaceholder: "Default";
9812
+ readonly type: "Type";
9813
+ readonly typeString: "String";
9814
+ readonly typeText: "Text";
9815
+ readonly bindLabel: "Parameter";
9816
+ readonly bindNone: "No parameter";
9817
+ readonly bindMissing: "Missing parameter";
9724
9818
  };
9725
9819
  readonly binding: {
9726
9820
  readonly notReady: "Blueprint not ready for this control.";
@@ -10237,8 +10331,8 @@ declare const en: {
10237
10331
  readonly createGameUi: "Create Game UI";
10238
10332
  readonly globalSubtitle: "Global";
10239
10333
  readonly blueprintType: "Blueprint";
10240
- readonly openGlobalBlueprint: "Open global blueprint";
10241
- readonly globalBlueprintUnavailable: "Global blueprint unavailable";
10334
+ readonly openGlobalBlueprint: "Open App logic";
10335
+ readonly globalBlueprintUnavailable: "App logic unavailable";
10242
10336
  readonly openSurface: "Open {label}";
10243
10337
  readonly renameSurface: "Rename {label}";
10244
10338
  readonly duplicateSurface: "Duplicate {label}";
@@ -10368,6 +10462,7 @@ declare const en: {
10368
10462
  readonly widgetRenderFailed: "Widget failed to draw";
10369
10463
  readonly wordsFromRowField: "These words come from the list row field \u201C{field}\u201D.";
10370
10464
  readonly wordsFromBlueprintValue: "These words come from the blueprint value \u201C{name}\u201D.";
10465
+ readonly wordsFromComponentParam: "These words come from the component parameter \u201C{param}\u201D, set on each placement.";
10371
10466
  };
10372
10467
  readonly editor: {
10373
10468
  readonly componentNotFound: "Component not found";
@@ -10598,14 +10693,22 @@ declare const en: {
10598
10693
  readonly hint: "Shown in the editor only. The game shows the story's current line.";
10599
10694
  readonly bindingNoEffect: "This binding has no effect in the {slot} slot.";
10600
10695
  readonly removeBinding: "Remove";
10696
+ readonly hintBlueprintValue: "Shown in the editor only. The game shows the Blueprint Value's result.";
10697
+ readonly hintComponentParam: "Shown while editing the component only. Each placement shows the value it sets for the parameter.";
10698
+ };
10699
+ readonly textWriters: {
10700
+ readonly title: "Written in the game by";
10701
+ readonly entry: "{blueprint} \u203A {node}";
10702
+ readonly count: "\u00D7{count}";
10703
+ readonly defaultValue: "Default value";
10704
+ readonly defaultValueHint: "The game shows this text until one of the blueprints below writes to it.";
10601
10705
  };
10602
10706
  readonly localization: {
10603
10707
  readonly direct: "Direct";
10604
10708
  readonly translationKey: "Translation key";
10605
- readonly noSourceLanguage: "The project has no source language";
10606
10709
  readonly none: "None";
10607
10710
  readonly createKey: "Create new key\u2026";
10608
- readonly createKeyTitle: "New localization key";
10711
+ readonly createKeyTitle: "New translation key";
10609
10712
  readonly keyName: "Key name";
10610
10713
  readonly keyNamePlaceholder: "menu.start\u2026";
10611
10714
  readonly keyNameHint: "Letters, digits, and dots/underscores/hyphens between them.";
@@ -10714,11 +10817,9 @@ declare const en: {
10714
10817
  readonly sectionColor: "Color";
10715
10818
  readonly sectionBehavior: "Behavior";
10716
10819
  readonly interactionDisabled: "Interaction disabled";
10717
- readonly localizeLabel: "Localize label";
10718
10820
  };
10719
10821
  readonly text: {
10720
10822
  readonly title: "Text";
10721
- readonly localizeText: "Localize text";
10722
10823
  };
10723
10824
  readonly textMarks: {
10724
10825
  readonly title: "Marks";
@@ -12157,6 +12258,7 @@ declare const en: {
12157
12258
  readonly voice: "Voice";
12158
12259
  readonly assets: "Assets";
12159
12260
  readonly console: "Console";
12261
+ readonly problems: "Problems";
12160
12262
  readonly storyMotion: "Story Motion";
12161
12263
  readonly dashboard: "Dashboard";
12162
12264
  readonly audioPreview: "Audio Preview";
@@ -13194,6 +13296,8 @@ declare const en: {
13194
13296
  readonly mirror: {
13195
13297
  readonly official: "official source";
13196
13298
  readonly change: "Change";
13299
+ readonly downloadFailed: "A file the build needed could not be downloaded. If this network reaches github.com slowly or not at all, choose a mirror for the build's downloads in Settings \u203A {section} and build again.";
13300
+ readonly certificateFailed: "The download's certificate could not be verified. That usually means a proxy, network accelerator or antivirus program on this computer is intercepting HTTPS; turning it off may fix this without a mirror.";
13197
13301
  };
13198
13302
  readonly preflight: {
13199
13303
  readonly "no-targets": "Select at least one platform and format.";
@@ -13506,185 +13610,209 @@ declare const en: {
13506
13610
  readonly description: "Nothing in the project references this asset";
13507
13611
  readonly message: "{asset} is not used anywhere";
13508
13612
  readonly messageIndexUnresolved: "Unused assets not listed: {location} points at an asset that cannot be identified";
13509
- readonly messageIndexUnreadable: "Unused assets not listed: {location} could not be read";
13613
+ readonly messageIndexUnreadable: "Unused assets not listed: which assets {location} uses could not be determined";
13510
13614
  readonly messageIndexNotBuilt: "Unused assets not listed: the project could not be scanned";
13615
+ readonly help: string;
13511
13616
  };
13512
13617
  readonly assetsMissing: {
13513
13618
  readonly title: "Missing asset";
13514
13619
  readonly description: "A reference names an asset the library no longer has";
13515
13620
  readonly message: "{location} references a missing asset";
13621
+ readonly help: string;
13516
13622
  };
13517
13623
  readonly assetsUnreadable: {
13518
13624
  readonly title: "Unreadable asset";
13519
13625
  readonly description: "The file cannot be read or decoded";
13520
- readonly message: "{asset} cannot be decoded";
13626
+ readonly message: "{asset} is damaged or is not in a format Studio can open";
13521
13627
  readonly messageMissingBytes: "{asset} cannot be read from disk";
13628
+ readonly help: string;
13522
13629
  };
13523
13630
  readonly assetsOversized: {
13524
13631
  readonly title: "Large file";
13525
13632
  readonly description: "A file a build carries that is over the size this project allows";
13526
13633
  readonly message: "{asset} is {size}, over the {limit} a build should carry";
13634
+ readonly help: string;
13527
13635
  };
13528
13636
  readonly assetsGroupIncomplete: {
13529
13637
  readonly title: "Unfinished asset set";
13530
13638
  readonly description: "A set that does not resolve to exactly one file for every variant it declares";
13531
13639
  readonly message: "{set} has no file for {variant}";
13532
13640
  readonly messageAmbiguous: "{set} has {count} files for {variant}";
13533
- readonly messageResidency: "{set} resolves {axis} while the game runs, inside {outerAxis}, which the build resolves";
13534
- readonly messageDeclaration: "{set} declares no variants to resolve";
13535
- readonly messageFallback: "{set} does not say which variant the others fall back to";
13536
- };
13537
- readonly portabilityAssetName: {
13538
- readonly title: "Unsafe file name";
13539
- readonly description: "Characters or names some filesystems reject";
13540
- readonly message: "{asset} cannot be written on every platform";
13541
- };
13542
- readonly portabilityCaseCollision: {
13543
- readonly title: "Case collision";
13544
- readonly description: "Names that differ only by letter case";
13545
- readonly message: "{asset} collides with {other} on case-insensitive filesystems";
13641
+ readonly messageResidency: "{set} varies by variant and sits under a set that varies by language, which no build can resolve";
13642
+ readonly messageDeclaration: "{set} declares no values to resolve";
13643
+ readonly messageFallback: "{set} does not say which value the others fall back to";
13644
+ readonly help: string;
13546
13645
  };
13547
13646
  readonly portabilityMediaFormat: {
13548
13647
  readonly title: "Unplayable format";
13549
13648
  readonly description: "A codec some selected build targets cannot play";
13550
13649
  readonly message: "{asset} does not play on {platform}";
13650
+ readonly help: string;
13551
13651
  };
13552
13652
  readonly portabilityVfxAlpha: {
13553
13653
  readonly title: "Transparent overlay clip";
13554
13654
  readonly description: "An overlay clip whose transparency some selected build targets ignore";
13555
13655
  readonly message: "{asset} covers the stage on {platform}";
13656
+ readonly help: string;
13556
13657
  };
13557
13658
  readonly networkFetchNotAllowlisted: {
13558
13659
  readonly title: "Address not on the allowlist";
13559
13660
  readonly description: "A Fetch node aimed at an address this project does not allow";
13560
13661
  readonly message: "{url} is not on this project's network request allowlist";
13662
+ readonly help: string;
13561
13663
  };
13562
13664
  readonly networkFetchDisallowed: {
13563
13665
  readonly title: "Network node without network access";
13564
13666
  readonly description: "A network node in a project whose network policy is off";
13565
13667
  readonly message: "{blueprint} makes a network request, which this project does not allow";
13668
+ readonly help: string;
13566
13669
  };
13567
13670
  readonly storyUnreadable: {
13568
13671
  readonly title: "Unreadable story";
13569
13672
  readonly description: "A story document this Studio cannot open";
13673
+ readonly help: string;
13570
13674
  };
13571
13675
  readonly storyInvalidCommand: {
13572
13676
  readonly title: "Invalid command";
13573
13677
  readonly description: "A row the compiler refuses";
13574
13678
  readonly message: "This row does not compile";
13679
+ readonly help: string;
13575
13680
  };
13576
13681
  readonly storyGotoMissing: {
13577
13682
  readonly title: "Missing label";
13578
13683
  readonly description: "A goto naming a label the scene does not declare";
13579
13684
  readonly message: "Jumps to {label}, which this scene never declares";
13685
+ readonly messageEmpty: "Names no label to go to";
13686
+ readonly help: string;
13580
13687
  };
13581
13688
  readonly storyLabelDuplicate: {
13582
13689
  readonly title: "Duplicate label";
13583
13690
  readonly description: "Two declarations of one label; only the first is reached";
13584
- readonly message: "{label} is already declared above, so this one is never reached";
13691
+ readonly message: "{label} is already declared above, so every /goto to it lands there and not here";
13692
+ readonly help: string;
13585
13693
  };
13586
13694
  readonly storyLabelUnused: {
13587
13695
  readonly title: "Unused label";
13588
13696
  readonly description: "A label nothing jumps to";
13589
13697
  readonly message: "Nothing jumps to {label}";
13698
+ readonly help: string;
13590
13699
  };
13591
13700
  readonly storyJumpMissing: {
13592
13701
  readonly title: "Missing scene";
13593
13702
  readonly description: "A jump naming a scene the project does not have";
13594
- readonly message: "Jumps to a scene the story no longer has";
13703
+ readonly message: "The target scene is not set, or is not in this story";
13704
+ readonly help: string;
13595
13705
  };
13596
13706
  readonly storyEmptyChoice: {
13597
13707
  readonly title: "Empty choice";
13598
13708
  readonly description: "A choice with nothing the player can pick";
13599
13709
  readonly message: "This choice has no options";
13600
13710
  readonly messageEmptyOption: "This option has no text";
13711
+ readonly help: string;
13601
13712
  };
13602
13713
  readonly storyDeadEnd: {
13603
13714
  readonly title: "Dead end";
13604
13715
  readonly description: "A scene that leaves on some paths and reaches its end on another";
13605
13716
  readonly message: "Play runs off the end of the scene here";
13717
+ readonly help: string;
13606
13718
  };
13607
13719
  readonly storyCallCycle: {
13608
13720
  readonly title: "Circular call";
13609
13721
  readonly description: "A returnable jump reaching a scene that can call its own back";
13610
13722
  readonly message: "Calls a scene that can call this one back";
13723
+ readonly help: string;
13611
13724
  };
13612
13725
  readonly storyUnreachableScene: {
13613
13726
  readonly title: "Unreachable scene";
13614
13727
  readonly description: "A scene nothing can reach from the start";
13615
13728
  readonly message: "Nothing reaches this scene";
13729
+ readonly help: string;
13616
13730
  };
13617
13731
  readonly storyEmptyScene: {
13618
13732
  readonly title: "Empty scene";
13619
13733
  readonly description: "A scene with no content";
13620
- readonly message: "This scene has no rows";
13734
+ readonly message: "This scene has no enabled rows";
13735
+ readonly help: string;
13621
13736
  };
13622
13737
  readonly storyAppTagUnknown: {
13623
13738
  readonly title: "Unknown build variant";
13624
13739
  readonly description: "A row compared with a variant the project does not have";
13625
- readonly message: "No build variant is named \"{name}\", so this row is in no build";
13740
+ readonly message: "No build variant is named \"{name}\", so this comparison has the same result in every build";
13741
+ readonly help: string;
13626
13742
  };
13627
13743
  readonly storyRowsAfterEnding: {
13628
13744
  readonly title: "Rows after an ending";
13629
13745
  readonly description: "Rows written after an /ending row in the same list, which never play";
13630
13746
  readonly message: "This row comes after an ending and is never played. Move it before the ending, or delete it";
13747
+ readonly help: string;
13631
13748
  };
13632
13749
  readonly storyQuitPageMissing: {
13633
13750
  readonly title: "Quit with no page";
13634
13751
  readonly description: "A /quit row that names no page, or one the project no longer has";
13635
- readonly message: "This row names no page, so the playthrough ends with nothing on screen";
13636
- readonly deleted: "This project has no page \"{page}\", so the playthrough ends with nothing on screen";
13752
+ readonly message: "This row names no page, so no page opens and the rows after it in this list never play";
13753
+ readonly deleted: "The page this row names is no longer in the project, so the playthrough ends with nothing on screen";
13754
+ readonly help: string;
13637
13755
  };
13638
13756
  readonly storyEndingNameDuplicate: {
13639
13757
  readonly title: "Two endings with one name";
13640
13758
  readonly description: "More than one ending sharing a display name";
13641
13759
  readonly message: "Another ending is also called \"{name}\". A screen listing endings shows the name twice";
13760
+ readonly help: string;
13642
13761
  };
13643
13762
  readonly storyCutPointOrphan: {
13644
13763
  readonly title: "Cut point with no variant";
13645
13764
  readonly description: "A cut point written while the project has no build variant";
13646
13765
  readonly message: "This project has no build variant, so this cut point ends nothing. Add a variant, or delete the row";
13766
+ readonly help: string;
13647
13767
  };
13648
13768
  readonly storyCutPointUnreachable: {
13649
13769
  readonly title: "Cut point out of reach";
13650
13770
  readonly description: "A cut point in a scene nothing can get to";
13651
13771
  readonly message: "Nothing can reach this scene, so this cut point never ends a build";
13772
+ readonly help: string;
13652
13773
  };
13653
13774
  readonly storyStageObjectMissing: {
13654
13775
  readonly title: "Missing stage object";
13655
13776
  readonly description: "A row acting on an object no row in the scene creates";
13656
- readonly message: "Nothing creates {object}, so this row has nothing to act on";
13657
- readonly messageCharacter: "Nothing brings {object} on stage, so this row has nothing to act on";
13777
+ readonly message: "No row in this scene creates {object}, so this row has nothing to act on";
13778
+ readonly messageCharacter: "No row in this scene brings {object} on stage, so this row has nothing to act on";
13779
+ readonly help: string;
13658
13780
  };
13659
13781
  readonly storyDeclaredNeverShown: {
13660
13782
  readonly title: "Unshown stage object";
13661
13783
  readonly description: "A create row declares an object no row shows";
13662
13784
  readonly message: "{object} is declared here and no row shows it";
13785
+ readonly help: string;
13663
13786
  };
13664
13787
  readonly storyStageObjectDuplicate: {
13665
13788
  readonly title: "Duplicate stage object";
13666
13789
  readonly description: "Two rows creating one stage name; the second reuses the first";
13667
13790
  readonly message: "{object} is already created above, so this row acts on that one";
13791
+ readonly help: string;
13668
13792
  };
13669
13793
  readonly storyVideoControlAfterEnd: {
13670
13794
  readonly title: "Video already finished";
13671
13795
  readonly description: "A row pausing, resuming, seeking or stopping a video after a play that waits for its end";
13672
13796
  readonly message: "{object} has already finished playing at this line; to continue while it plays, turn off \u201CWait for the video\u201D on its play row";
13797
+ readonly help: string;
13673
13798
  };
13674
13799
  readonly storyCharacterMissing: {
13675
13800
  readonly title: "Missing character";
13676
13801
  readonly description: "A row naming a character the project does not have";
13677
13802
  readonly message: "This row names a character the project does not have";
13803
+ readonly help: string;
13678
13804
  };
13679
13805
  readonly storyTransitionUnavailable: {
13680
13806
  readonly title: "Unavailable transition";
13681
13807
  readonly description: "A row naming a transition this version cannot play";
13682
13808
  readonly message: "The transition {transition} is not available, so this change plays as a cut";
13809
+ readonly help: string;
13683
13810
  };
13684
13811
  readonly storyBackgroundUnchanged: {
13685
13812
  readonly title: "Unchanged background";
13686
13813
  readonly description: "A row transitioning to the background already on screen";
13687
13814
  readonly message: "This background is already on screen, so the transition changes nothing";
13815
+ readonly help: string;
13688
13816
  };
13689
13817
  readonly blueprintReferenceMissing: {
13690
13818
  readonly title: "Missing target";
@@ -13696,40 +13824,47 @@ declare const en: {
13696
13824
  readonly messageChoice: "Names a choice that no longer exists";
13697
13825
  readonly messageEnding: "Names an ending that no longer exists";
13698
13826
  readonly messageCharacter: "Names a character that no longer exists";
13699
- readonly messageTextKey: "Names a text key the project does not declare";
13827
+ readonly messageTextKey: "Names a translation key the project does not declare";
13700
13828
  readonly messageDlc: "Names a DLC the project does not have";
13701
13829
  readonly messageInputAction: "Names an input action the project does not declare";
13830
+ readonly help: string;
13702
13831
  };
13703
13832
  readonly blueprintElementRefMissing: {
13704
13833
  readonly title: "Missing widget";
13705
13834
  readonly description: "A node bound to a widget the project no longer has";
13706
13835
  readonly message: "Bound to a widget that no longer exists";
13836
+ readonly help: string;
13707
13837
  };
13708
13838
  readonly blueprintFnTargetMissing: {
13709
13839
  readonly title: "Missing function";
13710
13840
  readonly description: "A Call Fn node whose function does not exist in its scope";
13711
13841
  readonly message: "Calls a function that does not exist in this scope";
13712
13842
  readonly messageNamed: "Calls {name}, which does not exist in this scope";
13843
+ readonly help: string;
13713
13844
  };
13714
13845
  readonly blueprintUnreachableNode: {
13715
13846
  readonly title: "Unreachable node";
13716
13847
  readonly description: "A node no entry point in its graph can reach";
13717
13848
  readonly message: "Nothing reaches this node, so it never runs";
13849
+ readonly help: string;
13718
13850
  };
13719
13851
  readonly blueprintDlcEntranceUnguarded: {
13720
13852
  readonly title: "Unguarded DLC entrance";
13721
- readonly description: "A Start Story into a DLC's story, with nothing asking whether the DLC is here";
13722
- readonly message: "Nothing in this graph asks whether the DLC is installed";
13853
+ readonly description: "A Start Game node starting a DLC's story, with nothing asking whether the DLC is installed";
13854
+ readonly message: "No Is DLC Installed in this layer asks about this story's DLC";
13855
+ readonly help: string;
13723
13856
  };
13724
13857
  readonly blueprintEmptyEvent: {
13725
13858
  readonly title: "Empty event";
13726
13859
  readonly description: "An event layer with nothing wired to run";
13727
13860
  readonly message: "This event runs nothing";
13861
+ readonly help: string;
13728
13862
  };
13729
13863
  readonly blueprintUnknownNode: {
13730
13864
  readonly title: "Unknown node type";
13731
13865
  readonly description: "A node whose type the project cannot load";
13732
13866
  readonly message: "{type} is not loaded, so this node will not run in the game";
13867
+ readonly help: string;
13733
13868
  };
13734
13869
  readonly blueprintAssembledAssetName: {
13735
13870
  readonly title: "Asset name assembled at run time";
@@ -13738,105 +13873,130 @@ declare const en: {
13738
13873
  readonly messageBinding: "\"{prop}\" on \"{element}\" is bound to an asset name assembled at run time (from \"{origin}\"). A game package carries only the assets whose names are written in the project, so nothing will be there in the released game. Choose the asset in the asset picker, or read one already chosen from a list row or a variable";
13739
13874
  readonly messageUnloadedNode: "\"{pin}\" on \"{node}\" receives an asset name from {origin}, which is not loaded, so the asset it names will not be in the released game. Install or switch on the plugin that provides this node type, then build again";
13740
13875
  readonly messageUnloadedNodeBinding: "\"{prop}\" on \"{element}\" is bound to an asset name from {origin}, which is not loaded, so the asset it names will not be in the released game. Install or switch on the plugin that provides this node type, then build again";
13741
- };
13742
- readonly uiUnlocalizedText: {
13743
- readonly title: "Unlocalized text";
13744
- readonly description: "Text written straight onto a widget in a project that has a second language";
13745
- readonly message: "{text} is not bound to a localization key";
13876
+ readonly help: string;
13746
13877
  };
13747
13878
  readonly uiPageUnreachable: {
13748
13879
  readonly title: "Unreachable page";
13749
13880
  readonly description: "A page nothing opens, embeds, or starts on";
13750
13881
  readonly message: "Nothing opens this page";
13882
+ readonly help: string;
13751
13883
  };
13752
13884
  readonly uiEmptyBehavior: {
13753
13885
  readonly title: "Button with no handler";
13754
13886
  readonly description: "A clickable widget nothing listens to";
13755
13887
  readonly message: "Nothing runs when this is clicked";
13888
+ readonly help: string;
13756
13889
  };
13757
13890
  readonly uiUnknownWidget: {
13758
13891
  readonly title: "Unknown widget type";
13759
13892
  readonly description: "A widget whose type the project cannot load";
13760
13893
  readonly message: "{type} is not loaded, so this widget will not be drawn in the game";
13894
+ readonly help: string;
13761
13895
  };
13762
13896
  readonly uiComponentMissing: {
13763
13897
  readonly title: "Missing component";
13764
13898
  readonly description: "An instance of a component the project does not have";
13765
13899
  readonly message: "This instance points at a component the project does not have";
13900
+ readonly help: string;
13766
13901
  };
13767
13902
  readonly uiFrameTargetMissing: {
13768
13903
  readonly title: "Missing embedded page";
13769
13904
  readonly description: "A Page widget embedding a page the project does not have";
13770
13905
  readonly message: "This Page widget embeds a page the project does not have";
13906
+ readonly help: string;
13771
13907
  };
13772
13908
  readonly uiFrameLoop: {
13773
13909
  readonly title: "Circular embedded page";
13774
13910
  readonly description: "A Page widget embedding a page that leads back to it";
13775
13911
  readonly message: "This Page widget embeds a page that leads back to it";
13912
+ readonly help: string;
13776
13913
  };
13777
13914
  readonly uiListItemFieldMissing: {
13778
13915
  readonly title: "Missing item field";
13779
13916
  readonly description: "A widget bound to an item field the list drawing it does not declare";
13780
13917
  readonly message: "This is bound to an item field the list does not declare, so every row shows the same value";
13918
+ readonly help: string;
13919
+ };
13920
+ readonly uiComponentParamMissing: {
13921
+ readonly title: "Missing text parameter";
13922
+ readonly description: "A widget in a component showing a parameter the component does not declare as text";
13923
+ readonly message: "This shows a parameter the component does not declare as text, so every placement shows no words here";
13924
+ readonly messageOutside: "This shows a component parameter but is not inside a component, so the game shows no words here";
13925
+ readonly help: string;
13781
13926
  };
13782
13927
  readonly uiListTextUntranslated: {
13783
13928
  readonly title: "Untranslated list content";
13784
13929
  readonly description: "Words written into a list's content in a project that has a second language";
13785
13930
  readonly message: "{text} and the rest of this list's content show as written in every language";
13931
+ readonly help: string;
13786
13932
  };
13787
13933
  readonly uiLocalizationKeyMissing: {
13788
- readonly title: "Missing localization key";
13934
+ readonly title: "Missing translation key";
13789
13935
  readonly description: "A widget reading its words from a key the project does not have";
13790
13936
  readonly message: "Reads its words from {key}, which the project does not have";
13937
+ readonly help: string;
13791
13938
  };
13792
13939
  readonly uiGestureAnsweredTwice: {
13793
13940
  readonly title: "Gesture answered twice";
13794
13941
  readonly description: "A widget with a pointer handler of its own, on a page whose action answers the same gesture";
13795
13942
  readonly message: "{action} on this page answers the same gesture this widget does, so both run";
13943
+ readonly help: string;
13796
13944
  };
13797
13945
  readonly blueprintSaveFieldEmpty: {
13798
13946
  readonly title: "Empty save field";
13799
13947
  readonly description: "A Save Game node that will run with a declared save field left empty";
13800
13948
  readonly message: "{field} is empty, so this save is written with its default instead";
13949
+ readonly help: string;
13801
13950
  };
13802
13951
  readonly blueprintRequiredInputUnwired: {
13803
13952
  readonly title: "Empty input";
13804
13953
  readonly description: "A node that will run with a required input left unconnected";
13805
13954
  readonly message: "{node} has nothing connected to {pin}";
13955
+ readonly help: string;
13806
13956
  };
13807
13957
  readonly blueprintStartSceneForeign: {
13808
13958
  readonly title: "Scene from another story";
13809
13959
  readonly description: "A Start Game node whose scene is not in the story it names";
13810
- readonly message: "This scene is in {owner}, not in {story}, so starting the game here stops it";
13960
+ readonly message: "This scene is in {owner}, not in {story}, so the game cannot start from it";
13961
+ readonly help: string;
13811
13962
  };
13812
13963
  readonly variablesUndeclared: {
13813
13964
  readonly title: "Undeclared variable";
13814
13965
  readonly description: "A variable used without a declaration";
13815
13966
  readonly message: "{variable} is used but never declared";
13967
+ readonly messageUnnamed: "This row uses a variable that is not declared anywhere";
13968
+ readonly help: string;
13816
13969
  };
13817
13970
  readonly variablesUnused: {
13818
13971
  readonly title: "Unused variable";
13819
13972
  readonly description: "A variable declared but never read or written";
13820
13973
  readonly message: "{variable} is declared but never used";
13974
+ readonly help: string;
13821
13975
  };
13822
13976
  readonly variablesNameCollision: {
13823
13977
  readonly title: "Variable name collision";
13824
13978
  readonly description: "One name declared in two places";
13825
13979
  readonly message: "{variable} is declared twice as a persistent variable";
13980
+ readonly messageSaved: "{variable} is declared twice as a saved variable";
13981
+ readonly help: string;
13826
13982
  };
13827
13983
  readonly variablesConditionNeverHolds: {
13828
13984
  readonly title: "Condition no path can satisfy";
13829
13985
  readonly description: "A condition whose variable can never reach the value it tests for";
13830
- readonly message: "{variable} is never more than {bound} here, so this condition cannot hold";
13986
+ readonly message: "{variable} is always within {bound} here, so this condition cannot hold";
13987
+ readonly messageUnnamed: "A variable with no declaration is always within {bound} here, so this condition cannot hold";
13988
+ readonly help: string;
13831
13989
  };
13832
13990
  readonly variablesReadNeverWritten: {
13833
13991
  readonly title: "Condition nothing can change";
13834
13992
  readonly description: "A variable a condition tests, that nothing in the project ever assigns";
13835
13993
  readonly message: "{variable} is tested by {conditions} but nothing ever sets it";
13994
+ readonly messageUnnamed: "A variable with no declaration is tested by {conditions} and nothing ever sets it";
13836
13995
  readonly conditionCount: {
13837
13996
  readonly one: "{count} condition";
13838
13997
  readonly other: "{count} conditions";
13839
13998
  };
13999
+ readonly help: string;
13840
14000
  };
13841
14001
  readonly variablesRandomOutsideAssignment: {
13842
14002
  readonly title: "Random outside an assignment";
@@ -13844,33 +14004,39 @@ declare const en: {
13844
14004
  readonly message: "{fn}() is re-rolled every time this condition is tested, so the branch can change between checks. Roll it once with /set, then test that variable";
13845
14005
  readonly messageChoiceOption: "{fn}() is re-rolled every time the menu draws, so this option flickers. Roll it once with /set, then test that variable";
13846
14006
  readonly messageInterpolation: "{fn}() is re-rolled every time this line draws, so the value changes on every redraw. Roll it once with /set, then show that variable";
14007
+ readonly help: string;
13847
14008
  };
13848
14009
  readonly textOverlong: {
13849
14010
  readonly title: "Overlong line";
13850
14011
  readonly description: "A line wider than the dialogue box holds";
13851
- readonly message: "{width} characters wide, over {max}";
14012
+ readonly message: "{width} columns wide, over {max}";
14013
+ readonly help: string;
13852
14014
  };
13853
14015
  readonly textEmpty: {
13854
14016
  readonly title: "Empty line";
13855
- readonly description: "A dialogue row with no text";
14017
+ readonly description: "A narration, dialogue or choice option row with no text";
13856
14018
  readonly message: "This line has no text";
14019
+ readonly help: string;
13857
14020
  };
13858
14021
  readonly localizationMissing: {
13859
14022
  readonly title: "Missing translation";
13860
14023
  readonly description: "A line or interface text with no translation in a target language";
13861
14024
  readonly message: "No {locale} translation";
13862
14025
  readonly messageInterface: "No {locale} translation of {text}";
14026
+ readonly help: string;
13863
14027
  };
13864
14028
  readonly localizationStale: {
13865
14029
  readonly title: "Stale translation";
13866
14030
  readonly description: "The source line changed after it was translated";
13867
14031
  readonly message: "{locale} translation is older than the line";
13868
14032
  readonly messageInterface: "{locale} translation of {text} is older than the text";
14033
+ readonly help: string;
13869
14034
  };
13870
14035
  readonly localizationMarkup: {
13871
14036
  readonly title: "Translation drops styling";
13872
- readonly description: "The line is styled and the translation renders it plainly";
13873
- readonly message: "{locale} translation does not carry this line's styling";
14037
+ readonly description: "The line has styling, pauses or inline events the translation does not carry";
14038
+ readonly message: "{locale} translation does not carry all of this line's styling, pauses and inline events";
14039
+ readonly help: string;
13874
14040
  };
13875
14041
  readonly localizationOrphan: {
13876
14042
  readonly title: "Orphan translation";
@@ -13880,16 +14046,19 @@ declare const en: {
13880
14046
  readonly one: "{count} {locale} translation";
13881
14047
  readonly other: "{count} {locale} translations";
13882
14048
  };
14049
+ readonly help: string;
13883
14050
  };
13884
14051
  readonly voiceMissing: {
13885
14052
  readonly title: "Missing voice";
13886
14053
  readonly description: "A line with no recording in a voiced language";
13887
14054
  readonly message: "No {locale} recording";
14055
+ readonly help: string;
13888
14056
  };
13889
14057
  readonly voiceStale: {
13890
14058
  readonly title: "Stale voice";
13891
14059
  readonly description: "The line changed after it was recorded";
13892
14060
  readonly message: "{locale} recording is older than the line";
14061
+ readonly help: string;
13893
14062
  };
13894
14063
  readonly voiceOrphan: {
13895
14064
  readonly title: "Orphan voice";
@@ -13899,13 +14068,15 @@ declare const en: {
13899
14068
  readonly one: "{count} {locale} recording";
13900
14069
  readonly other: "{count} {locale} recordings";
13901
14070
  };
14071
+ readonly help: string;
13902
14072
  };
13903
14073
  readonly brandBrokenLink: {
13904
14074
  readonly title: "Broken color link";
13905
14075
  readonly description: "A color pointing at a palette entry that resolves to nothing";
13906
- readonly message: "{where} uses {color}, which the palette does not have";
13907
- readonly messageChain: "{where} uses {color}, which links on to {missing}, a color the palette does not have";
14076
+ readonly message: "{where} uses a color the palette does not have";
14077
+ readonly messageChain: "{where} uses {color}, which follows a color the palette does not have";
13908
14078
  readonly messageCycle: "{where} uses {color}, whose links lead back to themselves";
14079
+ readonly help: string;
13909
14080
  };
13910
14081
  readonly typographyGlyphCoverage: {
13911
14082
  readonly title: "Missing glyphs";
@@ -13916,19 +14087,23 @@ declare const en: {
13916
14087
  readonly other: "{count} times";
13917
14088
  };
13918
14089
  readonly messageInLanguage: "No project font can draw \u201C{character}\u201D in {language} ({occurrences})";
14090
+ readonly messageInState: "No project font can draw \u201C{character}\u201D in the \u201C{state}\u201D state ({occurrences})";
14091
+ readonly messageInLanguageInState: "No project font can draw \u201C{character}\u201D in {language} in the \u201C{state}\u201D state ({occurrences})";
13919
14092
  readonly messageMore: "{characters} no project font can draw";
13920
14093
  readonly moreCharacterCount: {
13921
14094
  readonly one: "{count} more character";
13922
14095
  readonly other: "{count} more characters";
13923
14096
  };
13924
14097
  readonly messageMoreInLanguage: "{characters} no project font can draw in {language}";
13925
- readonly messageUnreadable: "{font} could not be read, so glyph coverage was not checked";
14098
+ readonly messageUnreadable: "{font} could not be read, so no character was checked";
13926
14099
  readonly messageUnloadable: "{font} is a .{format} font, which the game cannot draw with";
14100
+ readonly help: string;
13927
14101
  };
13928
14102
  readonly typographyLocaleNoFont: {
13929
14103
  readonly title: "Language with no font";
13930
14104
  readonly description: "A language every font of the project is restricted away from";
13931
- readonly message: "No project font is set for {language}";
14105
+ readonly message: "Every project font is limited to languages other than {language}";
14106
+ readonly help: string;
13932
14107
  };
13933
14108
  };
13934
14109
  readonly message: {
@@ -13974,6 +14149,22 @@ declare const en: {
13974
14149
  readonly showAll: "Show all {count}";
13975
14150
  readonly lineAria: "Line {line}";
13976
14151
  readonly findPlaceholder: "Find in problems";
14152
+ readonly scopeProject: "Whole project";
14153
+ readonly scopeOpenEditors: "Open editors";
14154
+ readonly scopeActiveEditor: "Current editor";
14155
+ readonly scopeAria: "Show problems from";
14156
+ readonly severityAria: "Severity";
14157
+ readonly groupAria: "Group";
14158
+ readonly emptyOpenEditors: "No problems in the open editors";
14159
+ readonly emptyActiveEditor: "No problems in the current editor";
14160
+ readonly emptyFiltered: "No problems at the selected severity";
14161
+ readonly explain: "About this rule";
14162
+ readonly settings: "Check settings";
14163
+ readonly rerunHint: "Check the whole project again, re-reading the asset files on disk";
14164
+ readonly jumpFailed: "This location can no longer be opened";
14165
+ };
14166
+ readonly statusBar: {
14167
+ readonly counts: "Problems: {errors}, {warnings}, {infos}";
13977
14168
  };
13978
14169
  readonly command: {
13979
14170
  readonly runProject: "Check project";
@@ -13996,6 +14187,7 @@ declare const en: {
13996
14187
  };
13997
14188
  readonly blockedHint: "Change this in Project \u25B8 Project \u25B8 Check before building";
13998
14189
  readonly skipped: "Project check skipped";
14190
+ readonly viewProblems: "View problems";
13999
14191
  };
14000
14192
  readonly settings: {
14001
14193
  readonly runOnBuild: "Check before building";
@@ -14005,6 +14197,8 @@ declare const en: {
14005
14197
  readonly failBuildOnWarning: "Warnings and errors";
14006
14198
  readonly optionMaxChars: "Maximum width";
14007
14199
  readonly optionCountMode: "Counting";
14200
+ readonly optionMaxMegabytes: "Largest file (MB)";
14201
+ readonly optionMaxCharacters: "Characters listed";
14008
14202
  readonly countModeEastAsianWidth: "Wide = 2 columns";
14009
14203
  readonly countModeCodePoints: "All = 1 column";
14010
14204
  };
@@ -14066,7 +14260,7 @@ declare const en: {
14066
14260
  readonly characters: "Characters";
14067
14261
  readonly dictionaryTerms: "Dictionary terms";
14068
14262
  readonly transformPresets: "Transform presets";
14069
- readonly localizationKeys: "Localization keys";
14263
+ readonly localizationKeys: "Translation keys";
14070
14264
  readonly projectLanguages: "Languages";
14071
14265
  readonly projectPlugins: "Plugins";
14072
14266
  readonly saveFields: "Save fields";
@@ -14165,9 +14359,9 @@ declare const en: {
14165
14359
  readonly statusReviewed: "Now reviewed";
14166
14360
  };
14167
14361
  readonly localizationKeys: {
14168
- readonly added: "Named string added";
14169
- readonly removed: "Named string removed";
14170
- readonly changed: "Named string changed";
14362
+ readonly added: "Translation key added";
14363
+ readonly removed: "Translation key removed";
14364
+ readonly changed: "Translation key changed";
14171
14365
  };
14172
14366
  readonly uiDocument: {
14173
14367
  readonly renamed: "Interface renamed";
@@ -14840,6 +15034,7 @@ declare const en: {
14840
15034
  readonly quality: "Checks";
14841
15035
  readonly version: "Versions";
14842
15036
  readonly ship: "Shipping";
15037
+ readonly checks: "Check rules";
14843
15038
  };
14844
15039
  readonly ui: {
14845
15040
  readonly title: "Help";
@@ -15643,14 +15838,25 @@ export type SearchJumpTarget = {
15643
15838
  } | {
15644
15839
  kind: "character";
15645
15840
  characterId: string;
15646
- } | {
15841
+ }
15842
+ /**
15843
+ * A page or a stage layer. With `elementId`, the widget on it to select once its editor opens - an
15844
+ * optional field rather than a variant of its own, so every consumer that opens the page keeps
15845
+ * opening it and only the ones that can say which widget say so.
15846
+ */
15847
+ | {
15647
15848
  kind: "uiSurface";
15648
15849
  surfaceId: string;
15850
+ elementId?: string;
15649
15851
  }
15650
- /** A component definition: its own editor tab, the one the component library opens. */
15852
+ /**
15853
+ * A component definition: its own editor tab, the one the component library opens. With
15854
+ * `elementId`, the widget inside the definition to select, as for a page.
15855
+ */
15651
15856
  | {
15652
15857
  kind: "uiComponent";
15653
15858
  componentId: string;
15859
+ elementId?: string;
15654
15860
  } | {
15655
15861
  kind: "asset";
15656
15862
  assetId: string;
@@ -15676,21 +15882,72 @@ export type SearchJumpTarget = {
15676
15882
  focusEventId?: string;
15677
15883
  focusFunctionId?: string;
15678
15884
  focusNodeId?: string;
15679
- } | {
15885
+ }
15886
+ /**
15887
+ * A named string: its row in a translation table, which is the one place its words are edited.
15888
+ * Opens the table of the project's first translated language; a project with none has no table,
15889
+ * and the jump shows the Localization panel instead, where a language is added.
15890
+ */
15891
+ | {
15680
15892
  kind: "localizationKey";
15681
15893
  keyName: string;
15682
15894
  }
15683
15895
  /**
15684
- * A project-level story variable — the panel that owns it, since no row declares one.
15685
- *
15686
- * Carries the identity even though the jump can only reveal the panel today, for the reason
15687
- * `localizationKey` carries its key: the target says what it points at, and the day the panel can
15688
- * be told which row to reveal, nothing that produces one of these has to change.
15896
+ * A project-level story variable: its row in the Variables panel, selected and scrolled into view.
15897
+ * `variableId` is the registry entry's id, or the declaration row's for one a story declares.
15689
15898
  */
15690
15899
  | {
15691
15900
  kind: "storyVariable";
15692
15901
  scope: "saved" | "persistent";
15693
15902
  variableId: string;
15903
+ }
15904
+ /**
15905
+ * A translation table - one language's - and, with `unitId`, the row of one translation unit in
15906
+ * it, scrolled into view and marked.
15907
+ *
15908
+ * The table lists one source at a time, so a row is found under the source it belongs to:
15909
+ * `storyId` for a story's lines and scene names, absent for the interface's words, the named keys
15910
+ * and the plugins' words. A character's name heads every story's rows and needs neither.
15911
+ */
15912
+ | {
15913
+ kind: "translation";
15914
+ locale: string;
15915
+ unitId?: string;
15916
+ storyId?: string;
15917
+ }
15918
+ /**
15919
+ * A voice table - one voiced language's - and, with `unitId` (a line's text id), that line's row,
15920
+ * where its take is linked. `storyId` names the story the line is in; without it the table looks
15921
+ * the line up itself.
15922
+ */
15923
+ | {
15924
+ kind: "voiceLine";
15925
+ locale: string;
15926
+ unitId?: string;
15927
+ storyId?: string;
15928
+ }
15929
+ /** A story motion, open in its own editor. */
15930
+ | {
15931
+ kind: "storyMotion";
15932
+ animationId: string;
15933
+ }
15934
+ /**
15935
+ * A page of Project settings - the panel's sub-pages - and, with `part`, the part of it to scroll
15936
+ * into view: `fonts` is the project's font stack on the Design page.
15937
+ */
15938
+ | {
15939
+ kind: "projectPage";
15940
+ page: "app" | "game" | "design" | "project" | "runtimes" | "settings";
15941
+ part?: "fonts";
15942
+ }
15943
+ /**
15944
+ * A story's own row in the Story panel's list, selected and scrolled into view - the place a story
15945
+ * is renamed or deleted, and the one way into a story whose document cannot be opened.
15946
+ */
15947
+ | {
15948
+ kind: "storyEntry";
15949
+ storyId: string;
15950
+ storyName: string;
15694
15951
  };
15695
15952
  type ModelBundleFormat = "live2d-cubism4" | "live2d-cubism2" | "spine-binary" | "spine-json" | "unknown";
15696
15953
  export declare enum AssetType {
@@ -16726,6 +16983,23 @@ type SelectionState = {
16726
16983
  type: "storyBlock";
16727
16984
  data: StoryBlockSelection;
16728
16985
  };
16986
+ type UITextMigrationChangeKind = "marksKept" | "bindingDropped" | "missingKey" | "keyDiffered";
16987
+ type UITextMigrationChange = {
16988
+ kind: UITextMigrationChangeKind;
16989
+ elementId: string;
16990
+ /** The prop the words are in (`text`, `label`, `placeholder`). */
16991
+ prop: string;
16992
+ /** The key the element named. */
16993
+ keyName: string;
16994
+ /** Where the element is: a page, or a component definition. Absent for an element on neither. */
16995
+ surfaceId?: string;
16996
+ componentId?: string;
16997
+ };
16998
+ type UITextCarriedKeys = Record<string, {
16999
+ words: string;
17000
+ translations?: Record<string, LocalizationUnit>;
17001
+ }>;
17002
+ type CarriedTranslations = Record<LocaleCode, Record<string, LocalizationUnit>>;
16729
17003
  type LiveUIComponentShell = Omit<UIComponentDefinition, "elements">;
16730
17004
  type LiveUIParts = {
16731
17005
  /** Records of the shared element map. */
@@ -16811,6 +17085,20 @@ type UIEditorClipboardPayload = {
16811
17085
  source?: UIEditorClipboardSource;
16812
17086
  /** Absent when the copied selection references no importable file. */
16813
17087
  assets?: UIEditorClipboardAssets;
17088
+ /**
17089
+ * The words and translations of the translation keys the copied widgets name, filled when the copy
17090
+ * is published for other windows. A project that lacks one of the keys receives its words on the
17091
+ * widgets instead (`settleIncomingUITextSources`); absent on an in-window copy, whose project
17092
+ * has every key it names.
17093
+ */
17094
+ textKeys?: UITextCarriedKeys;
17095
+ /**
17096
+ * What every language of the copying project says about the words the copied widgets write
17097
+ * directly, by unit id under the originals' ids (`listUITextOwnUnits`). Filled when the copy is
17098
+ * published; the paste writes them under the copies' ids. A paste without them - an in-window copy
17099
+ * not yet published, a duplicate - reads the originals' translations from the project itself.
17100
+ */
17101
+ translations?: CarriedTranslations;
16814
17102
  sourceSurfaceId: string;
16815
17103
  /** Top-level roots in the copied selection (original ids). */
16816
17104
  topLevelElementIds: UIElementId[];
@@ -16851,6 +17139,18 @@ type ImportTemplateBundleInput = {
16851
17139
  graphs: unknown;
16852
17140
  placement: ImportTemplatePlacement;
16853
17141
  assetIdMap?: Record<string, string>;
17142
+ /**
17143
+ * The words, and translations, of the keys the document's widgets name - for the ones this
17144
+ * project lacks, which arrive holding those words themselves (`settleIncomingUITextSources`).
17145
+ */
17146
+ textKeys?: UITextCarriedKeys;
17147
+ /**
17148
+ * What every language says about the words the document's widgets write directly, by unit id
17149
+ * under the ids the widgets have in `document` - a page copied in another window brings them.
17150
+ * Without it, widgets whose ids this project already translates (a page copied in this window)
17151
+ * take those translations.
17152
+ */
17153
+ translations?: CarriedTranslations;
16854
17154
  };
16855
17155
  declare class UIDocumentService extends Service<UIDocumentService> implements IUIDocumentService {
16856
17156
  private document;
@@ -16864,6 +17164,8 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
16864
17164
  private opSink;
16865
17165
  private historySuppressionDepth;
16866
17166
  private readonly contentRevisions;
17167
+ /** What the v13 step changed that an author can see, until the workspace has said so. */
17168
+ private textSourceMigrationChanges;
16867
17169
  protected init(ctx: WorkspaceContext, depend: (services: Service[]) => Promise<void>): Promise<void>;
16868
17170
  getDocument(): UIDocument;
16869
17171
  /**
@@ -16946,6 +17248,60 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
16946
17248
  }): void;
16947
17249
  updateElementLayouts(layoutPatches: Record<string, Partial<UILayout>>): void;
16948
17250
  updateElementProps(elementId: string, propsPatch: Record<string, unknown>): void;
17251
+ /**
17252
+ * Every widget that reads its words from `keyName`, turned into one that holds `words` itself.
17253
+ *
17254
+ * What removing a key does to the widgets that use it: each keeps showing what it showed, and none
17255
+ * is left naming a key the project no longer has. Component definitions' widgets are included; an
17256
+ * instance holds none of its definition's words, but a text parameter's value it reads from the key
17257
+ * becomes the key's words, given directly (prop `param.<paramId>`). One change to the document,
17258
+ * outside any page's undo history, like the removal of the key it goes with. Returns each site it
17259
+ * converted, for the translations that go with the words (`ui:<elementId>.<prop>`).
17260
+ */
17261
+ giveKeyedWidgetsTheirWords(keyName: string, words: string): {
17262
+ elementId: string;
17263
+ prop: string;
17264
+ }[];
17265
+ /**
17266
+ * Whether this project has a named key, for settling elements that arrive from elsewhere. A key
17267
+ * registry that has not been read answers yes for every key, so nothing is converted on a guess.
17268
+ */
17269
+ private readonly hasTextKey;
17270
+ /**
17271
+ * The translations of the keys arriving widgets were turned away from, filed under the widgets'
17272
+ * own units in this project's languages. `converted` carries the widgets' ids in this document.
17273
+ *
17274
+ * In the background: a language's library may still have to be read, and the elements have
17275
+ * arrived already. A language the keys came with no translation for gets none.
17276
+ */
17277
+ private adoptArrivingTranslations;
17278
+ /**
17279
+ * Give copied widgets the translations their originals' own words have, under the copies' ids.
17280
+ *
17281
+ * A widget's own words are translated through a unit named after the widget, so a copy - pasted,
17282
+ * duplicated, inside a duplicated page or component - would otherwise arrive translated in no
17283
+ * language. `table` is the arriving elements under their old ids, `idMap` what each became; `skip`
17284
+ * are the sites whose words came from a key this project lacks, which bring the key's translations
17285
+ * instead (`adoptArrivingTranslations`). `extra` are units owned by something other than an element
17286
+ * - a copied component's parameter defaults - already re-keyed, old id to new.
17287
+ *
17288
+ * `carried` is what a clipboard brought with it, which is what a paste from another project has
17289
+ * to go on, and a copy as it was when it was made. Without it the originals are this project's own
17290
+ * and their translations are read from its documents. Either way only languages this project
17291
+ * declares are written, a review is not inherited, and the write is not part of the paste's undo
17292
+ * step (`carriedTranslations.ts`).
17293
+ */
17294
+ private carryCopiedTranslations;
17295
+ /**
17296
+ * The changes the v13 step made on opening this document that an author can see, handed over
17297
+ * once: the workspace tells the author about them in one notice, and a second ask is empty.
17298
+ */
17299
+ takeTextSourceMigrationChanges(): UITextMigrationChange[];
17300
+ /**
17301
+ * The words a widget inserted into this project is given: in the project's source language, the
17302
+ * language its game is written in (`widgetDefaultWordsFor`).
17303
+ */
17304
+ private widgetDefaultWords;
16949
17305
  /** A fresh id for something this document will own. */
16950
17306
  generateId(): string;
16951
17307
  /**
@@ -17104,6 +17460,22 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
17104
17460
  private getCommonSurfaceIdForElements;
17105
17461
  private filterLinkedComponentLayoutPatch;
17106
17462
  private migrateIfNeeded;
17463
+ /**
17464
+ * The v13 step, for the project's own document as it is opened (`textSourceMigration.ts`).
17465
+ *
17466
+ * Not part of {@link migrateIfNeeded}, which is also how a template or a page copied from another
17467
+ * project comes in: this step reads the project's key registry and translation files, and the
17468
+ * translation edits it makes are written here, through the localization service, before the
17469
+ * document itself is saved by `load`. Written first so that a document still at v12 on disk -
17470
+ * its own save failed - is migrated again on the next open, and the edits are such that applying
17471
+ * them twice changes nothing.
17472
+ *
17473
+ * A key registry or a language file that cannot be read stops the open rather than being read
17474
+ * as empty: an element whose key could not be found is turned into one that holds its own words,
17475
+ * and a registry that is merely unreadable today would turn every keyed element in the project
17476
+ * into one, for good.
17477
+ */
17478
+ private migrateTextSources;
17107
17479
  /**
17108
17480
  * Every `nl.image` written in the shape that came before `imageFill`, rewritten into it.
17109
17481
  *
@@ -17292,11 +17664,38 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
17292
17664
  * deletion, and sweeping would make that a data loss with no warning.
17293
17665
  */
17294
17666
  setComponentParams(componentId: string, params: UIComponentParam[]): void;
17295
- /** Set one param value on one instance. An empty string is a value, not a reset. */
17667
+ /**
17668
+ * Set one param value on one instance. An empty string is a value, not a reset.
17669
+ *
17670
+ * Words written for a text parameter replace a key the instance named for it: a value holds one
17671
+ * or the other (`UIComponentLink.paramKeys`).
17672
+ */
17296
17673
  setComponentInstanceParam(elementId: string, paramId: string, value: string): void;
17674
+ /**
17675
+ * Name the translation key one instance's text parameter is read from, or (`null`) name none.
17676
+ *
17677
+ * Naming a key removes the words the instance held for the parameter - a value holds one source -
17678
+ * and naming none leaves the parameter with neither, which falls back to the definition's default.
17679
+ */
17680
+ setComponentInstanceParamKey(elementId: string, paramId: string, keyName: string | null): void;
17297
17681
  deleteComponents(componentIds: string[]): void;
17298
17682
  duplicateComponent(componentId: string): UIComponentDefinition | null;
17299
17683
  updateComponentElementLayout(componentId: string, elementId: string, layoutPatch: Partial<UILayout>): void;
17684
+ /**
17685
+ * Bind one prop of one element of a component definition to a field of its list row or to a text
17686
+ * parameter of the component - the two value bindings that need no blueprint - or (`null`) unbind
17687
+ * it. A definition's elements take no Blueprint Value (`ComponentDocumentServiceAdapter`), so there
17688
+ * is no blueprint to clear on the way.
17689
+ */
17690
+ setComponentElementValueBinding(componentId: string, elementId: string, propPath: string, binding: Extract<UIElementValueBinding, {
17691
+ kind: "listItemField" | "componentParam";
17692
+ }> | null): void;
17693
+ /**
17694
+ * Show one of a component's text parameters in the words of an element of its definition, or
17695
+ * (`null`) stop showing one. The component is the one whose definition holds the element; an
17696
+ * element on a page has no parameters to show and is left alone.
17697
+ */
17698
+ setElementComponentParamBinding(elementId: string, propPath: string, paramId: string | null): void;
17300
17699
  updateComponentElementProps(componentId: string, elementId: string, propsPatch: Record<string, unknown>): void;
17301
17700
  updateComponentElementAnimation(componentId: string, elementId: string, animation: UIPageAnimationSettings | null): void;
17302
17701
  updateComponentElementExtra(componentId: string, elementId: string, extraPatch: Record<string, unknown>): void;
@@ -17315,7 +17714,7 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
17315
17714
  */
17316
17715
  groupComponentElements(componentId: string, elementIds: readonly string[]): string | null;
17317
17716
  createComponentElement(componentId: string, parentId: string, type: string, layoutPatch?: Partial<UILayout>): UIElement | null;
17318
- pasteComponentClipboardPayload(componentId: string, targetParentId: string, beforeChildId: string | null, payload: UIEditorClipboardPayload): {
17717
+ pasteComponentClipboardPayload(componentId: string, targetParentId: string, beforeChildId: string | null, incoming: UIEditorClipboardPayload): {
17319
17718
  ok: true;
17320
17719
  newRootIds: string[];
17321
17720
  } | {
@@ -17325,7 +17724,7 @@ declare class UIDocumentService extends Service<UIDocumentService> implements IU
17325
17724
  createComponentInstance(parentId: string, componentId: string, layoutPatch?: Partial<UILayout>): UIElement;
17326
17725
  unlinkComponentInstance(elementId: string): string[];
17327
17726
  createElement(parentId: string, type: string, layoutPatch?: Partial<UILayout>): UIElement;
17328
- pasteClipboardPayload(surfaceId: string, targetParentId: string, beforeChildId: string | null, payload: UIEditorClipboardPayload): {
17727
+ pasteClipboardPayload(surfaceId: string, targetParentId: string, beforeChildId: string | null, incoming: UIEditorClipboardPayload): {
17329
17728
  ok: true;
17330
17729
  newRootIds: string[];
17331
17730
  } | {
@@ -18815,7 +19214,9 @@ declare const HELP_TOPIC_IDS: readonly [
18815
19214
  "screenEffects",
18816
19215
  "plugins"
18817
19216
  ];
18818
- type HelpTopicId = (typeof HELP_TOPIC_IDS)[number];
19217
+ type StaticHelpTopicId = (typeof HELP_TOPIC_IDS)[number];
19218
+ type LintRuleHelpTopicId = `lintRule.${string}`;
19219
+ type HelpTopicId = StaticHelpTopicId | LintRuleHelpTopicId;
18819
19220
  interface PanelComponentProps<TPayload = any> {
18820
19221
  panelId: string;
18821
19222
  payload?: TPayload;
@@ -19678,6 +20079,13 @@ export type RuntimePluginLocale = {
19678
20079
  * added after the plugin was installed. `null` when the project declares no such key.
19679
20080
  */
19680
20081
  text(key: string): string | null;
20082
+ /**
20083
+ * Words this plugin wrote directly and offered for translation from its studio entry
20084
+ * (`app.services.localization.registerWords`), in the language the game is running in: the
20085
+ * translation of the unit `id` names along the language's fallback chain, else `text` - the words
20086
+ * as written, which the plugin passes because the game carries translations and not source words.
20087
+ */
20088
+ words(id: string, text: string): string;
19681
20089
  };
19682
20090
  /**
19683
20091
  * `menu` - the whole menu bar above the game, declared at once.
@@ -20572,6 +20980,22 @@ export type FreezeGuard = {
20572
20980
  run<A extends unknown[], R>(handler: (...args: A) => R): (...args: A) => R | undefined;
20573
20981
  };
20574
20982
  declare function useFreezeGuard(scope?: string | readonly string[]): FreezeGuard;
20983
+ type WordsSourceValue = {
20984
+ /** The words written directly; with a key, what shows if the key is not in the running game. */
20985
+ text: string;
20986
+ /** The translation key the words are read from, or null for words written directly. */
20987
+ key: string | null;
20988
+ };
20989
+ type WordsSourceFieldProps = {
20990
+ value: WordsSourceValue;
20991
+ onChange: (next: WordsSourceValue) => void;
20992
+ /** Words over several lines; one line when absent. */
20993
+ multiline?: boolean;
20994
+ disabled?: boolean;
20995
+ /** Resets the box's draft when it changes - the id of whatever the words belong to. */
20996
+ draftResetKey?: string;
20997
+ };
20998
+ declare function WordsSourceField({ value, onChange, multiline, disabled, draftResetKey }: WordsSourceFieldProps): React$1.ReactElement;
20575
20999
  type DivProps = React$1.HTMLAttributes<HTMLDivElement>;
20576
21000
  declare function PluginAssetSelector(props: AssetSelectorProps): React$1.JSX.Element | null;
20577
21001
  export type PluginPanelRootProps = DivProps & {
@@ -20660,6 +21084,14 @@ declare const pluginUi: Readonly<{
20660
21084
  CardFooter: typeof CardFooter;
20661
21085
  InteractiveCard: typeof InteractiveCard;
20662
21086
  AssetSelector: typeof PluginAssetSelector;
21087
+ /**
21088
+ * Words a player reads, written directly or read from one of the project's translation keys - the
21089
+ * same choice, key list and in-place key editing as Studio's own text and button labels. Controlled:
21090
+ * `value` is `{ text, key }` with `key` null for words written directly, and `onChange` is
21091
+ * handed the next one. Words written directly are translated when the plugin offers them with
21092
+ * `app.services.localization.registerWords`; words read from a key are translated as the key.
21093
+ */
21094
+ WordsField: typeof WordsSourceField;
20663
21095
  Panel: Readonly<{
20664
21096
  Root: typeof PluginPanelRoot;
20665
21097
  Header: typeof PluginPanelHeader;
@@ -20758,6 +21190,7 @@ export declare const ui: Readonly<{
20758
21190
  CardFooter: typeof CardFooter;
20759
21191
  InteractiveCard: typeof InteractiveCard;
20760
21192
  AssetSelector: typeof PluginAssetSelector;
21193
+ WordsField: typeof WordsSourceField;
20761
21194
  Panel: Readonly<{
20762
21195
  Root: typeof PluginPanelRoot;
20763
21196
  Header: typeof PluginPanelHeader;
@@ -20939,7 +21372,7 @@ export type PluginAssetsService = {
20939
21372
  revokeObjectUrl(url: string): void;
20940
21373
  };
20941
21374
  /** An active editor locale code (built-in like "en"/"zh", or a plugin-provided locale). */
20942
- export type LocaleCode = string;
21375
+ type LocaleCode$1 = string;
20943
21376
  /**
20944
21377
  * A plugin's own message tables: `locale code -> (message key -> string)`. This
20945
21378
  * is the plugin's private catalog, unrelated to Studio's own translations.
@@ -20959,7 +21392,7 @@ export type PluginMessageBundle = {
20959
21392
  * {@link PluginI18n.onLocaleChange} to re-render on a language switch.
20960
21393
  */
20961
21394
  export type PluginTranslator = {
20962
- readonly locale: LocaleCode;
21395
+ readonly locale: LocaleCode$1;
20963
21396
  t(key: string, params?: Record<string, string | number>): string;
20964
21397
  };
20965
21398
  /**
@@ -20969,14 +21402,14 @@ export type PluginTranslator = {
20969
21402
  */
20970
21403
  export type PluginI18n = {
20971
21404
  /** The editor's active locale code. */
20972
- readonly locale: LocaleCode;
21405
+ readonly locale: LocaleCode$1;
20973
21406
  /**
20974
21407
  * Subscribe to editor-language changes. The listener fires with the new
20975
21408
  * locale code whenever the active editor language changes. Returns a
20976
21409
  * {@link PluginCleanup} (also tracked by the host, so it is reclaimed on
20977
21410
  * unload even if you forget to call it).
20978
21411
  */
20979
- onLocaleChange(listener: (locale: LocaleCode) => void): PluginCleanup;
21412
+ onLocaleChange(listener: (locale: LocaleCode$1) => void): PluginCleanup;
20980
21413
  /** Locale-aware number formatting bound to the editor's active locale. */
20981
21414
  formatNumber(value: number, options?: Intl.NumberFormatOptions): string;
20982
21415
  /** Locale-aware date formatting bound to the editor's active locale. */
@@ -21056,15 +21489,45 @@ export type PluginInterfaceService = {
21056
21489
  listGlobalFns(): PluginBlueprintFnEntry[];
21057
21490
  };
21058
21491
  /**
21059
- * The project's own localization keys, read-only.
21492
+ * One of the words a plugin puts in front of a player, offered for translation.
21493
+ *
21494
+ * `id` is the plugin's own (letters, digits, and `.` `_` `-` between them) and has to stay the same
21495
+ * while the words are the same thing - a translation is kept against it, so an id made from the words
21496
+ * themselves would lose every translation the moment the author corrected a letter. The translation
21497
+ * unit is `plugin:<pluginId>/<id>`, scoped to the plugin by the host.
21498
+ */
21499
+ export type PluginWordsEntry = {
21500
+ id: string;
21501
+ /** The words, in the project's source language. */
21502
+ text: string;
21503
+ /** Where a player meets them, for a translator: "File › Save". The plugin's name when absent. */
21504
+ context?: string;
21505
+ };
21506
+ /** A plugin's words as they are now, and a way for the host to hear that they changed. */
21507
+ export type PluginWordsSource = {
21508
+ list(): readonly PluginWordsEntry[];
21509
+ subscribe?(listener: () => void): () => void;
21510
+ };
21511
+ /**
21512
+ * The project's own localization keys, read-only, and a place to offer the plugin's own words.
21060
21513
  *
21061
- * A plugin that puts words in front of a player writes them as keys through this list rather than
21062
- * as literals, so they travel with everything else the project translates. Empty before the keys
21063
- * document has loaded, which is a moment rather than a state - subscribe through
21064
- * `services.workspace.registerReloader` if a panel has to re-read it.
21514
+ * A plugin that puts words in front of a player either names a key from this list - one of the
21515
+ * project's shared words - or writes them directly and offers them with `registerWords`, so they
21516
+ * travel with everything else the project translates. Empty before the keys document has loaded,
21517
+ * which is a moment rather than a state - subscribe through `services.workspace.registerReloader` if
21518
+ * a panel has to re-read it.
21065
21519
  */
21066
21520
  export type PluginLocalizationService = {
21067
21521
  listKeys(): PluginLocalizationKeyEntry[];
21522
+ /**
21523
+ * Offer the plugin's own words to the project's translation table and exports.
21524
+ *
21525
+ * Each listed entry with a letter in it gets a row under the plugin's name; the runtime entry
21526
+ * reads a word back in the player's language with `app.game.locale.words(id, text)`. List what
21527
+ * the author wrote directly; words read from a key are translated as the key and need no entry.
21528
+ * Call `subscribe`'s listener whenever the list would answer differently.
21529
+ */
21530
+ registerWords(source: PluginWordsSource): PluginCleanup;
21068
21531
  };
21069
21532
  export type PluginServices = {
21070
21533
  storage: PluginStorageService;
@@ -21182,6 +21645,7 @@ export {
21182
21645
  GameSurfaceMountDetail as RuntimePluginSurfaceMountTimelineDetail,
21183
21646
  GameTimelineSpanDetails as RuntimePluginTimelineSpanDetails,
21184
21647
  GameTimelineSpanName as RuntimePluginTimelineSpanName,
21648
+ LocaleCode$1 as LocaleCode,
21185
21649
  SelectOption$1 as SelectOption,
21186
21650
  };
21187
21651