Files
infinite-canvas/web/src/i18n/locales/en-US.ts
T

609 lines
72 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export default {
meta: {
title: "Infinite Canvas",
description: "An infinite canvas creation tool",
},
theme: { toggle: "Toggle theme" },
common: {
cancel: "Cancel",
save: "Save",
edit: "Edit",
done: "Done",
delete: "Delete",
copy: "Copy",
copied: "Copied",
details: "Details",
addToAssets: "Add to My Assets",
addedToAssets: "Added to My Assets",
copyPrompt: "Copy prompt",
promptCopied: "Prompt copied",
created: "Created: {{date}}",
updated: "Updated: {{date}}",
all: "All",
view: "View",
download: "Download",
upload: "Upload",
requestCanceled: "Request canceled",
durationMinutes: "{{minutes}}m {{seconds}}s",
durationSeconds: "{{seconds}}s",
imageReadFailed: "Failed to read image",
},
settingsPanels: {
common: { auto: "Auto", low: "Low", medium: "Medium", high: "High", xhigh: "Extra high" },
image: { title: "Image settings", quality: "Quality", size: "Size", align16: "Align to multiples of 16", align16Hint: "Round dimensions up to the next multiple of 16 after input", aspectRatio: "Aspect ratio", transparent: "Transparent background", transparentHint: "Generate an image without a background when supported by the model", count: "Image count", images: "{{count}} images" },
video: { title: "Video settings", quality: "Quality", size: "Size", seconds: "Seconds", resolution: "Resolution", ratio: "Aspect ratio", duration: "Duration", smart: "Smart", output: "Output", generateAudio: "Generate audio", watermark: "Add watermark", adaptive: "Adaptive", sizes: { landscape: "Landscape", portrait: "Portrait", square: "Square", widescreen: "Widescreen", tall: "Tall", auto: "Auto" }, ratios: { landscape: "Landscape", portrait: "Portrait", square: "Square", standardLandscape: "Standard landscape", standardPortrait: "Standard portrait", cinematic: "Cinematic", adaptive: "Adaptive" } },
audio: { title: "Audio settings", voice: "Voice", format: "Format", speed: "Speed", instructions: "Voice instructions", instructionsPlaceholder: "For example: natural, warm, and suitable for narration." },
text: { title: "Text settings", reasoning: "Reasoning effort" },
model: { select: "Select model", assign: "Assign a model for {{capability}} in the provider settings", noMatch: "No matching {{capability}} models", addFirst: "Add a provider and models in Settings first", capabilities: { image: "image generation", video: "video", text: "text", audio: "audio" } },
},
generation: { pending: ["Creating image", "Almost there", "Just a little longer", "Refining details"] },
imageReferences: { label: "Image {{index}}", separator: ", ", promptPrefix: "Reference image labels: {{labels}}. Use these labels to interpret image references in the prompt.\n\n{{prompt}}" },
seedance: { autoMatch: "Automatic", separator: ", ", references: { image: "Image {{index}}", video: "Video {{index}}", audio: "Audio {{index}}" }, promptPrefix: "Reference asset labels: {{labels}}. Use these labels to interpret image, video, and audio references in the prompt.\n\n{{prompt}}", referenceHint: "Reference videos must be mp4/mov, H.264/H.265, and 2460 FPS. Use authorized Volcengine asset:// assets when real faces are included.", errors: { format: "{{label}} supports mp4/mov only", size: "{{label}} exceeds 200 MB. Compress it before uploading.", duration: "{{label}} must be 215 seconds", dimensions: "{{label}} dimensions must be between 300 and 6000px", ratio: "{{label}} aspect ratio must be between 0.4 and 2.5", pixels: "{{label}} total pixel count must be between 409600 and 8295044", totalDuration: "Seedance reference videos cannot exceed 15 seconds in total" } },
modelPlugin: {
pollTimeout: "Plugin polling timed out. Check the request script or try again later.", executionFailed: "Model request script failed: {{message}}", noImages: "The model request script did not return any images",
variables: { prompt: "User prompt with the system prompt already included", images: "Reference images as a data URL array, available for image editing and image-to-video", messages: "Conversation message array including the system message", params: "Generation parameters: image {size,quality,count}, video {seconds,size,resolution,ratio,generateAudio,watermark}, audio {voice,format,speed,instructions}", model: "Model name without the provider prefix", baseUrl: "Provider endpoint as entered, without appending /v1", apiKey: "Provider API key; add it to request headers yourself", systemPrompt: "Original system prompt", reasoningEffort: "Text reasoning effort; auto lets the script decide whether to send it", http: "Convenience client: http.post(path, body, {headers,params,responseType}), http.get(path, opts), and http.url(path). Authorization: Bearer apiKey is included by default and can be overridden. Relative paths append /v1 to baseUrl.", request: "Raw request({ method, url, headers, params, data, responseType }) with no default headers. Add authentication yourself. Relative URLs are joined to baseUrl without /v1.", poll: "poll(request, extract, {intervalMs,timeoutMs}) continues until extract returns a truthy value", sleep: "Delay with sleep(ms)", signal: "Cancellation signal that can be passed to http/request", onDelta: "Push streaming text with onDelta(text) for text models" },
returns: { image: "Text-to-image and image editing use different APIs; distinguish them by whether images is empty. Return an image URL or data URL, an array of them, or [{ dataUrl }] / [{ url }] / [{ b64_json }].", video: "Poll inside the script and return { url }, { blob }, or a video URL string.", audio: "Return a Blob, base64/data URL string, or { b64_json } / { data } / { url }.", text: "Push streaming output with onDelta(text), then return the complete text string." },
templates: { openai: "OpenAI format", gemini: "Gemini format", imageOpenai: "Image generation and editing use different endpoints; distinguish them by whether images is empty.", availableImage: "Available: prompt, images(dataURL[]), params{size,quality,count}, model, baseUrl, apiKey", textToImage: "Text to image: /images/generations (JSON)", imageToImage: "Image editing: /images/edits (multipart/form-data with reference images uploaded as files)", formDataHeader: "Do not set Content-Type manually; let the browser add the boundary", imageGemini: "Gemini image generation and editing both use generateContent, with references in parts.inline_data.", availableImageGemini: "Available: prompt, images(dataURL[]), model, baseUrl, apiKey", videoOpenai: "Video with polling handled inside the script. Available: prompt, images(dataURL[]), params{seconds,size,resolution,ratio}", videoGemini: "Gemini (Veo) video: submit with predictLongRunning and poll the operation for the video URI.", availableVideoGemini: "Available: prompt, images(dataURL[]), params, model, baseUrl, apiKey", geminiNoVideoUri: "Gemini did not return a video URI", audioOpenai: "Audio TTS. Available: prompt, params{voice,format,speed,instructions}, model", audioGemini: "Gemini TTS: generateContent with AUDIO modality, returning base64 PCM in inlineData.data.", availableAudioGemini: "Available: prompt, params{voice}, model, baseUrl, apiKey", geminiNoAudio: "Gemini did not return audio", textOpenai: "Text chat using the OpenAI Responses API. Available: messages([{role,content}]), systemPrompt, model, reasoningEffort", textGemini: "Gemini text: generateContent with the system message in systemInstruction.", availableTextGemini: "Available: messages([{role,content}]), systemPrompt, model, baseUrl, apiKey" },
},
apiErrors: { requestFailed: "Request failed", requestCanceled: "Request canceled", baseUrlRequired: "Configure the Base URL first", apiKeyRequired: "Configure the API key first", authenticationFailed: "Authentication failed. Check the API key, plan permissions, and model permissions.", rateLimited: "The request was rate-limited or the quota is insufficient. Try again later.", notFound: "The endpoint was not found (404). Check the Base URL and selected model.", badGateway: "Gateway error (502). The API service is temporarily unavailable.", serviceBusy: "Service unavailable (503). Try again later.", httpFailed: "Request failed (HTTP {{status}}). Check the Base URL and API key.", htmlError: "The service returned an HTML error page ({{preview}})", audioModelRequired: "Configure an audio model first", audioGenerationFailed: "Audio generation failed", scriptNoAudio: "The model request script did not return audio", geminiAudioUnsupported: "The Gemini API format does not support audio generation. Use an OpenAI-format provider.", invalidImageSizeFormat: "Unsupported image size. Use auto, 9:16, or 1024x1024.", positiveImageRatio: "The image ratio must use positive numbers, such as 9:16.", imageRatioLimit: "The image aspect ratio cannot exceed 3:1. Adjust the dimensions.", positiveImageDimensions: "Image dimensions must be positive integers, such as 1024x1024.", imageDimensionStep: "Image width and height must be multiples of 16.", imageEdgeLimit: "The longest image edge cannot exceed 3840px.", imagePixelLimit: "The total image pixel count must be between 655360 and 8294400.", unknownImageResponse: "The API returned data in an unknown format (fields: {{fields}}). Check model or API compatibility.", noImageReturned: "The API did not return an image. The prompt may have triggered safety review or the model may not support this operation.", geminiRejected: "Gemini rejected the request: {{reason}}", geminiNoImage: "The Gemini API did not return an image", geminiMaskUnsupported: "The Gemini API format does not support mask editing", maskModelUnsupported: "This model does not support mask editing. Use another provider.", noContent: "No content returned", modelReadFailed: "Failed to load models", videoTimeout: "{{provider}}video generation timed out. Try again later.", videoReferencesUnsupported: "This video API does not support reference video or audio. Switch to Seedance 2.0 / Volcengine Agent Plan, or remove the reference assets.", pluginVideoExpired: "The plugin video task has expired. Generate it again.", scriptNoVideo: "The model request script did not return a video", noPlayableVideo: "The video API did not return a playable video", noVideoTaskId: "The video API did not return a task ID", videoTaskCreateFailed: "Failed to create video task", videoGenerationFailed: "Video generation failed", videoTaskQueryFailed: "Failed to query video task", seedanceAudioRequiresVisual: "Seedance reference audio cannot be used alone. Add a reference image or video.", videoPromptRequired: "Enter a video prompt or connect a reference image, video, or audio asset", seedanceNoTaskId: "The Seedance API did not return a task ID", seedanceTaskCreateFailed: "Failed to create Seedance task", seedanceNoVideoUrl: "The Seedance task succeeded but did not return a video URL", seedanceVideoTimeout: "Seedance video generation timed out", seedanceVideoFailed: "Seedance video generation failed", seedanceTaskQueryFailed: "Failed to query Seedance task", seedanceVideoDuration: "Each Seedance reference video must be 215 seconds", seedanceVideoTotalDuration: "Seedance reference videos cannot exceed 15 seconds in total", seedanceAudioDuration: "Each Seedance reference audio file must be 215 seconds", seedanceAudioTotalDuration: "Seedance reference audio cannot exceed 15 seconds in total", referenceImageReadFailed: "Failed to read the reference image. Choose another image or upload it again.", invalidReferenceVideo: "A reference video must be a public URL, asset ID, or locally saved video", invalidReferenceAudio: "Reference audio must be a public URL, asset ID, or locally saved audio file", videoModelRequired: "Configure a video model first", geminiVideoUnsupported: "The Gemini API format does not support video generation. Use an OpenAI-format provider.", noVideoTask: "The API did not return a video task", seedanceNoTask: "The Seedance API did not return a task", videoDownloadFailed: "Failed to download video", localAssetReadFailed: "Failed to read local asset" },
prompts: {
title: "Prompt Center",
library: "Prompt Library",
total: "{{count}} prompts",
category: "Category",
tags: "Tags",
search: "Search titles, content, or tags",
searchTitle: "Search by title",
loadFailed: "Failed to load prompts",
sourceMissing: "Prompt source not found",
use: "Use this prompt",
empty: "No matching prompts found",
loading: "Loading...",
loadMore: "Scroll down to load more",
end: "You've reached the end",
},
assets: {
title: "My Assets",
description: "Save frequently used text and images, then find them quickly by type, title, or tag.",
search: "Search titles, content, tags, or sources",
type: "Type",
export: "Export assets",
import: "Import assets",
add: "Add asset",
edit: "Edit asset",
empty: "No assets found",
manual: "Added manually",
selectImage: "Select an image file",
updated: "Asset updated",
saved: "Asset saved",
textCopied: "Text copied",
noneToExport: "No assets to export",
imported: "Imported {{count}} assets",
importFailed: "Import failed. Select a valid asset package.",
deleted: "Asset deleted",
packageName: "my-assets.zip",
kinds: { text: "Text", image: "Image", video: "Video" },
fields: {
title: "Title",
titleRequired: "Enter a title",
titlePlaceholder: "Give the asset an easy-to-find name",
coverUrl: "Cover URL",
coverPlaceholder: "Paste an image URL or upload a local cover",
tags: "Tags",
tagsPlaceholder: "Type a tag and press Enter",
source: "Source",
sourcePlaceholder: "Added manually / Canvas / Prompt Library",
note: "Note",
optional: "Optional",
textContent: "Text content",
textRequired: "Enter text content",
textPlaceholder: "Save prompts, copy, reference descriptions, and other text assets",
imageContent: "Image content",
},
selectImageFile: "Select image file",
noImageSelected: "No image selected",
preview: "Preview",
noCover: "No cover",
untitled: "Untitled asset",
noTags: "No tags",
untagged: "Untagged",
unknownSource: "Source not specified",
details: "Asset details",
deleteTitle: "Delete asset",
deleteConfirm: "Delete “{{name}}”? It will be removed from My Assets.",
copyText: "Copy text",
downloadImage: "Download image",
downloadVideo: "Download video",
},
notFound: {
title: "Page not found",
description: "There is no page at this address. It may have moved or been merged into another section.",
home: "Back to home",
},
workbench: {
logs: "Generation history",
settings: "Settings",
prompt: "Prompt",
viewPrompts: "Browse prompts",
viewAssets: "Browse My Assets",
clipboard: "Clipboard",
upload: "Upload",
adjust: "Adjust",
generate: "Generate",
results: "Results",
waiting: "Waiting {{time}}",
model: "Model",
generating: "Generating",
success: "Succeeded",
failed: "Generation failed",
retry: "Retry",
new: "New",
selectAll: "Select all",
noLogs: "No generation history",
deleteLogs: "Delete generation history",
deleteLogsConfirm: "Delete the selected {{count}} generation records?",
successCount: "{{count}} succeeded",
failCount: "{{count}} failed",
itemCount: "{{count}} images",
untitled: "Untitled",
configFirst: "Complete the configuration first",
generationFailed: "Generation failed",
retrySuccess: "Retry succeeded",
},
imageWorkbench: {
title: "Image Studio",
promptPlaceholder: "Describe the subject, style, composition, lighting, and intended use",
references: "Reference images",
removeReference: "Remove reference image",
dropReferences: "Drop to add reference images",
noReferences: "No reference images. Drag images here to add them.",
clipboardEmpty: "No readable images found on the clipboard",
clipboardAdded: "Added {{count}} reference images",
promptRequired: "Enter an image prompt",
configIncomplete: "Image generation configuration is incomplete",
invalidParams: "Invalid image generation parameters",
busy: "The Image Studio is already running a task",
generated: "Images generated",
addedReference: "Added to reference images",
resultTitle: "Generated image {{count}}",
source: "Image Studio",
unsupportedAsset: "Image Studio only supports text and image assets",
missingResult: "The API returned no image",
empty: "No images generated yet",
resultAlt: "Generated image {{count}}",
addReference: "Add as reference",
},
videoWorkbench: {
title: "Video Studio",
promptPlaceholder: "Describe camera movement, subject action, atmosphere, and visual style",
references: "Reference images",
videoReferences: "Reference videos",
audioReferences: "Reference audio",
removeImage: "Remove reference image",
removeVideo: "Remove reference video",
removeAudio: "Remove reference audio",
dropReferences: "Drop to upload reference assets",
noImages: "No reference images. Drag in up to 9 files.",
noVideos: "No reference videos. Drag in up to 3 files.",
noAudio: "No reference audio. Drag in up to 3 MP3/WAV files, each under 15 MB.",
unsupportedFiles: "Unsupported reference assets were ignored. Use images, MP4/MOV video, or MP3/WAV audio.",
imageTooLarge: "Reference images over 30 MB were ignored",
videoTooLarge: "Reference videos over 200 MB were ignored",
audioTooLarge: "Reference audio over 15 MB was ignored",
audioDurationInvalid: "Reference audio outside the duration limits was ignored: 215 seconds each, 15 seconds total.",
clipboardEmpty: "No readable images found on the clipboard",
clipboardAdded: "Added {{count}} reference images",
promptRequired: "Enter a video prompt",
referenceError: "{{error}}. {{hint}}",
invalidParams: "Invalid video generation parameters",
busy: "The Video Studio is already running a task",
generated: "Video generated",
timeout: "Video generation timed out. Try again later.",
resultTitle: "Generated video",
source: "Video Studio",
empty: "No video generated yet",
},
canvas: {
defaultTitle: "Infinite Canvas {{count}}",
library: "Canvas library",
title: "Infinite Canvas",
imported: "Imported {{count}} canvases",
importFailed: "Import failed. Select a valid canvas package.",
opening: "Opening canvas...",
loading: "Loading canvases...",
exportSelected: "Export selected",
deleteSelected: "Delete selected",
deleteAll: "Delete all",
import: "Import canvas",
create: "New canvas",
empty: "No canvases yet",
emptyDescription: "Create a canvas to save its nodes, connections, and appearance independently.",
collapsePanel: "Collapse panel",
expandPanel: "Expand panel",
home: "Home",
docs: "Documentation",
projects: "My Canvases",
deleteCurrent: "Delete current canvas",
importAsset: "Import asset",
exportCurrent: "Export current canvas",
undo: "Undo",
redo: "Redo",
openMenu: "Open canvas menu",
renameHint: "Double-click to rename the canvas",
shortcuts: "Keyboard shortcuts",
miniMapOpen: "Open minimap",
miniMapClose: "Close minimap",
resetView: "Reset view",
zoom: "Zoom canvas",
agentConnected: "Codex connected",
agentConnecting: "Codex {{activity}}",
agentDisconnected: "Codex disconnected",
connecting: "Connecting",
openAgent: "Open local Codex panel",
nodeTypes: { image: "Image", text: "Text", config: "Generation config", video: "Video", audio: "Audio", group: "Group" },
toolbar: {
select: "Select", pan: "Move", text: "Text", image: "Image", video: "Video", audio: "Audio", config: "Generation config", group: "Group", extensions: "Extension nodes", upload: "Upload assets", appearance: "Canvas appearance", clear: "Clear canvas",
themeMode: "Theme", light: "Light", dark: "Dark", gridStyle: "Grid style", dots: "Dots", lines: "Lines", blank: "Blank", imageInfo: "Image info",
},
project: {
untitled: "Untitled canvas", imported: "Imported canvas",
select: "Select {{name}}", stats: "{{nodes}} nodes · {{connections}} connections", updated: "Updated {{date}}", saveName: "Save name", cancelRename: "Cancel rename", export: "Export", rename: "Rename", delete: "Delete",
deleteTitle: "Delete canvases?", deleteDescription: "This will delete {{count}} canvases along with their nodes and connections.",
},
export: { defaultProjectName: "Infinite Canvas", defaultNodesName: "Canvas elements", item: "Element" },
createMenu: {
fromNode: "Generate from this node", close: "Close", text: "Generate text", textDescription: "Scripts, ad copy, and brand content", image: "Generate image", video: "Generate video", audio: "Audio reference", config: "Configuration node", configDescription: "Model, size, count, and input order", select: "Select a node",
},
node: {
node: "Node",
untitled: "Untitled node", renameHint: "Double-click to rename the node", group: "Group", nodeCount: "{{count}} nodes", generating: "Generating", failed: "Generation failed", retry: "Retry", missingPlugin: "Plugin missing", missingPluginDescription: "The plugin for node type “{{type}}” is not installed or enabled", generateImage: "Generate image from text", generate: "Generate", editText: "Double-click to edit text", emptyImage: "Empty image node", emptyVideo: "Empty video node", emptyAudio: "Empty audio node", audio: "Audio", batchExpanded: "Image group expanded", batchCollapsed: "Image group collapsed", createCopy: "Create copy", setPrimary: "Set as primary",
},
sidePanel: {
canvas: "Canvas", assets: "Assets", prompts: "Prompt Library", resize: "Resize left panel", elements: "Canvas elements", select: "Select", searchNodes: "Search nodes", focusNode: "Focus node", preview: "Large preview", noNodes: "No nodes on this canvas", clearAll: "Clear all", selected: "{{count}} selected", exporting: "Exporting selected elements…", exportName: "canvas-elements-{{count}}", exported: "Exported {{count}} elements", exportFailed: "Export failed. Try again.",
addingAssets: "Adding assets…", addedAssets: "Added {{count}} assets", mediaOnly: "Only image and video files are supported", addFailed: "Failed to add assets. Try again.", searchAssets: "Search assets", add: "Add", noAssets: "No assets", inserted: "Insert into canvas", removeAssetTitle: "Remove this asset?", remove: "Remove", removeAsset: "Remove asset", assetRemoved: "Asset removed",
searchPrompts: "Search prompts", noPrompts: "No prompts", promptCopied: "Prompt copied", copyFailed: "Copy failed", loadFailedRetry: "Load failed. Click to retry.", noMatchingPrompts: "No matching prompts", sourceEmpty: "No prompts from this source", viewDetails: "View details",
filter: { image: "Image", video: "Video", text: "Text", audio: "Audio", config: "Configuration", group: "Group" },
},
assetPicker: { title: "Select assets", insert: "Insert", search: "Search assets", empty: "No assets" },
imageTools: { copyPrompt: "Copy prompt", copyPromptTitle: "Copy the prompt used to generate this image", reversePrompt: "Reverse prompt", reversePromptTitle: "Create text and configuration nodes to infer the prompt", replace: "Replace image", locked: "Lock ratio", free: "Free ratio", lockTitle: "Switch to proportional scaling", freeTitle: "Switch to free resizing", mask: "Local edit", maskTitle: "Paint a mask and edit the selected area", crop: "Crop", cropTitle: "Crop into a new node", split: "Split", splitTitle: "Split the image by rows and columns", upscale: "Upscale", upscaleTitle: "Increase image resolution", superResolve: "Super resolution", superResolveTitle: "AI super resolution", angle: "Multi-angle", angleTitle: "Generate another angle", view: "View image", viewTitle: "View image details", more: "More", configure: "Configure quick tools", customize: "Customize toolbar", showLabels: "Show button labels", description: "Choose the quick tools shown in the image-node toolbar.", preview: "Node preview", imageNode: "Image node", quickTools: "Quick tools" },
nodeToolbar: { noPrompt: "No prompt to copy", infoTitle: "View node information", info: "Info", removeTitle: "Remove node", retryTitle: "Generate again", saveAsset: "Save asset", downloadAudio: "Download audio", downloadVideo: "Download video", downloadImage: "Download image", editTextTitle: "Edit text", editText: "Edit text", decreaseFont: "Decrease font size", increaseFont: "Increase font size", zoomOut: "Smaller", zoomIn: "Larger", uploadImage: "Upload image", replaceVideo: "Replace video", uploadVideo: "Upload video", replaceAudio: "Replace audio", uploadAudio: "Upload audio", nodeInfo: "Node information", name: "Name", type: "Type", size: "Size", position: "Position", status: "Status", imageGroup: "Image group", imageSize: "Image size" },
configNode: { title: "Generation config", image: "Image", text: "Text", video: "Video", audio: "Audio", prompt: "Prompt", references: "Reference images", videoReferences: "Reference videos", audioReferences: "Reference audio", items: "{{count}} items", images: "{{count}} images", compose: "Compose prompt", stop: "Stop", generate: "Generate" },
projectPage: {
stopTitle: "Stop generation?", stopDescription: "The current request will be interrupted. Completed results will be kept.", stop: "Stop", continue: "Continue generating", configConnection: "Configuration nodes cannot be connected to each other", notFound: "Current canvas not found", exporting: "Exporting current canvas…", exported: "Current canvas exported", clipboardText: "Clipboard text", clipboardImageAdded: "Added image from clipboard", clipboardTextAdded: "Added text from clipboard", noTextToSave: "No text to save", canvasText: "Canvas text", noVideoToSave: "No video to save", canvasVideo: "Canvas video", noImageToSave: "No image to save", canvasImage: "Canvas image", emptyReverse: "The image node is empty, so its prompt cannot be inferred", reverseTitle: "Reverse prompt", reverseConfigTitle: "Reverse prompt configuration", splitTitle: "{{name}} {{row}}-{{column}}", splitSuccess: "Split into {{count}} child nodes", maskResult: "Local edit result", maskFailed: "Local edit failed", generationFailed: "Generation failed", partialFailed: "Some images failed to generate", allFailed: "All images failed to generate", retryPromptMissing: "No prompt found for retry", referenceMissing: "The reference image is missing, so retry cannot continue", emptyTextImage: "The text node is empty, so an image cannot be generated", untitledCanvas: "Untitled canvas", superResolve: "AI super resolution", notImplemented: "Not implemented yet", imageDetails: "Image details", clearTitle: "Clear canvas?", clear: "Clear", clearDescription: "This will delete every node and connection on the current canvas.", reversePreset: "Infer a prompt suitable for AI image generation from the reference image.\n\nRequirements:\n1. Output only the prompt, with no explanation.\n2. Cover the subject, composition, style, lighting, color, materials, lens, and atmosphere.\n3. Write a complete prompt that can be used directly with an image model.", maskPrompt: "Only modify the transparent masked area and keep everything else unchanged. {{prompt}}", editTextPrompt: "Revise the text according to the instructions.\n\nOriginal:\n{{source}}\n\nInstructions:\n{{prompt}}"
},
reverseComposer: "Reference image: @[node:{{imageId}}]\nTask: @[node:{{textId}}]",
editors: {
reset: "Reset", zoomOut: "Zoom out", zoomIn: "Zoom in", loading: "Loading", unknown: "Unknown", cancel: "Cancel",
angleTitle: "AI Multi-angle", angleDescription: "The left side previews direction only; the result is regenerated from the original image", horizontal: "Horizontal angle", pitch: "Pitch angle", distance: "Camera distance", lens: "Wide-angle lens", standard: "Standard", wide: "Wide", aiGenerate: "Generate with AI",
upscaleTitle: "Upscale image", source: "Source", targetPixels: "Target pixels", maxReached: "The image is already 4K and does not need upscaling", targetReached: "The image already meets the target pixel count", algorithm: "Upscaling algorithm", outputSize: "Output size", upscale: "Generate upscaled image", high: "High-quality interpolation", highDescription: "Best for photos and detailed images", bilinear: "Bilinear", bilinearDescription: "Smooth and fast", nearest: "Nearest neighbor", nearestDescription: "Best for pixel art",
cropTitle: "Crop image", adjustCrop: "Adjust crop box", cropHint: "Mouse wheel to zoom · middle button or Space + left drag to pan", cropSize: "Crop size {{size}}", ratio: "Ratio {{ratio}}", original: "Original {{width}} x {{height}}", confirmCrop: "Crop", free: "Free", fixed: "Fixed", originalMode: "Original",
maskTitle: "Local mask edit", maskHint: "Mouse wheel to zoom · middle button or Space + left drag to pan · Alt + left/right drag to resize brush · Ctrl/Cmd+Z to undo · Ctrl/Cmd+Shift+Z to redo", brush: "Brush", erase: "Erase", undoMaskTitle: "Undo mask stroke (Ctrl/Cmd+Z)", undoMask: "Undo mask stroke", redoMaskTitle: "Redo mask stroke (Ctrl/Cmd+Shift+Z)", redoMask: "Redo mask stroke", brushSize: "Brush size", editInstructions: "Edit instructions", maskPlaceholder: "For example: change the selected area to metal while preserving the original lighting", maskPromptRequired: "Enter edit instructions", maskRequired: "Paint the area to edit first", aiEdit: "Edit with AI",
splitTitle: "Split image", splitDescription: "Create {{count}} image nodes and arrange them in the original grid to the right of the canvas", splitHint: "Mouse wheel to zoom · middle button or Space + left drag to pan · Delete removes the selected line · Ctrl/Cmd+Z to undo · Ctrl/Cmd+Shift+Z to redo", undoSplitTitle: "Undo split adjustment (Ctrl/Cmd+Z)", undoSplit: "Undo split adjustment", redoSplitTitle: "Redo split adjustment (Ctrl/Cmd+Shift+Z)", redoSplit: "Redo split adjustment", rows: "Rows", columns: "Columns", horizontalLine: "Horizontal line", verticalLine: "Vertical line", deleteLine: "Delete line", resetLines: "Reset lines", pieceCount: "Pieces", pieces: "{{count}}", averageSize: "Average size", generateChildren: "Create child nodes",
},
plugins: { title: "Node plugins", installedPlugin: "Installed plugin {{name}}", installed: "Installed {{name}}", installFailed: "Installation failed: {{error}}", enabled: "Enabled", disabled: "Disabled", upgradeAvailable: "New version available — click to upgrade", updateFromSource: "Update from source", updated: "Updated", uninstallTitle: "Uninstall this plugin?", uninstall: "Uninstall", newVersion: "A new version is available", officialDescription: "Official plugins from this project's registry", refresh: "Refresh", loadFailed: "Failed to load: {{error}}", loadingOfficial: "Loading official plugins…", noOfficial: "No official plugins", install: "Install", urlPlaceholder: "Enter a plugin JavaScript URL, for example https://.../plugin.js", noThirdParty: "No third-party plugins installed", official: "Official", local: "Local", thirdParty: "Third-party", warning: "Plugin code runs directly on this page and can access local data, including your AI API key. Only install plugins from sources you trust.", aiConfigRequired: "AI configuration is not ready. Configure a model and API key in Settings first.", interactiveTitle: "Interaction mode is active. Click to switch to Move mode and drag the node.", movableTitle: "Move mode is active. Click to switch to Interaction mode and operate the node content.", move: "Move", interact: "Interact" },
promptPanel: { video: "Describe the video you want to generate", audio: "Describe the audio you want to generate", image: "Describe the image you want to generate", text: "Describe the text you want to generate", editImage: "Describe how you want to change this image", editText: "Describe how you want to revise this text", stopGeneration: "Stop generation", generate: "Generate", stop: "Stop" },
composer: { title: "Compose prompt", description: "Use @ to reference connected assets; references are renumbered before sending", placeholder: "Enter a prompt and use @ to reference connected images or text", imagePreview: "Referenced image preview", resources: { image: "Image {{index}}", video: "Video {{index}}", audio: "Audio {{index}}", text: "Text {{index}}" } },
controls: { ratio: "Ratio", duplicate: "Duplicate", delete: "Delete", images: "{{count}} images", reasoning: "Reasoning" },
generation: { interrupted: "Generation was interrupted by a page refresh. Generate again.", front: "front view", rotateRight: "rotated {{angle}} degrees right", rotateLeft: "rotated {{angle}} degrees left", level: "eye-level view", topDown: "{{angle}}-degree top-down view", lowAngle: "{{angle}}-degree low-angle view", angleLabel: "AI multi-angle: {{horizontal}}, {{pitch}}, camera distance {{distance}}, {{lens}} lens", anglePrompt: "Regenerate a new view of the same subject from the reference image. Preserve the subject, colors, materials, and visual style; do not merely apply perspective distortion. {{angle}}." },
agentOps: { add_node: "Add node", update_node: "Update node", delete_node: "Delete node", delete_connections: "Delete connections", connect_nodes: "Connect", set_viewport: "Adjust view", select_nodes: "Select nodes", run_generation: "Run generation" },
pluginErrors: { invalidExport: "The plugin did not export a valid object", missingFields: "The plugin is missing id or nodes", downloadFailed: "Download failed (HTTP {{status}})", registryFailed: "Failed to load the official plugin registry (HTTP {{status}})" },
shortcut: {
dragCanvas: "Drag canvas",
pan: "Pan view",
toggleTool: "Temporarily switch Select / Move",
wheel: "Mouse wheel",
zoom: "Zoom canvas",
zoomSlider: "Zoom slider",
preciseZoom: "Adjust zoom precisely",
boxSelect: "Select multiple nodes",
addSelection: "Add nodes to selection",
selectAll: "Select all nodes",
copyPaste: "Copy/paste nodes or paste clipboard text/images",
copyPasteNodes: "Copy/paste nodes",
delete: "Delete selection",
escape: "Clear selection and close overlays",
dropMedia: "Drop images/videos/audio",
upload: "Upload to canvas",
drag: "Drag",
click: "Click",
},
},
navigation: {
canvas: "My Canvases",
image: "Image Studio",
video: "Video Studio",
prompts: "Prompt Library",
assets: "My Assets",
config: "Settings",
},
topNav: {
openMenu: "Open navigation menu",
menu: "Navigation menu",
navigation: "Navigation",
openAgent: "Open Agent",
closeAgent: "Close Agent",
plugins: "Node plugins",
docs: "Documentation",
switchLanguage: "Switch to {{language}}",
shortcuts: "Keyboard shortcuts",
lightTheme: "Switch to light theme",
darkTheme: "Switch to dark theme",
},
home: {
promptError: "Failed to load prompts",
description: "Generate, connect, and reshape <content>images, text, and graphics</content> in <canvas>Infinite Canvas</canvas>, turning one-off generations into a continuous creative process.",
start: "Get started",
openCanvas: "Open canvas",
showcaseTitle: "Keep every great result",
showcaseDescription: "Save reliable prompts, visual references, and generated images so your next creation starts from proven ideas.",
viewPrompts: "View prompt library",
},
version: {
viewUpdates: "View release updates",
title: "Release updates",
currentVersion: "Current version",
latestVersion: "Latest version",
checking: "Checking...",
checkUpdates: "Check for updates",
unreleased: "Unreleased",
latest: "Latest",
current: "Current",
readFailed: "Failed to read version",
changelogFailed: "Failed to read changelog",
updated: "Latest version information loaded",
updateFailed: "Failed to load the latest version information",
types: { added: "Added", fixed: "Fixed", changed: "Changed", optimized: "Optimized", docs: "Docs" },
},
config: {
title: "Settings & Preferences",
invalidFile: "The settings file format is invalid",
description: "Providers, model selection, sync, and local storage",
modalDescription: "Providers, default models, sync, and local storage",
tabs: {
channels: "Providers",
preferences: "Preferences",
promptSources: "Prompt sources",
localStorage: "Local storage",
},
localStorage: {
title: "IndexedDB storage usage",
description: "View browser data saved by Infinite Canvas, grouped by object store.",
indexedDbUsage: "IndexedDB usage",
siteUsage: "Total site usage",
quota: "Available quota",
contentEstimate: "Estimated from stored content",
siteUsageHint: "Includes IndexedDB and other site data",
quotaHint: "Allocated dynamically by the browser",
quotaProgress: "Site quota usage",
mainDatabase: "Infinite Canvas data",
records: "{{count}} records",
refresh: "Refresh usage",
readFailed: "Failed to read local storage",
stores: { appState: "App state", images: "Image files", media: "Audio and video files", imageLogs: "Image history", videoLogs: "Video history", agentMessages: "Agent messages", promptCache: "Prompt cache" },
},
promptSources: {
add: "Add source",
deleteTitle: "Delete “{{name}}”?",
deleteDescription: "The source configuration will be removed. Items already saved to My Assets are unaffected.",
refreshed: "Updated {{count}} prompts from “{{name}}”",
refreshFailedCached: "Update failed; the previous cache was kept",
refreshPartial: "Update complete: {{success}} succeeded and {{failed}} failed. Failed sources kept their previous cache.",
refreshAllSuccess: "Updated {{sources}} sources with {{total}} prompts",
refreshFailed: "Update failed",
builtIn: "Built-in",
itemCount: "{{count}} prompts",
failed: "Failed",
healthy: "Healthy",
unsynced: "Not synced",
lastSuccess: "Last successful {{time}}",
neverFetched: "Not fetched yet",
view: "View content",
refresh: "Fetch now",
edit: "Edit source",
schedule: "Scheduled fetch",
interval: "Fetch interval",
refreshAll: "Fetch all now",
lastFetched: "Last fetched {{time}}",
neverScheduled: "No scheduled fetch yet",
scheduleDescription: "When enabled, all active sources are fetched on this interval while the page is open.",
intervals: {
disabled: "Disabled",
minutes30: "Every 30 minutes",
hour1: "Every hour",
hours6: "Every 6 hours",
hours24: "Every 24 hours",
},
editor: {
addTitle: "Add prompt source",
editTitle: "Edit prompt source",
nameRequired: "Enter a source name",
invalidUrl: "Enter a valid JSON URL",
invalidHomepage: "Enter a valid homepage URL",
name: "Source name",
namePlaceholder: "Used for categories and labels",
homepage: "Source homepage (optional)",
enabled: "Enable source",
jsonFormat: "JSON format",
},
content: {
loadFailed: "Failed to fetch prompts",
title: "{{name}} · Prompt content",
count: "{{count}} prompts",
refresh: "Update now",
empty: "No prompts",
cover: "Cover",
titleColumn: "Title",
tags: "Tags",
actions: "Actions",
},
runtime: { requestFailed: "Request failed ({{status}})", urlRequired: "JSON URL is required", fetchFailed: "Failed to fetch “{{name}}”: {{error}}", noPrompts: "No valid prompts were parsed from “{{name}}”", invalidRoot: "Invalid “{{name}}” format: the root value must be an array" },
},
fileSecurity: "The JSON file contains API keys and WebDAV credentials. Keep it secure.",
import: "Import settings",
export: "Export settings",
imported: "Settings and preferences imported",
importedDirectConfig: "Local direct connection settings imported",
importFailed: "Failed to read the settings file",
saved: "Settings saved",
savedContinue: "Settings saved. Continue with your previous request.",
channels: {
description: "Choose a protocol for each provider, fetch its models, assign capabilities, and optionally customize request scripts.",
add: "Add provider",
unnamed: "Unnamed provider",
numberedName: "Provider {{count}}",
modelCount: "{{count}} models",
missingUrl: "API endpoint not set",
keepOne: "Keep at least one provider",
defaultName: "Default provider",
newName: "New provider",
indexedName: "Provider {{index}}",
},
preferences: {
interface: "Interface",
language: "Display language",
languageDescription: "Change the language used by the interface and components.",
defaultModels: "Default models",
defaultImageModel: "Default image model",
defaultVideoModel: "Default video model",
defaultTextModel: "Default text model",
defaultAudioModel: "Default audio model",
generation: "Generation preferences",
canvasImageCount: "Default canvas image count",
canvasImageCountDescription: "Used by new canvas image and configuration nodes. Individual nodes can override it.",
audioVoice: "Default audio voice",
audioFormat: "Default audio format",
audioSpeed: "Default audio speed",
audioInstructions: "Default audio instructions",
audioInstructionsPlaceholder: "For example: natural, warm, and suitable for narration.",
systemPrompt: "System prompt",
systemPromptPlaceholder: "For example: You are a visual director specializing in cinematic, photorealistic imagery.",
},
channelEditor: {
title: "Edit provider",
name: "Provider name",
protocol: "Protocol",
baseUrl: "API endpoint",
models: "Provider models",
modelDescription: "{{count}} selected; assign a capability to each model and optionally customize its request script.",
selectModels: "Select models",
scriptReady: "Script set",
script: "Request script",
empty: "Select models to fetch or manually add models.",
capabilities: {
image: "Image",
video: "Video",
text: "Text",
audio: "Audio",
},
},
modelSelect: {
missingConfig: "Enter an API endpoint and API key first",
fetched: "Fetched {{count}} models",
fetchFailed: "Failed to fetch models",
title: "Select provider models",
selected: "{{selected}} / {{total}} selected",
confirm: "Confirm",
search: "Search models",
modelName: "Enter a model name",
add: "Add model",
fetch: "Fetch model list",
description: "If the provider does not expose an OpenAI /models endpoint, add model names manually here.",
fetchedTab: "Fetched models ({{count}})",
existingTab: "Selected models ({{count}})",
visibleSelected: "{{selected}} / {{total}} selected in this list",
selectVisible: "Select this list",
clearVisible: "Clear this list",
fetchedEmpty: "Fetch models from the provider or add a model name manually.",
existingEmpty: "No models selected.",
},
scriptEditor: {
description: "The script is an async function body. Use the variables below and return the result; leave it empty to use the default request.",
insertTemplate: "Insert {{name}} template",
restoreDefault: "Restore default request",
returnRequirements: "Return requirements",
variables: "Available variables",
insert: "Click to insert",
placeholder: "// Leave empty to use the default request; insert a template to view an example.",
},
webdav: {
title: "WebDAV sync",
description: "Sync canvases, assets, generation history, and local media files. AI API keys are excluded; the browser connects directly to WebDAV.",
lastSynced: "Last synced {{time}}",
neverSynced: "Not synced yet",
url: "WebDAV URL",
directory: "Remote directory",
directoryDescription: "Business directories are created here, each containing {{manifest}} and files/",
username: "Username",
password: "Password / app password",
test: "Test connection",
syncing: "Syncing",
syncNow: "Sync now",
missingUrl: "Enter a WebDAV URL first",
available: "WebDAV connection is available",
testFailed: "WebDAV connection test failed",
preparing: "Preparing to sync",
failed: "WebDAV sync failed",
completed: "Sync complete: {{projects}} canvases, {{assets}} assets, {{records}} records, and {{files}} files ({{bytes}}) uploaded",
domains: {
canvas: "Canvases",
assets: "My Assets",
imageWorkbench: "Image Studio",
videoWorkbench: "Video Studio",
},
stages: {
waiting: "Waiting",
localWaiting: "Waiting for local data",
syncComplete: "Sync complete",
remoteManifest: "Reading remote manifest",
localData: "Reading local data",
downloadMedia: "Downloading missing media",
writeMerge: "Writing merged local data",
uploadMedia: "Uploading new media",
mediaReady: "Media is up to date",
mediaSkipped: "No media to upload",
checkMissingMedia: "Checking for missing media",
downloadMediaFile: "Downloading media",
checkLocalMedia: "Checking local media",
uploadMediaFile: "Uploading media {{size}}",
uploadManifest: "Uploading manifest {{size}}",
complete: "Complete",
},
errors: { testFailed: "WebDAV connection test failed", downloadFailed: "Failed to read the WebDAV sync file", downloadTimeout: "Timed out while reading the WebDAV sync file", emptyUpload: "The upload file is empty; upload canceled", uploadFailed: "Failed to upload the WebDAV sync file", directoryFailed: "Failed to create the remote WebDAV directory", requestTimeout: "The WebDAV request timed out. Check the network or remote service.", connectionFailed: "Could not connect to WebDAV. Check the address, HTTPS certificate, CORS, and network.", urlRequired: "Enter a WebDAV URL first", authenticationFailed: "WebDAV authentication failed. Check the username, password, or app password.", pathMissing: "The WebDAV path does not exist. Check the address and remote directory.", responseFailed: "{{fallback}}: {{status}}{{detail}}", syncFailed: "Sync failed", invalidManifest: "The {{domain}} sync manifest does not belong to this app" },
},
protocols: {
ark: "Volcengine Ark",
},
},
agent: {
status: { failed: "Connection failed", connected: "Connected", connecting: "Connecting", disconnected: "Disconnected" },
state: { ready: "Ready", connectionRequired: "Enter the Local URL and Connect token", invalidUrl: "The Local URL is invalid", offline: "Offline", skillReadFailed: "Failed to read Skill", skillParseFailed: "Failed to parse Skill", requestFailed: "Local Agent request failed" },
siteTools: { canvasList: "Canvas list", generationStatus: "Generation task status", imageConfig: "Image configuration", imageGenerate: "Generate in Image Studio", videoConfig: "Video configuration", videoGenerate: "Generate in Video Studio", promptSearch: "Search prompts", assetList: "Asset list", assetAdd: "Add asset", unknownTool: "Unknown tool: {{name}}", canvasLoading: "The canvas is still loading. Try again shortly.", canvasHint: "Use site_navigate to open /canvas/{id}", assetsLoading: "Assets are still loading. Try again shortly.", assetTitleRequired: "Provide the asset title", textContentRequired: "content is required when kind=text", imageUrlRequired: "imageUrl is required when kind=image", imageReadFailed: "Could not read the image. Use a data URL or a cross-origin accessible image URL.", assetKindUnsupported: "assets_add supports only kind=text or kind=image", imageGenerationStarted: "Opened Image Studio and started generation. Use generation_get_status to query the task.", imageConfigApplied: "Opened Image Studio and applied the parameters without starting generation.", videoGenerationStarted: "Opened Video Studio and started generation. Use generation_get_status to query the task.", videoConfigApplied: "Opened Video Studio and applied the parameters without starting generation." },
connect: { pluginTitle: "Option 1: Use the Codex plugin", pluginText: "Install the Infinite Canvas plugin in the Codex app and launch the canvas through it. The plugin starts the local Agent and supplies the connection details automatically.", directTitle: "Option 2: Run the Agent directly", directText: "Without the Codex plugin, run the command below in a terminal, then return here to connect or enter the Local URL and Connect token manually.", commandCopied: "Command copied", pluginReminder: "Codex plugin note", pluginReminderText: "The tool list enters the Codex context and consumes additional tokens only after installing the Codex plugin or adding MCP manually. Running npx -y @basketikun/canvas-agent alone does not install MCP.", removePlugin: "Remove plugin", removeMcp: "Remove manual MCP", copyCommand: "Copy command", title: "Connect local Agent", description: "Choose the connection method that fits your workflow.", webConnection: "Web connection", autoDiscover: "The Local URL and Connect token are discovered automatically by default. Enter them manually only if discovery fails.", disconnect: "Disconnect", connect: "Connect", localAddress: "Local address", urlPlaceholder: "For example http://127.0.0.1:17371", token: "Connection token", tokenPlaceholder: "Discover automatically or enter the Connect token" },
history: { workspace: "Workspace", defaultWorkspace: "Default canvas directory", selected: "{{count}} selected", count: "{{count}} conversations", empty: "No history", deleteCount: "Delete {{count}}", refresh: "Refresh", newThread: "New chat", selectThread: "Select {{name}}", untitled: "Untitled conversation", current: "Current", noWorkspaceThreads: "No conversations in this workspace yet", connectHint: "Connect the local Agent to view conversation history" },
skills: { selectLocal: "Select local Skill", search: "Search Skills", loading: "Loading Skills…", noMatch: "No matching enabled Skills", none: "No Skills available", select: "Select Skill", connectHint: "Connect the Agent to use Skills" },
skillManager: {
codexBusy: "Codex is running. Finish the current task before extracting a Skill.", noConversation: "This conversation has no completed content to extract", noCanvas: "There is no canvas on this page to extract", connecting: "This page is still connecting to the Agent. Try again shortly.", syncFailed: "Failed to sync the current canvas. Check the Agent connection and try again.", noDraft: "No Skill draft was generated", draftCreated: "Draft generated. Review it on the Skills tab before creating it.", draftFailed: "Failed to generate Skill draft", contentMissing: "Skill content was not returned", readFailed: "Failed to read Skill", defaultPromptMention: "The default prompt must include ${{name}}", created: "Skill created", updated: "Skill updated", saveFailed: "Failed to save Skill", deleteTitle: "Delete {{name}}", deleteDescription: "The local files cannot be recovered after deletion. Continue?", delete: "Delete", deleted: "Skill deleted", deleteFailed: "Failed to delete Skill", statusFailed: "Failed to update Skill status",
fromConversation: "Generate draft from this conversation", availableAfterRun: "Available when Codex finishes running", conversationDescription: "Extract reusable workflows from this conversation", noCompletedContent: "This conversation has no completed content", startConversation: "Start a conversation first", fromCanvas: "Generate draft from this canvas", canvasDescription: "Extract nodes and generation workflows from this page", canvasUnavailable: "There is no available canvas on this page", blankCreate: "Create from scratch", blankDescription: "Start with an empty form", localSkills: "Local Skills", localDescription: "Installed locally and run directly by Codex", reload: "Reload", reloadSkill: "Reload Skills", createSkill: "Create Skill", filterBySource: "Filter Skills by source", scopes: { all: "All sources", repo: "Project", user: "Personal", system: "System", admin: "Admin" }, loadErrors: "{{count}} Skills could not be loaded", externalReadonly: "External Skills can only be used or enabled and disabled", noDescription: "No description", enabled: "Enabled", disabled: "Disabled", selected: "Selected", use: "Use", editNamed: "Edit {{name}}", deleteNamed: "Delete {{name}}", connectToView: "Connect the Agent to view Skills", noMatch: "No matching Skills", none: "No local Skills yet", connectDescription: "Installed local Skills will load after connection", tryAnotherFilter: "Try another keyword or source", createOrInstall: "Create one, or install one locally and refresh", saveChanges: "Save changes", saveLocation: "Save to the local Agent workspace", basicInfo: "Basic information",
identifier: "Skill identifier", identifierExtra: "Used as the folder name and for $skill-name invocation.", identifierRequired: "Enter a Skill identifier", identifierMax: "The Skill identifier cannot exceed 64 characters", identifierPattern: "Use lowercase letters, numbers, and hyphens only; hyphens cannot repeat or appear at either end", identifierPlaceholder: "For example, product-grid", displayName: "Display name", displayNameMax: "The display name cannot exceed 64 characters", displayNamePlaceholder: "For example, Product grid generator", whenToUse: "When to use", whenToUseExtra: "Describe the Skill's capabilities and use cases so Codex can decide when to invoke it.", whenToUseRequired: "Describe when to use this Skill", whenToUseMax: "The use-case description cannot exceed 1,024 characters", noAngleBrackets: "The use-case description cannot contain angle brackets", whenToUsePlaceholder: "For example: Use when planning and generating a set of product images from product information", instructions: "Instructions", instructionsExtra: "Describe the steps, constraints, and output requirements in execution order.", instructionsRequired: "Enter the instructions", instructionsPlaceholder: "Describe execution steps, required checks, and the final output", advanced: "Advanced settings", shortDescription: "Card summary", shortDescriptionExtra: "Use 2564 characters for easy scanning.", shortDescriptionMin: "The card summary must contain at least 25 characters", shortDescriptionMax: "The card summary cannot exceed 64 characters", shortDescriptionPlaceholder: "Optional; shown in the list", defaultPrompt: "Default prompt", defaultPromptExtra: "Must include the exact $skill-name, such as $product-grid.", defaultPromptMax: "The default prompt cannot exceed 1,024 characters", defaultPromptPlaceholder: "Optional; prefilled when the Skill is selected",
},
composer: { removeImage: "Remove image", removeSkill: "Remove Skill", uploadImage: "Upload image", stop: "Stop", send: "Send", model: "Model: {{model}}", selectModel: "Select a Codex model. Current: {{model}}", reasoning: "Reasoning effort: {{effort}}", selectReasoning: "Select reasoning effort. Current: {{effort}}", permissionLabel: "Permissions: {{mode}}", selectPermission: "Select Codex permission mode. Current: {{mode}}", effort: { minimal: "Minimal", low: "Low", medium: "Medium", high: "High", xhigh: "Extra high", max: "Maximum", ultra: "Ultra" }, permission: { request: "Ask for approval", requestDescription: "Always ask before editing outside the workspace or accessing the network", automatic: "Automatic review", automaticDescription: "Codex reviews risky actions and asks only when needed", full: "Full access", fullShort: "Full access", fullDescription: "Unrestricted access to the network and local files" }, tools: { label: "Tool confirmation: {{mode}}", manual: "Manual", manualDescription: "Ask before the Agent writes to the canvas", automatic: "Automatic", automaticDescription: "Let the Agent perform canvas writes automatically", select: "Select tool confirmation mode. Current: {{mode}}" } },
panel: { connectionSettings: "Connection settings · {{status}}", connectionSettingsLabel: "Connection settings. Current status: {{status}}", chat: "Chat", history: "History", skills: "Skills", logs: "Logs", collapse: "Collapse chat", collapseLabel: "Collapse Agent panel", resize: "Resize right panel", content: "Agent content", mcpInitializing: "MCP is initializing. You can send messages when it is ready.", initFailed: "Codex conversation initialization failed. Start or resume a conversation.", placeholder: "Ask Codex or have it operate the site or canvas" },
chat: { latestMessages: "View latest messages", latestCall: "Latest call", input: "Input", cached: "Cached", output: "Output" },
logs: { copied: "Logs copied", selectedManual: "Logs selected; copy them manually", copyFailed: "Copy failed. Switch to raw JSON and copy manually.", title: "Runtime logs", diagnostics: "Diagnostics", rawJson: "Raw JSON", messages: "{{count}} messages", tool: "Tool: {{tool}}", noPendingTool: "No pending tool", all: "All {{count}}", errors: "Errors {{count}}", warnings: "Warnings {{count}}", info: "Info {{count}}", list: "Diagnostics log list", noFiltered: "No logs match this filter", empty: "No event logs", new: "{{count}} new logs", newLabel: "{{count}} new logs. View latest logs.", latest: "View latest logs", fullData: "Full diagnostics · {{count}} entries", copyAll: "Copy all logs", copyLastError: "Copy latest error", lastErrorCopied: "Latest error copied", clear: "Clear logs", repeated: "Repeated {{count}} times", details: "Details", skillLoading: "Skill loading", plugin: "Plugin", terminal: "Terminal", conversationStorage: "Conversation storage" },
message: { close: "Close", copied: "Copied", copyCode: "Copy code", copyLink: "Copy link", externalWarning: "You are about to open an external link. Make sure you trust it.", openExternal: "Open external link?", continueOpen: "Open", revealed: "Revealed in file manager", openLocalFailed: "Could not open the local file", openLocal: "Open local file?", localDescription: "This path will be revealed in your local file manager and will not be opened in the browser.", externalDescription: "You are about to open an external link. Make sure you trust it.", pathCopied: "Path copied", linkCopied: "Link copied", copyPath: "Copy path", showInFolder: "Show in file manager", toolCall: "Tool call", awaitingConfirmation: "Awaiting confirmation", reject: "Reject", approve: "Approve", networkApproval: "Network access request", fileApproval: "File edit request", permissionApproval: "Extended permission request", commandApproval: "Command execution request", decline: "Decline", allowOnce: "Allow once", allowSession: "Allow for session", thinking: "Thinking", commandsRunning: "Running {{count}} commands", commandRunning: "Running command", commandsCompleted: "Ran {{count}} commands{{failed}}", commandsFailed: " · {{count}} failed", failed: "Failed", running: "In progress", completed: "Completed", command: "Command", slowResponse: "The response is taking longer, but the task is still running. You can keep waiting or use the stop button beside the input to end this turn.", waitingSeconds: "Waited {{seconds}} seconds", waitingMinutes: "Waited {{minutes}}m {{seconds}}s", files: "Files", errorInfo: "Error", output: "Output", viewLarge: "View full image", attachmentPreview: "Image attachment preview", noEffect: "No effect", canceled: "Canceled", recorded: "Recorded", stopped: "Stopped", finished: "Finished", pending: "Pending" },
events: { analyzing: "Analyzing the task…", reasoning: "Reasoning summary", plan: "Execution plan", commandFailed: "Command failed", commandCompleted: "Command completed", executeCommand: "Run command", editFiles: "Edit files", searchWeb: "Search the web", viewImage: "View image", imageViewed: "Image viewed", viewingImage: "Viewing image", imageGeneration: "Generate image", imageFailed: "Image generation failed", imageCompleted: "Image generation completed", generatingImage: "Generating image…", compactContext: "Compact context", contextCompacted: "Conversation context compacted; continuing the task", compactingContext: "Compacting conversation context…", collaboration: "Collaborate", collaborationFailed: "Collaboration task failed", collaborationCompleted: "Collaboration task completed", collaborating: "Working with collaborators…", progress: "Task progress", progressCount: "{{completed}}/{{total}} completed", planning: "Preparing execution steps…", executingCommand: "Running command…", workingDirectory: "Working directory", exitStatus: "Exit status", duration: "Duration", seconds: "{{value}} seconds", filesCompleted: "File changes completed", preparingFiles: "Preparing file changes…", fileCompleted: "{{action}} completed: {{path}}", editingFile: "{{action}} in progress: {{path}}", filesEdited: "Edited {{count}} files: {{names}}{{more}}", editingFiles: "Editing {{count}} files: {{names}}{{more}}", andMore: " and more", openPage: "Open page: {{url}}", findInPage: "Find “{{pattern}}” on page", content: "content", search: "Search: {{query}}", relatedInfo: "related information", keyword: "Keyword", webpage: "Web page", add: "Add", delete: "Delete", edit: "Edit", diagnostics: "Infinite Canvas Agent diagnostics", address: "Address: {{endpoint}}", connection: "Connection: {{connection}} · Status: {{status}}", online: "Online", connecting: "Connecting", disabled: "Disabled", messageTool: "Messages: {{messages}} · Tool: {{tool}}", none: "None", noLogs: "No event logs", threadCreated: "Conversation created", turnStarted: "Processing started", progressUpdated: "Task progress updated", turnFailed: "Processing failed", turnStopped: "Processing stopped", turnCompleted: "Processing completed", toolCalled: "Tool called", toolFailed: "Tool failed", toolCompleted: "Tool completed", replyReceived: "Reply received", completed: "Completed", modelBusy: "Model temporarily busy", modelBusyDescription: "The selected model is receiving too many requests. Try again later or switch models.", taskFailed: "Task failed", taskFailedDescription: "Codex could not complete this task. Try again later." },
eventExtra: { toolNamed: "Call tool: {{name}}", toolOperation: "Tool operation", targetPage: "Target page", searchContent: "Search query", textContent: "Text content", operationContent: "Operations", imageCount: "Image count", tools: { generateImage: "Generate image", viewImage: "View image", executeCommand: "Run command", editFiles: "Edit files", searchWeb: "Search the web", canvasOps: "Canvas operations", readCanvas: "Read canvas", readSelection: "Read selection", exportSnapshot: "Export snapshot", createNode: "Create node", addAttachments: "Add attachment images", createText: "Create text", createTexts: "Create text nodes", createConfig: "Create generation config", createImageFlow: "Create image flow", createGenerationFlow: "Create generation flow", generateText: "Generate text", generateVideo: "Generate video", generateAudio: "Generate audio", updateNode: "Update node", updateText: "Update text", moveNodes: "Move nodes", resizeNode: "Resize node", deleteNodes: "Delete nodes", connectNodes: "Connect nodes", selectNodes: "Select nodes", setViewport: "Adjust viewport", runGeneration: "Run generation", openPage: "Open page" } },
eventMore: { toolRunning: "{{action}}…", openedRoute: "Opened {{route}}", canvasCount: "{{count}} canvases", promptCount: "Found {{count}} prompts", assetCount: "{{count}} assets", assetAdded: "Added to My Assets", generationStatus: "{{total}} tasks: {{queued}} queued, {{running}} running, {{succeeded}} succeeded, {{failed}} failed", workbenchExecuted: "Executed in the workbench", workbenchConfigRead: "Workbench configuration read", canvasRead: "Current canvas read", selectionRead: "Current selection read", textNodes: "{{count}} text nodes", imageNodes: "{{count}} images", configNodes: "{{count}} config nodes", videoNodes: "{{count}} videos", audioNodes: "{{count}} audio nodes", groupNodes: "{{count}} groups", otherNodes: "{{count}} other nodes", connections: "{{count}} connections", emptyCanvas: "The canvas is empty", executeTool: "Run {{tool}}", thinking: "Thinking...", operationRunning: "{{operation}} is running...", organizingCanvas: "Canvas read; Codex is organizing the result...", operationCompleted: "{{operation}} completed; Codex is continuing...", attachmentPrompt: "Please process the uploaded image attachments.", routes: { home: "Home", canvas: "Canvas", canvasProject: "Selected canvas", image: "Image Studio", video: "Video Studio", prompts: "Prompt Center", assets: "My Assets", config: "Settings" } },
runtime: {
mcpStarting: "Starting MCP: {{name}}", mcpConnecting: "Connecting tools and loading the available tool list", mcpReadyNamed: "MCP ready: {{name}}", toolsReady: "Tool list loaded. You can start chatting.", mcpFailedNamed: "MCP failed to start: {{name}}", mcpCanceledNamed: "MCP startup canceled: {{name}}", toolInitFailed: "The tool service could not finish initializing", mcpServicesStarting: "Starting MCP services", toolServicesPending: "{{count}} tool services are still initializing", checkingToolServices: "Checking tool service status", conversationInitializing: "Initializing the Codex conversation", conversationCreating: "Creating the conversation and starting canvas tools", someMcpFailed: "Some MCP services failed to initialize", remainingToolsReady: "The remaining tools are ready. You can start chatting.", conversationInitFailed: "Codex conversation initialization failed", conversationCreateFailed: "Could not create the Codex conversation", mcpServicesReady: "{{count}} MCP services initialized", toolInitCanceled: "Tool service initialization was canceled", mcpStatusComplete: "MCP status check completed", mcpListRead: "Loaded the complete tool service list returned by Codex",
historyReadFailed: "Failed to read history", conversationSyncFailed: "Failed to sync conversation", agentOutdated: "The local Agent is outdated. Restart Canvas Agent and reconnect.", restartRequired: "Agent restart required", versionMismatch: "Agent version mismatch", awaitingApproval: "Awaiting approval", codexRunning: "Codex is running", connected: "Connected", localAgentConnected: "Local Agent connected", processingFailed: "Processing failed", completed: "Completed", approvalGranted: "Permission approved", approvalCanceled: "Permission canceled", log: "Log", connectionLostDescription: "The local Agent connection failed or was interrupted", connectionFailedDescription: "Connection failed. Check the address and token.", connectionLost: "Connection lost", connectionFailed: "Connection failed", modelListFailed: "Failed to load model list",
imageTooLarge: "Image too large", imagePayloadTooLarge: "Image attachments exceed 30 MB. Remove some before sending.", imagesSent: "Sent {{count}} images", sending: "Sending", defaultModel: "Default model", defaultEffort: "Default effort", sendTask: "Send task", attachmentCount: "{{count}} attachments", attachmentsOnly: "Attachments only", startConversationFailed: "Failed to start conversation", attachmentHistoryFailed: "Failed to save attachment history", sendFailed: "Send failed", conversationSynced: "Conversation synced", taskStillRunning: "Task is still running", stopping: "Stopping", stopTask: "Stop task", taskStopped: "Task stopped", stopFailed: "Failed to stop", imageLimit: "Image attachments are limited to about 30 MB.", imageReadFailed: "Failed to read image", pendingCanvasTool: "Another canvas tool call is awaiting confirmation", awaitingConfirmation: "Awaiting confirmation", toolCompleted: "{{tool}} completed", toolExecutionFailed: "Tool execution failed", openCanvasFirst: "The canvas is not open. Use site_navigate to open it first.", canvasOperationFailed: "Canvas operation failed", canvasToolCanceled: "The user canceled the canvas tool call",
submittingApproval: "Submitting permission decision", waitingCodexApproval: "Waiting for Codex to confirm permission", approvalFailed: "Permission approval failed", enableFullAccess: "Enable full access", fullAccessDescription: "Codex will run without sandbox restrictions and can access the internet and any local files. Use this only when you trust the current task.", enableFullAccessAction: "Enable full access", offline: "Offline", addressRequired: "Enter the local Agent address", agentNotFound: "No local Agent was found. Use the Codex plugin or start Canvas Agent manually.", invalidAddress: "The local Agent address is invalid", connecting: "Connecting", creatingConversation: "Creating conversation", newConversation: "New conversation", newConversationFailed: "Failed to create conversation", conversationResumed: "Conversation resumed", resumeConversationFailed: "Failed to resume conversation", recordsDeleted: "Deleted {{count}} records", deleteConversationFailed: "Failed to delete conversation", deleteConversations: "Delete {{count}} conversations", deleteConversationsDescription: "This cannot be undone. Continue?", importGeneratedImages: "Import generated images", addedToSourceCanvas: "Added to the source canvas", imageGenerated: "Image generated", noImageAttachments: "No image attachments to add", invalidAttachmentNode: "Invalid image attachment node parameters", attachmentReadFailed: "Failed to read image attachment", referenceImage: "Reference image", generatedImageReadFailed: "Failed to read the image generated by Codex", generatedImageName: "Generated image {{index}}",
},
},
locale: {
zhCN: "简体中文",
enUS: "English",
},
};