From 2f66f9c173c524262103f20508045574cd6397a4 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Mon, 6 Apr 2026 18:05:42 +0000 Subject: [PATCH] feat: default to english, expand to 197 keys, persist locale in localStorage - Default locale is now English (not auto-detected) - Alert banner on home shows when browser language differs, offering to switch - Language preference stored in localStorage (wm_locale) for long persistence - Expanded from 90 to 197 translation keys covering actions, editor, pages - All 7 language files updated to match Co-Authored-By: Claude Opus 4.6 (1M context) --- .../lib/components/sidebar/UserMenu.svelte | 19 +-- frontend/src/lib/i18n/messages/de.ts | 158 +++++++++++++++++- frontend/src/lib/i18n/messages/en.ts | 158 +++++++++++++++++- frontend/src/lib/i18n/messages/es.ts | 158 +++++++++++++++++- frontend/src/lib/i18n/messages/fr.ts | 158 +++++++++++++++++- frontend/src/lib/i18n/messages/ja.ts | 158 +++++++++++++++++- frontend/src/lib/i18n/messages/ko.ts | 158 +++++++++++++++++- frontend/src/lib/i18n/messages/pt.ts | 158 +++++++++++++++++- frontend/src/lib/i18n/messages/zh.ts | 158 +++++++++++++++++- frontend/src/lib/i18n/t.svelte.ts | 55 +++--- .../src/routes/(root)/(logged)/+page.svelte | 10 +- 11 files changed, 1298 insertions(+), 50 deletions(-) diff --git a/frontend/src/lib/components/sidebar/UserMenu.svelte b/frontend/src/lib/components/sidebar/UserMenu.svelte index 889a2d8d56..a706aba5c8 100644 --- a/frontend/src/lib/components/sidebar/UserMenu.svelte +++ b/frontend/src/lib/components/sidebar/UserMenu.svelte @@ -16,7 +16,7 @@ import MenuButton from './MenuButton.svelte' import { Menu, MenuItem } from '$lib/components/meltComponents' import { type MenubarBuilders } from '@melt-ui/svelte' - import { t, getLocale, getLocaleChoice, setLocale } from '$lib/i18n/t.svelte' + import { t, getLocale, setLocale } from '$lib/i18n/t.svelte' import { SUPPORTED_LOCALES, LOCALE_NAMES } from '$lib/i18n/index' let showLanguages = $state(false) @@ -101,30 +101,17 @@ }} > - {t('user.language')}: {getLocaleChoice() === 'auto' - ? 'Detected' - : LOCALE_NAMES[getLocale()]} + {t('user.language')}: {LOCALE_NAMES[getLocale()]} {#if showLanguages}
- setLocale('auto')} - class={twMerge( - itemClass, - 'pl-8', - getLocaleChoice() === 'auto' ? 'font-semibold text-primary' : '' - )} - {item} - > - Detected ({LOCALE_NAMES[getLocale()]}) - {#each SUPPORTED_LOCALES as loc (loc)} setLocale(loc)} class={twMerge( itemClass, 'pl-8', - getLocaleChoice() === loc ? 'font-semibold text-primary' : '' + getLocale() === loc ? 'font-semibold text-primary' : '' )} {item} > diff --git a/frontend/src/lib/i18n/messages/de.ts b/frontend/src/lib/i18n/messages/de.ts index 9a67e9379e..df11edde1f 100644 --- a/frontend/src/lib/i18n/messages/de.ts +++ b/frontend/src/lib/i18n/messages/de.ts @@ -78,6 +78,33 @@ export const de: Record = { 'action.close': 'Schließen', 'action.confirm': 'Bestätigen', 'action.refresh': 'Aktualisieren', + 'action.duplicate': 'Duplizieren', + 'action.fork': 'Fork', + 'action.rename': 'Umbenennen', + 'action.move': 'Verschieben', + 'action.copy_path': 'Pfad kopieren', + 'action.export': 'Exportieren', + 'action.undo': 'Rückgängig', + 'action.redo': 'Wiederholen', + 'action.test': 'Testen', + 'action.view': 'Ansehen', + 'action.next': 'Weiter', + 'action.previous': 'Zurück', + 'action.remove': 'Entfernen', + 'action.enable': 'Aktivieren', + 'action.disable': 'Deaktivieren', + 'action.see_permissions': 'Berechtigungen', + 'action.deploy_to_prod': 'Auf Prod deployen', + 'action.refresh_token': 'Token erneuern', + 'action.view_runs': 'Ausführungen', + 'action.view_code': 'Code ansehen', + 'action.audit_logs': 'Audit-Logs', + 'action.schedule': 'Planen', + 'action.versions': 'Versionen', + 'action.delete_draft': 'Draft löschen', + 'action.publish_to_hub': 'Im Hub veröffentlichen', + 'action.run_now': 'Jetzt ausführen', + 'action.manage': 'Verwalten', // Page headers 'page.home': 'Start', @@ -86,5 +113,134 @@ export const de: Record = { 'page.schedules': 'Zeitpläne', 'page.workers': 'Workers', 'page.folders': 'Ordner', - 'page.groups': 'Gruppen' + 'page.groups': 'Gruppen', + 'page.runs': 'Ausführungen', + + // Home page + 'home.create_a': 'Erstellen:', + 'home.workspace': 'Workspace', + 'home.hub': 'Hub', + 'home.scripts': 'Skripte', + 'home.flows': 'Flows', + 'home.apps': 'Apps', + 'home.hub_flow': 'Hub-Flow', + 'home.hub_app': 'Hub-App', + 'home.view_on_hub': 'Im Hub ansehen', + 'home.content': 'Inhalte', + + // Variables page + 'variables.new_variable': 'Neue Variable', + 'variables.new_contextual': 'Neue Kontextvariable', + 'variables.contextual': 'Kontext', + 'variables.custom_contextual': 'Eigene Kontextvariablen', + 'variables.contextual_vars': 'Kontextvariablen', + 'variables.no_variables': 'Keine Variablen gefunden', + 'variables.path': 'Pfad', + 'variables.value': 'Wert', + 'variables.description': 'Beschreibung', + + // Resources page + 'resources.new_resource': 'Neue Ressource', + + // Schedules page + 'schedules.duplicate': 'Zeitplan duplizieren', + 'schedules.view_script': 'Skript ansehen', + 'schedules.view_flow': 'Flow ansehen', + + // Runs page + 'runs.cancel_jobs': 'Jobs abbrechen', + 'runs.rerun_jobs': 'Jobs neu starten', + 'runs.cancel_all': 'Alle gefilterten Jobs abbrechen', + 'runs.rerun_all': 'Alle gefilterten Jobs neu starten', + 'runs.force_cancel': 'Erzwungen abbrechen', + + // Editor - common + 'editor.save': 'Speichern', + 'editor.deploy': 'Deployen', + 'editor.draft': 'Draft', + 'editor.test': 'Testen', + 'editor.test_and_record': 'Testen & aufzeichnen', + 'editor.history': 'Verlauf', + 'editor.versions_history': 'Versionsverlauf', + 'editor.deployment_history': 'Deployment-Verlauf', + 'editor.edit_in_yaml': 'In YAML bearbeiten', + 'editor.flow_settings': 'Flow-Einstellungen', + 'editor.export': 'Exportieren', + 'editor.diff': 'Diff', + 'editor.editor': 'Editor', + 'editor.preview': 'Vorschau', + 'editor.main': 'Main', + 'editor.preprocessor': 'Preprocessor', + 'editor.diagram': 'Diagramm', + 'editor.save_to_workspace': 'Im Workspace speichern', + 'editor.exit_see_details': 'Beenden & Details', + 'editor.edit_in_fork': 'Im Fork bearbeiten', + 'editor.save_anyway': 'Trotzdem speichern', + 'editor.invite_others': 'Andere einladen', + + // Flow editor + 'flow.test_flow': 'Flow testen', + 'flow.test_flow_record': 'Flow testen & aufzeichnen', + 'flow.build_a_flow': 'Flow erstellen', + 'flow.fix_broken_flow': 'Flow reparieren', + 'flow.reset_tutorials': 'Tutorials zurücksetzen', + 'flow.skip_tutorials': 'Tutorials überspringen', + 'flow.create_group': 'Gruppe erstellen', + 'flow.test_iteration': 'Iteration testen', + 'flow.skip_failures': 'Fehler überspringen', + 'flow.run_parallel': 'Parallel ausführen', + + // App editor + 'app.public_url': 'Öffentliche URL', + 'app.app_inputs': 'App-Eingaben', + 'app.schedule_reports': 'Berichte planen', + 'app.troubleshoot': 'Fehlerbehebung', + 'app.lazy_mode': 'Lazy-Modus', + 'app.hub_export': 'Hub-Export', + + // Status labels + 'status.default': 'Standard', + 'status.primary': 'Primär', + 'status.modified': 'Geändert', + 'status.draft': 'Draft', + + // Tabs - common + 'tab.workspace': 'Workspace', + 'tab.contextual': 'Kontext', + 'tab.hub': 'Hub', + 'tab.scripts': 'Skripte', + 'tab.flows': 'Flows', + 'tab.apps': 'Apps', + + // Row actions (scripts/flows/apps) + 'row.view_json': 'JSON/YAML ansehen', + 'row.move_rename': 'Verschieben/Umbenennen', + 'row.duplicate_fork': 'Duplizieren/Fork', + 'row.go_to_public_page': 'Öffentliche Seite', + 'row.deployments': 'Deployments', + + // Confirmation dialogs + 'confirm.delete_forever': 'Endgültig löschen', + 'confirm.empty_trashbin': 'Papierkorb leeren', + 'confirm.discard_changes': 'Änderungen verwerfen', + 'confirm.override': 'Überschreiben', + + // Groups/Folders + 'groups.manage_group': 'Gruppe verwalten', + 'groups.new_group': 'Neue Gruppe', + 'folders.manage_folder': 'Ordner verwalten', + 'folders.new_folder': 'Neuer Ordner', + + // Triggers + 'triggers.suspend_job': 'Job pausieren', + 'triggers.more_triggers': 'Weitere Trigger', + 'triggers.scheduled_poll': 'Geplante Abfrage', + + // Misc + 'misc.all_workspaces': 'Alle Workspaces', + 'misc.instance_settings': 'Instanzeinstellungen', + 'misc.search': 'Suchen', + 'misc.filter': 'Filtern', + 'misc.tree_view': 'Baumansicht', + 'misc.loading': 'Laden...' } diff --git a/frontend/src/lib/i18n/messages/en.ts b/frontend/src/lib/i18n/messages/en.ts index ea19ac4689..9a3d3b3ca6 100644 --- a/frontend/src/lib/i18n/messages/en.ts +++ b/frontend/src/lib/i18n/messages/en.ts @@ -76,6 +76,33 @@ export const en = { 'action.close': 'Close', 'action.confirm': 'Confirm', 'action.refresh': 'Refresh', + 'action.duplicate': 'Duplicate', + 'action.fork': 'Fork', + 'action.rename': 'Rename', + 'action.move': 'Move', + 'action.copy_path': 'Copy path', + 'action.export': 'Export', + 'action.undo': 'Undo', + 'action.redo': 'Redo', + 'action.test': 'Test', + 'action.view': 'View', + 'action.next': 'Next', + 'action.previous': 'Previous', + 'action.remove': 'Remove', + 'action.enable': 'Enable', + 'action.disable': 'Disable', + 'action.see_permissions': 'See Permissions', + 'action.deploy_to_prod': 'Deploy to prod/staging', + 'action.refresh_token': 'Refresh token', + 'action.view_runs': 'View runs', + 'action.view_code': 'View code', + 'action.audit_logs': 'Audit logs', + 'action.schedule': 'Schedule', + 'action.versions': 'Versions', + 'action.delete_draft': 'Delete Draft', + 'action.publish_to_hub': 'Publish to Hub', + 'action.run_now': 'Run now', + 'action.manage': 'Manage', // Page headers 'page.home': 'Home', @@ -84,7 +111,136 @@ export const en = { 'page.schedules': 'Schedules', 'page.workers': 'Workers', 'page.folders': 'Folders', - 'page.groups': 'Groups' + 'page.groups': 'Groups', + 'page.runs': 'Runs', + + // Home page + 'home.create_a': 'Create a', + 'home.workspace': 'Workspace', + 'home.hub': 'Hub', + 'home.scripts': 'Scripts', + 'home.flows': 'Flows', + 'home.apps': 'Apps', + 'home.hub_flow': 'Hub flow', + 'home.hub_app': 'Hub app', + 'home.view_on_hub': 'View on the Hub', + 'home.content': 'Content', + + // Variables page + 'variables.new_variable': 'New variable', + 'variables.new_contextual': 'New contextual variable', + 'variables.contextual': 'Contextual', + 'variables.custom_contextual': 'Custom contextual variables', + 'variables.contextual_vars': 'Contextual variables', + 'variables.no_variables': 'No variables found', + 'variables.path': 'Path', + 'variables.value': 'Value', + 'variables.description': 'Description', + + // Resources page + 'resources.new_resource': 'New resource', + + // Schedules page + 'schedules.duplicate': 'Duplicate schedule', + 'schedules.view_script': 'View Script', + 'schedules.view_flow': 'View Flow', + + // Runs page + 'runs.cancel_jobs': 'Cancel jobs', + 'runs.rerun_jobs': 'Re-run jobs', + 'runs.cancel_all': 'Cancel all jobs matching filters', + 'runs.rerun_all': 'Re-run all jobs matching filters', + 'runs.force_cancel': 'Force Cancel', + + // Editor - common + 'editor.save': 'Save', + 'editor.deploy': 'Deploy', + 'editor.draft': 'Draft', + 'editor.test': 'Test', + 'editor.test_and_record': 'Test & record', + 'editor.history': 'History', + 'editor.versions_history': 'Versions History', + 'editor.deployment_history': 'Deployment History', + 'editor.edit_in_yaml': 'Edit in YAML', + 'editor.flow_settings': 'Flow settings', + 'editor.export': 'Export', + 'editor.diff': 'Diff', + 'editor.editor': 'Editor', + 'editor.preview': 'Preview', + 'editor.main': 'Main', + 'editor.preprocessor': 'Preprocessor', + 'editor.diagram': 'Diagram', + 'editor.save_to_workspace': 'Save to workspace', + 'editor.exit_see_details': 'Exit & see details', + 'editor.edit_in_fork': 'Edit in workspace fork', + 'editor.save_anyway': 'Save anyway', + 'editor.invite_others': 'Invite others', + + // Flow editor + 'flow.test_flow': 'Test flow', + 'flow.test_flow_record': 'Test flow & record', + 'flow.build_a_flow': 'Build a flow', + 'flow.fix_broken_flow': 'Fix a broken flow', + 'flow.reset_tutorials': 'Reset tutorials', + 'flow.skip_tutorials': 'Skip tutorials', + 'flow.create_group': 'Create group', + 'flow.test_iteration': 'Test an iteration', + 'flow.skip_failures': 'Skip failures', + 'flow.run_parallel': 'Run in parallel', + + // App editor + 'app.public_url': 'Public URL', + 'app.app_inputs': 'App inputs', + 'app.schedule_reports': 'Schedule reports', + 'app.troubleshoot': 'Troubleshoot panel', + 'app.lazy_mode': 'Lazy mode', + 'app.hub_export': 'Hub export', + + // Status labels + 'status.default': 'Default', + 'status.primary': 'Primary', + 'status.modified': 'Modified', + 'status.draft': 'Draft', + + // Tabs - common + 'tab.workspace': 'Workspace', + 'tab.contextual': 'Contextual', + 'tab.hub': 'Hub', + 'tab.scripts': 'Scripts', + 'tab.flows': 'Flows', + 'tab.apps': 'Apps', + + // Row actions (scripts/flows/apps) + 'row.view_json': 'View JSON/YAML', + 'row.move_rename': 'Move/Rename', + 'row.duplicate_fork': 'Duplicate/Fork', + 'row.go_to_public_page': 'Go to public page', + 'row.deployments': 'Deployments', + + // Confirmation dialogs + 'confirm.delete_forever': 'Delete forever', + 'confirm.empty_trashbin': 'Empty trashbin', + 'confirm.discard_changes': 'Discard changes', + 'confirm.override': 'Override', + + // Groups/Folders + 'groups.manage_group': 'Manage group', + 'groups.new_group': 'New group', + 'folders.manage_folder': 'Manage folder', + 'folders.new_folder': 'New folder', + + // Triggers + 'triggers.suspend_job': 'Suspend job execution', + 'triggers.more_triggers': 'More triggers', + 'triggers.scheduled_poll': 'Scheduled Poll', + + // Misc + 'misc.all_workspaces': 'All workspaces', + 'misc.instance_settings': 'Instance settings', + 'misc.search': 'Search', + 'misc.filter': 'Filter', + 'misc.tree_view': 'Tree view', + 'misc.loading': 'Loading...' } as const export type MessageKey = keyof typeof en diff --git a/frontend/src/lib/i18n/messages/es.ts b/frontend/src/lib/i18n/messages/es.ts index 35cfb561ba..1db3701e88 100644 --- a/frontend/src/lib/i18n/messages/es.ts +++ b/frontend/src/lib/i18n/messages/es.ts @@ -78,6 +78,33 @@ export const es: Record = { 'action.close': 'Cerrar', 'action.confirm': 'Confirmar', 'action.refresh': 'Actualizar', + 'action.duplicate': 'Duplicar', + 'action.fork': 'Fork', + 'action.rename': 'Renombrar', + 'action.move': 'Mover', + 'action.copy_path': 'Copiar ruta', + 'action.export': 'Exportar', + 'action.undo': 'Deshacer', + 'action.redo': 'Rehacer', + 'action.test': 'Probar', + 'action.view': 'Ver', + 'action.next': 'Siguiente', + 'action.previous': 'Anterior', + 'action.remove': 'Quitar', + 'action.enable': 'Activar', + 'action.disable': 'Desactivar', + 'action.see_permissions': 'Ver permisos', + 'action.deploy_to_prod': 'Desplegar a prod/staging', + 'action.refresh_token': 'Renovar token', + 'action.view_runs': 'Ver ejecuciones', + 'action.view_code': 'Ver código', + 'action.audit_logs': 'Auditoría', + 'action.schedule': 'Programar', + 'action.versions': 'Versiones', + 'action.delete_draft': 'Eliminar Draft', + 'action.publish_to_hub': 'Publicar en Hub', + 'action.run_now': 'Ejecutar ahora', + 'action.manage': 'Gestionar', // Page headers 'page.home': 'Inicio', @@ -86,5 +113,134 @@ export const es: Record = { 'page.schedules': 'Programados', 'page.workers': 'Workers', 'page.folders': 'Carpetas', - 'page.groups': 'Grupos' + 'page.groups': 'Grupos', + 'page.runs': 'Ejecuciones', + + // Home page + 'home.create_a': 'Crear un', + 'home.workspace': 'Espacio', + 'home.hub': 'Hub', + 'home.scripts': 'Scripts', + 'home.flows': 'Flujos', + 'home.apps': 'Apps', + 'home.hub_flow': 'Flujo de Hub', + 'home.hub_app': 'App de Hub', + 'home.view_on_hub': 'Ver en el Hub', + 'home.content': 'Contenido', + + // Variables page + 'variables.new_variable': 'Nueva variable', + 'variables.new_contextual': 'Nueva var. contextual', + 'variables.contextual': 'Contextual', + 'variables.custom_contextual': 'Variables contextuales', + 'variables.contextual_vars': 'Variables contextuales', + 'variables.no_variables': 'No se encontraron variables', + 'variables.path': 'Ruta', + 'variables.value': 'Valor', + 'variables.description': 'Descripción', + + // Resources page + 'resources.new_resource': 'Nuevo recurso', + + // Schedules page + 'schedules.duplicate': 'Duplicar programa', + 'schedules.view_script': 'Ver Script', + 'schedules.view_flow': 'Ver Flujo', + + // Runs page + 'runs.cancel_jobs': 'Cancelar trabajos', + 'runs.rerun_jobs': 'Reiniciar trabajos', + 'runs.cancel_all': 'Cancelar todos según filtros', + 'runs.rerun_all': 'Reiniciar todos según filtros', + 'runs.force_cancel': 'Forzar cancelación', + + // Editor - common + 'editor.save': 'Guardar', + 'editor.deploy': 'Desplegar', + 'editor.draft': 'Draft', + 'editor.test': 'Probar', + 'editor.test_and_record': 'Probar y grabar', + 'editor.history': 'Historial', + 'editor.versions_history': 'Historial de versiones', + 'editor.deployment_history': 'Historial de despliegues', + 'editor.edit_in_yaml': 'Editar en YAML', + 'editor.flow_settings': 'Ajustes del flujo', + 'editor.export': 'Exportar', + 'editor.diff': 'Diff', + 'editor.editor': 'Editor', + 'editor.preview': 'Vista previa', + 'editor.main': 'Principal', + 'editor.preprocessor': 'Preprocesador', + 'editor.diagram': 'Diagrama', + 'editor.save_to_workspace': 'Guardar en espacio', + 'editor.exit_see_details': 'Salir y ver detalles', + 'editor.edit_in_fork': 'Editar en fork', + 'editor.save_anyway': 'Guardar de todos modos', + 'editor.invite_others': 'Invitar a otros', + + // Flow editor + 'flow.test_flow': 'Probar flujo', + 'flow.test_flow_record': 'Probar flujo y grabar', + 'flow.build_a_flow': 'Crear un flujo', + 'flow.fix_broken_flow': 'Reparar flujo roto', + 'flow.reset_tutorials': 'Reiniciar tutoriales', + 'flow.skip_tutorials': 'Omitir tutoriales', + 'flow.create_group': 'Crear grupo', + 'flow.test_iteration': 'Probar iteración', + 'flow.skip_failures': 'Omitir errores', + 'flow.run_parallel': 'Ejecutar en paralelo', + + // App editor + 'app.public_url': 'URL pública', + 'app.app_inputs': 'Entradas de app', + 'app.schedule_reports': 'Programar informes', + 'app.troubleshoot': 'Panel de diagnóstico', + 'app.lazy_mode': 'Modo lazy', + 'app.hub_export': 'Exportar a Hub', + + // Status labels + 'status.default': 'Por defecto', + 'status.primary': 'Primario', + 'status.modified': 'Modificado', + 'status.draft': 'Draft', + + // Tabs - common + 'tab.workspace': 'Espacio', + 'tab.contextual': 'Contextual', + 'tab.hub': 'Hub', + 'tab.scripts': 'Scripts', + 'tab.flows': 'Flujos', + 'tab.apps': 'Apps', + + // Row actions (scripts/flows/apps) + 'row.view_json': 'Ver JSON/YAML', + 'row.move_rename': 'Mover/Renombrar', + 'row.duplicate_fork': 'Duplicar/Fork', + 'row.go_to_public_page': 'Ir a página pública', + 'row.deployments': 'Despliegues', + + // Confirmation dialogs + 'confirm.delete_forever': 'Eliminar para siempre', + 'confirm.empty_trashbin': 'Vaciar papelera', + 'confirm.discard_changes': 'Descartar cambios', + 'confirm.override': 'Sobrescribir', + + // Groups/Folders + 'groups.manage_group': 'Gestionar grupo', + 'groups.new_group': 'Nuevo grupo', + 'folders.manage_folder': 'Gestionar carpeta', + 'folders.new_folder': 'Nueva carpeta', + + // Triggers + 'triggers.suspend_job': 'Suspender ejecución', + 'triggers.more_triggers': 'Más disparadores', + 'triggers.scheduled_poll': 'Sondeo programado', + + // Misc + 'misc.all_workspaces': 'Todos los espacios', + 'misc.instance_settings': 'Ajustes de instancia', + 'misc.search': 'Buscar', + 'misc.filter': 'Filtrar', + 'misc.tree_view': 'Vista de árbol', + 'misc.loading': 'Cargando...' } diff --git a/frontend/src/lib/i18n/messages/fr.ts b/frontend/src/lib/i18n/messages/fr.ts index b40a9bdac4..bdac7d9c63 100644 --- a/frontend/src/lib/i18n/messages/fr.ts +++ b/frontend/src/lib/i18n/messages/fr.ts @@ -78,6 +78,33 @@ export const fr: Record = { 'action.close': 'Fermer', 'action.confirm': 'Confirmer', 'action.refresh': 'Actualiser', + 'action.duplicate': 'Dupliquer', + 'action.fork': 'Fork', + 'action.rename': 'Renommer', + 'action.move': 'Déplacer', + 'action.copy_path': 'Copier le chemin', + 'action.export': 'Exporter', + 'action.undo': 'Annuler', + 'action.redo': 'Rétablir', + 'action.test': 'Tester', + 'action.view': 'Voir', + 'action.next': 'Suivant', + 'action.previous': 'Précédent', + 'action.remove': 'Retirer', + 'action.enable': 'Activer', + 'action.disable': 'Désactiver', + 'action.see_permissions': 'Voir les permissions', + 'action.deploy_to_prod': 'Déployer en prod/staging', + 'action.refresh_token': 'Rafraîchir le token', + 'action.view_runs': 'Voir les exécutions', + 'action.view_code': 'Voir le code', + 'action.audit_logs': "Journaux d'audit", + 'action.schedule': 'Planifier', + 'action.versions': 'Versions', + 'action.delete_draft': 'Supprimer le Draft', + 'action.publish_to_hub': 'Publier sur le Hub', + 'action.run_now': 'Lancer maintenant', + 'action.manage': 'Gérer', // Page headers 'page.home': 'Accueil', @@ -86,5 +113,134 @@ export const fr: Record = { 'page.schedules': 'Plannings', 'page.workers': 'Workers', 'page.folders': 'Dossiers', - 'page.groups': 'Groupes' + 'page.groups': 'Groupes', + 'page.runs': 'Exécutions', + + // Home page + 'home.create_a': 'Créer un', + 'home.workspace': 'Espace', + 'home.hub': 'Hub', + 'home.scripts': 'Scripts', + 'home.flows': 'Flows', + 'home.apps': 'Apps', + 'home.hub_flow': 'Flow du Hub', + 'home.hub_app': 'App du Hub', + 'home.view_on_hub': 'Voir sur le Hub', + 'home.content': 'Contenu', + + // Variables page + 'variables.new_variable': 'Nouvelle variable', + 'variables.new_contextual': 'Nouvelle var. contextuelle', + 'variables.contextual': 'Contextuelle', + 'variables.custom_contextual': 'Variables contextuelles', + 'variables.contextual_vars': 'Variables contextuelles', + 'variables.no_variables': 'Aucune variable trouvée', + 'variables.path': 'Chemin', + 'variables.value': 'Valeur', + 'variables.description': 'Description', + + // Resources page + 'resources.new_resource': 'Nouvelle ressource', + + // Schedules page + 'schedules.duplicate': 'Dupliquer le planning', + 'schedules.view_script': 'Voir le script', + 'schedules.view_flow': 'Voir le flow', + + // Runs page + 'runs.cancel_jobs': 'Annuler les jobs', + 'runs.rerun_jobs': 'Relancer les jobs', + 'runs.cancel_all': 'Annuler tous les jobs filtrés', + 'runs.rerun_all': 'Relancer tous les jobs filtrés', + 'runs.force_cancel': "Forcer l'annulation", + + // Editor - common + 'editor.save': 'Enregistrer', + 'editor.deploy': 'Déployer', + 'editor.draft': 'Draft', + 'editor.test': 'Tester', + 'editor.test_and_record': 'Tester & enregistrer', + 'editor.history': 'Historique', + 'editor.versions_history': 'Historique des versions', + 'editor.deployment_history': 'Historique des déploiements', + 'editor.edit_in_yaml': 'Éditer en YAML', + 'editor.flow_settings': 'Paramètres du flow', + 'editor.export': 'Exporter', + 'editor.diff': 'Diff', + 'editor.editor': 'Éditeur', + 'editor.preview': 'Aperçu', + 'editor.main': 'Principal', + 'editor.preprocessor': 'Préprocesseur', + 'editor.diagram': 'Diagramme', + 'editor.save_to_workspace': "Enregistrer dans l'espace", + 'editor.exit_see_details': 'Quitter & voir détails', + 'editor.edit_in_fork': 'Éditer dans le fork', + 'editor.save_anyway': 'Enregistrer quand même', + 'editor.invite_others': "Inviter d'autres", + + // Flow editor + 'flow.test_flow': 'Tester le flow', + 'flow.test_flow_record': 'Tester & enregistrer', + 'flow.build_a_flow': 'Créer un flow', + 'flow.fix_broken_flow': 'Réparer un flow', + 'flow.reset_tutorials': 'Réinitialiser les tutoriels', + 'flow.skip_tutorials': 'Passer les tutoriels', + 'flow.create_group': 'Créer un groupe', + 'flow.test_iteration': 'Tester une itération', + 'flow.skip_failures': 'Ignorer les erreurs', + 'flow.run_parallel': 'Lancer en parallèle', + + // App editor + 'app.public_url': 'URL publique', + 'app.app_inputs': "Entrées de l'app", + 'app.schedule_reports': 'Planifier les rapports', + 'app.troubleshoot': 'Dépannage', + 'app.lazy_mode': 'Mode lazy', + 'app.hub_export': 'Export Hub', + + // Status labels + 'status.default': 'Défaut', + 'status.primary': 'Principal', + 'status.modified': 'Modifié', + 'status.draft': 'Draft', + + // Tabs - common + 'tab.workspace': 'Espace', + 'tab.contextual': 'Contextuel', + 'tab.hub': 'Hub', + 'tab.scripts': 'Scripts', + 'tab.flows': 'Flows', + 'tab.apps': 'Apps', + + // Row actions (scripts/flows/apps) + 'row.view_json': 'Voir JSON/YAML', + 'row.move_rename': 'Déplacer/Renommer', + 'row.duplicate_fork': 'Dupliquer/Fork', + 'row.go_to_public_page': 'Aller à la page publique', + 'row.deployments': 'Déploiements', + + // Confirmation dialogs + 'confirm.delete_forever': 'Supprimer définitivement', + 'confirm.empty_trashbin': 'Vider la corbeille', + 'confirm.discard_changes': 'Abandonner les modifications', + 'confirm.override': 'Écraser', + + // Groups/Folders + 'groups.manage_group': 'Gérer le groupe', + 'groups.new_group': 'Nouveau groupe', + 'folders.manage_folder': 'Gérer le dossier', + 'folders.new_folder': 'Nouveau dossier', + + // Triggers + 'triggers.suspend_job': "Suspendre l'exécution", + 'triggers.more_triggers': 'Plus de déclencheurs', + 'triggers.scheduled_poll': 'Sondage planifié', + + // Misc + 'misc.all_workspaces': 'Tous les espaces', + 'misc.instance_settings': "Paramètres d'instance", + 'misc.search': 'Rechercher', + 'misc.filter': 'Filtrer', + 'misc.tree_view': 'Vue arborescente', + 'misc.loading': 'Chargement...' } diff --git a/frontend/src/lib/i18n/messages/ja.ts b/frontend/src/lib/i18n/messages/ja.ts index 16c5ea3479..95614df6a9 100644 --- a/frontend/src/lib/i18n/messages/ja.ts +++ b/frontend/src/lib/i18n/messages/ja.ts @@ -78,6 +78,33 @@ export const ja: Record = { 'action.close': '閉じる', 'action.confirm': '確認', 'action.refresh': '更新', + 'action.duplicate': '複製', + 'action.fork': 'フォーク', + 'action.rename': '名前変更', + 'action.move': '移動', + 'action.copy_path': 'パスをコピー', + 'action.export': 'エクスポート', + 'action.undo': '元に戻す', + 'action.redo': 'やり直す', + 'action.test': 'テスト', + 'action.view': '表示', + 'action.next': '次へ', + 'action.previous': '前へ', + 'action.remove': '削除', + 'action.enable': '有効化', + 'action.disable': '無効化', + 'action.see_permissions': '権限を表示', + 'action.deploy_to_prod': '本番/ステージングにデプロイ', + 'action.refresh_token': 'トークンを更新', + 'action.view_runs': '実行を表示', + 'action.view_code': 'コードを表示', + 'action.audit_logs': '監査ログ', + 'action.schedule': 'スケジュール', + 'action.versions': 'バージョン', + 'action.delete_draft': 'Draftを削除', + 'action.publish_to_hub': 'Hubに公開', + 'action.run_now': '今すぐ実行', + 'action.manage': '管理', // Page headers 'page.home': 'ホーム', @@ -86,5 +113,134 @@ export const ja: Record = { 'page.schedules': 'スケジュール', 'page.workers': 'ワーカー', 'page.folders': 'フォルダ', - 'page.groups': 'グループ' + 'page.groups': 'グループ', + 'page.runs': '実行', + + // Home page + 'home.create_a': '作成:', + 'home.workspace': 'ワークスペース', + 'home.hub': 'Hub', + 'home.scripts': 'スクリプト', + 'home.flows': 'フロー', + 'home.apps': 'アプリ', + 'home.hub_flow': 'Hubフロー', + 'home.hub_app': 'Hubアプリ', + 'home.view_on_hub': 'Hubで表示', + 'home.content': 'コンテンツ', + + // Variables page + 'variables.new_variable': '新しい変数', + 'variables.new_contextual': '新しいコンテキスト変数', + 'variables.contextual': 'コンテキスト', + 'variables.custom_contextual': 'カスタムコンテキスト変数', + 'variables.contextual_vars': 'コンテキスト変数', + 'variables.no_variables': '変数が見つかりません', + 'variables.path': 'パス', + 'variables.value': '値', + 'variables.description': '説明', + + // Resources page + 'resources.new_resource': '新しいリソース', + + // Schedules page + 'schedules.duplicate': 'スケジュールを複製', + 'schedules.view_script': 'スクリプトを表示', + 'schedules.view_flow': 'フローを表示', + + // Runs page + 'runs.cancel_jobs': 'ジョブをキャンセル', + 'runs.rerun_jobs': 'ジョブを再実行', + 'runs.cancel_all': 'フィルター一致のジョブを全てキャンセル', + 'runs.rerun_all': 'フィルター一致のジョブを全て再実行', + 'runs.force_cancel': '強制キャンセル', + + // Editor - common + 'editor.save': '保存', + 'editor.deploy': 'デプロイ', + 'editor.draft': 'Draft', + 'editor.test': 'テスト', + 'editor.test_and_record': 'テストして記録', + 'editor.history': '履歴', + 'editor.versions_history': 'バージョン履歴', + 'editor.deployment_history': 'デプロイ履歴', + 'editor.edit_in_yaml': 'YAMLで編集', + 'editor.flow_settings': 'フロー設定', + 'editor.export': 'エクスポート', + 'editor.diff': '差分', + 'editor.editor': 'エディタ', + 'editor.preview': 'プレビュー', + 'editor.main': 'メイン', + 'editor.preprocessor': 'プリプロセッサ', + 'editor.diagram': 'ダイアグラム', + 'editor.save_to_workspace': 'ワークスペースに保存', + 'editor.exit_see_details': '終了して詳細を表示', + 'editor.edit_in_fork': 'フォークで編集', + 'editor.save_anyway': 'そのまま保存', + 'editor.invite_others': '他のユーザーを招待', + + // Flow editor + 'flow.test_flow': 'フローをテスト', + 'flow.test_flow_record': 'フローをテストして記録', + 'flow.build_a_flow': 'フローを作成', + 'flow.fix_broken_flow': 'エラーのあるフローを修正', + 'flow.reset_tutorials': 'チュートリアルをリセット', + 'flow.skip_tutorials': 'チュートリアルをスキップ', + 'flow.create_group': 'グループを作成', + 'flow.test_iteration': 'イテレーションをテスト', + 'flow.skip_failures': '失敗をスキップ', + 'flow.run_parallel': '並列実行', + + // App editor + 'app.public_url': '公開URL', + 'app.app_inputs': 'アプリ入力', + 'app.schedule_reports': 'レポートをスケジュール', + 'app.troubleshoot': 'トラブルシュートパネル', + 'app.lazy_mode': '遅延モード', + 'app.hub_export': 'Hubエクスポート', + + // Status labels + 'status.default': 'デフォルト', + 'status.primary': 'プライマリ', + 'status.modified': '変更済み', + 'status.draft': 'Draft', + + // Tabs - common + 'tab.workspace': 'ワークスペース', + 'tab.contextual': 'コンテキスト', + 'tab.hub': 'Hub', + 'tab.scripts': 'スクリプト', + 'tab.flows': 'フロー', + 'tab.apps': 'アプリ', + + // Row actions (scripts/flows/apps) + 'row.view_json': 'JSON/YAMLを表示', + 'row.move_rename': '移動/名前変更', + 'row.duplicate_fork': '複製/フォーク', + 'row.go_to_public_page': '公開ページを表示', + 'row.deployments': 'デプロイ', + + // Confirmation dialogs + 'confirm.delete_forever': '完全に削除', + 'confirm.empty_trashbin': 'ゴミ箱を空にする', + 'confirm.discard_changes': '変更を破棄', + 'confirm.override': '上書き', + + // Groups/Folders + 'groups.manage_group': 'グループを管理', + 'groups.new_group': '新しいグループ', + 'folders.manage_folder': 'フォルダを管理', + 'folders.new_folder': '新しいフォルダ', + + // Triggers + 'triggers.suspend_job': 'ジョブ実行を一時停止', + 'triggers.more_triggers': 'その他のトリガー', + 'triggers.scheduled_poll': 'スケジュールポーリング', + + // Misc + 'misc.all_workspaces': '全ワークスペース', + 'misc.instance_settings': 'インスタンス設定', + 'misc.search': '検索', + 'misc.filter': 'フィルター', + 'misc.tree_view': 'ツリー表示', + 'misc.loading': '読み込み中...' } diff --git a/frontend/src/lib/i18n/messages/ko.ts b/frontend/src/lib/i18n/messages/ko.ts index 68e7ab73ba..17ba819a45 100644 --- a/frontend/src/lib/i18n/messages/ko.ts +++ b/frontend/src/lib/i18n/messages/ko.ts @@ -78,6 +78,33 @@ export const ko: Record = { 'action.close': '닫기', 'action.confirm': '확인', 'action.refresh': '새로고침', + 'action.duplicate': '복제', + 'action.fork': '포크', + 'action.rename': '이름 변경', + 'action.move': '이동', + 'action.copy_path': '경로 복사', + 'action.export': '내보내기', + 'action.undo': '실행 취소', + 'action.redo': '다시 실행', + 'action.test': '테스트', + 'action.view': '보기', + 'action.next': '다음', + 'action.previous': '이전', + 'action.remove': '제거', + 'action.enable': '활성화', + 'action.disable': '비활성화', + 'action.see_permissions': '권한 보기', + 'action.deploy_to_prod': '프로덕션/스테이징에 배포', + 'action.refresh_token': '토큰 갱신', + 'action.view_runs': '실행 보기', + 'action.view_code': '코드 보기', + 'action.audit_logs': '감사 로그', + 'action.schedule': '스케줄', + 'action.versions': '버전', + 'action.delete_draft': 'Draft 삭제', + 'action.publish_to_hub': 'Hub에 게시', + 'action.run_now': '지금 실행', + 'action.manage': '관리', // Page headers 'page.home': '홈', @@ -86,5 +113,134 @@ export const ko: Record = { 'page.schedules': '스케줄', 'page.workers': '워커', 'page.folders': '폴더', - 'page.groups': '그룹' + 'page.groups': '그룹', + 'page.runs': '실행', + + // Home page + 'home.create_a': '생성:', + 'home.workspace': '워크스페이스', + 'home.hub': 'Hub', + 'home.scripts': '스크립트', + 'home.flows': '플로우', + 'home.apps': '앱', + 'home.hub_flow': 'Hub 플로우', + 'home.hub_app': 'Hub 앱', + 'home.view_on_hub': 'Hub에서 보기', + 'home.content': '콘텐츠', + + // Variables page + 'variables.new_variable': '새 변수', + 'variables.new_contextual': '새 컨텍스트 변수', + 'variables.contextual': '컨텍스트', + 'variables.custom_contextual': '사용자 정의 컨텍스트 변수', + 'variables.contextual_vars': '컨텍스트 변수', + 'variables.no_variables': '변수를 찾을 수 없습니다', + 'variables.path': '경로', + 'variables.value': '값', + 'variables.description': '설명', + + // Resources page + 'resources.new_resource': '새 리소스', + + // Schedules page + 'schedules.duplicate': '스케줄 복제', + 'schedules.view_script': '스크립트 보기', + 'schedules.view_flow': '플로우 보기', + + // Runs page + 'runs.cancel_jobs': '작업 취소', + 'runs.rerun_jobs': '작업 재실행', + 'runs.cancel_all': '필터와 일치하는 모든 작업 취소', + 'runs.rerun_all': '필터와 일치하는 모든 작업 재실행', + 'runs.force_cancel': '강제 취소', + + // Editor - common + 'editor.save': '저장', + 'editor.deploy': '배포', + 'editor.draft': 'Draft', + 'editor.test': '테스트', + 'editor.test_and_record': '테스트 및 기록', + 'editor.history': '히스토리', + 'editor.versions_history': '버전 히스토리', + 'editor.deployment_history': '배포 히스토리', + 'editor.edit_in_yaml': 'YAML로 편집', + 'editor.flow_settings': '플로우 설정', + 'editor.export': '내보내기', + 'editor.diff': '차이점', + 'editor.editor': '편집기', + 'editor.preview': '미리보기', + 'editor.main': '메인', + 'editor.preprocessor': '전처리기', + 'editor.diagram': '다이어그램', + 'editor.save_to_workspace': '워크스페이스에 저장', + 'editor.exit_see_details': '종료 후 상세 보기', + 'editor.edit_in_fork': '포크에서 편집', + 'editor.save_anyway': '그래도 저장', + 'editor.invite_others': '다른 사용자 초대', + + // Flow editor + 'flow.test_flow': '플로우 테스트', + 'flow.test_flow_record': '플로우 테스트 및 기록', + 'flow.build_a_flow': '플로우 만들기', + 'flow.fix_broken_flow': '오류 플로우 수정', + 'flow.reset_tutorials': '튜토리얼 초기화', + 'flow.skip_tutorials': '튜토리얼 건너뛰기', + 'flow.create_group': '그룹 생성', + 'flow.test_iteration': '반복 테스트', + 'flow.skip_failures': '실패 건너뛰기', + 'flow.run_parallel': '병렬 실행', + + // App editor + 'app.public_url': '공개 URL', + 'app.app_inputs': '앱 입력', + 'app.schedule_reports': '보고서 예약', + 'app.troubleshoot': '문제 해결 패널', + 'app.lazy_mode': '지연 모드', + 'app.hub_export': 'Hub 내보내기', + + // Status labels + 'status.default': '기본', + 'status.primary': '주요', + 'status.modified': '수정됨', + 'status.draft': 'Draft', + + // Tabs - common + 'tab.workspace': '워크스페이스', + 'tab.contextual': '컨텍스트', + 'tab.hub': 'Hub', + 'tab.scripts': '스크립트', + 'tab.flows': '플로우', + 'tab.apps': '앱', + + // Row actions (scripts/flows/apps) + 'row.view_json': 'JSON/YAML 보기', + 'row.move_rename': '이동/이름 변경', + 'row.duplicate_fork': '복제/포크', + 'row.go_to_public_page': '공개 페이지로 이동', + 'row.deployments': '배포', + + // Confirmation dialogs + 'confirm.delete_forever': '영구 삭제', + 'confirm.empty_trashbin': '휴지통 비우기', + 'confirm.discard_changes': '변경 사항 취소', + 'confirm.override': '덮어쓰기', + + // Groups/Folders + 'groups.manage_group': '그룹 관리', + 'groups.new_group': '새 그룹', + 'folders.manage_folder': '폴더 관리', + 'folders.new_folder': '새 폴더', + + // Triggers + 'triggers.suspend_job': '작업 실행 일시 중지', + 'triggers.more_triggers': '더 많은 트리거', + 'triggers.scheduled_poll': '예약 폴링', + + // Misc + 'misc.all_workspaces': '모든 워크스페이스', + 'misc.instance_settings': '인스턴스 설정', + 'misc.search': '검색', + 'misc.filter': '필터', + 'misc.tree_view': '트리 보기', + 'misc.loading': '로딩 중...' } diff --git a/frontend/src/lib/i18n/messages/pt.ts b/frontend/src/lib/i18n/messages/pt.ts index b648c12baa..c34a8d255a 100644 --- a/frontend/src/lib/i18n/messages/pt.ts +++ b/frontend/src/lib/i18n/messages/pt.ts @@ -78,6 +78,33 @@ export const pt: Record = { 'action.close': 'Fechar', 'action.confirm': 'Confirmar', 'action.refresh': 'Atualizar', + 'action.duplicate': 'Duplicar', + 'action.fork': 'Fork', + 'action.rename': 'Renomear', + 'action.move': 'Mover', + 'action.copy_path': 'Copiar caminho', + 'action.export': 'Exportar', + 'action.undo': 'Desfazer', + 'action.redo': 'Refazer', + 'action.test': 'Testar', + 'action.view': 'Visualizar', + 'action.next': 'Próximo', + 'action.previous': 'Anterior', + 'action.remove': 'Remover', + 'action.enable': 'Ativar', + 'action.disable': 'Desativar', + 'action.see_permissions': 'Ver permissões', + 'action.deploy_to_prod': 'Implantar em prod/staging', + 'action.refresh_token': 'Atualizar token', + 'action.view_runs': 'Ver execuções', + 'action.view_code': 'Ver código', + 'action.audit_logs': 'Auditoria', + 'action.schedule': 'Agendar', + 'action.versions': 'Versões', + 'action.delete_draft': 'Excluir Draft', + 'action.publish_to_hub': 'Publicar no Hub', + 'action.run_now': 'Executar agora', + 'action.manage': 'Gerenciar', // Page headers 'page.home': 'Início', @@ -86,5 +113,134 @@ export const pt: Record = { 'page.schedules': 'Agendamentos', 'page.workers': 'Workers', 'page.folders': 'Pastas', - 'page.groups': 'Grupos' + 'page.groups': 'Grupos', + 'page.runs': 'Execuções', + + // Home page + 'home.create_a': 'Criar um', + 'home.workspace': 'Workspace', + 'home.hub': 'Hub', + 'home.scripts': 'Scripts', + 'home.flows': 'Flows', + 'home.apps': 'Apps', + 'home.hub_flow': 'Flow do Hub', + 'home.hub_app': 'App do Hub', + 'home.view_on_hub': 'Ver no Hub', + 'home.content': 'Conteúdo', + + // Variables page + 'variables.new_variable': 'Nova variável', + 'variables.new_contextual': 'Nova variável contextual', + 'variables.contextual': 'Contextual', + 'variables.custom_contextual': 'Variáveis contextuais personalizadas', + 'variables.contextual_vars': 'Variáveis contextuais', + 'variables.no_variables': 'Nenhuma variável encontrada', + 'variables.path': 'Caminho', + 'variables.value': 'Valor', + 'variables.description': 'Descrição', + + // Resources page + 'resources.new_resource': 'Novo recurso', + + // Schedules page + 'schedules.duplicate': 'Duplicar agendamento', + 'schedules.view_script': 'Ver Script', + 'schedules.view_flow': 'Ver Flow', + + // Runs page + 'runs.cancel_jobs': 'Cancelar jobs', + 'runs.rerun_jobs': 'Reexecutar jobs', + 'runs.cancel_all': 'Cancelar todos os jobs com filtros', + 'runs.rerun_all': 'Reexecutar todos os jobs com filtros', + 'runs.force_cancel': 'Forçar cancelamento', + + // Editor - common + 'editor.save': 'Salvar', + 'editor.deploy': 'Implantar', + 'editor.draft': 'Draft', + 'editor.test': 'Testar', + 'editor.test_and_record': 'Testar e gravar', + 'editor.history': 'Histórico', + 'editor.versions_history': 'Histórico de versões', + 'editor.deployment_history': 'Histórico de implantação', + 'editor.edit_in_yaml': 'Editar em YAML', + 'editor.flow_settings': 'Configurações do flow', + 'editor.export': 'Exportar', + 'editor.diff': 'Diff', + 'editor.editor': 'Editor', + 'editor.preview': 'Pré-visualizar', + 'editor.main': 'Principal', + 'editor.preprocessor': 'Pré-processador', + 'editor.diagram': 'Diagrama', + 'editor.save_to_workspace': 'Salvar no workspace', + 'editor.exit_see_details': 'Sair e ver detalhes', + 'editor.edit_in_fork': 'Editar no fork', + 'editor.save_anyway': 'Salvar mesmo assim', + 'editor.invite_others': 'Convidar outros', + + // Flow editor + 'flow.test_flow': 'Testar flow', + 'flow.test_flow_record': 'Testar flow e gravar', + 'flow.build_a_flow': 'Criar um flow', + 'flow.fix_broken_flow': 'Corrigir um flow com erro', + 'flow.reset_tutorials': 'Reiniciar tutoriais', + 'flow.skip_tutorials': 'Pular tutoriais', + 'flow.create_group': 'Criar grupo', + 'flow.test_iteration': 'Testar uma iteração', + 'flow.skip_failures': 'Ignorar falhas', + 'flow.run_parallel': 'Executar em paralelo', + + // App editor + 'app.public_url': 'URL pública', + 'app.app_inputs': 'Entradas do app', + 'app.schedule_reports': 'Agendar relatórios', + 'app.troubleshoot': 'Painel de diagnóstico', + 'app.lazy_mode': 'Modo lazy', + 'app.hub_export': 'Exportar para Hub', + + // Status labels + 'status.default': 'Padrão', + 'status.primary': 'Primário', + 'status.modified': 'Modificado', + 'status.draft': 'Draft', + + // Tabs - common + 'tab.workspace': 'Workspace', + 'tab.contextual': 'Contextual', + 'tab.hub': 'Hub', + 'tab.scripts': 'Scripts', + 'tab.flows': 'Flows', + 'tab.apps': 'Apps', + + // Row actions (scripts/flows/apps) + 'row.view_json': 'Ver JSON/YAML', + 'row.move_rename': 'Mover/Renomear', + 'row.duplicate_fork': 'Duplicar/Fork', + 'row.go_to_public_page': 'Ir para página pública', + 'row.deployments': 'Implantações', + + // Confirmation dialogs + 'confirm.delete_forever': 'Excluir permanentemente', + 'confirm.empty_trashbin': 'Esvaziar lixeira', + 'confirm.discard_changes': 'Descartar alterações', + 'confirm.override': 'Sobrescrever', + + // Groups/Folders + 'groups.manage_group': 'Gerenciar grupo', + 'groups.new_group': 'Novo grupo', + 'folders.manage_folder': 'Gerenciar pasta', + 'folders.new_folder': 'Nova pasta', + + // Triggers + 'triggers.suspend_job': 'Suspender execução do job', + 'triggers.more_triggers': 'Mais gatilhos', + 'triggers.scheduled_poll': 'Polling agendado', + + // Misc + 'misc.all_workspaces': 'Todos os workspaces', + 'misc.instance_settings': 'Configurações da instância', + 'misc.search': 'Buscar', + 'misc.filter': 'Filtrar', + 'misc.tree_view': 'Visualização em árvore', + 'misc.loading': 'Carregando...' } diff --git a/frontend/src/lib/i18n/messages/zh.ts b/frontend/src/lib/i18n/messages/zh.ts index c87b25f6fb..8c815298f9 100644 --- a/frontend/src/lib/i18n/messages/zh.ts +++ b/frontend/src/lib/i18n/messages/zh.ts @@ -78,6 +78,33 @@ export const zh: Record = { 'action.close': '关闭', 'action.confirm': '确认', 'action.refresh': '刷新', + 'action.duplicate': '复制', + 'action.fork': 'Fork', + 'action.rename': '重命名', + 'action.move': '移动', + 'action.copy_path': '复制路径', + 'action.export': '导出', + 'action.undo': '撤销', + 'action.redo': '重做', + 'action.test': '测试', + 'action.view': '查看', + 'action.next': '下一步', + 'action.previous': '上一步', + 'action.remove': '移除', + 'action.enable': '启用', + 'action.disable': '禁用', + 'action.see_permissions': '查看权限', + 'action.deploy_to_prod': '部署到生产/预发布', + 'action.refresh_token': '刷新令牌', + 'action.view_runs': '查看运行', + 'action.view_code': '查看代码', + 'action.audit_logs': '审计日志', + 'action.schedule': '定时', + 'action.versions': '版本', + 'action.delete_draft': '删除Draft', + 'action.publish_to_hub': '发布到Hub', + 'action.run_now': '立即运行', + 'action.manage': '管理', // Page headers 'page.home': '首页', @@ -86,5 +113,134 @@ export const zh: Record = { 'page.schedules': '定时任务', 'page.workers': 'Workers', 'page.folders': '文件夹', - 'page.groups': '分组' + 'page.groups': '分组', + 'page.runs': '运行', + + // Home page + 'home.create_a': '创建', + 'home.workspace': '工作区', + 'home.hub': 'Hub', + 'home.scripts': '脚本', + 'home.flows': '流程', + 'home.apps': '应用', + 'home.hub_flow': 'Hub流程', + 'home.hub_app': 'Hub应用', + 'home.view_on_hub': '在Hub上查看', + 'home.content': '内容', + + // Variables page + 'variables.new_variable': '新建变量', + 'variables.new_contextual': '新建上下文变量', + 'variables.contextual': '上下文', + 'variables.custom_contextual': '自定义上下文变量', + 'variables.contextual_vars': '上下文变量', + 'variables.no_variables': '未找到变量', + 'variables.path': '路径', + 'variables.value': '值', + 'variables.description': '描述', + + // Resources page + 'resources.new_resource': '新建资源', + + // Schedules page + 'schedules.duplicate': '复制定时任务', + 'schedules.view_script': '查看脚本', + 'schedules.view_flow': '查看流程', + + // Runs page + 'runs.cancel_jobs': '取消任务', + 'runs.rerun_jobs': '重新运行任务', + 'runs.cancel_all': '取消所有符合筛选条件的任务', + 'runs.rerun_all': '重新运行所有符合筛选条件的任务', + 'runs.force_cancel': '强制取消', + + // Editor - common + 'editor.save': '保存', + 'editor.deploy': '部署', + 'editor.draft': 'Draft', + 'editor.test': '测试', + 'editor.test_and_record': '测试并记录', + 'editor.history': '历史', + 'editor.versions_history': '版本历史', + 'editor.deployment_history': '部署历史', + 'editor.edit_in_yaml': '以YAML编辑', + 'editor.flow_settings': '流程设置', + 'editor.export': '导出', + 'editor.diff': '差异对比', + 'editor.editor': '编辑器', + 'editor.preview': '预览', + 'editor.main': '主程序', + 'editor.preprocessor': '预处理器', + 'editor.diagram': '流程图', + 'editor.save_to_workspace': '保存到工作区', + 'editor.exit_see_details': '退出并查看详情', + 'editor.edit_in_fork': '在分支中编辑', + 'editor.save_anyway': '仍然保存', + 'editor.invite_others': '邀请其他人', + + // Flow editor + 'flow.test_flow': '测试流程', + 'flow.test_flow_record': '测试流程并记录', + 'flow.build_a_flow': '创建流程', + 'flow.fix_broken_flow': '修复异常流程', + 'flow.reset_tutorials': '重置教程', + 'flow.skip_tutorials': '跳过教程', + 'flow.create_group': '创建分组', + 'flow.test_iteration': '测试迭代', + 'flow.skip_failures': '跳过失败', + 'flow.run_parallel': '并行运行', + + // App editor + 'app.public_url': '公开URL', + 'app.app_inputs': '应用输入', + 'app.schedule_reports': '定时报告', + 'app.troubleshoot': '排障面板', + 'app.lazy_mode': '懒加载模式', + 'app.hub_export': 'Hub导出', + + // Status labels + 'status.default': '默认', + 'status.primary': '主要', + 'status.modified': '已修改', + 'status.draft': 'Draft', + + // Tabs - common + 'tab.workspace': '工作区', + 'tab.contextual': '上下文', + 'tab.hub': 'Hub', + 'tab.scripts': '脚本', + 'tab.flows': '流程', + 'tab.apps': '应用', + + // Row actions (scripts/flows/apps) + 'row.view_json': '查看JSON/YAML', + 'row.move_rename': '移动/重命名', + 'row.duplicate_fork': '复制/Fork', + 'row.go_to_public_page': '前往公开页面', + 'row.deployments': '部署记录', + + // Confirmation dialogs + 'confirm.delete_forever': '永久删除', + 'confirm.empty_trashbin': '清空回收站', + 'confirm.discard_changes': '放弃更改', + 'confirm.override': '覆盖', + + // Groups/Folders + 'groups.manage_group': '管理分组', + 'groups.new_group': '新建分组', + 'folders.manage_folder': '管理文件夹', + 'folders.new_folder': '新建文件夹', + + // Triggers + 'triggers.suspend_job': '暂停任务执行', + 'triggers.more_triggers': '更多触发器', + 'triggers.scheduled_poll': '定时轮询', + + // Misc + 'misc.all_workspaces': '所有工作区', + 'misc.instance_settings': '实例设置', + 'misc.search': '搜索', + 'misc.filter': '筛选', + 'misc.tree_view': '树形视图', + 'misc.loading': '加载中...' } diff --git a/frontend/src/lib/i18n/t.svelte.ts b/frontend/src/lib/i18n/t.svelte.ts index c498d0586c..5785646c77 100644 --- a/frontend/src/lib/i18n/t.svelte.ts +++ b/frontend/src/lib/i18n/t.svelte.ts @@ -1,42 +1,55 @@ -import { getLocalSetting, storeLocalSetting } from '$lib/utils' import { type Locale, SUPPORTED_LOCALES, detectLocale } from './index' import { en, type MessageKey } from './messages/en' import { messages } from './messages/index' -export type LocaleChoice = Locale | 'auto' +/** + * Persist locale in localStorage directly (not via getLocalSetting) + * to survive as long as possible — localStorage has no expiry. + */ +const STORAGE_KEY = 'wm_locale' -function getInitialChoice(): LocaleChoice { - const stored = getLocalSetting('locale') - if (stored && SUPPORTED_LOCALES.includes(stored as Locale)) { - return stored as Locale - } - return 'auto' +function readStored(): Locale | undefined { + try { + const v = localStorage.getItem(STORAGE_KEY) + if (v && SUPPORTED_LOCALES.includes(v as Locale)) return v as Locale + } catch {} + return undefined } -let choice = $state(getInitialChoice()) +function writeStored(l: Locale) { + try { + localStorage.setItem(STORAGE_KEY, l) + } catch {} +} + +/** Default is English. User can switch to any supported locale. */ +let locale = $state(readStored() ?? 'en') -/** The resolved locale actually used for translations */ export function getLocale(): Locale { - return choice === 'auto' ? detectLocale() : choice + return locale } -/** The raw user choice ('auto' or a specific locale) */ -export function getLocaleChoice(): LocaleChoice { - return choice +/** Whether the user's browser language differs from the active locale */ +export function detectedDiffers(): boolean { + return detectLocale() !== locale } -export function setLocale(l: LocaleChoice) { - choice = l - storeLocalSetting('locale', l === 'auto' ? undefined : l) +/** The browser-detected locale (for the alert banner) */ +export function getDetectedLocale(): Locale { + return detectLocale() +} + +export function setLocale(l: Locale) { + locale = l + writeStored(l) if (typeof document !== 'undefined') { - document.documentElement.lang = getLocale() + document.documentElement.lang = l } } export function t(key: MessageKey): string { - const loc = getLocale() - if (loc === 'en') { + if (locale === 'en') { return en[key] } - return messages[loc]?.[key] ?? en[key] + return messages[locale]?.[key] ?? en[key] } diff --git a/frontend/src/routes/(root)/(logged)/+page.svelte b/frontend/src/routes/(root)/(logged)/+page.svelte index 413a537787..2122a14289 100644 --- a/frontend/src/routes/(root)/(logged)/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/+page.svelte @@ -41,7 +41,7 @@ import { ignoredTutorials } from '$lib/components/tutorials/ignoredTutorials' import TutorialBanner from '$lib/components/home/TutorialBanner.svelte' import NoDirectDeployAlert from '$lib/components/NoDirectDeployAlert.svelte' - import { getLocale, getLocaleChoice, setLocale } from '$lib/i18n/t.svelte' + import { detectedDiffers, getDetectedLocale, setLocale } from '$lib/i18n/t.svelte' import { LOCALE_NAMES } from '$lib/i18n/index' import { getLocalSetting, storeLocalSetting } from '$lib/utils' import { X, Languages } from 'lucide-svelte' @@ -286,18 +286,18 @@ Windmill instance, such as keeping resource types up to date. {/if} - {#if !i18nBannerDismissed && getLocaleChoice() === 'auto' && getLocale() !== 'en'} + {#if !i18nBannerDismissed && detectedDiffers()}
- Windmill is displayed in {LOCALE_NAMES[getLocale()]} based on your browser settings. You can + Windmill is available in {LOCALE_NAMES[getDetectedLocale()]}. or change the language anytime from the user menu.