@intlify/h3
Version:
Internationalization for H3
312 lines (225 loc) β’ 9.07 kB
Markdown
<p align="center">
<img alt="logo" width="512" src="./assets/intlify-h3.svg">
</p>
<h1 align="center">@intlify/h3</h1>
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![CI][ci-src]][ci-href]
Internationalization for H3
<!-- eslint-disable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
> [!NOTE]
> Youβre viewing the `srvmid` repository, which is developing for H3 v2. If you want to check H3 v1, please see the [`@intlify/h3` repository](https://github.com/intlify/h3/tree/main)
<!-- eslint-enable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
β
οΈοΈ **Internationalization utils:** support [internationalization
utils](https://github.com/intlify/srvmid/blob/main/packages/h3/docs/index.md) via [@intlify/utils](https://github.com/intlify/utils)
β
οΈ **Translation:** Simple API like
[](https://vue-i18n.intlify.dev/)
β
**Custom locale detector:** You can implement your own locale detector
on server-side
```sh
npm install @intlify/h3
yarn add @intlify/h3
pnpm add @intlify/h3
bun add @intlify/h3
```
Detect locale from `accept-language` header:
```ts
import { H3 } from 'h3'
import { getHeaderLocale } from '@intlify/h3'
const app = new H3()
app.get('/', event => {
// detect locale from HTTP header which has `Accept-Language: ja,en-US;q=0.7,en;q=0.3`
const locale = getHeaderLocale(event.req)
return locale.toString()
})
```
Detect locale from URL query:
```ts
import { H3 } from 'h3'
import { getQueryLocale } from '@intlify/h3'
const app = new H3()
app.get('/', event => {
// detect locale from query which has 'http://localhost:3000?locale=en'
const locale = getQueryLocale(event.req)
return locale.toString()
})
```
If you want to use translation, you need to install `intlify` plugin. As a result, you can use `useTranslation` within the handler:
```ts
import { createServer } from 'node:http'
import { H3, toNodeListener } from 'h3'
import { intlify, detectLocaleFromAcceptLanguageHeader, useTranslation } from '@intlify/h3'
// install `intlify` plugin with `H3` constructor
const app = new H3({
plugins: [
// configure plugin options
intlify({
// detect locale with `accept-language` header
locale: detectLocaleFromAcceptLanguageHeader,
// resource messages
messages: {
en: {
hello: 'Hello {name}!'
},
ja: {
hello: 'γγγ«γ‘γ―γ{name}οΌ'
}
}
// something options
// ...
})
]
})
app.get('/', async event => {
// use `useTranslation` in event handler
const t = await useTranslation(event)
return t('hello', { name: 'h3' })
})
createServer(toNodeListener(app)).listen(3000)
```
You can detect locale with your custom logic from current `H3Event`.
example for detecting locale from url query, and get locale with `getDetectorLocale` util:
```ts
import { H3 } from 'h3'
import { intlify, getQueryLocale, getDetectorLocale } from '@intlify/h3'
import type { H3Event } from 'h3'
// define custom locale detector
const localeDetector = (event: H3Event): string => {
return getQueryLocale(event.req).toString()
}
const app = new H3({
plugins: [
intlify({
// set your custom locale detector
locale: localeDetector
// something options
// ...
})
]
})
app.get('/', async event => {
const locale = await getDetectorLocale(event)
console.log(`Current Locale: ${locale.language}`)
})
```
You can make that function asynchronous. This is useful when loading resources along with locale detection.
<!-- eslint-disable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
> [!NOTE]
> The case which a synchronous function returns a promise is not supported. you need to use `async function`.
<!-- eslint-enable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
```ts
import { H3 } from 'h3'
import { intlify, getCookieLocale } from '@intlify/h3'
import type { H3Event } from 'h3'
import type { DefineLocaleMessage, CoreContext } from '@intlify/h3'
const loader = (path: string) => import(path).then(m => m.default)
const messages: Record<string, () => ReturnType<typeof loader>> = {
en: () => loader('./locales/en.json'),
ja: () => loader('./locales/ja.json')
}
// define custom locale detector and lazy loading
const localeDetector = async (
event: H3Event,
intlify: CoreContext<string, DefineLocaleMessage>
): Promise<string> => {
// detect locale
const locale = getCookieLocale(event.req).toString()
// resource lazy loading
const loader = messages[locale]
if (loader && !intlify.messages[locale]) {
const message = await loader()
intlify.messages[locale] = message
}
return locale
}
const app = new H3({
plugins: [
intlify({
// set your custom locale detector
locale: localeDetector
// something options
// ...
})
]
})
```
<!-- eslint-disable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
> [!NOTE]
> Resource Keys completion can be used if you are using [Visual Studio Code](https://code.visualstudio.com/)
<!-- eslint-enable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
You can completion resources key on translation function with `useTranslation`.

resource keys completion has two ways.
<!-- eslint-disable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
> [!NOTE]
> The exeample code is [here](https://github.com/intlify/h3/tree/main/playground/local-schema)
<!-- eslint-enable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
You can `useTranslation` set the type parameter to the resource schema you want to key completion of the translation function.
the part of example:
```ts
app.get('/', async event => {
type ResourceSchema = {
hello: string
}
// set resource schema as type parameter
const t = await useTranslation<ResourceSchema>(event)
// you can completion when you type `t('`
return t('hello', { name: 'h3' })
})
```
<!-- eslint-disable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
> [!NOTE]
> The exeample code is [here](https://github.com/intlify/h3/tree/main/playground/global-schema)
<!-- eslint-enable markdown/no-missing-label-refs -- NOTE(kazupon): ignore github alert -->
You can do resource key completion with the translation function using the typescript `declare module`.
the part of example:
```ts
import en from './locales/en.ts'
// 'en' resource is master schema
type ResourceSchema = typeof en
// you can put the type extending with `declare module` as global resource schema
declare module '@intlify/h3' {
// extend `DefineLocaleMessage` with `ResourceSchema`
export interface DefineLocaleMessage extends ResourceSchema {}
}
app.get('/', async event => {
const t = await useTranslation(event)
// you can completion when you type `t('`
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.
`@intlify/h3` has a concept of composable utilities & helpers.
See the [API References](https://github.com/intlify/srvmid/blob/main/packages/h3/docs/index.md)
If you are interested in contributing to `@intlify/h3`, I highly recommend checking out [the contributing guidelines](https://github.com/intlify/srvmid/blob/main/CONTRIBUTING.md) here. You'll find all the relevant information such as [how to make a PR](https://github.com/intlify/srvmid/blob/main/CONTRIBUTING.md#pull-request-guidelines), [how to setup development](https://github.com/intlify/srvmid/blob/main/CONTRIBUTING.md#development-setup)) etc., there.
The development of `srvmid` is supported by my OSS sponsors!
<p align="center">
<a href="https://cdn.jsdelivr.net/gh/kazupon/sponsors/sponsors.svg">
<img alt="sponsor" src='https://cdn.jsdelivr.net/gh/kazupon/sponsors/sponsors.svg'/>
</a>
</p>
[](http://opensource.org/licenses/MIT)
<!-- Badges -->
[]: https://img.shields.io/npm/v/@intlify/h3?style=flat&colorA=18181B&colorB=FFAD33
[]: https://npmjs.com/package/@intlify/h3
[]: https://img.shields.io/npm/dm/@intlify/h3?style=flat&colorA=18181B&colorB=FFAD33
[]: https://npmjs.com/package/@intlify/h3
[]: https://github.com/intlify/srvmid/actions/workflows/ci.yml/badge.svg
[]: https://github.com/intlify/srvmid/actions/workflows/ci.yml