From 9ef9453ecb1fd823ad3697414c5e684706cd7440 Mon Sep 17 00:00:00 2001 From: The Muse Date: Thu, 6 Aug 2026 22:05:38 -0400 Subject: [PATCH] feat: complete english localization --- client/src/api/character.ts | 4 +- client/src/api/client.ts | 8 +- client/src/api/creativeHub.ts | 2 +- client/src/api/drama.ts | 13 +- client/src/api/novel/production.ts | 13 +- .../assetLibrary/AssetLibrarySection.tsx | 2 +- .../assetLibrary/AssetLibraryStatusGrid.tsx | 2 +- .../src/components/autoDirector/AICockpit.tsx | 162 ++++----- .../AutoDirectorApprovalPointMultiSelect.tsx | 10 +- .../AutoDirectorApprovalStrategyPanel.tsx | 20 +- .../DirectorBookAutomationCard.tsx | 4 +- .../DirectorRuntimeProjectionCard.tsx | 122 ++----- .../CharacterConversationWorkbench.tsx | 28 +- .../components/comic/GeneratedImageCard.tsx | 20 +- .../components/common/AiRevisionWorkspace.tsx | 20 +- .../src/components/common/FullscreenView.tsx | 4 +- client/src/components/common/LLMSelector.tsx | 22 +- .../components/common/SearchableSelect.tsx | 6 +- .../src/components/common/SelectControl.tsx | 2 +- client/src/components/common/SelectField.tsx | 4 +- client/src/components/common/StreamOutput.tsx | 10 +- .../creativeHub/OpenInCreativeHubButton.tsx | 13 +- .../image/ImageGenerationConfirmDialog.tsx | 126 +++---- .../knowledge/KnowledgeBindingPanel.tsx | 6 +- .../knowledge/KnowledgeDocumentPicker.tsx | 32 +- .../src/components/layout/AppVersionBadge.tsx | 6 +- .../layout/DesktopBootstrapShell.tsx | 124 +++---- .../layout/DesktopLegacyDataImportCard.tsx | 26 +- .../components/layout/DesktopUpdateCard.tsx | 4 +- .../components/layout/DesktopUpdateDialog.tsx | 4 +- .../components/layout/DesktopUpdatePanel.tsx | 30 +- client/src/components/layout/Navbar.tsx | 4 +- .../components/layout/NovelWorkspaceRail.tsx | 62 ++-- .../components/layout/ProjectGithubLink.tsx | 4 +- .../components/layout/ServerStartupGate.tsx | 10 +- client/src/components/layout/Sidebar.tsx | 58 ++-- .../components/layout/TaskRecoveryContext.tsx | 8 +- .../components/layout/TaskRecoveryDialog.tsx | 34 +- .../layout/desktopUpdaterPresentation.ts | 46 +-- .../layout/mobile/MobileSiteShell.tsx | 16 +- .../layout/mobile/mobileSiteNavigation.ts | 104 +++--- .../liveExecution/LiveExecutionDialog.tsx | 50 +-- .../onboarding/CreationSetupNotice.tsx | 6 +- .../onboarding/FirstNovelJourneyStrip.tsx | 4 +- .../components/onboarding/OnboardingTip.tsx | 4 +- .../onboarding/QuickSetupDialog.tsx | 102 +++--- .../taskQueue/TaskQueuePrimitives.tsx | 4 +- .../taskQueue/TaskQueueSemantic.tsx | 6 +- .../TensionCurveBeatContextStrip.tsx | 12 +- .../TensionCurveChapterDetailSidebar.tsx | 22 +- .../tensionCurve/TensionCurveEditDialog.tsx | 26 +- .../tensionCurve/TensionCurveNodes.tsx | 52 +-- .../tensionCurve/TensionCurvePanel.tsx | 20 +- .../TensionCurveVolumeContextBar.tsx | 14 +- .../tensionCurve/tensionCurveAnalysis.ts | 10 +- client/src/components/ui/dialog.tsx | 2 +- client/src/components/ui/toast.tsx | 2 +- .../visualAssets/VisualAssetDetails.tsx | 34 +- .../visualAssets/VisualAssetGrid.tsx | 2 +- .../visualAssets/VisualAssetLibrary.tsx | 85 +---- .../visualAssets/VisualAssetLibraryDialog.tsx | 4 +- .../visualAssets/visualAssetLibrary.labels.ts | 43 +-- .../workflow/AITakeoverContainer.tsx | 22 +- .../workspace/WorkspaceNextAction.tsx | 4 +- .../hooks/useDirectorChapterTitleRepair.ts | 8 +- client/src/hooks/useLlmLiveFeed.ts | 8 +- client/src/hooks/useSSE.ts | 2 +- .../src/lib/autoDirectorPauseNotifications.ts | 2 +- client/src/lib/desktop.ts | 6 +- client/src/lib/directorTaskNotice.ts | 12 +- client/src/lib/novelWorkflowActivityTags.ts | 14 +- client/src/lib/novelWorkflowContinuation.ts | 8 +- client/src/lib/novelWorkflowTaskUi.ts | 26 +- client/src/lib/textFile.ts | 2 +- client/src/pages/Home.tsx | 22 +- .../src/pages/antiAiRules/AntiAiRulesPage.tsx | 32 +- .../antiAiRules/antiAiRulesPage.shared.ts | 12 +- .../components/AntiAiEffectivePreviewCard.tsx | 28 +- .../components/AntiAiRuleDialog.tsx | 68 ++-- .../components/AntiAiRuleEffectTestCard.tsx | 42 +-- .../antiAiRules/components/AntiAiRuleList.tsx | 48 +-- .../components/AntiAiRuleStats.tsx | 8 +- .../components/EffectiveRuleList.tsx | 2 +- client/src/pages/astrology/AstrologyPage.tsx | 6 +- .../AutoDirectorFollowUpCenterPage.tsx | 56 ++-- .../AutoDirectorFollowUpBatchBar.tsx | 22 +- .../components/AutoDirectorFollowUpDetail.tsx | 83 ++--- .../components/AutoDirectorFollowUpList.tsx | 108 +++--- .../AutoDirectorFollowUpOverview.tsx | 41 +-- .../followUpPresentation.ts | 54 ++- .../pages/bookAnalysis/BookAnalysisPage.tsx | 59 ++-- .../pages/bookAnalysis/bookAnalysis.utils.ts | 28 +- .../bookAnalysisWorkspaceViewModel.ts | 64 ++-- .../BookAnalysisBudgetAdjustDialog.tsx | 46 +-- .../BookAnalysisChapterNavigator.tsx | 10 +- .../components/BookAnalysisChapterReader.tsx | 14 +- .../BookAnalysisCharacterAppearancePanel.tsx | 96 +++--- .../BookAnalysisCharacterCandidateCard.tsx | 8 +- .../BookAnalysisCharacterImagePanel.tsx | 62 ++-- .../components/BookAnalysisCharacterPanel.tsx | 77 ++--- .../components/BookAnalysisCreateDialog.tsx | 87 +++-- .../components/BookAnalysisDetailPanel.tsx | 92 +++--- .../BookAnalysisDiagnosisTipBanner.tsx | 6 +- .../components/BookAnalysisSectionCard.tsx | 72 ++-- .../components/BookAnalysisSidebar.tsx | 40 ++- .../BookAnalysisSourceRangePicker.tsx | 62 ++-- .../BookAnalysisStructuredSummary.tsx | 14 +- .../BookAnalysisWorkbenchViewTabs.tsx | 8 +- .../BookAnalysisWorkspaceToolbar.tsx | 44 +-- .../hooks/actions/useAnalysisBudget.ts | 8 +- .../hooks/actions/useAnalysisPublishing.ts | 8 +- .../hooks/useBookAnalysisWorkspace.ts | 16 +- .../characters/components/CharacterCard.tsx | 68 ++-- .../components/CharacterCreateDialog.tsx | 98 +++--- .../components/CharacterEditDialog.tsx | 30 +- .../components/CharacterImageDialog.tsx | 80 ++--- client/src/pages/chat/ChatPage.tsx | 92 +++--- .../chat/components/AssistantChatPanel.tsx | 42 +-- .../pages/chat/components/RuntimeSidebar.tsx | 114 +++---- .../comic/ComicImageGenerationNotice.tsx | 4 +- client/src/pages/comic/ComicProjectPage.tsx | 84 ++--- client/src/pages/comic/ComicWorkspacePage.tsx | 244 +++----------- .../pages/comic/project/CharactersPanel.tsx | 276 ++++++++-------- .../pages/comic/project/EpisodeListPanel.tsx | 112 +++---- .../pages/comic/project/PanelsGridPanel.tsx | 143 ++++---- .../src/pages/comic/project/ScenesPanel.tsx | 82 +++-- .../src/pages/creativeHub/CreativeHubPage.tsx | 43 ++- .../components/CreativeHubConversation.tsx | 28 +- .../components/CreativeHubDebugTraceCard.tsx | 16 +- .../components/CreativeHubInlineToolCall.tsx | 52 ++- .../CreativeHubMessagePrimitives.tsx | 30 +- .../components/CreativeHubNovelSetupCard.tsx | 60 ++-- .../components/CreativeHubSidebar.tsx | 190 +++++------ .../components/CreativeHubThreadList.tsx | 32 +- .../components/CreativeHubToolResultCard.tsx | 154 ++++----- .../components/CreativeHubTurnSummaryCard.tsx | 26 +- .../components/NovelProductionStarterCard.tsx | 176 +++++----- .../hooks/useCreativeHubRuntime.ts | 6 +- .../lib/creativeHubSyntheticMessages.ts | 48 +-- .../pages/creativeHub/lib/plannerLabels.ts | 38 +-- .../creativeHubWorkspaceViewModel.ts | 104 +++--- client/src/pages/drama/DramaProjectPage.tsx | 194 +++++------ client/src/pages/drama/DramaWorkspacePage.tsx | 146 ++++---- .../drama/components/DramaCharactersPanel.tsx | 88 ++--- .../components/DramaEpisodeAudioPanel.tsx | 50 +-- .../drama/components/DramaNextStepPanel.tsx | 58 ++-- .../drama/components/DramaQualityPanel.tsx | 90 ++--- .../drama/components/DramaSourcePanel.tsx | 78 ++--- .../drama/components/DramaVisualPanel.tsx | 185 ++++------- client/src/pages/drama/dramaDisplay.ts | 24 +- .../src/pages/genres/GenreManagementPage.tsx | 86 ++--- .../genres/components/GenreCreateDialog.tsx | 36 +- .../genres/components/GenreEditDialog.tsx | 22 +- .../genres/components/GenreTreeEditor.tsx | 22 +- .../pages/genres/components/GenreTreeItem.tsx | 20 +- client/src/pages/help/HelpPage.tsx | 44 +-- .../pages/home/components/HomeAssetHealth.tsx | 2 +- .../home/components/HomeAttentionQueue.tsx | 4 +- .../home/components/HomeNextActionPanel.tsx | 36 +- .../home/components/HomeRecentNovels.tsx | 22 +- .../pages/home/components/HomeStatusStrip.tsx | 2 +- client/src/pages/home/homeViewModel.ts | 101 +++--- client/src/pages/knowledge/KnowledgePage.tsx | 32 +- .../KnowledgeDocumentDetailDialog.tsx | 52 +-- .../components/KnowledgeDocumentsTab.tsx | 106 +++--- .../KnowledgeEmbeddingSettingsCard.tsx | 170 +++++----- .../components/KnowledgeLibraryOverview.tsx | 82 ++--- .../knowledge/components/KnowledgeOpsTab.tsx | 36 +- .../knowledge/components/knowledgeRagUi.ts | 16 +- client/src/pages/novels/NovelChapterEdit.tsx | 6 +- client/src/pages/novels/NovelCreate.tsx | 16 +- client/src/pages/novels/NovelEdit.tsx | 311 +++++------------- client/src/pages/novels/NovelList.tsx | 34 +- client/src/pages/novels/NovelPreview.tsx | 106 +++--- .../autoDirector/AutoDirectorCreatePage.tsx | 18 +- .../novels/autoDirector/StageBasicSetup.tsx | 68 ++-- .../novels/autoDirector/StageCandidates.tsx | 16 +- .../pages/novels/autoDirector/StageIdea.tsx | 26 +- .../novels/autoDirector/StageModelRun.tsx | 48 +-- .../novels/autoDirector/StageWorldStyle.tsx | 65 ++-- .../autoDirector/directorCreateStages.ts | 20 +- .../useAutoDirectorCreateController.ts | 26 +- .../novels/chapterDetailPlanning.shared.ts | 6 +- .../pages/novels/chapterPlanning.shared.ts | 4 +- .../pages/novels/components/BasicInfoTab.tsx | 16 +- .../components/BookPayoffLedgerCard.tsx | 84 ++--- .../ChapterExecutionActionPanel.tsx | 136 ++++---- .../components/ChapterExecutionQueueCard.tsx | 28 +- .../ChapterExecutionResultPanel.tsx | 48 ++- .../components/ChapterExecutionStatusFlow.tsx | 4 +- .../components/ChapterManagementTab.tsx | 32 +- .../components/ChapterRuntimePanels.tsx | 112 +++---- .../components/CharacterAssetSidebar.tsx | 40 +-- .../components/CharacterAssetWorkspace.tsx | 32 +- .../CharacterCastOptionsSection.tsx | 186 +++++------ .../components/CharacterDynamicsSection.tsx | 90 ++--- .../components/CharacterFocusSummary.tsx | 26 +- .../novels/components/CollapsibleSummary.tsx | 4 +- .../components/DirectorFactDebugDialog.tsx | 120 +++---- .../components/DirectorTakeoverEntryPanel.tsx | 4 +- .../NovelAutoDirectorCandidateBatches.tsx | 82 ++--- .../NovelAutoDirectorDialog.shared.ts | 6 +- .../NovelAutoDirectorIdeaInspirationPanel.tsx | 10 +- .../NovelAutoDirectorProgressPanel.tsx | 156 ++++----- .../novels/components/NovelBasicInfoForm.tsx | 138 ++++---- .../novels/components/NovelCharacterPanel.tsx | 4 +- .../NovelCreateResourceRecommendationCard.tsx | 36 +- .../NovelDirectorPreparationJourney.tsx | 36 +- .../pages/novels/components/NovelEditView.tsx | 76 ++--- .../NovelExistingProjectTakeoverDialog.tsx | 112 +++---- .../NovelProductionExperienceHandoff.tsx | 46 +-- .../NovelStyleRecommendationCard.tsx | 80 ++--- .../novels/components/NovelTaskDrawer.tsx | 206 ++++++------ .../NovelWorkflowRunningIndicator.tsx | 2 +- .../components/NovelWorldManagerCard.tsx | 112 +++---- .../novels/components/NovelWorldUsageCard.tsx | 138 ++++---- .../pages/novels/components/OutlineTab.tsx | 228 ++++++------- .../pages/novels/components/PipelineTab.tsx | 206 ++++++------ .../components/StoryMacroPlanTab.shared.tsx | 28 +- .../novels/components/StoryMacroPlanTab.tsx | 92 +++--- .../components/StructuredBeatSheetCard.tsx | 44 +-- .../StructuredChapterDetailCard.tsx | 96 +++--- .../components/StructuredChapterListCard.tsx | 78 ++--- .../components/StructuredOutlineWorkspace.tsx | 137 +++----- .../novels/components/VersionHistoryTab.tsx | 30 +- .../components/VolumePayoffOverviewCard.tsx | 48 +-- .../novels/components/WorldInjectionHint.tsx | 4 +- .../pages/novels/components/WorldSetupTab.tsx | 8 +- .../basicInfoForm/BasicInfoFormPrimitives.tsx | 4 +- .../BookFramingQuickFillButton.tsx | 12 +- .../basicInfoForm/BookFramingSection.tsx | 36 +- .../basicInfoForm/BookPositioningStudio.tsx | 66 ++-- .../ContinuationSourceSection.tsx | 48 +-- .../components/chapterEditor/AIDiffPanel.tsx | 52 +-- .../ChapterEditorDirectorPanel.tsx | 94 +++--- .../chapterEditor/ChapterEditorShell.tsx | 36 +- .../chapterEditor/ChapterEditorSidebar.tsx | 97 ++---- .../chapterEditor/ChapterTextEditor.tsx | 18 +- .../SelectionAIFloatingToolbar.tsx | 18 +- .../chapterEditor/chapterEditorUtils.ts | 20 +- .../components/chapterExecution.shared.tsx | 220 +++---------- .../ChapterExecutionInsightsSidebar.tsx | 36 +- .../ChapterExecutionOverviewPanel.tsx | 30 +- .../ChapterExecutionReferencePanel.tsx | 92 +++--- .../CharacterDynamicsPanel.tsx | 32 +- .../chapterInsights/ResourceRiskPanel.tsx | 80 ++--- .../chapterInsights/TimelinePanel.tsx | 66 ++-- .../characterAssetWorkspace.helpers.ts | 25 +- .../novels/components/characterPanel.utils.ts | 32 +- .../characterPanel/CharacterCreateDialog.tsx | 56 ++-- .../CharacterPreparationHero.tsx | 38 +-- .../SupplementalCharacterDialog.tsx | 126 +++---- .../characterPanel/characterPanel.labels.ts | 30 +- .../CharacterDialogueStage.tsx | 56 ++-- .../CharacterIntelligenceTab.tsx | 8 +- .../CharacterMindSceneAnalysis.tsx | 27 +- .../CharacterOverviewTab.tsx | 61 ++-- .../CharacterProfileTab.tsx | 40 +-- .../CharacterRelationshipGraphPanel.tsx | 114 +++---- .../CharacterResourceTab.tsx | 18 +- .../CharacterTimelineTab.tsx | 16 +- .../CharacterVisibleProfileTab.tsx | 40 +-- .../characterRelationshipGraphModel.ts | 14 +- .../characterWorkspace.helpers.ts | 72 ++-- .../components/cover/NovelCoverCard.tsx | 35 +- .../components/cover/NovelCoverDialog.tsx | 123 ++++--- .../components/cover/novelCoverDraft.ts | 27 +- .../directorAutoExecutionPlan.shared.tsx | 74 ++--- .../components/list/NovelListEmptyState.tsx | 10 +- .../components/list/NovelListFilterBar.tsx | 16 +- .../components/list/NovelListHeader.tsx | 18 +- .../components/list/NovelListPagination.tsx | 16 +- .../components/list/NovelProjectCard.tsx | 40 +-- .../components/list/novelListViewModel.ts | 99 +----- .../novelExistingProjectTakeoverViewModel.ts | 90 ++--- .../novelWorld/NovelWorldHandbookDialog.tsx | 222 ++++--------- .../novelWorld/NovelWorldSourcePanel.tsx | 56 ++-- .../outline/OutlineCurrentVolumeWorkspace.tsx | 100 +++--- .../outline/OutlineResourceCommitments.tsx | 30 +- .../novels/components/pipelineTab.utils.ts | 14 +- .../storyMacroPlan/StoryEngineStudio.tsx | 84 ++--- .../novels/components/storylineView.utils.ts | 40 +-- .../TakeoverChapterTargetSelector.tsx | 6 +- .../takeover/TakeoverContextSummaryPanel.tsx | 6 +- .../takeover/TakeoverDiagnosisPanel.tsx | 14 +- .../TakeoverProgressInspectionPanel.tsx | 6 +- .../NovelCreateTitleQuickFill.tsx | 90 ++--- .../titleWorkshop/NovelTitleWorkshop.tsx | 20 +- .../useNovelAutoDirectorCandidateMutations.ts | 16 +- .../hooks/useChapterExecutionActions.ts | 66 ++-- .../hooks/useNovelCharacterMutations.ts | 42 +-- .../hooks/useNovelEditChapterRuntime.ts | 42 +-- .../novels/hooks/useNovelEditMutations.ts | 28 +- .../pages/novels/hooks/useNovelStoryMacro.ts | 18 +- .../hooks/useNovelVolumePlanning.actions.ts | 28 +- .../useNovelVolumePlanning.chapterDetail.ts | 26 +- .../useNovelVolumePlanning.generation.ts | 46 +-- .../novels/hooks/useNovelVolumePlanning.ts | 22 +- .../hooks/useNovelVolumePlanning.utils.ts | 6 +- .../pages/novels/hooks/useNovelWorldSlice.ts | 18 +- .../hooks/useStorylineVersionControl.ts | 32 +- .../novels/hooks/useVolumeVersionControl.ts | 40 +-- .../mobile/MobileAutoDirectorStatusCard.tsx | 12 +- .../novels/mobile/MobileNovelEditView.tsx | 42 +-- .../novels/mobile/MobileNovelStepNav.tsx | 6 +- .../mobile/mobileNovelWorkspaceUtils.ts | 20 +- .../src/pages/novels/novelBasicInfo.shared.ts | 212 ++---------- .../pages/novels/novelEditTakeover.shared.ts | 34 +- .../pages/novels/novelWorkspaceNavigation.ts | 20 +- .../SimpleCreationMaterialsPanel.tsx | 42 +-- .../simpleCreation/SimpleNovelShelfPage.tsx | 89 ++--- .../pages/novels/structuredOutline.utils.ts | 2 +- .../novels/structuredOutlineSync.utils.ts | 20 +- client/src/pages/novels/volumePlan.utils.ts | 39 ++- .../promptWorkbench/PromptWorkbenchPage.tsx | 24 +- .../AdvancedPromptTemplateEditor.tsx | 68 ++-- .../components/ContextInjectionPanel.tsx | 36 +- .../components/PromptBodyEditor.tsx | 94 +++--- .../components/PromptCatalogSidebar.tsx | 18 +- .../components/PromptEditorShell.tsx | 33 +- .../components/PromptPreviewPanel.tsx | 28 +- .../components/PromptRunBar.tsx | 38 +-- .../components/VisualTemplateEditor.tsx | 46 +-- .../hooks/usePromptDraftSlots.ts | 14 +- .../promptWorkbench/hooks/usePromptPreview.ts | 198 +++++------ .../hooks/usePromptSlotPersistence.ts | 8 +- .../promptWorkbench/promptWorkbenchLabels.ts | 153 +++------ .../AutoDirectorApprovalPreferenceCard.tsx | 12 +- ...irectorBrowserNotificationSettingsCard.tsx | 40 +-- .../AutoDirectorChannelSettingsCard.tsx | 30 +- ...DirectorPendingReviewAutoPromotionCard.tsx | 50 +-- .../settings/AutoDirectorSettingsSection.tsx | 12 +- .../src/pages/settings/ModelRouteFields.tsx | 28 +- client/src/pages/settings/ModelRoutesPage.tsx | 110 +++---- client/src/pages/settings/SettingsPage.tsx | 52 +-- .../settings/autoDirectorEventOptions.ts | 26 +- .../components/ProviderConfigDialog.tsx | 60 ++-- .../components/ProviderRequestLimitFields.tsx | 14 +- .../components/ProviderSettingsSection.tsx | 10 +- .../components/ProviderStatusCard.tsx | 68 ++-- .../components/SettingsMaintenanceSection.tsx | 16 +- .../components/SettingsNavigationCards.tsx | 36 +- .../components/SettingsReadinessCard.tsx | 48 +-- .../components/SettingsSectionGroup.tsx | 17 +- .../StyleEngineRuntimeSettingsCard.tsx | 53 ++- client/src/pages/settings/modelRouteLabels.ts | 44 +-- .../src/pages/settings/modelRoutes.utils.ts | 10 +- .../storyModes/StoryModeManagementPage.tsx | 128 ++++--- .../components/StoryModeProfileFields.tsx | 20 +- .../components/StoryModeTreeCard.tsx | 18 +- .../components/TaskCenterDetailPanel.tsx | 44 +-- .../components/TaskCenterDetailSummary.tsx | 44 +-- .../components/TaskCenterFilterPanel.tsx | 56 ++-- .../tasks/components/TaskCenterListPanel.tsx | 24 +- .../TaskCenterManualEditImpactCard.tsx | 30 +- .../components/TaskCenterMilestoneHistory.tsx | 4 +- .../TaskCenterRuntimePolicyCard.tsx | 40 +-- .../components/TaskCenterSummaryCards.tsx | 8 +- client/src/pages/tasks/taskCenterUtils.ts | 96 +++--- client/src/pages/titles/TitleStudioPage.tsx | 10 +- .../titles/components/TitleFactoryPanel.tsx | 84 ++--- .../titles/components/TitleLibraryPanel.tsx | 56 ++-- .../titles/components/TitleSuggestionList.tsx | 25 +- client/src/pages/titles/titleStudio.shared.ts | 10 +- client/src/pages/worlds/WorldGenerator.tsx | 38 +-- client/src/pages/worlds/WorldList.tsx | 64 ++-- client/src/pages/worlds/WorldWorkspace.tsx | 30 +- .../components/WorldVisualizationBoard.tsx | 74 ++--- .../generator/WorldGeneratorStepOne.tsx | 110 +++---- .../generator/WorldGeneratorStepThree.tsx | 42 +-- .../generator/WorldGeneratorStepTwo.tsx | 46 +-- .../generator/WorldLibraryQuickPick.tsx | 20 +- .../generator/WorldPropertyOptionSelector.tsx | 33 +- .../generator/WorldReferenceSeedSelector.tsx | 30 +- .../generator/worldGeneratorShared.ts | 24 +- .../components/workspace/WorldAssetsTab.tsx | 172 +++++----- .../components/workspace/WorldAxiomsCard.tsx | 12 +- .../workspace/WorldConsistencyTab.tsx | 50 +-- .../workspace/WorldDeepeningTab.tsx | 34 +- .../workspace/WorldHandbookEditor.tsx | 158 ++++----- .../components/workspace/WorldLayersTab.tsx | 40 +-- .../components/workspace/WorldOverviewTab.tsx | 125 ++++--- .../workspace/WorldStructureTab.tsx | 72 ++-- .../workspace/handbook/HandbookPrimitives.tsx | 2 +- .../handbook/WorldHandbookForceSection.tsx | 34 +- .../handbook/WorldHandbookLocationSection.tsx | 34 +- .../handbook/WorldHandbookRuleSection.tsx | 34 +- .../handbook/WorldHandbookTensionSection.tsx | 32 +- .../structure/WorldFactionsSection.tsx | 86 ++--- .../structure/WorldRelationsSection.tsx | 56 ++-- .../workspace/worldWorkspaceShared.ts | 47 ++- client/src/pages/worlds/worldConsistencyUi.ts | 98 +++--- .../writingFormula/WritingFormulaPage.tsx | 44 +-- .../WritingFormulaAdvancedWorkspace.tsx | 2 +- .../WritingFormulaBookStyleFlow.tsx | 32 +- .../components/WritingFormulaCleanFlow.tsx | 50 +-- .../components/WritingFormulaCleanPanel.tsx | 44 +-- .../components/WritingFormulaCreateDialog.tsx | 218 ++++++------ .../components/WritingFormulaEditorPanel.tsx | 200 ++++++----- .../components/WritingFormulaImitateFlow.tsx | 40 +-- .../components/WritingFormulaLanding.tsx | 138 ++++---- .../components/WritingFormulaRulesPanel.tsx | 14 +- .../WritingFormulaWorkbenchPanel.tsx | 74 ++--- .../useWritingFormulaCreateFlow.ts | 14 +- .../writingFormulaLandingItems.ts | 24 +- .../writingFormulaRulePresentation.ts | 160 ++++----- .../writingFormula/writingFormulaV2.shared.ts | 14 +- client/src/store/chatStore.ts | 2 +- 408 files changed, 9330 insertions(+), 11175 deletions(-) diff --git a/client/src/api/character.ts b/client/src/api/character.ts index e59a4fe05..3fd04737f 100644 --- a/client/src/api/character.ts +++ b/client/src/api/character.ts @@ -4,7 +4,7 @@ import type { BaseCharacter } from "@ai-novel/shared/types/novel"; import { apiClient } from "./client"; export interface CharacterGenerateConstraints { - storyFunction?: "主角" | "反派" | "导师" | "对照组" | "配角"; + storyFunction?: "main character" | "Villain" | "tutor" | "control group" | "supporting role"; externalGoal?: string; internalNeed?: string; coreFear?: string; @@ -12,7 +12,7 @@ export interface CharacterGenerateConstraints { secret?: string; coreFlaw?: string; relationshipHooks?: string; - growthStage?: "起点" | "受挫" | "转折" | "觉醒" | "收束"; + growthStage?: "starting point" | "frustrated" | "turning point" | "Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know." | "Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know."; toneStyle?: string; } diff --git a/client/src/api/client.ts b/client/src/api/client.ts index 4abdd0890..a8ed6dd30 100644 --- a/client/src/api/client.ts +++ b/client/src/api/client.ts @@ -31,19 +31,19 @@ apiClient.interceptors.response.use( const backendError = error.response?.data?.error; const backendMessage = error.response?.data?.message; const silentErrorStatuses = error.config?.silentErrorStatuses ?? []; - let title = backendError ?? error.message ?? "请求失败。"; + let title = backendError ?? error.message ?? "The request failed."; let description = backendMessage && backendMessage !== backendError ? backendMessage : undefined; if (!status) { - title = "网络连接失败,请检查网络后重试。"; + title = "Network connection failed, please check the network and try again."; description = undefined; } else if (status >= 500) { - title = backendError ?? "服务器错误,请稍后重试。"; + title = backendError ?? "Server error, please try again later."; description = backendMessage && backendMessage !== title ? backendMessage : undefined; } if (!status || !silentErrorStatuses.includes(status)) { - const isGenericServerErrorToast = title === "服务器错误,请稍后重试。"; + const isGenericServerErrorToast = title === "Server error, please try again later."; if (description) { toast.error( diff --git a/client/src/api/creativeHub.ts b/client/src/api/creativeHub.ts index ee6a01ecd..cf42223b2 100644 --- a/client/src/api/creativeHub.ts +++ b/client/src/api/creativeHub.ts @@ -12,7 +12,7 @@ import { apiClient } from "./client"; function ensureThreadId(threadId: string): string { const normalized = threadId.trim(); if (!normalized) { - throw new Error("创作中枢线程不存在,请先创建线程。"); + throw new Error("The creation hub thread does not exist, please create a thread first."); } return normalized; } diff --git a/client/src/api/drama.ts b/client/src/api/drama.ts index dd6b281c0..5ab38d5d3 100644 --- a/client/src/api/drama.ts +++ b/client/src/api/drama.ts @@ -570,18 +570,7 @@ export async function downloadDramaEpisodeExport(id: string, order: number, form // ───────────────────────────────────────────────────────────────────────────── export async function getDramaCharacterImageStatus(id: string, characterId: string) { - const { data } = await apiClient.get>( - `/drama/projects/${id}/characters/${characterId}/image-status`, - ); - return data; -} - -/** 生成角色设计稿(面部特写 + 三视图合图,推荐使用) */ -export async function prepareDramaCharacterSheet( - id: string, - characterId: string, - provider?: string, -): Promise> { + const { data } = await apiClient.get>( `/drama/projects/${id}/characters/${characterId}/image-status`, ); return data; } /** Generate character design drafts (facial close-up + three-view composite image, recommended) */ export async function prepareDramaCharacterSheet( id: string, characterId: string, provider?: string, ): Promise> { const { data } = await apiClient.post>( `/drama/projects/${id}/characters/${characterId}/prepare-character-sheet`, provider ? { provider } : {}, diff --git a/client/src/api/novel/production.ts b/client/src/api/novel/production.ts index 04eda36f1..16a85fbff 100644 --- a/client/src/api/novel/production.ts +++ b/client/src/api/novel/production.ts @@ -87,18 +87,7 @@ export async function deleteCreativeDecision(id: string, decisionId: string) { } export async function batchInvalidateCreativeDecisions(id: string, decisionIds: string[]) { - const { data } = await apiClient.post>( - `/novels/${id}/creative-decisions/batch-invalidate`, - { decisionIds }, - ); - return data; -} - -/** - * [开发工具] 重置指定小说的所有章节正文及相关生成数据,供测试重跑使用。 - * 清除范围:章节正文、生成状态、事实账本、章节摘要、质量报告等。 - */ -export async function devResetNovelChapters(id: string): Promise<{ resetCount: number }> { + const { data } = await apiClient.post>( `/novels/${id}/creative-decisions/batch-invalidate`, { decisionIds }, ); return data; } /** * [Development Tools] Resets all chapter text and related generated data for the specified novel for testing reruns. * Scope of clearing: chapter text, generation status, fact ledger, chapter summary, quality report, etc. */ export async function devResetNovelChapters(id: string): Promise<{ resetCount: number }> { const { data } = await apiClient.post>( `/novels/${id}/dev/reset-chapters`, {}, diff --git a/client/src/components/assetLibrary/AssetLibrarySection.tsx b/client/src/components/assetLibrary/AssetLibrarySection.tsx index 077afd413..35be21f5a 100644 --- a/client/src/components/assetLibrary/AssetLibrarySection.tsx +++ b/client/src/components/assetLibrary/AssetLibrarySection.tsx @@ -21,7 +21,7 @@ export function AssetLibraryRecommendation(props: { const Icon = props.icon; return (
= { export default function AssetLibraryStatusGrid(props: { items: AssetLibraryStatusItem[] }) { return ( -
+
{props.items.map((item) => { const Icon = item.icon; return ( diff --git a/client/src/components/autoDirector/AICockpit.tsx b/client/src/components/autoDirector/AICockpit.tsx index 72124ca74..5f9e988d6 100644 --- a/client/src/components/autoDirector/AICockpit.tsx +++ b/client/src/components/autoDirector/AICockpit.tsx @@ -36,12 +36,12 @@ export interface AICockpitProps { function displayStateLabel(state: DirectorBookAutomationDisplayState): string { const labels: Record = { - processing: "AI 正在处理", - needs_confirmation: "等你确认", - paused: "已暂停", - needs_attention: "出错需处理", - completed: "已完成", - idle: "未开启", + processing: "AI is processing", + needs_confirmation: "Waiting for your confirmation", + paused: "Suspended", + needs_attention: "Error needs to be handled", + completed: "Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know.", + idle: "Not turned on", }; return labels[state]; } @@ -137,11 +137,11 @@ function stateSoftSurfaceClassName(state: DirectorBookAutomationDisplayState): s function formatDate(value: string | null | undefined): string { if (!value) { - return "暂无"; + return "None yet"; } const date = new Date(value); if (Number.isNaN(date.getTime())) { - return "暂无"; + return "None yet"; } return date.toLocaleString(); } @@ -157,7 +157,7 @@ function formatDuration(value: number | null | undefined): string | null { } const seconds = Math.round(value / 1000); if (seconds <= 0) { - return "<1 秒"; + return "<1 second"; } if (seconds < 60) { return `${seconds} 秒`; @@ -185,7 +185,7 @@ function formatUsageLine(usage: { } function fallbackProjectionReason(props: Pick): string { - return props.fallbackSummary?.trim() || "没有需要你处理的 AI 自动推进任务。"; + return props.fallbackSummary?.trim() || "There are no AI auto-advance tasks for you to handle."; } function renderActionLabel( @@ -196,28 +196,28 @@ function renderActionLabel( displayState === "needs_confirmation" && (action.type === "continue" || action.type === "auto_execute_range") ) { - return "确认并继续"; + return "Confirm and continue"; } - return action.label || "继续处理"; + return action.label || "Continue processing"; } function artifactTypeLabel(type: string): string { const labels: Record = { - book_contract: "书级约定", - story_macro: "故事规划", - character_cast: "角色", - volume_strategy: "分卷", - chapter_task_sheet: "任务单", - chapter_draft: "正文", - audit_report: "审校", - repair_ticket: "修复", - reader_promise: "读者承诺", - character_governance_state: "角色状态", - world_skeleton: "世界框架", - source_knowledge_pack: "资料包", - chapter_retention_contract: "留存约定", - continuity_state: "连续性", - rolling_window_review: "近期复盘", + book_contract: "book level agreement", + story_macro: "story planning", + character_cast: "Role", + volume_strategy: "Divide into volumes", + chapter_task_sheet: "Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know.", + chapter_draft: "text", + audit_report: "Review", + repair_ticket: "repair", + reader_promise: "reader commitment", + character_governance_state: "character status", + world_skeleton: "world frame", + source_knowledge_pack: "Information package", + chapter_retention_contract: "retention agreement", + continuity_state: "continuity", + rolling_window_review: "Recent review", }; return labels[type] ?? type; } @@ -226,11 +226,11 @@ function recoveryActionLabel( action: NonNullable["recoveryAction"], ): string | null { const labels: Record = { - retry: "重试当前步骤", - resume_after_review: "查看原因后继续", - switch_model: "切换模型后继续", - confirm_protected_content: "确认保护内容边界", - manual_repair: "先处理章节问题", + retry: "Retry current step", + resume_after_review: "Continue after checking the reason", + switch_model: "Continue after switching models", + confirm_protected_content: "Confirm protected content boundaries", + manual_repair: "Deal with chapter issues first", }; return action ? labels[action] ?? null : null; } @@ -239,16 +239,16 @@ function workerStateLabel( state: NonNullable["derivedState"], ): string { const labels: Record["derivedState"], string> = { - idle: "未运行", - queued_waiting_worker: "等待接手", - leased_starting: "正在接手", - running_step: "自动推进中", - waiting_gate: "等待确认", - auto_recovering: "恢复中", - cancelled: "已停止", - failed_recoverable: "等待恢复", - failed_hard: "需要处理", - succeeded: "已完成", + idle: "Not running", + queued_waiting_worker: "Waiting to take over", + leased_starting: "Taking over", + running_step: "Automatically advancing", + waiting_gate: "Waiting for confirmation", + auto_recovering: "Recovering", + cancelled: "Stopped", + failed_recoverable: "Waiting for recovery", + failed_hard: "Need to be processed", + succeeded: "Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know.", }; return labels[state] ?? state; } @@ -258,15 +258,15 @@ function workerStateDetail(health: NonNullable 0) { - return "任务已排队,后台执行接手后会继续推进。"; + return "The task has been queued and will continue to advance after the background execution takes over."; } if (health.runningCommandCount > 0 || health.leasedCommandCount > 0) { - return "后台执行正在处理当前任务。"; + return "Background execution is processing the current task."; } if (health.staleCommandCount > 0) { - return "后台执行中断后会从最近进度尝试恢复。"; + return "After background execution is interrupted, it will try to resume from the latest progress."; } - return "当前没有正在排队或执行的后台动作。"; + return "There are currently no background actions queued or executed."; } function SummaryMetric(props: { @@ -330,16 +330,16 @@ export default function AICockpit(props: AICockpitProps) {
{stateIcon("idle")}
-
AI 驾驶舱
+
AI Cockpit
{fallbackProjectionReason(props)}
- {fallbackStatusLabel ?? "未开启"} + {fallbackStatusLabel ?? "Not turned on"} {onOpenFallbackDetails ? ( + Check + ) : null} ); @@ -379,9 +379,9 @@ export default function AICockpit(props: AICockpitProps) { || focusProjection.headline?.trim() || displayStateLabel(focusProjection.displayState); const statusDetail = reason === statusHeadline - ? focusProjection.progressSummary?.trim() || "AI 会在这里汇总本书自动推进的最新状态。" + ? focusProjection.progressSummary?.trim() || "AI will summarize the latest status of the book's automatic advancement here." : reason; - const latestRecordText = recentItems[0] ? formatDate(recentItems[0].occurredAt) : "暂无"; + const latestRecordText = recentItems[0] ? formatDate(recentItems[0].occurredAt) : "None yet"; const handlePrimaryAction = () => { if (primaryAction && onAction) { @@ -414,7 +414,7 @@ export default function AICockpit(props: AICockpitProps) {
{stateIcon(focusProjection.displayState)}
-
AI 驾驶舱
+
AI Cockpit
{focusProjection.userHeadline || focusProjection.headline || reason}
@@ -425,8 +425,8 @@ export default function AICockpit(props: AICockpitProps) {
+ Check +
); } @@ -453,34 +453,34 @@ export default function AICockpit(props: AICockpitProps) {
- - + +
-
下一步
+
Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know.
- {focusProjection.nextActionLabel || "打开小说查看当前内容"} + {focusProjection.nextActionLabel || "Open the novel to view the current content"}
{canOpenDetails ? ( + Execution details + ) : null}
@@ -488,9 +488,9 @@ export default function AICockpit(props: AICockpitProps) { {circuitBreaker ? (
-
自动推进已暂停
-
{circuitBreaker.message || "系统检测到继续自动推进可能反复失败。"}
- {circuitRecovery ?
建议:{circuitRecovery}。
: null} +
Auto-advance paused
+
{circuitBreaker.message || "The system has detected that continued automatic advancement may fail repeatedly."}
+ {circuitRecovery ?
suggestion:{circuitRecovery}。
: null}
) : null} @@ -499,20 +499,20 @@ export default function AICockpit(props: AICockpitProps) {
- 后台执行 -
+ background execution +
{workerStateLabel(workerHealth.derivedState)}
{workerStateDetail(workerHealth)}
- - - - + + + +
{workerHealth.oldestQueuedWaitMs ? (
- 等待接手 {formatDuration(workerHealth.oldestQueuedWaitMs) ?? "<1 秒"} + Waiting to take over {formatDuration(workerHealth.oldestQueuedWaitMs) ?? "<1 second"}
) : null}
@@ -523,8 +523,8 @@ export default function AICockpit(props: AICockpitProps) {
- 产物记录 -
+ product record +
{artifactInsightLines.length > 0 ? ( {artifactInsightLines[0]} ) : null} @@ -549,7 +549,7 @@ export default function AICockpit(props: AICockpitProps) { {usageSummary ? ( } > @@ -557,7 +557,7 @@ export default function AICockpit(props: AICockpitProps) {
{formatUsageLine(usageSummary)}
{promptUsage.length > 0 ? (
-
阶段用量
+
Phase dosage
{promptUsage.map((item) => (
@@ -572,7 +572,7 @@ export default function AICockpit(props: AICockpitProps) { ) : null} {stepUsage.length > 0 ? (
-
推进步骤
+
Advance steps
{stepUsage.map((item) => (
@@ -591,7 +591,7 @@ export default function AICockpit(props: AICockpitProps) { {recentItems.length > 0 ? ( } > @@ -602,7 +602,7 @@ export default function AICockpit(props: AICockpitProps) { {item.usage ? (
{formatUsageLine(item.usage)}
) : item.durationMs ? ( -
耗时 {formatDuration(item.durationMs)}
+
time consuming {formatDuration(item.durationMs)}
) : null}
{formatDate(item.occurredAt)}
diff --git a/client/src/components/autoDirector/AutoDirectorApprovalPointMultiSelect.tsx b/client/src/components/autoDirector/AutoDirectorApprovalPointMultiSelect.tsx index b4afaacdc..c217c2e51 100644 --- a/client/src/components/autoDirector/AutoDirectorApprovalPointMultiSelect.tsx +++ b/client/src/components/autoDirector/AutoDirectorApprovalPointMultiSelect.tsx @@ -17,9 +17,9 @@ interface AutoDirectorApprovalPointMultiSelectProps { } function riskLabel(riskLevel: DirectorAutoApprovalPoint["riskLevel"]): string { - if (riskLevel === "high") return "高风险"; - if (riskLevel === "medium") return "中风险"; - return "低风险"; + if (riskLevel === "high") return "high risk"; + if (riskLevel === "medium") return "Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know."; + return "Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know."; } function riskClassName(riskLevel: DirectorAutoApprovalPoint["riskLevel"]): string { @@ -41,7 +41,7 @@ function toggleCodes(current: string[], targetCodes: string[], checked: boolean) export function summarizeDirectorAutoApprovalPoints(codes: string[]): string { const normalized = normalizeDirectorAutoApprovalPointCodes(codes, []); if (normalized.length === 0) { - return "不会自动通过审批点"; + return "Will not automatically pass the approval point"; } const labels: string[] = normalized .map((code) => DIRECTOR_AUTO_APPROVAL_POINTS.find((item) => item.code === code)?.label) @@ -49,7 +49,7 @@ export function summarizeDirectorAutoApprovalPoints(codes: string[]): string { if (labels.length <= 2) { return labels.join("、"); } - return `${labels.slice(0, 2).join("、")} 等 ${labels.length} 项`; + return `${labels.slice(0, 2).join("、")} and ${labels.length} items`; } export default function AutoDirectorApprovalPointMultiSelect({ diff --git a/client/src/components/autoDirector/AutoDirectorApprovalStrategyPanel.tsx b/client/src/components/autoDirector/AutoDirectorApprovalStrategyPanel.tsx index ce9a29816..a557c0732 100644 --- a/client/src/components/autoDirector/AutoDirectorApprovalStrategyPanel.tsx +++ b/client/src/components/autoDirector/AutoDirectorApprovalStrategyPanel.tsx @@ -26,7 +26,7 @@ export default function AutoDirectorApprovalStrategyPanel({ }: AutoDirectorApprovalStrategyPanelProps) { return (
-
自动推进方式
+
Automatic propulsion method
{enabled - ? "自动推进:系统会在目标范围内自动确认规划、章节执行、质量修复和必要重规划。" + ? "Automatic advancement: The system will automatically confirm planning, chapter execution, quality repair and necessary re-planning within the target range." : `副驾确认边界:${summarizeDirectorAutoApprovalPoints(approvalPointCodes)}。未包含的审批点会等待你确认。`}
{!enabled ? (
- 高级审批授权 - + Advanced approval authorization +
- 项目导航 - + Project navigation + ) : null}
); diff --git a/client/src/components/autoDirector/DirectorRuntimeProjectionCard.tsx b/client/src/components/autoDirector/DirectorRuntimeProjectionCard.tsx index 436a13397..f55b97c9c 100644 --- a/client/src/components/autoDirector/DirectorRuntimeProjectionCard.tsx +++ b/client/src/components/autoDirector/DirectorRuntimeProjectionCard.tsx @@ -23,11 +23,11 @@ interface DirectorRuntimeProjectionCardProps { function formatDate(value: string | null | undefined): string { if (!value) { - return "暂无"; + return "None yet"; } const date = new Date(value); if (Number.isNaN(date.getTime())) { - return "暂无"; + return "None yet"; } return date.toLocaleString(); } @@ -43,84 +43,14 @@ function formatDuration(value: number | null | undefined): string | null { } const seconds = Math.round(value / 1000); if (seconds <= 0) { - return "<1 秒"; + return "<1 second"; } if (seconds < 60) { - return `${seconds} 秒`; + return `${seconds} seconds`; } const minutes = Math.floor(seconds / 60); const restSeconds = seconds % 60; - return restSeconds > 0 ? `${minutes} 分 ${restSeconds} 秒` : `${minutes} 分`; -} - -function formatUsageLine(usage: { - llmCallCount: number; - promptTokens: number; - completionTokens: number; - totalTokens: number; - durationMs?: number | null; -}): string { - const duration = formatDuration(usage.durationMs); - return [ - `${formatTokenCount(usage.llmCallCount)} 次调用`, - `输入 ${formatTokenCount(usage.promptTokens)}`, - `输出 ${formatTokenCount(usage.completionTokens)}`, - `总计 ${formatTokenCount(usage.totalTokens)} Tokens`, - duration ? `累计调用耗时 ${duration}` : null, - ].filter(Boolean).join(" · "); -} - -function formatPolicyMode(mode: DirectorPolicyMode): string { - if (mode === "suggest_only") { - return "只给建议"; - } - if (mode === "run_next_step") { - return "推进下一步"; - } - if (mode === "auto_safe_scope") { - return "安全范围自动推进"; - } - return "推进到检查点"; -} - -function formatStatus(status: DirectorRuntimeProjectionStatus): string { - if (status === "running") { - return "推进中"; - } - if (status === "waiting_approval") { - return "等待确认"; - } - if (status === "blocked") { - return "已暂停"; - } - if (status === "failed") { - return "失败"; - } - if (status === "completed") { - return "已完成"; - } - return "待开始"; -} - -function statusClassName(status: DirectorRuntimeProjectionStatus): string { - if (status === "running") { - return "border-sky-300 bg-sky-50 text-sky-900"; - } - if (status === "waiting_approval") { - return "border-amber-300 bg-amber-50 text-amber-900"; - } - if (status === "blocked" || status === "failed") { - return "border-destructive/30 bg-destructive/5 text-destructive"; - } - if (status === "completed") { - return "border-emerald-300 bg-emerald-50 text-emerald-900"; - } - return "border-border bg-muted/30 text-muted-foreground"; -} - -function statusIcon(status: DirectorRuntimeProjectionStatus) { - if (status === "running") { - return ; + return restSeconds > 0 ? `${minutes} minutes ${restSeconds} seconds` : `${minutes} minutes`; } function formatUsageLine(usage: { llmCallCount: number; promptTokens: number; completionTokens: number; totalTokens: number; durationMs?: number | null; }): string { const duration = formatDuration(usage.durationMs); return [ `${formatTokenCount(usage.llmCallCount)} times`, `input ${formatTokenCount(usage.promptTokens)}`, `output ${formatTokenCount(usage.completionTokens)}`, `total ${formatTokenCount(usage.totalTokens)} Tokens`, duration ? `cumulative call time ${duration}` : null, ].filter(Boolean).join(" · "); } function formatPolicyMode(mode: DirectorPolicyMode): string { if (mode === "suggest_only") { return "Only suggestions are given"; } if (mode === "run_next_step") { return "Proceed to the next step"; } if (mode === "auto_safe_scope") { return "Automatically proceed within safe scope"; } return "Proceeded to checkpoint"; } function formatStatus(status: DirectorRuntimeProjectionStatus): string { if (status === "running") { return "Proceeding"; } if (status === "waiting_approval") { return "Waiting for confirmation"; } if (status === "blocked") { return "Paused"; } if (status === "failed") { return "Failed"; } if (status === "completed") { return "Completed"; } return "Pending start"; } function statusClassName(status: DirectorRuntimeProjectionStatus): string { if (status === "running") { return "border-sky-300 bg-sky-50 text-sky-900"; } if (status === "waiting_approval") { return "border-amber-300 bg-amber-50 text-amber-900"; } if (status === "blocked" || status === "failed") { return "border-destructive/30 bg-destructive/5 text-destructive"; } if (status === "completed") { return "border-emerald-300 bg-emerald-50 text-emerald-900"; } return "border-border bg-muted/30 text-muted-foreground"; } function statusIcon(status: DirectorRuntimeProjectionStatus) { if (status === "running") { return ; } if (status === "waiting_approval") { return ; @@ -163,7 +93,7 @@ function formatQualityBudgetSummary(summary: DirectorRuntimeProjection["qualityB } const chapterText = typeof summary.currentChapterOrder === "number" ? `第 ${summary.currentChapterOrder} 章` - : "当前章节"; + : "Current Chapter"; return `${chapterText}质量预算:局部修复 ${summary.patchRepairUsed}/1,整章重写 ${summary.chapterRewriteUsed}/1,窗口重规划 ${summary.windowReplanUsed}/1。${summary.nextActionLabel}`; } @@ -172,15 +102,15 @@ function formatRootCauseSummary(projection: DirectorRuntimeProjection): string | return null; } if (projection.rootCauseCode === "replan_required") { - return "当前问题来自章节职责失配,系统需要先调整附近章节安排。"; + return "The current problem comes from the mismatch of chapter responsibilities, and the system needs to adjust the arrangement of nearby chapters first."; } if (projection.rootCauseCode === "draft_obligation_unmet") { - return "正文已经生成,但仍有本章必须完成的内容没有兑现。"; + return "The main text has been generated, but there are still things that must be completed in this chapter that have not been fulfilled."; } if (projection.rootCauseCode === "draft_repair_exhausted") { - return "正文已经生成,但自动修复后仍有阻塞问题需要继续处理。"; + return "The main text has been generated, but there are still blocking issues that need to be dealt with after automatic repair."; } - return "正文没有成功生成,需要重新执行当前章节。"; + return "The main text was not successfully generated and the current chapter needs to be re-executed."; } function formatPercent(value: number | null | undefined): string { @@ -201,13 +131,13 @@ export default function DirectorRuntimeProjectionCard({ const primaryText = projection.headline?.trim() || projection.currentLabel?.trim() || projection.lastEventSummary?.trim() - || "等待同步当前推进状态"; + || "Waiting for synchronization of current advancement status"; const detailText = projection.detail?.trim(); const attentionText = projection.requiresUserAction ? projection.blockingReason?.trim() || projection.blockedReason?.trim() || projection.lastEventSummary?.trim() - || "请先处理当前停留点。" + || "Please process the current stop first." : projection.blockingReason?.trim() || projection.blockedReason?.trim(); const progressLine = projection.progressBreakdown?.explanation?.trim() || projection.progressSummary?.trim() @@ -221,7 +151,7 @@ export default function DirectorRuntimeProjectionCard({ const activeExecutionLine = projection.activeExecution ? `后台执行:${getDirectorNodeDisplayLabel({ nodeKey: projection.activeExecution.stepType, - fallback: projection.currentAction || "自动导演任务", + fallback: projection.currentAction || "Automatic director tasks", })}${projection.activeExecution.resourceClass ? ` · ${projection.activeExecution.resourceClass}` : ""}` : null; const waitingLine = projection.waitingReason ? `等待原因:${projection.waitingReason}` : null; @@ -238,7 +168,7 @@ export default function DirectorRuntimeProjectionCard({ workerHealthLine, projection.nextActionLabel ? `下一步:${projection.nextActionLabel}` : null, projection.recommendedAction?.reason ? `推荐原因:${projection.recommendedAction.reason}` : null, - projection.isAutopilotRecoverable ? "AI 可以从当前进度继续处理。" : null, + projection.isAutopilotRecoverable ? "The AI ​​can continue processing from its current progress." : null, rootCauseLine, obligationLine, qualityBudgetLine, @@ -259,7 +189,7 @@ export default function DirectorRuntimeProjectionCard({
{statusIcon(projection.status)}
-
导演进度
+
Director's progress
{primaryText}
@@ -281,19 +211,19 @@ export default function DirectorRuntimeProjectionCard({ {progressBreakdown && !compact ? (
-
规划
+
planning
{formatPercent(progressBreakdown.planningProgress ?? progressBreakdown.planningPercent)}
-
章节
+
chapter
{progressBreakdown.continuableChapters}/{progressBreakdown.totalChapters}
-
质量
+
quality
{formatPercent(progressBreakdown.qualityProgress ?? progressBreakdown.qualityRepairPercent)}
-
当前动作
+
Current action
{formatPercent(progressBreakdown.activeJobProgress)}
@@ -301,7 +231,7 @@ export default function DirectorRuntimeProjectionCard({ {attentionText ? (
- {projection.requiresUserAction ? "需要你处理:" : "暂停原因:"}{attentionText} + {projection.requiresUserAction ? "You need to handle:" : "Reason for suspension:"}{attentionText}
) : null} @@ -323,11 +253,11 @@ export default function DirectorRuntimeProjectionCard({ {usageSummary ? (
-
AI 用量
+
AI usage
{formatUsageLine(usageSummary)}
{promptUsage.length > 0 && !compact ? (
-
阶段用量
+
Phase dosage
{promptUsage.map((item) => (
@@ -340,7 +270,7 @@ export default function DirectorRuntimeProjectionCard({ ) : null} {stepUsage.length > 0 && !compact ? (
-
推进步骤
+
Advance steps
{stepUsage.map((item) => (
@@ -355,13 +285,13 @@ export default function DirectorRuntimeProjectionCard({ ) : null}
- 推进方式:{formatPolicyMode(projection.policyMode)} - 更新时间:{formatDate(projection.updatedAt)} + Promotion method:{formatPolicyMode(projection.policyMode)} + Update time:{formatDate(projection.updatedAt)}
{recentEvents.length > 0 && !compact ? (
-
最近进展
+
Recent Progress
{recentEvents.map((event) => (
{event.summary}
diff --git a/client/src/components/characterConversation/CharacterConversationWorkbench.tsx b/client/src/components/characterConversation/CharacterConversationWorkbench.tsx index 7a7b40be7..9399e9c34 100644 --- a/client/src/components/characterConversation/CharacterConversationWorkbench.tsx +++ b/client/src/components/characterConversation/CharacterConversationWorkbench.tsx @@ -92,10 +92,10 @@ export default function CharacterConversationWorkbench(props: CharacterConversat {displayName} 的对话空间} + title={{displayName} dialogue space} description={projection?.sourceDescription ?? sourceDescriptionForPolicy(policy)} meta={{projection?.sourceLabel ?? sourceLabelForPolicy(policy)} · {policyLabel(policy)}} - actions={<>{props.headerActions}{props.chapterAnchorOptions?.length && typeof props.chapterAnchor === "number" && props.onChapterAnchorChange ? : null}{props.onClose ? : null}} + actions={<>{props.headerActions}{props.chapterAnchorOptions?.length && typeof props.chapterAnchor === "number" && props.onChapterAnchorChange ? : null}{props.onClose ? : null}} className="rounded-xl border-border/50 shadow-none" headerClassName="bg-background px-5 py-4 xl:px-6" bodyClassName={cn( @@ -141,29 +141,29 @@ export default function CharacterConversationWorkbench(props: CharacterConversat } function ChapterAnchorSelect(props: { chapterAnchor: number; options: number[]; disabled: boolean; onChange: (chapterAnchor: number) => void }) { - return ; + return ; } function ConversationContextPanel(props: { projection: CharacterSubjectProjection | undefined }) { if (!props.projection) { - return ; + return ; } const { projection } = props; return ( ); } @@ -175,17 +175,17 @@ function policyForSubject(kind: CharacterSubjectRef["kind"]): CharacterConversat } function policyLabel(policy: CharacterConversationPolicy) { - return policy === "novel_influence" ? "可带入创作" : policy === "evidence_interview" ? "证据访谈" : "只读访谈"; + return policy === "novel_influence" ? "Can be brought into creation" : policy === "evidence_interview" ? "evidence interview" : "read-only interview"; } function sourceLabelForPolicy(policy: CharacterConversationPolicy) { - return policy === "novel_influence" ? "小说角色" : policy === "evidence_interview" ? "拆书角色档案" : "基础角色库"; + return policy === "novel_influence" ? "novel character" : policy === "evidence_interview" ? "Open book character files" : "Basic character library"; } function sourceDescriptionForPolicy(policy: CharacterConversationPolicy) { return policy === "novel_influence" - ? "角色会结合当前小说处境回应;只有你确认后,谈话倾向才会带入后续创作。" + ? "The character will respond based on the current novel situation; only after you confirm it, the conversational tendencies will be carried into subsequent creations." : policy === "evidence_interview" - ? "角色只依据选定章节范围内的原文证据回应,不会改写原文。" - : "角色依据角色库中的稳定设定回应;交流只用于理解人物,不会改写设定。"; + ? "The character will only respond based on the original text evidence within the selected chapter range, and will not rewrite the original text." + : "Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know."; } diff --git a/client/src/components/comic/GeneratedImageCard.tsx b/client/src/components/comic/GeneratedImageCard.tsx index e9a8629f0..aa6929202 100644 --- a/client/src/components/comic/GeneratedImageCard.tsx +++ b/client/src/components/comic/GeneratedImageCard.tsx @@ -11,10 +11,10 @@ const STATUS_DOT: Record = { }; const STATUS_TITLE: Record = { - idle: "未生成", - generating: "生成中", - done: "已就绪", - error: "生成失败", + idle: "Error 500 (Server Error)!!1500.That’s an error.There was an error. Please try again later.That’s all we know.", + generating: "Generating", + done: "Ready", + error: "Build failed", }; const SIZE_STYLE: Record, string> = { @@ -112,7 +112,7 @@ export function GeneratedImageCard({ {onDelete && (
@@ -179,13 +179,13 @@ export function GeneratedImageCard({ onClick={onGenerate} > {isGenerating ? : } - {generateLabel ?? (hasDoneImage ? "重新生成" : "AI 生图")} + {generateLabel ?? (hasDoneImage ? "Regenerate" : "AI generated pictures")} )} {onUpload && ( + Optimize selected content only +
{preview.trim() ? (
-
优化预览
+
Optimize preview
                 {preview}
               
- - + +
) : null} diff --git a/client/src/components/common/FullscreenView.tsx b/client/src/components/common/FullscreenView.tsx index ea76ec6aa..d8977d5df 100644 --- a/client/src/components/common/FullscreenView.tsx +++ b/client/src/components/common/FullscreenView.tsx @@ -37,8 +37,8 @@ export default function FullscreenView(props: FullscreenViewProps) { headerClassName, bodyClassName, fullscreenBodyClassName, - toggleLabel = "全屏查看", - exitLabel = "退出全屏", + toggleLabel = "View full screen", + exitLabel = "Exit full screen", } = props; const headingId = useId(); const [internalFullscreen, setInternalFullscreen] = useState(defaultFullscreen); diff --git a/client/src/components/common/LLMSelector.tsx b/client/src/components/common/LLMSelector.tsx index f87725996..517b94dc8 100644 --- a/client/src/components/common/LLMSelector.tsx +++ b/client/src/components/common/LLMSelector.tsx @@ -268,20 +268,20 @@ export default function LLMSelector({ return (
- {showBadge ? 模型 : null} + {showBadge ? Model : null}
diff --git a/client/src/components/creativeHub/OpenInCreativeHubButton.tsx b/client/src/components/creativeHub/OpenInCreativeHubButton.tsx index 5fad5bfa0..7ea1ea043 100644 --- a/client/src/components/creativeHub/OpenInCreativeHubButton.tsx +++ b/client/src/components/creativeHub/OpenInCreativeHubButton.tsx @@ -8,18 +8,7 @@ interface OpenInCreativeHubButtonProps { bindings: CreativeHubResourceBinding; label?: string; variant?: ComponentProps["variant"]; - size?: ComponentProps["size"]; - className?: string; -} - -export default function OpenInCreativeHubButton({ - bindings, - label = "在创作中枢中继续", - variant = "outline", - size = "sm", - className, -}: OpenInCreativeHubButtonProps) { - return ( + size?: ComponentProps["size"]; className?: string; } export default function OpenInCreativeHubButton({ bindings, label = "Continue in the Creation Hub", variant = "outline", size = "sm", className, }: OpenInCreativeHubButtonProps) { return ( diff --git a/client/src/components/image/ImageGenerationConfirmDialog.tsx b/client/src/components/image/ImageGenerationConfirmDialog.tsx index 31ce23b64..b60afa0ec 100644 --- a/client/src/components/image/ImageGenerationConfirmDialog.tsx +++ b/client/src/components/image/ImageGenerationConfirmDialog.tsx @@ -18,18 +18,18 @@ import { toast } from "@/components/ui/toast"; import SelectControl from "@/components/common/SelectControl"; const SIZE_OPTIONS = [ - { value: "1024x1024", label: "1024×1024(方形 1:1)" }, - { value: "1024x1536", label: "1024×1536(竖版 2:3,漫画/角色)" }, - { value: "1536x1024", label: "1536×1024(横版 3:2,三视图/表情稿)" }, + { value: "1024x1024", label: "1024×1024 (square 1:1)" }, + { value: "1024x1536", label: "1024×1536 (vertical 2:3, comic/character)" }, + { value: "1536x1024", label: "1536×1024 (Landscape 3:2, Three-view drawing/Emoji)" }, ]; const REF_KIND_LABEL: Record = { - character_sheet: "三视图", - character_expression: "表情稿", - character_face: "面部裁剪", - book_analysis_character_base: "基础形象", - asset: "资产", - scene: "场景", + character_sheet: "Three views", + character_expression: "Expressions", + character_face: "face cropping", + book_analysis_character_base: "basic image", + asset: "assets", + scene: "Scene", }; const REF_KIND_COLOR: Record = { @@ -166,16 +166,16 @@ export function ImageGenerationConfirmDialog({ })), }); if (!response.data) { - throw new Error("没有收到 Prompt 处理结果。"); + throw new Error("No prompt processing result was received."); } if (action === "optimize" && response.data.optimizedPrompt?.trim()) { setPrompt(response.data.optimizedPrompt.trim()); } setPromptAssistResult(response.data); } catch (error) { - const message = error instanceof Error ? error.message : "Prompt 处理失败。"; + const message = error instanceof Error ? error.message : "Prompt processing failed."; setPromptAssistError(message); - toast.error("Prompt 处理失败", { description: message }); + toast.error("Prompt processing failed", { description: message }); } finally { setPromptAssistLoading(null); } @@ -184,15 +184,15 @@ export function ImageGenerationConfirmDialog({ const footer = preview ? (

- {anyDirty ? "本次将使用上方修改后的参数生图(仅一次性,不保存到角色)" : "点击「开始生图」按当前参数生成"} + {anyDirty ? "This time, the modified parameters above will be used to generate the picture (one-time only, not saved to the character)" : "Click \"Start Generating Picture\" to generate according to the current parameters."}

+ Cancel +
@@ -201,7 +201,7 @@ export function ImageGenerationConfirmDialog({ return ( { if (!o) onCancel(); }}> - 正在准备生图素材... -
+ Preparing photo material... +
) : !preview ? ( -
无预览数据
+
No preview data
) : (
{/* 参考图素材 */}
- 参考素材 - + Reference material + {referenceImages.length}/{preview.referenceImages.length} {referenceDirty && ( @@ -231,18 +231,18 @@ export function ImageGenerationConfirmDialog({ onClick={() => setIncludedReferenceImageUrls(preview.referenceImages.map((ref) => ref.url))} disabled={submitting || !!promptAssistLoading} > - 恢复全部 - + Restore all + )}
{preview.referenceImages.length === 0 ? (
- 本次生图不附带参考图(纯文生图) -
+ This drawing does not come with reference pictures (pure text drawings) +
) : referenceImages.length === 0 ? (
- 本次生成不会发送参考图 -
+ Reference images will not be sent during this generation. +
) : (
{referenceImages.map((ref, i) => { @@ -250,27 +250,7 @@ export function ImageGenerationConfirmDialog({ const kindLabel = REF_KIND_LABEL[ref.kind] ?? ref.kind; return ( @@ -336,7 +316,7 @@ export function ImageGenerationConfirmDialog({ }} disabled={submitting || !!promptAssistLoading} /> -

{prompt.length} 字符 · 临时修改不会改动角色/项目设置

+

{prompt.length} Characters · Temporary modifications will not change character/item settings

优化要求

@@ -350,8 +330,8 @@ export function ImageGenerationConfirmDialog({ disabled={submitting || !!promptAssistLoading || !prompt.trim()} > {promptAssistLoading === "optimize" ? : } - 优化 Prompt - + Optimize Prompt + {optimizationInstruction && ( + Clear + )}
@@ -375,10 +355,10 @@ export function ImageGenerationConfirmDialog({ setOptimizationInstruction(e.target.value); clearPromptAssistResult(); }} - placeholder="例如:更像水彩、画面更温柔、保留服装和发型" + placeholder="For example: more like watercolor, softer picture, retaining clothing and hairstyle" disabled={submitting || !!promptAssistLoading} /> -

{optimizationInstruction.length} 字符 · 仅用于「优化 Prompt」

+

{optimizationInstruction.length} Character · Only used for "Optimize Prompt"

{(promptAssistResult || promptAssistError) && (
@@ -401,7 +381,7 @@ export function ImageGenerationConfirmDialog({ {promptAssistAction === "optimize" && promptAssistResult.changes.length > 0 && (
-

已调整

+

Adjusted

    {promptAssistResult.changes.map((item, index) => (
  • {item}
  • @@ -411,7 +391,7 @@ export function ImageGenerationConfirmDialog({ )} {promptAssistResult.risks.length > 0 && (
    -

    注意事项

    +

    Things to note

      {promptAssistResult.risks.map((item, index) => (
    • {item}
    • @@ -429,8 +409,8 @@ export function ImageGenerationConfirmDialog({

      - 负面 Prompt - {negativePromptDirty && 已修改} + Negative Prompt + {negativePromptDirty && Modified}

      {negativePromptDirty && ( + Restore default + )}