diff --git a/src/components/launch/LaunchWindow.tsx b/src/components/launch/LaunchWindow.tsx index 3b2bebfe..056a4fd8 100644 --- a/src/components/launch/LaunchWindow.tsx +++ b/src/components/launch/LaunchWindow.tsx @@ -374,6 +374,7 @@ export function LaunchWindow() { > {systemLocaleSuggestion && (
diff --git a/src/i18n/config.ts b/src/i18n/config.ts index 70dd6777..a30974e3 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -11,6 +11,7 @@ export const SUPPORTED_LOCALES = [ "ar", "ru", "vi", + "pt-BR", ] as const; export const I18N_NAMESPACES = [ "common", diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json new file mode 100644 index 00000000..bebd54d1 --- /dev/null +++ b/src/i18n/locales/pt-BR/common.json @@ -0,0 +1,50 @@ +{ + "actions": { + "cancel": "Cancelar", + "save": "Salvar", + "delete": "Deletar", + "close": "Fechar", + "share": "Compartilhar", + "done": "Concluir", + "open": "Abrir", + "upload": "Upload", + "export": "Exportar", + "showInFolder": "Mostrar na Pasta", + "file": "Arquivo", + "edit": "Editar", + "view": "Visualizar", + "window": "Janela", + "quit": "Sair", + "stopRecording": "Parar Gravação", + "undo": "Desfazer", + "redo": "Refazer", + "cut": "Recortar", + "copy": "Copiar", + "paste": "Colar", + "selectAll": "Selecionar Tudo", + "minimize": "Minimizar", + "reload": "Recarregar", + "forceReload": "Forçar Recarregar", + "toggleDevTools": "Alternar ferramentas de desenvolvedor", + "actualSize": "Tamanho Original", + "zoomIn": "Aumentar Zoom", + "zoomOut": "Diminuir Zoom", + "toggleFullScreen": "Tela Cheia", + "recordingStatus": "Gravando: {{source}}", + "about": "Sobre o OpenScreen", + "services": "Serviços", + "hide": "Ocultar OpenScreen", + "hideOthers": "Ocultar Outros", + "unhide": "Mostrar Todos" + }, + "playback": { + "play": "Play", + "pause": "Pause", + "fullscreen": "Tela Cheia", + "exitFullscreen": "Sair da Tela Cheia" + }, + "locale": { + "name": "Português Brasileiro", + "short": "PT-BR" + } +} diff --git a/src/i18n/locales/pt-BR/dialogs.json b/src/i18n/locales/pt-BR/dialogs.json new file mode 100644 index 00000000..c2b20116 --- /dev/null +++ b/src/i18n/locales/pt-BR/dialogs.json @@ -0,0 +1,71 @@ +{ + "export": { + "complete": "Exportação Concluída", + "yourFormatReady": "Seu {{format}} está pronto", + "showInFolder": "Mostrar na Pasta", + "finalizingVideo": "Finalizando exportação do vídeo...", + "compilingGifProgress": "Compilando GIF... {{progress}}%", + "compilingGifWait": "Compilando GIF... Isso pode demorar um pouco", + "takeMoment": "Isso pode levar um momento...", + "failed": "Falha na Exportação", + "tryAgain": "Por favor, tente novamente", + "finalizingVideoTitle": "Finalizando Vídeo", + "compilingGif": "Compilando GIF", + "exportingFormat": "Exportando {{format}}", + "compiling": "Compilando", + "renderingFrames": "Renderizando Quadros", + "processing": "Processando...", + "finalizing": "Finalizando...", + "compilingStatus": "Compilando...", + "status": "Status", + "format": "Formato", + "frames": "Quadros", + "cancelExport": "Cancelar Exportação", + "savedSuccessfully": "{{format}} salvo com sucesso!" + }, + "tutorial": { + "triggerLabel": "Como funciona o recorte", + "title": "Como Funciona o Recorte", + "description": "Entendendo como cortar partes indesejadas do seu vídeo.", + "explanationBefore": "A ferramenta de Recorte funciona definindo os segmentos que você deseja", + "remove": "remover", + "explanationMiddle": " — qualquer coisa", + "covered": "coberta", + "explanationAfter": "por um segmento de recorte vermelho será removida quando você exportar.", + "visualExample": "Exemplo Visual", + "removed": "REMOVIDO", + "kept": "Mantido", + "part1": "Parte 1", + "part2": "Parte 2", + "part3": "Parte 3", + "finalVideo": "Vídeo Final", + "step1Title": "1. Adicionar Recorte", + "step1DescriptionBefore": "Pressione ", + "step1DescriptionAfter": " ou clique no ícone da tesoura para marcar uma seção para remoção.", + + "step2Title": "2. Ajustar", + "step2Description": "Arraste as bordas da região vermelha para cobrir exatamente o que você deseja cortar." + }, + "unsavedChanges": { + "title": "Alterações Não Salvas", + "message": "Você tem alterações não salvas.", + "detail": "Deseja salvar seu projeto antes de fechar?", + "saveAndClose": "Salvar e Fechar", + "discardAndClose": "Descartar e Fechar", + "loadProject": "Carregar Projeto…", + "saveProject": "Salvar Projeto…", + "saveProjectAs": "Salvar Projeto Como…" + }, + "fileDialogs": { + "saveGif": "Salvar GIF Exportado", + "saveVideo": "Salvar Vídeo Exportado", + "selectVideo": "Selecionar Arquivo de Vídeo", + "saveProject": "Salvar Projeto OpenScreen", + "openProject": "Abrir Projeto OpenScreen", + "gifImage": "Imagem GIF", + "mp4Video": "Vídeo MP4", + "videoFiles": "Arquivos de Vídeo", + "openscreenProject": "Projeto OpenScreen", + "allFiles": "Todos os Arquivos" + } +} diff --git a/src/i18n/locales/pt-BR/editor.json b/src/i18n/locales/pt-BR/editor.json new file mode 100644 index 00000000..7e3f6953 --- /dev/null +++ b/src/i18n/locales/pt-BR/editor.json @@ -0,0 +1,45 @@ +{ + "newRecording": { + "title": "Voltar ao Gravador", + "description": "Sua sessão atual foi salva.", + "cancel": "Cancelar", + "confirm": "Confirmar" + }, + "loadingVideo": "Carregando vídeo...", + "errors": { + "noVideoLoaded": "Nenhum vídeo carregado", + "videoNotReady": "Vídeo não está pronto", + "unableToDetermineSourcePath": "Não foi possível determinar o caminho do vídeo de origem", + "failedToSaveGif": "Falha ao salvar GIF", + "gifExportFailed": "Falha na exportação do GIF", + "failedToSaveVideo": "Falha ao salvar vídeo", + "exportFailed": "Falha na exportação", + "exportFailedWithError": "Falha na exportação: {{error}}", + "exportBackgroundLoadFailed": "Falha na exportação: não foi possível carregar a imagem de fundo ({{url}})", + "failedToSaveExport": "Falha ao salvar exportação", + "failedToSaveExportedVideo": "Falha ao salvar vídeo exportado", + "failedToRevealInFolder": "Erro ao mostrar na pasta: {{error}}" + }, + "export": { + "canceled": "Exportação cancelada", + "exportedSuccessfully": "{{format}} exportado com sucesso" + }, + "project": { + "saveCanceled": "Salvamento do projeto cancelado", + "failedToSave": "Falha ao salvar o projeto", + "savedTo": "Projeto salvo em {{path}}", + "failedToLoad": "Falha ao carregar o projeto", + "invalidFormat": "Formato de arquivo de projeto inválido", + "loadedFrom": "Projeto carregado de {{path}}" + }, + "recording": { + "failedCameraAccess": "Falha ao solicitar acesso à câmera.", + "cameraBlocked": "O acesso à câmera está bloqueado. Ative-o nas configurações do sistema para usar a webcam.", + "systemAudioUnavailable": "Áudio do sistema não disponível. Gravando sem áudio do sistema.", + "microphoneDenied": "Acesso ao microfone negado. A gravação continuará sem áudio.", + "cameraDenied": "Acesso à câmera negado. A gravação continuará sem webcam.", + "cameraDisconnected": "Webcam desconectada.", + "cameraNotFound": "Câmera não encontrada.", + "permissionDenied": "Permissão de gravação negada. Por favor, permita a gravação de tela." + } +} diff --git a/src/i18n/locales/pt-BR/launch.json b/src/i18n/locales/pt-BR/launch.json new file mode 100644 index 00000000..18538092 --- /dev/null +++ b/src/i18n/locales/pt-BR/launch.json @@ -0,0 +1,47 @@ +{ + "tooltips": { + "hideHUD": "Ocultar HUD", + "closeApp": "Fechar App", + "restartRecording": "Reiniciar gravação", + "cancelRecording": "Cancelar gravação", + "pauseRecording": "Pausar gravação", + "resumeRecording": "Retomar gravação", + "openVideoFile": "Abrir arquivo de vídeo", + "openProject": "Abrir projeto" + }, + "audio": { + "enableSystemAudio": "Ativar áudio do sistema", + "disableSystemAudio": "Desativar áudio do sistema", + "enableMicrophone": "Ativar microfone", + "disableMicrophone": "Desativar microfone", + "defaultMicrophone": "Microfone Padrão" + }, + "webcam": { + "enableWebcam": "Ativar webcam", + "disableWebcam": "Desativar webcam", + "defaultCamera": "Câmera Padrão", + "searching": "Procurando...", + "noneFound": "Nenhuma câmera encontrada", + "unavailable": "Câmera indisponível" + }, + "cursor": { + "useEditableCursor": "Usar cursor editável", + "useSystemCursor": "Usar cursor do sistema" + }, + "sourceSelector": { + "loading": "Carregando fontes...", + "screens": "Telas ({{count}})", + "windows": "Janelas ({{count}})", + "defaultSourceName": "Tela" + }, + "recording": { + "selectSource": "Por favor, selecione uma fonte para gravar" + }, + "language": "Idioma", + "systemLanguagePrompt": { + "title": "Usar o idioma do seu sistema?", + "description": "Detectamos {{language}} como o idioma do seu sistema. Deseja mudar o OpenScreen para {{language}}?", + "switch": "Mudar para {{language}}", + "keepDefault": "Manter idioma atual" + } +} diff --git a/src/i18n/locales/pt-BR/settings.json b/src/i18n/locales/pt-BR/settings.json new file mode 100644 index 00000000..6788bdb2 --- /dev/null +++ b/src/i18n/locales/pt-BR/settings.json @@ -0,0 +1,197 @@ +{ + "zoom": { + "level": "Nível de Zoom", + "customScale": "Zoom Personalizado", + "selectRegion": "Selecione uma região de zoom para ajustar", + "deleteZoom": "Excluir Zoom", + "focusMode": { + "title": "Modo de Foco", + "manual": "Manual", + "auto": "Automático", + "autoDescription": "A câmera segue a posição do cursor gravado" + }, + "threeD": { + "title": "Rotação 3D", + "preset": { + "iso": "Iso", + "left": "Esquerda", + "right": "Direita" + } + }, + "position": { + "title": "Posição do Foco", + "x": "X (%)", + "y": "Y (%)", + "hint": "0 = mais à esquerda / topo, 100 = mais à direita / inferior" + } + }, + "speed": { + "playbackSpeed": "Velocidade de Reprodução", + "selectRegion": "Selecione uma região de velocidade para ajustar", + "deleteRegion": "Excluir Região de Velocidade", + "customPlaybackSpeed": "Velocidade Personalizada", + "maxSpeedError": "A velocidade não pode ser superior a 16×" + }, + "trim": { + "deleteRegion": "Excluir Região de Recorte" + }, + "layout": { + "title": "Layout", + "preset": "Predefinição", + "selectPreset": "Selecionar predefinição", + "pictureInPicture": "Picture in Picture", + "verticalStack": "Empilhamento Vertical", + "dualFrame": "Quadro Duplo", + "noWebcam": "Sem Webcam", + "webcamShape": "Formato da Câmera", + "webcamSize": "Tamanho da Webcam" + }, + "effects": { + "title": "Efeitos de Vídeo", + "blurBg": "Desfocar Fundo", + "motionBlur": "Desfoque de Movimento", + "off": "desativado", + "on": "ativado", + "shadow": "Sombra", + "roundness": "Arredondamento", + "padding": "Espaçamento" + }, + "background": { + "title": "Fundo", + "image": "Imagem", + "color": "Cor", + "gradient": "Gradiente", + "uploadCustom": "Enviar Personalizada", + "gradientLabel": "Gradiente {{index}}", + "colorWheel": "Roda de Cores", + "colorPalette": "Paleta de Cores" + }, + "crop": { + "title": "Cortar", + "cropVideo": "Cortar Vídeo", + "dragInstruction": "Arraste cada lado para ajustar a área de corte", + "ratio": "Proporção", + "free": "Livre", + "done": "Concluir", + "lockAspectRatio": "Bloquear proporção", + "unlockAspectRatio": "Desbloquear proporção" + }, + "exportFormat": { + "mp4": "MP4", + "gif": "GIF", + "mp4Video": "Vídeo MP4", + "mp4Description": "Arquivo de vídeo de alta qualidade", + "gifAnimation": "Animação GIF", + "gifDescription": "Imagem animada para compartilhamento" + }, + "exportQuality": { + "title": "Qualidade de Exportação", + "low": "Baixa", + "medium": "Média", + "high": "Alta" + }, + "gifSettings": { + "frameRate": "Taxa de Quadros do GIF", + "size": "Tamanho do GIF", + "loop": "Loop no GIF" + }, + "project": { + "save": "Salvar Projeto", + "load": "Carregar Projeto" + }, + "export": { + "videoButton": "Exportar Vídeo", + "gifButton": "Exportar GIF", + "chooseSaveLocation": "Escolher Local para Salvar" + }, + "links": { + "reportBug": "Relatar Bug", + "starOnGithub": "Dar Estrela no GitHub" + }, + "imageUpload": { + "invalidFileType": "Tipo de arquivo inválido", + "jpgOnly": "Por favor, envie um arquivo de imagem JPG ou JPEG.", + "uploadSuccess": "Imagem personalizada enviada com sucesso!", + "failedToUpload": "Falha ao enviar imagem", + "errorReading": "Ocorreu um erro ao ler o arquivo." + }, + "annotation": { + "title": "Configurações de Anotação", + "active": "Ativo", + "typeText": "Texto", + "typeImage": "Imagem", + "typeArrow": "Seta", + "typeBlur": "Desfoque", + "textContent": "Conteúdo do Texto", + "textPlaceholder": "Digite seu texto...", + "fontStyle": "Estilo da Fonte", + "selectStyle": "Selecionar estilo", + "size": "Tamanho", + "customFonts": "Fontes Personalizadas", + "textColor": "Cor do Texto", + "background": "Fundo", + "none": "Nenhum", + "color": "Cor", + "colorWheel": "Roda de Cores", + "colorPalette": "Paleta de Cores", + "clearBackground": "Limpar Fundo", + "uploadImage": "Enviar Imagem", + "supportedFormats": "Formatos suportados: JPG, PNG, GIF, WebP", + "arrowDirection": "Direção da Seta", + "strokeWidth": "Largura do Traço: {{width}}px", + "arrowColor": "Cor da Seta", + "blurType": "Tipo de Desfoque", + "blurTypeBlur": "Desfoque", + "blurTypeMosaic": "Mosaico", + "blurColor": "Cor do Desfoque", + "blurColorWhite": "Branco", + "blurColorBlack": "Preto", + "blurShape": "Formato do Desfoque", + "blurIntensity": "Intensidade do Desfoque", + "mosaicBlockSize": "Tamanho do Bloco do Mosaico", + "blurShapeRectangle": "Retângulo", + "blurShapeOval": "Oval", + "blurShapeFreehand": "Mão Livre", + "deleteAnnotation": "Excluir Anotação", + "shortcutsAndTips": "Atalhos e Dicas", + "tipMovePlayhead": "Mova o cursor de reprodução para a seção de anotação sobreposta e selecione um item.", + "tipTabCycle": "Use Tab para alternar entre itens sobrepostos.", + "tipShiftTabCycle": "Use Shift+Tab para alternar para trás.", + "invalidImageType": "Tipo de imagem inválido", + "imageFormatsOnly": "Por favor, envie um arquivo de imagem JPG, PNG, GIF ou WebP.", + "imageUploadSuccess": "Imagem enviada com sucesso!", + "failedImageUpload": "Falha ao enviar imagem" + }, + "fontStyles": { + "classic": "Clássico", + "editor": "Editor", + "strong": "Forte", + "typewriter": "Máquina de Escrever", + "deco": "Deco", + "simple": "Simples", + "modern": "Moderno", + "clean": "Clean" + }, + "customFont": { + "dialogTitle": "Adicionar Google Font", + "urlLabel": "URL de Importação do Google Fonts", + "urlPlaceholder": "https://fonts.googleapis.com/css2?family=Roboto&display=swap", + "urlHelp": "Pegue isso no Google Fonts: Selecione uma fonte → Clique em \"Get font\" → Copie a URL @import", + "nameLabel": "Nome de Exibição", + "namePlaceholder": "Minha Fonte Personalizada", + "nameHelp": "É assim que a fonte aparecerá no seletor de fontes", + "addButton": "Adicionar Fonte", + "addingButton": "Adicionando...", + "errorEmptyUrl": "Por favor, insira uma URL de importação do Google Fonts", + "errorInvalidUrl": "Por favor, insira uma URL válida do Google Fonts", + "errorEmptyName": "Por favor, insira um nome para a fonte", + "errorExtractFailed": "Não foi possível extrair a família da fonte da URL", + "successMessage": "Fonte \"{{fontName}}\" adicionada com sucesso", + "failedToAdd": "Falha ao adicionar fonte", + "errorTimeout": "A fonte demorou muito para carregar. Por favor, verifique a URL e tente novamente.", + "errorLoadFailed": "A fonte não pôde ser carregada. Por favor, verifique se a URL do Google Fonts está correta." + }, + "language": { + "title": "Idioma" + } +} diff --git a/src/i18n/locales/pt-BR/shortcuts.json b/src/i18n/locales/pt-BR/shortcuts.json new file mode 100644 index 00000000..208cd1dc --- /dev/null +++ b/src/i18n/locales/pt-BR/shortcuts.json @@ -0,0 +1,37 @@ +{ + "title": "Atalhos de Teclado", + "customize": "Personalizar", + "configurable": "Configurável", + "fixed": "Fixo", + "pressKey": "Pressione uma tecla…", + "clickToChange": "Clique para alterar", + "pressEscToCancel": "Pressione Esc para cancelar", + "helpText": "Clique em um atalho e pressione a nova combinação de teclas. Pressione Esc para cancelar.", + "resetToDefaults": "Redefinir para os padrões", + "alreadyUsedBy": "Já utilizado por {{action}}", + "swap": "Trocar", + "reservedShortcut": "Este atalho é reservado para \"{{label}}\" e não pode ser reatribuído.", + "savedToast": "Atalhos de teclado salvos", + "resetToast": "Atalhos redefinidos para o padrão — clique em Salvar para aplicar", + "actions": { + "addZoom": "Adicionar Zoom", + "addTrim": "Adicionar Recorte", + "addSpeed": "Adicionar Velocidade", + "addAnnotation": "Adicionar Anotação", + "addBlur": "Adicionar Desfoque", + "addKeyframe": "Adicionar Quadro-chave", + "deleteSelected": "Excluir Selecionado", + "playPause": "Reproduzir / Pausar" + }, + "fixedActions": { + "undo": "Desfazer", + "redo": "Refazer", + "cycleAnnotationsForward": "Alternar Anotações (Próximo)", + "cycleAnnotationsBackward": "Alternar Anotações (Anterior)", + "deleteSelectedAlt": "Excluir Selecionado (alt)", + "panTimeline": "Mover Linha do Tempo", + "zoomTimeline": "Zoom na Linha do Tempo", + "frameBack": "Quadro Anterior", + "frameForward": "Próximo Quadro" + } +} diff --git a/src/i18n/locales/pt-BR/timeline.json b/src/i18n/locales/pt-BR/timeline.json new file mode 100644 index 00000000..ba875db6 --- /dev/null +++ b/src/i18n/locales/pt-BR/timeline.json @@ -0,0 +1,55 @@ +{ + "buttons": { + "addZoom": "Adicionar Zoom (Z)", + "suggestZooms": "Sugerir Zooms a partir do Cursor", + "addTrim": "Adicionar Recorte (T)", + "addAnnotation": "Adicionar Anotação (A)", + "addBlur": "Adicionar Desfoque (B)", + "addSpeed": "Adicionar Velocidade (S)" + }, + "hints": { + "pressZoom": "Pressione Z para adicionar zoom", + "pressTrim": "Pressione T para adicionar recorte", + "pressAnnotation": "Pressione A para adicionar anotação", + "pressBlur": "Pressione B para adicionar região de desfoque", + "pressSpeed": "Pressione S para adicionar velocidade" + }, + "labels": { + "pan": "Mover", + "zoom": "Zoom", + "trim": "Recorte", + "speed": "Velocidade", + "zoomItem": "Zoom {{index}}", + "trimItem": "Recorte {{index}}", + "speedItem": "Velocidade {{index}}", + "annotationItem": "Anotação", + "blurItem": "Desfoque {{index}}", + "imageItem": "Imagem", + "emptyText": "Texto vazio" + }, + "emptyState": { + "noVideo": "Nenhum Vídeo Carregado", + "dragAndDrop": "Arraste e solte um vídeo para começar a editar" + }, + "errors": { + "cannotPlaceZoom": "Não é possível colocar zoom aqui", + "zoomExistsAtLocation": "Já existe um zoom neste local ou não há espaço suficiente disponível.", + "zoomSuggestionUnavailable": "Sugestão de zoom não disponível", + "noCursorTelemetry": "Nenhuma telemetria de cursor disponível", + "noCursorTelemetryDescription": "Grave um screencast primeiro para gerar sugestões baseadas no cursor.", + "noUsableTelemetry": "Nenhuma telemetria de cursor utilizável", + "noUsableTelemetryDescription": "A gravação não inclui dados suficientes de movimento do cursor.", + "noDwellMoments": "Nenhum momento claro de parada do cursor encontrado", + "noDwellMomentsDescription": "Tente uma gravação com pausas mais lentas do cursor em ações importantes.", + "noAutoZoomSlots": "Nenhum slot de zoom automático disponível", + "noAutoZoomSlotsDescription": "Pontos de parada detectados sobrepõem regiões de zoom existentes.", + "cannotPlaceTrim": "Não é possível colocar recorte aqui", + "trimExistsAtLocation": "Já existe um recorte neste local ou não há espaço suficiente disponível.", + "cannotPlaceSpeed": "Não é possível colocar velocidade aqui", + "speedExistsAtLocation": "Já existe uma região de velocidade neste local ou não há espaço suficiente disponível." + }, + "success": { + "addedZoomSuggestions": "Adicionada {{count}} sugestão de zoom baseada no cursor", + "addedZoomSuggestionsPlural": "Adicionadas {{count}} sugestões de zoom baseadas no cursor" + } +}