Como Alternar Dinamicamente o locale do PrimeVue
Hoje, enquanto trabalhava em um projeto desenvolvido com o Nuxt.js, deparei-me com a necessidade de implementar a internacionalização (i18n) para suportar os idiomas português e inglês. Para alcançar esse objetivo, integrei o módulo @nuxtjs/i18n, que facilita a localização do aplicativo.
Além disso, o projeto faz uso do nuxt-primevue, um conjunto abrangente de componentes para Nuxt. A fim de proporcionar uma experiência totalmente localizada, foi necessário configurar não apenas a tradução do aplicativo, mas também dos componentes fornecidos pelo PrimeVue.
Felizmente, o PrimeVue já oferece arquivos de localização para vários idiomas em seu repositório oficial, facilitando a integração com diferentes línguas.
primefaces / primelocaleA configuração da internacionalização para o PrimeVue é relativamente simples. No entanto, surgiu um desafio adicional: a necessidade de alterar dinamicamente o idioma do PrimeVue, sem a necessidade de recarregar a página. Enquanto o @nuxtjs/i18n possibilitava essa troca dinâmica de idiomas para o aplicativo, a mesma funcionalidade para o PrimeVue apresentou algumas dificuldades.
Este artigo visa compartilhar os desafios encontrados durante esse processo e fornecer soluções para esses problemas específicos. A abordagem detalhada aqui visa facilitar a implementação bem-sucedida da internacionalização tanto para o aplicativo quanto para os componentes do PrimeVue, permitindo uma experiência de usuário perfeitamente localizada e dinâmica.
Um dos primeiros problemas que encontrei estava, na verdade, relacionado ao @nuxtjs/i18n. A configuração do módulo estava inicialmente assim:
export default defineNuxtConfig({
i18n: {
baseUrl: 'https://example.com/',
defaultLocale: 'en',
langDir: 'locales',
locales: [
{ code: 'en', iso: 'en-US', name: 'English (US)', file: 'en.ts' },
{ code: 'pt', iso: 'pt-BR', name: 'Português (BR)', file: 'pt.ts' },
],
},
})
Como você pode perceber, o i18n estava configurado para ler a pasta 'locales', e um dos detalhes desse módulo que eu não sabia é que ele lê e modifica todos os arquivos contidos nessa pasta. Por não estar ciente desse detalhe, coloquei os locales do PrimeVue dentro dessa pasta da seguinte forma:
/locales ----/en.ts ----/pt.ts ----/primeEN.ts ----/primePT.ts
Desta forma, ao aplicar um desses locales no PrimeVue, o texto dos componentes ficavam da seguinte forma:
{ "type": 0, "start": 0, "end": 2, "loc": { "start": { "line": 1, "column": 1, "offset": 0 }, "end": { "line": 1, "column": 3, "offset": 2 }, "source": "Fr" }, "body": { "type": 2, "start": 0, "end": 2, "loc": { "start": { "line": 1, "column": 1, "offset": 0 }, "end": { "line": 1, "column": 3, "offset": 2 } }, "items": [ { "type": 3, "start": 0, "end": 2, "loc": { "start": { "line": 1, "column": 1, "offset": 0 }, "end": { "line": 1, "column": 3, "offset": 2 } } } ], "static": "Fr" } }
Como mencionado anteriormente, o i18n irá modificar todos os arquivos na pasta "locale", inclusive o locale do PrimeVue. Portanto, a primeira solução é NÃO colocar o locale do PrimeVue na mesma pasta do módulo i18n. No meu caso, optei por colocá-lo na pasta 'utils', para que fosse automaticamente importado quando eu alterasse dinamicamente o locale.
O segundo problema ocorreu porque eu não estava chamando o usePrimeVue() no topo do bloco setup, mas sim, dentro de uma função. Resumindo o problema, se o seu código estiver da seguinte forma, você encontrará um erro, pois o usePrimeVue() utiliza o inject() do Vue, que está disponível apenas no topo do bloco setup.
<script setup lang="ts">
const { locale, setLocale, t } = useI18n()
function changeLang() {
const primeConfig = usePrimeVue()
// Warns [Vue warn]: inject() can only be used inside setup() or functional components.
// Throws Uncaught Error: PrimeVue is not installed!
if (locale.value === 'en') {
setLocale('pt')
primeConfig.config.locale = primept
}
else {
setLocale('en')
primeConfig.config.locale = primeen
}
}
</script>
A solução é realizar conforme exemplificado no código abaixo, executando o usePrimeVue no início do bloco setup e atribuindo o seu valor a uma variável que pode ser utilizada posteriormente dentro da função responsável por alterar o idioma. Além disso, é possível aproveitar para modificar o idioma do i18n.
<script setup lang="ts">
const { locale, setLocale, t } = useI18n()
const primeConfig = usePrimeVue()
onMounted(() => {
if (locale.value === 'en')
primeConfig.config.locale = primeen
else
primeConfig.config.locale = primept
})
function changeLang() {
if (locale.value === 'en') {
setLocale('pt')
primeConfig.config.locale = primept
}
else {
setLocale('en')
primeConfig.config.locale = primeen
}
}
</script>
<template>
<button aria-label="Switch Language" @click="changeLang">
<Icon
:name="locale === 'pt' ? 'openmoji:flag-brazil' : 'openmoji:flag-united-states'"
size="24"
/>
</button>
</template>
E voilà, seu código agora estará funcionando perfeitamente, com o idioma sendo alterado dinamicamente, tanto no módulo do i18n quanto no do PrimeVue! 😊
Se você tiver alguma dúvida ou quiser entrar em contato, sinta-se à vontade para me encontrar em qualquer uma das redes sociais listadas abaixo. Muito obrigado por ler!