Language 中间件
Language Detector 中间件会自动识别用户首选语言(Locale),并通过 c.get('language') 提供结果。它支持从查询参数、Cookie、请求头以及 URL 路径等多种来源检测语言,非常适合用在国际化(i18n)与按地区定制内容的场景。
导入
ts
import { Hono } from 'hono'
import { languageDetector } from 'hono/language'基础用法
以下示例会按照默认顺序(查询参数 → Cookie → 请求头)检测语言,并在无法识别时回退到英文:
ts
const app = new Hono()
app.use(
languageDetector({
supportedLanguages: ['en', 'ar', 'ja'], // 必须包含回退语言
fallbackLanguage: 'en', // 必填
})
)
app.get('/', (c) => {
const lang = c.get('language')
return c.text(`Hello! Your language is ${lang}`)
})客户端示例
sh
# 通过路径
curl http://localhost:8787/ar/home
# 通过查询参数
curl http://localhost:8787/?lang=ar
# 通过 Cookie
curl -H 'Cookie: language=ja' http://localhost:8787/
# 通过请求头
curl -H 'Accept-Language: ar,en;q=0.9' http://localhost:8787/默认配置
ts
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,
}关键行为
检测流程
顺序:默认按以下顺序检查来源:
- 查询参数(?lang=ar)
- Cookie(language=ar)
Accept-Language请求头
缓存:会将检测到的语言写入 Cookie(默认 1 年)
回退:若未能检测到有效语言,则使用
fallbackLanguage(该值必须存在于supportedLanguages)
高级配置
自定义检测顺序
优先从路径(如 /en/about)检测:
ts
app.use(
languageDetector({
order: ['path', 'cookie', 'querystring', 'header'],
lookupFromPathIndex: 0, // /en/profile → 索引 0 对应 'en'
supportedLanguages: ['en', 'ar'],
fallbackLanguage: 'en',
})
)转换语言代码
对复杂的语言代码进行归一化(例如 en-US → en):
ts
app.use(
languageDetector({
convertDetectedLanguage: (lang) => lang.split('-')[0],
supportedLanguages: ['en', 'ja'],
fallbackLanguage: 'en',
})
)配置 Cookie
ts
app.use(
languageDetector({
lookupCookie: 'app_lang',
caches: ['cookie'],
cookieOptions: {
path: '/', // Cookie 路径
sameSite: 'Lax', // SameSite 策略
secure: true, // 仅通过 HTTPS 发送
maxAge: 86400 * 365, // 有效期 1 年
httpOnly: true, // 前端 JS 不可访问
domain: '.example.com', // 可选:指定域名
},
})
)若需禁用 Cookie 缓存:
ts
languageDetector({
caches: false,
})调试
打印检测日志:
ts
languageDetector({
debug: true, // 输出示例:“Detected from querystring: ar”
})选项参考
基础选项
| 选项 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
supportedLanguages | string[] | ['en'] | 是 | 允许的语言代码 |
fallbackLanguage | string | 'en' | 是 | 默认语言 |
order | DetectorType[] | ['querystring', 'cookie', 'header'] | 否 | 检测顺序 |
debug | boolean | false | 否 | 是否输出日志 |
检测相关选项
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
lookupQueryString | string | 'lang' | 查询参数名 |
lookupCookie | string | 'language' | Cookie 名称 |
lookupFromHeaderKey | string | 'accept-language' | 请求头名称 |
lookupFromPathIndex | number | 0 | 路径分段索引 |
Cookie 相关选项
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
caches | CacheType[] | false | ['cookie'] | 缓存策略 |
cookieOptions.path | string | '/' | Cookie 路径 |
cookieOptions.sameSite | 'Strict' | 'Lax' | 'None' | 'Strict' | SameSite 策略 |
cookieOptions.secure | boolean | true | 是否仅通过 HTTPS 发送 |
cookieOptions.maxAge | number | 31536000 | 过期时间(秒) |
cookieOptions.httpOnly | boolean | true | 是否禁止 JS 访问 |
cookieOptions.domain | string | undefined | Cookie 域名 |
高级选项
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
ignoreCase | boolean | true | 是否忽略大小写 |
convertDetectedLanguage | (lang: string) => string | undefined | 自定义语言代码转换 |
校验与错误处理
fallbackLanguage必须出现在supportedLanguages中(否则初始化时会抛错)lookupFromPathIndex必须大于等于 0- 配置无效时会在中间件初始化阶段抛出错误
- 检测失败会静默使用
fallbackLanguage
常见示例
基于路径的路由
ts
app.get('/:lang/home', (c) => {
const lang = c.get('language') // 'en'、'ar' 等
return c.json({ message: getLocalizedContent(lang) })
})支持多种语言代码
ts
languageDetector({
supportedLanguages: ['en', 'en-GB', 'ar', 'ar-EG'],
convertDetectedLanguage: (lang) => lang.replace('_', '-'), // 统一格式
})