Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Internationalization (i18n) Guide

This project uses @nuxtjs/i18n for internationalization with ESLint rules to prevent hardcoded text.

📁 Structure

i18n/
├── locales/
│   ├── pt.ts    # Portuguese translations
│   └── en.ts    # English translations
└── README.md    # This file

🚀 Usage

In Templates (.vue files)

<template>
  <div>
    <!-- Simple translation -->
    <h1>{{ $t('common.save') }}</h1>

    <!-- With parameters -->
    <p>{{ $t('footer.copyright', { year: 2025 }) }}</p>

    <!-- Nested keys -->
    <button>{{ $t('product.addToCart') }}</button>

    <!-- Pluralization -->
    <p>{{ $t('cart.items', cart.length) }}</p>
  </div>
</template>

In Script (Composition API)

<script setup>
const { t, locale, setLocale } = useI18n()

// Use translations
const message = t('message.saveSuccess')
const greeting = t('nav.home')

// Get current locale
console.log(locale.value) // 'pt' or 'en'

// Change locale
await setLocale('en')
</script>

In Script (Options API)

<script>
export default {
  methods: {
    showMessage() {
      const msg = this.$t('message.success')
      alert(msg)
    }
  }
}
</script>

➕ Adding New Translations

  1. Add the key to both locale files:

i18n/locales/pt.ts

export default {
  myFeature: {
    title: 'Meu Título',
    description: 'Minha Descrição',
    button: 'Meu Botão',
  }
}

i18n/locales/en.ts

export default {
  myFeature: {
    title: 'My Title',
    description: 'My Description',
    button: 'My Button',
  }
}
  1. Use in your component:
<template>
  <div>
    <h1>{{ $t('myFeature.title') }}</h1>
    <p>{{ $t('myFeature.description') }}</p>
    <button>{{ $t('myFeature.button') }}</button>
  </div>
</template>

🚨 ESLint Rules

The project has ESLint rules to prevent hardcoded text:

Rule: @intlify/vue-i18n/no-raw-text

❌ Wrong (will show ESLint warning):

<template>
  <h1>Welcome to our store</h1>
  <button>Add to Cart</button>
</template>

✅ Correct:

<template>
  <h1>{{ $t('home.welcome') }}</h1>
  <button>{{ $t('product.addToCart') }}</button>
</template>

Exceptions

The rule ignores:

  • Special characters: /, -, |, , :, ,, (, ), [, ], {, }
  • Icon names: mdi-* (e.g., mdi-home, mdi-cart)
  • Pure whitespace
  • Content in icon components (VIcon, v-icon, md-icon)

Disabled in:

  • plugins/** - Plugin files
  • composables/** - Composable files
  • middleware/** - Middleware files
  • *.config.* - Configuration files

🎯 Available Translation Keys

Common UI

  • common.* - Save, Cancel, Edit, Delete, etc.

Navigation

  • nav.* - Home, Products, Cart, Orders, etc.

Admin Panel

  • admin.* - Dashboard, Settings, etc.

Products

  • product.* - Name, Price, Stock, Add to Cart, etc.

Cart & Checkout

  • cart.* - Shopping cart related
  • checkout.* - Checkout process

Orders

  • order.* - Order status, history, tracking

Forms

  • form.* - Form fields and validation messages

Messages

  • message.* - Success, error, warning messages

Payment

  • payment.* - Payment methods and related

Language Settings

  • language.* - Language selector strings

Footer

  • footer.* - Footer links and copyright

🔄 Language Sync

The app automatically syncs the i18n locale with the whitelabel language setting:

  1. Admin changes language in /admin/language
  2. Setting is saved to whitelabel in database
  3. i18n locale updates immediately
  4. All translated text updates across the app

🔍 Running ESLint

Check for hardcoded text:

bun run lint

Fix auto-fixable issues:

bun run lint:fix

💡 Tips

  1. Always use translation keys - Never hardcode user-facing text
  2. Keep keys organized - Group related translations
  3. Use descriptive key names - product.addToCart not btn1
  4. Add translations to both files - pt.ts AND en.ts
  5. Test in both languages - Switch languages in /admin/language

📚 Resources