mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-08-07 01:54:24 +08:00
609 lines
72 KiB
TypeScript
609 lines
72 KiB
TypeScript
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 24–60 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 2–15 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 2–15 seconds", seedanceVideoTotalDuration: "Seedance reference videos cannot exceed 15 seconds in total", seedanceAudioDuration: "Each Seedance reference audio file must be 2–15 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: 2–15 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 25–64 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",
|
||
},
|
||
};
|