240 lines
6.4 KiB
Markdown
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
|
|
}
|
|
``` |