Um catálogo só cresce, e todas as páginas pagavam o catálogo inteiro
Adicionado1Corrigido1
Nesta versão
O texto que vive em uma única página, uma lista de versões, um arquivo de blog, uma lista longa de perguntas, era baixado por cada visitante em todas as páginas. Esta versão deixa você nomear esses grupos de mensagens e mantê-los no build. As páginas que os usam continuam saindo traduzidas, porque esse texto já está escrito no HTML, e o navegador para de baixá-lo. Procurar a prova revelou ainda um defeito real por baixo. Depois da primeira passagem, o Verbaly podia trocar texto traduzido correto da página pelo nome interno da mensagem quando essa mensagem faltava. Fica corrigido aqui, e importa para qualquer um que pré-renderize o seu site.
Um catálogo só cresce, e todas as páginas pagavam o catálogo inteiro
O texto que vive em uma única página, uma lista de versões, um arquivo de blog, uma lista longa de perguntas, era baixado por cada visitante em todas as páginas. Esta versão deixa você nomear esses grupos de mensagens e mantê-los no build. As páginas que os usam continuam saindo traduzidas, porque esse texto já está escrito no HTML, e o navegador para de baixá-lo. Procurar a prova revelou ainda um defeito real por baixo. Depois da primeira passagem, o Verbaly podia trocar texto traduzido correto da página pelo nome interno da mensagem quando essa mensagem faltava. Fica corrigido aqui, e importa para qualquer um que pré-renderize o seu site.
Destaques
O texto que só uma página precisa para de viajar para todas. Nomeie esse grupo de mensagens na sua configuração e o navegador não o baixa mais. As páginas que o usam continuam saindo traduzidas, porque esse texto já está no HTML.
O texto pré-renderizado não é mais destruído. Se uma mensagem faltar, o Verbaly mantém o texto que já está na página em vez de trocá-lo pelo nome interno da mensagem. Antes isso podia acontecer um instante depois de a página carregar.
Medido neste site: o arquivo que cada página carrega passou de 46,3 KB para 33,5 KB comprimido, e as árvores em espanhol e português baixaram cerca de 14 KB cada uma. Nada se perdeu na tela.
Nada muda se você não ativar. É uma opção nova, e um projeto que não a escreva se comporta exatamente como antes.
O build avisa quando algo parece errado, nomeando um grupo que não corresponde a nada do seu catálogo, ou um que o seu código lê diretamente.
Adicionado · 1
An option that keeps the groups of messages only the build needs out of the browser
Corrigido · 1
Pre-rendered text is no longer replaced by a message’s internal name when that message is missing
As nossas próprias verificações mediam a máquina, não o código
O job que verifica a nossa cobertura de testes falhava ao acaso, e a causa não era um teste lento. Um teste que leva 22 milissegundos era derrubado por um limite de 5 segundos, porque esse limite conta tempo real e o nosso comando de testes levanta doze processos sobre os mesmos núcleos. Duas vezes isso bloqueou uma publicação. Esta versão corrige na raiz, e dedica o resto à mesma ideia aplicada à nossa cadeia de suprimentos: o que o nosso build pode fazer, quais ferramentas ele roda exatamente, e código que nunca poderia ser executado. Nada do pacote muda.
Destaques
Nada do que você instala muda. O runtime é idêntico ao da 0.43.0 e toda a API publicada se comporta igual. Esta versão é sobre a maquinaria que nos verifica.
O nosso build parou de falhar ao acaso. A suíte podia derrubar um teste perfeitamente saudável só porque a máquina estava ocupada, e duas vezes isso bloqueou uma publicação.
Cada ferramenta que o nosso build roda está fixada em um commit exato. Uma tag pode ser movida por quem a controla, mas um commit não, então nada pode mudar em silêncio o que constrói o seu pacote.
O job que publica as versões pede permissão de escrita só onde precisa, em vez de dá-la a todo o fluxo.
A análise estática roda a cada mudança, e a sua configuração agora vive no nosso repositório, fixada e legível, em vez de ser um ajuste que só nós víamos.
Adicionado · 1
A CodeQL workflow, so the configuration of our static analysis lives in the repository instead of in a setting
Alterado · 4
The test suite no longer fails a healthy test when the machine is busy
Every GitHub Action our build uses is pinned to an exact commit
The release job holds write access only on the job that needs it
Three branches of code that could never execute were removed
O badge do nosso README diz ~3KB desde o começo, enquanto o runtime pesava na verdade 3,68 KB. Em vez de enfraquecer a afirmação, esta versão remove a última peça que valia a pena remover: o formato de tempo relativo são 318 bytes que quase nenhum aplicativo escreve, e agora só viaja quando alguma das suas mensagens o pede. O resto da versão é a mesma ideia apontada para tudo o mais que o projeto diz de si mesmo.
Destaques
O runtime pesa 3,00 KB. O formato de tempo relativo se junta ao ICU como algo que só viaja quando alguma das suas mensagens realmente o usa, e não há nada que você tenha que configurar.
Um formatador que você mesmo escreva agora sabe para qual mensagem foi chamado. Ele recebe o nome do parâmetro e a chave da mensagem, então os seus próprios erros podem dizer onde aconteceram, o que antes não dava.
A política de segurança cobre os doze pacotes, não os sete que existiam quando foi escrita, e agora explica como verificar que uma versão saiu mesmo do nosso CI.
A nossa postura de segurança é algo que você pode conferir em vez de algo que afirmamos: uma pontuação da OpenSSF roda a cada mudança e o badge do README a lê.
Adicionado · 2
A setting that ships relative time formatting anyway, for text that only reaches your app after the build
A formatter receives the parameter name and the message key it was called for
Alterado · 3
The runtime went from 3.28 KB to 3.00 KB for a project that writes neither ICU nor relative time
The size limits were tightened again, so the saving cannot be quietly spent later
The README quotes the measured number and names the command that measures it
A sintaxe própria do Verbaly cobre plurais, selects e formatos, e a sintaxe ICU é a saída para o que ela não cobre. Essa saída sempre foi descrita como algo opcional, e nunca foi: o parser entrava em todo aplicativo usando ICU ou não. O nosso próprio site de documentação não tem nenhuma mensagem ICU e o publicava em cada página. O Verbaly já lê os seus catálogos, então agora só manda o parser onde alguma mensagem realmente precisa dele.
Destaques
O runtime é 11% menor para quem não usa sintaxe ICU, que são quase todos os projetos. O parser só viaja quando alguma das suas mensagens realmente precisa dele, e não há nada que você tenha que ligar.
Nada muda se você usa ICU. O Verbaly vê isso nos seus catálogos e leva o parser junto, exatamente como antes.
Uma mensagem que chega ao seu aplicativo depois do build e usa ICU agora mostra o seu próprio texto e diz por quê, em vez de ficar meio renderizada em algo que parece quase certo. Se o seu texto vem de um CMS, um ajuste manda o parser mesmo assim.
Adicionado · 1
A setting that ships the ICU parser anyway, for text that only reaches your app after the build
Alterado · 3
The runtime went from 3.68 KB to 3.28 KB for a project whose messages do not use ICU syntax
An ICU message with no parser shows its own text and says why, instead of rendering something that looks almost right
The size limits were tightened to match, so the saving cannot be quietly spent later
Uma linha para trocar, e a sua escolha finalmente fica
O Verbaly trazia um trocador de idioma completo para uma forma de fazer os endereços e uma peça solta para a outra, então todo projeto escrevia a segunda à mão, o nosso incluído. Reescrever o nosso próprio site sobre o helper da biblioteca encontrou uma falha que estava lá desde que o trocador entrou no runtime: quem escolhia um idioma voltava ao do seu navegador na carga seguinte. A outra metade é que o Verbaly tinha começado a supor que você queria o idioma nos seus endereços; agora ele lê a sua montagem em vez de adivinhar.
Destaques
Trocar de idioma é uma linha, e é a mesma linha funcionem como funcionarem os seus endereços. Vai para o outro endereço quando o idioma mora lá, e muda o texto onde está quando não.
A sua escolha de idioma sobrevive à carga seguinte. Escolher inglês numa página em espanhol podia devolver você ao espanhol, porque a troca guardava a sua escolha num lugar e a página que recebe você lia outro.
O Verbaly deixa de supor que você quer o idioma nos seus endereços. Ele lê a sua montagem: se você constrói uma versão do seu site por idioma tem endereços por idioma, senão um só serve para todos. Você só escreve isso para discordar.
verbaly doctor diz se leu a sua escolha ou deduziu, para que um ajuste que ninguém escreveu não pareça uma decisão que alguém tomou.
A verificação de tamanho agora mede o que um aplicativo real embarca de verdade, e não só a importação mais pequena possível e a maior impossível.
Adicionado · 2
A language switcher that works the same in both ways of handling addresses, bound to your project so there is nothing to pass
The switch remembers your choice in both places a page can read it back from, under one name
Alterado · 4
Where the language lives in your addresses is read from your setup instead of assumed, and you only write it to disagree
verbaly doctor says whether it read that setting or worked it out
On Next.js the switch uses the app router, so a language change keeps your app alive instead of re-rendering twice
The size check measures four things now, and separates a budget from a warning light
Corrigido · 2
Someone who picked a language was sent back to their browser language on the next page load
A project with a single address was told it had one address per language, which was simply not true of it
Diga onde o idioma mora, e traduza também o cabeçalho
O Verbaly tem há muito tempo duas formas de carregar o idioma e nunca nomeou nenhuma delas, então qual você recebia era decidido por você lembrar de passar um campo opcional. Nomeá-las revelou o que fazia a nomeação importar: uma página podia estar traduzida em tudo o que um visitante olha e ainda assim dizer a um buscador que está em inglês, porque o título e a descrição moram no cabeçalho, onde ninguém os lê. A nossa própria documentação publicava 27 de 27 páginas assim.
Destaques
Agora você pode dizer onde o idioma mora nos seus endereços, uma vez, na configuração: /docs e /es/docs, um prefixo em todos os idiomas, ou um único endereço para todos. Antes a resposta dependia de qual helper você chamava e do que passava a ele.
O seletor de idioma é uma linha e não dá para escrever errado. O Verbaly te dá um helper que já conhece os seus idiomas, a sua fonte e o seu modo, e a mesma linha continua funcionando se você mudar de ideia sobre o modo.
O título e a descrição das suas páginas também são traduzidos. Eles moram no cabeçalho, ninguém os lê na página e são o que um resultado de busca mostra, então uma página podia parecer inteiramente traduzida e aparecer listada em inglês.
verbaly render conta as páginas cujo título ainda nunca muda e te diz uma vez, com a correção. Nunca derruba um build: o nome de um produto pode não se traduzir.
verbaly doctor diz em que modo estão os seus endereços, e avisa quando a sua configuração pede duas coisas que não podem ser verdade ao mesmo tempo.
Breaking: pedir um caminho sem nomear o seu idioma fonte não compila mais. Antes colocava prefixo em todos os idiomas incluindo o seu, em silêncio, o que quase nunca era o que alguém queria.
Adicionado · 4
A routing setting with three values, so where the language sits in your addresses is said once instead of inferred
A path helper that already knows your languages, your source and your mode, so a language switcher cannot be written wrong
A routing line in verbaly doctor, including a warning when two settings ask for opposite things
verbaly render counts the pages whose title never changes between languages, and says it once with the fix
Alterado · 3
Asking for a path now requires naming your source language wherever that decides the answer
Under one-address mode the path helper returns the address you are already on, so one switcher works in both modes
The English descriptions on this site were rewritten shorter: several ran past what a search result shows
Corrigido · 3
A translated page shipped its title and description in the source language, which is most of what a search result shows
Switching language without a navigation left the page title alone, and nothing said so
Pages that only redirect were being reported for a title nobody will ever read in a search result
Traduzir sobrevive a uma conexão ruim, e os agentes recebem o ciclo inteiro
O Verbaly deixa um agente de código executá-lo há um tempo, mas dos seus doze comandos só quatro chegaram a ficar disponíveis, e os dois que faltavam são os dois primeiros de que um agente precisa: descobrir o que falha em um projeto e envolver o texto que já está escrito nele. Olhando para isso apareceu algo pior ao lado. verbaly translate é o único comando que custa dinheiro e minutos, e uma única resposta ruim jogava fora a execução inteira: lotes já pagos e traduzidos nunca chegavam ao disco.
Destaques
verbaly translate não perde mais o trabalho que você já pagou. Uma requisição que não volta é tentada de novo, e se ainda assim falhar a execução continua e salva todo o resto. Rodar de novo pede só o que falta, em vez de pagar tudo outra vez.
Traduzir é umas quatro vezes mais rápido. Agora as requisições saem juntas em vez de uma atrás da outra, e uma execução longa vai contando o que chegou enquanto trabalha, em vez de ficar calada por minutos.
Você pode dizer o que nunca se traduz. Coloque os nomes do seu produto e qualquer forma que já tenha decidido em translate.glossary, e como você trata o leitor em translate.instructions, em vez de corrigir a mesma palavra à mão depois de cada execução.
Seu agente de código recebe as duas ferramentas que faltavam: uma para descobrir por que um projeto não funciona, e outra para encontrar o texto escrito direto nos seus componentes e envolvê-lo. Levar um aplicativo existente para o Verbaly já não precisa de um terminal.
Agora os agentes leem números, não frases. Cada ferramenta responde com dados simples além do texto, então um agente para de adivinhar uma redação que pode mudar entre versões.
Aceitar uma tradução automática continua sendo algo que só uma pessoa pode fazer, e isso não mudou.
Adicionado · 4
Two new tools for coding agents: one that diagnoses a project end to end, and one that wraps hardcoded text so the compiler can pick it up
Every agent tool now answers with structured data alongside the sentence it always returned
translate.instructions and translate.glossary, so tone and required wordings are settings of the project rather than something you fix afterwards
translate.concurrency and translate.retries, for a provider that rate limits you or a connection that drops
Corrigido · 6
One failed request threw away every request that had already succeeded, so a run that broke near the end wrote nothing at all
A request that failed for a passing reason was treated as a real failure, with no second attempt
Requests went out one at a time although nothing connected them
An answer cut short by length failed with a message about broken text instead of saying the batch was too big
A translate run said nothing at all while it worked, sometimes for minutes
verbaly doctor counted the way the rest of the tool stopped counting, and a suggested fix could end up in a different place than the problem it fixed
As traduções escritas por grupos já estão seguras em todo lugar
Você pode guardar suas traduções como grupos aninhados em vez de uma lista plana só, e o Verbaly já lê essa forma há um tempo. Só que apenas metade dele lia: os comandos que escrevem seus catálogos tomavam os nomes de grupo como se fossem mensagens. Então o extract adicionava uma segunda cópia de cada mensagem, o --prune apagava grupos inteiros com todas as traduções dentro, os exports chegavam quebrados ao seu tradutor e o translate dizia que não havia nada a fazer sobre um app pela metade. Para um catálogo plano nada muda.
Destaques
As traduções guardadas por grupos estão seguras de ponta a ponta. Agora todos os comandos leem e escrevem elas do mesmo jeito, e seu arquivo mantém a forma que você deu em vez de ficar achatado pelas suas costas.
O verbaly extract --prune não apaga mais traduções. Num catálogo escrito por grupos ele lia o nome de cada grupo como uma mensagem, não reconhecia e levava o grupo inteiro com todas as traduções dentro.
Seus arquivos para o tradutor param de chegar quebrados. O export escrevia [object Object] onde deveria ir o texto, e o verbaly translate dizia que não havia nada a fazer enquanto o verbaly status dizia que metade do app estava sem tradução.
Um idioma que você adicionar depois combina com o resto. Um catálogo novo assume a forma dos que você já tem, então um projeto nunca acaba metade por grupos e metade plano.
A ferramenta conta em inglês de verdade. Antes dizia 1 messages, 1 locales e 1 pages em nove lugares.
Um aviso repetido se diz uma vez só. Uma colisão de chaves era anunciada três vezes num único verbaly extract, uma delas depois de o resumo já ter sido impresso.
Alterado · 2
A catalog value that is not text is now refused, naming the file and the exact path, instead of being dropped the next time a catalog is written
Reading a message is faster on a large catalog, and stops falling off a cliff past a couple of thousand of them
Corrigido · 4
Commands that write your catalogs read a group name as if it were a message, so extract duplicated, prune deleted, export broke and translate went quiet
A language added later was always written flat, even when every other catalog in the project used groups
Nine lines of output said "1 messages", "1 locales", "1 pages", "1 keys" or "1 translations"
A key collision was reported once per command instead of once per run
A versão anterior deu nome às duas formas que um site tem de levar o seu idioma. Escrever a página que as explica destapou porque é que uma delas nunca tinha funcionado bem: se a tua app mantém um só endereço por página e carrega os idiomas a pedido, o Verbaly sabia que idioma o visitante queria e simplesmente nunca o pedia. Uma linha, e o exemplo das nossas próprias docs andava a ensiná-lo desde sempre.
Destaques
O idioma guardado já sobrevive a um F5 num site de um só endereço. Quem voltava recebia o idioma de origem outra vez, sem nada na consola que o explicasse.
Não muda nada se o teu idioma vai no endereço, que é do que trataram as duas versões anteriores. Isto só estava partido onde o idioma vem do armazenamento ou do navegador.
Um aviso que dava um conselho impossível passa a dar o certo. Quando a tua página diz um idioma e o Verbaly está noutro, dizia-te para leres o idioma do endereço. Num site de um só endereço não há nada para ler.
O React, o Vue e o Svelte foram testados um a um contra um idioma que chega quando a página já está no ecrã. Antes era um caminho raro e agora é o normal.
Corrigido · 2
A language chosen on a previous visit was recognised but never loaded, so the page stayed in the source language
The page-language warning suggested a fix that does not exist on a site without the language in the address
O Verbaly publica o teu site em cada idioma, cada um no seu próprio endereço. A versão anterior deixou essas páginas certas, e esta é sobre como as pessoas chegam até elas, e sobre poder perguntar a partir do teu próprio código a que idioma pertence uma página. As duas coisas tinham de ser escritas à mão por cada projeto, este site duas vezes num dia. Também corrige uma forma de o nome de uma página ser confundido com um idioma.
Destaques
Perguntar em que idioma está uma página já não precisa de um ajudante teu. O Verbaly responde com o idioma que o endereço diz, ou com nada quando o endereço não diz nenhum. Essa é uma pergunta diferente de qual o visitante prefere, e misturar as duas é o que deixava uma preferência guardada pintar o idioma errado por cima de uma página.
O Verbaly já pode mandar o visitante para o seu idioma. Ativas isso e quem aterra na tua página inicial vai para o teu site no seu idioma antes de se desenhar seja o que for. Só a página inicial, por isso um motor de busca continua a chegar direto a qualquer página do teu site.
Um site servido a partir de uma subpasta funciona. Dizes ao Verbaly qual é a pasta e os links dentro de cada idioma apontam para onde devem, em vez de apontarem para o nada em silêncio.
Uma página chamada /es-la-guia é uma página, não espanhol. O Verbaly lia o início de um endereço com demasiada vontade, por isso uma página cujo nome começava como um código de idioma podia ser traduzida para esse idioma. Agora só conta um código de idioma a sério.
O que esta versão não muda: uma app com um só endereço por página funciona exatamente como antes. Tudo isto é para sites onde cada idioma tem o seu próprio endereço.
Adicionado · 3
A way to ask which language the address says, which answers nothing when the address says none
An option that sends someone landing on your home page to their language, before anything is drawn
Support for a site served from a subfolder, in the address helpers and in the pages Verbaly writes
Corrigido · 1
A page whose name begins like a language code is no longer read as that language
O Verbaly publica o teu site estático em cada idioma, em /es/ e /pt/. Esta versão é sobre o que acontecia a quem chegava a uma dessas páginas: chegava em espanhol e piscava para inglês antes de voltar, nada dizia ao runtime que já estava numa página em espanhol, e todos os links apontavam para fora. A página estava certa e tudo o que havia entre ela e o visitante, não.
Destaques
Uma página pré-traduzida deixa de piscar para inglês. O Verbaly servia a página em espanhol e depois pintava o texto em inglês por cima até o catálogo espanhol acabar de carregar, precisamente nas páginas que esta funcionalidade existe para manter quietas.
Aterrar em /es/ já chega. O Verbaly lê o prefixo que ele próprio escreveu antes de olhar para o armazenamento ou para o navegador, porque a página que estás a ver já está nesse idioma.
Cada idioma deixa de ser uma ilha. Os seus links apontavam para a raiz do site, por isso chegar em espanhol e clicar uma vez devolvia-te ao inglês. Os links para páginas que esse idioma também tem ficam agora lá dentro.
O teu seletor de idioma leva ao teu site nesse idioma. É esse o endereço que se pode partilhar e o que os motores de busca indexam, e a página chega já traduzida, por isso não pisca nada. Numa app com um só endereço por página, mudar de idioma continua a mudar apenas o texto, tal como antes.
O que esta versão não faz: não encaminha ninguém. Quem aterra na tua raiz está a receber o idioma de origem, e mandá-lo para o seu idioma é uma regra na configuração do teu alojamento.
Adicionado · 3
A helper that gives you the same page in another language, which is what a language switcher needs on a mirrored site
A warning when the page language and your instance disagree, because that combination is always a flash
An end to end test that builds a site and walks a visitor through the pages it wrote
Alterado · 3
The DOM binder no longer repaints text it did not write while the catalog for that language is still loading
Locale detection reads the url first, then storage, then the browser
Mirrored redirect pages send you to the mirrored target, not to the root one
Corrigido · 3
The runtime undid the work of the pre-render on every mirrored page
Locale detection ignored the language prefix Verbaly had written itself
A link inside a translated message could stop the pre-render with an internal error
O gate do build recusa-se a compilar quando uma tradução não consegue renderizar o que a sua fonte renderiza, mas só vê o que está no seu projeto na hora de compilar. Esta versão vai atrás de tudo o que chega depois: um catálogo vindo de um gestor de conteúdos, um ficheiro de código que o Verbaly não conseguiu ler e uma quebra de linha dentro de uma mensagem com formatação sobre a qual a página pré-renderizada e o navegador discordavam. Quatro erros reais, cada um uma forma de publicar algo errado com todos os comandos verdes.
Destaques
Uma quebra de linha dentro de uma mensagem com formatação já não duplica numa página pré-renderizada. O Verbaly escrevia-a de uma forma que os navegadores leem como duas quebras, e a página substituía-as por uma ao carregar. Um salto visível, justamente nas páginas que essa funcionalidade existe para manter quietas.
Uma tradução que chega como null já não derruba a sua aplicação ao arrancar. Um campo que ninguém preencheu num gestor de conteúdos parava tudo antes do primeiro render. Agora essa chave é ignorada, a aplicação corre e a consola diz-lhe qual era.
Os comandos sobrevivem a um ficheiro que não conseguem ler. Um ficheiro com um erro de sintaxe terminava a execução inteira com uma posição e nenhum nome de ficheiro. Agora o ficheiro é nomeado, os seus textos são ignorados e todos os outros continuam a ser lidos.
O texto dentro de JSX escrito num ficheiro .js é encontrado como em qualquer outro sítio. Uma aplicação React com componentes em .js não conseguia sequer correr o comando extract, porque a primeira etiqueta o terminava.
Um aviso já não se repete porque um número mudou. Três deles imprimiam o valor que os causava, por isso um contador a subir podia encher a memória de cópias da mesma mensagem.
Adicionado · 3
One shared list of the HTML tags that take no children, read by every surface that renders rich text
A test that renders the same messages through the static output and through the browser and compares the two, the one that caught the line break bug
Files the parser cannot read are now reported by name, by the extract command, by doctor and by the build plugins
Alterado · 4
A catalog value that is not text is skipped with a warning naming its path, instead of crashing or disappearing
Every warning names the message it came from, and none of them prints the value that caused it
Files ending in .js are read with JSX support, the same as .jsx and .tsx
Counts in the command line read as text, so nothing says "1 messages" any more
Corrigido · 5
The pre-rendered page and the live page disagreed about line breaks inside rich messages
A null value in a catalog stopped the app before its first render
One unreadable file ended the extract, check and doctor commands
Three warnings could repeat forever as the value that caused them changed
The review command accepted a locale option that its help never mentioned
O pacote do compilador deixava você importar 132 coisas diferentes, e nenhuma estava escrita em lugar nenhum. Elas foram se acumulando conforme os pacotes de framework precisavam, e na versão 1.0 cada uma teria virado uma promessa que ninguém nunca revisou. Esta versão lê a lista inteira contra uma regra escrita, publica as 60 que passam, documenta elas e adiciona um teste que falha se a lista voltar a crescer sem querer.
Destaques
Se você usa a linha de comando ou qualquer um dos pacotes de framework, esta versão não muda nada para você. Nem configuração, nem imports, nada para editar. Tudo aqui acontece dentro de um pacote que só as integrações feitas à mão alcançam.
O pacote do compilador agora documenta o que você pode importar, em dois grupos: os tipos que o seu arquivo de configuração e o seu próprio provedor de tradução precisam, e as peças para construir uma integração que nós não publicamos. Todo o resto é interno e agora diz isso.
A lista foi de 132 nomes para 60. Cada um ficou porque uma integração real usa, porque é uma forma documentada de estender o Verbaly, ou porque outro precisa dele. Os 72 que não atendiam a nenhuma das três não estão mais lá.
Um plugin de build já não recebe a árvore interna com que o Verbaly lê o seu código. Antes chegava inteira só para ler dois campos dela, e agora ele recebe as mensagens que encontrou. Uma coisa menos que pode quebrar quando esse leitor mudar.
Os dois pacotes falham no próprio teste se a lista crescer, então tornar algo público é agora uma decisão que alguém revisa, em vez de algo que acontece no caminho de consertar outra coisa.
Adicionado · 3
A test in the compiler package and another in the runtime that pin the exact list of public names, each one verified to fail on an extra export before being trusted
A "Programmatic API" section in the compiler package readme: the two groups, every name by area, and a minimal plugin example
The custom-provider example now shows the type that describes it, and mentions that providers also receive the source files each text appears in
Alterado · 3
The per-file build step hands a plugin the messages it found instead of the internal parse tree
72 names are no longer importable from the compiler package; the command line covers the same ground
Nothing in the runtime moved, and nothing about what Verbaly renders changed
Corrigido · 1
Four test files were being measured against the budget for a quick test while they load the real compiler, which could fail a release at random
O Verbaly já se recusava a compilar quando uma tradução não conseguia renderizar o que a tua origem renderiza. Esta versão fecha a mesma história pelo outro lado: cada sítio onde o Verbaly fazia o seguro sem dizer nada agora avisa-te, no momento em que podes agir. Um plural que renderiza uma linha vazia, um preço sem moeda, um bloco escrito onde não pode funcionar e um nome importado de onde não existe: quatro formas de publicar o texto errado com tudo verde.
Destaques
Um plural sem caso geral agora avisa no navegador, não só na build. A verificação da build já o recusava, mas um catálogo que chega por carregamento diferido ou de um gestor de conteúdos nunca passa pela build, por isso a linha vazia ainda podia chegar a uma página real. Agora nomeia a mensagem e diz-te o que acrescentar.
Um marcador sem o seu argumento deixa de renderizar um número seco. Um preço sem código de moeda, uma medida sem unidade, uma data sem unidade de tempo: cada um imprimia o valor simples e calava-se. Agora cada um diz o que precisa e mostra a forma da correção.
Escrever um plural dentro de um template t já não é publicado com as chaves à vista. Nesse template os valores vêm do teu código, por isso um plural ou um formato escrito ali torna-se texto que os teus utilizadores veem. O verbaly extract e o verbaly doctor apontam agora o ficheiro e o texto exato.
Importar t do pacote recebe finalmente uma resposta que menciona o Verbaly. O t vem da tua instância ou do módulo gerado, nunca do pacote, e até agora só o bundler se queixava, com uma mensagem que não dava pista nenhuma de onde o t devia sair.
Cada erro da linha de comandos imprime o seu nome uma vez. Antes toda a falha lia-se [verbaly] [verbaly].
Adicionado · 3
The runtime reports every way a message can degrade, naming the message: a plural with no catch-all case, a placeholder missing its argument, a list that is not a list
verbaly extract and verbaly doctor point at a message that kept a plural or a format as literal text
The doctor reports t imported from a verbaly package, with the line that says where it really comes from
Alterado · 3
The doctor fails on setup faults that break a build on their own, and never on something that builds and renders
The relative-time warning names both suspects instead of blaming the time unit for what is often an invalid date
Nothing about what Verbaly renders changed: this version only adds the report
Corrigido · 2
Every error from the command line printed its name twice
A test that starts an external process was being measured against the budget for a quick one, which could fail a release at random
Um comando dizia que o projeto estava saudável enquanto outro bloqueava o build pelos mesmos arquivos. O doctor rejeitava catálogos escritos como grupos aninhados, mesmo o runtime sempre os tendo lido, e dizia a um projeto Astro ou Nuxt para instalar o pacote que o comando de setup tinha acabado de desaconselhar. O gate do build lia qualquer palavra entre sinais de menor e maior como markup, e derrubava traduções corretas por causa disso. Tudo isso agora conta a mesma história: o que um comando te diz é o que o seu projeto é.
Destaques
verbaly doctor para de contradizer o verbaly check. Uma tradução que está lá mas está quebrada agora também é um erro no doctor, então o comando que você roda quando algo parece errado não pode mais responder "o setup parece saudável" num projeto cujo build falha.
Catálogos escritos como grupos aninhados funcionam em todo lugar. O doctor os rejeitava como inválidos, e o gate só comparava os nomes dos grupos, então um grupo com uma linha sem tradução dentro contava como totalmente traduzido. Agora cada linha é checada sozinha, do jeito que o runtime já a lia.
O doctor aponta o pacote que o seu projeto realmente precisa: Astro, Nuxt, Next.js, SvelteKit, Vite ou o plugin do seu bundler. É a mesma resposta que o verbaly init dá, porque os dois agora leem uma tabela só.
O build para de falhar por texto que só parece markup. "Press <Enter> to continue" traduzido como "Pulsa <Intro> para continuar" era reportado como duas tags quebradas. Uma tag conta como estrutura só quando a mensagem a fecha, então a sua prosa continua prosa e uma tag de ênfase ou um link de verdade seguem protegidos.
Cada falha nomeia o passo que a repara, em vez de um único "rode extract" que só consertava as traduções que faltavam. E desligar a checagem de faltantes agora significa o que diz: você pode buildar com texto sem tradução, e o Verbaly continua se recusando a publicar uma tradução que renderiza errado.
Um valor que falta diz de qual mensagem veio. O aviso imprimia só o nome do placeholder, uma vez por nome, então a segunda mensagem com a mesma lacuna ficava calada.
Adicionado · 3
The doctor reports translation health: broken translations as an error, plural warnings as advice, in the same place it already reported the missing ones
The doctor explains a project with source scanning off, and stops guessing about orphan keys and types it cannot know about
One table maps your framework to the package that wires it, read by both verbaly init and verbaly doctor, covering Nuxt, Next.js, SvelteKit, Astro, Vite and the bundlers
Alterado · 5
The gate and the coverage report read every catalog the way the runtime does, so nested groups are counted line by line instead of by group name
A tag is only checked when the message closes it, so ordinary text with angle brackets is free to be translated
Turning off the missing check no longer turns off the rest of the gate: unknown keys and broken translations still block the build
Every failure prints the step that repairs it, in the build gate and in verbaly check
A missing value warns once per message, naming it, instead of once per placeholder name
Corrigido · 1
A stray invisible character made one compiler source file unreadable to git, which had been hiding its diffs since it was added
O gate do build deixa de confiar numa tradução preenchida
Até agora o check fazia uma única pergunta: existe um valor para cada key? Uma tradução podia deixar de fora o seu placeholder de nome, perder uma tag de ênfase ou achatar um bloco de plural, e o build seguia verde enquanto produção mostrava em silêncio o texto errado, ou nada. Agora o gate lê cada tradução contra o original e falha diante de tudo que não consegue mostrá-la, com o motivo em palavras simples e a linha do fonte para clicar. O runtime deixa de silenciar o mesmo tipo de bug, e o pacote de React fica verificado contra o Preact.
Destaques
O build agora pega traduções que existem mas estão quebradas. Um placeholder que falta, uma tag perdida, um bloco de plural transformado em texto simples, ou um plural sem caso curinga: cada um para o build com uma frase dizendo o que aconteceu e por que importa. Antes disto, um catálogo editado à mão não tinha verificação nenhuma.
O bug do texto vazio acabou. Um bloco de plural que perdia o caso curinga não mostrava nada para cada quantidade que não listava. Em polonês, uma mensagem com só "one" e "few" mostrava uma string vazia para 5 itens. Isso agora falha o build em vez de ir para produção.
O Verbaly diz a quem traduz quais formas plurais o idioma realmente precisa. Um catálogo polonês ou russo com só duas formas recebe um aviso nomeando as que faltam. É um conselho, não uma falha: o texto ainda é mostrado. As formas que nenhum contador real alcança nunca são pedidas, então espanhol, francês, português e italiano ficam em silêncio.
verbaly status mostra uma contagem de quebrados por idioma, então você vê o estado de um catálogo sem rodar o gate.
Um valor que falta agora avisa no console. Mostrar um placeholder cru porque ninguém passou o valor era o único caso de dado ruim que o Verbaly não reportava. Todos os outros já reportavam.
O Preact funciona, e agora está provado. O pacote de React roda a suite completa uma segunda vez com o React resolvido para preact/compat: hooks, troca de idioma, texto rico e render no servidor passam todos. Sem pacote separado e sem mudanças no seu código.
O VS Code pode mostrar as suas traduções ao passar o mouse. O README do repositório traz a configuração do i18n-ally que transforma as keys com hash em texto legível enquanto você programa.
Adicionado · 4
Structural validation of catalogs: every translation is read against its source, and each finding is either an error that fails the build or a warning that only prints
A broken count per language in verbaly status, in the text output and in --json
Preact verification in the React package: the same suite, run again through preact/compat
The i18n-ally editor setup in the README, so hashed keys read as real text in VS Code
Alterado · 3
Imports and machine translations are held to the same stricter standard: a flattened plural block or one that would render empty is now rejected too
t() warns once when a value is missing instead of quietly leaving the placeholder in your text
The verbaly_missing agent tool reports broken translations and warnings, not only missing ones
Seu agente de código já pode rodar todo o ciclo de tradução
Um novo servidor MCP dá ao Claude Code, ao Cursor e a qualquer cliente MCP quatro ferramentas: ver a cobertura, listar o que falta, extrair texto novo e traduzir as lacunas por máquina. Tudo o que o agente traduz continua esperando sua revisão. Uma Agent Skill pública e um llms.txt na documentação completam o canal, projetos Nuxt mantêm a raiz limpa e trechos de código que só são exibidos não podem mais virar chaves fantasma.
Destaques
O ciclo de tradução como ferramentas de agente. Um comando (claude mcp add verbaly -- npx -y @verbaly/mcp) e seu agente de código pode conferir a cobertura, listar traduções faltantes, extrair texto novo e preencher as lacunas com tradução de máquina. O que ele traduzir é salvo como rascunho, então nada é publicado sem uma pessoa dizer que sim.
Uma Agent Skill pública ensina Verbaly ao seu agente. Instale skills/verbaly do repositório no seu projeto e o agente conhece o ciclo de escrever, extrair, verificar e traduzir, e as regras que o mantêm seguro.
A documentação agora fala LLM. Este site publica um índice llms.txt, assim os agentes que leem documentação se orientam no Verbaly sem raspar HTML.
Projetos Nuxt mantêm a raiz limpa. Os tipos gerados agora vivem dentro de .nuxt/ e se registram sozinhos, exatamente como a integração do Astro já fazia. Nenhum arquivo na raiz do projeto e nenhuma mudança no tsconfig.
Código que só é exibido não pode mais virar uma chave de tradução. Páginas que mostram exemplos de t como texto visível em arquivos Vue, Astro ou Svelte corriam o risco de esses trechos serem extraídos como chaves reais. Agora só conta o código dentro de expressões de verdade.
Adicionado · 4
@verbaly/mcp: an MCP server with verbaly_status, verbaly_missing, verbaly_extract and verbaly_translate; failures come back as actionable messages, never a crashed server
A public Agent Skill in the repository (skills/verbaly), installable into any project
An llms.txt index on the docs site, generated from the real navigation
New compiler exports collectOrigins and resolveProvider for tooling built on the cycle
Alterado · 2
The Nuxt module writes the generated types into .nuxt/ and registers them automatically; an explicit dts option still wins
Markup extraction in .vue, .astro and .svelte files counts only expressions; plain display text is never extracted
Gettext PO, placeholders protegidos e um runtime mais sólido
O kit para tradutores está completo: exporte e importe arquivos gettext PO, e o XLIFF agora protege seus placeholders e tags para que um tradutor não consiga quebrá-los por acidente. O nome custom do sitemap no render enfim funciona, um crash raro com datas inválidas sumiu, e o runtime não pode mais crescer em silêncio acima do seu orçamento de tamanho.
Destaques
Exporte e importe arquivos gettext PO. verbaly export --format po escreve um arquivo .po por idioma, pronto para Poedit, Weblate ou qualquer editor PO. verbaly import os lê de volta com a mesma rede de segurança de todos os formatos: uma tradução que quebra um placeholder é rejeitada, não publicada. Entradas que uma ferramenta marca como fuzzy contam como não traduzidas.
Tradutores não podem mais quebrar seus placeholders no XLIFF. Placeholders e tags viajam como códigos protegidos com nomes com sentido, então as ferramentas de tradução os mostram como fichas intocáveis em vez de texto editável. As palavras de plural e select seguem editáveis de propósito: essas sim se traduzem.
Nomes custom de sitemap agora funcionam. Configurar um nome próprio para o sitemap no render era ignorado: sempre escrevia sitemap-i18n.xml. O nome que você configura é o nome que você recebe.
Um crash raro sumiu. Passar uma data inválida a uma mensagem podia lançar um erro em vez de degradar com graça. Ele foi encontrado por uma suíte nova de testes aleatórios que castiga o parser com lixo em cada execução, então essa classe de bug fica corrigida.
O runtime não pode mais crescer em silêncio. Cada push mede o bundle do core e falha se ele passar do orçamento de tamanho. A promessa de ~3 KB é garantida por uma máquina, não por um costume.
Adicionado · 4
verbaly export --format po and .po import: gettext PO with the catalog key as context, source locations as comments and fuzzy entries respected
XLIFF exports protect placeholders and tags as inline codes with semantic names; imports reconstruct them exactly
A size gate in CI: the core bundle is measured (min+gzip) on every push and the build fails over budget
Property-based tests: parser and formatter are exercised with random input on every run and must never crash
Corrigido · 2
A custom sitemap filename in render was ignored and always wrote sitemap-i18n.xml
An invalid date passed to a message threw an error instead of degrading with a warning
Traduções por máquina que você revisa antes de confiar
As traduções por máquina agora chegam como rascunhos que você revisa, não como trabalho pronto em que confia às cegas. Um comando novo as aprova, o gate do CI pode esperar um humano, e o modelo traduz com contexto do seu código.
Destaques
A saída da máquina é um rascunho até você dizer o contrário. verbaly translate continua preenchendo as lacunas, mas tudo o que escreve fica marcado como rascunho sem revisar. Seus catálogos ficam tão limpos quanto antes: o estado de revisão vive num arquivo .verbaly-drafts.json à parte, ao lado deles.
Aprove as traduções depois de lê-las. verbaly review lista tudo o que espera um humano; verbaly review --approve aceita, tudo ou um idioma por vez. Importar o arquivo de um tradutor também conta como revisão, então a marca de rascunho se limpa sozinha.
Bloqueie merges com texto de máquina sem revisar. verbaly check --drafts faz o CI falhar enquanto restar alguma tradução por máquina sem revisar. O verbaly check normal não muda, então nada quebra até você ativar.
Traduções melhores, porque o modelo recebe contexto. verbaly translate agora diz ao provider em quais arquivos fonte cada texto aparece, então o tom e o tamanho combinam com onde o texto é usado.
Veja o que falta revisar num relance. verbaly status (e --json) agora reportam quantos rascunhos sem revisar há por idioma.
Adicionado · 5
A .verbaly-drafts.json sidecar next to the catalogs records which keys are unreviewed machine translations; catalogs stay plain flat JSON
verbaly review: list drafts awaiting review; --approve accepts them, optionally per --locale
verbaly check --drafts: opt-in CI gate that also fails while unreviewed drafts remain
Translation requests carry the source files of each text, so providers translate with context
verbaly status (and --json) report the unreviewed draft count per locale
Alterado · 3
verbaly translate marks everything it writes as a draft
verbaly import clears the draft flag for imported keys: a human file is reviewed by definition
Locale discovery ignores dotfile sidecars, so the drafts file never becomes a phantom locale
Suporte a Astro, um codemod wrap e anotações no CI
O Astro entra para a família: uma linha conecta tudo e o rendering por idioma roda sozinho. Um novo comando wrap envolve seu texto JSX hardcoded por você, e as falhas de CI viram anotações direto nos seus pull requests.
Destaques
Suporte a Astro, uma linha. Adicione verbaly() às integrations do astro.config e tudo fica conectado: extração ao vivo enquanto você programa, chaves type-safe e o gate do build. As chaves tipadas vivem dentro da pasta .astro própria do Astro, então nenhum arquivo extra cai no seu projeto. No fluxo de espelho, verbaly render roda sozinho depois de cada build.
Escreva seu texto direto em arquivos .astro. O mesmo t`…` que você já usa em .js, .tsx, .svelte e .vue agora funciona no frontmatter e no markup dos componentes Astro.
Migrando um app existente? Deixe o verbaly wrap fazer a parte chata. Ele escaneia seu JSX, encontra o texto visível hardcoded e o envolve em t`…` por você. Primeiro reporta; nada é tocado até você passar --write.
As falhas de CI agora apontam para o seu código. verbaly check --reporter github transforma cada tradução faltando em uma anotação no arquivo e na linha exatos, direto no pull request.
verbaly status --json entrega os números de cobertura em formato machine-readable, prontos para badges e dashboards.
Adicionado · 7
@verbaly/astro: a thin Astro integration wiring the Vite plugin and running verbaly render after static builds (opt-in, never on path-based i18n routing)
.astro extraction: frontmatter and markup, same strict scanner as .svelte/.vue; the default include covers the extension
verbaly wrap: JSX/TSX onboarding codemod with report-first flow, --write to apply, and a "needs a human" list for ambiguous cases
verbaly check --reporter github: failures as workflow annotations with source file and line; githubCheckAnnotations exported for tooling
verbaly status --json: machine-readable coverage
verbaly init detects Astro projects and points at the integration
A dts config option: move the generated types file anywhere, or turn it off with dts: false
Alterado · 1
The Vite and unplugin transforms now respect the config include/exclude: only files the CLI would scan get rewritten, and include: [] turns source scanning off entirely
Corrigido · 1
A raw NUL byte in a compiler source file made git treat it as binary (no reviewable diffs); replaced with the escape
RTL automático, nomes de idioma reais e contexto para tradutores
Adicionar árabe ou hebraico agora simplesmente funciona: a direção da página segue o idioma em todo lugar. Seletores de idioma recebem nomes reais da plataforma, e os arquivos de tradução dizem onde cada texto vive.
Destaques
Idiomas da direita para a esquerda simplesmente funcionam. Adicione árabe, hebraico ou persa e a direção da página segue o idioma por conta própria: quando o usuário troca, quando o servidor renderiza e nas páginas estáticas pré-renderizadas. Sem atributo dir para administrar, nunca.
Seletores de idioma sem nomes fixos. localeName('es') devolve 'español' e localeName('de', 'en') devolve 'German'. Os nomes vêm da plataforma, então qualquer locale funciona sem manter uma tabela.
Precisa da direção você mesmo? localeDirection('ar') devolve rtl. É o mesmo helper que o resto do toolkit usa, exportado para os seus próprios layouts.
Tradutores agora veem onde cada texto vive. O verbaly export marca cada mensagem com os arquivos fonte de onde veio: o XLIFF recebe notas de localização padrão e o CSV uma coluna de localização, então o contexto deixa de ser adivinhação.
Adicionado · 4
localeDirection(locale): ltr or rtl for any locale, script-aware, never throws
localeName(locale, displayIn?): localized language names via Intl.DisplayNames, endonym by default
Source-file locations in translator exports: XLIFF location notes and a CSV location column
%verbaly.dir% placeholder for SvelteKit's app.html, next to %verbaly.lang%
Alterado · 3
switchLocale and persistLocale now set <html dir> alongside <html lang>
verbaly render writes dir on each mirrored page; the Nuxt module keeps it in sync live
CSV export header is now key,source,target,location; files in the old three-column shape still import fine
Chaves literais e páginas pré-renderizadas mais seguras
Mensagens rich finalmente podem mostrar uma chave literal, e páginas pré-renderizadas com verbaly render aplicam as mesmas regras de segurança do navegador.
Destaques
Mensagens agora podem mostrar chaves literais. Escreva { e } em uma mensagem rich e elas renderizam como { e }. Formas hex como { também funcionam, no navegador, em cada <Trans> e em páginas pré-renderizadas.
Páginas pré-renderizadas agora são tão seguras quanto o navegador. Atributos traduzidos passam pelos mesmos guards, então links inseguros e atributos perigosos de um catálogo nunca chegam ao HTML estático.
Adicionado · 2
Numeric character references ({, {) decode in rich text: bindDom, every <Trans> and verbaly render
safeAttribute(name, value): the attribute guard as a public core helper, shared by bindDom and verbaly render
Alterado · 1
Internal: render link handling reuses normalizeLink, the same helper every adapter uses
Corrigido · 1
verbaly render now applies the runtime attribute guards: unsafe URLs are blocked and style/srcdoc are never written from translations
Um <Trans> para tudo, extração ao vivo e uma visão de cobertura
Os componentes <Trans> de React, Vue e Svelte agora compartilham as mesmas props e as mesmas regras de render, a CLI aprende dois comandos do dia a dia e os últimos breaking changes planejados chegam antes da 1.0.
Destaques
<Trans> agora é o mesmo componente em React, Vue e Svelte: mesmas props, mesmas regras de render. Seu componente próprio vence, depois os links nomeados, depois a whitelist segura de tags; o desconhecido vira texto puro.
Breaking: os <Trans> de React e Vue agora renderizam tags da whitelist como em e code como elementos reais, igual ao Svelte e ao interpretador de DOM. Passe uma lista richTags vazia para manter o comportamento antigo de achatar para texto.
Breaking: @verbaly/svelte agora exige Svelte 5. Em troca o <Trans> ganha a prop components: mapeie um tag da mensagem para o seu próprio componente. No Svelte 4, fique na 0.22.0.
verbaly status mostra quanto falta traduzir, uma linha por idioma, sem falhar nada. verbaly check continua sendo o gate do build.
verbaly extract --watch mantém catálogos e tipos em dia enquanto você escreve código, pensado para setups de webpack, Rspack e Rollup onde o plugin do Vite não está disponível.
Dar feedback ficou mais fácil: o README leva os reportes de bugs e de atrito ao lugar certo, e os formulários de issues cobrem os dez pacotes.
Adicionado · 3
components prop on the Svelte <Trans>; instance and richTags props on React and Vue
verbaly status: per-language translation coverage, informational only
verbaly extract --watch: re-extracts as source files change, with the building block exported as watchProject
Alterado · 3
React and Vue <Trans> render whitelisted tags as real elements (breaking; an empty richTags list restores the old behavior)
@verbaly/svelte requires Svelte 5 (breaking); the shipped components moved to runes
An extract that changes nothing no longer rewrites catalog files, so file watchers stay quiet
O comando export aprende dois formatos mobile: pastas de recursos do Android e arquivos de strings do iOS. Um app web e seu companheiro mobile agora podem compartilhar um único conjunto de traduções.
Destaques
Exporte suas traduções para apps mobile: verbaly export --format android-xml escreve pastas que você pode soltar em res/, e --format ios-strings escreve pastas .lproj para o Xcode.
Padrões sensatos por plataforma: seu idioma fonte vira o padrão da plataforma, e as keys sem tradução ficam de fora para o app cair nele em vez de mostrar texto vazio.
Catálogos mais seguros: um catálogo com JSON quebrado agora para o comando e aponta o arquivo, em vez de ser lido em silêncio como vazio. Um BOM do Windows no início do arquivo é simplesmente tolerado.
Adicionado · 1
Two export formats in @verbaly/compiler: android-xml (Android resource layout, keys adapted to valid resource names) and ios-strings (one .lproj folder per locale)
Alterado · 2
A corrupt catalog file fails with a clear error naming the path; before, it was read as empty and a later extract could have lost translations
--missing is rejected for the mobile formats with a message explaining why: mobile output already skips untranslated keys
Uma limpeza a fundo nos dez pacotes, mais opções totalmente tipadas na sua config do Nuxt. Os internos ficaram mais organizados e um pouco menores, sem mudar como você escreve Verbaly.
Destaques
A key verbaly do nuxt.config.ts agora é totalmente tipada: você tem autocomplete e checagem de typos, e o módulo continua sem somar dependências.
Um editor mais calmo no dev. verbaly.d.ts só é reescrito quando o conteúdo realmente muda, então seu servidor TypeScript para de recarregar tipos a cada salvamento.
Um runtime um pouco menor: o core tree-shaken agora pesa 3.28 KB gzip, antes 3.30.
Tipos gerados mais limpos: um valor usado como data e como texto puro já não aparece duas vezes em verbaly.d.ts.
Mensagens da CLI mais claras. Cada erro e dica se lê em palavras simples, e o check agora imprime o texto fonte bem ao lado da key faltante.
Alterado · 3
A quality pass across the whole codebase: shared plugin code lives in one place, dead code is gone, and hot paths are simpler, with the full test suite green
Breaking, advanced only: the compiler helpers generateDts and writeDts take the catalog object directly instead of a Map. The command line and every bundler plugin are unaffected
Dev tooling updated to the latest stable (tsdown, typescript-eslint)
Escreva seu texto também em arquivos .svelte e .vue
O texto natural agora funciona dentro de componentes Svelte e Vue: escreva no arquivo, script ou markup, e o compilador extrai com key estável e params tipados.
Destaques
Escreva t`Hello ${name}` diretamente em um template .vue ou {$t`Hello ${name}`} em markup .svelte. O compilador detecta como sempre fez em arquivos .ts: key estável, params tipados, catálogos por idioma.
A forma store do Svelte é entendida: $t`…`, $t('key') e $t.id('key')`…` funcionam em qualquer parte de um arquivo .svelte.
Ao vivo no dev, com gate no build: salve um componente com texto novo e os catálogos mais verbaly.d.ts se atualizam na hora. Traduções faltantes continuam parando o build.
Keys legíveis e keys de runtime também funcionam no markup: t.id('home.title')`…` extrai sob a sua key, e chamadas t('key') contam como keys usadas para o check e o prune.
verbaly extract varre mais por padrão: arquivos .svelte e .vue, mais a pasta app/ ao lado de src/ (onde vivem o Nuxt 4 e o App Router do Next.js). Seu próprio include continua vencendo.
Adicionado · 2
SFC extraction in @verbaly/compiler: .svelte and .vue files are analyzed in full, script blocks and markup
@verbaly/vite and @verbaly/unplugin now transform .svelte/.vue sources
Alterado · 2
Rewrites inside component markup use single quotes, so bindings like :title="t`…`" stay valid
Default include is now {src,app}/** and covers .svelte/.vue; explicit configs are untouched
Next.js entra para a família: o ciclo está completo
A última grande integração de meta-framework. As páginas do App Router do Next.js renderizam já traduzidas, hidratam sem flash e funcionam no Turbopack e no webpack.
Destaques
Novo pacote @verbaly/next. Dois passos: envolva sua config com withVerbaly() no next.config.ts e solte <VerbalyProvider> no layout raiz. Server Components traduzem com await getT(); Client Components seguem usando useT e <Trans> como em qualquer app React.
Funciona no Turbopack (o padrão do Next 16) e no webpack. next dev extrai suas mensagens enquanto você digita, e next build para se faltar uma tradução.
Cada visitante recebe seu próprio idioma, resolvido uma vez por request a partir do cookie ou das preferências do navegador. As páginas chegam já traduzidas, nada pisca, e visitantes concorrentes nunca veem o idioma um do outro.
useSwitchLocale() troca o idioma na hora, lembra a escolha para a próxima visita e atualiza também os Server Components.
Mensagens rich agora podem exibir markup literal, então uma mensagem pode mostrar "<html lang>" como texto visível em vez de um escape quebrado.
Adicionado · 2
@verbaly/next, the 10th package: the withVerbaly config wrapper, a server API (getT, getVerbaly, getRequestLocale, getVerbalyProps), a client provider with useSwitchLocale, and the compiler as a loader for both bundlers
loadMessages(locale) in virtual:verbaly: the raw catalog that SSR integrations send to the client
Corrigido · 1
HTML entities decode inside rich text (core), so a message can display <html lang> literally and pre-rendered HTML round-trips cleanly
A segunda integração de meta-framework: um módulo Nuxt sem config renderiza cada página no idioma do visitante e hidrata sem flash.
Destaques
Novo pacote @verbaly/nuxt. Uma linha na sua config (modules: ['@verbaly/nuxt']) liga tudo: extração ao vivo, idioma por visitante e hidratação com o mesmo locale e catálogo que o servidor usou. Sem flash, sem mismatch.
Sem lock de framework: o módulo não depende nem de nuxt nem de @nuxt/kit, e é verificado contra um app Nuxt 4 real.
switchLocale() agora é um export do core compartilhado por SvelteKit, Nuxt e setups manuais. Carrega o catálogo primeiro e troca depois, então nada pisca. Os imports existentes continuam funcionando.
Apps client-only também estão cobertos: com ssr: false o módulo ainda escolhe o idioma certo no navegador.
Apoie o Verbaly: o GitHub Sponsors já está ativo em github.com/sponsors/AronSoto.
Adicionado · 2
@verbaly/nuxt, the 9th package: zero-config module plus a runtime plugin (per-request language, payload hydration, reactive <html lang>)
switchLocale / SwitchLocaleOptions (core)
Alterado · 1
@verbaly/sveltekit re-exports switchLocale from core, with identical API and behavior
A release de hardening: uma auditoria completa dos oito pacotes corrigiu cada aresta que encontrou, e o SSR ganha sua peça que faltava.
Destaques
A tradução de atributos agora é XSS-safe de ponta a ponta: data-verbaly-attr sanitiza atributos de URL e bloqueia style e srcdoc por completo, então um catálogo comprometido não consegue injetar scripts.
t() nunca quebra por argumentos de formato ruins: um código de moeda, data ou estilo de hora inválido avisa uma vez e renderiza o valor puro.
createRequestInstance(locale) no virtual:verbaly: o padrão SSR per-request em uma chamada, com o catálogo já carregado e sem flash.
A CLI agora rejeita flags fora de lugar. verbaly translate --locale es antes traduzia todos os idiomas em silêncio; agora dá erro e sugere --locales. Além de --dry-run para extract --prune.
normalizeLink() e resolveRequestLocale() agora vivem uma única vez no core, compartilhados por cada adapter e integração SSR.
Breaking:instance.inspect(key) agora retorna { from, source } em vez de { locale, source }: um só nome para um só conceito em toda a API de observabilidade.
Adicionado · 2
normalizeLink, resolveRequestLocale, LOCALE_STORAGE_KEY (core) and createRequestInstance (virtual:verbaly)
failOnMissing opt-out for the Vite build gate; --dry-run on verbaly extract
A primeira integração de meta-framework: páginas SvelteKit renderizam no idioma do visitante no servidor e hidratam sem flash.
Destaques
Novo pacote @verbaly/sveltekit. SSR em três fios: verbalyHandle() nos seus hooks de servidor, um load de +layout e %verbaly.lang% no app.html. As páginas chegam traduzidas.
O idioma é decidido por request: cookie primeiro, depois o header Accept-Language (es-PE casa com es), depois seu fallback. Requests concorrentes nunca vazam o idioma um do outro.
switchLocale(): um switch client-side que carrega o catálogo primeiro e depois salva a escolha no cookie que o servidor lê.
negotiateLocale() no core: o matcher de Accept-Language é um export público que qualquer servidor Node pode usar.
createInstance() no virtual:verbaly: instâncias frescas por request sobre seus catálogos compilados, mais os exports locales e sourceLocale.
Adicionado · 2
@verbaly/sveltekit, the 8th package: verbalyHandle + switchLocale
negotiateLocale (core) and SSR exports in virtual:verbaly
Alterado · 1
The Release workflow now resumes per package after a partial run
O ciclo write→ship se abre a humanos: exporte arquivos prontos para tradutores, importe de volta validados.
Destaques
verbaly export escreve um arquivo pronto para tradutores por idioma: XLIFF 2.0 para plataformas de tradução, CSV para planilhas. --missing exporta só o que falta traduzir.
verbaly import valida cada entrada: uma tradução que perde um placeholder, uma variante ou um tag é rejeitada e reportada.
As traduções existentes são mantidas a menos que você passe --overwrite, e --dry-run pré-visualiza o import inteiro.
Você não precisa de plataforma de tradução: os catálogos são JSON puro, e Crowdin, Lokalise e Phrase leem nativamente.
Adicionado · 2
verbaly export: translator-ready XLIFF 2.0 / CSV files per locale
verbaly import: a validated round-trip back into your catalogs
Alterado · 2
GitHub Release notes are now short: theme, highlights and a link to the full changelog
Community docs pass: SECURITY and CONTRIBUTING read friendlier