9. Internacionalização (i18n) e Localização
A internacionalização (i18n) e localização são aspectos cruciais do nosso processo de desenvolvimento, garantindo que nossos produtos sejam acessíveis e relevantes para usuários de diferentes regiões e culturas. Esta seção fornece diretrizes detalhadas para implementar e gerenciar a internacionalização em nossos projetos.
9.1. Estratégias de Internacionalização
9.1.1. Para Next.js (Frontend)
Utilizamos o framework Next.js para o frontend, aproveitando suas capacidades integradas de internacionalização.
-
Configuração básica:
No arquivo
next.config.js:module.exports = { i18n: { locales: ['pt', 'en', 'es'], defaultLocale: 'pt', }, } -
Uso de arquivos de tradução:
Crie arquivos JSON para cada idioma em
public/locales/:src/ presentation/ i18n/ locales/ translations/ commons/ actions/ actions.tsx (arquivo com traduções)const actions = { ptBR: { save: 'Salvar', cancel: 'Cancelar', delete: 'Excluir', edit: 'Editar', remove: 'Remover', select: 'Selecionar', }, en_US: { save: 'Save', cancel: 'Cancel', delete: 'Delete', edit: 'Edit', remove: 'Remove', select: 'Select', }, }; // ...Exemplo de arquivo de tradução:
i18n /locales /pt-BR.ts import { actions } from './translations/commons'; export default { translations: { commons: { actions: actions.ptBR, }, }, }; i18n /locales /en-US.ts import { actions } from './translations/commons'; export default { translations: { commons: { actions: actions.en_US, }, }, }; -
Implementação no componente:
import { useRouter } from 'next/router'; import { useTranslation } from 'next-i18next'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; export default function Home() { const { t } = useTranslation('common'); const router = useRouter(); return ( <h1>{t('welcome')}</h1> ); } export async function getStaticProps({ locale }) { return { props: { ...(await serverSideTranslations(locale, ['common'])), }, }; } -
Troca de idiomas:
const changeLanguage = (lng) => { router.push(router.pathname, router.asPath, { locale: lng }); };
9.1.2. Para Laravel (Backend e algumas views)
Para as partes do sistema que ainda utilizam Blade templates no Laravel:
-
Configuração:
No arquivo
config/app.php:'locale' => 'pt', 'fallback_locale' => 'en', 'available_locales' => ['pt', 'en', 'es'], -
Uso em Blade templates:
<h1>{{ __('messages.welcome') }}</h1> -
Arquivos de tradução:
As chaves devem seguir o padrão camelCase. Atualmente, são quatro principais arquivos de tradução em cada idioma:
Em resources/lang/:
resources/
lang/
en/
views/
components.php
layouts.php
pages.php
translated_auth.php
pt-BR/
views/
components.php
layouts.php
pages.php
translated_auth.phpO arquivo components.php contempla a tradução de elementos que se repetem diversas vezes ao longo da plataforma como buttons, inputs e pacote de nomenclatura.
Exemplo components.php:
<?php
return [
'buttons' => [
'filter' => 'Filter',
'filters' => 'Filters',
'start' => 'Start',
'pause' => 'Pause',
'favorite' => 'Favorite',
],
'inputs' => [
'email' => 'E-mail',
'name' => 'Name',
'fullName' => 'Full Name',
'mobilePhone' => 'Mobile Phone',
'password' => 'Password',
'passwordConfirmation' => 'Password Confirmation',
'newPassword' => 'New password',
'confirmPassword' => 'Confirm new password',
'cpfNumber' => 'CPF Number',
]
];O arquivo layouts.php tem as traduções do header e do sidemenu. Já pages.php tem o conteúdo dividido por páginas e subpáginas.
Exemplo:
<?php
return [
'trails' => [
'title' => 'Trails',
'progress' => 'Progress',
'start' => 'Start',
'course' => '{1} :count Course|[2,*] :count Courses',
'course_component' => '{1} :count Course Component|[2,*] :count Course Components',
'curricularComponent' => '{1} :count Curricular Component|[2,*] :count Curricular Components',
'content' => '{1} Content|[2,*] Contents',
'reviewsAndCertificate' => 'Reviews and Certificate',
'searchingFor' => 'Searching for:',
],
'courses' => [
'recommended' => 'Recommended',
'class' => 'Class',
'classes' => 'Classes',
'course' => 'Course',
'courses' => 'Courses',
'content' => 'Content',
'comments' => 'Comments',
]
];E, por fim, translated_auth.php que cuida do fluxo de signin, signup e reset password.
-
Troca de idiomas:
Route::get('language/{locale}', function ($locale) { if (in_array($locale, ['en', 'es', 'pt'])) { session()->put('locale', $locale); } return redirect()->back(); });E no
app/Http/Middleware/SetLocale.php:public function handle($request, Closure $next) { if (session()->has('locale')) { app()->setLocale(session()->get('locale')); } return $next($request); }
9.2. Gerenciamento de Traduções
O gerenciamento eficiente de traduções é crucial para manter a consistência e qualidade da internacionalização.
-
Processo de tradução:
- As chaves devem seguir o padrão camelCase.
- Todas as strings devem ser externalizadas em arquivos de tradução.
- Use chaves descritivas para as traduções (ex:
user.profile.titleem vez detitle). - Mantenha uma planilha central com todas as chaves e suas traduções.
-
Ferramenta de gerenciamento:
- Utilize uma ferramenta como POEditor ou Lokalise para gerenciar traduções.
- Integre a ferramenta com o pipeline de CI/CD para atualizações automáticas.
-
Revisão e aprovação:
- Implemente um processo de revisão por pares para novas traduções.
- O líder de internacionalização deve aprovar todas as novas traduções antes da implementação.
-
Manutenção contínua:
- Agende revisões regulares das traduções existentes.
- Mantenha um glossário de termos específicos do domínio para consistência.
-
Tratamento de plurais:
Para Next.js:
{ "items": { "one": "{{count}} item", "other": "{{count}} items" } }Para Laravel:
'items' => '{0} Nenhum item|{1} :count item|[2,*] :count items', -
Interpolação de variáveis:
Next.js:
t('greeting', { name: user.name })Laravel:
__('greeting', ['name' => $user->name])
9.3. Formatação de Datas, Números e Moedas
A formatação correta de datas, números e moedas é essencial para uma experiência de usuário localizada.
-
Datas:
Next.js (usando
date-fns):import { format, parseISO } from 'date-fns'; import { pt, enUS, es } from 'date-fns/locale'; const locales = { pt, en: enUS, es }; function formatDate(date, formatString, locale) { return format(parseISO(date), formatString, { locale: locales[locale], }); } // Uso formatDate('2023-05-15', 'PP', 'pt'); // 15 de maio de 2023Laravel:
use
Carbon\Carbon;
Carbon::parse('2023-05-15')->locale('pt')->isoFormat('LL'); // 15 de maio de 2023
2. **Números:**
Next.js:
```jsx
const formatNumber = (number, locale) => {
return new Intl.NumberFormat(locale).format(number);
};
// Uso
formatNumber(1234567.89, 'pt-BR'); // 1.234.567,89Laravel:
NumberFormatter::create('pt_BR', NumberFormatter::DECIMAL)->format(1234567.89);-
Moedas:
Next.js:
const formatCurrency = (amount, currency, locale) => { return new Intl.NumberFormat(locale, { style: 'currency', currency: currency, }).format(amount); }; // Uso formatCurrency(1234.56, 'BRL', 'pt-BR'); // R$ 1.234,56Laravel:
NumberFormatter::create('pt_BR', NumberFormatter::CURRENCY)->formatCurrency(1234.56, 'BRL');
Diretrizes Adicionais:
-
Testes de Internacionalização:
- Implemente testes automatizados para verificar a presença de todas as chaves de tradução em todos os idiomas suportados.
- Crie testes de integração que alternam entre idiomas e verificam o conteúdo correto.
-
Documentação:
- Mantenha uma documentação atualizada do processo de internacionalização.
- Inclua guias para desenvolvedores sobre como adicionar novas strings e manter as existentes.
-
Revisão de Código:
- Inclua verificações de internacionalização nas revisões de código.
- Use linters específicos para i18n para detectar strings não internacionalizadas.
-
Tratamento de RTL (Right-to-Left):
- Embora não seja imediatamente necessário para português, inglês e espanhol, considere o suporte futuro para idiomas RTL.
-
Fallback de Idiomas:
- Implemente um sistema de fallback robusto para garantir que, se uma tradução estiver faltando em um idioma, ela seja exibida em um idioma alternativo em vez de mostrar uma chave de tradução.
-
Contexto de Tradução:
- Forneça contexto para os tradutores, especialmente para strings curtas ou ambíguas.
-
Automação:
- Implemente scripts para detectar strings não traduzidas no código-fonte.
- Use ferramentas de CI/CD para alertar sobre chaves de tradução ausentes ou não utilizadas.
Responsabilidades do Líder de Internacionalização:
- Manter e atualizar as diretrizes de internacionalização.
- Revisar e aprovar todas as novas traduções antes da implementação.
- Coordenar com equipes de diferentes regiões para garantir a precisão cultural das traduções.
- Monitorar e reportar regularmente o status de cobertura de internacionalização do projeto.
- Treinar novos membros da equipe sobre as práticas de internacionalização.
- Realizar auditorias periódicas para garantir a conformidade com as diretrizes de internacionalização.