2102 lines
99 KiB
TypeScript
2102 lines
99 KiB
TypeScript
export const en = {
|
||
// --- Common ---
|
||
'common.add': 'Add',
|
||
'common.cancel': 'Cancel',
|
||
'common.cancelButton': 'Cancel',
|
||
'common.delete': 'Delete',
|
||
'common.description': 'Description',
|
||
'common.edit': 'Edit',
|
||
'common.failed': 'Failed',
|
||
'common.generating': 'Generating',
|
||
'common.loading': 'Loading',
|
||
'common.missing': 'Missing',
|
||
'common.name': 'Name',
|
||
'common.pending': 'Pending',
|
||
'common.queued': 'Queued',
|
||
'common.ready': 'Ready',
|
||
'common.rename': 'Rename',
|
||
'common.retry': 'Retry',
|
||
'common.running': 'Running',
|
||
'common.save': 'Save',
|
||
'common.saved': 'Saved',
|
||
'common.saveFailed': 'Save failed',
|
||
'common.saving': 'Saving',
|
||
'common.send': 'Send',
|
||
'common.stop': 'Stop',
|
||
'common.title': 'Title',
|
||
'common.language': 'Language',
|
||
|
||
// --- App shell / nav ---
|
||
'nav.canvas': 'AI Canvas',
|
||
'nav.library': 'Asset Library',
|
||
'nav.projects': 'Projects',
|
||
'nav.buildScene': 'Build Scene',
|
||
'nav.settings': 'Settings',
|
||
'nav.agents': 'Agents',
|
||
'nav.models': 'Models',
|
||
'nav.home': 'Home',
|
||
'nav.primary': 'Primary',
|
||
'nav.projectStages': 'Project stages',
|
||
'nav.backProjects': 'Back to projects',
|
||
'nav.story': 'Story',
|
||
'nav.assets': 'Assets',
|
||
'nav.script': 'Script',
|
||
'nav.video': 'Video',
|
||
'nav.countActive': '{count} active',
|
||
'nav.eyebrow': 'Calliope',
|
||
'nav.unsaved': 'Unsaved changes',
|
||
'nav.llm': 'LLMs',
|
||
'nav.llmBlurb': 'Configure the language models used by the agent.',
|
||
'nav.comfy': 'ComfyUI',
|
||
'nav.comfyBlurb': 'Where ComfyUI runs.',
|
||
'nav.workflows': 'Workflows',
|
||
'nav.workflowsBlurb': 'Upload and register ComfyUI workflows for generation.',
|
||
'nav.agent': 'Agent model',
|
||
'nav.agentBlurb': 'Model used for story drafting and agent tasks.',
|
||
'nav.skills': 'Skills',
|
||
'nav.skillsBlurb': 'Agent skills available in this project.',
|
||
'nav.queue': 'Job queue',
|
||
'nav.queueBlurb': 'Concurrency and timeouts for generation jobs.',
|
||
'nav.storage': 'System Paths',
|
||
'nav.storageBlurb': 'Where files live, and where the agent may work.',
|
||
|
||
// --- Toast ---
|
||
'toast.dismiss': 'Dismiss',
|
||
'toast.undo': 'Undo',
|
||
'toast.uploadFailed': 'Upload failed',
|
||
|
||
// --- Modal ---
|
||
'modal.dialog': 'Dialog',
|
||
'modal.closeDialog': 'Close dialog',
|
||
|
||
// --- Projects page ---
|
||
'projects.new': 'New Project',
|
||
'projects.title': 'Projects',
|
||
'projects.subtitle': 'Your local story-to-video workspace. Pick up where you left off.',
|
||
'projects.newReel': 'New reel',
|
||
'projects.close': 'Close',
|
||
'projects.titleField': 'Title',
|
||
'projects.titlePlaceholder': 'Moonlit Harbor',
|
||
'projects.ideaField': 'Story idea',
|
||
'projects.ideaPlaceholder':
|
||
'A lighthouse keeper finds a glowing bottle that shows memories of sailors lost at sea…',
|
||
'projects.ideaHint': 'Optional — you can refine this later on the Story stage.',
|
||
'projects.genre': 'Genre',
|
||
'projects.tone': 'Tone',
|
||
'projects.duration': 'Target duration',
|
||
'projects.durationHint': 'Guides beat and scene counts on the Story stage.',
|
||
'projects.cancel': 'Cancel',
|
||
'projects.create': 'Create project',
|
||
'projects.searchPlaceholder': 'Search projects…',
|
||
'projects.searchLabel': 'Search projects',
|
||
'projects.filterBy': 'Filter by status',
|
||
'projects.filterAll': 'All',
|
||
'projects.filterProgress': 'In Progress',
|
||
'projects.filterCompleted': 'Completed',
|
||
'projects.filterDraft': 'Drafts',
|
||
'projects.loading': 'Loading projects',
|
||
'projects.loadError': "Couldn't load projects",
|
||
'projects.loadErrorBody': 'The backend did not respond.',
|
||
'projects.emptyTitle': 'No projects yet',
|
||
'projects.emptyBody':
|
||
'Calliope turns a story idea into characters, shots and finished video — all on your machine.',
|
||
'projects.firstProject': 'Create your first project',
|
||
'projects.noMatchSearch': 'No projects match “{q}”',
|
||
'projects.noMatchFilter': 'No projects match the current filter',
|
||
'projects.noMatchBody': 'Try a different search or clear the filters.',
|
||
'projects.clearFilters': 'Clear filters',
|
||
'projects.newCard': 'Create New Project',
|
||
'projects.newCardSub': 'Start with a story idea',
|
||
'projects.created': 'Project “{title}” created',
|
||
'projects.createFailed': 'Could not create project',
|
||
|
||
// --- Project form options (values stored in English) ---
|
||
'genres.adventure': 'Adventure / Mystery',
|
||
'genres.drama': 'Drama',
|
||
'genres.scifi': 'Sci-Fi',
|
||
'genres.fantasy': 'Fantasy',
|
||
'genres.horror': 'Horror',
|
||
'genres.romance': 'Romance',
|
||
'genres.thriller': 'Thriller',
|
||
'tones.cinematic': 'Cinematic, atmospheric',
|
||
'tones.dark': 'Dark, tense',
|
||
'tones.whimsical': 'Whimsical, warm',
|
||
'tones.gritty': 'Gritty, realistic',
|
||
'tones.epic': 'Epic, sweeping',
|
||
'durations.30': '30 seconds',
|
||
'durations.1m': '1 minute',
|
||
'durations.2m': '2 minutes',
|
||
'durations.5m': '5 minutes',
|
||
'durations.10m': '10 minutes',
|
||
|
||
// --- Project card ---
|
||
'projectCard.actions': 'Project actions',
|
||
'projectCard.assets': 'Assets',
|
||
'projectCard.changeCover': 'Change cover',
|
||
'projectCard.characters': 'Characters',
|
||
'projectCard.deleted': 'Project deleted',
|
||
'projectCard.deleteFailed': 'Could not delete project',
|
||
'projectCard.deleteMessage': 'This will permanently delete the project and its assets. This cannot be undone.',
|
||
'projectCard.deleteTitle': 'Delete project',
|
||
'projectCard.menuLabel': 'Project menu',
|
||
'projectCard.noIdea': 'No story idea yet',
|
||
'projectCard.open': 'Open project',
|
||
'projectCard.renamedTo': 'Renamed to “{title}”',
|
||
'projectCard.renameFailed': 'Could not rename project',
|
||
'projectCard.renameTitle': 'Rename project',
|
||
'projectCard.scenes': 'Scenes',
|
||
'projectCard.status.in_progress': 'In Progress',
|
||
'projectCard.status.completed': 'Completed',
|
||
'projectCard.status.draft': 'Draft',
|
||
'projectCard.timeJustNow': 'just now',
|
||
'projectCard.timeM': '{n}m ago',
|
||
'projectCard.timeH': '{n}h ago',
|
||
'projectCard.timeD': '{n}d ago',
|
||
'projectCard.timeMo': '{n}mo ago',
|
||
'projectCard.timeY': '{n}y ago',
|
||
|
||
// --- Project detail page ---
|
||
'project.backToProjects': 'Back to projects',
|
||
'project.notFound': 'Project not found',
|
||
'project.invalidIdBody': '“{id}” isn’t a valid project id — the link may be broken or the project was deleted.',
|
||
'project.openVideoStage': 'Open the Video stage',
|
||
'project.runningQueued': '{running} running · {queued} queued',
|
||
'project.queueIdle': 'Queue idle',
|
||
|
||
// --- API errors ---
|
||
'api.unknownError': 'Something went wrong',
|
||
'api.networkError': 'Cannot reach the workbench backend — check that it is running and retry',
|
||
'api.httpError': 'Request failed (HTTP {status}): {detail}',
|
||
'playground.openFailed': 'Failed to open playground',
|
||
'playground.opening': 'Opening playground…',
|
||
'agents.opening': 'Opening agent…',
|
||
'agents.openFailed': 'Failed to open agent',
|
||
|
||
// --- ActivityPanel ---
|
||
'activity.title': 'Activity',
|
||
'activity.agentLog': 'Agent log',
|
||
'activity.agentWorking': 'Agent working…',
|
||
'activity.assetReady': 'Asset ready',
|
||
'activity.busyCount': '{n} busy',
|
||
'activity.connecting': 'Connecting',
|
||
'activity.reconnecting': 'Reconnecting',
|
||
'activity.quiet': 'Idle',
|
||
'activity.quietHint': 'No background jobs',
|
||
'activity.show': 'Show',
|
||
'activity.hide': 'Hide',
|
||
'activity.done': 'Done',
|
||
'activity.failed': 'Failed',
|
||
'activity.files': 'Files',
|
||
'activity.filesSaved': '{n} files saved',
|
||
'activity.finished': 'Finished',
|
||
'activity.jobDeleted': 'Job deleted',
|
||
'activity.outputSaved': 'Output saved',
|
||
'activity.queue': 'Queue',
|
||
'activity.queueIdle': 'Queue idle',
|
||
'activity.queueStats': '{active} active · {queued} queued',
|
||
'activity.queued': 'Queued',
|
||
'activity.removed': 'Removed',
|
||
'activity.running': 'Running',
|
||
'activity.storylineDrafted': 'Storyline drafted',
|
||
'activity.storyReady': 'Story ready',
|
||
'activity.working': 'Working…',
|
||
|
||
// --- SafeMedia ---
|
||
'safeMedia.noMedia': 'No media',
|
||
|
||
// --- ImageLightbox ---
|
||
'lightbox.clickToFit': 'Click to fit',
|
||
'lightbox.clickToZoom': 'Click to zoom',
|
||
'lightbox.closeEsc': 'Press Esc to close',
|
||
'lightbox.closeHint': 'Close',
|
||
'lightbox.closePreview': 'Close preview',
|
||
'lightbox.download': 'Download',
|
||
'lightbox.downloadMedia': 'Download media',
|
||
'lightbox.fitToScreen': 'Fit to screen',
|
||
'lightbox.imagePreview': 'Image preview',
|
||
'lightbox.imageUnavailable': 'Image unavailable',
|
||
'lightbox.next': 'Next',
|
||
'lightbox.prev': 'Previous',
|
||
'lightbox.openOriginal': 'Open original',
|
||
'lightbox.videoPreview': 'Video preview',
|
||
'lightbox.videoUnavailable': 'Video unavailable',
|
||
'lightbox.zoom100': '100%',
|
||
'lastFrame.export': 'Export last frame',
|
||
'lastFrame.exporting': 'Exporting last frame…',
|
||
'lastFrame.hint': 'Save the final frame as a full-size PNG, e.g. as a first-frame reference',
|
||
'lastFrame.fileTag': 'last-frame',
|
||
'lastFrame.done': 'Exported last frame {name} ({size})',
|
||
'lastFrame.errTimeout': 'The video took too long to load. Try again later.',
|
||
'lastFrame.errNotFound': 'The video file is missing or was removed.',
|
||
'lastFrame.errForbidden': 'You do not have permission to read this video.',
|
||
'lastFrame.errNetwork': 'Reading the video failed (network error). Check the connection and retry.',
|
||
'lastFrame.errDecode': 'The video is damaged; its ending cannot be decoded.',
|
||
'lastFrame.errUnsupported': 'This browser cannot play the video format, or the file is damaged.',
|
||
'lastFrame.errCrossOrigin':
|
||
'The video comes from another site that blocks reading its frames (cross-origin). Download the video first.',
|
||
'lastFrame.errNoPicture': 'This file has no video picture.',
|
||
'lastFrame.errUnseekable':
|
||
'Cannot reach the end of the video (unknown length, or the source does not allow seeking); no frame exported.',
|
||
'lastFrame.errBlack': 'The last second of the video is black; no frame exported.',
|
||
'lastFrame.errEmpty': 'The browser could not decode the ending. Retry, or use desktop Chrome / Edge.',
|
||
'lastFrame.errUnknown': 'Exporting the last frame failed: {msg}',
|
||
|
||
// --- Artifact / canvas nodes ---
|
||
'artifact.artifactLabel': 'Artifact',
|
||
'artifact.fileMissing': 'File missing',
|
||
'artifact.imageUnavailable': 'Image unavailable',
|
||
'artifact.playInViewer': 'Play in viewer',
|
||
'artifact.playVideo': 'Play video',
|
||
'artifact.videoUnavailable': 'Video unavailable',
|
||
'artifact.viewImage': 'View image',
|
||
'canvas.emptyHint': 'Ask the agent on the right to create characters, scenes, or to generate an image or video — outputs land here as cards.',
|
||
'canvas.loadFailed': 'Could not load this canvas',
|
||
'canvas.tidy': 'Tidy layout',
|
||
'canvas.tidyTitle': 'Re-arrange all cards into clean columns and grids',
|
||
'canvas.savePosFailed': 'Could not save position',
|
||
'canvas.openThatFailed': 'Could not open that canvas',
|
||
'canvas.sessionCreateFailed': 'Could not create session',
|
||
'canvas.sessionDeleteFailed': 'Could not delete session',
|
||
'canvas.renameFailed': 'Rename failed',
|
||
'canvas.suggestFilm': 'Create a new film',
|
||
'canvas.suggestStory': 'Draft a storyline',
|
||
'canvas.emptyBoard': 'Empty board',
|
||
'canvas.noChatSelected': 'No chat selected',
|
||
'canvas.failed': 'failed',
|
||
'canvas.generating': 'generating…',
|
||
'canvas.noMedia': 'no media',
|
||
'canvas.openPreview': 'Open large preview',
|
||
'canvas.running': 'running',
|
||
'canvas.openFailed': 'Failed to open board',
|
||
'canvas.opening': 'Opening board…',
|
||
'canvas.invalidId': 'Invalid canvas id',
|
||
'canvas.confirmDeleteChat': 'Delete this chat and its message history?',
|
||
'canvas.sessionDeleted': 'Session deleted',
|
||
'canvas.chatUnlinked': 'Chat unlinked — moved to Sandbox',
|
||
'canvas.unlinkFailed': 'Unlink failed',
|
||
'canvas.unlinkButton': 'Unlink',
|
||
'canvas.resizePanel': 'Resize chat panel (drag or arrow keys), currently {width} pixels',
|
||
'canvas.sendFailed': 'Failed to send',
|
||
'canvas.runCancelled': 'Run cancelled',
|
||
'canvas.cancelFailed': 'Cancel failed',
|
||
'canvas.tidied': 'Tidied {count} cards into columns',
|
||
'canvas.tidyFailed': 'Tidy failed',
|
||
'canvas.rename': 'Rename canvas',
|
||
'canvas.waitFinish': 'Wait for the run to finish',
|
||
'canvas.unlinkFrom': 'Unlink this chat from {title}',
|
||
'canvas.noChatYet': 'No chat on this canvas yet',
|
||
'canvas.collapseChat': 'Collapse chat',
|
||
'canvas.expandChat': 'Expand chat',
|
||
'canvas.deleteBlocked': 'Project assets and running jobs can’t be deleted here — replace them from Project Assets',
|
||
'canvas.deleteFailed': 'Could not delete {count} card(s)',
|
||
'canvas.deletedWithFile': 'Deleted {count} card(s) and file(s) from the Asset Library',
|
||
'canvas.deletedCardOnly': 'Removed {count} card(s) — file kept (project data)',
|
||
'canvas.deletedMixed': 'Deleted {files} file(s), kept {kept} (project data)',
|
||
'global.somethingWentWrong': 'Something went wrong.',
|
||
|
||
// --- Memory ---
|
||
'memory.title': 'Memory',
|
||
'memory.lead': 'Persisted facts the agent remembers across sessions.',
|
||
'memory.empty': 'Nothing saved yet',
|
||
'memory.loading': 'Loading memory',
|
||
'memory.placeholder': 'Add a fact the agent should remember…',
|
||
'memory.saveFailed': 'Could not save memory',
|
||
'memory.saved': 'Saved',
|
||
'memory.deleteFailed': 'Could not delete',
|
||
'memory.forget': 'Forget',
|
||
'memory.chooseProject': 'Project',
|
||
'memory.kindConvention': 'Convention',
|
||
'memory.kindCorrection': 'Correction',
|
||
'memory.kindPreference': 'Preference',
|
||
'memory.groupGlobal': 'Global',
|
||
'memory.groupProject': 'Project',
|
||
'memory.scopeGlobal': 'All projects',
|
||
'memory.scopeProject': 'This project',
|
||
'memory.sourceAgent': 'Agent',
|
||
'memory.sourceYou': 'You',
|
||
'memory.usedCount': 'Used {n} times',
|
||
|
||
// --- Skills ---
|
||
'skills.title': 'Skills',
|
||
'skills.lead': 'Agent skills available in this project.',
|
||
'skills.close': 'Close',
|
||
'skills.copied': 'Copied',
|
||
'skills.copy': 'Copy path',
|
||
'skills.copyPath': 'Path copied to clipboard',
|
||
'skills.copyPathBtn': 'Copy',
|
||
'skills.couldNotRead': 'Could not read skill',
|
||
'skills.filesIn': 'Files in this skill',
|
||
'skills.hideFiles': 'Hide files',
|
||
'skills.showFiles': 'Show files',
|
||
'skills.howto1': 'Skills add reusable abilities to the agent.',
|
||
'skills.howto2': 'Reference a skill with @name in the composer.',
|
||
'skills.howto3': 'The agent loads it on demand.',
|
||
'skills.howto4': 'Add skills by placing folders under .agents/skills.',
|
||
'skills.howtoTitle': 'How skills work',
|
||
'skills.loadingFile': 'Loading file…',
|
||
'skills.noFiles': 'No files',
|
||
'skills.noSkills': 'No skills available',
|
||
'skills.note': 'Note',
|
||
'skills.refresh': 'Refresh',
|
||
'skills.refreshed': 'Skills refreshed',
|
||
'skills.truncated': 'Preview truncated',
|
||
|
||
// --- Reasoning ---
|
||
'reasoning.title': 'Reasoning',
|
||
'reasoning.thinking': 'Thinking…',
|
||
'reasoning.show': 'Show reasoning',
|
||
|
||
// --- Agent chat/composer ---
|
||
'agentChat.approveRender': 'Approve render',
|
||
'agentChat.approveReplace': 'Approve replace',
|
||
'agentChat.emptyHint': 'The agent is ready. Ask it to draft storylines, edit assets, or build scenes.',
|
||
'agentChat.emptyTitle': 'Start a conversation',
|
||
'agentChat.loading': 'Loading conversation',
|
||
'agentChat.pickOption': 'Pick an option',
|
||
'agentChat.working': 'Agent is working…',
|
||
'agent.task.story': 'Draft Storyline',
|
||
'agent.task.script': 'Regenerate Script',
|
||
'agentComposer.aria': 'Message composer',
|
||
'agentComposer.attach': 'Attach file',
|
||
'agentComposer.attachLimit': 'Attachment limit reached',
|
||
'agentComposer.attachments': 'Attachments',
|
||
'agentComposer.mentionLock': 'Locked to this project',
|
||
'agentComposer.message': 'Message',
|
||
'agentComposer.placeholder': 'Ask the agent or @mention a skill…',
|
||
'agentComposer.remove': 'Remove attachment',
|
||
'agentComposer.sendTitle': 'Send message',
|
||
'agentComposer.stopTitle': 'Stop agent',
|
||
'agentComposer.working': 'Sending…',
|
||
'agentComposer.steer': 'Steer',
|
||
'agentComposer.steerTitle': 'Send a course correction while the agent works',
|
||
'agentComposer.steerPlaceholder': 'Steer the agent while it works…',
|
||
'agentChat.steering': 'Steering',
|
||
'agentPlan.planner': 'Plan',
|
||
'agentPlan.skipped': 'Skipped',
|
||
'agentTool.args': 'Arguments',
|
||
'agentTool.done': 'Done',
|
||
'agentTool.failed': 'Failed',
|
||
'agentTool.result': 'Result',
|
||
'agentTool.running': 'Running…',
|
||
'mentionMenu.noSkill': 'No matching skill',
|
||
'mentionMenu.noWorkflow': 'No matching workflow',
|
||
'mentionMenu.skills': 'Skills',
|
||
'mentionMenu.workflows': 'Workflows',
|
||
|
||
// --- Agent session sidebar ---
|
||
'sessionSidebar.collapse': 'Collapse sidebar',
|
||
'sessionSidebar.expand': 'Expand sidebar',
|
||
'sessionSidebar.deleteSession': 'Delete session',
|
||
'sessionSidebar.newProjectChat': 'New project chat',
|
||
'sessionSidebar.newSandbox': 'New sandbox',
|
||
'sessionSidebar.newSandboxButton': 'New sandbox session',
|
||
'sessionSidebar.noSessions': 'No sessions yet',
|
||
'sessionSidebar.open': 'Open session',
|
||
'sessionSidebar.projectFallback': 'Project chat',
|
||
'sessionSidebar.sandbox': 'Sandbox',
|
||
|
||
// --- Story stage ---
|
||
'story.stageTitle': 'Story',
|
||
'story.ideaTitle': 'Story idea',
|
||
'story.ideaPlaceholder': 'Describe the story you want to tell…',
|
||
'story.targetLength': 'Target length',
|
||
'story.lengthsHint': 'How long should the finished video feel?',
|
||
'story.lengthHint': 'Guides beat and scene counts.',
|
||
'story.draftStoryline': 'Draft storyline',
|
||
'story.draftPromptTitle': 'Draft prompt',
|
||
'story.promptExplain': 'The finished brief the agent uses to structure the story.',
|
||
'story.showPrompt': 'Show prompt',
|
||
'story.hidePrompt': 'Hide prompt',
|
||
'story.promptCollapsedHint': 'Edit the draft prompt before generating beats.',
|
||
'story.addBeat': 'Add beat',
|
||
'story.addBeatManual': 'Add beat manually',
|
||
'story.addBeatFailed': 'Could not add beat',
|
||
'story.beatAdded': 'Beat added',
|
||
'story.beatDeleted': 'Beat deleted',
|
||
'story.beatSaved': 'Beat saved',
|
||
'story.deleteBeat': 'Delete beat',
|
||
'story.deleteBeatFailed': 'Could not delete beat',
|
||
'story.beats': 'Beats',
|
||
'story.editBeatTitle': 'Edit beat',
|
||
'story.editCharTitle': 'Edit character',
|
||
'story.editLocTitle': 'Edit location',
|
||
'story.editItemTitle': 'Edit item',
|
||
'story.fieldAge': 'Age',
|
||
'story.fieldAppearance': 'Appearance',
|
||
'story.fieldConsistency': 'Consistency',
|
||
'story.fieldDescription': 'Description',
|
||
'story.fieldName': 'Name',
|
||
'story.fieldPersonality': 'Personality',
|
||
'story.fieldRole': 'Role',
|
||
'story.fieldTitle': 'Heading',
|
||
'story.noBeats': 'No beats yet',
|
||
'story.noBeatsBody': 'Add beats manually or let the agent draft a storyline.',
|
||
'story.continueAssets': 'Continue to assets',
|
||
'story.confirmDeleteBeatMsg': 'This beat will be permanently deleted. Continue?',
|
||
'story.confirmDeleteBeatTitle': 'Delete beat?',
|
||
'story.confirmExampleMsg': 'This replaces your current story idea with the example.',
|
||
'story.confirmExampleTitle': 'Load example?',
|
||
'story.exampleLoaded': 'Example loaded',
|
||
'story.extracted': 'Extracted from story',
|
||
'story.charTag': 'CHARACTER',
|
||
'story.envTag': 'LOCATION',
|
||
'story.itemTag': 'ITEM',
|
||
'story.beatsTitle': 'Story beats',
|
||
'story.characterSaved': 'Character saved',
|
||
'story.locationSaved': 'Location saved',
|
||
'story.itemSaved': 'Item saved',
|
||
'story.openAssets': 'Open assets',
|
||
'story.loadExample': 'Load example',
|
||
'story.saveBeatFailed': 'Could not save beat',
|
||
'story.saveCharacterFailed': 'Could not save character',
|
||
'story.saveItemFailed': 'Could not save item',
|
||
'story.saveLocationFailed': 'Could not save location',
|
||
'story.saveSettingsFailed': 'Could not save settings',
|
||
'story.settingsTitle': 'Story settings',
|
||
'story.llmBanner': 'The story stage uses the active LLM to draft and refine beats.',
|
||
'story.newBeat': 'New beat {n}',
|
||
|
||
// --- Assets stage ---
|
||
'assets.title': 'Assets',
|
||
'assets.lead': 'Characters, locations and items generated for your story.',
|
||
'assets.tabCharacters': 'Characters',
|
||
'assets.tabEnvironments': 'Locations',
|
||
'assets.tabItems': 'Items',
|
||
'assets.tabAria': 'Asset type tabs',
|
||
'assets.kind.character': 'Character',
|
||
'assets.kind.environment': 'Location',
|
||
'assets.kind.item': 'Item',
|
||
'assets.charSheets': 'Character sheets',
|
||
'assets.envRefs': 'Location references',
|
||
'assets.itemRefs': 'Item references',
|
||
'assets.charSheetPlaceholder': 'Reference sheet',
|
||
'assets.optionEnvironment': 'Location reference',
|
||
'assets.optionItem': 'Item reference',
|
||
'assets.optionSheet': 'Character sheet',
|
||
'assets.generateImage': 'Generate image',
|
||
'assets.generateSheet': 'Generate sheet',
|
||
'assets.replaceImage': 'Replace image',
|
||
'assets.regenImage': 'Regenerate image',
|
||
'assets.regenSheet': 'Regenerate sheet',
|
||
'assets.regenImageFor': 'Regenerate image for “{name}”',
|
||
'assets.regenSheetFor': 'Regenerate sheet for “{name}”',
|
||
'assets.generating': 'Generating…',
|
||
'assets.generatingEllipsis': 'Generating',
|
||
'assets.queuing': 'Queuing…',
|
||
'assets.generateMissing': 'Generate missing',
|
||
'assets.generateMissingTitle': 'Generate missing assets',
|
||
'assets.editPrompt': 'Edit prompt',
|
||
'assets.savePrompt': 'Save prompt',
|
||
'assets.resetSheetTemplate': 'Reset sheet template',
|
||
'assets.resetEnvTemplate': 'Reset location template',
|
||
'assets.resetItemTemplate': 'Reset item template',
|
||
'assets.noCharsTitle': 'No characters yet',
|
||
'assets.noCharsBody': 'Characters appear here once the story defines them.',
|
||
'assets.noEnvsTitle': 'No locations yet',
|
||
'assets.noEnvsBody': 'Locations appear here once the story defines them.',
|
||
'assets.noItemsTitle': 'No items yet',
|
||
'assets.noItemsBody': 'Items appear here once the story defines them.',
|
||
'assets.confirmDeleteTitle': 'Delete asset',
|
||
'assets.confirmDeleteLabel': 'Delete',
|
||
'assets.confirmDeleteBody': 'This asset and its generated images will be deleted. Continue?',
|
||
'assets.confirmDeleteFallback': 'Delete this asset?',
|
||
'assets.deleteCharacter': 'Delete character',
|
||
'assets.deleteEnvironment': 'Delete location',
|
||
'assets.deleteItem': 'Delete item',
|
||
'assets.deleteFor': 'Delete “{name}”',
|
||
'assets.description': 'Description',
|
||
'assets.appearance': 'Appearance',
|
||
'assets.personality': 'Personality',
|
||
'assets.cover': 'Cover',
|
||
'assets.removeCover': 'Remove cover',
|
||
'assets.removeCoverChar': 'Remove character cover',
|
||
'assets.removeCoverRef': 'Remove reference cover',
|
||
'assets.setCover': 'Set as cover',
|
||
'assets.setCoverChar': 'Set as character cover',
|
||
'assets.setCoverRef': 'Set as reference cover',
|
||
'assets.refPlaceholder': 'Reference',
|
||
'assets.sentToComfy': 'Sent to ComfyUI',
|
||
'assets.uploadImage': 'Upload image',
|
||
'assets.viewCharFull': 'View character full',
|
||
'assets.viewRefFull': 'View reference full',
|
||
'assets.viewFull': 'View full size',
|
||
'assets.charSheetAlt': 'Character sheet for {name}',
|
||
'assets.goToStory': 'Go to Story',
|
||
'assets.genSettings': 'Generation settings',
|
||
'assets.toast.addImageFailed': 'Could not add image',
|
||
'assets.toast.chooseImage': 'Choose an image',
|
||
'assets.toast.coverFail': 'Could not set cover',
|
||
'assets.toast.coverRemoved': 'Cover removed',
|
||
'assets.toast.coverUpdated': 'Cover updated',
|
||
'assets.toast.deleted': 'Asset deleted',
|
||
'assets.toast.deleteFailed': 'Could not delete asset',
|
||
'assets.toast.imageAdded': 'Image added',
|
||
'assets.toast.jobRequeued': 'Requested again',
|
||
'assets.toast.nothingMissing': 'Nothing is missing',
|
||
'assets.toast.notImage': 'That file is not an image',
|
||
'assets.toast.queued': 'Image queued',
|
||
'assets.toast.queuedMany': '{n} images queued',
|
||
'assets.toast.queuedOne': 'Image queued',
|
||
'assets.toast.retryFailed': 'Could not retry',
|
||
'assets.toast.savedPrompt': 'Prompt saved',
|
||
'assets.toast.savePromptFailed': 'Could not save prompt',
|
||
'assets.wf.sheet': 'Character sheet workflow',
|
||
'assets.wf.environment': 'Location reference workflow',
|
||
'assets.wf.item': 'Item reference workflow',
|
||
'assets.wf.selectSheet': 'Select a sheet workflow',
|
||
'assets.wf.selectEnv': 'Select a location workflow',
|
||
'assets.wf.selectItem': 'Select an item workflow',
|
||
'assets.wf.needWorkflow': 'Set up a workflow on the Settings page first.',
|
||
'assets.wf.missingInputs': 'This workflow is missing required inputs.',
|
||
'assets.wf.none': 'No workflow selected',
|
||
'assets.wf.noPromptPre': 'This workflow has no prompt input.',
|
||
'assets.wf.noPromptPost': 'Add a prompt field to use it here.',
|
||
'assets.noWorkflowPre': 'Generation needs a workflow.',
|
||
'assets.noWorkflowPost': 'Configure one in Settings.',
|
||
'assets.noWorkflowLink': 'Open Settings',
|
||
|
||
// --- Build scene ---
|
||
'buildScene.title': 'Build Scene',
|
||
'buildScene.builderBadge': '3D Builder',
|
||
'buildScene.preparing': 'Preparing scene…',
|
||
'buildScene.stillLoading': 'Scene still loading…',
|
||
'buildScene.expandChat': 'Expand chat',
|
||
'buildScene.collapseChat': 'Collapse chat',
|
||
'buildScene.videoExported': 'Video exported',
|
||
'buildScene.legacyNeedsViewport': 'Viewport not ready for export',
|
||
'buildScene.videoExportFailed': 'Video export failed',
|
||
'buildScene.captureSaved': 'Capture saved',
|
||
'buildScene.createSceneFailed': 'Could not create scene',
|
||
'buildScene.deleteSceneFailed': 'Could not delete scene',
|
||
'buildScene.sendFailed': 'Could not send message',
|
||
'buildScene.runCancelled': 'Run cancelled',
|
||
'buildScene.cancelFailed': 'Could not cancel',
|
||
'buildScene.openCompositionFailed': 'Could not open composition',
|
||
'buildScene.uploadSizeFail': 'File too large',
|
||
|
||
// --- Script stage ---
|
||
'script.actionField': 'Action',
|
||
'script.actionPlaceholder': 'What happens in this scene…',
|
||
'script.dialogField': 'Dialogue',
|
||
'script.dialogPlaceholder': 'Who says what…',
|
||
'script.headingField': 'Heading',
|
||
'script.headingPlaceholder': 'INT. HARBOR — NIGHT',
|
||
'script.sceneNumber': 'Scene {n}',
|
||
'script.edit': 'Edit scene',
|
||
'script.editScene': 'Edit scene',
|
||
'script.editSceneNumbered': 'Edit scene {n}',
|
||
'script.durationField': 'Duration',
|
||
'script.addScene': 'Add scene',
|
||
'script.deleteSceneTitle': 'Delete scene',
|
||
'script.deleteSceneMessage': 'This scene and its shots will be deleted. Continue?',
|
||
'script.delete': 'Delete scene',
|
||
'script.loadingScenes': 'Loading scenes',
|
||
'script.noScenesTitle': 'No scenes yet',
|
||
'script.noScenesBody': 'Break your story into scenes to start filming.',
|
||
'script.regenerate': 'Regenerate script',
|
||
'script.break': 'Break into shots',
|
||
'script.breakTitle': 'Break scene into shots',
|
||
'script.rebreak': 'Rebreak shots',
|
||
'script.rebreakTitle': 'Rebreak shots for this scene',
|
||
'script.breakAllIntoShots': 'Break all into shots',
|
||
'script.breakAllTitle': 'Break every scene into shots',
|
||
'script.chainOn': 'Chain clips',
|
||
'script.chainOff': 'Unchain clips',
|
||
'script.chainTitle': 'Toggle clip chaining',
|
||
'script.save': 'Save',
|
||
'script.untitledScene': 'Untitled scene',
|
||
'script.untitledShot': 'Untitled shot',
|
||
'script.justAdded': 'Added',
|
||
'script.rendering': 'Rendering…',
|
||
'script.renderedCount': '{n} clips rendered',
|
||
'script.clipDone': 'Clip done',
|
||
'script.noActionYet': 'No action written yet',
|
||
'script.shotClipSingular': '1 clip',
|
||
'script.shotClipPlural': '{n} clips',
|
||
'script.moveSceneUp': 'Move scene up',
|
||
'script.moveSceneDown': 'Move scene down',
|
||
'script.deleteShotAria': 'Delete shot',
|
||
'script.deleteShotTitle': 'Delete shot',
|
||
'script.status.rendering': 'Rendering',
|
||
'script.status.renderFailed': 'Failed',
|
||
'script.status.clipReady': 'Ready',
|
||
'script.status.noClip': 'No clip',
|
||
'script.toast.addSceneFail': 'Could not add scene',
|
||
'script.toast.boardExpanded': 'Scene opened on the board',
|
||
'script.toast.breakAllConfirm': 'Break all scenes into shots?',
|
||
'script.toast.breakAllFail': 'Could not break scenes',
|
||
'script.toast.breakFail': 'Could not break scene',
|
||
'script.toast.breakIntoShots': 'Scene broken into shots',
|
||
'script.toast.deleteClipFail': 'Could not delete clip',
|
||
'script.toast.deleted': 'Scene deleted',
|
||
'script.toast.deletedShot': 'Shot deleted',
|
||
'script.toast.deleteFailed': 'Could not delete',
|
||
'script.toast.saveSceneFail': 'Could not save scene',
|
||
'script.toast.sceneAdded': 'Scene added',
|
||
'script.toast.sceneSaved': 'Scene saved',
|
||
'script.toast.updateSceneFail': 'Could not update scene',
|
||
|
||
// --- Script drawer ---
|
||
'scriptDrawer.script': 'Script',
|
||
'scriptDrawer.heading': 'Heading',
|
||
'scriptDrawer.action': 'Action',
|
||
'scriptDrawer.dialog': 'Dialogue',
|
||
'scriptDrawer.characters': 'Characters',
|
||
'scriptDrawer.noAction': 'No action written',
|
||
'scriptDrawer.noDialog': 'No dialogue',
|
||
'scriptDrawer.regionAria': 'Script region',
|
||
'scriptDrawer.untitled': 'Untitled',
|
||
'scriptDrawer.untitledScene': 'Untitled scene',
|
||
|
||
// --- Queue stage ---
|
||
'queue.sceneLabel': 'Scene',
|
||
'queue.clipLabel': 'Clip #{n}',
|
||
'queue.jobLabel': 'Job #{n}',
|
||
'queue.scene': 'Scene {n}',
|
||
'queue.sceneRef': 'Scene reference',
|
||
'queue.clipRef': 'Clip reference',
|
||
'queue.clipQueued': 'Clip queued',
|
||
'queue.clipsDoneSummary': '{done}/{total} clips done',
|
||
'queue.clipsMissing': 'Some shots have no clip yet',
|
||
'queue.clipRenderUpdated': 'Clip render updated',
|
||
'queue.clipsChanged': 'Clips changed',
|
||
'queue.blockoutLabel': 'Blockout',
|
||
'queue.blockoutSuffix': 'blockout',
|
||
'queue.blockoutClipSuffix': 'blockout clip',
|
||
'queue.uploadSuffix': 'upload',
|
||
'queue.generateAllTitle': 'Generate all clips',
|
||
'queue.generateMissing': 'Generate missing',
|
||
'queue.regenerateAll': 'Regenerate all',
|
||
'queue.queueingProgress': 'Queued {n}/{total} jobs',
|
||
'queue.queued': 'Queued',
|
||
'queue.queuedInSequence': 'Will run in sequence',
|
||
'queue.pauseQueue': 'Pause queue',
|
||
'queue.resumeQueue': 'Resume queue',
|
||
'queue.paused': 'Queue paused',
|
||
'queue.pausedText': 'New jobs wait until you resume.',
|
||
'queue.resumeNow': 'Resume now',
|
||
'queue.editTab': 'Scenes',
|
||
'queue.filmTab': 'Film',
|
||
'queue.filmViewAria': 'Film view',
|
||
'queue.viewAria': 'Queue view',
|
||
'queue.emptyHeader': 'Nothing queued yet',
|
||
'queue.noTimeline': 'No timeline yet',
|
||
'queue.noTimelineBody': 'Generate clips first, then export the film.',
|
||
'queue.savedDrafts': 'Drafts saved here',
|
||
'queue.exportFilm': 'Export film',
|
||
'queue.downloadFilm': 'Download film',
|
||
'queue.exporting': 'Exporting…',
|
||
'queue.exportingTitle': 'Exporting film',
|
||
'queue.exportingSub': 'Combining {n} clips into a single video.',
|
||
'queue.exportQueued': 'Export queued',
|
||
'queue.exportedAgo': 'Exported {ago}',
|
||
'queue.exportFailed': 'Export failed',
|
||
'queue.retryExport': 'Retry export',
|
||
'queue.exportUnavailable': 'Export not available yet',
|
||
'queue.notExported': 'Not exported',
|
||
'queue.notExportedTitle': 'No export yet',
|
||
'queue.slateSub': '{clips} clips · {time} · 0.5s crossfades · loudness matched',
|
||
'queue.staleBanner': 'Clips changed since export',
|
||
'queue.exportDisabledTitle': 'Add at least one clip to export',
|
||
'queue.chainDisabledReason': 'Select a scene or clip first',
|
||
'queue.editInTimeline': 'Edit in timeline',
|
||
'queue.inThisFilm': 'In this film',
|
||
'queue.filmMeta': '{scenes} scenes · {clips} clips · {duration}',
|
||
'queue.reexport': 'Re-export',
|
||
|
||
// --- Job / job drawer ---
|
||
'job.title': 'Job',
|
||
'job.status.generating': 'Generating',
|
||
'job.status.generatingPulse': 'Generating',
|
||
'job.status.queued': 'Queued',
|
||
'job.status.running': 'Running',
|
||
'job.status.done': 'Done',
|
||
'job.status.failed': 'Failed',
|
||
'job.cancelJob': 'Cancel job',
|
||
'job.cancelFailed': 'Could not cancel job',
|
||
'job.cancelled': 'Cancelled',
|
||
'job.requeued': 'Requeued',
|
||
'job.retryJob': 'Retry job',
|
||
'job.retryFailed': 'Could not retry job',
|
||
'job.exportFilm': 'Export film',
|
||
'jobDrawer.title': 'Job details',
|
||
'jobDrawer.historyAria': 'Job history',
|
||
'jobDrawer.noJobs': 'No jobs yet',
|
||
'jobDrawer.noPrompt': 'No prompt for this job',
|
||
'jobDrawer.output': 'Output',
|
||
'jobDrawer.prompt': 'Prompt',
|
||
'jobDrawer.references': 'References',
|
||
'jobDrawer.characterRef': 'Character reference',
|
||
'jobDrawer.locationRef': 'Location reference',
|
||
'jobDrawer.audioInput': 'Audio input',
|
||
'jobDrawer.videoInput': 'Video input',
|
||
'jobDrawer.refImage': 'Reference image',
|
||
'jobDrawer.currentClip': 'Current clip',
|
||
'jobDrawer.otherInputs': 'Other inputs',
|
||
'jobDrawer.copy': 'Copy',
|
||
'jobDrawer.copied': 'Copied',
|
||
'jobDrawer.copySettings': 'Copy settings',
|
||
'jobDrawer.applying': 'Applying…',
|
||
'jobDrawer.applyToScene': 'Apply to scene',
|
||
'jobDrawer.h3Hint': 'The selection above was used for this job.',
|
||
|
||
// --- Filmstrip ---
|
||
'filmstrip.title': 'Filmstrip',
|
||
'filmstrip.clipTitle': '{scene} · shot {shot} · {time}',
|
||
'filmstrip.scene': 'Scene',
|
||
'filmstrip.sceneClips': '{n} clips',
|
||
'filmstrip.prev': 'Previous clip',
|
||
'filmstrip.next': 'Next clip',
|
||
|
||
// --- Clip monitor / clip source ---
|
||
'clipMonitor.untitled': 'Untitled clip',
|
||
'clipMonitor.id': 'Clip ID',
|
||
'clipMonitor.sceneId': 'Scene ID',
|
||
'clipMonitor.generating': 'Generating…',
|
||
'clipMonitor.generationFailed': 'Generation failed',
|
||
'clipMonitor.queued': 'Queued',
|
||
'clipMonitor.noRenderHint': 'This clip has no render yet.',
|
||
'clipMonitor.downloadClip': 'Download clip',
|
||
'clipMonitor.videoUnavailable': 'Video unavailable',
|
||
'clipMonitor.showDetails': 'Show details',
|
||
'clipMonitor.hideDetails': 'Hide details',
|
||
'clipSource.title': 'Clip source',
|
||
'clipSource.projectClips': 'Project clips',
|
||
'clipSource.noClips': 'No clips available',
|
||
'clipSource.autoName': 'Auto',
|
||
'clipSource.autoDesc': 'Auto label',
|
||
'clipSource.uploadName': 'Upload',
|
||
'clipSource.uploadDesc': 'Upload a file',
|
||
|
||
// --- Video edit workspace ---
|
||
'videoEdit.clipId': 'Clip ID',
|
||
'videoEdit.sceneId': 'Scene ID',
|
||
'videoEdit.generateLabel': 'Generate',
|
||
'videoEdit.videoSource': 'Video source',
|
||
'videoEdit.noVideoInputWf': 'This workflow has no video input',
|
||
'videoEdit.noWf': 'No workflow selected',
|
||
'videoEdit.wfLink': 'Configure workflows in Settings',
|
||
'videoEdit.enableWfPre': 'Render with the active workflow?',
|
||
'videoEdit.enableWfPost': 'It determines output format.',
|
||
'videoEdit.assetHint': 'Pick the generation target',
|
||
'videoEdit.continueHint': 'Continue with the selected workflow',
|
||
'videoEdit.viewPrompt': 'View prompt',
|
||
'videoEdit.dockAria': 'Clip generation inputs',
|
||
|
||
// --- Shot brief ---
|
||
'shotBrief.copyTitle': 'Copy shot description',
|
||
'shotBrief.copied': 'Copied',
|
||
'shotBrief.copy': 'Copy',
|
||
'shotBrief.collapse': 'Collapse shot brief',
|
||
'shotBrief.expand': 'Expand shot brief',
|
||
'shotBrief.noDesc': 'No shot description — this clip inherited the scene defaults.',
|
||
'shotBrief.notePre': 'This clip has no per-shot description yet — the text above is the full scene action. Use',
|
||
'shotBrief.breakIntoShots': 'Break into shots',
|
||
'shotBrief.notePost': 'in the Script stage to split it into coverage.',
|
||
'shotBrief.dialogKey': 'Dialog in this shot',
|
||
'shotBrief.characters': 'Characters',
|
||
|
||
// --- Prompt preview modal ---
|
||
'promptPreview.title': 'Prompt preview',
|
||
'promptPreview.generate': 'Generate',
|
||
'promptPreview.regenerate': 'Regenerate',
|
||
'promptPreview.resolving': 'Resolving prompt…',
|
||
'promptPreview.saveDraft': 'Save draft',
|
||
'promptPreview.draftSaved': 'Draft saved',
|
||
'promptPreview.promptEmpty': 'Nothing to preview yet',
|
||
'promptPreview.noClip': 'No clip',
|
||
'promptPreview.noClipSelected': 'No clip selected',
|
||
'promptPreview.untitled': 'Untitled',
|
||
'promptPreview.failedHint': 'Prompt resolution failed — showing a fallback instead.',
|
||
'promptPreview.staleHint': 'Resolution is stale — resend to get the current prompt.',
|
||
'promptPreview.fromDraftHint': 'Based on your draft, not the current workflow.',
|
||
'promptPreview.proseHint': 'Editable prose prompt — changes stay local.',
|
||
'promptPreview.h3Hint': 'Prompt built from the selection above.',
|
||
'promptPreview.criticTitle': 'Continuity check',
|
||
'promptPreview.h3Rewrite': 'Rewritten',
|
||
'promptPreview.editorAria': 'Prompt editor',
|
||
'promptPreview.defaultWorkflow': 'default',
|
||
'promptPreview.sceneMeta': 'Scene #{index} · {heading}',
|
||
'promptPreview.shotMeta': 'Shot {label} · {heading}',
|
||
|
||
// --- Workflows (wf) ---
|
||
'wf.title': 'Workflows',
|
||
'wf.lead': 'Upload and register ComfyUI workflows for generation.',
|
||
'wf.loadingWorkflows': 'Loading workflows',
|
||
'wf.noWorkflows': 'No workflows registered',
|
||
'wf.noWorkflowsHint': 'Drop a workflow JSON below to get started.',
|
||
'wf.detectedInputs': 'Detected inputs',
|
||
'wf.detectedOutputs': 'Detected outputs',
|
||
'wf.inputs': 'Inputs',
|
||
'wf.outputs': 'Outputs',
|
||
'wf.inputsCount': '{n} inputs',
|
||
'wf.outputsCount': '{n} outputs',
|
||
'wf.kind': 'Type',
|
||
'wf.kindImage': 'Image',
|
||
'wf.kindVideo': 'Video',
|
||
'wf.enable': 'Enable',
|
||
'wf.disable': 'Disable',
|
||
'wf.disabled': 'Disabled',
|
||
'wf.stateEnabled': 'Enabled',
|
||
'wf.stateDisabled': 'Disabled',
|
||
'wf.enabledState': 'Enabled',
|
||
'wf.hideIo': 'Hide inputs/outputs',
|
||
'wf.viewIo': 'Show inputs/outputs',
|
||
'wf.dropHint': 'Drop workflow JSON here',
|
||
'wf.dropSub': 'or click to browse',
|
||
'wf.namePlaceholder': 'Workflow name',
|
||
'wf.descPlaceholder': 'Short description (optional)',
|
||
'wf.invalidJson': 'This file is not valid workflow JSON',
|
||
'wf.jsonLocked': 'Frozen by an active job',
|
||
'wf.jsonPreview': 'Workflow JSON',
|
||
'wf.reanalyze': 'Re-analyze',
|
||
'wf.saveToLibrary': 'Save to library',
|
||
'wf.savedWorkflows': 'Saved workflows',
|
||
'wf.savedToLibrary': 'Saved to library',
|
||
'wf.saveFailed': 'Could not save workflow',
|
||
'wf.updateFailed': 'Could not update workflow',
|
||
'wf.updated': 'Workflow updated',
|
||
'wf.deleted': 'Workflow deleted',
|
||
'wf.deleteFailed': 'Could not delete workflow',
|
||
'wf.deleteTitle': 'Delete workflow',
|
||
'wf.deleteMessage': 'This workflow and its saved JSON will be deleted.',
|
||
'wf.analyzeRegister': 'Analyze & register',
|
||
'wf.countImage': '{n} images',
|
||
'wf.countVideo': '{n} videos',
|
||
'wf.countSaved': '{n} saved',
|
||
'wf.profileH3': 'Use case',
|
||
'wf.profileProse': 'This workflow generates {kind} from a {target}.',
|
||
'wf.promptFormat': 'Prompt format',
|
||
'wf.noInputs': 'No inputs detected',
|
||
'wf.noInputsCached': 'No inputs',
|
||
'wf.noOutputs': 'No outputs detected',
|
||
'wf.noOutputsCached': 'No outputs',
|
||
|
||
// --- Comfy dynamic form (cdf) ---
|
||
'cdf.browse': 'Browse',
|
||
'cdf.chooseAsset': 'Choose asset',
|
||
'cdf.clear': 'Clear',
|
||
'cdf.clearAria': 'Clear field',
|
||
'cdf.dropPre': 'Drop a file',
|
||
'cdf.localPath': 'Local path',
|
||
'cdf.noAssets': 'No assets yet',
|
||
'cdf.noInputs': 'No configurable inputs',
|
||
'cdf.orChooseAsset': 'or choose an asset',
|
||
'cdf.required': 'required',
|
||
'cdf.requiredMsg': 'This field is required',
|
||
'cdf.selectedPreviewAlt': 'Selected preview',
|
||
'cdf.uploadedPreviewAlt': 'Uploaded preview',
|
||
'cdf.uploadFailed': 'Upload failed',
|
||
'cdf.uploading': 'Uploading…',
|
||
|
||
// --- Omni composer ---
|
||
'omni.advanced': 'Advanced',
|
||
'omni.assetType': 'Asset type',
|
||
'omni.choose': 'Choose',
|
||
'omni.chooseReference': 'Choose reference',
|
||
'omni.clearSlot': 'Clear slot',
|
||
'omni.decrease': 'Decrease',
|
||
'omni.increase': 'Increase',
|
||
'omni.duration': 'Duration',
|
||
'omni.resolution': 'Resolution',
|
||
'omni.seed': 'Seed',
|
||
'omni.emptyCharacters': 'No characters yet',
|
||
'omni.emptyLocations': 'No locations yet',
|
||
'omni.emptyItems': 'No items yet',
|
||
'omni.emptyShots': 'No shots yet',
|
||
'omni.emptyClips': 'No clips yet',
|
||
'omni.emptyUploads': 'No uploads yet',
|
||
'omni.emptyUploadsNew': 'No uploads yet',
|
||
'omni.generate': 'Generate',
|
||
'omni.generateAria': 'Generate',
|
||
'omni.negativeAria': 'Negative prompt',
|
||
'omni.negativePlaceholder': 'Negative prompt…',
|
||
'omni.negativeToggle': 'Negative prompt',
|
||
'omni.noMatches': 'No matches',
|
||
'omni.noPromptRole': 'This workflow has no prompt input',
|
||
'omni.promptAria': 'Prompt',
|
||
'omni.promptPlaceholder': 'Describe the image…',
|
||
'omni.queuing': 'Queuing…',
|
||
'omni.removeSlot': 'Remove',
|
||
'omni.required': 'Required',
|
||
'omni.roleAudio': 'Audio',
|
||
'omni.roleCharacter': 'Character',
|
||
'omni.roleLocation': 'Location',
|
||
'omni.roleVideo': 'Video',
|
||
'omni.searchAssets': 'Search assets',
|
||
'omni.searchIn': 'Search in',
|
||
'omni.thisList': 'this list',
|
||
'omni.uploadNew': 'Upload new',
|
||
|
||
// --- Attach to project dialog ---
|
||
'attach.panelAria': 'Attach to project',
|
||
'attach.title': 'Attach to project',
|
||
'attach.addToProject': 'Add to project',
|
||
'attach.noScenes': 'No scenes yet',
|
||
'attach.noCharacters': 'No characters yet',
|
||
'attach.noLocations': 'No locations yet',
|
||
'attach.pickProject': 'Pick a project',
|
||
'attach.selectProject': 'Select project',
|
||
'attach.selectScene': 'Select scene',
|
||
'attach.selectCharacter': 'Select character',
|
||
'attach.selectLocation': 'Select location',
|
||
'attach.pickCharacter': 'Pick a character',
|
||
'attach.pickLocation': 'Pick a location',
|
||
'attach.pickScene': 'Pick a scene',
|
||
'attach.projectField': 'Project',
|
||
'attach.sceneField': 'Scene',
|
||
'attach.characterField': 'Character',
|
||
'attach.locationField': 'Location',
|
||
'attach.nameField': 'Name',
|
||
'attach.asCharacterSheet': 'as character sheet',
|
||
'attach.asItem': 'as item',
|
||
'attach.asLocation': 'as location',
|
||
'attach.addAs': 'Add as',
|
||
'attach.addBtn': 'Add',
|
||
'attach.added': 'Attached',
|
||
'attach.addedTo': 'Added to “{title}”',
|
||
'attach.failed': 'Could not attach',
|
||
'attach.dismiss': 'Dismiss',
|
||
'attach.viewInProject': 'View in project',
|
||
'attach.newItem': 'New item',
|
||
'attach.newItemHint': 'Create an item from this media.',
|
||
'attach.newItemPlaceholder': 'Item name',
|
||
'attach.projectFallback': 'Untitled project',
|
||
'attach.scene': 'Scene',
|
||
|
||
// --- Asset Library ---
|
||
'library.selectAll': 'Select all',
|
||
'library.deselectAll': 'Deselect all',
|
||
'library.itemCount': '{count} item(s)',
|
||
'library.loadError': 'Failed to load the library',
|
||
'library.subtitle': 'Generated assets in one place — preview, filter and remove images and videos not tied to a project',
|
||
'library.deleteSelected': 'Delete ({count})',
|
||
'library.addToProject': 'Add to Project',
|
||
'library.filterLabel': 'Filter by kind',
|
||
'library.filterAll': 'All',
|
||
'library.filterImage': 'Images',
|
||
'library.filterVideo': 'Videos',
|
||
'library.loadMore': 'Load more ({count} remaining)',
|
||
'library.loadingMore': 'Loading…',
|
||
'library.confirmDelete': 'Delete {count} selected file(s) from the Asset Library? This cannot be undone.',
|
||
'library.deleted': 'Deleted {count} file(s)',
|
||
'library.deletedPartial': '{kept} file(s) kept — still referenced by project data',
|
||
'library.deleteFailed': 'Could not delete',
|
||
'library.emptyTitle': 'Nothing in the Asset Library',
|
||
'library.emptyBody': 'Images and videos that are not linked to a project land here — upload on a canvas or generate in a sandbox chat.',
|
||
'library.emptyFilterTitle': 'No {kind} in the library',
|
||
'library.emptyFilterBody': 'Nothing matches this filter yet — try All or generate something new.',
|
||
|
||
// --- Settings ---
|
||
'settings.pageSub': 'Generation queue, agent runtime and storage paths · LLMs, ComfyUI connections and Skills live on their own pages',
|
||
'settings.secQueue': 'Queue & generation',
|
||
'settings.secQueueBlurb': 'Concurrency, retries, polling and dry run',
|
||
'settings.secAgent': 'Agent runtime',
|
||
'settings.secAgentBlurb': 'Steps, context, prompt hardening and shell',
|
||
'settings.secStorage': 'Storage paths',
|
||
'settings.secStorageBlurb': 'Data, assets and agent workspace folders',
|
||
'settings.elsewhere': 'Managed elsewhere',
|
||
'settings.linkModelsBlurb': 'LLMs and default model per agent',
|
||
'settings.linkConnectionsBlurb': 'Addresses, connection tests and workflow library',
|
||
'settings.linkAgentsBlurb': 'Skills and standalone chats for the five agents',
|
||
'settings.dryRunTitle': 'Dry-run mode',
|
||
'settings.dryRunHint': 'When on, ComfyUI is not called and jobs return placeholder images / videos so you can walk the flow; turn off for real generation.',
|
||
'settings.agentRunSection': 'Agent runtime',
|
||
'settings.agentRunLead': 'Caps tool-call steps per run and how much history is carried along.',
|
||
'settings.rangeHint': 'Range {min}–{max}',
|
||
'settings.loadFailed': 'Could not load settings — check that the workbench server is running',
|
||
'skillName.character-consistency': 'Character consistency',
|
||
'skillName.h3-video-prompt-enhancer': 'H3 video prompt enhancer',
|
||
'skillName.scene-to-video': 'Scene to video',
|
||
'skillName.shot-composer-blockout': 'Shot blockout',
|
||
'settings.loading': 'Loading settings',
|
||
'settings.allSaved': 'All changes saved',
|
||
'settings.unsaved': 'Unsaved changes',
|
||
'settings.saveChanges': 'Save changes',
|
||
'settings.discard': 'Discard',
|
||
'settings.saved': 'Saved',
|
||
'settings.saveFailed': 'Could not save settings',
|
||
'settings.savedDryRun': 'Dry run saved',
|
||
'settings.current': 'Current',
|
||
'settings.useThis': 'Use this',
|
||
'settings.useActiveLlm': 'Currently active',
|
||
'settings.llmSection': 'LLMs',
|
||
'settings.llmLead': 'Configure the language models used by the agent.',
|
||
'settings.addLlm': 'Add LLM',
|
||
'settings.addAtLeastOneLlm': 'Add at least one LLM.',
|
||
'settings.llmNamePlaceholder': 'My LLM',
|
||
'settings.llmDefaultName': 'Generic model',
|
||
'settings.newLlmDefault': 'New LLM',
|
||
'settings.model': 'Model',
|
||
'settings.baseUrl': 'Base URL',
|
||
'settings.apiKey': 'API key',
|
||
'settings.apiKeyOptional': 'Optional',
|
||
'settings.apiKeyHint': 'Some providers accept no key.',
|
||
'settings.apiKeySaved': 'Key saved',
|
||
'settings.requiredName': 'Name is required',
|
||
'settings.requiredModel': 'Model is required',
|
||
'settings.requiredBaseUrl': 'Base URL is required',
|
||
'settings.invalidValue': 'Invalid value',
|
||
'settings.invalidField': 'Invalid',
|
||
'settings.remove': 'Remove',
|
||
'settings.removeLlmTitle': 'Remove LLM',
|
||
'settings.name': 'Name',
|
||
'settings.active': 'Active',
|
||
'settings.testLlm': 'Test connection',
|
||
'settings.llmTestOk': 'Connected ({ms} ms)',
|
||
'settings.llmTestFail': 'Connection failed: {detail}',
|
||
'settings.llmTestAuth': 'API key rejected ({detail})',
|
||
'settings.llmTestTimeout': 'No response within 15 s',
|
||
'settings.llmTestConnect': 'Could not reach the server ({detail})',
|
||
'settings.agentModelsSection': 'Agent model',
|
||
'settings.agentModelsLead': 'Model used for story drafting and agent tasks.',
|
||
'settings.agentMaxStepsField': 'Max steps',
|
||
'settings.agentMaxStepsHint': 'Cap on tool calls per agent run.',
|
||
'settings.queueSection': 'Job queue',
|
||
'settings.queueLead': 'Concurrency and timeouts for generation jobs and agent tool calls.',
|
||
'settings.concurrencyField': 'Concurrent jobs',
|
||
'settings.pollIntervalField': 'Poll interval (sec)',
|
||
'settings.pollTimeoutField': 'Job timeout (s)',
|
||
'settings.pollTimeoutHint': 'How long a ComfyUI job or one agent tool call may run. 0 waits until it finishes.',
|
||
'settings.maxRetriesField': 'Max retries',
|
||
'settings.maxError': 'Too high',
|
||
'settings.minError': 'Too low',
|
||
'settings.notNumber': 'Must be a number',
|
||
'settings.comfySection': 'ComfyUI',
|
||
'settings.comfyLead': 'Where ComfyUI runs.',
|
||
'settings.comfyHint': 'Must be reachable from this machine.',
|
||
'settings.comfyMultiHint': 'ComfyUI addresses now support multiple connections (local / LAN / cloud), bindable per imported workflow.',
|
||
'settings.comfyGoto': 'Manage in “ComfyUI Connections” →',
|
||
'settings.storageSection': 'System Paths',
|
||
'settings.storageLead': 'Where files live on disk, and where the agent may work.',
|
||
'settings.storageCalloutStrong': 'Changing data directory',
|
||
'settings.storageCalloutBody': 'moves assets. Existing paths keep working until set here.',
|
||
'settings.dataDir': 'Data directory',
|
||
'settings.assetsDir': 'Assets directory',
|
||
'settings.workspaceDir': 'Agent workspace',
|
||
'settings.workspaceDirHint':
|
||
'Sandbox folder the AI agent’s shell may work in (run_command). Leave empty to use DATA_DIR/workspace. The agent cannot touch anything outside it.',
|
||
'settings.shellSection': 'Agent shell',
|
||
'settings.shellLead': 'Let the agent run installed command-line tools in its workspace.',
|
||
'settings.shellCalloutStrong': 'Opt-in only:',
|
||
'settings.shellCalloutBody':
|
||
'commands run on this machine, sandboxed to the agent workspace. Sensitive files (config, database, credentials) are always denied; anything not read-only asks you first.',
|
||
'settings.shellLabel': 'Enable agent shell (run_command)',
|
||
'settings.shellHint':
|
||
'Off by default. When on, the agent may run inspection commands (ffprobe) freely and mutating commands only after you approve a scope="shell" question card.',
|
||
'settings.historyBudgetSection': 'Context history budget',
|
||
'settings.historyBudgetLead':
|
||
'Caps how much conversation history each agent request replays, so long sessions never overflow the model’s context window.',
|
||
'settings.historyBudgetField': 'History budget (characters)',
|
||
'settings.historyBudgetHint':
|
||
'≈4 characters per token. Oldest whole turns drop first; presets below are good starting points.',
|
||
'settings.historyBudgetSmall': 'Small · 60k',
|
||
'settings.historyBudgetMedium': 'Medium · 120k',
|
||
'settings.historyBudgetLarge': 'Large · 400k',
|
||
'settings.hardeningSection': 'Prompt hardening',
|
||
'settings.hardeningLead': 'Rules prepended to generation prompts.',
|
||
'settings.hardeningHint': 'Used to enforce negative constraints or style guardrails.',
|
||
'settings.hardeningPlaceholder': 'No violence, no gore, no explicit content.',
|
||
'settings.hardeningRulesLabel': 'Hardening rules',
|
||
'settings.hardeningCalloutStrong': 'Hardening applies',
|
||
'settings.hardeningCalloutBody': 'to every prompt sent through the pipeline.',
|
||
'settings.leaveTitle': 'Leave without saving?',
|
||
'settings.leaveMessage': 'You have unsaved changes that will be lost.',
|
||
'settings.leaveConfirm': 'Leave',
|
||
'settings.dryRunLabel': 'Validate only (dry run)',
|
||
|
||
// --- Shot editor ---
|
||
'shot.scene': 'Scene',
|
||
'shot.hint': 'Add objects, arrange the shot, then capture.',
|
||
'shot.addObject': 'Add object',
|
||
'shot.clearScene': 'Clear scene',
|
||
'shot.visibility': 'Toggle visibility',
|
||
'shot.lock': 'Toggle lock',
|
||
'shot.emptyScene': 'Scene is empty',
|
||
'shot.objName.male': 'Male',
|
||
'shot.objName.female': 'Female',
|
||
'shot.objName.child': 'Child',
|
||
'shot.objName.cube': 'Cube',
|
||
'shot.objName.plane': 'Plane',
|
||
'shot.objName.cylinder': 'Cylinder',
|
||
'shot.objName.sphere': 'Sphere',
|
||
'shot.objName.capsule': 'Capsule',
|
||
'shot.objName.cone': 'Cone',
|
||
'shot.objName.torus': 'Torus',
|
||
'shot.objName.camera': 'Camera',
|
||
'shot.selectObject': 'Select object',
|
||
'shot.selectObjectPose': 'Select object and pose it',
|
||
'shot.fov': 'Field of view',
|
||
'shot.transform': 'Transform',
|
||
'shot.pose': 'Pose',
|
||
'shot.shotSection': 'Shot',
|
||
'shot.shotSize': 'Shot size',
|
||
'shot.angle': 'Camera angle',
|
||
'shot.elevation': 'Elevation',
|
||
'shot.composition': 'Composition',
|
||
'shot.center': 'Center',
|
||
'shot.captureRef': 'Reference capture',
|
||
'shot.railExpand': 'Expand session rail',
|
||
'shot.railCollapse': 'Collapse session rail',
|
||
'shot.railOpen': 'Open {title}',
|
||
'shot.railNoScenes': 'No scenes yet',
|
||
'shot.railDeleteScene': 'Delete scene',
|
||
'shot.newScene': 'New scene',
|
||
'shot.captures': '{count} captures',
|
||
'shot.videoBadge': 'Video',
|
||
'shot.captureAlt': 'Scene capture',
|
||
'shot.noCaptures': 'No captures yet',
|
||
'shot.timelinePlay': 'Play',
|
||
'shot.timelinePause': 'Pause',
|
||
'shot.timelinePlayhead': 'Playhead',
|
||
'shot.camKeyframe': 'Camera at {time}s',
|
||
'shot.objKeyframe': '{name} at {time}s',
|
||
'shot.keyframeCamAdd': 'Add camera keyframe',
|
||
'shot.keyframeCamRemove': 'Remove camera keyframe',
|
||
'shot.keyframeObjAdd': 'Add keyframe for {name}',
|
||
'shot.keyframeObjDelete': 'Delete keyframe',
|
||
'shot.keyframeObjSelectFirst': 'Select an object first',
|
||
'shot.exportHint': 'Need scene objects or at least 2 camera keyframes (captures not required).',
|
||
'shot.exportHintNeedBeats': 'Add scene objects or ≥2 camera keyframes to export. Captures are not required.',
|
||
'shot.exportTitle': 'Export timeline',
|
||
'shot.exportImage': 'Export image',
|
||
'shot.exportVideo': 'Export video',
|
||
'shot.viewportTools': 'Tools',
|
||
'shot.toolSelect': 'Select',
|
||
'shot.toolSelectTitle': 'Select tool',
|
||
'shot.toolMove': 'Move',
|
||
'shot.toolMoveTitle': 'Move tool',
|
||
'shot.toolRotate': 'Rotate',
|
||
'shot.toolRotateTitle': 'Rotate tool',
|
||
'shot.toolScale': 'Scale',
|
||
'shot.toolScaleTitle': 'Scale tool',
|
||
'shot.toolPose': 'Pose',
|
||
'shot.toolPoseTitle': 'Pose tool',
|
||
'shot.toolPoseDisabled': 'Select an object to pose it',
|
||
'shot.undoTitle': 'Undo',
|
||
'shot.redoTitle': 'Redo',
|
||
'shot.gridTitle': 'Toggle grid',
|
||
'shot.grid': 'Grid',
|
||
'shot.compositionTitle': 'Toggle composition guides',
|
||
'shot.captureTitle': 'Capture frame',
|
||
'shot.capture': 'Capture',
|
||
'shot.errBlob': 'Could not read the captured frame',
|
||
'shot.errRecorder': 'Could not start recorder',
|
||
'shot.errNoData': 'No scene data to export',
|
||
|
||
// Models settings page (spec-v2 §9)
|
||
'models.title': 'Models',
|
||
'models.subtitle': 'Add custom LLMs for your agents · phase 1 covers LLMs only; image / video models come later',
|
||
'models.statusCount': '{n} models · {m} available',
|
||
'models.add': 'Add model',
|
||
'models.tabLlm': 'Language models',
|
||
'models.tabImage': 'Image models',
|
||
'models.tabVideo': 'Video models',
|
||
'models.comingSoon': 'Coming later',
|
||
'models.empty': 'No models yet — click "Add model" in the top right to connect your first LLM',
|
||
'models.typeLocal': 'Local',
|
||
'models.typeLan': 'LAN',
|
||
'models.typeCloud': 'Cloud',
|
||
'models.defaultBadge': 'Agent default',
|
||
'models.setDefault': 'Set as default',
|
||
'models.defaultSetToast': 'Set as agent default model',
|
||
'models.test': 'Test connection',
|
||
'models.testing': 'Testing…',
|
||
'models.edit': 'Edit',
|
||
'models.delete': 'Delete',
|
||
'models.statusUntested': 'Not tested',
|
||
'models.statusConnected': 'Connected',
|
||
'models.statusFailed': 'Connection failed',
|
||
'models.latency': '{ms}ms latency',
|
||
'models.agentsUsing': 'used by {n} agents',
|
||
'models.lastTestAt': 'last test {time}',
|
||
'models.consecutiveFails': '{n} consecutive failures',
|
||
'models.cloudPaused': 'Cloud calls paused',
|
||
'models.formTitleAdd': 'Add model',
|
||
'models.formTitleEdit': 'Edit model',
|
||
'models.formClose': 'Close',
|
||
'models.fName': 'Name',
|
||
'models.fNamePh': 'Name this model, e.g. DeepSeek official',
|
||
'models.fApiType': 'API type',
|
||
'models.apiOpenai': 'OpenAI-compatible',
|
||
'models.apiAnthropic': 'Anthropic',
|
||
'models.apiOther': 'Other',
|
||
'models.apiTypeHelp': 'Phase 1 supports OpenAI-compatible APIs only; other protocols arrive with image / video models',
|
||
'models.fBaseUrl': 'Base URL',
|
||
'models.baseUrlHelp': 'Include protocol and port, e.g. http://192.168.200.18:11434/v1',
|
||
'models.fModel': 'Model name',
|
||
'models.modelHelp': 'Use the model ID from your provider',
|
||
'models.fApiKey': 'API key',
|
||
'models.keyNoEcho': 'never echoed',
|
||
'models.keyHelp': 'Stored on this server only; the full key is never shown in the UI',
|
||
'models.keyKeepHint': 'Key saved — leave empty to keep it',
|
||
'models.fTimeout': 'Timeout',
|
||
'models.timeoutSec': '{n}s',
|
||
'models.testOk': '✓ Test passed · {ms}ms · {model} available',
|
||
'models.testFail': '✕ Test failed · {reason}',
|
||
'models.needTest': 'Save unlocks after a passing test',
|
||
'models.testBtn': 'Test connection',
|
||
'models.save': 'Save model',
|
||
'models.errName': 'Please name this model',
|
||
'models.errUrl': 'Invalid URL — it needs protocol and path, e.g. https://api.deepseek.com/v1',
|
||
'models.errModel': 'Please enter the model name from your provider',
|
||
'models.errKey': 'Please enter the API key',
|
||
'models.failTimeout': 'Timed out ({sec}s, no response): the server cannot reach this address — check the address, port and firewall',
|
||
'models.failAuth': 'Authentication failed (401): check that the API key is correct and not expired; with aggregators, confirm the model is enabled for your account',
|
||
'models.failNotFound': 'Reachable but model not found (404): check the model name spelling',
|
||
'models.failNotOpenai': 'Reachable but not recognized as an OpenAI-compatible API — make sure the path ends with /v1',
|
||
'models.failConnect': 'The server cannot connect to this address — check the address and port',
|
||
'models.failHttp': 'Test failed (HTTP {status})',
|
||
'models.delTitle': 'Delete model',
|
||
'models.delConfirmUsed': '{n} agents use this model; after deletion they fall back to the agent default. Delete?',
|
||
'models.delConfirmFree': 'Delete this model? This cannot be undone.',
|
||
'models.delDefaultHint': 'This is the agent default — pick another default first',
|
||
'models.agentsTitle': 'Agent default models',
|
||
'models.agentsHint': 'Changes apply to new sessions · per-agent overrides live on the Agents page',
|
||
'models.agentDefault': 'Agent default',
|
||
'models.agentStory': 'Screenplay',
|
||
'models.agentStyle': 'Visual design',
|
||
'models.agentScript': 'Storyboards',
|
||
'models.agentAssets': 'Asset library',
|
||
'models.agentVideo': 'Shot lists',
|
||
'models.unavailable': '(unavailable)',
|
||
'models.noticeStrong': 'Connectivity is measured from the workbench server:',
|
||
'models.noticeBody': 'a URL opening in your browser does not mean the server running this workbench can reach it; connection tests and chat requests are made by the server. API keys are stored on the server only and never echoed in the UI.',
|
||
'models.saved': 'Model saved',
|
||
'models.deleted': 'Model deleted',
|
||
'models.assignSaved': 'Agent models updated',
|
||
'models.saveFailed': 'Save failed: {detail}',
|
||
'models.loading': 'Loading…',
|
||
'models.loadFailed': 'Failed to load settings',
|
||
'models.idleFormHint': 'Pick "Edit" on a card, or click "Add model" above',
|
||
|
||
// --- A shell + projects overview (HEL-608) ---
|
||
'shell.brand': 'Film Atelier',
|
||
'shell.brandMark': 'F',
|
||
'shell.brandHome': 'Back to project overview',
|
||
'shell.navAria': 'Primary',
|
||
'shell.navProjects': 'Projects',
|
||
'shell.navWorkbench': 'Workbench',
|
||
'shell.navImage': 'Image Gen',
|
||
'shell.navVideo': 'Video Gen',
|
||
'shell.navTasks': 'Jobs',
|
||
'shell.navAgents': 'Agents',
|
||
'shell.navConnections': 'ComfyUI Connections',
|
||
'shell.navModels': 'Models',
|
||
'shell.navLibrary': 'Asset Library',
|
||
'shell.navSettings': 'Settings',
|
||
'shell.comfy_ok': '{name} connected',
|
||
'shell.comfy_fail': '{name} unreachable',
|
||
'shell.comfy_testing': 'Testing {name}…',
|
||
'shell.comfyUnset': 'ComfyUI · not configured',
|
||
'shell.scopeHint': 'Switch project',
|
||
'shell.scopeAll': 'All projects',
|
||
'shell.scopeAllList': 'All projects list',
|
||
'shell.scopeRecent': 'Recent projects',
|
||
'shell.scopeLoadFailed': 'Could not load projects',
|
||
'shell.scopeEmpty': 'No projects yet — create one',
|
||
'shell.scopeStage': '{n}/5 confirmed',
|
||
'shell.queueRunning': '{n} generating',
|
||
'shell.queueQueued': '{n} queued',
|
||
'shell.queueIdle': 'Queue idle',
|
||
'shell.queueActive': '{n} active',
|
||
'shell.trayTitle': 'Job tray',
|
||
'shell.trayRecent': 'Recent jobs · click to see all jobs',
|
||
'shell.trayEmpty': 'No generation jobs yet',
|
||
'shell.trayAll': 'View all jobs',
|
||
'shell.searchTitle': 'Search pages and projects',
|
||
'shell.searchPlaceholder': 'Search pages, projects',
|
||
'shell.searchShortcut': 'Search (Ctrl/⌘ + K)',
|
||
'shell.searchEmpty': 'No page or project matches “{q}”',
|
||
'shell.searchGroupPages': 'Pages',
|
||
'shell.searchGroupProjects': 'Projects · open the workbench',
|
||
'shell.searchHintMove': 'select',
|
||
'shell.searchHintOpen': 'open',
|
||
'shell.searchHintClose': 'close',
|
||
'shell.reduceMotion': 'Reduce motion',
|
||
'shell.reduceHint': 'Turn off movement, scaling and glow animations; keep only short fades',
|
||
'shell.reduceSystem': 'Following the system “Reduce motion” setting',
|
||
'shell.tabAria': 'Primary (narrow screens)',
|
||
'shell.tabProjects': 'Projects',
|
||
'shell.tabCreate': 'Create',
|
||
'shell.tabGenerate': 'Generate',
|
||
'shell.tabMore': 'More',
|
||
'shell.morePages': 'More pages',
|
||
'shell.moreTools': 'Tools',
|
||
'home.title': 'Projects overview',
|
||
'home.subtitle': 'Manage your projects — start from an idea or a ready-made script.',
|
||
'home.projectCount': '{n} projects · {m} in progress',
|
||
'home.startIdea': 'Start from an idea',
|
||
'home.importScript': 'Import a script',
|
||
'home.entryIdeaTitle': 'Start from an idea',
|
||
'home.entryIdeaBody': 'Describe an idea once; the agents take it through story, boards and clips step by step.',
|
||
'home.entryScriptTitle': 'Import a script',
|
||
'home.entryScriptBody': 'Already have a script? Paste it in, create the project, and let the script agent break it into ordered scenes.',
|
||
'home.ideaPlaceholder': 'A rainy little harbor where the lighthouse keeper finds…',
|
||
'home.scriptField': 'Full script',
|
||
'home.scriptPlaceholder': 'Paste the complete script here…',
|
||
'home.scriptHint': 'After creating, the Agents page opens and the script agent turns the pasted script into ordered scenes.',
|
||
'home.errTitle': 'Please give the project a title',
|
||
'home.errScript': 'Please paste the full script',
|
||
'home.myProjects': 'My projects',
|
||
'home.myProjectsHint': 'Click a project to continue working',
|
||
'home.emptyProjects': 'No projects yet. Use “Start from an idea” or “Import a script” above to create the first one.',
|
||
'home.noIdea': 'No idea description yet',
|
||
'home.statScenes': '{n} scenes',
|
||
'home.statCharacters': '{n} characters',
|
||
'home.statAssets': 'assets {ready}/{total}',
|
||
'home.statusDraft': 'Draft',
|
||
'home.statusProgress': 'In progress',
|
||
'home.statusDone': 'Completed',
|
||
'home.tasksTitle': 'Jobs',
|
||
'home.activeJobs': '{n} active',
|
||
'home.emptyJobs': 'No generation jobs yet',
|
||
'home.emptyJobsSub': 'Jobs started from a project or the workbench will show up here.',
|
||
'home.tasksNote': 'Full generation history and filters live in the Jobs page (nav → 生成任务).',
|
||
'home.kindImage': 'image',
|
||
'home.kindVideo': 'video',
|
||
'home.kindExport': 'film',
|
||
'home.jobDone': 'done',
|
||
'home.jobRunning': 'running',
|
||
'home.jobQueued': 'queued',
|
||
'home.jobFailed': 'failed',
|
||
'home.jobRequeued': 'Job requeued',
|
||
'home.jobRetryFailed': 'Could not requeue the job',
|
||
'home.jobProject': 'Project #{id}',
|
||
|
||
// --- ComfyUI connections page (a6, HEL-611) ---
|
||
'conn.title': 'ComfyUI Connections',
|
||
'conn.subtitle': 'Register local, LAN or cloud ComfyUI API addresses · connectivity is probed by the server running this workbench',
|
||
'conn.statusCount': '{n} connections · {m} passing',
|
||
'conn.add': 'Add connection',
|
||
'conn.loading': 'Loading connections…',
|
||
'conn.loadFailed': 'Failed to load connections',
|
||
'conn.empty': 'No ComfyUI connections yet — add your first address with “Add connection”.',
|
||
'conn.targetsTitle': 'Where jobs run',
|
||
'conn.targetImage': 'Standalone image',
|
||
'conn.targetVideo': 'Standalone video',
|
||
'conn.targetFlow': 'Workbench jobs',
|
||
'conn.targetChange': 'Change',
|
||
'conn.targetMixed': '{n} connections',
|
||
'conn.targetNote': 'Jobs follow each workflow’s binding; unbound workflows use the default connection. Change bindings in the workflow library — the image / video pages can also switch before generating.',
|
||
'conn.defaultBadge': 'Default',
|
||
'conn.test': 'Test connection',
|
||
'conn.testing': 'Testing…',
|
||
'conn.edit': 'Edit',
|
||
'conn.delete': 'Delete',
|
||
'conn.setDefault': 'Set as default',
|
||
'conn.delDefaultHint': 'The default connection cannot be deleted; set another default first',
|
||
'conn.delTitle': 'Delete connection',
|
||
'conn.delConfirmUsed': 'Workflows bound to this connection will fall back to the default. Existing job snapshots are kept. Delete “{name}”?',
|
||
'conn.delConfirmFree': 'Delete connection “{name}”?',
|
||
'conn.statusUntested': 'Untested',
|
||
'conn.statusConnected': 'Test passed',
|
||
'conn.statusFailed': 'Test failed',
|
||
'conn.latency': '{ms} ms latency',
|
||
'conn.version': 'version {v}',
|
||
'conn.lastTestAt': 'last tested {time}',
|
||
'conn.boundWorkflows': '{n} workflows bound',
|
||
'conn.tokenSaved': 'Token saved — leave blank to keep it',
|
||
'conn.saved': 'Connection saved',
|
||
'conn.deleted': 'Connection deleted',
|
||
'conn.saveFailed': 'Save failed: {detail}',
|
||
'conn.defaultSetToast': 'Set as default connection',
|
||
'conn.formTitleAdd': 'Add ComfyUI connection',
|
||
'conn.formTitleEdit': 'Edit ComfyUI connection',
|
||
'conn.formClose': 'Close',
|
||
'conn.fName': 'Name',
|
||
'conn.fNamePh': 'e.g. Local ComfyUI / render box',
|
||
'conn.fBaseUrl': 'API address',
|
||
'conn.fBaseUrlPh': 'http://192.168.200.18:8188',
|
||
'conn.baseUrlHelp': 'HTTP API address of ComfyUI (default port 8188); same format for local, LAN and cloud.',
|
||
'conn.fAuth': 'Authentication',
|
||
'conn.authNone': 'None',
|
||
'conn.authBearer': 'Bearer token',
|
||
'conn.authHeader': 'Custom header',
|
||
'conn.authHelp': 'Only needed when the endpoint sits behind auth (reverse proxy key, etc.).',
|
||
'conn.fToken': 'Access token',
|
||
'conn.fHeaderName': 'Header name',
|
||
'conn.fHeaderNamePh': 'X-Api-Key',
|
||
'conn.keyNoEcho': 'stored server-side only, never echoed',
|
||
'conn.keyHelp': 'The token lives in the workbench server config file and never reaches the browser.',
|
||
'conn.fNotes': 'Notes',
|
||
'conn.fNotesPh': 'optional: what this box runs, VRAM…',
|
||
'conn.errName': 'Name is required',
|
||
'conn.errUrl': 'Address must be a valid http:// or https:// URL',
|
||
'conn.errHeaderName': 'Custom header needs a header name',
|
||
'conn.testOk': '✓ Test passed · {ms} ms · ComfyUI {v}',
|
||
'conn.testFail': '✕ {reason}',
|
||
'conn.needTest': 'Pass the test before saving',
|
||
'conn.testBtn': 'Test',
|
||
'conn.save': 'Save',
|
||
'conn.noticeStrong': 'The server decides connectivity: ',
|
||
'conn.noticeBody': 'an address opening in your browser does not mean generation works; both tests and generation requests are made by the server running this workbench. Tokens stay server-side.',
|
||
'conn.wfTitle': 'Workflow library',
|
||
'conn.wfHint': 'Import ComfyUI API-format JSON, classify as image / video, bind to a connection',
|
||
'conn.wfEmpty': 'No workflows imported yet. In ComfyUI enable developer mode, export as “API format” JSON, then paste it here.',
|
||
'conn.wfCount': '{n} workflows · {m} image · {k} video',
|
||
'conn.wfKindImage': 'Image',
|
||
'conn.wfKindVideo': 'Video',
|
||
'conn.wfConnection': 'Bound connection',
|
||
'conn.wfConnectionActive': 'Follows the default connection',
|
||
'conn.wfParams': '{n} fillable parameters',
|
||
'conn.wfImport': 'Import workflow',
|
||
'conn.wfImporting': 'Importing…',
|
||
'conn.wfNodes': '{n} nodes',
|
||
'conn.wfImportedN': 'Workflow imported — {n} fillable parameters detected',
|
||
'conn.wfImportedNoParams': 'Workflow imported, but no fillable parameters were detected: it will run with its built-in settings',
|
||
'conn.wfImportFailed': 'Import failed: {detail}',
|
||
'conn.wfImportTitle': 'Import ComfyUI workflow (API-format JSON)',
|
||
'conn.wfImportHint': 'Paste or pick a file; name is required, the kind decides whether it shows in the image or video window.',
|
||
'conn.wfJsonInvalid': 'Not valid API-format JSON (expected an object of node id to class_type)',
|
||
'conn.wfJsonPh': 'Paste the ComfyUI API-format JSON here, or pick a file',
|
||
'conn.wfDeleted': 'Workflow deleted',
|
||
'conn.wfImportedBroken': 'Imported, but the workflow file is incomplete and must be re-exported before generating: {detail}',
|
||
'conn.wfBrokenBadge': 'Incomplete file — cannot generate',
|
||
// --- Five usages & import confirmation (HEL-636) ---
|
||
'usage.text2image': 'Text → Image',
|
||
'usage.image2image': 'Image → Image',
|
||
'usage.text2video': 'Text → Video',
|
||
'usage.image2video': 'Image → Video',
|
||
'usage.ref2video': 'Reference → Video',
|
||
'usage.pending': 'Usage pending',
|
||
'wfRole.image': 'Input image',
|
||
'wfRole.first_frame': 'First frame',
|
||
'wfRole.last_frame': 'Last frame',
|
||
'wfRole.reference_image': 'Reference',
|
||
'wfRole.mask': 'Mask',
|
||
'conn.wfImportAction': 'Import workflow',
|
||
'conn.wfConfirmTitle': 'Confirm detection',
|
||
'conn.wfStepAnalyze': 'Paste & analyze',
|
||
'conn.wfStepConfirm': 'Confirm & save',
|
||
'conn.wfChooseFile': 'Choose file',
|
||
'conn.wfAnalyze': 'Analyze',
|
||
'conn.wfAnalyzing': 'Analyzing…',
|
||
'conn.wfConfirmHint': 'Review the evidence, output nodes and image slots; correct the usage or slot roles before saving.',
|
||
'conn.wfUsageLabel': 'Usage',
|
||
'conn.wfUsageAuto': 'Auto-detected: {usage}',
|
||
'conn.wfUsageNeedPick': 'Pick manually',
|
||
'conn.wfPickUsage': 'Choose a usage first',
|
||
'conn.wfSlotsLabel': 'Image slots',
|
||
'conn.wfSlotsHint': 'Roles are inferred from wiring; override them (input image / first / last frame / reference / mask) and the manual choice sticks.',
|
||
'conn.wfBack': 'Back',
|
||
'conn.wfConfirmSave': 'Confirm & save',
|
||
'conn.wfImportedWithUsage': 'Saved as “{usage}” with {n} fillable parameters',
|
||
'conn.wfPendingCount': '{n} pending',
|
||
'conn.wfConfirmed': 'Usage confirmed: {usage} — the workflow can generate now',
|
||
'conn.wfSourceUser': 'Usage set manually; re-analysis will not overwrite it',
|
||
'conn.wfSourceAuto': 'Usage auto-detected',
|
||
'conn.wfDisabledBadge': 'Disabled',
|
||
'conn.wfConfirmAria': 'Confirm workflow usage',
|
||
'conn.wfOutputLabel': 'Output nodes',
|
||
'conn.wfOutputNeedPick': 'Unrecognized custom output nodes — designate them',
|
||
'conn.wfOutputHint': 'Check the nodes that actually produce results and pick each one’s media type; generation harvests images/videos only from these nodes.',
|
||
'conn.wfOutputPick': 'Check at least one output node',
|
||
'conn.wfOutputKindAria': 'Output node media type',
|
||
'conn.wfOutputPendingBadge': 'Outputs unset',
|
||
'conn.wfOutputNeedMap': 'This workflow has unrecognized output nodes; designate them and their media type to enable it',
|
||
'conn.wfOutputApply': 'Save output mapping',
|
||
'conn.wfMapCancel': 'Cancel',
|
||
'conn.wfOutputApplied': 'Output mapping saved: node {nodes}',
|
||
'conn.wfOutputCleared': 'Output mapping cleared — the workflow is pending again',
|
||
'conn.missingMaterial': 'A dedicated Qwen Image 2.1 workflow JSON is not in the repo yet: export it from ComfyUI and import it here — the generic import path is ready.',
|
||
// --- Standalone image / video generation (a3/a4, HEL-612) ---
|
||
'studio.image.title': 'Image',
|
||
'studio.image.subtitle': 'Generate images with imported workflows · shares connections & queue with ComfyUI Connections',
|
||
'studio.video.title': 'Video',
|
||
'studio.video.subtitle': 'Generate videos with imported workflows · shares connections & queue with ComfyUI Connections',
|
||
'studio.genParams': 'Parameters',
|
||
'studio.modeTextToImage': 'Text to image',
|
||
'studio.modeTextToVideo': 'Text to video',
|
||
'studio.video.resultsTitle': 'Preview',
|
||
'studio.image.historyTitle': 'Image history',
|
||
'studio.video.historyTitle': 'Video history',
|
||
'studio.historyCount': '{n} total',
|
||
'studio.doneAt': 'Done at {time}',
|
||
'studio.kindImageText': 'image',
|
||
'studio.kindVideoText': 'video',
|
||
'studio.loading': 'Loading…',
|
||
'studio.connLabel': 'Connection',
|
||
'studio.connQueue': 'Queue {n}',
|
||
'studio.connUntested': 'Checking…',
|
||
'studio.connOk': 'Connected · {ms} ms',
|
||
'studio.connFail': 'Unreachable',
|
||
'studio.connManage': 'Manage connections',
|
||
'studio.wfLabel': 'Workflow',
|
||
'studio.wfParams': '{n} fillable params',
|
||
'studio.wfBindTo': 'Bound to {name}',
|
||
'studio.wfFollowActive': 'Follows the default connection',
|
||
'studio.promptLabel': 'Positive prompt',
|
||
'studio.promptPh': 'Describe the shot: subject, setting, light, style…',
|
||
'studio.negLabel': 'Negative prompt',
|
||
'studio.seedLabel': 'Seed',
|
||
'studio.sizeLabel': 'Size',
|
||
'studio.batchLabel': 'Batch',
|
||
'studio.durationLabel': 'Duration (s)',
|
||
'studio.fpsLabel': 'Frame rate',
|
||
'studio.stepsLabel': 'Steps',
|
||
'studio.cfgLabel': 'CFG',
|
||
'studio.paramsTitle': 'Workflow params',
|
||
'studio.chars': '{n} chars',
|
||
'studio.insertStyle': 'Insert style words',
|
||
'studio.styleSoon': 'Skill word library arrives with the Agents feature',
|
||
'studio.generateN': 'Generate · {n} images',
|
||
'studio.generate': 'Generate',
|
||
'studio.submitting': 'Submitting…',
|
||
'studio.etaHint': 'Actual time depends on the target connection and workflow',
|
||
'studio.errNoConn': 'Select a generation connection first',
|
||
'studio.errConnDown': "This connection is unavailable (last test failed at {time}) — switch to another or fix it in ComfyUI Connections",
|
||
'studio.errPrompt': 'Please fill in the prompt',
|
||
'studio.errPromptLong': 'Prompt exceeds 2000 characters — please trim it',
|
||
'studio.errRefImage': 'Image-to-image needs a reference image',
|
||
'studio.errFirstLast': 'First/last-frame video needs both the first and the last frame',
|
||
'studio.errUpload': 'Please upload {label}',
|
||
'studio.errFill': 'Please fill in {label}',
|
||
'studio.slotRef': 'Reference image',
|
||
'studio.slotRefN': 'Reference {n}',
|
||
'studio.slotMask': 'Mask',
|
||
'studio.slotFirst': 'First frame',
|
||
'studio.slotLast': 'Last frame',
|
||
'studio.slotOptional': 'Optional',
|
||
'studio.slotRefVideo': 'Reference video',
|
||
'studio.slotAudio': 'Reference audio',
|
||
'studio.slotPick': 'Click or drop a file',
|
||
'studio.slotFromResults': 'Pick from image results',
|
||
'studio.taskCurrent': 'Current task',
|
||
'studio.taskQueued': 'Queued',
|
||
'studio.taskRunning': 'Generating',
|
||
'studio.taskCancel': 'Cancel task',
|
||
'studio.queuedBehind': '{n} task(s) ahead',
|
||
'studio.stepsShort': 'Steps {v}',
|
||
'studio.usedShort': 'Elapsed {v}',
|
||
'studio.etaShort': 'ETA {v}',
|
||
'studio.targetShort': 'Target {name}',
|
||
'studio.renderFrames': 'Frame {done}/{total}',
|
||
'studio.noActiveTask': 'No active task · set the parameters on the left and press Generate',
|
||
'studio.resultsTitle': 'Recent results',
|
||
'studio.selectHint': 'Selected',
|
||
'studio.sendToImg2Img': 'Send to img2img',
|
||
'studio.zoom': 'Zoom',
|
||
'studio.download': 'Download',
|
||
'studio.downloadMp4': 'Download MP4',
|
||
'studio.copyPrompt': 'Copy prompt',
|
||
'studio.copiedToast': 'Copied — paste it into image/video generation',
|
||
'studio.sentToImg2ImgToast': 'Filled in as the reference image — check the params and generate',
|
||
'studio.noImg2ImgWf': 'No image workflow declares a reference-image input yet — import an img2img workflow in ComfyUI Connections first',
|
||
'studio.videoRefStrip': 'First / last frame reference',
|
||
'studio.historyEmptyImage': 'No image generations yet — set the parameters on the left and press Generate',
|
||
'studio.historyEmptyVideo': 'No video generations yet — set the parameters on the left and press Generate',
|
||
'studio.jobName': 'Task #{id}',
|
||
'studio.retryLink': 'Retry',
|
||
'studio.retryQueuedToast': 'Task re-queued',
|
||
'studio.retryFailedToast': 'Re-queue failed: {detail}',
|
||
'studio.errNoWorkflow': 'Choose a workflow first',
|
||
'studio.errBlocked': 'Cannot submit: {reason}',
|
||
'studio.queuedToast': 'Submitted to “{name}”, queued',
|
||
'studio.submitFailedToast': 'Submit failed: {detail}',
|
||
'studio.jobFailedToast': 'Generation failed: {detail}',
|
||
'studio.wfNoParamsNote': 'This workflow has no fillable parameters and will run with its built-in prompt and settings. To fill them here, tag node titles with (Input:prompt) etc. in ComfyUI and re-import.',
|
||
'studio.wfAutoParamsNote': 'No (Input:…) title tags found — {n} parameters were detected from node types; blank fields keep the workflow values.',
|
||
'studio.promptNotDeclared': 'This workflow has no prompt node — nothing to fill',
|
||
'studio.modeImageEdit': 'Image edit',
|
||
'studio.modeImageToVideo': 'Image to video',
|
||
'studio.modeRefToVideo': 'Reference to video',
|
||
'studio.slotInput': 'Input image',
|
||
'studio.slotHintOne': 'Required · 1 image',
|
||
'studio.slotEmptyInput': 'Click or drop the input image',
|
||
'studio.slotEmptyFirst': 'Click or drop the first frame',
|
||
'studio.slotEmptySub': 'PNG / JPG / WebP · ≤ 20MB each',
|
||
'studio.slotFromResultsShort': 'From results',
|
||
'studio.errImageFormat': '"{name}" is not supported — use PNG / JPG / WebP; this file will not be used',
|
||
'studio.errImageSize': '"{name}" is larger than 20MB — compress it and upload again',
|
||
'studio.errNeedInputImage': 'Image edit needs an input image',
|
||
'studio.errNeedFirstFrame': 'Image to video needs a first frame',
|
||
'studio.errNeedRef': 'Reference to video needs at least 1 reference image',
|
||
'studio.errRefMax': 'At most {max} reference images: {n} selected, these {k} were not added',
|
||
'studio.refHint': 'Required · 1–{max} · {n} selected',
|
||
'studio.refAdd': 'Add reference image',
|
||
'studio.refAddSub': '{n} more · max {max}',
|
||
'studio.refReplace': 'Replace',
|
||
'studio.refRemove': 'Remove reference {n}',
|
||
'studio.refRejectedShort': 'Not added',
|
||
'studio.refFull': 'Limit of {max} reached — remove one to add another',
|
||
'studio.refStrip': 'Reference images ({n} used)',
|
||
'studio.resolutionLabel': 'Output resolution',
|
||
'studio.resolutionHint': 'About {v}×{v} px, keeps the input aspect; 0 = original size',
|
||
'studio.wfBrokenTitle': 'This workflow file is incomplete — ComfyUI cannot run it, generation is blocked',
|
||
'studio.wfBrokenHint': 'Re-export the API-format JSON from a ComfyUI that has the custom nodes installed, then import it again under ComfyUI connections.',
|
||
'studio.errWfBroken': 'Workflow file is incomplete — re-export it before generating',
|
||
'studio.cancelToast': 'Cancel requested',
|
||
'studio.deleteBtn': 'Delete',
|
||
'studio.delTitle': 'Delete task record',
|
||
'studio.delConfirm': 'Deleting also removes this job’s result files; the history cannot be restored. Delete?',
|
||
'studio.delTitleJob': 'Delete job “{name}”',
|
||
'studio.delConfirmMulti': 'This job produced {n} results. Deleting removes the whole job record and all {n} result files; this cannot be undone. Delete?',
|
||
'studio.deleteFailedToast': 'Delete failed: {detail}',
|
||
'studio.deletedTakeNoFilesToast': 'Deleted “{name}”',
|
||
'studio.deletedTakeToast': 'Deleted “{name}” together with its result files',
|
||
'studio.deletedToast': 'Job deleted together with its result files',
|
||
'studio.wfDeletedTag': 'Workflow deleted',
|
||
'studio.wfEmptyTitle': 'No {kind} workflows yet',
|
||
'studio.wfEmptyBody': "Enable ComfyUI's developer mode, export the workflow as API JSON, then import it on the ComfyUI Connections page as {kind}.",
|
||
'studio.wfEmptyGo': 'Import in ComfyUI Connections',
|
||
'studio.missingQwen': 'Dedicated Qwen Image 2.1 (t2i / img2img / mask) JSONs are still missing — the generic import path is ready; export from ComfyUI and import.',
|
||
'studio.missingFirstLast': 'The dedicated MiniMax H3 first/last-frame JSON is still missing — the bundled t2v / reference-to-video examples can be imported meanwhile.',
|
||
'studio.pickerTitle': 'Pick an image result',
|
||
'studio.pickerEmpty': 'No image results available yet',
|
||
'studio.pickerPick': 'Use',
|
||
'studio.uploadFailedToast': 'Upload failed: {detail}',
|
||
'studio.playAria': 'Play',
|
||
'studio.pauseAria': 'Pause',
|
||
'studio.fullscreenAria': 'Fullscreen',
|
||
|
||
// --- Generation tasks page (HEL-612) ---
|
||
'tasks.title': 'Generation tasks',
|
||
'tasks.subtitle': 'All image / video tasks — standalone windows and the creation flow',
|
||
'tasks.filterAll': 'All',
|
||
'tasks.filterImage': 'Images',
|
||
'tasks.filterFailed': 'Failed',
|
||
'tasks.filterActive': 'Active',
|
||
'tasks.filterVideo': 'Videos',
|
||
'tasks.count': '{n} tasks · {m} active',
|
||
'tasks.empty': 'No generation tasks yet. Submit the first one in Image or Video.',
|
||
'tasks.emptyFiltered': 'No tasks match the current filter.',
|
||
'tasks.goGenerate': 'Open Image',
|
||
'tasks.sourceStudioImage': 'Standalone image',
|
||
'tasks.sourceStudioVideo': 'Standalone video',
|
||
'tasks.sourcePlayground': 'Playground',
|
||
'tasks.sourceFlow': 'Creation flow',
|
||
'tasks.sourceOther': 'Generation',
|
||
'tasks.queued': 'Queued',
|
||
'tasks.running': 'Running',
|
||
'tasks.done': 'Done',
|
||
'tasks.failed': 'Failed',
|
||
'tasks.retry': 'Retry',
|
||
'tasks.cancel': 'Cancel',
|
||
'tasks.delete': 'Delete',
|
||
'tasks.download': 'Download',
|
||
'tasks.delTitle': 'Delete task',
|
||
'tasks.delConfirm': 'The result files will be removed together with the task. Delete it?',
|
||
'tasks.searchPh': 'Search tasks…',
|
||
'tasks.outputs': '{n} outputs',
|
||
|
||
'agentsPage.title': 'Agents',
|
||
'agentsPage.subtitle': 'Chat independently with the five creation agents; define and assign Skills',
|
||
'agentsPage.statusChip': '{n} Skills · {m} enabled',
|
||
'agentsPage.agentsTitle': 'Five agents',
|
||
'agentsPage.skillLib': 'Skill library',
|
||
'agentsPage.skillLibCount': '{n}',
|
||
'agentsPage.installedTitle': '{name} · installed Skills',
|
||
'agentsPage.installedCount': '{n} · {m} on',
|
||
'agentsPage.newSkill': 'New Skill',
|
||
'agentsPage.skillLibEmpty': 'No Skills yet — create one with “New Skill” above.',
|
||
'agentsPage.skillsCount': '{n} Skills',
|
||
'agentsPage.replying': 'Replying…',
|
||
'agentsPage.idle': 'Idle',
|
||
'agentsPage.assigned': 'assigned {n}',
|
||
'agentsPage.edit': 'Edit',
|
||
'agentsPage.toggleSkill': 'Enable or disable Skill',
|
||
'agentsPage.independentNote': 'Independent chat · not part of the creation flow',
|
||
'agentsPage.model': 'Model',
|
||
'agentsPage.modelDefault': 'Agent default',
|
||
'agentsPage.newSessionLabel': 'New chat',
|
||
'agentsPage.newSession': 'New chat',
|
||
'agentsPage.clear': 'Clear',
|
||
'agentsPage.export': 'Export',
|
||
'agentsPage.skillManage': 'Skill manager',
|
||
'agentsPage.composerPlaceholder': 'Keep chatting, or paste a script fragment… (Enter to send, Shift+Enter for newline)',
|
||
'agentsPage.send': 'Send',
|
||
'agentsPage.clearTitle': 'Clear chat',
|
||
'agentsPage.clearConfirm': 'History cannot be recovered after clearing. Clear the chat with the {name} agent?',
|
||
'agentsPage.skillErrName': 'Please give the Skill a name',
|
||
'agentsPage.skillErrAssign': 'Assign it to at least one Agent, otherwise it never takes effect',
|
||
'agentsPage.skillLoadFailed': 'Failed to read Skill content',
|
||
'agentsPage.skillSaved': 'Skill saved',
|
||
'agentsPage.skillSaveFailed': 'Save failed: {detail}',
|
||
'agentsPage.skillEnabled': 'Skill enabled',
|
||
'agentsPage.skillDisabled': 'Skill disabled — new replies will not use it',
|
||
'agentsPage.skillDeleted': 'Skill deleted',
|
||
'agentsPage.skillRestored': 'Rolled back to a previous version',
|
||
'agentsPage.skillTypeTemplate': 'Prompt template',
|
||
'agentsPage.skillTypeKnowledge': 'Reference knowledge',
|
||
'agentsPage.skillTypeRules': 'Process rules',
|
||
'agentsPage.versions': 'Version history',
|
||
'agentsPage.versionsEmpty': 'No versions yet — every save snapshots the old one.',
|
||
'agentsPage.restore': 'Restore',
|
||
'agentsPage.close': 'Close',
|
||
'agentsPage.editSkill': 'Edit Skill',
|
||
'agentsPage.skillName': 'Name',
|
||
'agentsPage.skillNamePh': 'e.g. cyberpunk-style-kit',
|
||
'agentsPage.skillType': 'Type',
|
||
'agentsPage.skillDesc': 'Description',
|
||
'agentsPage.skillDescPh': 'When should the agent use this Skill (shown in its skill list)',
|
||
'agentsPage.skillContent': 'Content',
|
||
'agentsPage.skillContentPh': 'Markdown supported: prompt templates, references, or process rules…',
|
||
'agentsPage.skillContentHint': 'Markdown supported; saving auto-bumps the version and archives the old one.',
|
||
'agentsPage.assignTo': 'Assign to',
|
||
'agentsPage.saveNext': 'Save v{v}+1',
|
||
'agentsPage.save': 'Save',
|
||
'agentsPage.disable': 'Disable',
|
||
'agentsPage.enable': 'Enable',
|
||
'agentsPage.delete': 'Delete',
|
||
'agentsPage.delSkillTitle': 'Delete Skill',
|
||
'agentsPage.delSkillConfirm': 'Deletion is irreversible; the {n} assigned agents lose it too. Delete it?',
|
||
'agentsPage.skillIdleHint': 'Pick “Edit” from the Skill library, or click “New Skill”',
|
||
'agentsPage.sugScript1': 'Turn an idea into a three-act outline',
|
||
'agentsPage.sugScript1P': 'I have an idea: a convenience-store clerk notices the same customer at the same minute every night. Please write a three-act short-film outline.',
|
||
'agentsPage.sugScript2': 'Polish an existing script',
|
||
'agentsPage.sugScript2P': 'I will paste an existing script — read it first, then point out three improvements to dialogue and pacing.',
|
||
'agentsPage.sugStyle1': 'Propose style directions',
|
||
'agentsPage.sugStyle1P': 'A neon-lit rainy urban romance short — give me three distinct visual style directions, each with English image-prompt keyword sets.',
|
||
'agentsPage.sugStyle2': 'Cinematic-realism keywords',
|
||
'agentsPage.sugStyle2P': 'Compile a ready-to-use set of cinematic-realism style prompts (positive + negative), English with Chinese notes.',
|
||
'agentsPage.sugBoard1': 'Break the script into a storyboard',
|
||
'agentsPage.sugBoard1P': 'Break this script into a shot list: shot number, size, camera move, frame content, dialogue cue, suggested duration.',
|
||
'agentsPage.sugBoard2': 'Storyboard a climax',
|
||
'agentsPage.sugBoard2P': 'A thirty-second chase climax — give one storyboard pass with clear rhythm changes.',
|
||
'agentsPage.sugAssets1': 'Character sheet prompts',
|
||
'agentsPage.sugAssets1P': 'The protagonist is a 17-year-old night-owl girl detective — write a consistent character-sheet prompt set (front / side / full body).',
|
||
'agentsPage.sugAssets2': 'Asset checklist',
|
||
'agentsPage.sugAssets2P': 'Based on the rainy convenience-store scene, list scene and prop asset prompts.',
|
||
'agentsPage.sugShot1': 'One video prompt',
|
||
'agentsPage.sugShot1P': 'A push-in shot at the store entrance, neon sign to glass door — write one directly usable video-model prompt.',
|
||
'agentsPage.sugShot2': 'First/last-frame shots',
|
||
'agentsPage.sugShot2P': 'Show how to write a first/last-frame video prompt: how to describe first frame, last frame, camera move, and duration.',
|
||
|
||
|
||
|
||
'workbench.title': 'Creation Workbench',
|
||
'workbench.subtitle': 'Script → style → storyboard → assets → shot list, five agents in relay',
|
||
'workbench.pickerSubtitle': 'Pick a project to continue its five-stage flow',
|
||
'workbench.pickerEmpty': 'No projects yet',
|
||
'workbench.pickerEmptyBody': 'Go back to the overview and start from an idea or import a script.',
|
||
'workbench.pickerGoHome': 'Open overview',
|
||
'workbench.pickerFootHint': 'You can also enter the workbench from the overview\'s 从创意开始 / 导入剧本 entries.',
|
||
'workbench.stageProgress': 'Five-stage progress',
|
||
'workbench.activeJobs': '{n} jobs running',
|
||
'workbench.stage.script': 'Script',
|
||
'workbench.stage.style': 'Visual Style',
|
||
'workbench.stage.storyboard': 'Storyboard',
|
||
'workbench.stage.assets': 'Assets',
|
||
'workbench.stage.shot': 'Shot List',
|
||
'workbench.lockedStep': 'Unlocks after 「{stage}」 is confirmed',
|
||
'workbench.state.todo': 'Not started',
|
||
'workbench.state.running': 'Generating',
|
||
'workbench.state.draft': 'Awaiting confirm',
|
||
'workbench.state.confirmed': 'Confirmed',
|
||
'workbench.state.edited': 'Edited',
|
||
'workbench.copied': 'Copied — paste it into image/video generation',
|
||
'workbench.copyFailed': 'Copy failed, please copy manually',
|
||
'workbench.copy': 'Copy',
|
||
'workbench.charCount': '{n} chars',
|
||
'workbench.runStage': 'Generate with {agent}',
|
||
'workbench.runDone': '{agent} finished the draft — please review and confirm',
|
||
'workbench.runFailed': 'Generation failed, please retry',
|
||
'workbench.runningHint': '{agent} is writing this stage…',
|
||
'workbench.confirmNext': 'Confirm & continue',
|
||
'workbench.confirmLast': 'Confirm stage',
|
||
'workbench.confirmed': '「{agent}」 stage confirmed',
|
||
'workbench.confirmFailed': 'Confirm failed, please retry',
|
||
'workbench.restore': 'Restore confirmed',
|
||
'workbench.restored': 'Restored to the last confirmed version',
|
||
'workbench.restoreFailed': 'Restore failed, please retry',
|
||
'workbench.draftNotice': 'This is an unconfirmed draft — the next agent only sees it after you confirm.',
|
||
'workbench.draftSaved': 'Draft saved — still needs confirmation',
|
||
'workbench.saveFailed': 'Save failed, please retry',
|
||
'workbench.saveDraft': 'Save draft',
|
||
'workbench.cancelEdit': 'Cancel',
|
||
'workbench.editDraft': 'Edit',
|
||
'workbench.regenerate': 'Regenerate',
|
||
'workbench.regenerateHint': 'Ask the agent to redo this stage (the confirmed version is kept and restorable)',
|
||
'workbench.instructionPh': 'Extra instructions (optional), e.g. more cinematic, casual dialogue…',
|
||
'workbench.jobSubmitted': 'Generation queued — results return to this project',
|
||
'workbench.jobSubmitFailed': 'Failed to submit the job',
|
||
'workbench.jobRequeued': 'Job re-queued',
|
||
'workbench.retryJob': 'Retry',
|
||
'workbench.cancelJob': 'Cancel job',
|
||
'workbench.openOutput': 'Open result',
|
||
'workbench.jobRunningPct': '{n}%',
|
||
'workbench.jobRunning': 'Running',
|
||
'workbench.jobQueued': 'Queued',
|
||
'workbench.jobDone': 'Done',
|
||
'workbench.jobFailed': 'Failed',
|
||
'workbench.generating': 'Generating…',
|
||
'workbench.progressChip': 'Stage {n}/5',
|
||
'workbench.backHome': 'Overview',
|
||
'workbench.loadFailed': 'Failed to load the workbench.',
|
||
'workbench.retryLoad': 'Retry',
|
||
'workbench.agentSkills': '{n} skills',
|
||
'workbench.chatWithAgent': 'Chat solo',
|
||
'workbench.tasksTitle': 'Stage jobs',
|
||
'workbench.tasksAll': 'All jobs',
|
||
'workbench.tasksEmpty': 'No generation jobs yet. Send prompts from the assets or shot-list stage.',
|
||
'workbench.flowTitle': 'Five-stage progress',
|
||
'workbench.script.todoTitle': 'Start from the script: hand your idea to the Script agent',
|
||
'workbench.script.todoIdea': 'Your idea:',
|
||
'workbench.script.generate': 'Draft the script',
|
||
'workbench.script.importBtn': 'Import existing script',
|
||
'workbench.script.writeManually': 'Write manually',
|
||
'workbench.script.importPlaceholder': 'Paste an existing script here… Importing skips script drafting and continues from visual style.',
|
||
'workbench.script.importHint': 'The imported script becomes the confirmed baseline of this stage.',
|
||
'workbench.script.importConfirm': 'Import & skip drafting',
|
||
'workbench.script.importDone': 'Script imported — continue from visual style',
|
||
'workbench.script.importFailed': 'Import failed, please check the text and retry',
|
||
'workbench.script.editorHint': 'Edit the script text directly; confirmation is still required after saving.',
|
||
'workbench.script.copyLabel': 'Full script',
|
||
'workbench.style.todoTitle': 'Define the visual style for the script',
|
||
'workbench.style.todoBody': 'The Visual Style agent proposes several distinct directions, each with copy-ready image prompts.',
|
||
'workbench.style.generate': 'Propose style directions',
|
||
'workbench.style.namePh': 'Direction name, e.g. Neon Cyber',
|
||
'workbench.style.descPh': 'Description (palette / lighting / texture)',
|
||
'workbench.style.promptPh': 'English image keywords, comma separated',
|
||
'workbench.style.negativePh': 'Negative prompt (optional, English)',
|
||
'workbench.style.negativeLabel': 'Negative prompt',
|
||
'workbench.style.remove': 'Remove direction',
|
||
'workbench.style.add': 'Add direction',
|
||
'workbench.style.chosen': 'Selected',
|
||
'workbench.style.chooseHint': 'When confirming this stage, your selected style is handed to later stages.',
|
||
'workbench.style.promptLabel': 'Style prompt',
|
||
'workbench.board.scene': 'Scene',
|
||
'workbench.board.size': 'Shot size',
|
||
'workbench.board.camera': 'Camera',
|
||
'workbench.board.duration': 'Sec',
|
||
'workbench.board.desc': 'Description',
|
||
'workbench.board.dialog': 'Dialog/SFX',
|
||
'workbench.board.descPh': 'What this shot shows',
|
||
'workbench.board.dialogPh': 'Dialog or SFX cue (optional)',
|
||
'workbench.board.remove': 'Remove shot',
|
||
'workbench.board.add': 'Add shot',
|
||
'workbench.board.todoTitle': 'Break the script into a shot-by-shot storyboard',
|
||
'workbench.board.todoBody': 'The Storyboard agent produces shot numbers, sizes, camera moves, framing and durations.',
|
||
'workbench.board.generate': 'Draft the storyboard',
|
||
'workbench.board.summary': '{n} shots · ~{sec}s',
|
||
'workbench.asset.kindCharacter': 'Character',
|
||
'workbench.asset.kindLocation': 'Location',
|
||
'workbench.asset.kindProp': 'Prop',
|
||
'workbench.asset.namePh': 'Asset name',
|
||
'workbench.asset.descPh': 'Description (appearance, usage)',
|
||
'workbench.asset.promptPh': 'Full English image prompt',
|
||
'workbench.asset.promptLabel': 'Image prompt',
|
||
'workbench.asset.remove': 'Remove asset',
|
||
'workbench.asset.add': 'Add asset',
|
||
'workbench.asset.todoTitle': 'Build the asset list with image prompts',
|
||
'workbench.asset.todoBody': 'The Assets agent combines script, style and storyboard into copy-ready prompts for characters/locations/props.',
|
||
'workbench.asset.generate': 'Draft the asset list',
|
||
'workbench.asset.generateImage': 'Generate image',
|
||
'workbench.asset.generateHint': 'Generate with the connected ComfyUI workflow; results return to this project',
|
||
'workbench.asset.summary': '{n} assets',
|
||
'workbench.vshot.noPh': 'Shot no., e.g. S1',
|
||
'workbench.vshot.descPh': 'Description of the shot',
|
||
'workbench.vshot.promptPh': 'Full video-model prompt (English)',
|
||
'workbench.vshot.promptLabel': 'Video prompt',
|
||
'workbench.vshot.remove': 'Remove shot',
|
||
'workbench.vshot.add': 'Add shot',
|
||
'workbench.vshot.todoTitle': 'Produce the shot-by-shot video script',
|
||
'workbench.vshot.todoBody': 'The Shot List agent turns the storyboard into prompts ready for video models.',
|
||
'workbench.vshot.generate': 'Draft the shot list',
|
||
'workbench.vshot.generateVideo': 'Generate shot video',
|
||
'workbench.vshot.generateHint': 'Generate with the connected ComfyUI video workflow; results return to this project',
|
||
'workbench.vshot.summary': '{n} shots',
|
||
'home.errScriptShort': 'The script looks too short — check the paste is complete (min 30 characters)',
|
||
'home.stageProgress': 'Five-stage progress',
|
||
'tasks.sourceWorkbench': 'Creation flow',
|
||
'jobst.idSuffix': ' · ComfyUI prompt ID {id}',
|
||
'jobst.done': 'Done',
|
||
'jobst.doneDetail': 'ComfyUI finished and the results are saved',
|
||
'jobst.dryRun': 'Placeholder',
|
||
'jobst.dryRunDetail': 'Placeholder only: Dry-run is on, ComfyUI was not called',
|
||
'jobst.noOutput': 'No output',
|
||
'jobst.noOutputDetail': 'The job ended without any result file — not a finished generation',
|
||
'jobst.missing': 'Files missing',
|
||
'jobst.missingDetail': 'The task succeeded, but its result files are no longer on the server',
|
||
'jobst.queued': 'Queued',
|
||
'jobst.queuedDetail': 'Waiting in the workbench queue to be sent to ComfyUI',
|
||
'jobst.connecting': 'Connecting',
|
||
'jobst.connectingDetail': 'Connecting to ComfyUI and uploading inputs',
|
||
'jobst.comfyQueued': 'Accepted',
|
||
'jobst.comfyQueuedDetail': 'ComfyUI accepted the job and queued it',
|
||
'jobst.comfyQueuedAhead': 'ComfyUI accepted the job — {n} ahead in its queue',
|
||
'jobst.comfyRunning': 'Running',
|
||
'jobst.comfyRunningDetail': 'ComfyUI is running the job',
|
||
'jobst.saving': 'Saving',
|
||
'jobst.savingDetail': 'ComfyUI returned results, downloading them',
|
||
'jobst.failed': 'Failed',
|
||
'jobst.cancelled': 'Cancelled',
|
||
'studio.ratioLabel': 'Aspect ratio',
|
||
'studio.megapixelsLabel': 'Megapixels',
|
||
'studio.outputSize': 'Output {w} × {h}',
|
||
'studio.denoiseLabel': 'Denoise',
|
||
'studio.errNumber': '“{label}” must be a number',
|
||
'studio.errInteger': '“{label}” must be a whole number',
|
||
'studio.errMin': '“{label}” must be at least {v}',
|
||
'studio.errMax': '“{label}” must be at most {v}',
|
||
'studio.errOption': '“{label}” is not one of the workflow\'s options',
|
||
'studio.reuseParams': 'Reuse settings',
|
||
'studio.reusedToast': 'Settings from this job are filled in — adjust and generate again',
|
||
'studio.reuseMissingWf': 'The workflow this job used no longer exists',
|
||
'studio.doneToast': 'Done: {n} file(s) (ComfyUI prompt ID {id})',
|
||
'studio.dryRunToast': 'Placeholder only: Dry-run is on, ComfyUI was not called',
|
||
'studio.dryRunNote': 'Dry-run is on: Generate only writes placeholder files and never calls ComfyUI. Turn it off in Settings.',
|
||
// --- HEL-643: workflow import check / real test / media groups ---
|
||
'studio.errVideoFormat': '"{name}" is not a supported video format — use MP4 / WebM / MOV',
|
||
'studio.errAudioFormat': '"{name}" is not a supported audio format — use MP3 / WAV / M4A',
|
||
'studio.errMediaSize': '"{name}" exceeds the size limit — compress it first',
|
||
'studio.errNeedRefMedia': '"{label}" needs at least {n} clips',
|
||
'studio.refHintMedia': 'Required · 1–{max} clips · {n} selected',
|
||
'studio.refAddMedia': 'Add {kind}',
|
||
'studio.refAddSubMedia': '{n} more · max {max}',
|
||
'studio.refRemoveMedia': 'Remove {kind} {n}',
|
||
'studio.refFullMedia': 'Limit of {max} clips reached — remove one to add another',
|
||
'wfMedia.h3Limits': 'MiniMax H3 Ref2VA official limits: up to 9 reference images, 3 reference videos and 3 reference audios; each clip 2–15s with video/audio totals ≤15s each; audio cannot be the only reference; at most 12 reference files in total.',
|
||
'wfMedia.h3TotalOver': '{n} reference files selected — above the official cap of 12; generation may fail',
|
||
'wfMedia.h3AudioAlone': 'Audio cannot be the only reference — add at least one reference image or video',
|
||
'conn.wfCheckTitle': 'Connection compatibility check',
|
||
'conn.wfCheckEndpoint': 'Target: {name}',
|
||
'conn.wfCheckBtn': 'Re-check',
|
||
'conn.wfChecking': 'Checking…',
|
||
'conn.wfCheckOk': 'This connection has the nodes and models this workflow needs',
|
||
'conn.wfCheckProblems': '{n} missing node(s)/model(s) found',
|
||
'conn.wfCheckUnreachable': 'Cannot verify (ComfyUI unreachable) — saving stays possible; re-check after fixing the connection',
|
||
'conn.wfCheckSaveHint': 'You can still save the draft (it is not marked generatable); install the missing pieces and re-check.',
|
||
'conn.wfTestBtn': 'Test',
|
||
'conn.wfLastTest': 'Last test',
|
||
'conn.wfTestPassed': '{time} passed ({n} files)',
|
||
'conn.wfTestRunning': '{time} running',
|
||
'conn.wfTestFailed': '{time} failed',
|
||
'wft.title': 'Test workflow',
|
||
'wft.connection': 'Target connection',
|
||
'wft.costNote': 'A test submits one real job to the selected ComfyUI and uses its VRAM and queue time.',
|
||
'wft.submit': 'Start test',
|
||
'wft.confirmTitle': 'Confirm a real run',
|
||
'wft.confirmBody': 'One real job will be submitted to "{endpoint}" ({n} jobs in queue). The test only passes when at least one downloadable output of the right media type comes back.',
|
||
'wft.running': 'Testing…',
|
||
'wft.cancel': 'Cancel test',
|
||
'wft.passed': 'Test passed: {n} file(s) produced',
|
||
'wft.passedShort': 'Passed ({n} files)',
|
||
'wft.failed': 'Test failed',
|
||
'wft.failedShort': 'Failed',
|
||
'wft.cancelledShort': 'Cancelled',
|
||
'wft.reusedToast': 'A test is already running for this workflow — attached to it',
|
||
'wft.history': 'Test records ({n})',
|
||
'wft.clear': 'Clear test records',
|
||
'wft.cleared': 'Test records cleared',
|
||
'wft.never': 'Never tested',
|
||
'wft.download': 'Download',
|
||
'wft.errRequired': 'Please fill in "{label}"',
|
||
'wft.errListMin': '"{label}" needs at least {n} {unit}',
|
||
'tasks.testBadge': 'Test',
|
||
'tasks.sourceWorkflowTest': 'Workflow test',
|
||
// --- 生成台 (HEL-653) ---
|
||
'cdf.orig': 'Original {v}',
|
||
'desk.title': 'Generate',
|
||
'desk.advanced': 'Advanced · {n} · untouched ones keep the workflow values',
|
||
'desk.chipResolution': 'Resolution {v}',
|
||
'desk.chipSeconds': '{v}s',
|
||
'desk.chipSeed': 'Seed {v}',
|
||
'desk.closeInspector': 'Close inspector',
|
||
'desk.countActive': '{n} running',
|
||
'desk.countTakes': '{n} takes',
|
||
'desk.ctxAsset': '{kind} “{name}”',
|
||
'desk.ctxShot': 'Shot {no}',
|
||
'desk.ctxBack': 'Back to {stage}',
|
||
'desk.ctxDismiss': 'Dismiss source note',
|
||
'desk.ctxFrom': 'From “{project}”',
|
||
'desk.ctxNoBackfill': 'Results stay in the desk feed and are not filled back into {stage}',
|
||
'desk.dayDate': '{m}/{d}',
|
||
'desk.download': 'Download',
|
||
'desk.dropNoSlot': '{n} file(s) have no slot: this workflow has no input of that kind',
|
||
'desk.dryRun': 'Dry run',
|
||
'desk.durMin': '{m}m {s}s',
|
||
'desk.durSec': '{s}s',
|
||
'desk.elapsed': 'Time',
|
||
'desk.emptyFailed': 'No failed takes',
|
||
'desk.emptyFeed': 'No takes yet. Write a prompt below and press Generate.',
|
||
'desk.filterAria': 'Filter takes',
|
||
'desk.filterAll': 'All',
|
||
'desk.filterImage': 'Images',
|
||
'desk.filterVideo': 'Videos',
|
||
'desk.filterFailed': 'Failed',
|
||
'desk.generate': 'Generate',
|
||
'desk.genHint': 'Generate (Ctrl/⌘ + Enter)',
|
||
'desk.inputs': 'Inputs',
|
||
'desk.inspector': 'Inspector',
|
||
'desk.keyClose': 'Close',
|
||
'desk.keyInspector': 'Show / hide',
|
||
'desk.keySelect': 'Select',
|
||
'desk.keyUse': 'Use',
|
||
'desk.kvCreated': 'Submitted',
|
||
'desk.kvName': 'Name',
|
||
'desk.kvPromptId': 'ComfyUI prompt id',
|
||
'desk.kvUsage': 'Usage',
|
||
'desk.loadEarlier': 'Show {n} earlier takes',
|
||
'desk.missingSub': 'Redo with the same params, or remove this take',
|
||
'desk.missingTitle': 'The result files are no longer on the server',
|
||
'desk.needWorkflow': 'Missing: workflow',
|
||
'desk.noConn': 'Not connected',
|
||
'desk.noPromptInput': 'This workflow takes no prompt; it runs with its own values.',
|
||
'desk.notGenerated': 'Not generated',
|
||
'desk.noWorkflows': 'No image or video workflow is ready yet',
|
||
'desk.openInDesk': 'Tune in desk',
|
||
'desk.openInDeskHint': 'Open the desk with this prompt and pick the workflow and params yourself; results stay in the desk feed',
|
||
'desk.openInspector': 'Inspector',
|
||
'desk.origValue': 'Workflow value',
|
||
'desk.outputN': 'Result {n}',
|
||
'desk.outputs': 'All results',
|
||
'desk.paramError': 'Invalid parameter: {msg}',
|
||
'desk.paramsAll': 'All params',
|
||
'desk.paramsChanged': 'Params · {n} changed',
|
||
'desk.paramsCommon': 'Common params',
|
||
'desk.pickTake': 'Pick a take in the feed to see its result',
|
||
'desk.pickWorkflow': 'Choose workflow',
|
||
'desk.promptOnly': 'Prompt only',
|
||
'desk.promptPh': 'Describe the shot… (Ctrl/⌘ + Enter to generate, / to focus)',
|
||
'desk.restoreAll': 'Restore all workflow values',
|
||
'desk.redo': 'Redo with same params',
|
||
'desk.removeRecord': 'Remove record',
|
||
'desk.restoreOrig': 'Restore original',
|
||
'desk.reuse': 'Reuse',
|
||
'desk.reuseToComposer': 'Reuse in composer',
|
||
'desk.seedRandom': 'Random',
|
||
'desk.sendToSlot': 'Send to image slot',
|
||
'desk.sent': 'Submitted',
|
||
'desk.sentToSlotToast': 'Sent to the current workflow’s image slot',
|
||
'desk.slotOne': '{label} ×1',
|
||
'desk.slotRange': '{label} {min}–{max}',
|
||
'desk.specSize': 'Size',
|
||
'desk.stillNeed': 'Missing: {what}',
|
||
'desk.tabParams': 'Params',
|
||
'desk.tabResult': 'Result',
|
||
'desk.today': 'Today',
|
||
'desk.took': 'Took {d}',
|
||
'desk.wfBroken': 'Unavailable',
|
||
'desk.wfCurrent': 'current',
|
||
'desk.wfDefaultConn': 'Default connection',
|
||
'desk.wfImport': 'Import / manage workflows',
|
||
'desk.wfLastFailed': 'Last run failed',
|
||
'desk.wfNoMatch': 'No matching workflow',
|
||
'desk.wfOk': 'Ready',
|
||
'desk.wfSearchPh': 'Search workflows or a usage: image to video, reference…',
|
||
'desk.wfTesting': 'Test running',
|
||
'desk.wfUntested': 'Not tested',
|
||
'desk.workflow': 'Workflow',
|
||
'desk.yesterday': 'Yesterday',
|
||
'wfd.stepParse': 'Parse JSON',
|
||
'wfd.stepNodes': 'Identify nodes',
|
||
'wfd.stepModels': 'Verify models',
|
||
'wfd.stepSlots': 'Build input slots',
|
||
'wfd.noOutput': 'The workflow has no output node — cannot import',
|
||
'wfd.nodesAutoOk': 'Usage auto-detected: {usage}',
|
||
'wfd.nodesUserOk': 'Usage confirmed: {usage}',
|
||
'wfd.modelsOk': '"{name}" has all required nodes and models',
|
||
'wfd.slotsOk': '{n} input slot(s) built ({m} media)',
|
||
'wfd.checksAria': 'Import check results',
|
||
'wfd.showDetails': 'Show error details',
|
||
'wfd.hideDetails': 'Hide error details',
|
||
'wfd.unreachableSuggest': 'Being unverifiable does not block saving; re-check after fixing the connection.',
|
||
'wfd.nodesPickSuggest': 'Pick the usage and finish the output mapping below before saving.',
|
||
'wfd.showRaw': 'View raw JSON',
|
||
'wfd.hideRaw': 'Hide raw JSON',
|
||
};
|
||
|
||
export type Dict = typeof en;
|