Plurais e formas de select entram em cena quando uma única string de origem não basta — a tradução passa a depender de um número ou de uma categoria. @lingo.dev/react expõe dois helpers práticos (l.plural e l.select) que são compilados para ICU MessageFormat nos bastidores, então os tradutores veem a sintaxe padrão e o runtime continua igual.
Plurais#
l.plural(count, forms, { context }) escolhe a forma correta com base em count e nas regras de plural do CLDR para o idioma.
const l = useLingo();
l.plural(items.length, {
one: "1 item",
other: "{count} items",
}, { context: "Cart summary" });
// → "1 item" (en, count=1) / "5 items" (en, count=5)
// → "1 Eintrag" / "5 Einträge" (de, after translation)Formas por idioma#
O mapa de formas aceita todas as categorias de plural do CLDR — zero, one, two, few, many, other. Cada idioma usa o que precisa:
- O inglês usa
one+other(1 vs. todo o resto) - O russo usa
one+few+many+other(1; 2-4; 5-20; 21, 31, ...) - O árabe usa as seis
- O japonês usa apenas
other(sem distinção de plural)
Você só precisa fornecer as formas que o idioma de origem usa — os tradutores adicionam o restante para cada idioma de destino.
{count} é interpolado automaticamente em qualquer forma de plural. Você não o passa via values — ele vem do primeiro argumento.
Combinando com outros placeholders#
Em frases com contagem e outras variáveis, escreva as variáveis nas strings das formas; elas serão repassadas ao ICU.
l.plural(notifications.length, {
one: "1 message from {sender}",
other: "{count} messages from {sender}",
}, { context: "Inbox header" });Depois, passe os valores na chamada — mas tem um detalhe: a assinatura de l.plural só inclui { context }. Para casos mistos, use l.text diretamente com a sintaxe de plural do ICU:
l.text(`{count, plural, one {1 message from {sender}} other {# messages from {sender}}}`, {
values: { count: notifications.length, sender: user.name },
context: "Inbox header",
});O token # é substituído literalmente pelo valor da contagem — útil quando você quer usá-lo sem a interpolação com chaves.
Select#
l.select(value, forms, { context }) escolhe uma forma com base em uma chave de texto (gênero, função, tipo de conteúdo — qualquer categoria).
l.select(user.gender, {
male: "He uploaded a photo",
female: "She uploaded a photo",
other: "They uploaded a photo",
}, { context: "Activity feed" });other é obrigatório como fallback. A correspondência é exata — não há aproximação nem comparação que ignore maiúsculas e minúsculas.
Selectordinal#
Para números ordinais (1º, 2º, 3º), use ICU selectordinal diretamente via l.text:
l.text(`You finished in {place, selectordinal, one {#st} two {#nd} few {#rd} other {#th}} place`, {
values: { place: rank },
context: "Leaderboard",
});
// → "You finished in 1st place" / "2nd" / "3rd" / "4th, 5th, ..."No que isso é compilado#
Tanto l.plural quanto l.select montam uma string em ICU MessageFormat e a passam para l.text. A forma compilada é o que lingo extract extrai e armazena nos seus arquivos de idioma — os tradutores editam a sintaxe ICU diretamente, não o literal do objeto JS.
Exemplo: l.plural(n, { one: "1 item", other: "{count} items" }, { context: "Cart" }) é extraído como:
{count, plural, one {1 item} other {{count} items}}Isso significa que os tradutores podem adaptar as categorias para cada idioma, inclusive categorias que não existem na origem. O russo vira {count, plural, one {...} few {...} many {...} other {...}} sem nenhuma mudança no código.
Quando não usar isso#
- Um booleano simples de "1 ou muitos". Duas chamadas de
l.textdentro de umiffuncionam bem e são mais fáceis para os tradutores identificarem. - Um enum programático que não aparece para o usuário. Plural / select servem para a tradução de mensagens categóricas, não para conduzir a lógica do app.
Próximos passos#
- useLingo — semântica básica de
l.textel.rich. - Formatting — formatação de números, moeda, datas e listas via Intl nativo.
