Files
pole-book/client/I18N_README.md
2025-06-22 07:24:36 +02:00

6.4 KiB

Internationalization (i18n) Setup

This project includes a comprehensive internationalization system built with Astro 5.x. The system supports multiple languages with URL-based routing and automatic language detection.

Features

  • URL-based language routing (Spanish: /, English: /en/)
  • Spanish as default language (no URL prefix)
  • Automatic language detection from URL
  • Language switcher component
  • Type-safe translation keys
  • Fallback to default language
  • Middleware for automatic redirects
  • SEO-friendly URLs

Supported Languages

Currently supported languages:

  • Spanish (es) - Default language (no URL prefix)
  • English (en) - Secondary language (with /en/ prefix)

URL Structure

  • Spanish (default): /, /elements, /about
  • English: /en/, /en/elements, /en/about

How to Use

1. Adding New Translations

Edit the translation dictionaries in src/lib/i18n.ts:

const translations = {
  es: {
    'your.new.key': 'Texto en español',
    // ... more translations
  },
  en: {
    'your.new.key': 'English text',
    // ... more translations
  }
}

2. Using Translations in Components

---
import { t, getLanguageFromPath } from '../lib/i18n';

const currentLang = getLanguageFromPath(Astro.url.pathname);
---

<h1>{t('your.new.key', currentLang)}</h1>

3. Creating Language-Specific Pages

For English pages, create them in the src/pages/[lang]/ directory:

---
// src/pages/[lang]/about.astro (English only)
import { t, isSupportedLanguage, type SupportedLanguage, DEFAULT_LANGUAGE } from '../../lib/i18n';

const { lang } = Astro.params;

if (!lang || !isSupportedLanguage(lang)) {
  return Astro.redirect('/about');
}

const currentLang = lang as SupportedLanguage;

// Redirect Spanish to root
if (currentLang === DEFAULT_LANGUAGE) {
  return Astro.redirect('/about');
}
---

<h1>{t('about.title', currentLang)}</h1>

For Spanish pages (default), create them directly in src/pages/:

---
// src/pages/about.astro (Spanish default)
import { t, DEFAULT_LANGUAGE } from '../lib/i18n';

const currentLang = DEFAULT_LANGUAGE;
---

<h1>{t('about.title', currentLang)}</h1>

4. Adding the Language Switcher

The language switcher is automatically included in the main layout. To add it to other components:

---
import LanguageSwitcher from '../components/LanguageSwitcher.astro';
---

<LanguageSwitcher />

Use the getLocalizedPath function for navigation:

---
import { getLocalizedPath, getLanguageFromPath } from '../lib/i18n';

const currentLang = getLanguageFromPath(Astro.url.pathname);
---

<a href={getLocalizedPath('/about', currentLang)}>About</a>

File Structure

src/
├── lib/
│   └── i18n.ts              # Main i18n utilities and translations
├── components/
│   ├── LanguageSwitcher.astro  # Language selection component
│   └── ...                   # Other components
├── pages/
│   ├── [lang]/              # English-specific pages
│   │   ├── index.astro      # Redirects Spanish to root
│   │   ├── elements.astro   # Redirects Spanish to root
│   │   └── ...
│   ├── index.astro          # Spanish default homepage
│   ├── elements.astro       # Spanish default elements page
│   └── ...                  # Other Spanish default pages
└── middleware.ts            # Language routing middleware

API Reference

Translation Functions

t(key, lang?)

Get a translation for a given key and language.

t('nav.home', 'es') // Returns: "Inicio"
t('nav.home', 'en') // Returns: "Home"

getLanguageFromPath(pathname)

Extract language from URL path.

getLanguageFromPath('/en/elements') // Returns: "en"
getLanguageFromPath('/elements')    // Returns: "es" (default)
getLanguageFromPath('/')            // Returns: "es" (default)

getLocalizedPath(path, lang)

Generate a localized URL path.

getLocalizedPath('/elements', 'es') // Returns: "/elements"
getLocalizedPath('/elements', 'en') // Returns: "/en/elements"

isSupportedLanguage(lang)

Check if a language is supported.

isSupportedLanguage('es') // Returns: true
isSupportedLanguage('fr') // Returns: false

Constants

  • SUPPORTED_LANGUAGES - Array of supported language codes (['es', 'en'])
  • DEFAULT_LANGUAGE - Default language code ('es')
  • TranslationKey - TypeScript type for translation keys

Adding New Languages

  1. Add the language code to SUPPORTED_LANGUAGES in src/lib/i18n.ts
  2. Add translations for the new language in the translations object
  3. Update the language switcher component if needed
  4. Create language-specific pages in src/pages/[lang]/

Example for French:

export const SUPPORTED_LANGUAGES = ['es', 'en', 'fr'] as const;

const translations = {
  es: { /* Spanish translations */ },
  en: { /* English translations */ },
  fr: { /* French translations */ }
}

Best Practices

  1. Use descriptive keys: Use namespaced keys like nav.home, elements.title
  2. Keep translations organized: Group related translations together
  3. Test all languages: Ensure all translations are complete
  4. Use TypeScript: Leverage the TranslationKey type for type safety
  5. Handle missing translations: The system falls back to the default language
  6. Spanish first: Always put Spanish translations first in the dictionary

SEO Considerations

  • Spanish content is served at root URLs (better for SEO)
  • English content has /en/ prefix
  • Language is properly set in the HTML lang attribute
  • Search engines can index content in multiple languages
  • Use proper hreflang tags if needed for advanced SEO

Troubleshooting

Common Issues

  1. Translation not found: Check if the key exists in all language dictionaries
  2. Language not detected: Ensure the URL follows the correct pattern
  3. Redirect loops: Check middleware configuration
  4. Type errors: Use the TranslationKey type for translation keys

Debug Mode

Enable debug logging by adding console logs in the i18n functions:

export function t(key: TranslationKey, lang: SupportedLanguage = DEFAULT_LANGUAGE): string {
  console.log(`Translating: ${key} for language: ${lang}`);
  // ... rest of function
}