diff --git a/locales/en.json b/locales/en.json new file mode 100644 index 00000000..eacd6fd6 --- /dev/null +++ b/locales/en.json @@ -0,0 +1,312 @@ +{ + "pageTitle": "VDO.Ninja OBS Control Dock", + "mainHeading": "VDO.Ninja OBS Control", + "languageSwitcher": { + "label": "Language:" + }, + "collapsible": { + "clickToExpand": "Click to expand", + "clickToCollapse": "Click to collapse" + }, + "customCss": { + "title": "Custom CSS", + "label": "Enter your custom CSS here:", + "description": "This CSS will be applied to the sources." + }, + "obsConnection": { + "title": "OBS WebSocket Connection", + "websocketUrlLabel": "WebSocket URL:", + "passwordLabel": "Password:", + "cameraPrefixLabel": "General Camera prefix:", + "reactionPrefixLabel": "Reaction prefix: VDO.", + "highlightPrefixLabel": "Highlight prefix: VDO.", + "reactionPrefixDynamicLabel": "Reaction prefix: {{prefix}}{{separator}}{{subPrefix}}", + "highlightPrefixDynamicLabel": "Highlight prefix: {{prefix}}{{separator}}{{subPrefix}}", + "connectButton": "Connect", + "disconnectButton": "Disconnect", + "statusDisconnected": "Status: Disconnected", + "statusConnected": "Status: Connected", + "statusConnecting": "Status: Connecting...", + "statusError": "Status: Error", + "statusErrorUrlMissing": "Status: Error - URL missing", + "statusErrorTimeout": "Status: Error - Connection timed out", + "statusErrorCameraPrefixMissing": "Status: Error - Camera Prefix Missing" + }, + "vdoNinjaSettings": { + "title": "VDO.Ninja Settings", + "baseUrlLabel": "VDO.Ninja Base URL:", + "baseUrlPlaceholder": "https://vdo.ninja", + "roomNameLabel": "Room Name:", + "roomNamePlaceholder": "e.g., MyNinjaRoom", + "passwordLabel": "Password:", + "passwordPlaceholder": "Room or &password", + "streamIdsLabel": "Stream IDs:", + "streamIdsPlaceholder": "streamId1,streamId2", + "roomOrStreamIdsNeeded": "Room Name or Stream ID(s) needed", + "connectButton": "Connect", + "disconnectButton": "Disconnect", + "cancelButton": "Cancel", + "statusDisconnected": "Status: Disconnected", + "statusConnected": "Status: Connected", + "statusConnecting": "Status: Connecting...", + "statusConnectionFailed": "Status: Connection Failed", + "statusConnectionLost": "Status: Connection Lost" + }, + "streamIdMappings": { + "title": "Stream ID Mappings", + "addNewMappingButton": "Add New Mapping", + "ruleTitle": "Stream Mapping Rule", + "streamIdPlaceholder": "Stream ID", + "streamIdTooltip": "VDO.Ninja Stream ID", + "labelPlaceholder": "Label (optional)", + "labelTooltip": "VDO.Ninja Stream Label", + "matchTypeTooltip": "How to match stream", + "matchType": { + "idOnly": "ID Only", + "labelOnly": "Label Only", + "bothRequired": "Both Required", + "eitherMatch": "Either Match" + }, + "targetSceneTooltip": "Target OBS Scene", + "selectSceneOption": "Select a scene...", + "removeRuleTooltip": "Remove this mapping rule", + "cloneToMainSceneLabel": "Clone to main scene", + "switchToSceneOnAddLabel": "Switch to scene on add", + "ruleDescription": "Define how incoming streams are routed to OBS scenes." + }, + "obsTargetSettings": { + "title": "OBS Target Settings", + "sourceCreationScenesLabel": "Scenes for Source Creation:", + "sourceCreationScenesDesc": "Select one or more scenes. The first will be the primary, others for copying.", + "loadingScenes": "Loading scenes...", + "noScenesFound": "No scenes found", + "refetchScenesButton": "Re-Fetch Scenes", + "screenShareSettings": { + "title": "Screen Sharing Settings:", + "widthLabel": "Width:", + "heightLabel": "Height:", + "resolutionNote": "This resolution will be used for screen sharing sources in scenes with a 'Reaction' layout." + }, + "autoAddSourcesLabel": "Auto-add new streams as sources", + "autoRemoveSourcesLabel": "Auto-remove sources on disconnect", + "newSourceSizing": { + "label": "Default Source Sizing:", + "defaultSizeOption": "Default (1920x1080 at 0,0)", + "bestFitOption": "Best Fit (Preserve Aspect)", + "stretchToFillOption": "Stretch to Fill Screen", + "overrideNote": "Specific layouts defined in the \"Layouts\" section will override these for those scenes." + }, + "codec": { + "label": "Codec:", + "noneOption": "none", + "learnMoreTitle": "Learn more about codec options" + } + }, + "sceneLayouts": { + "title": "Scene Layouts", + "addNewLayoutButton": "Add New Layout", + "description": "Define automatic layouts for specific OBS scenes. These will override the default source sizing for the configured scenes.", + "sceneLabel": "Scene:", + "selectSceneOption": "Select Scene...", + "layoutLabel": "Layout:", + "selectLayoutOption": "Select Layout...", + "layoutTypes": { + "grid": "Grid", + "reaction": "Reaction", + "highlight": "Highlight" + }, + "noActiveLayouts": "No active layouts", + "removeLayoutTooltip": "Remove this layout configuration", + "sceneAlreadyConfiguredTooltip": "(Already in use)", + "sceneAlreadyConfiguredAlert": "Scene '{{sceneName}}' is already in use by another layout configuration.", + "controls": { + "margin": "Margin", + "spacing": "Spacing", + "offsetX": "X Offset", + "offsetY": "Y Offset", + "gridSplitScreenTwoCameras": "Split screen for 2 cameras (Grid)", + "distributeCameras": "Distribute cameras (Reaction/Highlight)" + } + }, + "activeStreams": { + "title": "Active Streams", + "noActiveStreams": "No active streams", + "streamIdLabel": "ID: {{id}}", + "labelLabel": "Label: {{label}}", + "targetSceneLabelText": "Target Scene: {{sceneName}}", + "notSet": "Not Set", + "defaultSceneTag": "default", + "mappedSceneTag": "mapped", + "addedToObs": "✓ Added to OBS", + "notInObs": "✗ Not in OBS", + "buttons": { + "addToObs": "Add to OBS", + "removeFromObs": "Remove from OBS", + "highlight": "Highlight", + "unhighlight": "Unhighlight", + "screenShare": "Screen Share", + "stopScreenShare": "Stop Screen Share" + } + }, + "log": { + "title": "Log" + }, + "vdoNinja": { + "defaultStreamLabel": "Stream {{id}}" + }, + "logMessages": { + "settingsSaved": "Settings saved.", + "settingsLoaded": "Settings loaded from localStorage.", + "customCssChangedWillApplyToSource": "Custom CSS input changed. It will be applied directly to OBS source settings on next creation/update.", + "errorLoadingSettings": "Error loading settings from localStorage: {{message}}. Using defaults.", + "noSavedSettings": "No saved settings found. Using default values.", + "appInitialized": "VDO.Ninja OBS Control Dock Initialized. Welcome!", + "jsShaLoaded": "jsSHA library loaded successfully (fallback for Web Crypto).", + "errorLoadingJsSha": "Error: Failed to load jsSHA library. OBS authentication might fail if Web Crypto is also unavailable.", + "loadedStreamMappings": "Loaded {{count}} stream mappings.", + "errorLoadingStreamMappings": "Error loading stream mappings from localStorage: {{message}}", + "warningStreamMappingElementsNotFound": "Warning: Could not find all expected elements in a stream mapping UI div.", + "loadedLayoutConfigs": "Loaded {{count}} scene layout configurations.", + "errorLoadingLayoutConfigs": "Error loading scene layout configurations: {{message}}", + "savedLayoutConfigs": "Saved {{count}} scene layout configurations.", + "errorSavingLayoutsDuplicateScene": "Error saving layouts: Scene '{{sceneName}}' is configured multiple times. Please ensure each scene has only one layout.", + "layoutSceneNotFound": "Saved scene '{{sceneName}}' for layout not found in current OBS scenes.", + "errorHidingSource": "Error hiding source item {{sourceName}} in {{sceneName}}: {{message}}", + "sceneAlreadyConfiguredError": "Scene '{{sceneName}}' is already configured for another layout. Reverting selection.", + "vdoNinja": { + "disconnected": "Disconnected from VDO.Ninja.", + "alreadyConnected": "Already connected to VDO.Ninja.", + "errorRoomOrStreamIdNeeded": "VDO.Ninja Error: Room Name or Stream ID(s) must be provided.", + "connectionTimeout": "VDO.Ninja connection timed out. No activity received from iframe.", + "roomOrStreamIdNeededForConnect": "VDO.Ninja: Room Name or specific Stream ID(s) must be provided to connect.", + "streamIdsEmptyAfterTrim": "VDO.Ninja: Stream IDs provided but were empty after trimming.", + "initializingIframe": "Initializing VDO.Ninja iframe with URL: {{url}}", + "invalidBaseUrl": "Invalid VDO.Ninja base URL in settings: {{url}}", + "iframeConnectedActive": "VDO.Ninja iframe connection established and active.", + "streamConnectedActive": "VDO.Ninja stream connected/active: \"{{label}}\" (ID: {{id}})", + "autoAddingStream": "Auto-adding stream {{id}} to OBS.", + "streamDisconnectedInactive": "VDO.Ninja stream disconnected/inactive: \"{{label}}\" (ID: {{id}})", + "autoRemovingStream": "Auto-removing stream {{id}} from OBS.", + "streamLabelUpdated": "VDO.Ninja stream label updated for ID {{id}}: \"{{newLabel}}\" (was \"{{oldLabel}}\")", + "connectionLostResetting": "VDO.Ninja connection lost (no activity from iframe). Attempting to reset." + }, + "obs": { + "disconnecting": "Disconnecting from OBS WebSocket...", + "errorCameraPrefixRequired": "Error: General Camera prefix is required for OBS connection.", + "errorUrlRequired": "Error: OBS WebSocket URL is required.", + "attemptingConnection": "Attempting to connect to OBS WebSocket at {{url}}...", + "connectionTimeout": "OBS WebSocket connection attempt timed out.", + "connectionOpenedWaitingHello": "OBS WebSocket connection opened. Waiting for Server Hello...", + "receivedHelloSendingIdentify": "Received Hello from OBS. Sending Identify...", + "authDataPrepared": "Authentication data prepared for Identify message.", + "warningAuthRequiredNoPassword": "Warning: OBS server requires authentication, but no password provided.", + "authSuccessConnected": "OBS WebSocket Authentication successful! Connection established.", + "requestError": "OBS Request Error (Type: {{type}}, ID: {{id}}): {{error}} (Code: {{code}})", + "eventSceneListChanged": "OBS Event: Scene list changed. Re-fetching scenes.", + "errorProcessingMessage": "Error processing OBS WebSocket message: {{message}}. Data: {{data}}", + "webSocketError": "OBS WebSocket Error: {{error}}", + "authFailedReason": "Authentication Failed - incorrect password or auth required and not provided.", + "connectionClosedReasonCode": "Code: {{code}}{{wasClean}}", + "uncleanDisconnection": " (Unclean disconnection)", + "connectionClosed": "OBS WebSocket Connection Closed. Reason: {{reason}}", + "errorCreatingConnection": "Error creating OBS WebSocket connection: {{message}}", + "authGenerationError": "OBS Authentication generation error: {{message}}", + "cannotSendRequestNotConnected": "Cannot send request '{{requestType}}': Not connected to OBS.", + "errorSendingRequest": "Error sending OBS request '{{requestType}}': {{message}}", + "requestTimeout": "OBS Request '{{requestType}}' (ID: {{id}}) timed out.", + "connectionEstablishedFetchingData": "OBS Connection fully established. Fetching initial data...", + "errorPostConnectionSetup": "Error during post-OBS connection setup (fetching scenes): {{message}}", + "connectionClosedOrLost": "OBS Connection has been closed or lost.", + "cannotFetchScenesNotConnected": "Cannot fetch OBS scenes: Not connected to OBS.", + "fetchingScenes": "Fetching OBS scenes...", + "fetchedScenesCount": "Fetched {{count}} scenes from OBS.", + "failedToFetchScenes": "Failed to fetch OBS scenes or no scenes returned.", + "errorFetchingScenes": "Error fetching OBS scenes: {{message}}", + "cannotHighlightNotConnected": "Cannot highlight: Not connected to OBS.", + "highlightLayoutActiveManualLegacy": "Scene '{{sceneName}}' uses the new Highlight Layout. Manual highlight button may have limited effect or is superseded.", + "stoppingScreenShareForHighlight": "A screen share is active ({{id}}). Stopping it before highlighting.", + "cannotScreenShareNotConnected": "Cannot start screen share: Not connected to OBS.", + "unhighlightingForScreenShare": "A camera is highlighted ({{id}}). Unhighlighting it before starting screen share.", + "cannotAddScreenShareNotConnected": "Cannot add screen share: Not connected to OBS.", + "cannotAddScreenShareNoRoom": "Cannot add screen share: VDO.Ninja Room name is required for screen sharing URLs.", + "cannotAddScreenShareNoReactionLayoutScene": "Cannot add screen share: No scenes are configured with a 'Reaction' layout.", + "addingUpdatingScreenShareToReactionScenes": "Adding/Updating screen share source '{{sourceName}}' (URL: {{url}}) to Reaction scenes. Primary creation in '{{primaryScene}}'. ({{count}} scenes total)", + "reconfiguringExistingScreenShare": "Reconfiguring existing screen share source '{{oldName}}' to be '{{newName}}'.", + "reconfiguredRenamedScreenShare": "Reconfigured and renamed existing screen share source to '{{sourceName}}'.", + "screenShareExistsUpdating": "Screen share source '{{sourceName}}' already exists. Updating its settings.", + "creatingNewScreenShareInScene": "Creating new screen share source '{{sourceName}}' in scene '{{sceneName}}'.", + "ensuredTransformedScreenShareReaction": "Ensured and transformed screen share source '{{sourceName}}' in Reaction scene '{{sceneName}}'.", + "sourceFoundInSceneEnabled": "Source '{{sourceName}}' found in scene '{{sceneName}}', item ID: {{itemId}}. Ensuring it's enabled.", + "sourceAddedToScene": "Source '{{sourceName}}' added to scene '{{sceneName}}', item ID: {{itemId}}.", + "errorCreatingSceneItem": "Error creating scene item for '{{sourceName}}' in '{{sceneName}}': {{message}}", + "errorCheckingSceneForItem": "Error checking for '{{sourceName}}' in scene '{{sceneName}}': {{message}}", + "errorApplyingInitialTransform": "Error applying initial default transform to '{{sourceName}}' in '{{sceneName}}': {{message}}", + "successConfigScreenShare": "Successfully configured screen share for stream {{streamId}} ({{label}}).", + "errorAddingUpdatingScreenShare": "Error adding/updating screen share source '{{sourceName}}': {{message}}.", + "cannotToggleHighlightNotConnected": "Cannot toggle highlight: Not connected to OBS.", + "streamUnhighlighted": "Stream {{id}} unhighlighted (renamed from {{oldName}} to {{newName}}).", + "streamSuccessfullyUnhighlighted": "Stream {{id}} successfully unhighlighted (renamed to {{newName}}).", + "streamSuccessfullyHighlighted": "Stream {{id}} successfully highlighted (renamed to {{newName}}).", + "unhighlightError": "Could not unhighlight (rename) {{sourceName}}, it might not exist or another error: {{message}}", + "highlightError": "Could not highlight (rename) {{sourceName}}, it might not exist or another error: {{message}}", + "legacyHighlightUnhighlightOnRemove": "Stream {{id}} was legacy highlighted. Unhighlighting.", + "cannotAddStreamNotConnected": "Cannot add stream \"{{label}}\" ({{id}}) to OBS: Not connected to OBS.", + "cannotAddStreamNoTargetSceneName": "Cannot add stream \"{{label}}\" ({{id}}): Target OBS scene name is required but not set (no default and no mapping).", + "foundExistingStandardSource": "Found existing standard source '{{sourceName}}' for stream {{streamId}}.", + "foundExistingHighlightForConnectingStream": "Found existing OBS source '{{sourceName}}' which matches highlight naming for connecting stream {{streamId}}. Updating internal highlight state.", + "foundExistingHighlightedSource": "Found existing highlighted source '{{sourceName}}' for stream {{streamId}}.", + "noExistingSourceFoundWillCreate": "Neither standard ('{{baseSourceName}}') nor highlighted ('{{highlightedSourceName}}') source found for stream {{streamId}}. Will create new.", + "noExistingStandardSourceSamePrefix": "Standard source '{{sourceName}}' not found for stream {{streamId}} (highlight prefix is same). Will create new.", + "errorGettingCanvasSize": "Error getting OBS canvas size: {{message}}. Using default {{width}}x{{height}}.", + "sourceNotGlobalCreating": "Source '{{sourceName}}' does not exist globally. Creating it in scene '{{sceneName}}'.", + "sourceCreatedAddedToScene": "Source '{{sourceName}}' created and added to scene '{{sceneName}}'.", + "sourceGlobalUpdatingWithUrl": "Source '{{sourceName}}' already exists globally. Updating its settings. URL: {{url}}", + "sourceFoundAsItemInScene": "Source '{{sourceName}}' found as item in scene '{{sceneName}}'.", + "sourceNotInSceneAdding": "Source '{{sourceName}}' not in scene '{{sceneName}}'. Adding it.", + "cloningToMainScene": "Cloning source '{{sourceName}}' to main scene (from checkboxes) '{{sceneName}}' due to mapping rule.", + "addingSourceToOtherScene": "Adding source '{{sourceName}}' as item to other selected scene '{{sceneName}}'.", + "switchingProgramScene": "Switching OBS current program scene to '{{sceneName}}'.", + "successfullyProcessedStream": "Successfully processed stream \"{{label}}\" ({{id}}), effective OBS source: '{{sourceName}}'.", + "errorManagingStream": "Error managing stream '{{sourceName}}' (\"{{label}}\") in OBS: {{message}}", + "applyTransformAndGridCalled": "applyTransformAndGrid called for {{sourceName}} in {{sceneName}}. Triggering full layout update for scene.", + "triggeringLayoutUpdate": "Triggering layout update for scene '{{sceneName}}'...", + "gridFallbackSourceChanged": "Grid settings for '{{sourceGridScene}}' (primary fallback candidate) changed. Triggering update for Reaction/Highlight scene '{{dependentScene}}'.", + "noSceneItemsForLayout": "No scene items found in scene '{{sceneName}}' for layout update.", + "applyingConfiguredLayout": "Applying '{{layoutType}}' layout to scene '{{sceneName}}'. ({{count}} items)", + "unknownLayoutType": "Unknown layout type '{{layoutType}}' for scene '{{sceneName}}'. Applying default sizing.", + "noSpecificLayoutApplyingDefault": "No specific layout for scene '{{sceneName}}'. Applying default source sizing ('{{sizing}}').", + "errorTriggeringLayoutUpdate": "Error during layout update for scene '{{sceneName}}': {{message}}", + "applyingDefaultSizing": "Applying default source sizing ('{{sizing}}') to {{count}} items in scene '{{sceneName}}'.", + "errorApplyingDefaultTransformItem": "Error applying default transform to {{sourceName}} in {{sceneName}}: {{message}}", + "noSourcesForGridLayout": "No VDO.Ninja camera sources to apply Grid layout in scene '{{sceneName}}'.", + "applyingGridLayoutScene": "Applying Grid Layout to {{count}} VDO.Ninja camera sources in scene '{{sceneName}}'.", + "applyingGridSplitScreen": "Applying 2-camera split screen grid layout to scene '{{sceneName}}'.", + "reactionMainNotFoundFallbackGrid": "Main content for Reaction layout in scene '{{sceneName}}' not found/visible. Applying fallback grid of cameras.", + "highlightMainNotFoundFallbackGrid": "Main content for Highlight layout in scene '{{sceneName}}' not found/visible. Applying fallback grid of cameras.", + "usingGridSceneFallbackSettings": "Using grid settings from the first configured 'Grid' layout scene ('{{sceneName}}') as fallback for '{{targetScene}}'.", + "usingDefaultGridFallbackSettings": "No 'Grid' layout scene found. Using default grid settings as fallback for '{{targetScene}}'.", + "applyingFallbackGridToCameras": "Applying fallback Grid layout to {{count}} camera sources in scene '{{sceneName}}'.", + "noCamerasForFallbackGridHidingAll": "No camera items to display in fallback grid for scene '{{sceneName}}'. All VDO sources in this scene will be hidden.", + "cannotRemoveStreamNotConnected": "Cannot remove stream {{id}} from OBS: Not connected to OBS.", + "triggeredRemoval": "User or auto-triggered removal of stream '{{id}}' from OBS. Base source: '{{baseName}}'.", + "streamScreenSharingRemoving": "Stream {{id}} was actively screen sharing. Initiating screen share removal.", + "finishedRemovingSourceItems": "Finished removing source items for stream {{id}} from specified OBS scenes.", + "cannotRemoveScreenShareNotConnected": "Cannot remove screen share: Not connected to OBS.", + "attemptingRemoveScreenShareSource": "Attempting to fully remove screen share source '{{sourceName}}' from OBS (all scenes and input).", + "removingGlobalInput": "Removing global input '{{sourceName}}' from OBS.", + "successfullyRemovedInput": "Successfully removed input '{{sourceName}}'.", + "errorScreenShareRemovalProcess": "Error during screen share removal process for '{{sourceName}}': {{message}}", + "removingSourceItemFromScene": "Removing source item '{{sourceName}}' (ID: {{itemId}}) from scene '{{sceneName}}'.", + "errorTryingRemoveSourceItem": "Error trying to remove source item '{{sourceName}}' from scene '{{sceneName}}': {{message}}", + "codecChangedUpdatingSources": "Codec changed to: {{codec}}. Updating OBS sources...", + "codecChangedNotConnected": "OBS is not connected. Sources will not be updated with the new codec until reconnection and a new action.", + "sourceUpdatedWithUrlAndCss": "Source '{{sourceName}}' updated with URL: {{url}} and custom CSS.", + "screenShareSourceUpdatedWithUrlAndCss": "Screen share source '{{sourceName}}' updated with URL: {{url}} and custom CSS.", + "codecUpdateComplete": "Codec update for OBS sources complete.", + "codecCssUpdateComplete": "Codec/CSS update for OBS sources complete.", + "inputNameChanged": "OBS Event: Input name changed from '{{oldName}}' to '{{newName}}'. Checking relevant scenes for layout updates.", + "foundPreExistingHighlight": "Found pre-existing highlighted source in OBS: '{{sourceName}}'. Setting active highlight to stream ID: {{streamId}}.", + "errorCheckingMainContentEnabled": "Error checking if main content {{sourceName}} is enabled: {{message}}" + } + } +} diff --git a/locales/pt.json b/locales/pt.json new file mode 100644 index 00000000..c5533ae8 --- /dev/null +++ b/locales/pt.json @@ -0,0 +1,312 @@ +{ + "pageTitle": "Painel de Controle do OBS - VDO.Ninja", + "mainHeading": "VDO.Ninja - Controle do OBS", + "languageSwitcher": { + "label": "Idioma:" + }, + "collapsible": { + "clickToExpand": "Clique para expandir", + "clickToCollapse": "Clique para recolher" + }, + "customCss": { + "title": "CSS Personalizado", + "label": "Insira seu CSS personalizado aqui:", + "description": "Este CSS será aplicado às fontes." + }, + "obsConnection": { + "title": "Conexão com OBS WebSocket", + "websocketUrlLabel": "URL WebSocket:", + "passwordLabel": "Senha:", + "cameraPrefixLabel": "Prefixo Geral das Câmeras:", + "reactionPrefixLabel": "Prefixo de Reação: VDO.", + "highlightPrefixLabel": "Prefixo de Destaque: VDO.", + "reactionPrefixDynamicLabel": "Prefixo de Reação: {{prefix}}{{separator}}{{subPrefix}}", + "highlightPrefixDynamicLabel": "Prefixo de Destaque: {{prefix}}{{separator}}{{subPrefix}}", + "connectButton": "Conectar", + "disconnectButton": "Desconectar", + "statusDisconnected": "Status: Desconectado", + "statusConnected": "Status: Conectado", + "statusConnecting": "Status: Conectando...", + "statusError": "Status: Erro", + "statusErrorUrlMissing": "Status: Erro - URL faltando", + "statusErrorTimeout": "Status: Erro - Tempo de conexão esgotado", + "statusErrorCameraPrefixMissing": "Status: Erro - Prefixo da Câmera Faltando" + }, + "vdoNinjaSettings": { + "title": "Configurações do VDO.Ninja", + "baseUrlLabel": "URL Base do VDO.Ninja:", + "baseUrlPlaceholder": "https://vdo.ninja", + "roomNameLabel": "Nome da Sala:", + "roomNamePlaceholder": "ex: MinhaSalaNinja", + "passwordLabel": "Senha:", + "passwordPlaceholder": "Sala ou &password", + "streamIdsLabel": "IDs de Stream:", + "streamIdsPlaceholder": "streamId1,streamId2", + "roomOrStreamIdsNeeded": "Nome da Sala ou ID(s) de Stream são necessários", + "connectButton": "Conectar", + "disconnectButton": "Desconectar", + "cancelButton": "Cancelar", + "statusDisconnected": "Status: Desconectado", + "statusConnected": "Status: Conectado", + "statusConnecting": "Status: Conectando...", + "statusConnectionFailed": "Status: Falha na Conexão", + "statusConnectionLost": "Status: Conexão Perdida" + }, + "streamIdMappings": { + "title": "Mapeamentos de ID de Stream", + "addNewMappingButton": "Adicionar Novo Mapeamento", + "ruleTitle": "Regra de Mapeamento de Stream", + "streamIdPlaceholder": "ID do Stream", + "streamIdTooltip": "ID do Stream VDO.Ninja", + "labelPlaceholder": "Rótulo (opcional)", + "labelTooltip": "Rótulo do Stream VDO.Ninja", + "matchTypeTooltip": "Como reconhecer o stream", + "matchType": { + "idOnly": "Apenas ID", + "labelOnly": "Apenas Rótulo", + "bothRequired": "Ambos Necessários", + "eitherMatch": "Qualquer um Combina" + }, + "targetSceneTooltip": "Cena Alvo do OBS", + "selectSceneOption": "Selecione uma cena...", + "removeRuleTooltip": "Remover esta regra de mapeamento", + "cloneToMainSceneLabel": "Clonar para cena principal", + "switchToSceneOnAddLabel": "Mudar para cena ao adicionar", + "ruleDescription": "Defina como os streams de entrada são roteados para as cenas do OBS." + }, + "obsTargetSettings": { + "title": "Configurações de Alvo do OBS", + "sourceCreationScenesLabel": "Cenas para Criação de Fontes:", + "sourceCreationScenesDesc": "Selecione uma ou mais cenas. A primeira será a principal, as outras para cópia.", + "loadingScenes": "Carregando cenas...", + "noScenesFound": "Nenhuma cena encontrada", + "refetchScenesButton": "Buscar Cenas Novamente", + "screenShareSettings": { + "title": "Configurações de Compartilhamento de Tela:", + "widthLabel": "Largura:", + "heightLabel": "Altura:", + "resolutionNote": "Esta resolução será usada para as fontes de compartilhamento de tela em cenas com layout de 'Reação'." + }, + "autoAddSourcesLabel": "Adicionar automaticamente novos streams como fontes", + "autoRemoveSourcesLabel": "Remover automaticamente fontes ao desconectar", + "newSourceSizing": { + "label": "Dimensionamento Padrão de Fonte:", + "defaultSizeOption": "Padrão (1920x1080 em 0,0)", + "bestFitOption": "Melhor Ajuste (Preservar Proporção)", + "stretchToFillOption": "Esticar para Preencher Tela", + "overrideNote": "Layouts específicos definidos na seção \"Layouts\" irão sobrescrever estas configurações para aquelas cenas." + }, + "codec": { + "label": "Codec:", + "noneOption": "nenhum", + "learnMoreTitle": "Saiba mais sobre as opções de codec" + } + }, + "sceneLayouts": { + "title": "Layouts de Cena", + "addNewLayoutButton": "Adicionar Novo Layout", + "description": "Defina layouts automáticos para cenas específicas do OBS. Estes irão sobrescrever o dimensionamento padrão de fonte para as cenas configuradas.", + "sceneLabel": "Cena:", + "selectSceneOption": "Selecione a Cena...", + "layoutLabel": "Layout:", + "selectLayoutOption": "Selecione o Layout...", + "layoutTypes": { + "grid": "Grade", + "reaction": "Reação", + "highlight": "Destaque" + }, + "noActiveLayouts": "Nenhum layout ativo", + "removeLayoutTooltip": "Remover esta configuração de layout", + "sceneAlreadyConfiguredTooltip": "(Já em uso)", + "sceneAlreadyConfiguredAlert": "A cena '{{sceneName}}' já está em uso por outra configuração de layout.", + "controls": { + "margin": "Margem", + "spacing": "Espaçamento", + "offsetX": "Deslocamento X", + "offsetY": "Deslocamento Y", + "gridSplitScreenTwoCameras": "Tela dividida para 2 câmeras (Grade)", + "distributeCameras": "Distribuir câmeras (Reação/Destaque)" + } + }, + "activeStreams": { + "title": "Streams Ativos", + "noActiveStreams": "Nenhum stream ativo", + "streamIdLabel": "ID: {{id}}", + "labelLabel": "Rótulo: {{label}}", + "targetSceneLabelText": "Cena Alvo: {{sceneName}}", + "notSet": "Não Definido", + "defaultSceneTag": "padrão", + "mappedSceneTag": "mapeado", + "addedToObs": "✓ Adicionado ao OBS", + "notInObs": "✗ Não está no OBS", + "buttons": { + "addToObs": "Adicionar ao OBS", + "removeFromObs": "Remover do OBS", + "highlight": "Destacar", + "unhighlight": "Remover Destaque", + "screenShare": "Compart. Tela", + "stopScreenShare": "Parar Compart." + } + }, + "log": { + "title": "Registro" + }, + "vdoNinja": { + "defaultStreamLabel": "Stream {{id}}" + }, + "logMessages": { + "settingsSaved": "Configurações salvas.", + "settingsLoaded": "Configurações carregadas do localStorage.", + "customCssChangedWillApplyToSource": "Entrada de CSS personalizado mudada. Ela será aplicada diretamente à configuração de fontes do OBS na próxima criação/atualização.", + "errorLoadingSettings": "Erro ao carregar configurações do localStorage: {{message}}. Usando padrões.", + "noSavedSettings": "Nenhuma configuração salva encontrada. Usando valores padrão.", + "appInitialized": "Painel de Controle OBS VDO.Ninja Inicializado. Bem-vindo!", + "jsShaLoaded": "Biblioteca jsSHA carregada com sucesso (fallback para Web Crypto).", + "errorLoadingJsSha": "Erro: Falha ao carregar a biblioteca jsSHA. A autenticação OBS pode falhar se Web Crypto também não estiver disponível.", + "loadedStreamMappings": "{{count}} mapeamentos de stream carregados.", + "errorLoadingStreamMappings": "Erro ao carregar mapeamentos de stream do localStorage: {{message}}", + "warningStreamMappingElementsNotFound": "Aviso: Não foi possível encontrar todos os elementos esperados em uma div da UI de mapeamento de stream.", + "loadedLayoutConfigs": "{{count}} configurações de layout de cena carregadas.", + "errorLoadingLayoutConfigs": "Erro ao carregar configurações de layout de cena: {{message}}", + "savedLayoutConfigs": "{{count}} configurações de layout de cena salvas.", + "errorSavingLayoutsDuplicateScene": "Erro ao salvar layouts: A cena '{{sceneName}}' está configurada várias vezes. Por favor, garanta que cada cena tenha apenas um layout.", + "layoutSceneNotFound": "A cena '{{sceneName}}' salva para o layout não foi encontrada nas cenas atuais do OBS.", + "errorHidingSource": "Erro ao ocultar item de fonte {{sourceName}} em {{sceneName}}: {{message}}", + "sceneAlreadyConfiguredError": "A cena '{{sceneName}}' já está configurada para outro layout. Revertendo seleção.", + "vdoNinja": { + "disconnected": "Desconectado do VDO.Ninja.", + "alreadyConnected": "Já conectado ao VDO.Ninja.", + "errorRoomOrStreamIdNeeded": "Erro VDO.Ninja: Nome da Sala ou ID(s) de Stream devem ser fornecidos.", + "connectionTimeout": "Tempo de conexão com VDO.Ninja esgotado. Nenhuma atividade recebida do iframe.", + "roomOrStreamIdNeededForConnect": "VDO.Ninja: Nome da Sala ou ID(s) de Stream específicos devem ser fornecidos para conectar.", + "streamIdsEmptyAfterTrim": "VDO.Ninja: IDs de Stream fornecidos, mas estavam vazios após remover espaços.", + "initializingIframe": "Inicializando iframe VDO.Ninja com URL: {{url}}", + "invalidBaseUrl": "URL base VDO.Ninja inválida nas configurações: {{url}}", + "iframeConnectedActive": "Conexão iframe VDO.Ninja estabelecida e ativa.", + "streamConnectedActive": "Stream VDO.Ninja conectado/ativo: \"{{label}}\" (ID: {{id}})", + "autoAddingStream": "Adicionando automaticamente stream {{id}} ao OBS.", + "streamDisconnectedInactive": "Stream VDO.Ninja desconectado/inativo: \"{{label}}\" (ID: {{id}})", + "autoRemovingStream": "Removendo automaticamente stream {{id}} do OBS.", + "streamLabelUpdated": "Rótulo do stream VDO.Ninja atualizado para ID {{id}}: \"{{newLabel}}\" (era \"{{oldLabel}}\")", + "connectionLostResetting": "Conexão VDO.Ninja perdida (sem atividade do iframe). Tentando reiniciar." + }, + "obs": { + "disconnecting": "Desconectando do OBS WebSocket...", + "errorCameraPrefixRequired": "Erro: Prefixo Geral da Câmera é obrigatório para conexão com o OBS.", + "errorUrlRequired": "Erro: URL WebSocket OBS é obrigatória.", + "attemptingConnection": "Tentando conectar ao OBS WebSocket em {{url}}...", + "connectionTimeout": "Tentativa de conexão OBS WebSocket esgotou o tempo.", + "connectionOpenedWaitingHello": "Conexão OBS WebSocket aberta. Aguardando Hello do Servidor...", + "receivedHelloSendingIdentify": "Hello recebido do OBS. Enviando Identify...", + "authDataPrepared": "Dados de autenticação preparados para mensagem Identify.", + "warningAuthRequiredNoPassword": "Aviso: Servidor OBS requer autenticação, mas nenhuma senha foi fornecida.", + "authSuccessConnected": "Autenticação OBS WebSocket bem-sucedida! Conexão estabelecida.", + "requestError": "Erro na Requisição OBS (Tipo: {{type}}, ID: {{id}}): {{error}} (Código: {{code}})", + "eventSceneListChanged": "Evento OBS: Lista de cenas alterada. Buscando cenas novamente.", + "errorProcessingMessage": "Erro ao processar mensagem OBS WebSocket: {{message}}. Dados: {{data}}", + "webSocketError": "Erro OBS WebSocket: {{error}}", + "authFailedReason": "Falha na Autenticação - senha incorreta ou autenticação necessária e não fornecida.", + "connectionClosedReasonCode": "Código: {{code}}{{wasClean}}", + "uncleanDisconnection": " (Desconexão não limpa)", + "connectionClosed": "Conexão OBS WebSocket Fechada. Motivo: {{reason}}", + "errorCreatingConnection": "Erro ao criar conexão OBS WebSocket: {{message}}", + "authGenerationError": "Erro na geração de autenticação OBS: {{message}}", + "cannotSendRequestNotConnected": "Não é possível enviar requisição '{{requestType}}': Não conectado ao OBS.", + "errorSendingRequest": "Erro ao enviar requisição OBS '{{requestType}}': {{message}}", + "requestTimeout": "Requisição OBS '{{requestType}}' (ID: {{id}}) esgotou o tempo.", + "connectionEstablishedFetchingData": "Conexão OBS totalmente estabelecida. Buscando dados iniciais...", + "errorPostConnectionSetup": "Erro durante configuração pós-conexão OBS (buscando cenas): {{message}}", + "connectionClosedOrLost": "Conexão OBS foi fechada ou perdida.", + "cannotFetchScenesNotConnected": "Não é possível buscar cenas OBS: Não conectado ao OBS.", + "fetchingScenes": "Buscando cenas OBS...", + "fetchedScenesCount": "{{count}} cenas buscadas do OBS.", + "failedToFetchScenes": "Falha ao buscar cenas OBS ou nenhuma cena retornada.", + "errorFetchingScenes": "Erro ao buscar cenas OBS: {{message}}", + "cannotHighlightNotConnected": "Não é possível destacar: Não conectado ao OBS.", + "highlightLayoutActiveManualLegacy": "A cena '{{sceneName}}' usa o novo Layout de Destaque. O botão de destaque manual pode ter efeito limitado ou ser substituído.", + "stoppingScreenShareForHighlight": "Um compartilhamento de tela está ativo ({{id}}). Parando antes de destacar.", + "cannotScreenShareNotConnected": "Não é possível iniciar compartilhamento de tela: Não conectado ao OBS.", + "unhighlightingForScreenShare": "Uma câmera está destacada ({{id}}). Removendo destaque antes de iniciar compartilhamento de tela.", + "cannotAddScreenShareNotConnected": "Não é possível adicionar compartilhamento de tela: Não conectado ao OBS.", + "cannotAddScreenShareNoRoom": "Não é possível adicionar compartilhamento de tela: Nome da Sala VDO.Ninja é obrigatório para URLs de compartilhamento de tela.", + "cannotAddScreenShareNoReactionLayoutScene": "Não é possível adicionar compartilhamento de tela: Nenhuma cena está configurada com um layout de 'Reação'.", + "addingUpdatingScreenShareToReactionScenes": "Adicionando/Atualizando fonte de compart. de tela '{{sourceName}}' (URL: {{url}}) para cenas de Reação. Criação primária em '{{primaryScene}}'. ({{count}} cenas no total)", + "reconfiguringExistingScreenShare": "Reconfigurando fonte de compart. de tela existente '{{oldName}}' para ser '{{newName}}'.", + "reconfiguredRenamedScreenShare": "Fonte de compart. de tela existente reconfigurada e renomeada para '{{sourceName}}'.", + "screenShareExistsUpdating": "Fonte de compart. de tela '{{sourceName}}' já existe. Atualizando suas configurações.", + "creatingNewScreenShareInScene": "Criando nova fonte de compart. de tela '{{sourceName}}' na cena '{{sceneName}}'.", + "ensuredTransformedScreenShareReaction": "Fonte de compartilhamento de tela '{{sourceName}}' assegurada e transformada na cena de Reação '{{sceneName}}'.", + "sourceFoundInSceneEnabled": "Fonte '{{sourceName}}' encontrada na cena '{{sceneName}}', ID do item: {{itemId}}. Garantindo que está ativada.", + "sourceAddedToScene": "Fonte '{{sourceName}}' adicionada à cena '{{sceneName}}', ID do item: {{itemId}}.", + "errorCreatingSceneItem": "Erro ao criar item de cena para '{{sourceName}}' em '{{sceneName}}': {{message}}", + "errorCheckingSceneForItem": "Erro ao verificar por '{{sourceName}}' na cena '{{sceneName}}': {{message}}", + "errorApplyingInitialTransform": "Erro ao aplicar transformação padrão inicial para '{{sourceName}}' em '{{sceneName}}': {{message}}", + "successConfigScreenShare": "Compartilhamento de tela configurado com sucesso para stream {{streamId}} ({{label}}).", + "errorAddingUpdatingScreenShare": "Erro ao adicionar/atualizar fonte de compart. de tela '{{sourceName}}': {{message}}.", + "cannotToggleHighlightNotConnected": "Não é possível alternar destaque: Não conectado ao OBS.", + "streamUnhighlighted": "Stream {{id}} sem destaque (renomeado de {{oldName}} para {{newName}}).", + "streamSuccessfullyUnhighlighted": "Stream {{id}} sem destaque com sucesso (renomeado para {{newName}}).", + "streamSuccessfullyHighlighted": "Stream {{id}} destacado com sucesso (renomeado para {{newName}}).", + "unhighlightError": "Não foi possível remover o destaque (renomear) de {{sourceName}}, pode não existir ou outro erro: {{message}}", + "highlightError": "Não foi possível destacar (renomear) {{sourceName}}, pode não existir ou outro erro: {{message}}", + "legacyHighlightUnhighlightOnRemove": "O stream {{id}} era um destaque legado. Removendo o destaque.", + "cannotAddStreamNotConnected": "Não é possível adicionar stream \"{{label}}\" ({{id}}) ao OBS: Não conectado ao OBS.", + "cannotAddStreamNoTargetSceneName": "Não é possível adicionar stream \"{{label}}\" ({{id}}): Nome da cena alvo OBS é obrigatório mas não definido (sem padrão e sem mapeamento).", + "foundExistingStandardSource": "Fonte padrão '{{sourceName}}' existente encontrada para o stream {{streamId}}.", + "foundExistingHighlightForConnectingStream": "Fonte OBS existente '{{sourceName}}' que corresponde à nomeação de destaque para o stream {{streamId}} conectado. Atualizando estado interno de destaque.", + "foundExistingHighlightedSource": "Fonte destacada '{{sourceName}}' existente encontrada para o stream {{streamId}}.", + "noExistingSourceFoundWillCreate": "Nenhuma fonte padrão ('{{baseSourceName}}') nem destacada ('{{highlightedSourceName}}') encontrada para o stream {{streamId}}. Será criada uma nova.", + "noExistingStandardSourceSamePrefix": "Fonte padrão '{{sourceName}}' não encontrada para o stream {{streamId}} (prefixo de destaque é o mesmo). Será criada uma nova.", + "errorGettingCanvasSize": "Erro ao obter tamanho da tela OBS: {{message}}. Usando padrão {{width}}x{{height}}.", + "sourceNotGlobalCreating": "Fonte '{{sourceName}}' não existe globalmente. Criando na cena '{{sceneName}}'.", + "sourceCreatedAddedToScene": "Fonte '{{sourceName}}' criada e adicionada à cena '{{sceneName}}'.", + "sourceGlobalUpdatingWithUrl": "Fonte '{{sourceName}}' já existe globalmente. Atualizando suas configurações. URL: {{url}}", + "sourceFoundAsItemInScene": "Fonte '{{sourceName}}' encontrada como item na cena '{{sceneName}}'.", + "sourceNotInSceneAdding": "Fonte '{{sourceName}}' não está na cena '{{sceneName}}'. Adicionando.", + "cloningToMainScene": "Clonando fonte '{{sourceName}}' para cena principal (dos checkboxes) '{{sceneName}}' devido à regra de mapeamento.", + "addingSourceToOtherScene": "Adicionando fonte '{{sourceName}}' como item para outra cena selecionada '{{sceneName}}'.", + "switchingProgramScene": "Mudando cena do programa atual OBS para '{{sceneName}}'.", + "successfullyProcessedStream": "Stream \"{{label}}\" ({{id}}) processado com sucesso, fonte OBS efetiva: '{{sourceName}}'.", + "errorManagingStream": "Erro ao gerenciar stream '{{sourceName}}' (\"{{label}}\") no OBS: {{message}}", + "applyTransformAndGridCalled": "applyTransformAndGrid chamado para {{sourceName}} em {{sceneName}}. Acionando atualização completa de layout para a cena.", + "triggeringLayoutUpdate": "Acionando atualização de layout para a cena '{{sceneName}}'...", + "gridFallbackSourceChanged": "As configurações de grid para '{{sourceGridScene}}' (candidata principal para fallback) foram alteradas. Acionando atualização para a cena Reaction/Highlight '{{dependentScene}}'.", + "noSceneItemsForLayout": "Nenhum item de cena encontrado na cena '{{sceneName}}' para atualização de layout.", + "applyingConfiguredLayout": "Aplicando layout '{{layoutType}}' à cena '{{sceneName}}'. ({{count}} itens)", + "unknownLayoutType": "Tipo de layout '{{layoutType}}' desconhecido para a cena '{{sceneName}}'. Aplicando dimensionamento padrão.", + "noSpecificLayoutApplyingDefault": "Nenhum layout específico para a cena '{{sceneName}}'. Aplicando dimensionamento padrão de fonte ('{{sizing}}').", + "errorTriggeringLayoutUpdate": "Erro durante a atualização de layout para a cena '{{sceneName}}': {{message}}", + "applyingDefaultSizing": "Aplicando dimensionamento padrão de fonte ('{{sizing}}') para {{count}} itens na cena '{{sceneName}}'.", + "errorApplyingDefaultTransformItem": "Erro ao aplicar transformação padrão para {{sourceName}} em {{sceneName}}: {{message}}", + "noSourcesForGridLayout": "Nenhuma fonte de câmera VDO.Ninja para aplicar layout de Grade na cena '{{sceneName}}'.", + "applyingGridLayoutScene": "Aplicando Layout de Grade para {{count}} fontes de câmera VDO.Ninja na cena '{{sceneName}}'.", + "applyingGridSplitScreen": "Aplicando layout de grade de tela dividida para 2 câmeras à cena '{{sceneName}}'.", + "reactionMainNotFoundFallbackGrid": "Conteúdo principal para layout de Reação na cena '{{sceneName}}' não encontrado/visível. Aplicando grade de fallback de câmeras.", + "highlightMainNotFoundFallbackGrid": "Conteúdo principal para layout de Destaque na cena '{{sceneName}}' não encontrado/visível. Aplicando grade de fallback de câmeras.", + "usingGridSceneFallbackSettings": "Usando configurações de grade da primeira cena 'Grade' configurada ('{{sceneName}}') como fallback para '{{targetScene}}'.", + "usingDefaultGridFallbackSettings": "Nenhuma cena de layout 'Grade' encontrada. Usando configurações de grade padrão como fallback para '{{targetScene}}'.", + "applyingFallbackGridToCameras": "Aplicando layout de Grade de fallback para {{count}} fontes de câmera na cena '{{sceneName}}'.", + "noCamerasForFallbackGridHidingAll": "Nenhum item de câmera para exibir na grade de fallback para a cena '{{sceneName}}'. Todas as fontes VDO nesta cena serão ocultadas.", + "cannotRemoveStreamNotConnected": "Não é possível remover stream {{id}} do OBS: Não conectado ao OBS.", + "triggeredRemoval": "Remoção acionada por usuário ou automaticamente do stream '{{id}}' do OBS. Fonte base: '{{baseName}}'.", + "streamScreenSharingRemoving": "Stream {{id}} estava ativamente compartilhando tela. Iniciando remoção do compartilhamento de tela.", + "finishedRemovingSourceItems": "Concluída remoção de itens de fonte para stream {{id}} das cenas OBS especificadas.", + "cannotRemoveScreenShareNotConnected": "Não é possível remover compartilhamento de tela: Não conectado ao OBS.", + "attemptingRemoveScreenShareSource": "Tentando remover completamente fonte de compart. de tela '{{sourceName}}' do OBS (todas as cenas e entrada).", + "removingGlobalInput": "Removendo entrada global '{{sourceName}}' do OBS.", + "successfullyRemovedInput": "Entrada '{{sourceName}}' removida com sucesso.", + "errorScreenShareRemovalProcess": "Erro durante processo de remoção de compart. de tela para '{{sourceName}}': {{message}}", + "removingSourceItemFromScene": "Removendo item de fonte '{{sourceName}}' (ID: {{itemId}}) da cena '{{sceneName}}'.", + "errorTryingRemoveSourceItem": "Erro ao tentar remover item de fonte '{{sourceName}}' da cena '{{sceneName}}': {{message}}", + "codecChangedUpdatingSources": "Codec alterado para: {{codec}}. Atualizando fontes OBS...", + "codecChangedNotConnected": "OBS não está conectado. As fontes não serão atualizadas com o novo codec até reconexão e uma nova ação.", + "sourceUpdatedWithUrlAndCss": "Fonte '{{sourceName}}' atualizada com URL: {{url}} e CSS personalizado.", + "screenShareSourceUpdatedWithUrlAndCss": "Fonte de compart. de tela '{{sourceName}}' atualizada com URL: {{url}} e CSS personalizado.", + "codecUpdateComplete": "Atualização de codec para fontes OBS completa.", + "codecCssUpdateComplete": "Atualização de Codec/CSS para fontes OBS completa.", + "inputNameChanged": "Evento OBS: Nome da entrada alterado de '{{oldName}}' para '{{newName}}'. Verificando cenas relevantes para atualizações de layout.", + "foundPreExistingHighlight": "Fonte destacada pré-existente encontrada no OBS: '{{sourceName}}'. Definindo destaque ativo para o ID de stream: {{streamId}}.", + "errorCheckingMainContentEnabled": "Erro ao verificar se o conteúdo principal {{sourceName}} está ativo: {{message}}" + } + } +} diff --git a/obs.html b/obs.html index 107a79d9..a0498300 100644 --- a/obs.html +++ b/obs.html @@ -1,1503 +1,4308 @@ -
- - -