diff --git a/.gitignore b/.gitignore index 359af33e..4653afb1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ +# translations +# *.mo # NOTE: including the .mo in the repository to allow simple installation via: pip install git+ +*.pot + + # demo and debug folders myTests/* __pycache__/ @@ -98,4 +103,4 @@ Temporary Items # swp files *.swp -.idea/ \ No newline at end of file +.idea/ diff --git a/FoxDot/demo/00_intro.py b/FoxDot/demo/en/00_intro.py similarity index 100% rename from FoxDot/demo/00_intro.py rename to FoxDot/demo/en/00_intro.py diff --git a/FoxDot/demo/01_playing_notes.py b/FoxDot/demo/en/01_playing_notes.py similarity index 100% rename from FoxDot/demo/01_playing_notes.py rename to FoxDot/demo/en/01_playing_notes.py diff --git a/FoxDot/demo/02_algorithmic_manipulation.py b/FoxDot/demo/en/02_algorithmic_manipulation.py similarity index 100% rename from FoxDot/demo/02_algorithmic_manipulation.py rename to FoxDot/demo/en/02_algorithmic_manipulation.py diff --git a/FoxDot/demo/03_playing_samples.py b/FoxDot/demo/en/03_playing_samples.py similarity index 100% rename from FoxDot/demo/03_playing_samples.py rename to FoxDot/demo/en/03_playing_samples.py diff --git a/FoxDot/demo/04_using_patterns.py b/FoxDot/demo/en/04_using_patterns.py similarity index 100% rename from FoxDot/demo/04_using_patterns.py rename to FoxDot/demo/en/04_using_patterns.py diff --git a/FoxDot/demo/05_player_attributes.py b/FoxDot/demo/en/05_player_attributes.py similarity index 100% rename from FoxDot/demo/05_player_attributes.py rename to FoxDot/demo/en/05_player_attributes.py diff --git a/FoxDot/demo/06_rests.py b/FoxDot/demo/en/06_rests.py similarity index 100% rename from FoxDot/demo/06_rests.py rename to FoxDot/demo/en/06_rests.py diff --git a/FoxDot/demo/07_basic_clock.py b/FoxDot/demo/en/07_basic_clock.py similarity index 100% rename from FoxDot/demo/07_basic_clock.py rename to FoxDot/demo/en/07_basic_clock.py diff --git a/FoxDot/demo/08_scales.py b/FoxDot/demo/en/08_scales.py similarity index 100% rename from FoxDot/demo/08_scales.py rename to FoxDot/demo/en/08_scales.py diff --git a/FoxDot/demo/09_groups.py b/FoxDot/demo/en/09_groups.py similarity index 100% rename from FoxDot/demo/09_groups.py rename to FoxDot/demo/en/09_groups.py diff --git a/FoxDot/demo/10_using_vars.py b/FoxDot/demo/en/10_using_vars.py similarity index 100% rename from FoxDot/demo/10_using_vars.py rename to FoxDot/demo/en/10_using_vars.py diff --git a/FoxDot/demo/11_playing_custom_samples.py b/FoxDot/demo/en/11_playing_custom_samples.py similarity index 100% rename from FoxDot/demo/11_playing_custom_samples.py rename to FoxDot/demo/en/11_playing_custom_samples.py diff --git a/FoxDot/demo/12_synthdefs.py b/FoxDot/demo/en/12_synthdefs.py similarity index 100% rename from FoxDot/demo/12_synthdefs.py rename to FoxDot/demo/en/12_synthdefs.py diff --git a/FoxDot/demo/13_advanced_clock.py b/FoxDot/demo/en/13_advanced_clock.py similarity index 100% rename from FoxDot/demo/13_advanced_clock.py rename to FoxDot/demo/en/13_advanced_clock.py diff --git a/FoxDot/demo/14_player_attributes_reference.py b/FoxDot/demo/en/14_player_attributes_reference.py similarity index 100% rename from FoxDot/demo/14_player_attributes_reference.py rename to FoxDot/demo/en/14_player_attributes_reference.py diff --git a/FoxDot/demo/15_pattern_generator_reference.py b/FoxDot/demo/en/15_pattern_generator_reference.py similarity index 100% rename from FoxDot/demo/15_pattern_generator_reference.py rename to FoxDot/demo/en/15_pattern_generator_reference.py diff --git "a/FoxDot/demo/pt_BR/00_introdu\303\247\303\243o.py" "b/FoxDot/demo/pt_BR/00_introdu\303\247\303\243o.py" new file mode 100644 index 00000000..65bfaa1e --- /dev/null +++ "b/FoxDot/demo/pt_BR/00_introdu\303\247\303\243o.py" @@ -0,0 +1,21 @@ +# Tutorial 0: Introdução + +################ +# Executando código + +# Para executar o código no FoxDot, vá com seu cursor de texto até o 'bloco' de código +# (seção de texto não separada por linhas em branco) e pressione Ctrl+Enter + +# Para executar apenas uma linha ao invés do bloco, pressione Alt+Return + +# Tente isso agora, mova o cursor para a linha de código abaixo e pressione Ctrl+Enter + +print("Hello World") + +############## +# Ajuda + +# Se você esquecer, ou quiser saber mais sobre a função ou classe +# escreva help seguido pelo nome do objeto Python entre parênteses: + +help(object) diff --git a/FoxDot/demo/pt_BR/01_primeiros_sons.py b/FoxDot/demo/pt_BR/01_primeiros_sons.py new file mode 100644 index 00000000..c4614400 --- /dev/null +++ b/FoxDot/demo/pt_BR/01_primeiros_sons.py @@ -0,0 +1,108 @@ +# Tutorial 1: Primeiros Sons + +# No FoxDot, todas as variáveis com dois caracteres são reservadas para os objetos players, por exe,plo, 'p1' +# Criar um objeto Player sem parâmetros tocará uma única nota, C central por padrão, repetidamente até ser parada. +# Use >> para pagar um desse sons para um objeto player, por exemplo: + +p1 >> pluck() + +# Para parar um objeto player individual, simplismente execute + +p1.stop() + +# Além das variáveis de dois caractes que que são pré-reservadas, você pode criar seus +# próprios com um nome de sua escolha + +foo = Player() +foo >> pluck() + +# O >> no Python normalmente é reservada para um tipo de operação, como + ou -, mas isso não é o caso no caso no FoxDot. +# Se um usuário re-executar o código, FoxDot atualizará p1 instantaneamente criando um PlayerObject, +# isso quer dizer que você pode fazer mudanças na sua música usando apenas uma linha de código. + +# Agora se você passar um parâmetro para seu objeto player, você pode mudar a nota que será tocada. +# O primeiro parâmetro deve ser o grau da nota a ser tocada +# (por padrão é a nota mais baixa de 5 oitava da escala maior) e não precisa ser especificado pelo name. + +# Python, como muitas linguagens de programação, usa indexação-zero quando acessado valores em um array, +# isso significa que 0 refere-se a primeira nota da escala. +# Passe para o seu objeto player instruções para fazer música com seu Synth. +# O primeiro parâmetro é a nota a da escala a ser tocada. O seguinte código +# toca as 3 primeiras notas de escala padrão (maio) repetidamente. + +# Uma única nota +p1 >> pluck(0) + +# Or a list of notes +# Ou uma lista de notas +p1 >> pluck([0,1,2]) + +# Mas, você precisa especificar qualquer outra mudança... + +# Como as durações das notas, ou o tamanho de cada nota +p1 >> pluck([0,0,0], dur=[1,2,3]) + +# Ou a amplitude, o "volume" de cada nota +p1 >> pluck([0,0,0], amp=[1,2,3]) + +# Se a segunda lista, o amp, por exemplo, for mais longa, então, a primeira lista (os graus) apenas voltará ao começo, e será pareados com os elementos restantes da segunda lista (a amplitude). +p1 >> pluck([0,2,4], amp=[1,2,3,1,5]) + +# De modo geral, todas as listas são atravedas independente do seu tamanho +p1 >> pluck([0,2,4], dur=[1,2], amp=[1,2,3,1,5]) + +# Os parâmetros podem ser inteiro, ponto flutuante, fração, lista, +# tuplas, ou um misto de todos os anteriores + +p1 >> pluck([0,0,0], dur=2) + +p1 >> pluck([0,0,0], dur=1.743) + +p1 >> pluck([0,0,0], dur=[0.25,0.5,0.75]) + +p1 >> pluck([0,0,0], dur=[1/4,1/2,3/4]) + +p1 >> pluck([0,0,0], dur=[1/4,0.25,3]) + +# Listas de valoers são iteradas enquanto o Player toca as notas +# A seguinte duração é igual a: 1,2,3,1,4,3 +# Se você não entender isso, não se preocupe, isso será abordado com mais detalhes no tutorial sobre Padrões +p1 >> pluck([0,0,0], dur=[1,[2,4],3]) + +# Valores in uma tuplas são usados simultaneamente, por exemplo, p1 tocará 3 notas individuais, então, um acordes de 3 notas tocadas juntas, ao mesmo tempo. +p1 >> pluck([0,2,4,(0,2,4)]) + +# Você pode passar valores para os atributos do objeto player diretamente +p1.oct = 5 + +# Para ver todos os nomes dos atriburos do Player, apenas execute +print(Player.get_attributes()) + +# Um tutorial sobre os atributos do Player irá abordar o assunto com mais detalhes + +# Você também pode armazenar diferentes players e usa-los em lugares diferentes +proxy_1 = pads([0,1,2,3], dur=1/2) +proxy_2 = pads([4,5,6,7], dur=1) + +p1 >> proxy_1 # Primeiro usando o p1 + +p1 >> proxy_2 # Isso troca as instruções do p1 + +# Para tocar varias sequencias juntas, basta fazer a mesma coisa com outro player +# Player object: + +p1 >> pluck([0, 2, 3, 4], dur=1/2) + +p2 >> pads([(0, 2, 4), (3, 5, 7)], dur=8) + +# Toca apenas esse player, muta os outros +p1.solo() # valor padrão é 1 (solo ativo) + +# E então desative o solo +p1.solo(0) + +# Pare (não apenas mute) outros players +p1.only() + +# Use Ctrl+. para limpar tudo que estiver agendado no relógio (parar o som de todos os players) ou execute +Clock.clear() diff --git "a/FoxDot/demo/pt_BR/02_manipula\303\247\303\243o_algor\303\255timica.py" "b/FoxDot/demo/pt_BR/02_manipula\303\247\303\243o_algor\303\255timica.py" new file mode 100644 index 00000000..3b7793c6 --- /dev/null +++ "b/FoxDot/demo/pt_BR/02_manipula\303\247\303\243o_algor\303\255timica.py" @@ -0,0 +1,43 @@ +# Tutorial 2: Manipulação Algorítimica + +# O código a baixo toca as quatro primeiras notas da escala padrão repetidamente: +p1 >> pads([0,1,2,3]) + +# É posível manipular isso, por exemplo, adicionando uma lista de números para o objeto Player +# isso adiciona 2 graus à 4 nota tocada +p1 >> pads([0,1,2,3]) + [0,0,0,2] + +# e isso adiciona 2 graus a cada 3 notas tocadas +p1 >> pads([0,1,2,3]) + [0,0,2] + +# os valores também podem ser entrelaçados ou agrupados +p1 >> pads([0,1,2,3]) + [0,1,[0,(0,2)]] + +# esse comportamente é particularmente útil com o método follow. +b1 >> bass([0,4,5,3], dur=2) +p1 >> pads().follow(b1) + [2,4,7] + +# Você pode agendar ações para os players +# isso dirá ao p1 para inverter as notas a cada 4 batidas +p1 >> pads([0,2,4,6]) +p1.every(4, "reverse") + +# Você pode "encadear" o método junto do player adicionando-o ao final +# da linha original: +p1 >> pads([0,2,4,6]).every(4, "reverse") + +# Para cancelar o "reverse", use o método 'never': + +p1.never("reverse") + +# Aqui estão alguns outros métodos que você usar: + +# Usar "stutter" tocará a mesma nota 'n' vezes com diferentes atributes especificados + +p1.every(4, "stutter", 4, oct=4, pan=[-1,1]) + +# Rotate moverá todos os valores em 1 em ordem +p1.every(4, "rotate") + +# Para mudar a ordem das notas aleatóriamente, use "shuffle" +p1.every(4, "shuffle") diff --git a/FoxDot/demo/pt_BR/03_reproduzindo_samples.py b/FoxDot/demo/pt_BR/03_reproduzindo_samples.py new file mode 100644 index 00000000..1a3cc529 --- /dev/null +++ b/FoxDot/demo/pt_BR/03_reproduzindo_samples.py @@ -0,0 +1,84 @@ +# Tutorial 3: Reproduzindo Samples Embutidos + + +# FoxDot também pode usar uma sequência e manipular samples de áudio. +# Para fazer isso, tudo que o você precisa é usar SynthDef especial: o 'play'. +# O primeiro parâmetro do SynthDef play deve ser uma string de caracteres +# diferente de uma lista de números como você faria com outros SynthDef. +# Cara caractere representa um arquico diferente de áudio, que está armazenado em um buffer no SuperCollider. + +# Para ver a relação do caracter com cada arquivo de áudio, execute +print(Samples) + +# Você pode tocar arquivos de samples nos sub diretórios de FoxDot/snd/ usando o +# Synth 'play' e usand uma string de caracteres ao invés de uma lista de notas. +bd >> play("x") + +# Um caractere refere-se a um som e um espaço vazio (ou qualquer outro caractere que não tem uma sample mapeado) é usado para silencio, então +# você pode espalhar o som pelo tempo +bd >> play("x x x ") + +hh >> play(" -") + +# Você pode entrelaçar padrões usando parênteses +# isso é equivalente a: "x o xo " +d1 >> play("(x )( x)o ") + +# O código a baixo é o mesmo que "-------=" +hh >> play("---(-=)") + +# Colocar caracteres entre colchetes tocará tudo em um espaço de uma batida +# e tocará como um caracter, não simultaneamente, mas, em uma rapida subsequência +d1 >> play("x-o[-o]") + +d1 >> play("x-o[---]") + +d1 >> play("x-o[-----]") + +d1 >> play("x-o[--------------]") + +# e podem ser colocados entre parênteses como se fosse um único caracter. +d1 >> play("x[--]o(=[-o])") + +# Você pode combinar parênteses como desejar: os padrões abaixo são identicos +d1 >> play("x-o(-[-o])") + +d1 >> play("x-o[-(o )]") + +# As chaves selecionam um sample aleatóriamente, se você quiser mais variação +d1 >> play("x-o{-=[--][-o]}") + +# Os colchetes angulares combinam padrões para serem tocados simultaneamente +d1 >> play("<- ><# >") + +d1 >> play("< - >< # >< V>") + +# Cara caracter é mapeado para uma pasta de arquivos se som e você pode selecionar diferentes +# samples usando o parâmetro nomeado "sample" +d1 >> play("(x[--])xu[--]") + +d1 >> play("(x[--])xu[--]", sample=1) + +d1 >> play("(x[--])xu[--]", sample=2) + +# Muda o sample a cada batida +d1 >> play("(x[--])xu[--]", sample=[1,2,3]) + +# Você pode criar duas camadas de padrões juntos - note o "P", veja o tutorial 4 para mais informações. +d1 >> play(P["x-o-"] & P[" **"]) + +# E mude efeitos aplicando-o para todas as camadas de padrões ao mesmo tempo +d1 >> play(P["x-o-"] & P[" **"], room=0.5) + +# Exemplos com samples para o tutorial de players +# Condicionais... +d1 >> play("x[--]xu[--]x", sample=(d1.degree=="x")) + +# Ou mude para o 2 sample multiplicando +d1 >> play("x[--]xu[--]x", sample=(d1.degree=="x")*2) + +# Encadeie multiplas condicionais +d1 >> play("x[--]xu[--]x", sample=(d1.degree=="x")*2 + (d1.degree=="-")*5) + +# Isso é o mesmo que +d1 >> play("x[--]xu[--]x", sample=d1.degree.map({"x":2, "-":5})) diff --git "a/FoxDot/demo/pt_BR/04_usando_padr\303\265es.py" "b/FoxDot/demo/pt_BR/04_usando_padr\303\265es.py" new file mode 100644 index 00000000..dc3502df --- /dev/null +++ "b/FoxDot/demo/pt_BR/04_usando_padr\303\265es.py" @@ -0,0 +1,150 @@ +# Tutorial 4: Usando Padrões + + +# Objetos Player usam listas Python, algo próximo a arrays em outras linguagens, +# para as suas sequências. Você já usou elas anteriormente, mas, elas não são exatamente +# flexiveis para manipular. Por exemplo, tente multiplicar a lista por dois, algo como: + +print([1, 2, 3] * 2) + +# Esse é o resultado que você esperava? + +# FoxDot usa um tipo de container chamado 'Pattern' para ajudar a resolver esse problema. +# Ele atua parecido com uma lista comum, mas, qualquer operação matemática é feita em cada item +# da lista e feito por pares se usado um segundo padrão. Um padrão básico é criado como +# você criaria uma lista ou tupla normal, mas com um 'P' antes. + +print(P[1,2,3] * 2) + +print(P[1,2,3] + 100) + +# Nessa operação, a saida consiste em todas as combinações dos dois padrões, algo como: +# [1+3, 2+4, 3+3, 1+4, 2+3, 3+4] +print(P[1,2,3] + [3,4]) + +# Você pode usar a sintaxe de fatiamento do Python para gerar uma série de números + +print(P[:8]) + +print(P[0,1,2,3:20]) + +print(P[2:15:3]) + +# Tente alguma outra operação matemática e veja qual é o resultado obtido. +print(P[1,2,3] * (1,2)) + +# Objetos Pattern também são automaticamente entrelaçados com qualquer lista aninhada. +# Compare +# Lista normal: +for n in [0,1,2,[3,4],5]: + print(n) + +# com +# Pattern +for n in P[0,1,2,[3,4],5]: + print(n) + +# Use PGroups se você quiser evitar esse comportamento. Isso tanbém pode ser feito +# usando tuplas no Patterns: +for n in P[0,1,2,(3,4)]: + print(n) + +# Isso é um PGroup: +print(P(0,2,4) + 2) + +print(type(P(0,2,4) + 2)) + +# Em Python, você pode gerar um intervalo de inteiro com a sintaxe range(start, stop, step). +# Por padrão, start é 0 e step e 1. +print(list(range(10))) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +# Você pode usar PRange(start, stop, step) para criar um objeto Pattern com os valores equivalentes: +print(PRange(10)) # P[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +# P[0, 2, 2, 6, 4, 10, 6, 14, 8, 18] +# [0*1, 1*2, 2*1, 3*2, 4*1, 5*2, 6*1, 7*2, 8*1...] +print(PRange(10) * [1, 2]) # comportamento da classe Pattern + +# Adicionar uma lista (ou Pattern) a um Pattern irá adicionar os valores dos +# elementos um para o outro, onde listas Python seriam concatenatedas. +print(PRange(10) + [0,10]) + +# Para concatenar Patterns, use o operador pipe, como: +print(PRange(10) | [0,10]) +# FoxDot converte automaticamente qualquer objeto entre o pipe, que envolva um Pattern, em uma classe base Pattern +# então, você não precisa se preocupar em criar em os tipos. + +# Toca todos os valores juntos +p1 >> pluck(P(4,6,8)) +p1 >> pluck(P[0,1,2,P(4,6,8),7,8]) + +# Espalhe os valores entre o "dur", por exemplo, se o dur for 2 batidas, então, irá tocar cada valor em 2/3 batidas +p1 >> pluck(P*(0,2,4), dur=1/2) +p1 >> pluck(P*(0,2,4), dur=1) +p1 >> pluck(P*(0,2,4), dur=2) +p1 >> pluck(P[0,1,2,P*(4,6,8),7,8], dur=1) + +# Isso é o mesmo que P*, mas todas as vezes as notas são reproduzidas e elas são espalhadas pelo valor do dur. +p1 >> pluck(P/(0,2,4), dur=1/2) +p1 >> pluck(P/(0,2,4), dur=1) +p1 >> pluck(P/(0,2,4), dur=2) +p1 >> pluck(P[0,1,2,P/(4,6,8),7,8], dur=1) + +# Espalhe os valores pelo "sus" atual, por exemplo, se o dur for 2 batidas e o sus for 3 batidas, então, será tocado cada valor 1 batida a parte. +p1 >> pluck(P+(0,2,4), dur=2, sus=3) +p1 >> pluck(P+(0,2,4), dur=2, sus=1) +p1 >> pluck(P[0,1,2,P+(4,6,8),7,8], dur=1, sus=3) + +# Espalhe os primeiros (tamanho - 1) valores com um intervalo com o último valor entre cada um +# Toque 0,2,4 com um intervalo de 0.5: +p1 >> pluck(P^(0,2,4,0.5), dur=1/2) + +# Os padrões tem vários métodos para manipular os conteúdos +help(Pattern) + +# Padrão simples +print(P[:8]) + +# Emparalhe o padrão para criar aleatoriedade +print(P[:8].shuffle()) + +# Adicione um padrão invertido ao padrão +print(P[:8].palindrome()) + +# Rode o padrão por n (padrão 1) +print(P[:8].rotate()) +print(P[:8].rotate(3)) +print(P[:8].rotate(-3)) + +# Pegue o padrão e adicione ele quantas vezes precisar até que o números de elementos seja igual ao desejado em um novo padrão +print(P[:8].stretch(12)) +print(P[:8].stretch(20)) + +# Inverta um padrão +print(P[:8].reverse()) + +# Repita o padrão n vezes +print(P[:8].loop(2)) + +# Adiciona um deslocamento somado +print(P[:8].offadd(5)) + +# Adiciona um deslocamento multiplicado +print(P[:8].offmul(5)) + +# Stutter - Repete cada elemento n vezes +print(P[:8].stutter(5)) + +# Amen +# Combina e une o primeiro e os dois últimos itens, de modo que um +# padrão de bateria "x-o-" se tornaria "(x[xo])-o([-o]-)" e imita +# o famoso ritmo "amen break" +d1 >> play(P["x-o-"].amen()) +print(P[:8].amen()) + +# Bubble +# Combina e une o primeiro e os dois últimos itens, de modo que um +# padrão de bateria "x-o-" se tornaria "(x[xo])-o([-o]-)" +d1 >> play(P["x-o-"].bubble()) +print(P[:8].bubble()) + diff --git a/FoxDot/demo/pt_BR/05_atributos_do_player.py b/FoxDot/demo/pt_BR/05_atributos_do_player.py new file mode 100644 index 00000000..fe6d50f3 --- /dev/null +++ b/FoxDot/demo/pt_BR/05_atributos_do_player.py @@ -0,0 +1,48 @@ +# Tutorial 5: Atributos Do Player + +# Você pode definir uma variável fora o player +pitches = P[0,1,2,3,4] +harmony = pitches + 2 + +print(pitches) +print(harmony) + +p1 >> pluck(pitches) +p2 >> star(harmony) + +# Definir a duração diferente para o segundo pode não ter o efeito esperado +p1 >> pluck(pitches) +p2 >> star(harmony, dur=1/2) + +# Mas, é possível que um player toque exatamente como um outro player. +# Para que um player siga outro player, use o método follow: +p1 >> pluck(pitches) + +p2 >> star(dur=1/2).follow(p1) + 2 + +# Você também pode referenciar explicitamente um atributo, como o pitch ou a duração: + +p2 >> star(p1.pitch) + 2 # isso é o mesmo que .follow(p1) + +# Também funciona com outro atributo +p1 >> pluck(pitches) +p2 >> star(dur=p1.dur).follow(p1) + 2 + +# Você pode referenciar e testar o valor atual +# O == retornará 1 se verdadeira e 0 se falso +print(p1.degree) +print(p1.degree == 2) + +# Isso permite que você crie condicionas, como +p1 >> pluck([0,1,2,3], amp=(p1.degree==1)) + +p1 >> pluck([0,1,2,3], amp=(p1.degree>1)) + +# Ou mude para um amp diferente multiplicando por 4 +p1 >> pluck([0,1,2,3], amp=(p1.degree==1)*4) + +# Encadeie multiplas condicionais +p1 >> pluck([0,1,2,3], amp=(p1.degree==1)*4 + (p1.degree==2)*1) + +# Que é o mesmo que +p1 >> pluck([0,1,2,3], amp=p1.degree.map({1:4, 2:1})) diff --git a/FoxDot/demo/pt_BR/06_pausas.py b/FoxDot/demo/pt_BR/06_pausas.py new file mode 100644 index 00000000..5726db8e --- /dev/null +++ b/FoxDot/demo/pt_BR/06_pausas.py @@ -0,0 +1,11 @@ +# Tutorial 6: Pausas + + +# Pausas podem ser adicionadas usando um objeto rest na lista de dur +# As pausas de silêncio da nota que será "tocada". + +# Sem a pausa, 5 notas (sim, dur=1 deve funcionar, mas, deixe-me explicitar um contra ponto no próximo exemplo) +p1 >> pads([0,1,2,3,4], dur=[1,1,1,1,1]) + +# Toque a nota 4 ... com uma pausa, a nota "4" será silenciada por 4 batidas +p1 >> pads([0,1,2,3,4], dur=[1,1,1,1,rest(4)]) diff --git "a/FoxDot/demo/pt_BR/07_rel\303\263gico_b\303\241sico.py" "b/FoxDot/demo/pt_BR/07_rel\303\263gico_b\303\241sico.py" new file mode 100644 index 00000000..8021c96e --- /dev/null +++ "b/FoxDot/demo/pt_BR/07_rel\303\263gico_b\303\241sico.py" @@ -0,0 +1,21 @@ +# Tutorial 7: Relógio Básico + + +# Pare parar o som de todos os player, você pode pressionar Ctrl+. (Segue Ctrl e bata no ponto) +# Que é um atalho de tecla para o comando: +Clock.clear() + +# Mude o tempo (isso tera efeito na próxima barra), o padrão é 120. +Clock.bpm = 144 + +# Para ver o que esta agendado para ser tocado. +print(Clock) + +# Para ver qual é a latência +print(Clock.latency) + +# Alguma vezes você quer saber quando que a próxima X batida do ciclo irá começar. +# Para fazer isso nós podemos usar o método 'mod'. Por exemplo, se nós quisermos ver quando +# é o início da próxima 32 batida, podemos fazer +print(Clock.mod(32)) + diff --git a/FoxDot/demo/pt_BR/08_escalas.py b/FoxDot/demo/pt_BR/08_escalas.py new file mode 100644 index 00000000..50532154 --- /dev/null +++ b/FoxDot/demo/pt_BR/08_escalas.py @@ -0,0 +1,41 @@ +# Tutorial 8: Escalas + + +# Por padrão, os Players usam a escala de C Maior. +# Você pode mudar isso usando os parâmetros nomeados: 'scale' e 'root'. +# Escalas podem ser definidas como uma lista de semitons, por exemplo, a escala Maior é [0,2,4,5,7,9,11] +# ou uma escala pré definida no módulo Scale, por exemplo, Scale.minor. +# Root refere-se a tônica da escala; 0 é igual a C, 1 é C#, 2 é D e assim por diante. + +# A escala padrão pode ser alterada para todos os player que não use uma escala específica. +# Isso é feito usando a sintaxe abaixo (cada linha é tecnicamente equivalente): + +Scale.default.set("major") +Scale.default.set(Scale.major) +Scale.default.set([0,2,4,5,7,9,11]) + +# Ou a mesma coisa, mas menor: +Scale.default.set("minor") +Scale.default.set(Scale.minor) +Scale.default.set([0,2,3,5,7,10]) + +# Para econizar tempo, você também pode fazer +Scale.default = "minor" + +# O mesmo se aplica para o root: +Root.default.set(1) +Root.default.set("C#") + +# Ou: +Root.default.set(2) +Root.default.set("D") + +# Para ver a lista de todas as escala, use +print(Scale.names()) + +# Você pode mudar a escala usada por um player usando o parâmetro 'scale' +p1 >> pads([0,1,2], scale=Scale.minor) + +# Similar a escala, você pode mudar a nota raiz do plaeyr usando o parâmetro 'root' +# porem apenas com números, ao contrário do objeto Root.default que aceita string +p1 >> pads([0,1,2], scale=Scale.minor, root=2) diff --git a/FoxDot/demo/pt_BR/09_grupos.py b/FoxDot/demo/pt_BR/09_grupos.py new file mode 100644 index 00000000..3407a03d --- /dev/null +++ b/FoxDot/demo/pt_BR/09_grupos.py @@ -0,0 +1,69 @@ +# Tutorial 9: Grupos + + +# Os atributos dos players, com degree ou scale, podem ser alterados atribuindo-lhes o valor diretamente, então, isto aqui +p1 >> pads([0,2,4,2], scale=Scale.majorPentatonic) + +# seria equivalente a +p1 >> pads() +p1.degree = [0,2,4,2] +p1.scale = Scale.majorPentatonic + +# Isso é muito útil se você quiser usar o mesmo valor para múltiplos Players simultaneament, por exemlo: +p1 >> pads([0,2,4,2]) +p2 >> pads([2,1,0,4]) +p3 >> pads([2,3]) +p1.dur=p2.dur=p3.dur=[1,1/2,1/4,1/4] + +p1.stop() +p2.stop() +p3.stop() + +# Você também pode referênciar todos os membros que o nome começam com a mesma letra +p_all.dur = [1/2,1/4] # Roda para p1, p2, etc, que estiverem tocando! + +# ou +p_all.amplify = 1 + +# ou... +p_all.stop() + +# ou... +p_all.solo() + +# Para reduzir um pouco a digitação, os players podem ser agrupados juntos, assim, modificar os atributos é bem simple: +p1 >> pads([0,2,4,2]) +p2 >> pads([2,1,0,4]) +p3 >> pads([2,3]) +g1 = Group(p1, p2, p3) +g1.dur=[1,1/2,1/4,1/4] + +# Você também pode agrupas com os grupos _all +g1 = Group(p_all, d_all, b1, b2) + +# Defina um volume por 4 batidas, e depois altera ele por mais 4 +# Isso sobreescreve amplitudes definidas em seus players +g1.amp=var([1,0],4) + +g1.stop() + +# Você pode usar funções para agrupar coisas juntas. Para executar use CTRL+Enter, não ALT+Enter. +def tune(): + b1 >> bass([0,3], dur=4) + p1 >> pluck([0,4], dur=1/2) + d1 >> play("x--x--x-") +tune() + +# Ou agende no relógio a chamada da função agrupadora +def verse(): + b1 >> bass([0,3], dur=4) + p1 >> pluck([0,4], dur=1/2) + d1 >> play("x--x--x-") + Clock.future(16, chorus) +def chorus(): + b1 >> bass([0,4,5,3], dur=4) + p1 >> pluck([0,4,7,9], dur=1/4) + d1 >> play("x-o-") + Clock.future(16, verse) +verse() + diff --git "a/FoxDot/demo/pt_BR/10_usando_vari\303\241veis_dependente_do_tempo.py" "b/FoxDot/demo/pt_BR/10_usando_vari\303\241veis_dependente_do_tempo.py" new file mode 100644 index 00000000..c83392a4 --- /dev/null +++ "b/FoxDot/demo/pt_BR/10_usando_vari\303\241veis_dependente_do_tempo.py" @@ -0,0 +1,143 @@ +# Tutorial 10: Usando Variáveis Dependente Do Tempo + + +# Um TimeVar é uma abreviação para "Time Dependent Variable" (Variável Dependente Do Tempo) e é uma funcionalidade chave para o FoxDot. +# Um TimeVar tem uma série de valores que devem mudar depois de um número de batidas pré definidas +# e isso é criado usando um objeto var com a sintaxe var([lista_de_valores],[lista_de_durações]). + +# Gera os valores: 0,0,0,0,3,3,3,3... +a = var([0,3],4) # Duração pode ser um único valor +print(int(Clock.now()), a) # 'a' inicializa com o valor 0 +# >>> 0 0 # O primeiro valor de ser diferente... + +print(int(Clock.now()), a) # Depois de 4 batidos o valor muda para 3 +# >>> 4 3 + +print(int(Clock.now()), a) # Depois de outras 4 batidas, o valor muda para 0 +# >>> 8 0 + +# Duração também pode ser uma lista +a = var([0,3],[4,2]) +print(int(Clock.now()), a) + +# Quando um TimeVar é usado em uma operação matemática, o valor também se torna um TimeVars +# que muda o estado quando o TimeVar original mudar – isso pode ser feito com padrões também +a = var([0,3], 4) +print(int(Clock.now()), a + 5) # Quando a batida é 0, a é 5 +# >>> 0 5 + +print(int(Clock.now()), a + 5) # Quando a batida é 4, a é 8 +# >>> 4 8 + +b = PRange(4) + a +print(int(Clock.now()), b) # Depois de 8 batidas, o valor muda para 0 +# >>> 8 P[0, 1, 2, 3] + +print(int(Clock.now()), b) # Depois de 12 batidas, o valor muda par 3 +# >>> 12 P[3, 4, 5, 6] + +# Use 'var' com seu Player para criar uma progrssão de acordes. +a = var([0,4,5,3], 4) +b1 >> bass(a, dur=PDur(3,8)) +p1 >> pads(a + (0,2), dur=PDur(7,16)) + +# Você pode adicionar um 'var' a um Player ou um var. +b1 >> bass(a, dur=PDur(3,8)) + var([0,1],[3,1]) + +b = a + var([0,10],8) + +print(int(Clock.now()), (a, b)) + +# Atualizar os valores de um 'var' irá mudar em todos os lugares +a.update([1,4], 8) + +print(int(Clock.now()), (a, b)) + +# Vars podem ser nomeadas ... +var.chords = var([0,4,5,4],4) + +# E usadas depois +b1 >> pluck(var.chords) + +# Qualquer players usando a var nomeda será atualzado +var.chords = var([0,1,5,3],4) + +# Você pode usar um 'linvar' para criar mudanças nos valores gradativamente durante o tempo +# Varie o valor de 0 a 1 durante 16 batidas +c = linvar([0,1],16) + +# Rode isso várias vezes e veja a mudança acontecer +print(int(Clock.now()), c) + +# Varie o amp baseado nesse linvar +p1 >> pads(a, amp=c) + +# um 'Pvar' é um 'var' que pode armazenar padrões (em oposição a dizer, números inteiros) +d = Pvar([P[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], P[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]], 8) + +print(int(Clock.now()), d) + +p1 >> pads(a, amp=c, dur=1/4) + d + +# Mude a escala a cada 16 batidas +Scale.default = Pvar([Scale.major, Scale.minor],16) + +# Você também pode definir um valor para durar para sempre quando for alcançado usando um valor especial chamado "inf" + +x = var([0, 1, 2, 3], [4, 4, 4, inf]) + +print(x) # Manteha pressionado - eventualmente irá para no 3 + +###################### +# Outros tipos de "var" + +# Aqui está uma lista de sub-classes de "var" que retornam valores entre +# os números especificados. Por exemplo, um "linvar" muda gradualmente +# os valores modo linear: + +print(linvar([0,1],8)) # matenha rodando para ver o valor alterar entre 0 e 1 + +# Exemplo: aumente o corte do filtro passa-altas em 32 batidas + +p1 >> play("x-o-", hpf=linvar([0,4000],[32,0])) + +# Outros tipos incluem "sinvar" e "expvar" + +print("Linear:", linvar([0, 1], 8)) +print("Sinusoidal:", sinvar([0, 1], 8)) +print("Exponential:", expvar([0, 1], 8)) + +################# +# Pattern TimeVar + +# As vezes nós queremos armazenar um padrão inteiro em um var, mas +# se tertarmos isso, ele seram entrelaçados automaticamente: + +pattern1 = P[0, 1, 2, 3] +pattern2 = P[4, 5, 6, 7] + +print(var([pattern1, pattern2], 4)) + +# Para armazenar o todo padrão você precisa usar um "Pvar", que não +# entrelaça os valores, mas guarda os padrões em seu lugar + +print(Pvar([pattern1, pattern2], 4)) + +p1 >> pluck(Pvar([pattern1, pattern2], 4), dur=1/4) + + + +########################### +# Compensando o horário de início + +# Um outro truque bem útil é compensar o tempo de início para o var. Por +# padrão isso é feito quando o tempo do relógio é 0 mas você pode especificar um valor +# diferente usando o parâmetro "start" + +print(linvar([0, 1], 8)) +print(linvar([0, 1], 8, start=2)) + +# Isso pode ser combinado com Clock.mod() para iniciar uma rampa no início do +# próximo ciclo de 32 batidas: + +d1 >> play("x-o-", hpf=linvar([0,4000],[32,inf], start=Clock.mod(32))) diff --git a/FoxDot/demo/pt_BR/11_reproduzindo_samples_customizados.py b/FoxDot/demo/pt_BR/11_reproduzindo_samples_customizados.py new file mode 100644 index 00000000..c6cf2f1c --- /dev/null +++ b/FoxDot/demo/pt_BR/11_reproduzindo_samples_customizados.py @@ -0,0 +1,39 @@ +# Tutorial 11: Reproduzindo Samples Customizados + +# Você pode usar seus próprios samples simplismente colocando seus arquivos de áudio dentro do diretório de samples que já existe no FoxDot. +# Ele esta localizado no diretório 'snd' na raiz da instalação do FoxDot +# (por exemplo, 'C:\Python27\Lib\site-packages\FoxDot\snd'). + +# Você viu anterior mente como tocar samples com o play(). Também é possível tocar sample com o loop(). +s1 >> loop('foxdot') + +# Você deve ter notado que isso toca apenas a primeira parte do sample repetidamente. +# Esse comportamento poder ser alterado com muitos dos parâmetros que vimos aé agora para controlar outros synths. dur é um bom lugar pra começar +s1 >> loop('foxdot', dur=4) + +# Se você tiver um diretório de samples que gostaria de usar com FoxDot, você pode chamar loop() com o caminho completo do sample +s1 >> loop('/path/to/samples/quack.wav') + +# Se você passar o caminho de um diretório para o loop, ele irá reproduzir o primeiro sample que encontrar. Você pode mudar o sample que está sendo reproduzido com o parâmetro sample= + +# Toque o primeiro sample da minha coleção +s1 >> loop('/path/to/samples') + +# Toque o segundo sample da minha coleção +s1 >> loop('/path/to/samples', sample=1) + +# Se você for usar muitos sample de um diretório, você pode adiciona-lo aos caminhos usados para buscar os samples. O FoxDot olhará em todos os caminhos para buscar um sample correspondente ao nome. +Samples.addPath('/path/to/samples') +s1 >> loop('quack') + +# Depois de ter um caminho de busca, você pode usar a correspondência de padrões para procurar samples. + +# Toque o 3 sample dentro do diretório 'snare' +s1 >> loop('snare/*', sample=2) + +# Também pode usar * nos nomes dos diretórios +s1 >> loop('*_120bpm/drum*/kick*') + +# ** significa "todos os subdiretórios recursivos". Isso reproduzirá o primeiro sample +# aninhado em 'percussion' (por exemplo, 'percussion/kicks/classic/808.wav') +s1 >> loop('percussion/**/*') diff --git a/FoxDot/demo/pt_BR/12_sintetizadores.py b/FoxDot/demo/pt_BR/12_sintetizadores.py new file mode 100644 index 00000000..750dbdd3 --- /dev/null +++ b/FoxDot/demo/pt_BR/12_sintetizadores.py @@ -0,0 +1,62 @@ +# Tutoral 12: Sintetizadores + + +# O FoxDot cria música dando um 'instrumento digital' para um objeto player +# para tocar, que são chamados de 'SynthDefs'. Você pode ver a lista de 'Synths' +# pré-instalados executando + +print(SynthDefs) + +# Cara um desses representa um *objeto* `SynthDef`. Esses objetos são +# dados ao Players para ser tocado - como dar um instrumento para alguem de sua +# orquestra. + +# Escrevendo suas próprias Definições de Sintetizador + +# Isso é um pouco mais avançado, mas se você já escreveu SynthDefs no +# Supercollider, você se sentirá em casa. Senão, volte para esta esção mais +# tarde. + +# O FoxDot pode acessar qualquer SynthDef armazenado no servidor do SuperCollider, +# mas, você precisa saber que ele está lá. Se você já escreveu um SynthDef +# no SuperCollider e nomeou ele com \mySynth, então, você pode criar uma instância de um +# SynthDef no FoxDot, por exemplo: + +mySynth = SynthDef("mySynth") + +# Usar o mesmo nome para o seu SynthDef no FoxDot e SuperCollider +# é uma boa ideia para evitar confusões. Se você quer escrever (ou editar) o seu +# SynthDef durante o tempo de execução no FoxDot você pode usar uma API SuperCollider +# importando o módulo SCLang. Todos os SynthDef no FoxDot herdam o comportamento +# da classe-base, como, por exemplo, os filtros passa-baixo/alto e vibrato, +# mas isso pode ser sobreescrito ou atualizado fácilmente. Se você quiser saber mais +# about digital sound processing and SynthDef creation, check out the +# veja a documentação do SuperCollider. Abaixo está um exemplo da criação no FoxDot: + +# Importe o módulo para escrever código SCLang no Python +from FoxDot.lib.SCLang import * + +# Crie um SynthDef nomeado como 'example' (usar o mesmo nome para a variáble e para o SynthDef é uma boa ideia) +example = SynthDef("example") + +# Crie o oscilador (osc) usando um sinal de onda +example.osc = SinOsc.ar(ex.freq) + +# E adicione um envelope sonoro percurssivo (env) +example.env = Env.perc() + +# Finalmente, adicione-o! +example.add() + +# Como criar um SynthDef + +with SynthDef("pads") as pads: + pads.osc = SinOsc.ar(pads.freq) + pads.env = Env.perc() + +# É equivalente a + +pads = SynthDef("pads") +pads.osc = SinOsc.ar(pads.freq) +pads.env = Env.perc() +pads.add() diff --git "a/FoxDot/demo/pt_BR/13_rel\303\263gio_avan\303\247ado.py" "b/FoxDot/demo/pt_BR/13_rel\303\263gio_avan\303\247ado.py" new file mode 100644 index 00000000..6db0eecb --- /dev/null +++ "b/FoxDot/demo/pt_BR/13_rel\303\263gio_avan\303\247ado.py" @@ -0,0 +1,50 @@ +# Tutorial 13: Relógio Avançado + +# Para ver o que esta agendado para ser tocado. +print(Clock) + +# Para ver qual é a latência +print(Clock.latency) + +# O relógio pode agendar qualquer objeto que tenha um método __call__, como uma função +# Mas, precisa de um tempo absoluto para agendar a função +# Clock.schedule precisa saber a batida para agendar algo +Clock.schedule() # lanvata TypeError + +# Agende um evento depois de certa duração +# Clock.future precisa saber quantas batidas a frete deve agendar algo +Clock.future() # lavanta TypeError + +# Ambos são equivalentes +Clock.schedule(lambda: print("hello"), Clock.now() + 4) +Clock.future(4, lambda: print("hello")) + +# Para agendar alguma coisa +Clock.schedule(lambda: print("hello ")) + +# Nós podemos chamar algo a cada n batidas +Clock.every(4, lambda: print("hello")) + +# Pega o tempo atual e adiciona 2. Útil para agendamentos. +print(Clock.now() + 2) + +# Agende para a próxima bara +nextBar(Clock.clear) + +# Com um decorador +@nextBar +def change(): + Root.default=4 + Scale.default="minor" + # etc etc + +# Você pode criar suas próprias e decora-las com isto, para poderem ser +# usadas em um .every de um Player +@PlayerMethod +def test(self): + print(self.degree) + +p1 >> pluck([0,4]).every(3, "test") + +# E cancele isso com +p1.never("test") diff --git "a/FoxDot/demo/pt_BR/14_refer\303\252ncia_dos_atributos_do_player.py" "b/FoxDot/demo/pt_BR/14_refer\303\252ncia_dos_atributos_do_player.py" new file mode 100644 index 00000000..63e63ec7 --- /dev/null +++ "b/FoxDot/demo/pt_BR/14_refer\303\252ncia_dos_atributos_do_player.py" @@ -0,0 +1,422 @@ +# Tutorial 14: Referência dos Atributos Do Player +# --- TODO: this needs updating + + +# Para ver todos os atributos: +print(Player.get_attributes()) + +# Você pode ver quais efeitos estão disponíveis executando +print(FxList) + +# Vamos usar o filtro passa-alta como exemplo. Você pode isso descrito +# como: +# "" + +# Cada elemento tem um argumento "principal" e então um parametro filho. Aqui o +# argumento principal é "hpf" (abreviação de high pass filter) e o seu argumento filho +# é "hpr" (abreviação de high pass resonance). O efeito é adicionado apenas quando o +# argumento principal for diferente de zero: +d1 >> dirt([0,4,2,1], dur=1/2, hpf=4000) + +# Isso define o filtro em 4000 Hz,ou seja, apenas as frequências do sinal +# de áudio *acima* disso serão ouvida. Vamos mudar o valor de ressonância. Seu +# valor padrão é 1, então, vamos diminui-lo +d1 >> dirt([0,4,2,1], dur=1/2, hpf=4000, hpr=0.3) + + +# Notou uma diferença? Mós podemos usar padrões/var no nósso efeito para criar +# mudanças temporais: +d1 >> dirt([0,4,2,1], dur=1/2, hpf=linvar([0,4000],8), hpr=P[1,1,0.3].stretch(8)) + + + + +#################### +# Referência +#################### + + + +#################### +# amp - Amplitude (o padrão é 1) +# Define o volume da nota/padrão + +d1 >> play("*", dur=1/2, amp=1) + +# Metade do Volume +d1 >> play("*", dur=1/2, amp=.5) + +# Crie um padrão com amp +d1 >> play("*", dur=1/2, amp=[1,0,1,1,0]) + + + +#################### +# amplify - Muda o amp, multiplando o valor (em vez de sobrescrever) + +# Crie um padrão com amp +d1 >> play("*", dur=1/2, amp=[1,0,1,1,0]) +d1 >> play("*", dur=1/2, amplify=[.5,1,0]) + +# Defnia uma "queda" na música (toca no volume máximo por 28, depois 0 por 4) +p1 >> blip([0,1,2,3], amplify=var([1,0],[28,4])) + + + +#################### +# bend + + + +#################### +# benddelay - Veja bend + + + +#################### +# bits +# A profundidade de bits, em número de bits, à qual o sinal é reduzido; +# deve ser um valor entre 1 e 24, outros valores são ignorados. +# Use crush para definir a quantidade de redução do bitrate (o padrão é 8) + + + +#################### +# bitcrush - Veja bits + + + +#################### +# blur + + + +#################### +# bpf - Filtro Passa-Faixa + + + +#################### +# bpnoise - Veja bpf + + + +#################### +# bpr - Veja bpf + + + +#################### +# bpm + + + +#################### +# buf + + + +#################### +# channel + + + +#################### +# chop +# 'Corta' o sinal em partes usando pulsos de ondes de baixa frequência durante a sustentação da nota. + + + +#################### +# coarse + + + +#################### +# comb delay - Veja echo + + + +#################### +# crush + + + +#################### +# cut +# Fatia a duração +p1 >> pluck(P[:8], dur=1/2, cut=1/8) +p1 >> pluck(P[:8], dur=1/2, cut=1/4) +p1 >> pluck(P[:8], dur=1/2, cut=1/2) + + + +#################### +# cutoff + + + +#################### +# decay - Veja echo + + + +#################### +# degree - Os graus, ou notas, pode ser especificado via parâmetro nomeado (ou o primeiro posicional) +p1 >> blip(degree=[0,1,2,3]) + +# Que é o mesmo que: +p1 >> blip([0,1,2,3]) + +# Toca apenas a nota "raiz" do acorde +b1 >> bass(p1.degree[0]) + + + +#################### +# delay - Uma duração de tempo a ser esperada antes da informação ser enviada ao SuperCollider (o padrão é 0) + +# Atrasa toda terceira nota em .1 +p1 >> blip([0,1,2,3], delay=[0,0,0.1]) + + Atrasa toda terceira nota em .5 +p1 >> blip([0,1,2,3], delay=[0,0,0.5]) + +# Toca a nota para cada delay diferente +p1 >> blip([0,1,2,3], delay=(0,0.1)) + +p1 >> blip([0,1,2,3], delay=(0,0.25)) + +p1 >> blip([0,1,2,3], delay=(0,.1,.2,.3)) + + + +#################### +# dist + + + +#################### +# dur - Durações (o padrão é 1 e 1/2 para o 'play()') + + + +#################### +# echo +# Principal: echo, Filho: decay +# Define o tempo de decaimento para qualquer efeito de eco em batidas, funciona melhor no 'play()' (o padrão é 0) +# Multiplicando pelo valor da sustentação +d1 >> play("x-o-", echo=0.1) + +d1 >> play("x-o-", echo=0.5) + +p1 >> pluck(P[:8], echo=.25) + +p1 >> pluck(P[:8], echo=.5) + +p1 >> pluck(P[:8], echo=.5, decay=.5) + + + +#################### +# env + + + +#################### +# fmod + + + +#################### +# formant + + + +#################### +# freq + + + +#################### +# hpf - Filtro Passa-Alta +# Filtro as fequências abaixo de um valor, removendo baixas frequências + +# 4000 hertz +p1 >> pluck(P[:8], dur=1/2, hpf=4000) + +# HPF é 0 por 4 batidas, então, 4000 por 4 batidas +p1 >> pluck(P[:8], dur=1/2, hpf=var([0,4000],[4,4])) + +# Mude linearmente o hpf de 0 a 4000 por 4 batidas, 4 batidas voltando para 0 +p1 >> pluck(P[:8], dur=1/2, hpf=linvar([0,4000],[4,4])) + +# Mude linearmente o hpf de 0 a 4000 por 8 batidas, então, volte direto para 0 +p1 >> pluck(P[:8], dur=1/2, hpf=linvar([0,4000],[8,0])) + +# Com uma ressonância diferente (o padrão é 1) +p1 >> pluck(P[:8], dur=1/2, hpf=linvar([0,4000],[8,0]), hpr=.5) + +# Com uma ressonância usando um linvar +p1 >> pluck(P[:8], dur=1/2, hpf=linvar([0,4000],[8,0]), hpr=linvar([0.1,1],12)) + + + +#################### +# hpr - Veja hpf + + + +#################### +# lpf - Filtro Passa-Baixa +# Filtro todas as frequências acima de um valor, removendo frequências mais altas + +# 4000 hertz +p1 >> pluck(P[:8], dur=1/2, lpf=400) + +# Com ressonância mudando com um linvar +p1 >> pluck(P[:8], dur=1/2, lpf=linvar([500,4000],[8,0]), lpr=linvar([0.1,1],12)) + + + +#################### +# lpr - Veja lpf + + + +#################### +# midinote + + + +#################### +# pan +# Panorâma, onde -1 é o esquerdo, 1 é o direito (o padrão é 0) + + + +#################### +# pitch - Veja degree + + + +#################### +# pshift + + + +#################### +# oct + + + +#################### +# rate +# Parâmetro usado para alterações diversas em um sinal. Por exemplo, taxa de reprodução do 'play()' (o padrão é 1). + + + +#################### +# room +# Principal: room, Filho: mix (o padrão é 0.1) + +# O parâmetro room especifica o tamanho da sala +d1 >> play("x-o-", room=0.5) + +# Mix é a mistura seca/úmida do reverb ou o quanto o reverb é misturado com a fonte. 1 é todo reverb, 0 é nenhum reverb. (0.1 por padrão) +d1 >> play("x-o-", room=0.5, mix=.5) + + + +#################### +# Reveb +# Veja Room + + + +#################### +# sample +# Parâmetro especial para o 'play()'; seleciona outro arquivo de áudio de um banco de samples de um caracteres. + + + +#################### +# scale + + + +#################### +# shape + + + +#################### +# slide - Deslize para +# Desliza o valor de frequência de um sinal para freq * (slide+1) ao longo da duração de uma nota (o padrão é 0) + +p1 >> pluck(P[:8], dur=1/2, slide=1) + +p1 >> pluck(P[:8], dur=1/2, slide=12) + +p1 >> pluck(P[:8], dur=1/2, slide=var([0,-1],[12,4])) + + + +#################### +# slidedelay + + + +#################### +# slidefrom + + + +#################### +# slider + + + +#################### +# spread + + + +#################### +# spin + + + +#################### +# striate + + + +#################### +# stutter + + + +#################### +# sus - Sustentação (usa o mesmo valor de `dur` padrão) + + + +#################### +# swell + + + +#################### +# vib - Vibrato +# Principal: vib, Filho: vibdepth (o padrão é 0.2) + +p1 >> pluck(P[:8], dur=1/2, vib=12) + +# Com o atributo filho, vibdepth (0.2 por padrão) +p1 >> pluck(P[:8], dur=1/2, vib=12, vibdepth=0.5) + + + +#################### +# vibdepth - Veja vib diff --git "a/FoxDot/demo/pt_BR/15_refer\303\252ncia_dos_geradores_de_padr\303\265es.py" "b/FoxDot/demo/pt_BR/15_refer\303\252ncia_dos_geradores_de_padr\303\265es.py" new file mode 100644 index 00000000..22bee46d --- /dev/null +++ "b/FoxDot/demo/pt_BR/15_refer\303\252ncia_dos_geradores_de_padr\303\265es.py" @@ -0,0 +1,204 @@ +# Tutorial 15: Referência Dos Geradores de Padrões + + +# Existem muitas classes Pattern no FoxDot para ajudar você a gerar lista de números mas também se comporta +# na mesma maneira que um Pattern base. Para ver quais padrões existem e começar a usa-los, execute +print(classes(Patterns.Sequences)) + + + +#################### +# PEuclid +# PEuclid(n, k) +# Retorna o ritmo Euclidiano que espalha 'n' pulsos, quantos possíveis, dentro de 'k' passos. + +# 3 pulsos dentro de 8 passos +print(PEuclid(3, 8)) + + + +#################### +# PDur +# PDur(n, k, start=0, dur=0.25) +# Retorna a atual duração baseada no ritmo Euclidiano (veja PEuclid) onde dur é o tamanho de cada passo. +# Espalhe 'n' pulsos dentro de 'k' passos, quantos forem possíveis + +print(PDur(3,8)) # P[0.75, 0.75, 0.5] + +print(PDur(5,8)) + +# Dado uma lista de 3 durações, adiciona outrao com lista com 5 durações +print(PDur([3,5],8)) + +d1 >> play("x", dur=PDur(5,8)) + + + +#################### +# PIndex +# Retorna o index acessado + +print(PIndex()) +print(PIndex()*4) + + + +#################### +# PSine +# PSine(n=16) +# Retorna valores de um ciclo de onda senoidal dividida em 'n' partes + +# Divide em 5 partes +print(PSine(5)) + +# Divide em 10 +print(PSine(10)) + + + +#################### +# PTri +# PTri(start, stop=None, step=None) +# Retorna um Pattern equivalente à `Pattern(range(start, stop, step))` com sua forma invertida adicionada. +# Pense nisso com um "Tri"ângulo. + +# Suba até 5 então desça até 1 +print(PTri(5)) + +# Suba até 8 então desça até 1 +print(PTri(8)) + +# Suba de 3 a 10 e então desça até 4 +print(PTri(3,10)) + +# Suba de 3 até 30, de 2 em 2, então desça até 4 +print(PTri(3,20,2)) + +# Suba até 4, então desça até 1, depois suba até 8, e depois desça até 1 +print(PTri([4,8])) + +p1 >> pluck(PTri(5), scale=Scale.default.pentatonic) + +# A mesma coisa que +p1 >> pluck(PRange(5) | PRange(5,0,-1), scale=Scale.default.pentatonic) + + + +#################### +# PRand +# PRand(start, stop=None) +# Retorna um inteiro aleatório entre start e stop. + +# Retorna um inteiro aleatório entre 0 e start. +print(PRand(8)[:5]) + +# Retorna um inteiro aleatórios entre start e stop. +print(PRand(8,16)[:5]) + +# Se start for um tipo de container retornará um item aleatório deste container. +print(PRand([1,2,3])[:5]) + +# Você pode passar uma semete +print(PRand([1,2,3], seed=5)[:5]) + +# Gere uma melodia aleatória +p1 >> pluck(PRand(8)) + +# Cria uma lista aleatória e itere pelos mesmos valores +p1 >> pluck(PRand(8)[:3]) + + + +#################### +# PRhythm +# PRhythm recebe uma lista de durações únicas e tuplas com valores que podem ser fornecida ao `PDur` + +# O seguinte toca o hi hat com um ritmo Euclidiano com 3 pulsos em 8 passos +d1 >> play("x-o-", dur=PRhythm([2,(3,8)])) + +print(PRhythm([2, (3,8)])) + + + +#################### +# PSum +# PSum(n, total) +# Retorna um Pattern com tamaho 'n' onde cada elemento representa uma parte na soma do 'total' + +# Retorna uma padrão com tamanho igual 3, onde cada elemento somado é igual a 8 +print(PSum(3,8)) + +# Retorna um padrão com o tamanho igual 5, onde cada elemento somando é igual a 4 +print(PSum(5,4)) + + + +#################### +# PStep +# PStep(n, value, default=0) +# Retorna um Pattern onde cara n-termos é 'value' e o resto é o 'default' + +# A cada 4, torne o valor igual 1, os outros elementos vão ser 0 por padrão +print(PStep(4,1)) + +# A cada 8, use 6, o resto será 4 +print(PStep(8,6,4)) + +# A cada 5, use 2, senão, 1 +print(PStep(5,2,1)) + + + +#################### +# PWalk +# PWalk(max=7, step=1, start=0) + +# Por padrão , retorna um Pattern com elemento aleatoriamente 1 acima ou abaixo do anterior +print(PWalk()[:16]) + +# Mudando o intervalo +print(PWalk(step=2)[:16]) + +# Com um valor máximo +print(PWalk(max=2)[:16]) + +# Começe com um número diferente de 0 +print(PWalk(start=6)[:16]) + + + +#################### +# PWhite +# PWhite(lo=0, hi=1) +# Retorna valores aleatórios de ponto flutuante entre 'lo' e 'hi' + +# 'lo' por padrão é 0, e 'hi' é 1 +print(PWhite()[:8]) + +# Retorna números aleatórios entre 1 e 5 +print(PWhite(1,5)[:8]) + + + +#################### +# Geradores de Padrões Customizados + +# Geradores de Pattern customizados podem ser criados usando a subclasse GeneratorPattern +# e sobrescrevendo `GeneratorPattern.func` + +class CustomGeneratorPattern(GeneratorPattern): + def func(self, index): + return int(index / 4) + +print(CustomGeneratorPattern()[:10]) + +# Isso pode ser feito de modo conciso usando `GeneratorPattern.from_func`, +# passando uma função que recebe um index e retorna algum item para o padrão. + +def some_func(index): + return int(index / 4) + +print(GeneratorPattern.from_func(some_func)[:10]) + +# Podemos usar lambdas também +print(GeneratorPattern.from_func(lambda index: int(index / 4))[:10]) diff --git a/FoxDot/lib/Settings/__init__.py b/FoxDot/lib/Settings/__init__.py index 19ceff96..1a400fad 100644 --- a/FoxDot/lib/Settings/__init__.py +++ b/FoxDot/lib/Settings/__init__.py @@ -1,5 +1,7 @@ from __future__ import absolute_import, division, print_function +import ctypes +import locale import os import sys @@ -55,6 +57,7 @@ FOXDOT_STARTUP_PATH = os.path.realpath(FOXDOT_ROOT + "/lib/Custom/startup.py") FOXDOT_SND = os.path.realpath(FOXDOT_ROOT + "/snd/") FOXDOT_LOOP = os.path.realpath(FOXDOT_ROOT + "/snd/_loop_/") +FOXDOT_LOCALE_DIR = os.path.realpath(FOXDOT_ROOT + "/locale") SCLANG_EXEC = 'sclang.exe' if SYSTEM == WINDOWS else 'sclang' SYNTHDEF_DIR = os.path.realpath(FOXDOT_ROOT + "/osc/scsyndef/") @@ -80,6 +83,16 @@ except FileNotFoundError: pass +def GET_LANG(default='en'): + if SYSTEM == WINDOWS: # TODO: need testing in windows + try: + lang = locale.windows_locale.get(ctypes.windll.kernel32.GetUserDefaultLCID()) or default + except: + return default + else: + lang, encode = locale.getlocale() + return lang + def GET_SYNTHDEF_FILES(): return [os.path.realpath(SYNTHDEF_DIR + "/" + path) for path in os.listdir(SYNTHDEF_DIR)] @@ -87,7 +100,17 @@ def GET_FX_FILES(): return [os.path.realpath(EFFECTS_DIR + "/" + path) for path in os.listdir(EFFECTS_DIR)] def GET_TUTORIAL_FILES(): - return [os.path.realpath(TUTORIAL_DIR + "/" + path) for path in sorted(os.listdir(TUTORIAL_DIR))] + lang = GET_LANG() + tutorial_dir = os.path.join(TUTORIAL_DIR, lang) + default_tutorial_dir = os.path.join(TUTORIAL_DIR, 'en') + if '_' in lang and not os.path.exists(tutorial_dir): + lang = lang.split('_')[0] + tutorial_dir = os.path.join(TUTORIAL_DIR, lang) + if not os.path.exists(tutorial_dir): + tutorial_dir = default_tutorial_dir + elif not os.path.exists(tutorial_dir): + tutorial_dir = default_tutorial_dir + return [os.path.realpath(tutorial_dir + "/" + path) for path in sorted(os.listdir(tutorial_dir))] # Set Environment Variables diff --git a/FoxDot/lib/Translation.py b/FoxDot/lib/Translation.py new file mode 100644 index 00000000..ef318def --- /dev/null +++ b/FoxDot/lib/Translation.py @@ -0,0 +1,30 @@ +"""Translation (t9n) module. + +Examples +-------- +Create .pot file Portable Object Template: + $ xgettext --from-code=UTF-8 -o FoxDot.pot -k'_' -l python FoxDot/lib/Workspace/*.py # extract new phrases + +Add new locale: + $ FOXDOT_LOCALE='pt_BR' # 'en_GB', 'es_CO' or just 'ru', 'fr' + $ msginit -i FoxDot.pot -o FoxDot/locale/$FOXDOT_LOCALE/LC_MESSAGES/FoxDot.po --locale $FOXDOT_LOCALE + +Add new phrases to existing locale files: + $ msgmerge -U FoxDot/locale/$FOXDOT_LOCALE/LC_MESSAGES/FoxDot.po FoxDot.pot + +Create/Update .mo file: + $ msgfmt -o FoxDot/locale/$FOXDOT_LOCALE/LC_MESSAGES/FoxDot.mo FoxDot/locale/$FOXDOT_LOCALE/LC_MESSAGES/FoxDot.po + +Stating a new demo translation: + $ cp -r FoxDot/demo/en/ FoxDot/demo/$FOXDOT_LOCALE/ + +You can translate the file name, as it will be used in the tutorial menu, just be careful to keep the pattern {num}_{name}.py, for example: + $ mv FoxDot/demo/$FOXDOT_LOCALE/00_intro.py FoxDot/demo/$FOXDOT_LOCALE/00_introdução.py +""" +from gettext import translation + +from .Settings import FOXDOT_LOCALE_DIR, GET_LANG + +t = translation('FoxDot', FOXDOT_LOCALE_DIR, [GET_LANG()], fallback=True) +# t.install() +_ = t.gettext diff --git a/FoxDot/lib/Workspace/ConfigFile.py b/FoxDot/lib/Workspace/ConfigFile.py index 7a098352..def4c039 100644 --- a/FoxDot/lib/Workspace/ConfigFile.py +++ b/FoxDot/lib/Workspace/ConfigFile.py @@ -3,6 +3,7 @@ from .tkimport import * from ..Settings import FOXDOT_ICON, FOXDOT_ICON_GIF +from ..Translation import _ try: import tkMessageBox @@ -37,10 +38,10 @@ def __init__(self, path): self.textbox.grid(row=0, column=0, columnspan=2) self.y_scroll.config(command=self.textbox.yview) - self.exit = Button(self.root, text="Cancel", command=self.save_and_close) + self.exit = Button(self.root, text=_("Cancel"), command=self.save_and_close) self.exit.grid(row=1, column=0, stick=N+S+E+W) - self.save = Button(self.root, text="Save Changes", command=self.save_changes) + self.save = Button(self.root, text=_("Save Changes"), command=self.save_changes) self.save.grid(row=1, column=1, sticky=N+S+E+W, columnspan=2) self.unsaved = True @@ -61,7 +62,7 @@ def start(self): def save_and_close(self, event=None): """ Asks the user if they want to save changes """ if self.get_text() != self.text: - answer = tkMessageBox.askyesno("Save changes", "Do you want to save your changes?") + answer = tkMessageBox.askyesno(_("Save changes"), _("Do you want to save your changes?")) if answer: return self.save_changes() return self.root.destroy() @@ -75,6 +76,6 @@ def save_changes(self): f.write(text) f.close() self.root.destroy() - tkMessageBox.showwarning(title="Just a heads up", message="A restart of FoxDot is required for the changes to take effect") + tkMessageBox.showwarning(title=_("Just a heads up"), message=_("A restart of FoxDot is required for the changes to take effect")) return diff --git a/FoxDot/lib/Workspace/Editor.py b/FoxDot/lib/Workspace/Editor.py index c6e2a65a..ddd71411 100644 --- a/FoxDot/lib/Workspace/Editor.py +++ b/FoxDot/lib/Workspace/Editor.py @@ -42,6 +42,7 @@ from ..Settings import MENU_ON_STARTUP, TRANSPARENT_ON_STARTUP, RECOVER_WORK, CHECK_FOR_UPDATE from ..Settings import PY_VERSION from ..ServerManager import TempoServer +from ..Translation import _ # App object @@ -66,11 +67,11 @@ def check_versions(): if pypi_version is not None and Version(pypi_version) > Version(this_version): tkMessageBox.showinfo( - "New version available", - "There is a new version of FoxDot available from PyPI. Upgrade by going to your command prompt " - "and running:\n\npip install FoxDot --upgrade" - ) + _("New version available"), + _("""There is a new version of FoxDot available from PyPI. Upgrade by going to your command prompt and running: +pip install FoxDot --upgrade""") + ) return # Used for docstring prompt @@ -360,7 +361,7 @@ def hello(): # print(hello) # print() - hello = "Welcome to FoxDot! Press {}+{} for help.".format(ctrl, self.help_key) + hello = _("Welcome to FoxDot! Press {ctrl}+{help_key} for help.").format(ctrl=ctrl, help_key=self.help_key) print(hello) print("-" * len(hello)) @@ -380,7 +381,7 @@ def recover_work(): if len(text): - loading = tkMessageBox.askyesno("Load unsaved work?", "Your code wasn't saved last time you used FoxDot, do you want to load any unsaved work?") + loading = tkMessageBox.askyesno(_("Load unsaved work?"), _("Your code wasn't saved last time you used FoxDot, do you want to load any unsaved work?")) self.root.update() @@ -413,8 +414,8 @@ def recover_work(): self.transparent.set(True) self.root.after(100, self.toggle_transparency) - def set_window_title(self, text="Live Coding with Python and SuperCollider"): - return self.root.title("FoxDot v{} - {}".format(self.version, text)) + def set_window_title(self, text=_("Live Coding with Python and SuperCollider")): + return self.root.title(_("FoxDot v{version} - {title}").format(version=self.version, title=text)) def run(self): """ Starts the Tk mainloop for the master widget """ @@ -642,26 +643,27 @@ def help(self, event=None): else: ctrl = "Ctrl" - print("FoxDot Help:") - print("-----------------------------------------") - print("{}+Return : Execute code".format(ctrl)) - print("{}+. : Stop all sound".format(ctrl)) - print("{}+= : Increase font size".format(ctrl)) - print("{}+- : Decrease font size".format(ctrl)) - print("{}+L : Insert lambda symbol".format(ctrl)) - print("{}+T : Insert tilde symbol".format(ctrl)) - print("{}+S : Save your work".format(ctrl)) - print("{}+O : Open a file".format(ctrl)) - print("{}+M : Toggle the menu".format(ctrl)) - print("{}+{} : Toggle console window".format(ctrl, self.toggle_key)) - print("print(SynthDefs) : View available SynthDefs") - print("print(Samples) : View character-to-sample mapping") - print("print(FxList) : View audio effects") - print("print(Attributes) : View Player attributes") - print("print(PatternMethods) : View Pattern methods") - print("---------------------------------------------------") - print("Please visit foxdot.org for more information") - print("---------------------------------------------------") + help_text = _("""FoxDot Help: +----------------------------------------- +{ctrl}+Return : Execute code +{ctrl}+. : Stop all sound +{ctrl}+= : Increase font size +{ctrl}+- : Decrease font size +{ctrl}+L : Insert lambda symbol +{ctrl}+T : Insert tilde symbol +{ctrl}+S : Save your work +{ctrl}+O : Open a file +{ctrl}+M : Toggle the menu +{ctrl}+{toggle_key} : Toggle console window +print(SynthDefs) : View available SynthDefs +print(Samples) : View character-to-sample mapping +print(FxList) : View audio effects +print(Attributes) : View Player attributes +print(PatternMethods) : View Pattern methods +--------------------------------------------------- +Please visit foxdot.org for more information +---------------------------------------------------""") + print(help_text.format(ctrl=ctrl, toggle_key=self.toggle_key)) return "break" # Save the current text: Ctrl+s @@ -672,7 +674,7 @@ def save(self, event=None): text = self.text.get("0.0",END) if not self.saved: - self.filename = tkFileDialog.asksaveasfilename(filetypes=[("Python files", ".py")], + self.filename = tkFileDialog.asksaveasfilename(filetypes=[(_("Python files"), ".py")], defaultextension=".py") if self.filename: @@ -680,7 +682,7 @@ def save(self, event=None): self.saved = True - print("Saved '{}'".format(self.filename)) + print(_("Saved '{filename}'").format(filename=self.filename)) # Remove tmp file self.clear_temp_file() @@ -691,7 +693,7 @@ def save(self, event=None): def saveAs(self,event=None): text = self.text.get("0.0",END) - self.filename = tkFileDialog.asksaveasfilename(filetypes=[("Python files", ".py")], + self.filename = tkFileDialog.asksaveasfilename(filetypes=[(_("Python files"), ".py")], defaultextension=".py") if self.filename is not None: @@ -699,7 +701,7 @@ def saveAs(self,event=None): self.saved = True - print("Save successful!") + print(_("Save successful!")) # Remove tmp file @@ -727,14 +729,14 @@ def loadfile(self, path): else: f = open(path, encoding="utf8") except Exception as e: - return print("{} error occurred when loading file:\n - '{}'".format(e.__class__.__name__, path)) + return print(_("{} error occurred when loading file:\n - '{}'").format(e.__class__.__name__, path)) self.set_all(f.read()) f.close() return def newfile(self, event=None): ''' Clears the document and asks if the user wants to save ''' - answer = tkMessageBox.askyesnocancel("New file", "Save your work before creating a new document?") + answer = tkMessageBox.askyesnocancel(_("New file"), _("Save your work before creating a new document?")) if answer is not None: if answer is True: if not self.save(): @@ -746,7 +748,7 @@ def newfile(self, event=None): return "break" def export_console(self): - fn = tkFileDialog.asksaveasfilename(filetypes=[("Plain Text File", ".txt")], + fn = tkFileDialog.asksaveasfilename(filetypes=[(_("Plain Text File"), ".txt")], defaultextension='.txt') with open(fn, 'w') as f: f.write(self.console.read()) @@ -770,7 +772,7 @@ def open_samples_folder(self): subprocess.Popen([cmd, FOXDOT_SND]) except OSError as e: print(e) - print("Hmm... Looks like we couldn't open the directory but you can find the samples in {}".format(FOXDOT_SND)) + print(_("Hmm... Looks like we couldn't open the directory but you can find the samples in {}").format(FOXDOT_SND)) return @@ -803,7 +805,7 @@ def toggle_sc3_plugins(self, event=None): else: f.write(line) # Pop-up to tell the user a restart is required - tkMessageBox.showwarning(title="Just a heads up", message="Restart of FoxDot is required for the changes to take effect") + tkMessageBox.showwarning(title=_("Just a heads up"), message=_("Restart of FoxDot is required for the changes to take effect")) return "break" def toggle_transparency(self, event=None): @@ -1811,10 +1813,10 @@ def allow_connections(self, **kwargs): Clock = self.namespace["_Clock"] if self.listening_for_connections.get() == True: Clock.start_tempo_server(TempoServer, **kwargs) - print("Listening for connections on {}".format(Clock.tempo_server)) + print(_("Listening for connections on {server}").format(server=Clock.tempo_server)) else: Clock.kill_tempo_server() - print("Closed connections") + print(_("Closed connections")) return def show_popup(self, *args): diff --git a/FoxDot/lib/Workspace/MenuBar.py b/FoxDot/lib/Workspace/MenuBar.py index e70db896..ce9f1d0b 100644 --- a/FoxDot/lib/Workspace/MenuBar.py +++ b/FoxDot/lib/Workspace/MenuBar.py @@ -6,6 +6,7 @@ from functools import partial from ..Settings import * from ..Code import FoxDotCode +from ..Translation import _ # Code menu @@ -32,72 +33,72 @@ def __init__(self, master, visible=True): # File menu filemenu = Menu(self, tearoff=0) - filemenu.add_command(label="New Document", command=self.root.newfile, accelerator="Ctrl+N") - filemenu.add_command(label="Open", command=self.root.openfile, accelerator="Ctrl+O") - filemenu.add_command(label="Save", command=self.root.save, accelerator="Ctrl+S") - filemenu.add_command(label="Save As...", command=self.root.saveAs ) - self.add_cascade(label="File", menu=filemenu) + filemenu.add_command(label=_("New Document"), command=self.root.newfile, accelerator="Ctrl+N") + filemenu.add_command(label=_("Open"), command=self.root.openfile, accelerator="Ctrl+O") + filemenu.add_command(label=_("Save"), command=self.root.save, accelerator="Ctrl+S") + filemenu.add_command(label=_("Save As..."), command=self.root.saveAs ) + self.add_cascade(label=_("File"), menu=filemenu) # Edit menu editmenu = Menu(self, tearoff=0) - editmenu.add_command(label="Undo", command=self.root.undo, accelerator="Ctrl+Z") - editmenu.add_command(label="Redo", command=self.root.redo, accelerator="Ctrl+Y") + editmenu.add_command(label=_("Undo"), command=self.root.undo, accelerator="Ctrl+Z") + editmenu.add_command(label=_("Redo"), command=self.root.redo, accelerator="Ctrl+Y") editmenu.add_separator() - editmenu.add_command(label="Cut", command=self.root.edit_cut, accelerator="Ctrl+X") - editmenu.add_command(label="Copy", command=self.root.edit_copy, accelerator="Ctrl+C") - editmenu.add_command(label="Paste", command=self.root.edit_paste, accelerator="Ctrl+V") - editmenu.add_command(label="Select All", command=self.root.select_all, accelerator="Ctrl+A") + editmenu.add_command(label=_("Cut"), command=self.root.edit_cut, accelerator="Ctrl+X") + editmenu.add_command(label=_("Copy"), command=self.root.edit_copy, accelerator="Ctrl+C") + editmenu.add_command(label=_("Paste"), command=self.root.edit_paste, accelerator="Ctrl+V") + editmenu.add_command(label=_("Select All"), command=self.root.select_all, accelerator="Ctrl+A") editmenu.add_separator() - editmenu.add_command(label="Increase Font Size", command=self.root.zoom_in, accelerator="Ctrl+=") - editmenu.add_command(label="Decrease Font Size", command=self.root.zoom_out, accelerator="Ctrl+-") + editmenu.add_command(label=_("Increase Font Size"), command=self.root.zoom_in, accelerator="Ctrl+=") + editmenu.add_command(label=_("Decrease Font Size"), command=self.root.zoom_out, accelerator="Ctrl+-") editmenu.add_separator() - editmenu.add_command(label="Clear Console", command=self.root.clear_console) - editmenu.add_command(label="Export Console Log", command=self.root.export_console) - editmenu.add_command(label="Toggle Console", command=self.root.toggle_console) + editmenu.add_command(label=_("Clear Console"), command=self.root.clear_console) + editmenu.add_command(label=_("Export Console Log"), command=self.root.export_console) + editmenu.add_command(label=_("Toggle Console"), command=self.root.toggle_console) editmenu.add_separator() - editmenu.add_checkbutton(label="Toggle Fullscreen", command=(lambda: self.root.toggle_true_fullscreen(zoom=True)), variable=self.root.true_fullscreen_toggled) - editmenu.add_command(label="Toggle Menu", command=self.root.toggle_menu, accelerator="Ctrl+M") - editmenu.add_checkbutton(label="Toggle Window Transparency", command=self.root.toggle_transparency, variable=self.root.transparent) - editmenu.add_checkbutton(label="Toggle Auto-fill Prompt", command=self.root.toggle_prompt, variable=self.root.show_prompt) - editmenu.add_checkbutton(label="Toggle Beat Counter", command=self.root.toggle_counter, variable=self.root.show_counter) - self.add_cascade(label="Edit", menu=editmenu) + editmenu.add_checkbutton(label=_("Toggle Fullscreen"), command=(lambda: self.root.toggle_true_fullscreen(zoom=True)), variable=self.root.true_fullscreen_toggled) + editmenu.add_command(label=_("Toggle Menu"), command=self.root.toggle_menu, accelerator="Ctrl+M") + editmenu.add_checkbutton(label=_("Toggle Window Transparency"), command=self.root.toggle_transparency, variable=self.root.transparent) + editmenu.add_checkbutton(label=_("Toggle Auto-fill Prompt"), command=self.root.toggle_prompt, variable=self.root.show_prompt) + editmenu.add_checkbutton(label=_("Toggle Beat Counter"), command=self.root.toggle_counter, variable=self.root.show_counter) + self.add_cascade(label=_("Edit"), menu=editmenu) # Note: Alt renders properly to look like Option, so we don't need a # conditional for those shortcuts codemenu = Menu(self, tearoff=0) - codemenu.add_command(label="Evaluate Block", command=self.root.exec_block, accelerator="{}+Return".format(ctrl)) - codemenu.add_command(label="Evaluate Line", command=self.root.exec_line, accelerator="Alt+Return") - codemenu.add_command(label="Clear Scheduling Clock", command=self.root.killall, accelerator="{}+.".format(ctrl)) + codemenu.add_command(label=_("Evaluate Block"), command=self.root.exec_block, accelerator="{}+Return".format(ctrl)) + codemenu.add_command(label=_("Evaluate Line"), command=self.root.exec_line, accelerator="Alt+Return") + codemenu.add_command(label=_("Clear Scheduling Clock"), command=self.root.killall, accelerator="{}+.".format(ctrl)) codemenu.add_separator() - codemenu.add_checkbutton(label="Use SC3 Plugins", command=self.root.toggle_sc3_plugins, variable=self.sc3_plugins) + codemenu.add_checkbutton(label=_("Use SC3 Plugins"), command=self.root.toggle_sc3_plugins, variable=self.sc3_plugins) codemenu.add_separator() - codemenu.add_checkbutton(label="Listen for connections", command=self.root.allow_connections, variable=self.root.listening_for_connections) - self.add_cascade(label="Language", menu=codemenu) + codemenu.add_checkbutton(label=_("Listen for connections"), command=self.root.allow_connections, variable=self.root.listening_for_connections) + self.add_cascade(label=_("Language"), menu=codemenu) # Help helpmenu = Menu(self, tearoff=0) - helpmenu.add_command(label="Display help message", comman=self.root.help, accelerator="{}+{}".format(ctrl, self.root.help_key)) - helpmenu.add_command(label="Visit FoxDot Homepage", command=self.root.openhomepage) - helpmenu.add_command(label="Documentation", command=self.root.opendocumentation) + helpmenu.add_command(label=_("Display help message"), comman=self.root.help, accelerator="{}+{}".format(ctrl, self.root.help_key)) + helpmenu.add_command(label=_("Visit FoxDot Homepage"), command=self.root.openhomepage) + helpmenu.add_command(label=_("Documentation"), command=self.root.opendocumentation) helpmenu.add_separator() cpu_menu=Menu(self, tearoff=0) - cpu_menu.add_radiobutton(label="Low", variable=self.cpu_usage, value=0, command=self.set_cpu_usage) - cpu_menu.add_radiobutton(label="Medium", variable=self.cpu_usage, value=1, command=self.set_cpu_usage) - cpu_menu.add_radiobutton(label="High", variable=self.cpu_usage, value=2, command=self.set_cpu_usage) - helpmenu.add_cascade(label="CPU Usage", menu=cpu_menu) + cpu_menu.add_radiobutton(label=_("Low"), variable=self.cpu_usage, value=0, command=self.set_cpu_usage) + cpu_menu.add_radiobutton(label=("Medium"), variable=self.cpu_usage, value=1, command=self.set_cpu_usage) + cpu_menu.add_radiobutton(label=_("High"), variable=self.cpu_usage, value=2, command=self.set_cpu_usage) + helpmenu.add_cascade(label=_("CPU Usage"), menu=cpu_menu) lat_menu=Menu(self, tearoff=0) - lat_menu.add_radiobutton(label="Low", variable=self.latency, value=0, command=self.set_latency) - lat_menu.add_radiobutton(label="Medium", variable=self.latency, value=1, command=self.set_latency) - lat_menu.add_radiobutton(label="High", variable=self.latency, value=2, command=self.set_latency) - helpmenu.add_cascade(label="Clock Latency", menu=lat_menu) + lat_menu.add_radiobutton(label=_("Low"), variable=self.latency, value=0, command=self.set_latency) + lat_menu.add_radiobutton(label=_("Medium"), variable=self.latency, value=1, command=self.set_latency) + lat_menu.add_radiobutton(label=_("High"), variable=self.latency, value=2, command=self.set_latency) + helpmenu.add_cascade(label=_("Clock Latency"), menu=lat_menu) helpmenu.add_separator() - helpmenu.add_command(label="Open Samples Folder", command=self.root.open_samples_folder) - helpmenu.add_command(label="Open config file (advanced)", command=self.root.open_config_file) - self.add_cascade(label="Help & Settings", menu=helpmenu) + helpmenu.add_command(label=_("Open Samples Folder"), command=self.root.open_samples_folder) + helpmenu.add_command(label=_("Open config file (advanced)"), command=self.root.open_config_file) + self.add_cascade(label=_("Help & Settings"), menu=helpmenu) # Tutorials @@ -116,9 +117,9 @@ def __init__(self, master, visible=True): num = data[0] name = " ".join(data[1:]).title() - tutorialmenu.add_command(label="Load Tutorial {}: {}".format(num, name), command=partial(self.root.loadfile, tutorial)) + tutorialmenu.add_command(label=_("Load Tutorial {num}: {name}").format(num=num, name=name), command=partial(self.root.loadfile, tutorial)) - self.add_cascade(label="Tutorials", menu=tutorialmenu) + self.add_cascade(label=_("Tutorials"), menu=tutorialmenu) # Add to root @@ -139,11 +140,11 @@ def allow_connections(self, **kwargs): if self.listening_for_connections.get() == True: Clock = self.root.namespace["Clock"] Clock.start_tempo_server(TempoServer, **kwargs) - print("Listening for connections on {}".format(Clock.tempo_server)) + print(_("Listening for connections on {server}").format(server=Clock.tempo_server)) else: Clock = self.root.namespace["Clock"] Clock.kill_tempo_server() - print("Closed connections") + print(_("Closed connections")) return def start_listening(self, **kwargs): @@ -168,14 +169,14 @@ class PopupMenu(Menu): def __init__(self, master, **kwargs): self.root = master Menu.__init__(self, master.root, tearoff=0) - self.add_command(label="Undo", command=self.root.undo, accelerator="{}+Z".format(ctrl)) - self.add_command(label="Redo", command=self.root.redo, accelerator="{}+Y".format(ctrl)) + self.add_command(label=_("Undo"), command=self.root.undo, accelerator="{}+Z".format(ctrl)) + self.add_command(label=_("Redo"), command=self.root.redo, accelerator="{}+Y".format(ctrl)) self.add_separator() - self.add_command(label="Copy", command=self.root.edit_copy, accelerator="{}+C".format(ctrl)) - self.add_command(label="Cut", command=self.root.edit_cut, accelerator="{}+X".format(ctrl)) - self.add_command(label="Paste", command=self.root.edit_paste, accelerator="{}+V".format(ctrl)) + self.add_command(label=_("Copy"), command=self.root.edit_copy, accelerator="{}+C".format(ctrl)) + self.add_command(label=_("Cut"), command=self.root.edit_cut, accelerator="{}+X".format(ctrl)) + self.add_command(label=_("Paste"), command=self.root.edit_paste, accelerator="{}+V".format(ctrl)) self.add_separator() - self.add_command(label="Select All", command=self.root.select_all, accelerator="{}+A".format(ctrl)) + self.add_command(label=_("Select All"), command=self.root.select_all, accelerator="{}+A".format(ctrl)) self.bind("", self.hide) # hide when clicked off @@ -195,14 +196,14 @@ class ConsolePopupMenu(Menu): def __init__(self, master, **kwargs): self.root = master Menu.__init__(self, master.root, tearoff=0) - self.add_command(label="Undo", state=DISABLED, accelerator="{}+Z".format(ctrl)) - self.add_command(label="Redo", state=DISABLED, accelerator="{}+Y".format(ctrl)) + self.add_command(label=_("Undo"), state=DISABLED, accelerator="{}+Z".format(ctrl)) + self.add_command(label=_("Redo"), state=DISABLED, accelerator="{}+Y".format(ctrl)) self.add_separator() - self.add_command(label="Copy", command=self.root.edit_copy, accelerator="{}+C".format(ctrl)) - self.add_command(label="Cut", state=DISABLED, accelerator="{}+X".format(ctrl)) - self.add_command(label="Paste", state=DISABLED, accelerator="{}+V".format(ctrl)) + self.add_command(label=_("Copy"), command=self.root.edit_copy, accelerator="{}+C".format(ctrl)) + self.add_command(label=_("Cut"), state=DISABLED, accelerator="{}+X".format(ctrl)) + self.add_command(label=_("Paste"), state=DISABLED, accelerator="{}+V".format(ctrl)) self.add_separator() - self.add_command(label="Select All", command=self.root.select_all, accelerator="{}+A".format(ctrl)) + self.add_command(label=_("Select All"), command=self.root.select_all, accelerator="{}+A".format(ctrl)) self.bind("", self.hide) # hide when clicked off def show(self, event): diff --git a/FoxDot/locale/pt_BR/LC_MESSAGES/FoxDot.mo b/FoxDot/locale/pt_BR/LC_MESSAGES/FoxDot.mo new file mode 100644 index 00000000..d704fa09 Binary files /dev/null and b/FoxDot/locale/pt_BR/LC_MESSAGES/FoxDot.mo differ diff --git a/FoxDot/locale/pt_BR/LC_MESSAGES/FoxDot.po b/FoxDot/locale/pt_BR/LC_MESSAGES/FoxDot.po new file mode 100644 index 00000000..811dc841 --- /dev/null +++ b/FoxDot/locale/pt_BR/LC_MESSAGES/FoxDot.po @@ -0,0 +1,352 @@ +# Portuguese translations for FoxDot package. +# Copyright (C) 2025 +# This file is distributed under the same license as the FoxDot package. +# taconi , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.9.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-09-24 20:18-0300\n" +"PO-Revision-Date: 2025-09-24 20:22-0300\n" +"Last-Translator: taconi \n" +"Language-Team: \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: FoxDot/lib/Workspace/ConfigFile.py:41 +msgid "Cancel" +msgstr "Cancelar" + +#: FoxDot/lib/Workspace/ConfigFile.py:44 +msgid "Save Changes" +msgstr "Salvar Alterações" + +#: FoxDot/lib/Workspace/ConfigFile.py:65 +msgid "Save changes" +msgstr "Salvar alterações" + +#: FoxDot/lib/Workspace/ConfigFile.py:65 +msgid "Do you want to save your changes?" +msgstr "Você que salvar suas alterações" + +#: FoxDot/lib/Workspace/ConfigFile.py:79 FoxDot/lib/Workspace/Editor.py:808 +msgid "Just a heads up" +msgstr "Só uma aviso" + +#: FoxDot/lib/Workspace/ConfigFile.py:79 +msgid "A restart of FoxDot is required for the changes to take effect" +msgstr "É necessário reiniciar o FoxDot para que as alterações entrem em vigor" + +#: FoxDot/lib/Workspace/Editor.py:70 +msgid "New version available" +msgstr "Nova versão disponível" + +#: FoxDot/lib/Workspace/Editor.py:71 +msgid "" +"There is a new version of FoxDot available from PyPI. Upgrade by going to " +"your command prompt and running:\n" +"\n" +"pip install FoxDot --upgrade" +msgstr "" +"Há uma nova versão do FoxDot dispovível no PyPI. Atualize indo ao " +"seu prompt de comando e executando:\n" +"\n" +"pip install FoxDot --upgrade" + +#: FoxDot/lib/Workspace/Editor.py:364 +#, python-brace-format +msgid "Welcome to FoxDot! Press {ctrl}+{help_key} for help." +msgstr "Bem-vindo ao FoxDot! Pressione {ctrl}+{help_key} para ajuda." + +#: FoxDot/lib/Workspace/Editor.py:384 +msgid "Load unsaved work?" +msgstr "Carregar backup?" + +#: FoxDot/lib/Workspace/Editor.py:384 +msgid "" +"Your code wasn't saved last time you used FoxDot, do you want to load any " +"unsaved work?" +msgstr "" +"Seu código não foi salva na última vez que você sou o FoxDot, gostaria de carregar " +"o backup?" + +#: FoxDot/lib/Workspace/Editor.py:417 +msgid "Live Coding with Python and SuperCollider" +msgstr "Live Coding com Python e SuperCollider" + +#: FoxDot/lib/Workspace/Editor.py:418 +#, python-brace-format +msgid "FoxDot v{version} - {title}" +msgstr "" + +#: FoxDot/lib/Workspace/Editor.py:646 +#, python-brace-format +msgid "" +"FoxDot Help:\n" +"-----------------------------------------\n" +"{ctrl}+Return : Execute code\n" +"{ctrl}+. : Stop all sound\n" +"{ctrl}+= : Increase font size\n" +"{ctrl}+- : Decrease font size\n" +"{ctrl}+L : Insert lambda symbol\n" +"{ctrl}+T : Insert tilde symbol\n" +"{ctrl}+S : Save your work\n" +"{ctrl}+O : Open a file\n" +"{ctrl}+M : Toggle the menu\n" +"{ctrl}+{toggle_key} : Toggle console window\n" +"print(SynthDefs) : View available SynthDefs\n" +"print(Samples) : View character-to-sample mapping\n" +"print(FxList) : View audio effects\n" +"print(Attributes) : View Player attributes\n" +"print(PatternMethods) : View Pattern methods\n" +"---------------------------------------------------\n" +"Please visit foxdot.org for more information\n" +"---------------------------------------------------" +msgstr "" +"FoxDot Help:\n" +"-----------------------------------------\n" +"{ctrl}+Enter : Executar o código\n" +"{ctrl}+. : Parar todo som\n" +"{ctrl}+= : Aumentar o tamanho da fonte\n" +"{ctrl}+- : Diminuir o tamanho da fonte\n" +"{ctrl}+L : Inserir o símbolo lambda\n" +"{ctrl}+T : Inserir o símbolo tilde\n" +"{ctrl}+S : Salvar seu trabalho\n" +"{ctrl}+O : Abrir um arquivo\n" +"{ctrl}+M : Alterar visibilidade do menu\n" +"{ctrl}+{toggle_key} : Alterar visibilidade do console\n" +"print(SynthDefs) : Ver SynthDefs disponíveis\n" +"print(Samples) : Ver mapemande de caracter-sample\n" +"print(FxList) : Ver efeitos de áudio\n" +"print(Attributes) : Ver atributos do Player\n" +"print(PatternMethods) : Vier métodos do Pattern\n" +"---------------------------------------------------\n" +"Por favor, visite foxdot.org para mais informações\n" +"---------------------------------------------------" + +#: FoxDot/lib/Workspace/Editor.py:677 FoxDot/lib/Workspace/Editor.py:696 +msgid "Python files" +msgstr "Aquivos Python" + +#: FoxDot/lib/Workspace/Editor.py:685 +#, python-brace-format +msgid "Saved '{filename}'" +msgstr "Salvo '{filename}'" + +#: FoxDot/lib/Workspace/Editor.py:704 +msgid "Save successful!" +msgstr "Salvo com sucesso!" + +#: FoxDot/lib/Workspace/Editor.py:732 +#, python-brace-format +msgid "" +"{} error occurred when loading file:\n" +" - '{}'" +msgstr "" + +#: FoxDot/lib/Workspace/Editor.py:739 +msgid "New file" +msgstr "Novo arquivo" + +#: FoxDot/lib/Workspace/Editor.py:739 +msgid "Save your work before creating a new document?" +msgstr "Salve seu trabalho antes de criar um novo documento?" + +#: FoxDot/lib/Workspace/Editor.py:751 +msgid "Plain Text File" +msgstr "Arquivos de Texto" + +#: FoxDot/lib/Workspace/Editor.py:775 +#, python-brace-format +msgid "" +"Hmm... Looks like we couldn't open the directory but you can find the " +"samples in {}" +msgstr "" + +#: FoxDot/lib/Workspace/Editor.py:808 +msgid "Restart of FoxDot is required for the changes to take effect" +msgstr "É necessário reiniciar o FoxDot para que as alterações entrem em vigor" + +#: FoxDot/lib/Workspace/Editor.py:1816 FoxDot/lib/Workspace/MenuBar.py:143 +#, python-brace-format +msgid "Listening for connections on {server}" +msgstr "Ouvindo conexões no {server}" + +#: FoxDot/lib/Workspace/Editor.py:1819 FoxDot/lib/Workspace/MenuBar.py:147 +msgid "Closed connections" +msgstr "Conexões fechadas" + +#: FoxDot/lib/Workspace/MenuBar.py:36 +msgid "New Document" +msgstr "Novo Documento" + +#: FoxDot/lib/Workspace/MenuBar.py:37 +msgid "Open" +msgstr "Abrir" + +#: FoxDot/lib/Workspace/MenuBar.py:38 +msgid "Save" +msgstr "Salvar" + +#: FoxDot/lib/Workspace/MenuBar.py:39 +msgid "Save As..." +msgstr "Salvar Como..." + +#: FoxDot/lib/Workspace/MenuBar.py:40 +msgid "File" +msgstr "Arquivo" + +#: FoxDot/lib/Workspace/MenuBar.py:45 FoxDot/lib/Workspace/MenuBar.py:172 +#: FoxDot/lib/Workspace/MenuBar.py:199 +msgid "Undo" +msgstr "" + +#: FoxDot/lib/Workspace/MenuBar.py:46 FoxDot/lib/Workspace/MenuBar.py:173 +#: FoxDot/lib/Workspace/MenuBar.py:200 +msgid "Redo" +msgstr "" + +#: FoxDot/lib/Workspace/MenuBar.py:48 FoxDot/lib/Workspace/MenuBar.py:176 +#: FoxDot/lib/Workspace/MenuBar.py:203 +msgid "Cut" +msgstr "" + +#: FoxDot/lib/Workspace/MenuBar.py:49 FoxDot/lib/Workspace/MenuBar.py:175 +#: FoxDot/lib/Workspace/MenuBar.py:202 +msgid "Copy" +msgstr "Copiar" + +#: FoxDot/lib/Workspace/MenuBar.py:50 FoxDot/lib/Workspace/MenuBar.py:177 +#: FoxDot/lib/Workspace/MenuBar.py:204 +msgid "Paste" +msgstr "Colar" + +#: FoxDot/lib/Workspace/MenuBar.py:51 FoxDot/lib/Workspace/MenuBar.py:179 +#: FoxDot/lib/Workspace/MenuBar.py:206 +msgid "Select All" +msgstr "Selecionar Tudo" + +#: FoxDot/lib/Workspace/MenuBar.py:53 +msgid "Increase Font Size" +msgstr "Aumentar a Fonte" + +#: FoxDot/lib/Workspace/MenuBar.py:54 +msgid "Decrease Font Size" +msgstr "Diminuir a Fonte" + +#: FoxDot/lib/Workspace/MenuBar.py:56 +msgid "Clear Console" +msgstr "Limpar Console" + +#: FoxDot/lib/Workspace/MenuBar.py:57 +msgid "Export Console Log" +msgstr "Exportar Log do Console" + +#: FoxDot/lib/Workspace/MenuBar.py:58 +msgid "Toggle Console" +msgstr "Console" + +#: FoxDot/lib/Workspace/MenuBar.py:60 +msgid "Toggle Fullscreen" +msgstr "Fullscreen" + +#: FoxDot/lib/Workspace/MenuBar.py:61 +msgid "Toggle Menu" +msgstr "Menu" + +#: FoxDot/lib/Workspace/MenuBar.py:62 +msgid "Toggle Window Transparency" +msgstr "Transparência" + +#: FoxDot/lib/Workspace/MenuBar.py:63 +msgid "Toggle Auto-fill Prompt" +msgstr "Autocomplete" + +#: FoxDot/lib/Workspace/MenuBar.py:64 +msgid "Toggle Beat Counter" +msgstr "Contador de Batidas" + +#: FoxDot/lib/Workspace/MenuBar.py:65 +msgid "Edit" +msgstr "Editor" + +#: FoxDot/lib/Workspace/MenuBar.py:71 +msgid "Evaluate Block" +msgstr "Executar o Código" + +#: FoxDot/lib/Workspace/MenuBar.py:72 +msgid "Evaluate Line" +msgstr "Executar a Linha" + +#: FoxDot/lib/Workspace/MenuBar.py:73 +msgid "Clear Scheduling Clock" +msgstr "Limpar Relógio de Agendamento" + +#: FoxDot/lib/Workspace/MenuBar.py:75 +msgid "Use SC3 Plugins" +msgstr "" + +#: FoxDot/lib/Workspace/MenuBar.py:77 +msgid "Listen for connections" +msgstr "Ouça as conexões" + +#: FoxDot/lib/Workspace/MenuBar.py:78 +msgid "Language" +msgstr "Linguagem" + +#: FoxDot/lib/Workspace/MenuBar.py:84 +msgid "Display help message" +msgstr "Mostrar mensagem de ajuda" + +#: FoxDot/lib/Workspace/MenuBar.py:85 +msgid "Visit FoxDot Homepage" +msgstr "Visite o site do FoxDot" + +#: FoxDot/lib/Workspace/MenuBar.py:86 +msgid "Documentation" +msgstr "Documentação" + +#: FoxDot/lib/Workspace/MenuBar.py:89 FoxDot/lib/Workspace/MenuBar.py:94 +msgid "Low" +msgstr "Baixo" + +#: FoxDot/lib/Workspace/MenuBar.py:91 FoxDot/lib/Workspace/MenuBar.py:96 +msgid "High" +msgstr "Alto" + +#: FoxDot/lib/Workspace/MenuBar.py:92 +msgid "CPU Usage" +msgstr "Uso de CPU" + +#: FoxDot/lib/Workspace/MenuBar.py:95 +msgid "Medium" +msgstr "Médio" + +#: FoxDot/lib/Workspace/MenuBar.py:97 +msgid "Clock Latency" +msgstr "Latência do Relógio" + +#: FoxDot/lib/Workspace/MenuBar.py:99 +msgid "Open Samples Folder" +msgstr "Abrir Diretório de Samples" + +#: FoxDot/lib/Workspace/MenuBar.py:100 +msgid "Open config file (advanced)" +msgstr "Abrir arquivo de configurações (avançado)" + +#: FoxDot/lib/Workspace/MenuBar.py:101 +msgid "Help & Settings" +msgstr "Ajuda & Configurações" + +#: FoxDot/lib/Workspace/MenuBar.py:120 +#, python-brace-format +msgid "Load Tutorial {num}: {name}" +msgstr "Abrir Tutorial {num}: {name}" + +#: FoxDot/lib/Workspace/MenuBar.py:122 +msgid "Tutorials" +msgstr "Tutoriais" diff --git a/changelog b/changelog index 00b8cf7b..f7bcaa5a 100644 --- a/changelog +++ b/changelog @@ -1,5 +1,7 @@ ### 0.9.* +- Internationalizing the tutorials and adding translation for pt-BR +- Internationalizing the editor and adding translation for pt-BR - Added support for Python >3.11, dropping support for earlier versions.g ### 0.8.* diff --git a/setup.py b/setup.py index 477c02f5..ae8be7df 100644 --- a/setup.py +++ b/setup.py @@ -54,12 +54,13 @@ 'osc/*.scd', 'osc/sceffects/*.scd', 'osc/scsyndef/*.scd', - 'demo/*.py', + 'demo/**/*.py', 'rec/.null', 'lib/Extensions/*/*.*', 'lib/Extensions/*/*/*.*', 'lib/.version', 'README.md', + 'locale/**/**/*.mo', ], 'FoxDot.lib.Workspace': ['img/*', 'tmp/*'], 'FoxDot.lib.Settings' : ['conf.txt']})