Middleware Language
Le middleware Language Detector détermine automatiquement la langue préférée de l’utilisateur (locale) à partir de différentes sources et la rend accessible via c.get('language'). Ses stratégies de détection incluent les paramètres de requête, les cookies, les en-têtes et les segments du chemin de l’URL. Il convient à l’internationalisation (i18n) et au contenu propre à chaque langue.
Importation
import { Hono } from 'hono'
import { languageDetector } from 'hono/language'Utilisation de base
Détecter la langue à partir de la chaîne de requête, d’un cookie et d’un en-tête, dans cet ordre par défaut, avec repli sur l’anglais :
const app = new Hono()
app.use(
languageDetector({
supportedLanguages: ['en', 'ar', 'ja'], // Must include fallback
fallbackLanguage: 'en', // Required
})
)
app.get('/', (c) => {
const lang = c.get('language')
return c.text(`Hello! Your language is ${lang}`)
})Exemples côté client
# Via path
curl http://localhost:8787/ar/home
# Via query parameter
curl http://localhost:8787/?lang=ar
# Via cookie
curl -H 'Cookie: language=ja' http://localhost:8787/
# Via header
curl -H 'Accept-Language: ar,en;q=0.9' http://localhost:8787/Configuration par défaut
export const DEFAULT_OPTIONS: DetectorOptions = {
order: ['querystring', 'cookie', 'header'],
lookupQueryString: 'lang',
lookupCookie: 'language',
lookupFromHeaderKey: 'accept-language',
lookupFromPathIndex: 0,
caches: ['cookie'],
ignoreCase: true,
fallbackLanguage: 'en',
supportedLanguages: ['en'],
cookieOptions: {
sameSite: 'Strict',
secure: true,
maxAge: 365 * 24 * 60 * 60,
httpOnly: true,
},
debug: false,
}Comportements principaux
Processus de détection
Ordre : Vérifie les sources dans cet ordre par défaut :
- Paramètre de requête (?lang=ar)
- Cookie (language=ar)
- En-tête Accept-Language
Mise en cache : Stocke la langue détectée dans un cookie, pendant un an par défaut
Repli : Utilise
fallbackLanguagesi aucune langue valide n’est détectée ; cette valeur doit figurer danssupportedLanguages
Configuration avancée
Ordre de détection personnalisé
Donner la priorité à la détection dans le chemin de l’URL, par exemple /en/about :
app.use(
languageDetector({
order: ['path', 'cookie', 'querystring', 'header'],
lookupFromPathIndex: 0, // /en/profile → index 0 = 'en'
supportedLanguages: ['en', 'ar'],
fallbackLanguage: 'en',
})
)Correspondance progressive des locales
Lorsqu’un code de locale détecté comme ja-JP ne figure pas dans supportedLanguages, le middleware supprime progressivement les sous-étiquettes pour trouver une correspondance. Par exemple, pour zh-Hant-CN, il essaie zh-Hant, puis zh. Une correspondance exacte est toujours privilégiée.
app.use(
languageDetector({
supportedLanguages: ['en', 'ja', 'zh-Hant'],
fallbackLanguage: 'en',
})
)
// Accept-Language: ja-JP → matches 'ja'
// Accept-Language: zh-Hant-CN → matches 'zh-Hant'Transformation des codes de langue
Normaliser les codes complexes, par exemple en-US → en :
app.use(
languageDetector({
convertDetectedLanguage: (lang) => lang.split('-')[0],
supportedLanguages: ['en', 'ja'],
fallbackLanguage: 'en',
})
)Configuration des cookies
app.use(
languageDetector({
lookupCookie: 'app_lang',
caches: ['cookie'],
cookieOptions: {
path: '/', // Cookie path
sameSite: 'Lax', // Cookie same-site policy
secure: true, // Only send over HTTPS
maxAge: 86400 * 365, // 1 year expiration
httpOnly: true, // Not accessible via JavaScript
domain: '.example.com', // Optional: specific domain
},
})
)Pour désactiver la mise en cache dans les cookies :
languageDetector({
caches: false,
})Débogage
Journaliser les étapes de détection :
languageDetector({
debug: true, // Shows: "Detected from querystring: ar"
})Référence des options
Options de base
| Option | Type | Valeur par défaut | Obligatoire | Description |
|---|---|---|---|---|
supportedLanguages | string[] | ['en'] | Oui | Codes de langue autorisés |
fallbackLanguage | string | 'en' | Oui | Langue par défaut |
order | DetectorType[] | ['querystring', 'cookie', 'header'] | Non | Ordre de détection |
debug | boolean | false | Non | Activer la journalisation |
Options de détection
| Option | Type | Valeur par défaut | Description |
|---|---|---|---|
lookupQueryString | string | 'lang' | Nom du paramètre de requête |
lookupCookie | string | 'language' | Nom du cookie |
lookupFromHeaderKey | string | 'accept-language' | Nom de l’en-tête |
lookupFromPathIndex | number | 0 | Index du segment de chemin |
Options des cookies
| Option | Type | Valeur par défaut | Description |
|---|---|---|---|
caches | CacheType[] | false | ['cookie'] | Paramètres de cache |
cookieOptions.path | string | '/' | Chemin du cookie |
cookieOptions.sameSite | 'Strict' | 'Lax' | 'None' | 'Strict' | Politique SameSite |
cookieOptions.secure | boolean | true | HTTPS uniquement |
cookieOptions.maxAge | number | 31536000 | Expiration en secondes |
cookieOptions.httpOnly | boolean | true | Accessibilité depuis JS |
cookieOptions.domain | string | undefined | Domaine du cookie |
Options avancées
| Option | Type | Valeur par défaut | Description |
|---|---|---|---|
ignoreCase | boolean | true | Correspondance sans distinction de casse |
convertDetectedLanguage | (lang: string) => string | undefined | Transformation du code de langue |
Validation et gestion des erreurs
fallbackLanguagedoit figurer danssupportedLanguages, sinon une erreur est levée lors de la configurationlookupFromPathIndexdoit être ≥ 0- Les configurations invalides lèvent des erreurs lors de l’initialisation du middleware
- En cas d’échec de la détection,
fallbackLanguageest utilisé sans signaler d’erreur
Recettes courantes
Routage basé sur le chemin
app.get('/:lang/home', (c) => {
const lang = c.get('language') // 'en', 'ar', etc.
return c.json({ message: getLocalizedContent(lang) })
})Plusieurs langues prises en charge
languageDetector({
supportedLanguages: ['en', 'en-GB', 'ar', 'ar-EG'],
convertDetectedLanguage: (lang) => lang.replace('_', '-'), // Normalize
})