Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions electron/locale/catalogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { es } from "./es";
import { fr } from "./fr";
import { ja } from "./ja";
import { ko } from "./ko";
import { pt } from "./pt";
import { zhCN } from "./zh-CN";
import { zhTW } from "./zh-TW";

Expand All @@ -19,4 +20,5 @@ export const desktopCatalogs: Record<UiLocale, DesktopMessageCatalog> = {
es,
fr,
de,
pt,
};
43 changes: 43 additions & 0 deletions electron/locale/pt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { DesktopMessageKey } from "./en";

export const pt: Record<DesktopMessageKey, string> = {
file: "Arquivo",
openProject: "Abrir projeto…",
reopenLast: "Reabrir o último projeto",
recentProjects: "Projetos recentes",
noRecent: "Não há projetos recentes",
clearRecent: "Limpar projetos recentes",
edit: "Editar",
undo: "Desfazer",
redo: "Refazer",
cut: "Cortar",
copy: "Copiar",
paste: "Colar",
pasteMatch: "Colar e combinar formatação",
delete: "Excluir",
selectAll: "Selecionar tudo",
view: "Exibir",
reload: "Recarregar",
forceReload: "Forçar recarga",
devTools: "Alternar ferramentas de desenvolvedor",
resetZoom: "Tamanho real",
zoomIn: "Aproximar",
zoomOut: "Afastar",
fullscreen: "Alternar tela cheia",
window: "Janela",
minimize: "Minimizar",
zoom: "Zoom",
front: "Trazer tudo para a frente",
close: "Fechar janela",
quit: "Sair do Rescript",
about: "Sobre o Rescript",
services: "Serviços",
hide: "Ocultar Rescript",
hideOthers: "Ocultar outros",
unhide: "Mostrar tudo",
restart: "Reiniciar",
later: "Mais tarde",
updateTitle: "Atualização disponível",
updateMessage: "Rescript {version} está pronto para ser instalado.",
updateDetail: "Reinicie agora para aplicar a atualização.",
};
4 changes: 4 additions & 0 deletions lib/alignModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export const ALIGN_MODELS: Partial<
id: "onnx-community/mms-300m-1130-forced-aligner-ONNX",
normalize: "latin-lower",
},
pt: {
id: "onnx-community/mms-300m-1130-forced-aligner-ONNX",
normalize: "latin-lower",
},
zh: {
id: "onnx-community/wav2vec2-large-xlsr-53-chinese-zh-cn-ONNX",
normalize: "cjk",
Expand Down
10 changes: 10 additions & 0 deletions lib/fillers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ const FILLER_WORDS = new Set([
"emm",
"emmm",
"eee",
// Portuguese
"hã",
"hãhã",
"ahn",
"ahnn",
"ãh",
"ãhh",
"ãhm",
"éh",
"éhh",
// Chinese
"嗯",
"嗯嗯",
Expand Down
2 changes: 2 additions & 0 deletions lib/i18n/catalogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { es } from "./messages/es";
import { fr } from "./messages/fr";
import { ja } from "./messages/ja";
import { ko } from "./messages/ko";
import { pt } from "./messages/pt";
import { zhCN } from "./messages/zh-CN";
import { zhTW } from "./messages/zh-TW";
import type { UiLocale } from "./locales";
Expand All @@ -19,4 +20,5 @@ export const catalogs: Record<UiLocale, MessageCatalog> = {
es,
fr,
de,
pt,
};
8 changes: 8 additions & 0 deletions lib/i18n/locales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const UI_LOCALES = [
"es",
"fr",
"de",
"pt",
] as const;

export type UiLocale = (typeof UI_LOCALES)[number];
Expand Down Expand Up @@ -92,6 +93,12 @@ export const UI_LOCALE_META: Record<UiLocale, UiLocaleMeta> = {
nsis: "de_DE",
match: prefix("de"),
},
pt: {
htmlLang: "pt",
nativeLabel: "Português",
nsis: "pt_BR",
match: prefix("pt"),
},
};

function isTraditionalChinese(tag: string): boolean {
Expand All @@ -111,6 +118,7 @@ const MATCH_ORDER: readonly UiLocale[] = [
"es",
"fr",
"de",
"pt",
"en",
];

Expand Down
218 changes: 218 additions & 0 deletions lib/i18n/messages/pt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import type { MessageKey } from "./en";

/** Portuguese UI catalog. Every key in {@link en} must be present. */
export const pt: Record<MessageKey, string> = {
"app.title": "Rescript — edite vídeos como edita texto",
"common.cancel": "Cancelar",
"common.close": "Fechar",
"common.delete": "Excluir",
"common.download": "Baixar",
"common.import": "Importar",
"common.loading": "Carregando",
"common.remove": "Remover",
"common.restore": "Restaurar",
"common.retry": "Tentar de novo",
"common.searchOrCreate": "Buscar ou criar…",
"common.settings": "Configurações",
"common.system": "Sistema",
"common.tools": "Ferramentas",
"settings.appearance": "Aparência",
"settings.light": "Claro",
"settings.dark": "Escuro",
"settings.interfaceLanguage": "Idioma da interface",
"settings.privacy": "Privacidade",
"settings.helpImprove": "Ajude a melhorar o app",
"settings.telemetryHelp": "Envia estatísticas anônimas de uso de recursos e relatórios de falhas.",
"settings.support": "Suporte / feedback",
"settings.reportIssue": "Reportar um problema",
"settings.homepage": "Página inicial",
"settings.github": "GitHub",
"settings.followX": "Seguir no X",
"model.transcriptSource": "Origem da transcrição",
"model.language": "Idioma",
"model.transcriptLanguage": "Idioma da transcrição",
"model.importTranscript": "Importar transcrição",
"upload.recentProjects": "Projetos recentes",
"upload.removeRecent": "Remover dos recentes",
"upload.dropPrefix": "Solte um arquivo de vídeo ou áudio aqui, ou",
"upload.browse": "navegue",
"upload.chooseTranscriptFirst": "Escolha uma transcrição no menu acima e depois solte a mídia",
"upload.willUseTranscript": "Usará {name} · MP4, WebM, MOV, MP3, WAV, …",
"upload.mediaFormats": "MP4, WebM, MOV, MP3, WAV, M4A, …",
"upload.gettingReady": "Preparando tudo",
"upload.gettingReadyHelp": "Configurando o motor de mídia; isso só acontece uma vez.",
"upload.unsupported": "Este navegador não pode executar o editor",
"upload.unsupportedHelp":
"A edição precisa de SharedArrayBuffer, que exige uma página isolada entre origens. Experimente uma versão recente do Chrome, Edge, Safari ou Firefox via HTTPS.",
"upload.transcribeTitle": "Transcrever",
"upload.transcribeText": "Whisper localmente, ou importe SRT / VTT.",
"upload.editTitle": "Editar",
"upload.editText": "Selecione palavras e pressione Excluir para editar.",
"upload.exportTitle": "Exportar",
"upload.exportText": "Renderize o corte final em MP4 ou M4A.",
"editor.chooseTranscript": "Primeiro escolha um arquivo de transcrição no menu de origem.",
"editor.chooseMedia": "Escolha um arquivo de vídeo ou áudio.",
"editor.undo": "Desfazer (⌘Z)",
"editor.redo": "Refazer (⇧⌘Z)",
"editor.export": "Exportar",
"topbar.startOver": "Começar de novo",
"transcript.replace": "Substituir transcrição a partir de SRT, VTT ou JSON",
"transcript.header": "Transcrição",
"transcript.wordDeleted": "{count} palavra",
"transcript.wordsDeleted": "{count} palavras",
"transcript.replaceConfirm": "Substituir a transcrição atual por este arquivo?",
"transcript.invalidFile": "Escolha um arquivo de transcrição SRT, VTT ou JSON.",
"transcript.noSpeech": "Nenhuma fala detectada. Confirme que este arquivo tem áudio, ou importe uma transcrição.",
"transcript.cut": "Cortar",
"transcript.follow": "Seguir cabeçote",
"transcript.hideDeleted": "Ocultar palavras excluídas",
"transcript.showDeleted": "Mostrar palavras excluídas",
"transcript.correct": "Corrigir",
"transcript.scrollWithPlayhead": "Rolar com o cabeçote",
"transcript.joinSplit": "Clipe dividido — clique para unir estes clipes",
"transcript.joinClips": "Unir clipes",
"transcript.hesitation": "Hesitação detectada (não transcrita) — corte-a com Remover vícios de linguagem",
"tools.bulk": "Limpezas em massa da transcrição",
"tools.removeFillers": "Remover vícios de linguagem",
"tools.removeFillersTitle": "Corta vícios (\"ãh\", \"mmm\", \"...\", …) do vídeo",
"tools.restoreFillers": "Restaurar vícios de linguagem",
"tools.restoreFillersTitle": "Devolve cada vício cortado",
"tools.removeSilences": "Remover silêncios",
"tools.removeSilencesTitle": "Corta pausas e silêncios (≥{seconds} s) do vídeo",
"tools.restoreSilences": "Restaurar silêncios",
"tools.restoreSilencesTitle": "Devolve cada pausa cortada",
"timeline.removed": "{trimmed} removido — duração original {duration}",
"timeline.back5": "Voltar 5 s",
"timeline.playPause": "Reproduzir / pausar (espaço)",
"timeline.forward5": "Avançar 5 s",
"timeline.split": "Dividir",
"timeline.splitTitle": "Dividir clipe no cabeçote (S)",
"timeline.splitDisabled": "Mova o cabeçote para uma região mantida para dividir",
"timeline.delete": "Excluir",
"timeline.deleteTitle": "Excluir clipe selecionado (Excluir)",
"timeline.deleteDisabled": "Selecione um clipe na linha do tempo para excluí-lo",
"timeline.restore": "Restaurar",
"timeline.restoreTitle": "Restaurar corte selecionado (Excluir)",
"timeline.restoreDisabled": "Selecione um corte ou uma seção de silêncio na linha do tempo para restaurar",
"timeline.zoomOut": "Afastar",
"timeline.fit": "Ajustar à janela",
"timeline.zoomIn": "Aproximar — arraste as bordas das palavras para ajustar o tempo",
"timeline.joinClips": "Unir estes clipes (remover divisão)",
"timeline.trimStart": "Recortar início do clipe",
"timeline.trimEnd": "Recortar final do clipe",
"timeline.hesitationAdjust": "… hesitação detectada — arraste as bordas para ajustar, ou corte-a com Remover vícios de linguagem",
"timeline.hesitationCut": "… hesitação detectada — corte-a com Remover vícios de linguagem",
"timeline.dragTiming": "{word} — arraste as bordas para ajustar o tempo",
"timeline.scrollZoom": "Role para aproximar / afastar",
"speaker.moveStart": "Arraste para mover onde este falante começa",
"speaker.moveLabel": "Mover rótulo do falante",
"speaker.options": "Opções do falante",
"speaker.change": "Alterar falante",
"speaker.rename": "Renomear falante",
"speaker.renameAction": "Renomear",
"speaker.replace": "Substituir no projeto por…",
"speaker.removeProject": "Remover do projeto",
"speaker.newName": "Novo nome",
"speaker.find": "Buscar um falante…",
"speaker.noMatches": "Nenhum falante correspondente",
"speaker.renameTo": "Renomear {current} para {next}",
"speaker.button": "Falante",
"speaker.search": "Buscar ou criar…",
"speaker.defaultName": "Falante {number}",
"speaker.create": "Criar \"{name}\"",
"export.title": "Exportar",
"export.type": "Tipo de exportação",
"export.video": "Vídeo",
"export.audio": "Áudio",
"export.transcript": "Transcrição",
"export.subtitles": "Legendas",
"export.videoUnavailable": "A exportação de vídeo não está disponível para projetos só de áudio",
"export.noAudio": "Este arquivo não tem faixa de áudio",
"export.noWordsFirst": "Transcreva ou importe uma transcrição primeiro",
"export.format": "Formato",
"export.resolution": "Resolução",
"export.original": "Original",
"export.plainText": "Texto sem formatação",
"export.statOriginal": "Original",
"export.statCuts": "Cortes",
"export.statEdited": "Editado",
"export.transcriptHelp": "Texto com rótulos de falante e cortes removidos. Sem marcas de tempo.",
"export.subtitlesHelp":
"SRT e VTT usam a linha do tempo editada (com cortes aplicados). JSON conserva a lista completa de palavras para reimportar.",
"export.encodingHelp": "Recodificando com ffmpeg.wasm — arquivos longos demoram um pouco.",
"export.reexport": "Reexportar com as últimas edições",
"export.rendering": "Renderizando no seu navegador…",
"export.downloadFile": "Baixar {name}",
"export.downloadFormat": "Baixar .{format}",
"export.exportFormat": "Exportar {format}",
"export.timeline": "Linha do tempo",
"export.timelineTitle": "Exportar uma sequência NLE (Resolve, Premiere, Final Cut, Pro Tools)",
"export.nle": "NLE",
"export.frameRate": "Taxa de quadros",
"export.timelineHelp":
"A sequência referencia a mídia original pelo nome do arquivo — vincule-a de novo no NLE após importar.",
"export.timelineHelpAaf": "AAF do Pro Tools / Logic (somente metadados).",
"export.timelineHelpFcpx": "FCPXML do Final Cut Pro.",
"export.timelineHelpPremiere": "XML do Adobe Premiere Pro (xmeml).",
"export.timelineHelpResolve": "XML do DaVinci Resolve (xmeml).",
"export.aafOverCap":
"Esta edição tem {count} clipes; AAF admite até {max}. Use Resolve, Premiere ou Final Cut.",
"export.preparing": "Preparando…",
"import.reading": "Lendo transcrição…",
"import.importing": "Importando…",
"import.failed": "Falha ao importar",
"import.readingFile": "Lendo arquivo…",
"import.chooseFileShort": "Escolha um arquivo…",
"import.chooseFile": "Escolha uma transcrição SRT, VTT ou JSON",
"import.selected": "{name} selecionado",
"banner.faster": "Quer transcrições e exportações mais rápidas?",
"banner.getDesktop": "Obtenha o app de desktop do Rescript",
"banner.downloadFor": "Baixar para {platform}",
"banner.dismiss": "Dispensar",
"social.githubRepo": "Repositório do GitHub",
"social.discordServer": "Servidor do Discord",
"social.xProfile": "Perfil do X",
"globalError.title": "Rescript — algo deu errado",
"globalError.heading": "Algo deu errado",
"globalError.body":
"O editor encontrou um erro inesperado. Seus projetos salvos ainda estão neste dispositivo; ao recarregar devem voltar.",
"progress.loadingMedia": "Carregando mídia…",
"progress.loadingMediaEngine": "Carregando motor de mídia…",
"progress.extractingAudio": "Extraindo áudio…",
"progress.loadingSpeechModel": "Carregando modelo de voz…",
"progress.loadingSpeechCache": "Carregando modelo de voz do cache…",
"progress.downloadingSpeech": "Baixando modelo de voz…",
"progress.gpuFallback": "A GPU foi interrompida — continuando na CPU…",
"progress.detectingSpeech": "Detectando fala…",
"progress.transcribing": "Transcrevendo…",
"progress.loadingAlignCache": "Carregando modelo de alinhamento do cache…",
"progress.downloadingAlign": "Baixando modelo de alinhamento…",
"progress.aligning": "Alinhando palavras…",
"progress.speakers": "Identificando falantes…",
"error.selectModel": "Selecione um modelo de voz para transcrever.",
"error.workerCrashed": "O worker de transcrição falhou.",
"error.mediaEngineNetwork": "Não foi possível carregar o motor de mídia — a conexão caiu. Verifique sua internet e tente de novo.",
"error.processFile": "Não foi possível processar este arquivo.",
"error.extractAudio": "Não foi possível extrair áudio deste arquivo.",
"error.nothingToExport": "Tudo foi excluído — não há nada para exportar.",
"error.videoExport": "A exportação falhou ao renderizar o vídeo.",
"error.audioExport": "A exportação falhou ao renderizar o áudio.",
"error.export": "Erro ao exportar.",
"error.timelineExport": "Erro ao exportar a linha do tempo.",
"error.timelineEmpty": "Não há nada para colocar na linha do tempo.",
"error.aafTemplate": "Não foi possível carregar o modelo de exportação AAF.",
"error.emptyTranscript": "Esse arquivo de transcrição está vazio.",
"error.noTimedWords": "Não foram encontradas palavras com tempo nessa transcrição.",
"error.parseJson": "Não foi possível analisar essa transcrição JSON.",
"error.jsonShape": 'JSON deve ser um array de palavras ou { "words": [...] }.',
"error.noWords": "Não há palavras para exportar.",
"error.projectMissing": "Esse projeto não está mais salvo.",
"error.openProject": "Não foi possível abrir esse projeto.",
"error.removeProject": "Não foi possível remover esse projeto.",
"error.readTranscript": "Não foi possível ler essa transcrição.",
"error.clearRecent": "Não foi possível limpar os projetos recentes.",
"error.modelDownload":
"Não foi possível terminar de baixar o modelo de voz — a conexão caiu. Verifique sua internet e tente de novo; as partes já baixadas são preservadas.",
"error.gpuReset": "A transcrição foi interrompida quando a GPU reiniciou (muitas vezes após bloquear a tela). Tente de novo.",
"confirm.clearRecent": "Remover todos os projetos recentes? As edições salvas serão excluídas.",
};
10 changes: 9 additions & 1 deletion lib/languages.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type TranscriptLanguage = "en" | "es" | "fr" | "de" | "zh";
export type TranscriptLanguage = "en" | "es" | "fr" | "de" | "pt" | "zh";

export interface TranscriptLanguageInfo {
label: string;
Expand Down Expand Up @@ -41,6 +41,12 @@ export const TRANSCRIPT_LANGUAGES: Record<
flag: "🇩🇪",
code: "DE",
},
pt: {
label: "Portuguese",
nativeLabel: "Português",
flag: "🇧🇷",
code: "PT",
},
zh: {
label: "Chinese",
nativeLabel: "中文",
Expand All @@ -54,6 +60,7 @@ export const TRANSCRIPT_LANGUAGE_ORDER: TranscriptLanguage[] = [
"es",
"fr",
"de",
"pt",
"zh",
];

Expand All @@ -65,6 +72,7 @@ export function isTranscriptLanguage(
value === "es" ||
value === "fr" ||
value === "de" ||
value === "pt" ||
value === "zh"
);
}
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@
"ko_KR",
"es_ES",
"fr_FR",
"de_DE"
"de_DE",
"pt_BR"
],
"multiLanguageInstaller": true,
"artifactName": "${productName}-Setup.${ext}"
Expand Down
Loading
Loading