i18n e Localizacao — Preparar Antes de Traduzir

SkillAI & models

Internationalization and localization, prepare the product for another language, region, or writing direction before a translator exists on the project. Use when building any UI that could receive another language, when formatting dates/numbers/currency, when handling plurals, when testing text exp

Available today. Use it from your connected AI after setup.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the i18n e Localizacao skill

What this skill tells your AI

The instructions your AI receives, as published by felvieira/claude-skills-fv in skills/58-i18n-localization/SKILL.md and read by ahel’s review.

Internacionalizacao (i18n) e trabalho de arquitetura, nao de tradutor. Se a string esta concatenada no meio do componente, a largura foi calculada para o portugues e a data foi montada com dia + "/" + mes, nenhuma traducao conserta — o codigo precisa mudar primeiro. Esta skill cobre o que fazer antes da primeira palavra ser traduzida.

Governanca Global

Esta skill segue GLOBAL.md, policies/execution.md, policies/handoffs.md, policies/token-efficiency.md, policies/stack-flexibility.md e policies/evals.md.

Para tabelas de expansao por idioma, exemplos de formatter por plataforma e receitas de teste, consultar docs/skill-guides/i18n-localization.md apenas quando necessario.

Fronteira com skills vizinhas:

  • 02-ui-ux-design define layout e tokens — esta skill impoe as restricoes que o layout tem de aguentar (texto que cresce, direcao que inverte)
  • 56-responsive-conversion conserta layout quebrado por largura de tela; aqui a quebra vem do conteudo (texto traduzido mais longo), com a mesma raiz de container que se recusa a crescer
  • 57-mobile-ux-foundations cobre escala de fonte do sistema; esta skill cobre o crescimento causado pelo idioma
  • 22-accessibility-specialist e dona do WCAG — lang/dir corretos e leitura por screen reader no idioma certo sao o recorte compartilhado
  • 13-marketing-copy e 50-direct-response-copy escrevem o texto; esta skill garante que o texto seja traduzivel sem reescrever o codigo

Quando Usar

  • construir UI que pode receber outro idioma, mesmo que hoje seja so pt-BR
  • formatar data, hora, numero, moeda, unidade ou nome
  • lidar com plural, genero ou ordenacao de texto
  • preparar suporte a RTL (arabe, hebraico, persa, urdu)
  • diagnosticar layout que quebrou depois de traduzir
  • auditar codebase existente antes de contratar traducao

Quando Nao Usar

  • escrever ou revisar o texto em si (isso e 13-marketing-copy ou 50-direct-response-copy)
  • traduzir conteudo — esta skill prepara o terreno, nao substitui tradutor humano ou servico de traducao
  • corrigir layout que quebra por largura de tela, sem relacao com idioma (isso e 56-responsive-conversion)
  • auditoria completa de acessibilidade (isso e 22-accessibility-specialist)

Entradas Esperadas

  • codebase ou componente alvo
  • locales que o produto precisa suportar (ou "nenhum ainda, mas quero preparar")
  • restricoes de dominio: moeda, formato legal de documento, fuso horario relevante

Saidas Esperadas

  • relatorio de auditoria: string hardcoded, concatenacao, formato fixo, largura rigida, uso de left/right
  • codigo corrigido com strings externalizadas e formatters por locale
  • checklist de i18n marcado
  • evidencia de teste em pseudolocale e RTL

Por Que Isso Nao Pode Ficar Para Depois

Retrofit de i18n custa muito mais que fazer certo desde o inicio, porque o problema nao esta nas strings — esta na forma como o codigo foi escrito:

Decisao tomada sem pensar em i18nO que quebra depois
"Ola, " + nome + "!"Ordem das palavras muda entre idiomas; a frase fica sem sentido
width: 120px num botaoAlemao e ~30% mais longo que o portugues; o texto corta
margin-left: 16pxEm RTL o espaco fica do lado errado
${dia}/${mes}/${ano}EUA le 08/03 como 3 de agosto, nao 8 de marco
count + " itens"Idiomas com 3+ formas de plural (russo, arabe, polones) ficam errados
Texto dentro de PNGPrecisa refazer a imagem por idioma
Ordenacao com sort() cruAcentos e alfabetos nao-latinos ordenam errado

Nenhum destes e resolvido por tradutor. Todos exigem mudanca de codigo.

Protocolo de Auditoria

Fase 1 — Encontrar o que esta preso ao idioma

# String literal em JSX/template (o suspeito principal)
grep -rnE '>[A-Za-zÀ-ÿ]{4,}[^<]*<' src/ app/ --include=*.tsx --include=*.jsx

# Concatenacao de frase
grep -rnE '"[^"]*" *\+ *[a-zA-Z_$]|\+ *" [a-z]' src/ app/

# Data/numero montados a mao
grep -rnE 'getMonth\(\)|getDate\(\)|toFixed\(2\).*R\$|"R\$ *" *\+' src/ app/

# Direcao fisica em vez de logica
grep -rnE 'margin-left|margin-right|padding-left|padding-right|text-align: *(left|right)|\b(ml|mr|pl|pr)-[0-9]' src/ app/

# Largura fixa (vai cortar texto mais longo)
grep -rnE 'width: *[0-9]{2,}px|w-\[[0-9]+px\]' src/ app/

Cada hit e candidato, nao bug confirmado — validar na Fase 2.

Fase 2 — Testar com pseudolocale, antes de existir traducao

Pseudolocale transforma Salvar em algo como [Ŝåṽåŕ ---]: mantem legivel, mas expande o texto e troca os caracteres. Revela de uma vez:

  • String hardcoded — o que nao muda nao esta externalizado
  • Falta de espaco — o texto expandido corta ou empurra o layout
  • Concatenacao — a frase montada aparece parcialmente pseudolocalizada
  • Problema de encoding — caractere acentuado vira ? ou caixinha

Android tem pseudolocales nativos (en-XA para expansao, ar-XB para RTL). Na web e em outras stacks, gerar o pseudolocale a partir do arquivo de strings resolve — a tecnica importa mais que a ferramenta.

Regra de dimensionamento: assumir +30% de expansao sobre o portugues como piso de teste. Texto curto (rotulo de botao) expande proporcionalmente mais que texto longo.

Fase 3 — Testar RTL

Nao basta espelhar tudo. Espelha o layout; nao espelha conteudo que tem direcao propria:

EspelhaNao espelha
Direcao da leitura e do fluxoNumeros
Posicao de sidebar, icone e labelGrafico com eixo temporal convencional
Seta de "voltar"/"avancar"Logo da marca
Barra de progressoIcone de relogio, de midia (play/pause)
Alinhamento de textoCodigo, URL, e-mail

O teste minimo e alternar dir="rtl" no root e percorrer o fluxo principal. O que usa propriedade logica (margin-inline-start) acompanha sozinho; o que usa margin-left fica errado — e esse e justamente o inventario da Fase 1.

Fase 4 — Corrigir pela causa

Ver o catalogo abaixo. Trocar margin-left por margin-inline-start um a um sem entender o padrao gera regressao na proxima tela.

Fase 5 — Reconferir Fase 2 e 3 apos o fix

Rodar pseudolocale e RTL de novo (não só no elemento corrigido — a troca de propriedade lógica pode ter afetado espaçamento vizinho). Se algo que passava antes do fix quebrou agora, o fix vazou escopo — revisar antes de considerar a correção concluída.

Catalogo — Problema, Causa, Correcao

1. String presa ao codigo

Toda string visivel ao usuario sai do componente e vai para arquivo de recurso, com chave semantica (checkout.confirmButton), nao a frase em si como chave (a frase muda; a chave nao deveria).

Interpolacao com variavel nomeada, nunca concatenacao:

Errado:  "Ola, " + nome + "! Voce tem " + n + " mensagens."
Certo:   t("home.greeting", { nome, count: n })
         // pt: "Ola, {nome}! Voce tem {count} mensagens."
         // ja: "{nome}さん、{count}件のメッセージがあります。"  ← ordem diferente

A ordem das palavras muda entre idiomas. Concatenacao fixa a ordem do portugues no codigo.

2. Plural

Portugues e ingles tem 2 formas (1 / outros). Russo tem 3, arabe tem 6, japones tem 1. if (n === 1) funciona em pt e quebra no resto.

Usar a API de plural da plataforma (Intl.PluralRules na web, plurals no Android, stringsdict no iOS) e deixar cada locale declarar suas proprias formas. Zero merece caso proprio quando o texto muda ("Nenhuma mensagem" em vez de "0 mensagens").

3. Data, hora, numero e moeda

Nunca montar a mao. O formatter da plataforma ja sabe a convencao de cada locale:

08/03/2026  → pt-BR: 8 de marco    en-US: 3 de agosto     ← mesma string, sentido oposto
1.234,56    → pt-BR                en-US: 1,234.56
R$ 1.000    → simbolo, posicao e separador variam por locale

Regras que evitam a maioria dos bugs:

  • Armazenar em formato canonico (ISO 8601 para data/hora, valor numerico + codigo de moeda), formatar so na exibicao
  • Guardar timestamp com fuso — data sem fuso vira dia errado na virada da meia-noite
  • Nunca traduzir o dado, so a apresentacao

4. Expansao de texto

Assumir que o texto vai crescer, e projetar para isso:

  • Container com min-width/min-height, nunca dimensao fixa
  • Botao cresce com o rotulo; linha de texto pode quebrar em duas
  • Truncamento com reticencias e ultimo recurso, e nunca em informacao essencial ou acao
  • Testar o rotulo mais longo real, nao o mais curto

Mesma raiz do bug de min-width: auto da skill 56 — container que se recusa a crescer — aqui disparado pelo idioma.

5. Direcao logica em vez de fisica

Fisico (quebra em RTL)Logico (acompanha)
margin-left / margin-rightmargin-inline-start / margin-inline-end
padding-left / padding-rightpadding-inline-start / padding-inline-end
text-align: lefttext-align: start
left / rightinset-inline-start / inset-inline-end
border-leftborder-inline-start

Tailwind: usar ms-*/me-*/ps-*/pe-* em vez de ml-*/mr-*/pl-*/pr-*.

6. Texto dentro de imagem

Texto em PNG/JPG nao e traduzivel sem refazer o arquivo, nao e lido por screen reader e nao escala com a fonte. Texto sobre imagem vai em HTML por cima; texto em SVG e traduzivel se estiver em <text>, nao vetorizado.

7. Ordenacao e busca

array.sort() cru ordena por code point: "Zebra" vem antes de "Ácido", e alfabetos nao-latinos saem embaralhados. Usar comparador sensivel a locale (Intl.Collator). Busca precisa decidir explicitamente se ignora acento e caixa — e o comportamento deve ser o mesmo para "cafe" e "café".

8. Formulario que assume um pais

Nome, endereco, telefone e documento variam por pais:

  • Nao exigir "sobrenome" — parte do mundo tem nome unico
  • Endereco: campos e ordem mudam; CEP nem sempre e numerico
  • Telefone: aceitar codigo de pais, nao presumir 11 digitos
  • Documento (CPF, SSN, NIF) e especifico de pais, nunca campo generico obrigatorio
  • Aceitar caractere nao-ASCII em nome — validacao [a-zA-Z] rejeita "José" e "أحمد"

9. lang e dir corretos

O atributo lang no root diz ao screen reader qual pronuncia usar e ao browser como quebrar linha. Trecho em outro idioma no meio da pagina leva lang proprio. dir acompanha o idioma. Sem isso, leitor de tela le portugues com fonetica inglesa — e isso e falha de acessibilidade, nao so de i18n.

Anti-Padroes

  • Deixar i18n "para quando internacionalizar" — o custo de retrofit e muito maior que o de fazer certo
  • Frase concatenada com variavel no meio
  • Chave de traducao sendo a propria frase em portugues
  • if (n === 1) como logica de plural
  • Data/moeda montadas com template string
  • Data sem fuso horario quando o horario importa
  • margin-left/text-align: left em produto que pode receber RTL
  • Largura fixa em botao ou rotulo
  • Truncar acao ou informacao essencial em vez de deixar quebrar linha
  • Texto embutido em bitmap
  • sort() cru em lista visivel ao usuario
  • Validar nome com [a-zA-Z]
  • Presumir que todo mundo tem sobrenome, CEP numerico ou telefone de 11 digitos
  • Traduzir com maquina sem revisao e mandar para producao
  • Espelhar numero, logo ou icone de midia em RTL

Checklist

Arquitetura:

  • Nenhuma string visivel hardcoded no componente
  • Chave semantica, nao a frase como chave
  • Interpolacao com variavel nomeada, sem concatenacao
  • Plural via API da plataforma, com caso proprio para zero quando o texto muda
  • Data/hora/numero/moeda via formatter de locale
  • Dado guardado em formato canonico; formatacao so na exibicao
  • Timestamp com fuso quando o horario importa

Layout:

  • Container com min-*, sem dimensao fixa em elemento com texto
  • Testado com +30% de expansao (pseudolocale)
  • Propriedade logica (inline-start/inline-end) em vez de left/right
  • Testado com dir="rtl" no fluxo principal
  • Numero, logo e icone de midia nao espelhados
  • Nenhum texto traduzivel dentro de bitmap

Dados e conteudo:

  • Ordenacao com comparador de locale
  • Busca com comportamento definido para acento e caixa
  • Formulario nao presume formato de nome, endereco, telefone ou documento de um pais so
  • lang e dir corretos no root e em trecho de outro idioma

Evidencia de Conclusao

  • relatorio problema → causa → correcao por ocorrencia
  • captura ou descricao do fluxo principal em pseudolocale, sem corte nem string nao traduzida
  • captura ou descricao do fluxo principal em RTL, sem elemento espelhado errado
  • checklist marcado, com item nao aplicavel justificado

Handoff

Recebe de

  • 02-ui-ux-design — layout e tokens que precisam aguentar texto que cresce
  • 04-frontend-integration — componentes implementados a auditar
  • 13-marketing-copy / 50-direct-response-copy — texto a externalizar

Entrega para

  • 56-responsive-conversion — quando a expansao de texto expoe bug de layout que vale corrigir na raiz
  • 22-accessibility-specialist — lang/dir e leitura por screen reader entram na auditoria WCAG
  • 05-qa-testing — pseudolocale e RTL viram teste de regressao, nao verificacao manual unica
  • 03-backend-api — formato canonico de data/moeda e o contrato da API, nao decisao de frontend

Regra de Codigo Limpo

Comentario so onde a regra de locale nao e obvia — por que um formato especifico foi fixado, ou por que determinado campo nao e obrigatorio em certo pais. Chave de traducao bem nomeada dispensa comentario.

Fontes

  • Pseudolocales e teste de bidirecionalidade: documentacao oficial do Android sobre localizacao.
  • Formatadores sensiveis a locale: Intl (ECMAScript), Foundation (Apple), bibliotecas equivalentes por plataforma.
  • Regras de plural por idioma: CLDR (Unicode Common Locale Data Repository).
  • Propriedades logicas de CSS: especificacao CSS Logical Properties (W3C).
  • lang/dir e leitura assistiva: WCAG 2.2 (criterios de idioma da pagina e de partes).

Integracao com Pipeline

  • Orquestrador (skill 09): aciona esta skill no inicio de produto com escopo multi-idioma, e antes de contratar traducao em produto existente
  • UI/UX Design (skill 02): dona do layout; esta skill impoe que o layout aguente texto maior e direcao invertida
  • Responsive Conversion (skill 56): trata quebra por largura de tela; esta trata quebra por conteudo
  • Accessibility (skill 22): dona do WCAG; lang/dir e o recorte compartilhado
  • QA (skill 05): transforma pseudolocale e RTL em regressao automatizada

Signals

GitHub stars
23
Forks
6
Last commit
Sep 2026
Advanced
Item type
skill
Key
i18n-localization-felvieira
Source
github.com/felvieira/claude-skills-fv