Seu português está sempre três releases atrás do seu inglês
Localização falha porque é entregue como uma passada única e a fonte continua se movendo, a correção é um loop que redispara cada tradução no instante em que a string em inglês de que ela veio muda.
Apollo Space Research
Apollo Space
Abra a versão em inglês de quase qualquer produto e os botões fazem sentido. Mude para português, ou espanhol, ou japonês, e em algum lugar na terceira tela uma palavra está errada. Não mal traduzida, desatualizada. O inglês diz “Archive”, o português ainda diz “Excluir”, porque três releases atrás o botão mudou e a tradução não. Ninguém decidiu lançar uma mentira. A mentira foi lançada porque a tradução foi finalizada uma vez, e o produto não foi.
Esse intervalo entre “finalizado uma vez” e “nunca finalizado” é o problema inteiro da localização. E é a coisa que quase toda ferramenta entende ao contrário.
Uma tradução não é uma entrega. É um relacionamento com uma string que não para de mudar.
Este post é sobre o que muda quando você trata localização desse jeito, não como um trabalho que você completa, mas como um loop que você mantém. O mecanismo é pequeno. A consequência é que o português para de ficar atrás do inglês.
A versão ingênua: uma localização é uma passada
Aqui está como é feito em quase todo lugar, e é razoável, que é por que é uma armadilha.
Você termina uma feature. As strings em inglês se assentam. Você as exporta, um arquivo de chaves e valores, e envia o arquivo para ser traduzido, por um fornecedor, por um contratado, por um script que chama um modelo. Alguns dias depois um arquivo traduzido volta. Você o coloca no lugar. Cada idioma se acende. Você lança. Localização: feita.
Está feita. Esse é exatamente o problema. Está feita do jeito que uma fotografia está feita, um registro perfeito de um momento que começa a envelhecer no instante em que é tirado.
Porque o inglês não fica parado. No próximo sprint alguém renomeia “Archive” para “Move to archive”. Alguém divide uma tela em duas e escreve quatro novas strings. Alguém conserta um typo na fonte e, sem pensar, muda levemente o significado. Cada uma dessas edições é invisível para os arquivos traduzidos, que estão sentados no repositório exatamente como voltaram do fornecedor, congelados no momento da passada. O inglês seguiu em frente. O português ficou onde foi fotografado.
Então o intervalo se abre. Silenciosamente, uma string por vez. Um novo botão aparece sem tradução, na melhor das hipóteses cai de volta para o inglês, na pior mostra uma chave bruta como button.archive. Uma string renomeada mantém sua tradução antiga, agora sutilmente errada. Uma string deletada deixa uma entrada morta que ninguém limpa. Nada disso é alto o suficiente para quebrar um build. Tudo isso é alto o suficiente para um cliente em São Paulo notar que o produto foi claramente construído para outra pessoa.
A versão ingênua não está errada porque as traduções são ruins. Está errada porque trata um alvo móvel como um parado. Você pode rodar a passada de novo, claro, reexportar, reenviar, reimportar. Mas você só faz isso quando alguém nota a deriva, o que significa que a deriva já foi lançada. A passada é sempre uma resposta a um problema que o cliente encontrou primeiro.
Por que “só retraduzir tudo” não conserta
O remendo óbvio é tornar a passada barata o suficiente para rodar constantemente. Tradução por um modelo custa uma fração do que um fornecedor humano cobra, então por que não retraduzir o catálogo inteiro de strings a cada release e dar a deriva por resolvida?
Duas razões, e são as razões que tornam a ideia barata cara.
A primeira é que retraduzir tudo joga fora trabalho que você queria manter. Algumas das suas strings foram traduzidas uma vez, depois corrigidas à mão por alguém que de fato fala o idioma e sabia que a tradução literal soava como um robô. Uma rodada geral sobrescreve essas correções com output de máquina fresco. Você não recebe menos erros. Você recebe os mesmos erros de volta, mais a perda de cada conserto que um humano fez. O sistema que deveria manter a qualidade acabou de apagá-la.
A segunda é que tradução sem contexto produz bobagem confiante. A palavra “Open” é um verbo num botão e um adjetivo num badge de status, “Open ticket” versus “Ticket is open”. Um modelo que recebe uma lista plana de strings não faz ideia de qual é qual, então chuta, e chuta do mesmo jeito toda vez independentemente de onde a string mora. “Save” perto de um documento significa uma coisa; “Save” perto de um checkout significa outra; “Save 20%” significa uma terceira. Retraduza o catálogo inteiro cegamente e você lava boas traduções e ruins juntas em velocidade industrial.
Então a correção barata falha duas vezes. É desperdiçadora, a maioria das strings não mudou e não precisava ser tocada. E é descuidada, ela tira o contexto que tornou as boas traduções boas. Fazer a coisa errada mais rápido não é o mesmo que fazer a coisa certa.
A lição escondida em ambas as falhas é a mesma. A unidade de localização nunca foi o arquivo. Era a string, e especificamente, o relacionamento da string com a fonte de que veio. Uma tradução não é uma entrega. É um relacionamento com uma string que não para de mudar. Conserte a unidade errada e você vai lançar trabalho desatualizado ou destruir bom trabalho, e geralmente os dois.
Nosso jeito: localize a mudança, não o catálogo
Aqui está a ideia, e como a maioria das boas ideias ela é quase irritantemente simples uma vez que você a vê. Pare de traduzir catálogos. Comece a traduzir mudanças.
Uma string de fonte não é um valor num arquivo. É um valor com um histórico, foi adicionado em alguma data, editado pela última vez em outra, e carrega uma impressão digital de seu texto em inglês atual. A tradução que a acompanha lembra de qual versão do inglês ela foi feita. Então o sistema sempre consegue responder a uma pergunta que o mundo baseado em arquivos não consegue: esta tradução ainda está descrevendo o inglês de que nasceu, ou o inglês se moveu por baixo dela?
Essa única pergunta é o motor inteiro. Quando o inglês muda, sua impressão digital muda, e cada tradução que foi feita da impressão digital antiga está agora, comprovadamente, desatualizada, não por chute, por registro. O sistema não retraduz o catálogo. Ele redispara exatamente as strings cuja fonte se moveu, e deixa as milhares que não se moveram completamente em paz.
E ele as redispara com contexto, porque a essa altura sabe onde cada string mora. Esta string é um label de botão; aquela é uma mensagem de erro; esta fica ao lado de um preço. Um company brain que leu o produto sabe a diferença entre o imperativo “Open” e o adjetivo “open”, porque sabe a tela a que cada um pertence. Então a retradução não é um chute cego contra uma lista plana, é uma reescrita consciente de contexto de uma string, a string que de fato mudou, na voz que o resto daquela superfície já usa.
Caminhe uma edição por isso. Imagine que um designer renomeia “Archive” para “Move to archive” numa terça à tarde. A impressão digital da string em inglês muda no momento em que essa edição aterrissa. O sistema nota que cada idioma apontando para a impressão digital antiga está agora desatualizado, digamos uma dúzia deles, e redispara apenas esses, cada um retraduzido com o conhecimento de que este é um botão que executa uma ação no item atual. O revisor humano, em vez de encarar uma reexportação completa do catálogo inteiro, vê uma lista arrumada: uma string de fonte mudou, aqui estão as doze traduções que produziu, aprove ou corrija. Quando o botão renomeado chega a um cliente, o português já diz o português para “Move to archive”, não o português para o botão que não existe mais.
A parte que faz disso manutenção, não mágica: um humano ainda assina
Seria fácil ler tudo isso como “o agent traduz tudo automaticamente e você nunca mais olha”. Esse não é o design, e o lugar onde ele quebraria te diz por quê.
Tradução de máquina é boa o suficiente para rascunhar e não boa o suficiente para confiar sem supervisão nas strings que carregam peso. Um aviso legal, uma linha de política de reembolso, a redação exata de uma checkbox de consentimento, essas são strings onde uma tradução errada de som plausível é pior que uma óbvia, porque ninguém a pega até importar. O piloto-automático ingênuo lança essas silenciosamente. O loop cuidadoso as roteia.
Então o redisparo não termina numa tradução. Ele termina numa proposta. O sistema fez a parte tediosa, encontrou as strings que se moveram, rascunhou traduções conscientes de contexto para cada, e as montou numa única mudança pequena e revisável. Uma pessoa que lê o idioma dá o aceno, ou conserta a que ficou dura, e o conserto dela é lembrado, com impressão digital, e nunca silenciosamente sobrescrito por um redisparo futuro. A abordagem barata de retraduzir-tudo não conseguia prometer isso. Este loop é construído para que consiga.
Essa é a diferença entre automação que substitui o revisor e automação que o respeita. O trabalho que é tedioso e mecânico, fazer o diff da fonte, encontrar as strings desatualizadas, rascunhar a primeira passada, é exatamente o trabalho que um humano faz mal e detesta fazer. O trabalho que é de alto juízo, esta linha de consentimento diz a coisa certa neste idioma e nesta cultura, é exatamente o trabalho que um humano faz bem e um modelo não deveria fazer sozinho. Ponha o loop no primeiro e a pessoa no segundo, e você ganha velocidade sem entregar a parte que de fato precisava de um humano.
O que isso compra, e o que para de custar
Some tudo e a mudança não é “traduções ficam prontas mais rápido”. É que traduções param de se desfazer.
No modelo antigo, cada release era uma pequena aposta de que ninguém mudou uma string localizada, e você perdia essa aposta silenciosa e frequentemente. O custo não era o trabalho de tradução, isso era barato. O custo era o gotejar de strings desatualizadas chegando a clientes em cada idioma menos o que você constrói, cada uma um pequeno sinal de que o produto não foi realmente feito para eles. Suponha que um time veloz lance dúzias de edições de string por semana; no modelo de passada, alguma fração dessas deriva para cada locale não-inglês e fica ali até um cliente ou um ticket de suporte trazer à tona. A deriva nunca foi um problema de tradução. Era um problema de manutenção vestido de fantasia de tradução.
Uma tradução não é uma entrega. É um relacionamento com uma string que não para de mudar. Uma vez que você segura o relacionamento em vez do arquivo, a pergunta “nosso português está atual?” para de ser uma coisa que você audita e passa a ser uma coisa que o sistema pode responder a qualquer momento, porque ele sabe quais traduções apontam para quais versões da fonte. Atual não é um estado que você periodicamente restaura. É o padrão que o loop mantém.
E o custo que ele para de pagar é o pior tipo de custo, o silencioso. Nenhum time jamais colocou “deixar o espanhol desatualizar” num roadmap. Aconteceu nos intervalos entre intenções, uma string não-redisparada por vez, até a experiência no segundo idioma estar visivelmente uma geração atrás da primeira. Fechar esse intervalo não exige um sprint heroico de localização. Exige que a mudança da fonte e a tradução sejam o mesmo evento, em vez de dois eventos com uma distância crescente entre eles.
A virada: a quem você para de pedir que seja a rede de segurança
Tire as impressões digitais e os redisparos e há uma pessoa no fundo de tudo isso, e vale dizer quem.
Em algum lugar de uma empresa que lança em mais de um idioma, alguém é a ferramenta de diff humana. Ela fala o segundo idioma, e por isso o trabalho de pegar a deriva cai sobre ela por padrão: notar o novo botão sem tradução, lembrar que “Archive” foi renomeado, sinalizar a string que está errada desde a primavera. Não está na descrição de cargo dela. Virou trabalho dela porque o sistema não fazia, e alguém tinha que fazer, e ela era quem notaria. Cada hora que ela passa sendo verificadora de frescor de um catálogo de strings é uma hora que ela não passa na coisa que só um humano fluente consegue fazer, fazer o produto soar como se fosse escrito naquele idioma, não traduzido para ele.
Esse é o trabalho que vale a pena proteger. Não o diff. A voz. O juízo de que uma tradução literal está tecnicamente correta e culturalmente surda. O conhecimento de que esta frase chega calorosa num mercado e fria em outro. Um loop pode encontrar as strings que se moveram e rascunhar a primeira versão; ele nunca pode decidir o que “certo” soa para um cliente que cresceu falando o idioma. O ponto de automatizar a manutenção não é remover o humano da localização. É movê-lo da parte que estava abaixo dele para a parte que sempre foi dele.
É isso que estamos construindo na Apollo, não um botão de tradução mais rápido, mas um loop de localização onde a mudança da fonte e a tradução são um evento, para que o segundo idioma nunca tenha que ficar atrás do primeiro. Se você já mudou um produto para seu próprio idioma e sentiu, na terceira tela, que ele não foi realmente feito para você, você já sabe o intervalo que isso fecha. A tradução nunca foi a parte difícil. Mantê-la verdadeira era.
A Apollo cuida da operação repetitiva da sua empresa pro seu time não precisar.
Entre na lista de espera: acesso antecipado, preço de usuário fundador e um lugar na primeira fila enquanto a gente constrói.
Entrar na lista de esperaA morte lenta da voz de um marketeiro
Você publica uma peça real por semana e silenciosamente a traduz em dez, e cada tradução é uma pequena chance de soar um pouco menos como você mesmo. Construímos o OS porque nada no mercado estava guardando isso.
Pensamento de ProdutoNo dia em que alguém pede demissão, sua empresa esquece como ela funciona
Onboarding não está quebrado porque o treinamento é ruim. Está quebrado porque sua empresa não consegue lembrar, e cansamos de ver a resposta sair pela porta.
Pensamento de ProdutoA primeira coisa que um novo contratado deveria fazer é ler a empresa
Um ótimo onboarding não te entrega docs, ele já sabe quem você é quando você faz login.