Skip to content

i18n: chrome visible del Video Editor - #105

Merged
IAnMove merged 3 commits into
mainfrom
i18n/video-editor-chrome
Sep 2, 2026
Merged

i18n: chrome visible del Video Editor#105
IAnMove merged 3 commits into
mainfrom
i18n/video-editor-chrome

Conversation

@IAnMove

@IAnMove IAnMove commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Zona i18n

Boy-scout del chrome visible de Video Editor (ui/src/features/video-editor/VideoEditorPanel.tsx). Namespace nuevo videoEditor (EN+ES, 89 claves, misma forma). El panel usa useUiTranslation('videoEditor'); no se llama a useTranslation de react-i18next.

Entra al catálogo:

  • toolbar: Import / From HocusPocus / Export MP4 / Cancelar
  • empty states, picker de HocusPocus, aria-labels de esas herramientas
  • play/pause, Split, screenshot, cabezal, timeline chrome (resumen, quitar, transiciones por defecto)
  • status y errores de import/export/hand-off/reemplazo que ve el usuario
  • botón “Rehacer en Creación de vídeo”

Video Editor se queda como nombre de producto (igual que Story Lab). Workspace no se traduce; Output folder sigue el glosario.

Qué se deja hardcoded a propósito

  • nombres de clip, ficheros, comic animatic / Series shot N como fallback de nombre
  • transiciones del inspector (Hard cut, Crossfade, Momentos después…, textos de recorte ya en ES)
  • mute/unmute, duplicate, Fit/Fill, Earlier/Later
  • editorClipRecoveryMessage y mensajes crudos del backend
  • Studio, 3D, Director, Story Lab, Series Lab (fuera de zona)

El contrato Python de reemplazo ahora apunta a t('inspector.redoInVideoCreation') y al catálogo ES.

Cómo probar

cd ui && npm run i18n:check
cd ui && npx tsc -b --pretty false
cd ui && npx tsx --tsconfig tsconfig.app.json --import ./tests/setupI18n.ts --test \
  tests/i18nFoundation.test.tsx tests/videoEditorI18n.test.tsx \
  tests/videoEditorTimeline.test.tsx tests/videoEditorPicker.test.tsx \
  tests/videoEditorResponsive.test.tsx tests/videoEditorHandoff.test.tsx \
  tests/videoEditorExportPersistence.test.tsx tests/videoEditorDraftWorkspace.test.tsx

En la app: Video Editor → cambiar idioma en Ajustes. Toolbar/empty/picker/timeline deben pasar a ES; nombres de clip y transiciones no.

No mezclar.


Note

Low Risk
UI copy and test updates only; no API, auth, or export pipeline logic changes beyond localized user-visible strings.

Overview
Moves Video Editor visible chrome from hardcoded strings into the videoEditor i18n namespace (EN+ES), wiring VideoEditorPanel through useUiTranslation('videoEditor') and shared common for Cancel.

Toolbar, empty states, HocusPocus picker, playback controls, export preview labels, inspector output settings, timeline chrome, and user-facing status/errors (import/export, hand-off, replace) now use catalog keys with interpolation and plurals. Hand-off and export reconnect paths use a tRef so async callbacks stay on the active language.

Docs and check-i18n-catalogs.mjs expand the videoEditor namespace description, add glossary Video Editor, and forbid returning migrated literals in the panel. Tests cover catalog parity, panel usage, and language switching in export/handoff flows plus a new videoEditorI18n test.

Intentionally not migrated in this PR (per scope): trim bar Spanish text, transition inspector labels (e.g. “Preview this transition”), mute/fit/duplicate/EEarlier/Later, clip names, and raw backend messages.

Reviewed by Cursor Bugbot for commit 0456d53. Configure here.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

PR Review — Loreframe Studio

Risk: low
Scope: 9 file(s); +429/-87; React UI, docs

Automated review from scripts/analyze_pr.py. This is a heuristic pass (no LLM) so humans still own the merge decision.

Findings

  • low — UI changed — rebuild before merge
    Run cd ui && npm run build (CI already does this). Pinokio Update rebuilds for end users; keep ui/dist untracked.

Changed files

  • added: ui/tests/videoEditorI18n.test.tsx
  • modified: docs/development/INTERNATIONALIZATION.md, ui/scripts/check-i18n-catalogs.mjs, ui/src/features/video-editor/VideoEditorPanel.tsx, ui/src/i18n/locales/en/videoEditor.json, ui/src/i18n/locales/es/videoEditor.json, ui/tests/i18nFoundation.test.tsx, ui/tests/videoEditorExportPersistence.test.tsx, ui/tests/videoEditorHandoff.test.tsx

CONTRIBUTING checklist

  • python scripts/verify_clean_repo.py
  • python -m compileall -q app/services app/launch.py scripts
  • cd ui && npm run build if the UI changed
  • No weights, CivitAI sidecars, or generated guides
  • Stays local-first (no required accounts / telemetry)

Posted by the repo PR review workflow. Re-runs on each push to the PR.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Code health

Metric Value
Production LOC 235,070
Production files 509
Test LOC 64,514
Functions measured 14,750
Functions complexity ≥ 15 773
Maximum complexity 667

Markdown, JSON catalogs and tests are out of this table. Only app/ runtime + ui/src TS/JS count.

Most complex functions

Complexity Where
667 app/wgp.py:7157 generate_video
374 ui/src/stores/useStore.ts:4426 Async method 'startGeneration'
356 app/_launch_runtime.py:23154 _run_generation
308 app/wgp.py:12274 generate_video_tab
272 ui/src/components/Sidebar/SceneAnimatorPanel.tsx:469 Function 'SceneAnimatorPanel'
266 ui/src/stores/useStore.ts:9164 Async method 'loadSettingsFromOutput'
258 app/services/director/planners/short_film.py:3433 ShortFilmPlanner._plan_story_driven
254 app/services/director_pipeline.py:13539 _run_video_generation
245 app/services/director_pipeline.py:7663 _run_pipeline
241 ui/src/features/agent/agentActions.ts:1077 Function 'parseAction'
227 ui/src/features/agent/agentActions.ts:2672 Async function 'executeAgentActions'
226 app/services/director_pipeline.py:6492 update_comic_preview

Trend vs baseline

Metric Δ
Production LOC +1,405
Test LOC +700
Functions ≥ 15 -1
Maximum complexity +0

Warnings

  • production LOC increased by +1,405
  • complexity hotspot ui/src/stores/useStore.ts rose 373 -> 374
  • complexity hotspot app/services/model3d_service.py rose 51 -> 54
  • complexity hotspot ui/src/components/MainContent/TabFilter.tsx rose 19 -> 23
  • complexity hotspot ui/src/features/agent/AgentAssistantPanel.tsx rose 19 -> 23
  • hotspot ui/src/features/agent/agentActions.ts increased by +3 lines
  • hotspot ui/src/features/video-editor/VideoEditorPanel.tsx increased by +19 lines
  • hotspot ui/src/types/index.ts increased by +3 lines
  • hotspot app/services/model3d_service.py increased by +58 lines
  • hotspot ui/src/features/agent/capabilityRegistry.ts increased by +2 lines
  • hotspot ui/src/features/agent/applicationAdapters.ts increased by +7 lines

Ratchet passed.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Language switch reprocesses editor handoff
    • processPendingHandoff now reads translations from a tRef so a language change no longer recreates the callback or re-run the localStorage hand-off effect.
  • ✅ Fixed: Language switch resets export status
    • pollExport and the reconnect effect no longer depend on t, so switching language does not cancel polling or reset export status.

Create PR

Or push these changes by commenting:

@cursor push 3740d1c4dd
Preview (3740d1c4dd)
diff --git a/ui/src/features/video-editor/VideoEditorPanel.tsx b/ui/src/features/video-editor/VideoEditorPanel.tsx
--- a/ui/src/features/video-editor/VideoEditorPanel.tsx
+++ b/ui/src/features/video-editor/VideoEditorPanel.tsx
@@ -670,6 +670,8 @@
 export function VideoEditorPanel() {
   const { t } = useUiTranslation('videoEditor')
   const { t: tCommon } = useUiTranslation('common')
+  const tRef = useRef(t)
+  tRef.current = t
   const refreshOutputs = useStore(s => s.refreshOutputs)
   const activeWorkspace = useStore(s => s.activeWorkspace)
   const [draft] = useState(() => loadEditorDraft(activeWorkspace))
@@ -876,7 +878,7 @@
           }]
         : [])
     if (!pendingSources.length) {
-      setError(t('errors.handoffEmpty'))
+      setError(tRef.current('errors.handoffEmpty'))
       return
     }
 
@@ -894,20 +896,20 @@
       for (let index = 0; index < pendingSources.length; index++) {
         const item = pendingSources[index]
         setAddProgress(kind === 'sequence'
-          ? t('status.openingSeriesShot', { current: index + 1, total: pendingSources.length })
-          : t('status.openingNamed', { name: item.name || 'comic animatic' }))
+          ? tRef.current('status.openingSeriesShot', { current: index + 1, total: pendingSources.length })
+          : tRef.current('status.openingNamed', { name: item.name || 'comic animatic' }))
         nextClips.push(await createClipFromSource(item.url, item.url, item.name || `Series shot ${index + 1}`))
       }
 
       if (clips.length && !window.confirm(
         kind === 'sequence'
-          ? t('confirm.replaceMontage', { count: clips.length })
-          : t('confirm.addHandoff', { count: clips.length }),
+          ? tRef.current('confirm.replaceMontage', { count: clips.length })
+          : tRef.current('confirm.addHandoff', { count: clips.length }),
       )) return
 
       const committedClips = kind === 'sequence' ? nextClips : [...clips, ...nextClips]
       if (!persistEditorDraft(committedClips, nextProjectName, nextResolution, fps, draftWorkspaceRef.current)) {
-        throw new Error(t('errors.draftSave'))
+        throw new Error(tRef.current('errors.draftSave'))
       }
       setClips(committedClips)
       setSelectedId((kind === 'sequence' ? committedClips[0] : nextClips[0])?.id || null)
@@ -919,13 +921,13 @@
       setPendingHandoff(null)
       setError(null)
     } catch (reason) {
-      setError(t('errors.handoffOpen', { message: (reason as Error).message }))
+      setError(tRef.current('errors.handoffOpen', { message: (reason as Error).message }))
     } finally {
       handoffProcessingRef.current = false
       setAdding(false)
       setAddProgress('')
     }
-  }, [clips, createClipFromSource, fps, projectName, resolution, t])
+  }, [clips, createClipFromSource, fps, projectName, resolution])
 
   useEffect(() => {
     let pending: PendingEditorSource | null = null
@@ -1864,24 +1866,24 @@
       }
     } catch (reason) {
       if (mountedRef.current && epoch === exportPollEpochRef.current) {
-        setError(t('errors.reconnectExport', { jobId, message: (reason as Error).message }))
+        setError(tRef.current('errors.reconnectExport', { jobId, message: (reason as Error).message }))
       }
     } finally {
       if (exportPollingRef.current === jobId) exportPollingRef.current = null
     }
-  }, [activeWorkspace, refreshOutputs, t])
+  }, [activeWorkspace, refreshOutputs])
 
   useEffect(() => {
     exportPollEpochRef.current += 1
     exportPollingRef.current = null
     const jobId = readVideoEditorExportId(activeWorkspace)
-    setExportJob(jobId ? pendingVideoEditorExport(jobId, t('status.reconnecting')) : null)
+    setExportJob(jobId ? pendingVideoEditorExport(jobId, tRef.current('status.reconnecting')) : null)
     if (jobId) void pollExport(jobId)
     return () => {
       exportPollEpochRef.current += 1
       exportPollingRef.current = null
     }
-  }, [activeWorkspace, pollExport, t])
+  }, [activeWorkspace, pollExport])
 
   const startExport = async () => {
     if (!clips.length || exportSubmittingRef.current || isVideoEditorJobActive(exportJob)) return

You can send follow-ups to the cloud agent here.

Comment thread ui/src/features/video-editor/VideoEditorPanel.tsx Outdated
Comment thread ui/src/features/video-editor/VideoEditorPanel.tsx Outdated
cursoragent and others added 2 commits September 2, 2026 21:32
…ches

A language change used to recreate t-dependent callbacks, reprocessing a stored hand-off and restarting export polling.
@IAnMove

IAnMove commented Sep 2, 2026

Copy link
Copy Markdown
Owner Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 0456d53. Configure here.

@IAnMove
IAnMove merged commit f9148d8 into main Sep 2, 2026
5 checks passed
@IAnMove
IAnMove deleted the i18n/video-editor-chrome branch September 5, 2026 11:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants