@intlify/h3
Internationalization middleware & utilities for h3
🌟 Features
✅️ Translation: Simple API like
vue-i18n
✅ Custom locale detector: You can implement your own locale detector
on server-side
✅️️ Useful utilities: support internationalization composables
utilities via @intlify/utils
💿 Installation
npm install @intlify/h3
yarn add @intlify/h3
pnpm add @intlify/h3
bun add @intlify/h3
🚀 Usage
import { createServer } from 'node:http'
import { createApp, createRouter, eventHandler, toNodeListener } from 'h3'
import {
defineI18nMiddleware,
detectLocaleFromAcceptLanguageHeader,
useTranslation,
} from '@intlify/h3'
const middleware = defineI18nMiddleware({
locale: detectLocaleFromAcceptLanguageHeader,
messages: {
en: {
hello: 'Hello {name}!',
},
ja: {
hello: 'こんにちは、{name}!',
},
},
})
const app = createApp({ ...middleware })
const router = createRouter()
router.get(
'/',
eventHandler(async (event) => {
const t = await useTranslation(event)
return t('hello', { name: 'h3' })
}),
)
app.use(router)
createServer(toNodeListener(app)).listen(3000)
🛠️ Custom locale detection
You can detect locale with your custom logic from current H3Event
.
example for detecting locale from url query:
import { defineI18nMiddleware, getQueryLocale } from '@intlify/h3'
import type { H3Event } from 'h3'
const localeDetector = (event: H3Event): string => {
return getQueryLocale(event).toString()
}
const middleware = defineI18nMiddleware({
locale: localeDetector,
})
You can make that function asynchronous. This is useful when loading resources along with locale detection.
[!NOTE]
The case which a synchronous function returns a promise is not supported. you need to use async function
.
import { defineI18nMiddleware, getQueryLocale } from '@intlify/h3'
import type { DefineLocaleMessage } from '@intlify/h3'
import type { H3Event } from 'h3'
const loader = (path: string) => import(path).then((m) => m.default || m)
const messages: Record<string, () => ReturnType<typeof loader>> = {
en: () => loader('./locales/en.json'),
ja: () => loader('./locales/ja.json'),
}
const localeDetector = async (event: H3Event, i18n: CoreContext<string, DefineLocaleMessage>): Promise<string> => {
const locale = getCookieLocale(event).toString()
const loader = messages[locale]
if (loader && !i18n.messages[locale]) {
const message = await loader()
i18n.messages[locale] = message
}
return locale
}
const middleware = defineI18nMiddleware({
locale: localeDetector,
})
🧩 Type-safe resources
[!WARNING]
This is experimental feature (inspired from vue-i18n).
We would like to get feedback from you 🙂.
[!NOTE]
The exeample code is here
You can support the type-safe resources with schema using TypeScript on defineI18nMiddleware
options.
Locale messages resource:
export default {
hello: 'hello, {name}!'
}
your application code:
import { defineI18nMiddleware } from '@intlify/h3'
import { createApp } from 'h3'
import en from './locales/en.ts'
type ResourceSchema = typeof en
const middleware = defineI18nMiddleware<[ResourceSchema], 'en' | 'ja'>({
messages: {
en: { hello: 'Hello, {name}' },
},
})
const app = createApp({ ...middleware })
Result of type checking with tsc
:
npx tsc --noEmit
index.ts:13:3 - error TS2741: Property 'ja' is missing in type '{ en: { hello: string; }; }' but required in type '{ en: ResourceSchema; ja: ResourceSchema; }'.
13 messages: {
~~~~~~~~
../../node_modules/@intlify/core/node_modules/@intlify/core-base/dist/core-base.d.ts:125:5
125 messages?: {
~~~~~~~~
The expected type comes from property 'messages' which is declared here on type 'CoreOptions<string, { message: ResourceSchema; datetime: DateTimeFormat; number: NumberFormat; }, { messages: "en"; datetimeFormats: "en"; numberFormats: "en"; } | { ...; }, ... 8 more ..., NumberFormats<...>>'
Found 1 error in index.ts:13
If you are using Visual Studio Code as an editor, you can notice that there is a resource definition omission in the editor with the following error before you run the typescript compilation.
🖌️ Resource keys completion
[!WARNING]
This is experimental feature (inspired from vue-i18n).
We would like to get feedback from you 🙂.
[!NOTE]
Resource Keys completion can be used if you are using Visual Studio Code
You can completion resources key on translation function with useTranslation
.
resource keys completion has twe ways.
Type parameter for useTranslation
[!NOTE]
The exeample code is here
You can useTranslation
set the type parameter to the resource schema you want to key completion of the translation function.
the part of example:
const router = createRouter()
router.get(
'/',
eventHandler(async (event) => {
type ResourceSchema = {
hello: string
}
const t = await useTranslation<ResourceSchema>(event)
return t('hello', { name: 'h3' })
}),
)
global resource schema with declare module '@intlify/h3'
[!NOTE]
The exeample code is here
You can do resource key completion with the translation function using the typescript declare module
.
the part of example:
import en from './locales/en.ts'
type ResourceSchema = typeof en
declare module '@intlify/h3' {
export interface DefineLocaleMessage extends ResourceSchema {}
}
const router = createRouter()
router.get(
'/',
eventHandler(async (event) => {
const t = await useTranslation(event)
return t('hello', { name: 'h3' })
}),
)
The advantage of this way is that it is not necessary to specify the resource schema in the useTranslation
type parameter.
🛠️ Utilites & Helpers
@intlify/h3
has a concept of composable utilities & helpers.
Utilities
@intlify/h3
composable utilities accept event (from
eventHandler((event) => {})
) as their first argument. (Exclude useTranslation
) return the Intl.Locale
Translations
useTranslation(event)
: use translation function, asynchronous
getHeaderLocale(event, options)
: get locale from accept-language
headergetHeaderLocales(event, options)
: get some locales from accept-language
headertryHeaderLocale(event, options)
: try to get locale from accept-language
headertryHeaderLocales(event, options)
: try to get some locales from accept-language
header
Cookies
getCookieLocale(event, options)
: get locale from cookietryCookieLocale(event, options)
: try to get locale from cookiesetCookieLocale(event, options)
: set locale to cookie
Misc
getPathLocale(event, options)
: get locale from pathtryPathLocale(event, options)
: try to get locale from pathgetQueryLocale(event, options)
: get locale from querytryQueryLocale(event, options)
: try to get locale from query
Helpers
detectLocaleFromAcceptLanguageHeader(event)
: detect locale from accept-language
header
🙌 Contributing guidelines
If you are interested in contributing to @intlify/h3
, I highly recommend checking out the contributing guidelines here. You'll find all the relevant information such as how to make a PR, how to setup development) etc., there.
©️ License
MIT