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

240 lines
6.4 KiB
Markdown

# 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`:
```typescript
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
```astro
---
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:
```astro
---
// 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/`:
```astro
---
// 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:
```astro
---
import LanguageSwitcher from '../components/LanguageSwitcher.astro';
---
<LanguageSwitcher />
```
### 5. Creating Localized Links
Use the `getLocalizedPath` function for navigation:
```astro
---
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.
```typescript
t('nav.home', 'es') // Returns: "Inicio"
t('nav.home', 'en') // Returns: "Home"
```
#### `getLanguageFromPath(pathname)`
Extract language from URL path.
```typescript
getLanguageFromPath('/en/elements') // Returns: "en"
getLanguageFromPath('/elements') // Returns: "es" (default)
getLanguageFromPath('/') // Returns: "es" (default)
```
#### `getLocalizedPath(path, lang)`
Generate a localized URL path.
```typescript
getLocalizedPath('/elements', 'es') // Returns: "/elements"
getLocalizedPath('/elements', 'en') // Returns: "/en/elements"
```
#### `isSupportedLanguage(lang)`
Check if a language is supported.
```typescript
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:
```typescript
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:
```typescript
export function t(key: TranslationKey, lang: SupportedLanguage = DEFAULT_LANGUAGE): string {
console.log(`Translating: ${key} for language: ${lang}`);
// ... rest of function
}
```