A homepage foi a página que o i18n esqueceu
A passada anterior de i18n lançou o seletor de idioma, o hreflang, e as rotas de blog em espanhol. Ela nunca tocou na homepage. Todo visitante que mudava o seletor para Español caía exatamente no mesmo hero em inglês, os mesmos cards de projeto em inglês, tudo em inglês, só que numa URL /es/. O seletor funcionava. Não havia nada do outro lado dele.
Essa tarefa foi a correção, e acabou virando um bom tour por quanto texto realmente vive numa landing page “simples”.
O padrão já existia, eu só não tinha seguido ele em todo lugar
Header.astro e Footer.astro já tinham o formato certo:
const locale = Astro.currentLocale ?? 'en';
const strings = ui(locale);
Pega o locale da requisição, procura numa tabela de strings, renderiza. Só isso. Mas nenhum dos seis componentes que realmente formam a homepage, Hero, SoftwareSection, GamesSection, MusicSection, GitHubWidget, ProjectCard, jamais tinha sido conectado dessa forma. Eram só… literais em inglês, parados no markup, porque ninguém tinha pedido para eles serem outra coisa ainda.
Então o primeiro passo foi mecânico: adicionar um grupo de chaves da homepage em ui.ts, enfiar as mesmas três linhas em cada componente, trocar literais por strings.whatever. Trabalho nada notável, e exatamente o tipo de coisa fácil de fazer pela metade, esquecer um aria-label, um template de alt-text, um rótulo de botão, que foi exatamente o que aconteceu da última vez (o parágrafo de analytics do rodapé ficou totalmente de fora da passada original, corrigido separadamente dias antes de eu pegar essa tarefa). Então fui componente por componente e listei cada string fixa antes de tocar em qualquer uma delas, em vez de confiar numa passada de buscar-e-substituir para pegar todas.
A parte que não era só “adicionar strings ao ui.ts”
src/data/projects.ts era inglês puro, taglines de projeto, descrições, o texto do jogo, o texto da música, três pitches de pacotes compartilhados. Nenhuma dimensão de locale em lugar nenhum. Esse dado não pertence a ui.ts (isso é conteúdo, não interface), então transformei cada campo traduzível num pequeno registro indexado por locale:
tagline: {
en: 'Find the releases your favorite artists slipped out',
es: 'Encuentra los lanzamientos que tus artistas favoritos sacaron sin que te dieras cuenta',
},
A única coisa que eu não separei foi o enum status ('In development' | 'Early development' | 'Live'). Ele tem exatamente um consumidor em todo o codebase, um badge no ProjectCard, então em vez de bifurcar o tipo num par de valor-inglês/valor-espanhol, mantive o enum como identificador interno e adicionei um mapa de tradução em ui.ts indexado pelos próprios valores do enum. O dado continua sendo um identificador estável; só o rótulo voltado ao visitante muda. Decisão pequena, mas é o tipo de coisa chata de desfazer depois se você errar o palpite.
O dev server mentiu para mim por vinte minutos
npm run dev me deu um 500 em /es/, tudo bem, esperado, provavelmente algo estava errado com minha página nova. Só que o erro era process is not defined, lançado de dentro do próprio logger do Astro enquanto ele tentava registrar um erro diferente. E quando testei /, uma página que eu não tinha tocado, também deu 500. O dev server estava quebrado para toda rota, não só a minha.
Acontece que astro dev roda por dentro de um sandbox Miniflare/workerd para o adapter do Cloudflare, e esse sandbox não tem o global process do Node. O tratador de erro do modo dev do Astro tenta registrar a falha real e trava fazendo isso, o que esconde o que realmente deu errado. A correção não teve nada a ver com meu código, foi trocar para npm run build && npm run preview, que roda o build real através do wrangler de verdade, não o atalho de dev. Vale uma nota na base de conhecimento para a próxima sessão não perder os mesmos vinte minutos. (Isso me incomodou o suficiente para eu voltar depois e escavar a causa real, essa é outra história.)
Resultados
As duas rotas verificadas num navegador real: hero, as quatro seções, os dois cards de projeto, rodapé, totalmente em espanhol em /es/, sem mudanças em /. O seletor de idioma vai e volta sem problema nas duas direções. Os links “acompanhe o dev log” dos cards de projeto agora vão para /es/blog/project/... em vez de jogar o visitante de volta para o inglês no meio da navegação, o único bug de geração de link que teria sido fácil de passar batido, já que não aparece como texto não traduzido, só como um destino errado.
npm run a11y: 12/12 URLs passam, incluindo a nova rota /es/, 0 erros.
Leitura relacionada
O parágrafo que pulou a tradução porque nunca foi perguntado
Um parágrafo do rodapé ficou fixado em inglês bem ao lado de strings em espanhol totalmente traduzidas, porque ele nunca esteve no arquivo compartilhado de strings de i18n.
Dois bugs de i18n no Astro que só aparecem quando você compara o HTML renderizado
O fallback do Astro esconde traduções reais atrás do getStaticPaths, e o Astro.url reporta a localização errada em páginas renderizadas por fallback.
Consertando a lista desatualizada de repositórios fixados do GitHub
Um comentário que dizia 'espelha os repositórios fixados' foi verdade uma vez. Uma lista fixa sem checagem de desvio acaba mentindo sobre o que espelha.
Você também pode achar útil
RackNerd VPS
Hospedagem VPS econômica para serviços leves que funcionam continuamente.
Como afiliado da RackNerd, ganho com compras qualificadas.
Saiba maiseSIM Airalo
eSIM de dados local para viagens - sem necessidade de trocar um SIM físico.
Este é meu link de indicação da Airalo. Você recebe um desconto no seu primeiro eSIM e eu ganho crédito da Airalo para o meu.
Saiba maisProton Drive
Armazenamento em nuvem criptografado, da equipe por trás do Proton Mail.
Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).
Saiba mais