@arronqzy/i18n 0.1.1

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.
@@ -0,0 +1,1360 @@
1
+ export const enUS = {
2
+ common: {
3
+ ok: "OK",
4
+ cancel: "Cancel",
5
+ confirm: "Confirm",
6
+ delete: "Delete",
7
+ save: "Save",
8
+ reset: "Reset",
9
+ preview: "Preview",
10
+ sync: "Sync",
11
+ edit: "Edit",
12
+ default: "Default",
13
+ none: "None",
14
+ node: "Node",
15
+ hint: "Hint",
16
+ export: "Export",
17
+ import: "Import",
18
+ search: "Search",
19
+ close: "Close",
20
+ expand: "Expand",
21
+ collapse: "Collapse",
22
+ upload: "Upload",
23
+ clear: "Clear",
24
+ copy: "Copy",
25
+ paste: "Paste",
26
+ rename: "Rename",
27
+ add: "Add",
28
+ remove: "Remove",
29
+ loading: "Loading…",
30
+ colorPickerAria: "{label} color picker",
31
+ hintAria: "{label} hint",
32
+ secondsAgo: "{sec}s ago",
33
+ minutesAgo: "{min}m ago",
34
+ hoursAgo: "{hour}h ago",
35
+ daysAgo: "{day}d ago",
36
+ },
37
+ panel: {
38
+ ai: {
39
+ title: "Offline AI assistant",
40
+ open: "AI assistant",
41
+ hide: "Hide AI",
42
+ welcome: "Local offline assistant. Load a model, then ask or edit.",
43
+ downloadModel: "Load",
44
+ modelReady: "Model ready.",
45
+ statusIdle: "Idle",
46
+ statusLoading: "{pct}%",
47
+ statusReady: "Ready",
48
+ statusUnsupported: "No WebGPU",
49
+ webgpuRequired: "Chrome/Edge + WebGPU required (offline only).",
50
+ inputPlaceholder: "Describe the change…",
51
+ send: "Send",
52
+ done: "Done",
53
+ parseFailed: "Could not parse model output:",
54
+ applyFailed: "Failed",
55
+ needActionHint:
56
+ "(No executable action. Select a widget and be specific, or switch to 3B.)",
57
+ unclearIntent:
58
+ "I didn't catch that.\n\nPlease say whether you want to **ask** or **edit**, for example:\n- \"What can you do?\"\n- \"What components are there?\"\n- \"Add a table\"\n- \"Set the selected widget width to 400\"",
59
+ layerLockedAddFailed: "Active layer is locked. Unlock or switch layers.",
60
+ unknownMaterial:
61
+ "Unknown material 「{type}」. Try: text / table / grid / image / bar / line / pie.",
62
+ error: "Error",
63
+ model15b: "1.5B",
64
+ model15bHint: "Faster, less VRAM; use 3B for harder tasks",
65
+ model3b: "3B",
66
+ model3bHint: "Higher accuracy; larger download and VRAM",
67
+ quickMakeLogin: "Simple login page",
68
+ quickMakeLoginSave: "Login page + save",
69
+ quickExplainSelection: "Explain selection",
70
+ quickAddTable: "Add table",
71
+ quickAddClock: "Add blueprint timer",
72
+ quickBlueprintTimerRun: "Blueprint timer + run",
73
+ quickWhatComponents: "What components?",
74
+ quickHowTable: "Table setup",
75
+ historyLabel: "{count} messages",
76
+ historyExpand: "Earlier {count}",
77
+ historyCollapse: "Collapse",
78
+ historyHidden: "{count} earlier hidden",
79
+ inputHint: "Enter to send",
80
+ stepRunning: "Step {step}: {type}…",
81
+ stepLine: "{step}. {type} — {result}",
82
+ stepsSummary: "Steps",
83
+ stoppedMaxSteps: "Step limit reached.",
84
+ stoppedFail: "Did not finish.",
85
+ stoppedParseFail: "Could not parse further actions.",
86
+ },
87
+ menubar: {
88
+ file: "File",
89
+ edit: "Edit",
90
+ view: "View",
91
+ blueprint: "Blueprint",
92
+ settings: "Settings",
93
+ export: "Export",
94
+ import: "Import",
95
+ exportPanelJson: "Export panel JSON",
96
+ importPanelJson: "Import panel JSON",
97
+ exportBlueprint: "Export blueprint",
98
+ importBlueprint: "Import blueprint",
99
+ undo: "Undo",
100
+ redo: "Redo",
101
+ bringForward: "Bring forward",
102
+ sendBackward: "Send backward",
103
+ bringToFront: "Bring to front",
104
+ sendToBack: "Send to back",
105
+ deleteSelected: "Delete selected",
106
+ zoomOut: "Zoom out",
107
+ zoomIn: "Zoom in",
108
+ switchToLight: "Switch to light",
109
+ switchToDark: "Switch to dark",
110
+ fontSmall: "Font: small",
111
+ fontMedium: "Font: medium",
112
+ fontLarge: "Font: large",
113
+ productName: "Product name",
114
+ productNamePlaceholder: "Enter the current build product name",
115
+ uploadTitleIcon: "Upload title icon",
116
+ clearTitleIcon: "Clear title icon",
117
+ viewTitleIcon: "View title icon",
118
+ viewTitleIconHint: "Click to view the title icon",
119
+ titleIconThumbAlt: "Title icon thumbnail",
120
+ titleIconPreviewAlt: "Title icon preview",
121
+ titleIconPreviewTitle: "Title icon preview",
122
+ titleIconPreviewDesc: "Current image used as the preview page tab icon",
123
+ undoShortcut: "Undo (Cmd/Ctrl + Z)",
124
+ redoShortcut: "Redo (Cmd/Ctrl + Shift + Z)",
125
+ nodeZOrderAria: "Node stacking order",
126
+ showBlueprintPanel: "Show blueprint panel",
127
+ toggleTheme: "Toggle theme",
128
+ toggleThemeHint: "Toggle dark / light theme",
129
+ zoomOutCanvas: "Zoom out canvas",
130
+ zoomInCanvas: "Zoom in canvas",
131
+ selectedCount: "{count} selected",
132
+ zoom: "Zoom",
133
+ duplicateNode: "Duplicate node",
134
+ locateSourceNode: "Locate source node",
135
+ openInMappingLayer: "Open in mapping layer",
136
+ deleteNode: "Delete node",
137
+ deleteSelectedNodes: "Delete selected nodes ({count})",
138
+ pasteNode: "Paste node",
139
+ selectAllInLayer: "Select all in current layer",
140
+ },
141
+ material: {
142
+ searchPlaceholder: "Search materials (name / category)",
143
+ tabMaterials: "Materials",
144
+ tabTree: "Node tree",
145
+ searchResults: "Search results ({count})",
146
+ emptyMaterialsTitle: "No materials matched",
147
+ emptyMaterialsDesc: "Try another keyword, or switch category and search again.",
148
+ treeSearchPlaceholder: "Search nodes (name / type / ID)",
149
+ referenceOnlyTree: "Reference subtree only",
150
+ emptyNodesTitle: "No nodes matched",
151
+ emptyNodesDesc: "Try a node name, type, or ID keyword.",
152
+ charts: "Charts",
153
+ basic: "Basic",
154
+ media: "Media",
155
+ bar: "Bar chart",
156
+ line: "Line chart",
157
+ pie: "Pie chart",
158
+ area: "Area chart",
159
+ scatter: "Scatter chart",
160
+ radar: "Radar chart",
161
+ gauge: "Gauge",
162
+ funnel: "Funnel chart",
163
+ text: "Text",
164
+ geometry: "Geometry",
165
+ grid: "Grid layout",
166
+ image: "Image",
167
+ video: "Video",
168
+ audio: "Audio",
169
+ reference: "Reference",
170
+ table: "Table",
171
+ rect: "Rectangle",
172
+ mappingLayerNode: "Mapping layer node",
173
+ mappingLayerTitle: "Mapping layer \"{name}\"",
174
+ mappingLayerWithBase: "Mapping layer \"{name}\" · Base: {base}",
175
+ mappingLayer: "Mapping layer",
176
+ mappingLayerWithBaseShort: "Mapping layer · Base: {base}",
177
+ sameSource: "Same source",
178
+ sameSourceTitle: "Same-source node {id}",
179
+ nodeLocked: "Node locked",
180
+ shallowCopy: "Shallow copy",
181
+ deepCopy: "Deep copy",
182
+ shallowCopyTitle: "Shallow reference (follows source)",
183
+ deepCopyTitle: "Deep reference (frozen snapshot)",
184
+ duplicateNode: "Duplicate node",
185
+ deleteNode: "Delete node",
186
+ lockedNodeCannotDelete: "Locked nodes cannot be deleted",
187
+ circularRefStopped: "Circular reference detected; stopped expanding",
188
+ circularRefSuffix: "(circular reference)",
189
+ emptyLayer: "Empty layer",
190
+ targetLayer: "Target layer",
191
+ willMoveToLayer: "Will move to this layer",
192
+ cannotMoveToLayer: "Cannot move to this layer",
193
+ dragToLayer: "Drag node to this layer",
194
+ dragToThisLayer: "Drag node onto this layer",
195
+ releaseToMove: "Release to move to this layer",
196
+ referenceComponent: "Reference component",
197
+ },
198
+ config: {
199
+ panelTitle: "Config panel",
200
+ expandSearch: "Expand search",
201
+ collapseSearch: "Collapse search",
202
+ searchPlaceholder: "Search config, e.g. border, tooltip, audio, grid...",
203
+ searching: "Searching: {query}",
204
+ emptyNoNodeTitle: "No configurable node",
205
+ emptyNoNodeDesc: "Select a node on the canvas first, then configure it here.",
206
+ noMatch: "No matches found. Try another keyword.",
207
+ notChartType: "This node is not a chart type; no chart options available.",
208
+ uploadWrittenBase64: "Saved as base64",
209
+ uploadServerAndBase64: "Uploaded to server and saved as base64",
210
+ uploadServerFailedKeepBase64: "Server upload failed; kept local base64 only",
211
+ lockNode: "Lock node (disable z-order / position / size / rotation)",
212
+ batchTitle: "Batch settings",
213
+ batchTitleWithCount: "Batch settings ({count})",
214
+ lockAll: "Lock all",
215
+ unlockAll: "Unlock all",
216
+ bringAllForward: "Bring all forward",
217
+ sendAllBackward: "Send all backward",
218
+ setAllZIndex1: "Set all zIndex to 1",
219
+ setAllBgBlue: "Set all backgrounds to blue",
220
+ expandNodeConfig: "Expand node config",
221
+ collapseNodeConfig: "Collapse node config",
222
+ removeFromSelection: "Remove",
223
+ removeFromSelectionTitle: "Remove this node from the current multi-selection",
224
+ lockedNode: "Locked node",
225
+ lockedNodeHint: "This node is locked; only the lock switch is available.",
226
+ noEditableMatch: "No editable nodes matched. Try another keyword.",
227
+ nodeLabel: "{name} · {id}",
228
+ sectionNodeInfo: "Node info",
229
+ sectionStyleBackground: "Common style / Background",
230
+ sectionStyleBorder: "Common style / Border",
231
+ sectionChartBasic: "Chart / Basic",
232
+ sectionChartAdvanced: "Chart / Advanced",
233
+ sectionText: "Text",
234
+ sectionTable: "Table",
235
+ sectionAudio: "Audio",
236
+ sectionVideo: "Video",
237
+ sectionImage: "Image",
238
+ sectionGeometry: "Geometry",
239
+ sectionGrid: "Grid layout",
240
+ sectionGridChildSpan: "Grid child span",
241
+ sectionReference: "Reference",
242
+ groupBgFill: "Background fill",
243
+ groupBgLayout: "Background layout",
244
+ groupBorderGeometry: "Border geometry",
245
+ groupBorderVisual: "Border appearance",
246
+ groupBasicDisplay: "Basic display",
247
+ groupTooltip: "Tooltip",
248
+ groupData: "Data",
249
+ groupAxes: "Axes",
250
+ groupSeries: "Series",
251
+ groupCommonForm: "Common (form)",
252
+ groupLayoutAndCoord: "Layout & coordinates",
253
+ groupHighFreq: "Frequent options",
254
+ groupAxisPointer: "Axis pointer & snap",
255
+ groupJsonAdvanced: "JSON advanced mode",
256
+ groupTextContent: "Text content",
257
+ groupTextStyle: "Text style",
258
+ groupInputAbility: "Input",
259
+ groupAudioSource: "Audio source",
260
+ groupDisplayStyle: "Display style",
261
+ groupVideoSource: "Video source",
262
+ groupImageSource: "Image source",
263
+ groupDisplayMode: "Display mode",
264
+ groupBasicShape: "Basic shape",
265
+ groupCanvasScript: "Advanced (Canvas script)",
266
+ groupSketchOverlay: "Sketch overlay",
267
+ groupGridParams: "Grid parameters",
268
+ groupCrossSlots: "Cross slots",
269
+ groupRefSource: "Reference source",
270
+ groupCopyStrategy: "Copy strategy",
271
+ name: "Name",
272
+ nodeName: "Node name",
273
+ nodeNamePlaceholder: "Custom node name (shown in the node tree)",
274
+ type: "Type",
275
+ layer: "Layer",
276
+ selectLayer: "Select layer",
277
+ pleaseSelectLayer: "Please select a layer",
278
+ rotate: "Rotation",
279
+ width: "Width",
280
+ height: "Height",
281
+ nodeZOrder: "Node stacking",
282
+ currentZIndex: "Current zIndex: {value}",
283
+ backgroundColor: "Background color",
284
+ backgroundImage: "Background image",
285
+ backgroundImageUrl: "Background image / URL",
286
+ uploadImage: "Upload image",
287
+ backgroundSize: "Background size",
288
+ backgroundPosition: "Background position",
289
+ selectBackgroundSize: "Select background size",
290
+ selectBackgroundPosition: "Select background position",
291
+ borderWidth: "Border width (px)",
292
+ borderRadius: "Border radius (px)",
293
+ borderStyle: "Border style",
294
+ selectBorderStyle: "Select border style",
295
+ borderColor: "Border color",
296
+ borderColorShort: "Border color",
297
+ chartTitle: "Chart title",
298
+ title: "Title",
299
+ primaryColor: "Primary color",
300
+ primaryGradient: "Primary gradient",
301
+ usePrimaryGradient: "Use gradient for primary color",
302
+ gradientFrom: "Gradient start",
303
+ gradientTo: "Gradient end",
304
+ gradientDirection: "Gradient direction",
305
+ selectGradientDirection: "Select gradient direction",
306
+ gradientPreview: "Gradient preview",
307
+ dirToRight: "Left → right",
308
+ dirToBottom: "Top → bottom",
309
+ dirToBottomRight: "Top-left → bottom-right",
310
+ dirToTopRight: "Bottom-left → top-right",
311
+ renderMode: "Render mode",
312
+ render: "Render",
313
+ selectRenderMode: "Select render mode",
314
+ showTooltip: "Show tooltip",
315
+ tooltipTrigger: "Tooltip trigger",
316
+ selectTooltipTrigger: "Select trigger",
317
+ tooltipBg: "Tooltip background",
318
+ tooltipBgColor: "Tooltip background color",
319
+ tooltipTextColor: "Tooltip text color",
320
+ tooltipFormatter: "Tooltip formatter (optional)",
321
+ tooltipFormatterPlaceholder: "e.g. {b}: {c}",
322
+ formatterPlaceholdersTitle: "Available placeholders",
323
+ formatterPlaceholders: "{a}=series, {b}=category, {c}=value, {d}=percent (pie)",
324
+ formatterExamplesTitle: "Common templates + examples",
325
+ formatterExample1: "1) {b}: {c} -> Mon: 120",
326
+ formatterExample2: "2) {a}<br/>{b}: {c} -> Sales<br/>Mon: 120",
327
+ formatterExample3: "3) {b}: {c} ({d}%) -> Source: 335 (42%)",
328
+ formatterExample4: "4) ${c} / {b} -> $120 / Mon",
329
+ labelsCsv: "Categories (comma-separated)",
330
+ valuesCsv: "Values (comma-separated)",
331
+ xAxisName: "X-axis name",
332
+ yAxisName: "Y-axis name",
333
+ xAxisNamePlaceholder: "e.g. date / category",
334
+ yAxisNamePlaceholder: "e.g. sales / value",
335
+ xAxisTick: "X-axis ticks",
336
+ yAxisTick: "Y-axis ticks",
337
+ xAxisTickColor: "X-axis tick color",
338
+ yAxisTickColor: "Y-axis tick color",
339
+ xAxisSplitLine: "X-axis split lines",
340
+ yAxisSplitLine: "Y-axis split lines",
341
+ xAxisSplitLineColor: "X-axis split-line color",
342
+ yAxisSplitLineColor: "Y-axis split-line color",
343
+ xAxisLabelColor: "X-axis label color",
344
+ yAxisLabelColor: "Y-axis label color",
345
+ xAxisLabelFontSize: "X-axis label font size",
346
+ yAxisLabelFontSize: "Y-axis label font size",
347
+ xAxisLabelAutoEllipsis: "X-axis label auto-ellipsis",
348
+ yAxisLabelAutoEllipsis: "Y-axis label auto-ellipsis",
349
+ gaugeValue: "Gauge value",
350
+ barWidth: "Bar width",
351
+ barWidthPx: "Bar width (px)",
352
+ smooth: "Smooth curve",
353
+ pieInnerRadius: "Inner radius",
354
+ pieInnerRadiusPct: "Inner radius (%)",
355
+ pieOuterRadius: "Outer radius",
356
+ pieOuterRadiusPct: "Outer radius (%)",
357
+ gridLeft: "Grid left padding",
358
+ gridRight: "Grid right padding",
359
+ gridTop: "Grid top padding",
360
+ gridBottom: "Grid bottom padding",
361
+ gridLeftHint: "Controls left whitespace of the plot area.",
362
+ gridRightHint: "Controls right whitespace of the plot area.",
363
+ gridTopHint: "Controls top whitespace of the plot area.",
364
+ gridBottomHint: "Controls bottom whitespace of the plot area.",
365
+ gridLeftForm: "Grid left (grid.left)",
366
+ gridRightForm: "Grid right (grid.right)",
367
+ gridTopForm: "Grid top (grid.top)",
368
+ gridBottomForm: "Grid bottom (grid.bottom)",
369
+ legendPosition: "Legend position",
370
+ legendPositionForm: "Legend position (legend.top)",
371
+ legendOrient: "Legend orientation",
372
+ legendOrientForm: "Legend orientation (legend.orient)",
373
+ legendPositionHint: "Where the legend docks in the container.",
374
+ legendOrientHint: "Arrange legend horizontally or vertically.",
375
+ selectLegendPosition: "Select legend position",
376
+ selectLegendOrient: "Select legend orientation",
377
+ legendTop: "Top",
378
+ legendBottom: "Bottom",
379
+ legendLeft: "Left",
380
+ legendRight: "Right",
381
+ legendHorizontal: "Horizontal",
382
+ legendVertical: "Vertical",
383
+ xAxisMin: "X-axis min",
384
+ xAxisMax: "X-axis max",
385
+ yAxisMin: "Y-axis min",
386
+ yAxisMax: "Y-axis max",
387
+ xAxisMinHint: "Set X-axis minimum; leave empty to remove in JSON.",
388
+ xAxisMaxHint: "Set X-axis maximum; leave empty to remove in JSON.",
389
+ yAxisMinHint: "Set Y-axis minimum; leave empty to remove in JSON.",
390
+ yAxisMaxHint: "Set Y-axis maximum; leave empty to remove in JSON.",
391
+ xAxisLabelRotate: "X-axis label rotation",
392
+ yAxisLabelRotate: "Y-axis label rotation",
393
+ rotateUnitHint: "Unit: degrees.",
394
+ showLegend: "Show legend",
395
+ showLegendWithKey: "Show legend (legend.show)",
396
+ showLegendHint: "Toggle legend visibility.",
397
+ gridContainLabel: "Grid contain label",
398
+ gridContainLabelHint: "Reserve space for axis labels automatically.",
399
+ zoomInside: "Inside zoom",
400
+ zoomInsideWithKey: "Inside zoom (dataZoom[type=inside])",
401
+ zoomInsideHint: "Enable mouse-wheel / gesture zoom.",
402
+ zoomSlider: "Slider zoom",
403
+ zoomSliderWithKey: "Slider zoom (dataZoom[type=slider])",
404
+ zoomSliderHint: "Show a bottom drag zoom bar.",
405
+ enableAnimation: "Enable animation",
406
+ enableAnimationHint: "Animate transitions when data changes.",
407
+ animationDuration: "Animation duration",
408
+ animationDurationMs: "Animation duration (ms)",
409
+ animationDurationHint: "Animation duration in milliseconds.",
410
+ showAxisPointer: "Show axis pointer",
411
+ showAxisPointerWithKey: "Show axis pointer (axisPointer.show)",
412
+ showAxisPointerHint: "Show axis alignment hint on hover.",
413
+ axisPointerType: "Axis pointer type",
414
+ axisPointerTypeWithKey: "Axis pointer type (axisPointer.type)",
415
+ axisPointerTypeHint: "Pointer style: line / shadow / cross.",
416
+ selectAxisPointerType: "Select axis pointer type",
417
+ axisPointerLine: "Line",
418
+ axisPointerShadow: "Shadow",
419
+ axisPointerCross: "Cross",
420
+ axisPointerSnap: "Axis pointer snap",
421
+ axisPointerSnapHint: "Snap pointer to nearest data point.",
422
+ advancedOptionJson: "Advanced option JSON (overrides base config)",
423
+ enableAdvancedJson: "Enable advanced mode (edit chart JSON directly)",
424
+ advancedJsonHintLabel: "Chart JSON advanced mode",
425
+ advancedJsonHint: "Base options are generated first; advanced mode deep-merges on top.",
426
+ advancedJsonPlaceholder: 'e.g. {"grid":{"left":24}}',
427
+ geometryScriptPlaceholder:
428
+ "// e.g. ctx.fillStyle = 'rgba(255,255,255,0.25)'; ctx.fillRect(8,8,width-16,height-16);",
429
+ jsonInvalid: "Invalid JSON; it will apply automatically once fixed",
430
+ jsonValidApplied: "JSON is valid and applied to the chart live.",
431
+ expandLayoutCoord: "Expand layout & coordinates",
432
+ collapseLayoutCoord: "Collapse layout & coordinates",
433
+ expandHighFreq: "Expand frequent options",
434
+ collapseHighFreq: "Collapse frequent options",
435
+ expandAxisPointer: "Expand axis pointer options",
436
+ collapseAxisPointer: "Collapse axis pointer options",
437
+ textHtml: "Text content (HTML)",
438
+ fontFamily: "Font family",
439
+ fontFamilyPlaceholder: "e.g. Inter, PingFang SC, Microsoft YaHei",
440
+ fontSize: "Font size",
441
+ fontSizePx: "Font size (px)",
442
+ fontWeight: "Font weight",
443
+ selectFontWeight: "Select font weight",
444
+ textAlign: "Align",
445
+ selectTextAlign: "Select alignment",
446
+ alignLeft: "Left",
447
+ alignCenter: "Center",
448
+ alignRight: "Right",
449
+ alignJustify: "Justify",
450
+ lineHeight: "Line height",
451
+ textColor: "Text color",
452
+ allowCanvasInput: "Allow direct input on canvas (on by default)",
453
+ audioUrl: "Audio URL",
454
+ uploadAudio: "Upload audio",
455
+ startRecord: "Start recording",
456
+ stopRecord: "Stop recording",
457
+ autoPauseMedia: "Auto-pause media while editing",
458
+ audioIconPreset: "Preset speaker icon",
459
+ selectIcon: "Select icon",
460
+ iconDefaultProgress: "Default (show progress bar)",
461
+ iconSpeaker: "Speaker",
462
+ iconMusic: "Music note",
463
+ iconHeadphone: "Headphones",
464
+ iconWave: "Wave",
465
+ visualEffect: "Playback effect",
466
+ effect: "Effect",
467
+ selectEffect: "Select effect",
468
+ effectNone: "None",
469
+ effectPulse: "Pulse highlight",
470
+ effectRipple: "Ripple",
471
+ effectSpeed: "Effect speed",
472
+ speed: "Speed",
473
+ selectSpeed: "Select speed",
474
+ speedSlow: "Slow",
475
+ speedNormal: "Normal",
476
+ speedFast: "Fast",
477
+ uploadPoster: "Upload poster",
478
+ clearPoster: "Clear poster",
479
+ audioPoster: "Audio poster",
480
+ audioPosterAlt: "Audio poster preview",
481
+ audioPosterHint: "With a poster or icon set, the progress bar is hidden; click the icon to play/pause.",
482
+ videoUrl: "Video URL",
483
+ uploadVideo: "Upload video",
484
+ imageUrlCss: "Image URL / CSS",
485
+ imageUrlHintLabel: "Image URL",
486
+ imageUrlHint: "Use a remote URL or url(\"data:...\"); uploads are saved as base64 automatically.",
487
+ objectFit: "Object fit",
488
+ objectFitFull: "Object fit (object-fit / background-size)",
489
+ fitCover: "cover (crop to fill)",
490
+ fitContain: "contain (fit entirely)",
491
+ fitFill: "fill (stretch)",
492
+ alignPosition: "Alignment",
493
+ shape: "Shape",
494
+ selectShape: "Select shape",
495
+ shapeRect: "Rectangle",
496
+ shapeCircle: "Circle",
497
+ shapeTriangle: "Triangle",
498
+ shapeDiamond: "Diamond",
499
+ shapeHexagon: "Hexagon",
500
+ shapeStar: "Star",
501
+ shapeHeart: "Heart",
502
+ color: "Color",
503
+ geometryColor: "Geometry color",
504
+ canvasScriptHint: "Canvas draw logic; variables: ctx, width, height, element. Script errors are ignored safely.",
505
+ penColor: "Pen color",
506
+ penWidth: "Pen width",
507
+ applySketch: "Apply sketch to node",
508
+ clearSketch: "Clear sketch",
509
+ rows: "Rows",
510
+ cols: "Columns",
511
+ rowCount: "Row count",
512
+ colCount: "Column count",
513
+ gapPx: "Gap (px)",
514
+ paddingPx: "Padding (px)",
515
+ snapThresholdPx: "Snap threshold (px)",
516
+ gridHint: "Nodes dragged near a slot center snap into the grid and appear as children in the node tree.",
517
+ colSpan: "Column span (colSpan)",
518
+ rowSpan: "Row span (rowSpan)",
519
+ gridChildHint: "Grid children can span multiple cells for complex layouts.",
520
+ refLayer: "Referenced layer",
521
+ noneNoRef: "None (no reference)",
522
+ copyMode: "Copy mode",
523
+ copy: "Copy",
524
+ selectCopyMode: "Select copy mode",
525
+ shallowFollow: "Shallow copy (follow source layer)",
526
+ deepFreeze: "Deep copy (freeze current snapshot)",
527
+ copyStrategyHint: "Shallow copy syncs the referenced layer live; deep copy freezes the snapshot.",
528
+ doubleClickText: "Double-click to enter text",
529
+ slotOccupied: "Slot {n} (occupied)",
530
+ slotEmpty: "Slot {n} (empty)",
531
+ configureAudioFirst: "Configure an audio source first",
532
+ clickPause: "Click to pause",
533
+ clickPlay: "Click to play",
534
+ audioNotConfigured: "Audio not configured",
535
+ pause: "Pause",
536
+ play: "Play",
537
+ audioPlaceholder: "Audio placeholder",
538
+ audioPlaying: "Audio playing",
539
+ audioReady: "Audio ready",
540
+ videoPlaceholder: "Video placeholder",
541
+ imagePlaceholder: "Image placeholder",
542
+ materialPlaceholder: "{type} placeholder",
543
+ refLayerEmpty: "Referenced layer has no nodes",
544
+ selectRefLayer: "Select a referenced layer on the right",
545
+ nodeLockedBadge: "Locked",
546
+ nodeLockedTitle: "Node locked",
547
+ lockedExcludedBadge: "Locked nodes excluded",
548
+ lockedExcludedTitle: "Some nodes are locked and were excluded automatically",
549
+ searchKwLayout: "layout",
550
+ searchKwBorder: "border",
551
+ searchKwWidth: "width",
552
+ searchKwRadius: "radius",
553
+ searchKwStyle: "style",
554
+ searchKwXAxis: "x-axis",
555
+ searchKwYAxis: "y-axis",
556
+ searchKwTick: "tick",
557
+ searchKwSplit: "split line",
558
+ searchKwAdvanced: "advanced",
559
+ searchKwRichText: "rich text",
560
+ searchKwAutoPause: "auto pause",
561
+ searchKwGrid: "grid",
562
+ searchKwColor: "color",
563
+ searchKwAlign: "align",
564
+ searchKwLineHeight: "line height",
565
+ searchKwInput: "input",
566
+ searchKwRecord: "record",
567
+ searchKwPoster: "poster",
568
+ searchKwChart: "chart",
569
+ searchKwCrossCol: "col span",
570
+ searchKwCrossRow: "row span",
571
+ searchKwGap: "gap",
572
+ searchKwPadding: "padding",
573
+ searchKwSnap: "snap",
574
+ searchKwThreshold: "threshold",
575
+ searchKwFont: "font",
576
+ searchKwUpload: "upload",
577
+ searchKwPreview: "preview",
578
+ searchKwScript: "script",
579
+ searchKwSketch: "sketch",
580
+ searchKwRef: "reference",
581
+ rowsShort: "Rows",
582
+ colsShort: "Cols",
583
+ groupTableData: "1. Data source",
584
+ groupTableAppearance: "3. Appearance",
585
+ groupTableColumnDetail: "Column detail · {name}",
586
+ groupTableDataHint:
587
+ "Prefer Scope binding; you can also paste static JSON. Dynamic wins when non-empty; otherwise fall back to static; if both empty, show empty state.",
588
+ groupTableAppearanceHint: "Header, stripes, row height, and base colors.",
589
+ groupTableColumns: "2. Columns (order & width)",
590
+ groupTableColumnsHint:
591
+ "Use up/down to reorder columns; edit width on the right. Select a column to configure field and widget below.",
592
+ tableMoveColumnUp: "Move up",
593
+ tableMoveColumnDown: "Move down",
594
+ tableAdvancedData: "Advanced data options",
595
+ tableAdvancedDataHint: "Transform mode, list path, and row id field — defaults are usually fine.",
596
+ tableSource: "Scope binding",
597
+ tableSourceHint:
598
+ "Template from blueprint output, e.g. {scope?.list} or {scope?.data?.rows}. Non-empty data overrides static rows below.",
599
+ tableRowsText: "Static rows (JSON)",
600
+ tableRowsTextHint:
601
+ "Default demo data for a new table. Used when Scope is unbound, empty, or fails to resolve.",
602
+ tableRowsEdit: "Edit JSON",
603
+ tableRowsMock: "Generate mock data",
604
+ tableRowsEditTitle: "Edit static rows",
605
+ tableRowsEditDesc: "Edit a JSON array. Format is validated before save.",
606
+ tableRowsEditEditorHint: "Tab to indent · foldable",
607
+ tableRowsEditFormat: "Format",
608
+ tableRowsEditNeedArray: "Please provide a JSON array, e.g. [{...}]", tableRowsEditInvalidJson: "Invalid JSON. Please fix and retry.",
609
+ tableRowsMockTitle: "Generate mock rows",
610
+ tableRowsMockDesc:
611
+ "Generates values from current columns (name/status/score/email…). Configure count, prefix, status enums, score range, and extras.",
612
+ tableMockRowCount: "Row count",
613
+ tableMockLocale: "Locale style",
614
+ tableMockLocaleZh: "Chinese",
615
+ tableMockLocaleEn: "English",
616
+ tableMockNamePrefix: "Name prefix",
617
+ tableMockSeed: "Seed (optional)",
618
+ tableMockStatusValues: "Status values (comma-separated)",
619
+ tableMockScoreMin: "Score min",
620
+ tableMockScoreMax: "Score max",
621
+ tableMockIncludeId: "Include id",
622
+ tableMockIncludeTimestamp: "Include createdAt",
623
+ tableMockIncludeExtras: "Add email/phone/city extras",
624
+ tableMockGenerate: "Generate",
625
+ tableTransformMode: "Data shape",
626
+ tableTransformModeHint:
627
+ "Auto: detect; Records: [{field:value}]; Matrix: 2D array; Path: pick a nested list by path.",
628
+ tableTransformPath: "List path",
629
+ tableTransformPathHint: "When data is nested, e.g. data.list means raw.data.list.",
630
+ tableRowIdField: "Row id field",
631
+ tableRowIdFieldHint: "Stable row id for virtualization. Leave empty to auto-generate.",
632
+ tableShowHeader: "Show header",
633
+ tableStripe: "Stripe rows",
634
+ tableStripeHint: "Alternating row backgrounds for long tables.",
635
+ tableRowHeight: "Row height (px)",
636
+ tableRowHeightHint: "Used by virtual scroll sizing; 28–48 is typical.",
637
+ tableStyleColor: "Table text color",
638
+ tableStyleFontSize: "Table font size",
639
+ tableHeaderBg: "Header background",
640
+ tableHeaderFontSize: "Header font size",
641
+ tableColumns: "Columns",
642
+ tableColumnsHint: "Which fields to show, header labels, widths, and cell widgets (text/tag/…).",
643
+ tableColumnField: "Data field",
644
+ tableColumnFieldHint: "Property name on each row, e.g. name or status.",
645
+ tableColumnTitle: "Header label",
646
+ tableColumnTitleHint: "Title shown in the header; can differ from the field name.",
647
+ tableColumnWidth: "Width (px)",
648
+ tableColumnWidget: "Cell display",
649
+ tableColumnWidgetHint:
650
+ "Text; Tag/Badge for colored marks; Link; Progress for ratios; Image/Boolean for those shapes.",
651
+ tableDisplayTemplate: "Display template",
652
+ tableDisplayTemplateHint:
653
+ "Runs after value mapping. {current}/{value} is the mapped value; {row.field} works too. E.g. mapped 10 + {current}分 → 10分. Leave empty to show the mapped result as-is.",
654
+ tableTooltipEnabled: "Enable tooltip",
655
+ tableTooltipEnabledHint: "Show a tooltip on hover; configure placement and template separately.",
656
+ tableTooltipPlacementLabel: "Tooltip placement",
657
+ tableTooltipPlacement: {
658
+ top: "Top",
659
+ right: "Right",
660
+ bottom: "Bottom",
661
+ left: "Left",
662
+ },
663
+ tableTooltipTemplate: "Tooltip template",
664
+ tableTooltipTemplateHint:
665
+ "Same placeholders as the display template (based on the mapped value); leave empty to use the final cell text.",
666
+ tableWidgetProps: "Widget options",
667
+ tableWidgetPropsHint: "Configure link URL, image source, progress max, etc. per widget.",
668
+ tableImageUrlMode: "Image URL source",
669
+ tableImageUrlModeHint:
670
+ "Field: use a row field as URL; Static: paste/upload/Scope template; Prefix: CDN prefix + field; Template: build with {value}/{row.xxx}.",
671
+ tableImageUrlModeField: "Row field (URL)",
672
+ tableImageUrlModeStatic: "Static / upload / Scope",
673
+ tableImageUrlModePrefix: "Prefix + field + suffix",
674
+ tableImageUrlModeTemplate: "URL template",
675
+ tableImageUrl: "Image URL",
676
+ tableImageUrlHint:
677
+ "https://…, data:…, or Scope template like {scope?.cdnAvatar}; or upload below.",
678
+ tableImageUrlField: "URL field",
679
+ tableImageUrlFieldHint: "Row field holding path/URL; defaults to this column field.",
680
+ tableImageUrlPrefix: "URL prefix",
681
+ tableImageUrlPrefixHint: "e.g. https://cdn.example.com/ or {scope?.cdn}/, then append field.",
682
+ tableImageUrlSuffix: "URL suffix",
683
+ tableImageUrlSuffixHint: "Optional, e.g. .png or a query string.",
684
+ tableImageUrlTemplate: "URL template",
685
+ tableImageUrlTemplateHint: "e.g. https://cdn/{row.id}.png or {value}; supports {value}, {row.field}.",
686
+ tableImageUpload: "Upload image",
687
+ tableImageWidth: "Thumb width",
688
+ tableImageHeight: "Thumb height",
689
+ tableImageObjectFit: "Object fit",
690
+ tableImageFitCover: "Cover",
691
+ tableImageFitContain: "Contain",
692
+ tableImageFitFill: "Fill",
693
+ tableTagColor: "Tag color",
694
+ tableTagColorHint: "Default color when no color-map entry matches.",
695
+ tableColorMap: "Color by value (no condition)",
696
+ tableColorMapHint: "When display/raw value equals the left text, use that color. e.g. ok → green.",
697
+ tableAddColorMap: "Add color",
698
+ tableColorMapValue: "Match value",
699
+ tableColorMapColor: "Color",
700
+ tableHrefRules: "Conditional hrefs",
701
+ tableHrefRulesHint: "First matching rule wins; else fall back to href field/template/value. Supports {value}/{row.xxx}.",
702
+ tableAddHrefRule: "Add href rule",
703
+ tableHrefRuleItem: "Href rule {n}",
704
+ tableHrefRuleHref: "Href",
705
+ tableProgressMode: "Progress source",
706
+ tableProgressModeHint: "Field: numeric row field; Static: fixed/Scope; Rules: value by condition.",
707
+ tableProgressModeField: "Numeric field",
708
+ tableProgressModeStatic: "Static / Scope",
709
+ tableProgressModeRules: "By condition",
710
+ tableProgressField: "Progress field",
711
+ tableProgressFieldHint: "Field holding the number; defaults to this column.",
712
+ tableProgressStatic: "Static progress",
713
+ tableProgressStaticHint: "Number, or Scope template like {scope?.pct} (must resolve to a number).",
714
+ tableProgressRules: "Conditional progress",
715
+ tableAddProgressRule: "Add progress rule",
716
+ tableProgressRuleItem: "Progress rule {n}",
717
+ tableProgressRuleValue: "Progress value",
718
+ tableActionOnClick: "On click → blueprint node",
719
+ tableActionOnTrue: "On enable → blueprint node",
720
+ tableActionOnFalse: "On disable → blueprint node",
721
+ tableActionBlueprintHint: "Pick a blueprint node from the list, or None to skip. Injects a true signal; Logic can read scope.__uiEventPayload.",
722
+ tableActionBlueprintPlaceholder: "Select blueprint node",
723
+ tableActionBlueprintNone: "None (no trigger)",
724
+ tableLinkHrefField: "Href field",
725
+ tableLinkHrefFieldHint: "Row field for href; empty uses this column value.",
726
+ tableLinkHrefTemplate: "Href template",
727
+ tableLinkHrefTemplateHint: "e.g. /detail/{row.id}; supports {value}, {row.field}.",
728
+ tableLinkOpenNewTab: "Open in new tab",
729
+ tableProgressMax: "Progress max",
730
+ tableProgressShowLabel: "Show percent",
731
+ tableProgressDisplay: "Progress look",
732
+ tableProgressDisplayHint:
733
+ "Bar+label, bar only, percent text only, or circular progress.",
734
+ tableProgressDisplayBarLabel: "Bar + text",
735
+ tableProgressDisplayBar: "Bar only",
736
+ tableProgressDisplayLabel: "Text percent only",
737
+ tableProgressDisplayCircle: "Circular",
738
+ tableProgressSize: "Circle size (px)",
739
+ tableTextFontSize: "Font size",
740
+ tableTextFontWeight: "Font weight",
741
+ tableTextColor: "Text color",
742
+ tableTextFontFamily: "Font family",
743
+ tableTextFontStyle: "Font style",
744
+ tableTextDecoration: "Decoration",
745
+ tableTextWeightNormal: "Normal",
746
+ tableTextWeightBold: "Bold",
747
+ tableTextStyleNormal: "Normal",
748
+ tableTextStyleItalic: "Italic",
749
+ tableTextDecoNone: "None",
750
+ tableTextDecoUnderline: "Underline",
751
+ tableTextDecoLineThrough: "Line-through",
752
+ tableBooleanTrueLabel: "True label",
753
+ tableBooleanFalseLabel: "False label",
754
+ tableBooleanYes: "Yes",
755
+ tableBooleanNo: "No",
756
+ tableColumnUntitled: "Column {n}",
757
+ tableAddColumn: "Add column",
758
+ tableRemoveColumn: "Remove",
759
+ tableNoColumns: "No columns yet",
760
+ tableValueMap: "Display value mapping",
761
+ tableValueMapHint:
762
+ "First replace the raw value (templates allowed: {current}/{value}/{row.field}), e.g. ok → Normal or {current}-passed. Unmatched values stay unchanged; then the display template is applied.",
763
+ tableValueMapBooleanHint:
764
+ "Boolean column: map raw values to Yes or No. Multiple rules may map to the same side; if the same condition maps to both Yes and No, a conflict warning is shown.",
765
+ tableValueMapBooleanConflict:
766
+ "Conflict: the same condition maps to both Yes and No (mappings {indexes}). Keep only one side.",
767
+ tableAddValueMap: "Add mapping",
768
+ tableMapItem: "Mapping {n}",
769
+ tableDisplayBoolean: "Map to",
770
+ tableDisplayBooleanHint: "When matched, treat the cell as Yes or No.",
771
+ tableStyleRuleItem: "Style rule {n}",
772
+ tableCellStyleRules: "Conditional cell styles",
773
+ tableCellStyleRulesHint:
774
+ "Restyle a cell when a condition matches, e.g. highlight when score > 80. Field can be empty to use this column.",
775
+ tableAddCellStyleRule: "Add style rule",
776
+ tableRowStyleRules: "Conditional row styles",
777
+ tableRowStyleRulesHint: "Color a whole row when it matches, e.g. status = bad.",
778
+ tableAddRowStyleRule: "Add row style",
779
+ tableNoRowStyleRules: "No row style rules",
780
+ tableConditionOp: "When",
781
+ tableConditionOpHint: "Pick how to compare, then fill the value on the right.",
782
+ tableConditionLogic: "Logic",
783
+ tableConditionLogicAnd: "AND (all match)",
784
+ tableConditionLogicOr: "OR (any match)",
785
+ tableConditionLogicNot: "NOT (negate all-match)",
786
+ tableConditionLogicHint:
787
+ "Default is AND. Add multiple sub-conditions; NOT negates the AND of the group.",
788
+ tableConditionAddItem: "Add sub-condition",
789
+ tableConditionItem: "Sub-condition {n}",
790
+ tableConditionField: "Field to check",
791
+ tableConditionFieldHint: "Row field to compare. For cell rules, leave empty to use this column.",
792
+ tableConditionValue: "Compare to",
793
+ tableConditionValueHint: "Target value, e.g. ok or 80.",
794
+ tableTextOverflow: "Text overflow",
795
+ tableTextOverflowHint: "Ellipsis: single-line truncate; Wrap: wrap inside the cell.",
796
+ tableTextOverflowEllipsis: "Ellipsis",
797
+ tableTextOverflowWrap: "Wrap",
798
+ tableDisplayValue: "Show as",
799
+ tableDisplayValueHint:
800
+ "Text when matched. Templates: {current}/{value} = raw cell value, {row.field} = other columns.",
801
+ tableBgColor: "Background",
802
+ tableBgColorHint: "Background when the rule matches (#hex or rgba).",
803
+ tableEmpty: "No data",
804
+ tableColName: "Name",
805
+ tableColStatus: "Status",
806
+ tableColScore: "Score",
807
+ tableMode: {
808
+ auto: "Auto detect",
809
+ records: "Object array (recommended)",
810
+ matrix: "2D matrix",
811
+ path: "By path",
812
+ },
813
+ tableWidget: {
814
+ text: "Text",
815
+ tag: "Colored tag",
816
+ badge: "Dot badge",
817
+ link: "Link",
818
+ progress: "Progress",
819
+ image: "Image",
820
+ boolean: "Yes / No",
821
+ },
822
+ tableOp: {
823
+ eq: "Equals",
824
+ neq: "Not equal",
825
+ gt: "Greater than",
826
+ gte: "Greater or equal",
827
+ lt: "Less than",
828
+ lte: "Less or equal",
829
+ contains: "Contains",
830
+ startsWith: "Starts with",
831
+ endsWith: "Ends with",
832
+ in: "In list",
833
+ empty: "Is empty",
834
+ notEmpty: "Not empty",
835
+ regex: "Matches regex",
836
+ truthy: "Is truthy",
837
+ falsy: "Is falsy",
838
+ },
839
+ tableConditionFieldPlaceholder: "Field name",
840
+ tableConditionValuePlaceholder: "Compare value",
841
+ },
842
+ messages: {
843
+ nodeNotFound: "Node not found; it may have been deleted",
844
+ sourceNodeNotFound: "Source node not found; it may have been deleted",
845
+ targetLayerNotFound: "Target layer does not exist",
846
+ nodeMoveSameLayer: "Already on the current layer",
847
+ nodeDeleteLocked: "Locked nodes cannot be deleted. Unlock in Node info on the right, then retry",
848
+ nodeDeleteLayerLocked: "The node's layer is locked; cannot delete. Unlock it in the layers panel first",
849
+ nodeBatchDeleteContainsLocked: "Selection includes locked nodes; cannot batch-delete. Unlock them in Node info first",
850
+ nodeMoveLocked: "Locked nodes cannot change layers. Unlock in Node info on the right first",
851
+ nodeMoveSourceLayerLocked: "The node's layer is locked; cannot change layers. Unlock it in the layers panel first",
852
+ nodeMoveTargetLayerLocked: "Target layer is locked; cannot move into it. Unlock it in the layers panel first",
853
+ activeLayerLockedCannotAdd: "Current layer is locked; cannot add nodes",
854
+ nodeLayerLockedCannotCopy: "The node's layer is locked; cannot copy",
855
+ selectionContainsLockedLayerNode: "Selection includes locked-layer content; cannot batch-delete",
856
+ sourceLayerLockedCannotPaste: "Source node's layer is locked; cannot paste",
857
+ nodeConfigLocked: "This node is locked; config fields are read-only.",
858
+ nodeConfigLayerLocked: "This node's layer is locked; config fields are read-only.",
859
+ readImageFailed: "Failed to read image",
860
+ readAudioFailed: "Failed to read audio",
861
+ readVideoFailed: "Failed to read video",
862
+ readRecordAudioFailed: "Failed to read recording",
863
+ audioLocalSaved: "Saved local audio (base64)",
864
+ audioRemoteUploaded: "Uploaded to server and updated remote URL",
865
+ audioServerUploadFailed: "Server upload failed; kept local audio only",
866
+ audioPosterSet: "Audio poster set",
867
+ audioRecordUnsupported: "Recording is not supported in this environment",
868
+ audioRecordSaved: "Recording saved; ready to play",
869
+ audioRecording: "Recording...",
870
+ audioRecordStartFailed: "Cannot start recording; check microphone permission",
871
+ videoLocalSaved: "Saved local video (base64)",
872
+ videoRemoteUploaded: "Uploaded to server and updated remote URL",
873
+ videoServerUploadFailed: "Server upload failed; kept local video only",
874
+ operationRestricted: "Operation restricted",
875
+ importInvalidFormat: "Import failed: invalid file format",
876
+ importJsonParseError: "Import failed: JSON parse error",
877
+ blueprintImportInvalid: "Blueprint import failed: invalid file format",
878
+ iconReadFailed: "Failed to read icon; please retry",
879
+ blueprintNotFound: "Blueprint not found or has been deleted",
880
+ blueprintSynced: "Synced \"{name}\"",
881
+ blueprintSavedLocal: "Blueprint saved locally",
882
+ blueprintSavedToLibrary: "Blueprint saved to library",
883
+ blueprintSyncedToLibrary: "Blueprint synced to library",
884
+ blueprintExported: "Blueprint exported",
885
+ blueprintRenamed: "Blueprint renamed",
886
+ renameFailed: "Rename failed",
887
+ blueprintDeletedFromLibrary: "Blueprint deleted from library",
888
+ blueprintImported: "Blueprint imported and loaded",
889
+ workspaceCreated: "Created workspace \"{name}\"",
890
+ workspaceLoaded: "Workspace loaded",
891
+ workspaceLoadedDesc: "View and blueprint restored",
892
+ openWorkspaceFailed: "Failed to open workspace",
893
+ syncFailed: "Sync failed",
894
+ workspaceDeleted: "Workspace deleted",
895
+ openPreviewFailed: "Failed to open preview",
896
+ clearedBlueprintLogs: "Cleared {removed} blueprint log(s) from IndexedDB",
897
+ noSavedBlueprintLogs: "No saved logs in IndexedDB",
898
+ mergeNeedTwoLayers: "Select at least 2 layers to merge",
899
+ layerNotFound: "Layer not found",
900
+ defaultLayerCannotDelete: "Default layer cannot be deleted",
901
+ lockedLayerCannotDelete: "Locked layer cannot be deleted",
902
+ selectTargetLayer: "Please select a target layer",
903
+ shallowRefBlockingDelete: "This layer is still shallow-referenced; delete reference nodes or switch to deep copy first",
904
+ noNodesSelected: "No nodes selected",
905
+ noMigratableNodes: "No migratable nodes found",
906
+ lockedCannotOpenMapping: "Selection includes locked content; cannot open in a new layer",
907
+ saveWorkspaceFirst: "Please save the workspace first",
908
+ workspaceNotFound: "Workspace not found or has been deleted",
909
+ workspaceDataInvalid: "Invalid workspace data format",
910
+ },
911
+ defaults: {
912
+ unnamedProduct: "Untitled product",
913
+ unnamedBlueprint: "Untitled blueprint",
914
+ layer1: "Layer 1",
915
+ layerN: "Layer {n}",
916
+ layerRandom: "Layer-{id}",
917
+ mappingLayerN: "Mapping layer {n}",
918
+ doubleClickTextHtml: "Double-click to enter text",
919
+ bar: "Bar chart",
920
+ line: "Line chart",
921
+ area: "Area chart",
922
+ scatter: "Scatter chart",
923
+ radar: "Radar chart",
924
+ gauge: "Gauge",
925
+ funnel: "Funnel chart",
926
+ pie: "Pie chart",
927
+ text: "Text",
928
+ grid: "Grid layout",
929
+ image: "Image",
930
+ video: "Video",
931
+ audio: "Audio",
932
+ reference: "Reference",
933
+ geometry: "Geometry",
934
+ table: "Table",
935
+ },
936
+ workspace: {
937
+ create: "Create workspace",
938
+ createHint: "Create a new IndexedDB workspace with the current product name without overwriting existing ones",
939
+ syncDirty: "Sync *",
940
+ syncUpdate: "Sync \"{name}\" to IndexedDB",
941
+ syncUpToDate: "Workspace is in sync with IndexedDB",
942
+ currentWorkspaceFallback: "Current workspace",
943
+ savedWorkspaces: "Saved workspaces",
944
+ workspaceNamed: "Workspace: {name}",
945
+ noSavedWorkspaces: "No saved workspaces",
946
+ deleteConfirmTitle: "Delete workspace?",
947
+ deleteConfirmBody: "Permanently delete \"{name}\" from IndexedDB. This cannot be undone.",
948
+ blueprintLibrary: "Blueprint library",
949
+ saveBlueprintToLibrary: "Save blueprint to library",
950
+ syncBlueprint: "Sync blueprint",
951
+ noSyncChanges: "Nothing to sync",
952
+ lifecycle: "Lifecycle",
953
+ canvasLoading: "Loading canvas…",
954
+ configEmptyTitle: "No blueprint node selected",
955
+ configEmptyDesc: "Select a node in the blueprint panel to see its config here.",
956
+ previewLoading: "Loading preview…",
957
+ previewNoNodes: "This workspace has no view nodes to preview",
958
+ previewHint: "Click Sync or Create workspace in the editor before previewing",
959
+ previewDocTitle: "Preview",
960
+ },
961
+ layers: {
962
+ title: "Layers",
963
+ mapping: "Mapping",
964
+ primary: "Primary",
965
+ mappingLayer: "Mapping layer",
966
+ primaryLayer: "Primary layer",
967
+ expandInput: "Expand input",
968
+ collapseInput: "Collapse input",
969
+ expandInputAria: "Expand layer input",
970
+ collapseInputAria: "Collapse layer input",
971
+ add: "Add layer",
972
+ addShort: "New",
973
+ merge: "Merge layers",
974
+ mergeShort: "Merge",
975
+ mergeNeedTwo: "Select at least 2 layers to merge",
976
+ namePlaceholder: "Enter layer name",
977
+ setPrimary: "Set as primary layer",
978
+ isPrimary: "Current primary layer",
979
+ setPrimaryHint: "Set as primary layer (used for preview)",
980
+ isPrimaryHint: "Current primary layer (used for preview)",
981
+ lock: "Lock layer",
982
+ unlock: "Unlock layer",
983
+ lockShort: "Lock",
984
+ unlockShort: "Unlock",
985
+ rename: "Rename layer",
986
+ renameShort: "Rename",
987
+ saveName: "Save layer name",
988
+ cancelEditName: "Cancel editing layer name",
989
+ cancelEdit: "Cancel edit",
990
+ delete: "Delete layer",
991
+ cannotDeleteDefault: "Default layer cannot be deleted",
992
+ cannotDeleteLocked: "Locked layer cannot be deleted",
993
+ selectMergeLayers: "Select layers to merge",
994
+ mappingCannotMerge: "Mapping layers cannot be merged",
995
+ cannotMergeSuffix: "(cannot merge)",
996
+ mergedName: "Merged layer name",
997
+ mergedNamePlaceholder: "Optional; leave empty for a random name",
998
+ mergedNamePlaceholderOptional: "Merged layer name (optional)",
999
+ confirmMerge: "Confirm merge",
1000
+ confirmMergeAria: "Confirm merge layers",
1001
+ cancelMerge: "Cancel merge",
1002
+ cancelMergeAria: "Cancel merge layers",
1003
+ joinMerge: "Include in merge",
1004
+ mergeDialogTitle: "Merge layers",
1005
+ mergeOk: "Merge",
1006
+ mergeSelectedCount: "{count} layers selected",
1007
+ confirmDeleteTitle: "Confirm delete",
1008
+ confirmDeleteMappingBody: "This will delete {count} related mapping layer(s). Continue?",
1009
+ continueDelete: "Continue deleting",
1010
+ confirmDeleteLayerTitle: "Confirm delete layer",
1011
+ aboutToDeleteLayer: "About to delete layer: {name}",
1012
+ migrateNodesTo: "Migrate nodes to",
1013
+ selectTargetLayer: "Select target layer",
1014
+ pleaseSelectLayer: "Please select a layer",
1015
+ deleteMappingWithNodes: "Delete mapping layer and its nodes",
1016
+ deleteAllNodesToo: "Also delete all nodes on this layer",
1017
+ confirmDelete: "Confirm delete",
1018
+ },
1019
+ scope: {
1020
+ dataTitle: "Scope data",
1021
+ templateHintLabel: "Scope template",
1022
+ updated: "Updated",
1023
+ expand: "Expand scope",
1024
+ collapse: "Collapse scope",
1025
+ usageHint1: "Use template strings to reference scope in forms, e.g. {scope?.a||0}, {scope?.name||''}. Supports ?. and || placeholders.",
1026
+ usageHint2: "Array-spread templates [...{scope?.a?.b}], [...{scope?.data?.data?.statusName}]: output comma-separated strings in text fields; expand to n items in chart category arrays (e.g. 3 records → 3 categories).",
1027
+ previewTitle: "Resolved preview",
1028
+ previewArray: "Array · {count} item(s)",
1029
+ expandPreview: "Expand",
1030
+ collapsePreview: "Collapse",
1031
+ warningsTitle: "Usage warnings",
1032
+ expandWarnings: "Expand warnings",
1033
+ collapseWarnings: "Collapse warnings",
1034
+ fieldName: "Node name",
1035
+ fieldTextHtml: "Text content",
1036
+ fieldTextFontFamily: "Text font family",
1037
+ fieldTextFontWeight: "Text font weight",
1038
+ fieldTextColor: "Text color",
1039
+ fieldChartTitle: "Chart title",
1040
+ fieldChartColor: "Chart color",
1041
+ fieldChartGradientFrom: "Gradient start",
1042
+ fieldChartGradientTo: "Gradient end",
1043
+ fieldChartXAxisName: "X-axis name",
1044
+ fieldChartYAxisName: "Y-axis name",
1045
+ fieldChartXAxisTickColor: "X-axis tick color",
1046
+ fieldChartYAxisTickColor: "Y-axis tick color",
1047
+ fieldChartXAxisSplitLineColor: "X-axis split-line color",
1048
+ fieldChartYAxisSplitLineColor: "Y-axis split-line color",
1049
+ fieldChartXAxisLabelColor: "X-axis label color",
1050
+ fieldChartYAxisLabelColor: "Y-axis label color",
1051
+ fieldChartTooltipBackgroundColor: "Tooltip background color",
1052
+ fieldChartTooltipTextColor: "Tooltip text color",
1053
+ fieldChartTooltipFormatter: "Tooltip formatter",
1054
+ fieldChartLabelsText: "Chart categories",
1055
+ fieldChartValuesText: "Chart values",
1056
+ fieldStyleBackgroundColor: "Background color",
1057
+ fieldStyleBackgroundImage: "Background image",
1058
+ fieldStyleBackgroundImageRemoteUrl: "Background image remote URL",
1059
+ fieldStyleBackgroundSize: "Background size",
1060
+ fieldStyleBackgroundPosition: "Background position",
1061
+ fieldStyleBorderColor: "Border color",
1062
+ fieldAudioSrc: "Audio URL",
1063
+ fieldAudioRemoteUrl: "Audio remote URL",
1064
+ fieldVideoSrc: "Video URL",
1065
+ fieldVideoRemoteUrl: "Video remote URL",
1066
+ fieldGeometryColor: "Geometry color",
1067
+ fieldGeometryScript: "Geometry script",
1068
+ warnMissingPath: "\"{fieldLabel}\" references scope.{path}, but \"{path}\" is missing from the current scope. Please check.",
1069
+ warnSpreadNotArray: "\"{fieldLabel}\" uses {template}, which only maps array values, but scope.{arrayPath} is not an array. Example: with scope {demoScope}, {demoTemplate} outputs {demoOutput}; deep paths can use {deepTemplate} (scope {deepScope} → {deepOutput}).",
1070
+ warnSpreadInvalid: "\"{fieldLabel}\" has invalid {template}. Use {demoTemplate} or {deepTemplate}. Example: with scope {demoScope}, output is {demoOutput}.",
1071
+ demoInProgress: "In progress",
1072
+ demoDone: "Done",
1073
+ demoJoined: "In progress,Done",
1074
+ },
1075
+ history: {
1076
+ title: "History",
1077
+ expand: "Expand history",
1078
+ collapse: "Collapse history",
1079
+ searchPlaceholder: "Search history, e.g. delete, layer, zoom...",
1080
+ emptyTitle: "No history yet",
1081
+ emptyDesc: "After you perform an action, history appears here.",
1082
+ noMatchTitle: "No history matched",
1083
+ noMatchDesc: "Try another keyword, e.g. delete, layer, zoom.",
1084
+ initial: "Initialize",
1085
+ nodeUpdate: "Update node",
1086
+ nodeGroupDrag: "Batch move nodes",
1087
+ nodeGroupResize: "Batch resize nodes",
1088
+ nodeGroupRotate: "Batch rotate nodes",
1089
+ nodeDelete: "Delete node",
1090
+ nodeBatchDelete: "Batch delete nodes",
1091
+ nodeZFront: "Bring node to front",
1092
+ nodeZBack: "Send node to back",
1093
+ nodeZUp: "Bring node forward",
1094
+ nodeZDown: "Send node backward",
1095
+ nodeDuplicate: "Duplicate node",
1096
+ nodeRefCopyMode: "Set reference copy mode",
1097
+ nodeAdd: "Add node",
1098
+ layerActivate: "Switch layer",
1099
+ layerAdd: "Add layer",
1100
+ layerRename: "Rename layer",
1101
+ layerToggleLock: "Toggle layer lock",
1102
+ layerOpenSelectedMapping: "Open selection in mapping layer",
1103
+ layerDelete: "Delete layer",
1104
+ layerToggleMerge: "Toggle merge selection",
1105
+ layerMerge: "Merge layers",
1106
+ layerSetPrimary: "Set primary layer",
1107
+ panelImport: "Import panel",
1108
+ fallback: "Edit",
1109
+ },
1110
+ theme: {
1111
+ switchToLight: "Switch to light",
1112
+ switchToDark: "Switch to dark",
1113
+ toggleTheme: "Toggle theme",
1114
+ toggleThemeHint: "Toggle dark / light theme",
1115
+ language: "Language",
1116
+ zhCN: "中文",
1117
+ enUS: "English",
1118
+ },
1119
+ },
1120
+ blueprint: {
1121
+ toolbar: {
1122
+ library: "Blueprint library",
1123
+ libraryEmpty: "Library is empty",
1124
+ saved: "Saved",
1125
+ imported: "Imported",
1126
+ openLibraryTooltip: "Open library: click to load; click the selected item again to return to the workspace blueprint",
1127
+ clickAgainReturnWorkspace: "Click again to return to the workspace blueprint",
1128
+ renameTooltip: "Rename \"{name}\"",
1129
+ renameAriaLabel: "Rename {name}",
1130
+ deleteTooltip: "Delete \"{name}\" from library",
1131
+ deleteAriaLabel: "Delete {name}",
1132
+ saveToLocalLibrary: "Save blueprint to local library",
1133
+ saveToLocalAriaLabel: "Save blueprint locally",
1134
+ syncUpdateNamed: "Sync update library item \"{name}\"",
1135
+ syncToLibrary: "Sync current edits to the library",
1136
+ alreadyInSyncNamed: "\"{name}\" already matches the library version",
1137
+ selectBlueprintFirst: "Select a blueprint from the library first",
1138
+ syncAriaLabel: "Sync blueprint to library",
1139
+ simulateScene: "Simulate scene",
1140
+ simulateSceneTooltip: "Simulate scene: pick a lifecycle node as the current lifecycle phase",
1141
+ simulateSceneAriaLabel: "Simulate scene",
1142
+ runAllTooltip: "Run all: execute the full task chain from the selected lifecycle node",
1143
+ runAllAriaLabel: "Run all",
1144
+ resetToStartTooltip: "Reset: clear execution history and restart debug from the selected lifecycle node",
1145
+ resetToStartAriaLabel: "Reset to start",
1146
+ stepBackTooltip: "Step back: undo the last node execution and restore log / canvas state",
1147
+ stepBackAriaLabel: "Step back",
1148
+ stepNextTooltip: "Step next: send a true signal to the next node, one node at a time",
1149
+ stepNextFalseHalt: "Current node emitted a false signal; cannot step next",
1150
+ stepNextChainComplete: "Already at the last node; task chain finished",
1151
+ stepNextAriaLabel: "Step next",
1152
+ logPanelTooltip: "Task output log: view node timing, inputs, and outputs on the right",
1153
+ logPanelAriaLabel: "Task output log",
1154
+ addNode: "Add node",
1155
+ deleteNode: "Delete node",
1156
+ deleteEdge: "Delete edge",
1157
+ },
1158
+ dialog: {
1159
+ renameTitle: "Rename blueprint",
1160
+ renameDescription: "Change the display name of this library item.",
1161
+ blueprintName: "Blueprint name",
1162
+ cancel: "Cancel",
1163
+ confirm: "Confirm",
1164
+ deleteTitle: "Delete blueprint",
1165
+ deleteDescription: "Delete \"{name}\" from the library? This cannot be undone.",
1166
+ delete: "Delete",
1167
+ exportTitle: "Export blueprint",
1168
+ saveTitle: "Save blueprint",
1169
+ exportDescription: "Enter a name and notes, then export the current blueprint as JSON.",
1170
+ saveDescription: "Enter a name and notes, then save the current blueprint to the local library.",
1171
+ export: "Export",
1172
+ save: "Save",
1173
+ unnamedBlueprint: "Untitled blueprint",
1174
+ namePlaceholder: "e.g. Home page init flow",
1175
+ remark: "Blueprint notes",
1176
+ remarkPlaceholder: "Optional: describe purpose, triggers, etc.",
1177
+ taskRunningTitle: "Node is running a task",
1178
+ taskRunningDescription: "Node {fromNodeId} is running (Swagger parse or request debug). Switch to {target}?",
1179
+ cancelSelection: "Clear selection",
1180
+ nodeTarget: "Node {id}",
1181
+ taskSwitchHint: "Keep & switch continues in the background; Cancel & switch aborts the current task.",
1182
+ stayOnNode: "Stay on this node",
1183
+ cancelAndSwitch: "Cancel & switch",
1184
+ keepAndSwitch: "Keep & switch",
1185
+ importedBlueprint: "Imported blueprint",
1186
+ },
1187
+ node: {
1188
+ typeBlueprint: "Blueprint",
1189
+ typeLogic: "Logic",
1190
+ typeAnd: "AND",
1191
+ typeLifecycle: "Lifecycle",
1192
+ typeView: "View",
1193
+ typeFetch: "Fetch",
1194
+ typeJson: "JSON",
1195
+ typeClock: "Clock",
1196
+ summaryNoUrl: "URL not configured",
1197
+ summaryOutputCount: "{count} time(s)",
1198
+ summaryInterval: "Interval {seconds}s",
1199
+ summaryEmitImmediate: "Emit immediately",
1200
+ summaryEmitDelayed: "Delay first emit",
1201
+ summaryEmptyJson: "Empty JSON",
1202
+ summaryNoScript: "Script not configured",
1203
+ summaryNoBlueprint: "No blueprint selected",
1204
+ summaryNoView: "No view nodes linked",
1205
+ summaryViewOne: "View node {id}",
1206
+ summaryViewMany: "{count} view nodes linked",
1207
+ summaryAnd: "Output when both inputs are true",
1208
+ phaseCreated: "Created (created)",
1209
+ phaseBeforeMount: "Before mount (beforeMount)",
1210
+ phaseMounted: "Mounted (mounted)",
1211
+ phaseUpdated: "Updated (updated)",
1212
+ phaseBeforeDestroy: "Before destroy (beforeDestroy)",
1213
+ phaseDestroy: "Destroyed (destroy)",
1214
+ phaseActivated: "Activated (activated)",
1215
+ phaseDeactivated: "Deactivated (deactivated)",
1216
+ phaseBlueprintActivated: "Blueprint activated (blueprintActivated)",
1217
+ dragToMove: "Drag to move",
1218
+ signalSentCount: "Signals sent",
1219
+ signalIn: "True/false signal input",
1220
+ signalOut: "True/false signal output",
1221
+ lifecycleOut: "Emit true/false when lifecycle matches",
1222
+ andInA: "Input A (OR across edges)",
1223
+ andInB: "Input B (OR across edges)",
1224
+ andOut: "Emit true when both inputs are true",
1225
+ abortClock: "Abort clock: stop remaining ticks and running downstream tasks",
1226
+ },
1227
+ config: {
1228
+ title: "Blueprint node config",
1229
+ roleBlueprint: "Blueprint node",
1230
+ roleLifecycle: "Lifecycle node",
1231
+ roleAnd: "AND node",
1232
+ roleFetch: "Fetch node",
1233
+ roleJson: "JSON node",
1234
+ roleLogic: "Logic node",
1235
+ roleClock: "Clock node",
1236
+ roleView: "View node",
1237
+ nodeName: "Node name",
1238
+ configType: "Config type",
1239
+ configBlueprint: "Blueprint config",
1240
+ configLogic: "Logic config",
1241
+ configAnd: "AND",
1242
+ configLifecycle: "Lifecycle config",
1243
+ configFetch: "Fetch",
1244
+ configJson: "JSON node",
1245
+ configClock: "Clock",
1246
+ configView: "View node config",
1247
+ linkedViewNodes: "Linked view nodes",
1248
+ selectViewNode: "Select view nodes",
1249
+ viewMultiHint: "Multi-select view canvas nodes; configure the blueprint node here. Edit view props in the view panel.",
1250
+ linkedViewCount: "{count} view node(s) linked: {names}",
1251
+ noViewOnCanvas: "No nodes on the view canvas",
1252
+ searchViewNodes: "Search view nodes…",
1253
+ noMatchingNodes: "No matching nodes",
1254
+ selectedCount: "{count} selected",
1255
+ blueprintAttrs: "Blueprint attributes",
1256
+ blueprintAttrsHint: "After selecting a library blueprint, it runs only when the input receives a true signal; on success it emits true (with nested output and node info), on failure it emits false.",
1257
+ refLibrary: "Reference library blueprint",
1258
+ selectLibraryBlueprint: "Select a blueprint from the library",
1259
+ unlinked: "Unlinked",
1260
+ selectLibraryFirst: "Select a blueprint from the library first.",
1261
+ allowFalsePropagateBlueprint: "Allow false-signal propagation: when on, false outputs do not block the chain and errors continue downstream.",
1262
+ lifecycleHook: "Lifecycle hook",
1263
+ lifecycleNoInput: "Lifecycle nodes have no input port; only an output on the right.",
1264
+ lifecycleBlueprintActivatedHint: "When this blueprint is referenced by another blueprint node and receives a true signal, it automatically emits true downstream with the parent input as the value.",
1265
+ lifecyclePageHint: "When the page enters the matching lifecycle, automatically emit true/false downstream.",
1266
+ listenPhase: "Listen phase",
1267
+ parentBlueprintNode: "Parent blueprint node: {id}",
1268
+ andTitle: "AND",
1269
+ andHint: "Two inputs on the left: inA and inB. Each port may have n edges; any true on a port makes that port true (OR). Emit true only when both inA and inB are true; otherwise emit false.",
1270
+ taskChain: "Task chain",
1271
+ allowFalsePropagateDefault: "Allow false-signal propagation: by default false blocks the chain; when on, false signals and errors continue downstream.",
1272
+ fetchTitle: "Fetch",
1273
+ fetchHint: "On a true signal, send an HTTP request; optionally import Swagger and pick a URL from the endpoint list.",
1274
+ swaggerUrlOptional: "Swagger document URL (optional)",
1275
+ abortParse: "Abort parsing",
1276
+ abortSwaggerAria: "Abort Swagger parsing",
1277
+ parseSwagger: "Parse Swagger document",
1278
+ parsingSwagger: "Parsing Swagger… click the button on the right to abort",
1279
+ parsedEndpoints: "Parsed {count} endpoint(s)",
1280
+ requestUrl: "Request URL",
1281
+ suggestApi: "Suggest from API",
1282
+ manualInput: "Manual input",
1283
+ apiHostBaseUrl: "API host / Base URL",
1284
+ selectEndpoint: "Select endpoint",
1285
+ selectOrSearchEndpoint: "Click to select or search endpoints",
1286
+ sendDebugRequest: "Send debug request",
1287
+ abortRequest: "Abort request",
1288
+ abortDebugAria: "Abort debug request",
1289
+ sendingDebug: "Sending debug request… click the button on the right to abort",
1290
+ requestFailed: "Request failed",
1291
+ debugResponse: "Debug response",
1292
+ requestMethod: "Request method",
1293
+ requestHeadersJson: "Request headers (JSON)",
1294
+ requestBody: "Request body",
1295
+ responseParse: "Response parsing",
1296
+ timeoutMs: "Timeout (ms)",
1297
+ fillSwaggerUrlFirst: "Enter a Swagger document URL first",
1298
+ fillRequestUrlFirst: "Enter a request URL first",
1299
+ noMatchingEndpoint: "No matching endpoints",
1300
+ swaggerParseFailed: "Failed to parse Swagger document",
1301
+ enterSwaggerUrl: "Enter a Swagger document URL",
1302
+ cannotFetchSwagger: "Cannot fetch Swagger document",
1303
+ swaggerHttpFailed: "Swagger request failed: HTTP {status}",
1304
+ swaggerHtmlReturned: "Response is HTML; provide an OpenAPI/Swagger JSON URL",
1305
+ swaggerInvalidJson: "Swagger document is not valid JSON",
1306
+ jsonTitle: "JSON node",
1307
+ jsonHint: "On a true signal, parse the JSON below into an object/array and emit true; on parse failure emit false.",
1308
+ jsonContent: "JSON content",
1309
+ jsonFormatError: "Invalid JSON: {error}",
1310
+ jsonFormatOk: "JSON is valid",
1311
+ logicTitle: "Logic node",
1312
+ logicHint: "On a true signal, pass input into the update function below; the return value is emitted as true. Syntax or runtime errors emit false (error as the value).",
1313
+ jsCode: "JavaScript code",
1314
+ jsError: "JavaScript error: {error}",
1315
+ jsSyntaxOk: "JavaScript syntax is valid",
1316
+ clockTitle: "Clock node",
1317
+ clockHint: "Starts timing only after a true signal; each tick emits true with current time (formatted / timestamp / isoTime). False signals pass through unchanged.",
1318
+ clockIntervalSeconds: "Clock interval (seconds)",
1319
+ clockIntervalHint: "Seconds between outputs; must be > 0 when emitting multiple times or when immediate send is off.",
1320
+ outputCount: "Output count",
1321
+ outputCountHint: "Total outputs after a true signal; default 1.",
1322
+ emitImmediately: "Emit immediately: when on and count > 1, run the first tick right away and the rest every m seconds; with count 1 it also runs immediately. When off, every tick (including the first) waits m seconds.",
1323
+ timeFormat: "Time format",
1324
+ timeFormatHint: "Supports YYYY, MM, DD, HH, mm, ss. Default YYYY-MM-DD HH:mm:ss.",
1325
+ },
1326
+ log: {
1327
+ title: "Blueprint task output log",
1328
+ simulateSceneWithPhase: "Simulate scene: {phaseLabel}",
1329
+ selectLifecycleToDebug: "Select a lifecycle node to start debugging",
1330
+ clearIdbTooltip: "Clear all saved blueprint execution logs from IndexedDB now",
1331
+ clearIdbAria: "Clear IndexedDB logs",
1332
+ clearCurrentTooltip: "Clear current log and reset canvas execution highlights",
1333
+ clearCurrentAria: "Clear log",
1334
+ emptyHint: "No execution records yet. Use Run all or Step next on the toolbar to start.",
1335
+ input: "Input",
1336
+ output: "Output",
1337
+ hasNewLogs: "New logs",
1338
+ saveLog: "Save log",
1339
+ saveLogTooltip: "Save the current debug log to IndexedDB",
1340
+ exportJson: "Export JSON",
1341
+ exportJsonTooltip: "Export the current debug log as a JSON file",
1342
+ autoSaveAfterRun: "Auto-save to IndexedDB after run",
1343
+ autoSaveTooltip: "After a debug run finishes, automatically write the log to IndexedDB",
1344
+ maxSavedCount: "Max saved count",
1345
+ maxSavedCountTooltip: "Max log entries kept in IndexedDB; oldest are removed when exceeded",
1346
+ maxSavedCountAria: "Max IndexedDB log count",
1347
+ retentionDays: "Retention days",
1348
+ retentionDaysTooltip: "Saved logs older than this many days are removed on cleanup",
1349
+ retentionDaysAria: "Log retention days",
1350
+ cleanupExpired: "Clean expired / over-limit",
1351
+ cleanupTooltip: "Clean IndexedDB logs by retention days and max count",
1352
+ },
1353
+ dev: {
1354
+ hint: "Right-click canvas to add nodes · drag from right handle to left handle · expect A→B blue edge",
1355
+ stats: "Nodes {nodes} · Edges {edges}",
1356
+ },
1357
+ },
1358
+ } as const;
1359
+
1360
+ export type { MessageCatalog } from "./zh-CN";