feat(useLocale): handle generic messages (#3100)

Co-authored-by: hywax <me@hywax.space>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
Alex
2025-03-10 22:37:28 +05:00
committed by GitHub
parent 04fc367568
commit a9c8eb3f60
46 changed files with 369 additions and 86 deletions

View File

@@ -17,6 +17,11 @@ Nuxt UI provides an **App** component that wraps your app to provide global conf
### Locale ### Locale
::module-only
#ui
:::div
Use the `locale` prop with the locale you want to use from `@nuxt/ui/locale`: Use the `locale` prop with the locale you want to use from `@nuxt/ui/locale`:
```vue [app.vue] ```vue [app.vue]
@@ -31,13 +36,42 @@ import { fr } from '@nuxt/ui/locale'
</template> </template>
``` ```
:::
#ui-pro
:::div
Use the `locale` prop with the locale you want to use from `@nuxt/ui-pro/locale`:
```vue [app.vue]
<script setup lang="ts">
import { fr } from '@nuxt/ui-pro/locale'
</script>
<template>
<UApp :locale="fr">
<NuxtPage />
</UApp>
</template>
```
:::
::
### Custom locale ### Custom locale
You also have the option to add your own locale using `defineLocale`: You also have the option to add your own locale using `defineLocale`:
::module-only
#ui
:::div
```vue [app.vue] ```vue [app.vue]
<script setup lang="ts"> <script setup lang="ts">
const locale = defineLocale({ import type { Messages } from '@nuxt/ui'
const locale = defineLocale<Messages>({
name: 'My custom locale', name: 'My custom locale',
code: 'en', code: 'en',
dir: 'ltr', dir: 'ltr',
@@ -54,6 +88,35 @@ const locale = defineLocale({
</template> </template>
``` ```
:::
#ui-pro
:::div
```vue [app.vue]
<script setup lang="ts">
import type { Messages } from '@nuxt/ui-pro'
const locale = defineLocale<Messages>({
name: 'My custom locale',
code: 'en',
dir: 'ltr',
messages: {
// implement pairs
}
})
</script>
<template>
<UApp :locale="locale">
<NuxtPage />
</UApp>
</template>
```
:::
::
::tip ::tip
Look at the `code` parameter, there you need to pass the iso code of the language. Example: Look at the `code` parameter, there you need to pass the iso code of the language. Example:
@@ -116,6 +179,11 @@ export default defineNuxtConfig({
#### Set the `locale` prop using `useI18n` #### Set the `locale` prop using `useI18n`
::module-only
#ui
:::div
```vue [app.vue] ```vue [app.vue]
<script setup lang="ts"> <script setup lang="ts">
import * as locales from '@nuxt/ui/locale' import * as locales from '@nuxt/ui/locale'
@@ -130,6 +198,28 @@ const { locale } = useI18n()
</template> </template>
``` ```
:::
#ui-pro
:::div
```vue [app.vue]
<script setup lang="ts">
import * as locales from '@nuxt/ui-pro/locale'
const { locale } = useI18n()
</script>
<template>
<UApp :locale="locales[locale]">
<NuxtPage />
</UApp>
</template>
```
:::
::
:: ::
### Dynamic direction ### Dynamic direction
@@ -138,6 +228,11 @@ Each locale has a `dir` property which will be used by the `App` component to se
In a multilingual application, you might want to set the `lang` and `dir` attributes on the `<html>` element dynamically based on the user's locale, which you can do with the [useHead](https://nuxt.com/docs/api/composables/use-head) composable: In a multilingual application, you might want to set the `lang` and `dir` attributes on the `<html>` element dynamically based on the user's locale, which you can do with the [useHead](https://nuxt.com/docs/api/composables/use-head) composable:
::module-only
#ui
:::div
```vue [app.vue] ```vue [app.vue]
<script setup lang="ts"> <script setup lang="ts">
import * as locales from '@nuxt/ui/locale' import * as locales from '@nuxt/ui/locale'
@@ -162,6 +257,38 @@ useHead({
</template> </template>
``` ```
:::
#ui-pro
:::div
```vue [app.vue]
<script setup lang="ts">
import * as locales from '@nuxt/ui-pro/locale'
const { locale } = useI18n()
const lang = computed(() => locales[locale.value].code)
const dir = computed(() => locales[locale.value].dir)
useHead({
htmlAttrs: {
lang,
dir
}
})
</script>
<template>
<UApp :locale="locales[locale]">
<NuxtPage />
</UApp>
</template>
```
:::
::
## Supported languages ## Supported languages
:supported-languages :supported-languages

View File

@@ -17,6 +17,11 @@ Nuxt UI provides an **App** component that wraps your app to provide global conf
### Locale ### Locale
::module-only
#ui
:::div
Use the `locale` prop with the locale you want to use from `@nuxt/ui/locale`: Use the `locale` prop with the locale you want to use from `@nuxt/ui/locale`:
```vue [App.vue] ```vue [App.vue]
@@ -31,15 +36,43 @@ import { fr } from '@nuxt/ui/locale'
</template> </template>
``` ```
:::
#ui-pro
:::div
Use the `locale` prop with the locale you want to use from `@nuxt/ui-pro/locale`:
```vue [App.vue]
<script setup lang="ts">
import { fr } from '@nuxt/ui-pro/locale'
</script>
<template>
<UApp :locale="fr">
<RouterView />
</UApp>
</template>
```
:::
::
### Custom locale ### Custom locale
You also have the option to add your locale using `defineLocale`: You also have the option to add your locale using `defineLocale`:
::module-only
#ui
:::div
```vue [App.vue] ```vue [App.vue]
<script setup lang="ts"> <script setup lang="ts">
import { defineLocale } from '@nuxt/ui/composables/defineLocale' import type { Messages } from '@nuxt/ui'
import { defineLocale } from '@nuxt/ui/composables/defineLocale.js'
const locale = defineLocale({ const locale = defineLocale<Messages>({
name: 'My custom locale', name: 'My custom locale',
code: 'en', code: 'en',
dir: 'ltr', dir: 'ltr',
@@ -56,6 +89,36 @@ const locale = defineLocale({
</template> </template>
``` ```
:::
#ui-pro
:::div
```vue [App.vue]
<script setup lang="ts">
import type { Messages } from '@nuxt/ui-pro'
import { defineLocale } from '@nuxt/ui/composables/defineLocale.js'
const locale = defineLocale<Messages>({
name: 'My custom locale',
code: 'en',
dir: 'ltr',
messages: {
// implement pairs
}
})
</script>
<template>
<UApp :locale="locale">
<RouterView />
</UApp>
</template>
```
:::
::
::tip ::tip
Look at the `code` parameter, there you need to pass the iso code of the language. Example: Look at the `code` parameter, there you need to pass the iso code of the language. Example:
@@ -131,6 +194,11 @@ app.mount('#app')
#### Set the `locale` prop using `useI18n` #### Set the `locale` prop using `useI18n`
::module-only
#ui
:::div
```vue [App.vue] ```vue [App.vue]
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
@@ -146,6 +214,29 @@ const { locale } = useI18n()
</template> </template>
``` ```
:::
#ui-pro
:::div
```vue [App.vue]
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import * as locales from '@nuxt/ui-pro/locale'
const { locale } = useI18n()
</script>
<template>
<UApp :locale="locales[locale]">
<RouterView />
</UApp>
</template>
```
:::
::
:: ::
### Dynamic direction ### Dynamic direction
@@ -154,6 +245,11 @@ Each locale has a `dir` property which will be used by the `App` component to se
In a multilingual application, you might want to set the `lang` and `dir` attributes on the `<html>` element dynamically based on the user's locale, which you can do with the [useHead](https://unhead.unjs.io/usage/composables/use-head) composable: In a multilingual application, you might want to set the `lang` and `dir` attributes on the `<html>` element dynamically based on the user's locale, which you can do with the [useHead](https://unhead.unjs.io/usage/composables/use-head) composable:
::module-only
#ui
:::div
```vue [App.vue] ```vue [App.vue]
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
@@ -181,6 +277,41 @@ useHead({
</template> </template>
``` ```
:::
#ui-pro
:::div
```vue [App.vue]
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useHead } from '@unhead/vue'
import * as locales from '@nuxt/ui-pro/locale'
const { locale } = useI18n()
const lang = computed(() => locales[locale.value].code)
const dir = computed(() => locales[locale.value].dir)
useHead({
htmlAttrs: {
lang,
dir
}
})
</script>
<template>
<UApp :locale="locales[locale]">
<RouterView />
</UApp>
</template>
```
:::
::
## Supported languages ## Supported languages
:supported-languages :supported-languages

View File

@@ -10,7 +10,7 @@
"@nuxt/content": "^3.3.0", "@nuxt/content": "^3.3.0",
"@nuxt/image": "^1.9.0", "@nuxt/image": "^1.9.0",
"@nuxt/ui": "latest", "@nuxt/ui": "latest",
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@07b08b1", "@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@ab37812",
"@nuxthub/core": "^0.8.18", "@nuxthub/core": "^0.8.18",
"@nuxtjs/plausible": "^1.2.0", "@nuxtjs/plausible": "^1.2.0",
"@octokit/rest": "^21.1.1", "@octokit/rest": "^21.1.1",

26
pnpm-lock.yaml generated
View File

@@ -241,8 +241,8 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:.. version: link:..
'@nuxt/ui-pro': '@nuxt/ui-pro':
specifier: https://pkg.pr.new/@nuxt/ui-pro@07b08b1 specifier: https://pkg.pr.new/@nuxt/ui-pro@ab37812
version: https://pkg.pr.new/@nuxt/ui-pro@07b08b1(@babel/parser@7.26.9)(magicast@0.3.5)(typescript@5.6.3)(vue@3.5.13(typescript@5.6.3)) version: https://pkg.pr.new/@nuxt/ui-pro@ab37812(@babel/parser@7.26.9)(magicast@0.3.5)(typescript@5.6.3)(vue@3.5.13(typescript@5.6.3))
'@nuxthub/core': '@nuxthub/core':
specifier: ^0.8.18 specifier: ^0.8.18
version: 0.8.18(db0@0.3.1(better-sqlite3@11.8.1))(ioredis@5.6.0)(magicast@0.3.5)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(yaml@2.7.0)) version: 0.8.18(db0@0.3.1(better-sqlite3@11.8.1))(ioredis@5.6.0)(magicast@0.3.5)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(yaml@2.7.0))
@@ -1704,8 +1704,8 @@ packages:
vitest: vitest:
optional: true optional: true
'@nuxt/ui-pro@https://pkg.pr.new/@nuxt/ui-pro@07b08b1': '@nuxt/ui-pro@https://pkg.pr.new/@nuxt/ui-pro@ab37812':
resolution: {tarball: https://pkg.pr.new/@nuxt/ui-pro@07b08b1} resolution: {tarball: https://pkg.pr.new/@nuxt/ui-pro@ab37812}
version: 3.0.0-beta.3 version: 3.0.0-beta.3
peerDependencies: peerDependencies:
typescript: 5.6.3 typescript: 5.6.3
@@ -8707,12 +8707,12 @@ snapshots:
- typescript - typescript
- yaml - yaml
'@nuxt/ui-pro@https://pkg.pr.new/@nuxt/ui-pro@07b08b1(@babel/parser@7.26.9)(magicast@0.3.5)(typescript@5.6.3)(vue@3.5.13(typescript@5.6.3))': '@nuxt/ui-pro@https://pkg.pr.new/@nuxt/ui-pro@ab37812(@babel/parser@7.26.9)(magicast@0.3.5)(typescript@5.6.3)(vue@3.5.13(typescript@5.6.3))':
dependencies: dependencies:
'@nuxt/kit': 3.16.0(magicast@0.3.5) '@nuxt/kit': 3.16.0(magicast@0.3.5)
'@nuxt/schema': 3.16.0 '@nuxt/schema': 3.16.0
'@nuxt/ui': 'link:' '@nuxt/ui': 'link:'
'@vueuse/core': 12.8.2(typescript@5.6.3) '@vueuse/core': 13.0.0(vue@3.5.13(typescript@5.6.3))
consola: 3.4.0 consola: 3.4.0
defu: 6.1.4 defu: 6.1.4
dotenv: 16.4.7 dotenv: 16.4.7
@@ -8726,7 +8726,7 @@ snapshots:
tinyglobby: 0.2.12 tinyglobby: 0.2.12
typescript: 5.6.3 typescript: 5.6.3
unplugin: 2.2.0 unplugin: 2.2.0
unplugin-auto-import: 19.1.1(@nuxt/kit@3.16.0(magicast@0.3.5))(@vueuse/core@12.8.2(typescript@5.6.3)) unplugin-auto-import: 19.1.1(@nuxt/kit@3.16.0(magicast@0.3.5))(@vueuse/core@13.0.0(vue@3.5.13(typescript@5.6.3)))
unplugin-vue-components: 28.4.1(@babel/parser@7.26.9)(@nuxt/kit@3.16.0(magicast@0.3.5))(vue@3.5.13(typescript@5.6.3)) unplugin-vue-components: 28.4.1(@babel/parser@7.26.9)(@nuxt/kit@3.16.0(magicast@0.3.5))(vue@3.5.13(typescript@5.6.3))
transitivePeerDependencies: transitivePeerDependencies:
- '@babel/parser' - '@babel/parser'
@@ -14788,18 +14788,6 @@ snapshots:
universalify@2.0.1: {} universalify@2.0.1: {}
unplugin-auto-import@19.1.1(@nuxt/kit@3.16.0(magicast@0.3.5))(@vueuse/core@12.8.2(typescript@5.6.3)):
dependencies:
local-pkg: 1.1.1
magic-string: 0.30.17
picomatch: 4.0.2
unimport: 4.1.2
unplugin: 2.2.0
unplugin-utils: 0.2.4
optionalDependencies:
'@nuxt/kit': 3.16.0(magicast@0.3.5)
'@vueuse/core': 12.8.2(typescript@5.6.3)
unplugin-auto-import@19.1.1(@nuxt/kit@3.16.0(magicast@0.3.5))(@vueuse/core@13.0.0(vue@3.5.13(typescript@5.6.3))): unplugin-auto-import@19.1.1(@nuxt/kit@3.16.0(magicast@0.3.5))(@vueuse/core@13.0.0(vue@3.5.13(typescript@5.6.3))):
dependencies: dependencies:
local-pkg: 1.1.1 local-pkg: 1.1.1

View File

@@ -1,12 +1,11 @@
<script lang="ts"> <script lang="ts">
import type { ConfigProviderProps, TooltipProviderProps } from 'reka-ui' import type { ConfigProviderProps, TooltipProviderProps } from 'reka-ui'
import { localeContextInjectionKey } from '../composables/useLocale' import type { ToasterProps, Locale, Messages } from '../types'
import type { ToasterProps, Locale } from '../types'
export interface AppProps extends Omit<ConfigProviderProps, 'useId' | 'dir' | 'locale'> { export interface AppProps<T extends Messages = Messages> extends Omit<ConfigProviderProps, 'useId' | 'dir' | 'locale'> {
tooltip?: TooltipProviderProps tooltip?: TooltipProviderProps
toaster?: ToasterProps | null toaster?: ToasterProps | null
locale?: Locale locale?: Locale<T>
} }
export interface AppSlots { export interface AppSlots {
@@ -18,14 +17,15 @@ export default {
} }
</script> </script>
<script setup lang="ts"> <script setup lang="ts" generic="T extends Messages = Messages">
import { toRef, useId, provide } from 'vue' import { toRef, useId, provide } from 'vue'
import { ConfigProvider, TooltipProvider, useForwardProps } from 'reka-ui' import { ConfigProvider, TooltipProvider, useForwardProps } from 'reka-ui'
import { reactivePick } from '@vueuse/core' import { reactivePick } from '@vueuse/core'
import { localeContextInjectionKey } from '../composables/useLocale'
import UToaster from './Toaster.vue' import UToaster from './Toaster.vue'
import UOverlayProvider from './OverlayProvider.vue' import UOverlayProvider from './OverlayProvider.vue'
const props = defineProps<AppProps>() const props = defineProps<AppProps<T>>()
defineSlots<AppSlots>() defineSlots<AppSlots>()
const configProviderProps = useForwardProps(reactivePick(props, 'scrollBody')) const configProviderProps = useForwardProps(reactivePick(props, 'scrollBody'))

View File

@@ -1,13 +1,13 @@
import { defu } from 'defu' import { defu } from 'defu'
import type { Locale, Direction, Messages } from '../types/locale' import type { Locale, Direction } from '../types/locale'
interface DefineLocaleOptions { interface DefineLocaleOptions<M> {
name: string name: string
code: string code: string
dir?: Direction dir?: Direction
messages: Messages messages: M
} }
export function defineLocale(options: DefineLocaleOptions): Locale { export function defineLocale<M>(options: DefineLocaleOptions<M>): Locale<M> {
return defu<DefineLocaleOptions, [{ dir: Direction }]>(options, { dir: 'ltr' }) return defu<DefineLocaleOptions<M>, [{ dir: Direction }]>(options, { dir: 'ltr' })
} }

View File

@@ -1,16 +1,16 @@
import { computed, inject, ref } from 'vue' import { computed, inject, toRef } from 'vue'
import type { InjectionKey, Ref } from 'vue' import type { InjectionKey, Ref } from 'vue'
import type { Locale } from '../types/locale' import { createSharedComposable } from '@vueuse/core'
import type { Locale, Messages } from '../types/locale'
import { buildLocaleContext } from '../utils/locale' import { buildLocaleContext } from '../utils/locale'
import en from '../locale/en' import en from '../locale/en'
import { createSharedComposable } from '@vueuse/core'
export const localeContextInjectionKey: InjectionKey<Ref<Locale | undefined>> = Symbol('nuxt-ui.locale-context') export const localeContextInjectionKey: InjectionKey<Ref<Locale<unknown> | undefined>> = Symbol('nuxt-ui.locale-context')
const _useLocale = (localeOverrides?: Ref<Locale | undefined>) => { const _useLocale = (localeOverrides?: Ref<Locale<Messages> | undefined>) => {
const locale = localeOverrides || inject(localeContextInjectionKey, ref())! const locale = localeOverrides || toRef(inject<Locale<Messages>>(localeContextInjectionKey))
return buildLocaleContext(computed(() => locale.value || en)) return buildLocaleContext<Messages>(computed(() => locale.value || en))
} }
export const useLocale = createSharedComposable(_useLocale) export const useLocale = createSharedComposable(_useLocale)

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'العربية', name: 'العربية',
code: 'ar', code: 'ar',
dir: 'rtl', dir: 'rtl',

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Azərbaycanca', name: 'Azərbaycanca',
code: 'az', code: 'az',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'বাংলা', name: 'বাংলা',
code: 'bn', code: 'bn',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Čeština', name: 'Čeština',
code: 'cs', code: 'cs',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Danish', name: 'Danish',
code: 'da', code: 'da',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Deutsch', name: 'Deutsch',
code: 'de', code: 'de',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Ελληνικά', name: 'Ελληνικά',
code: 'el', code: 'el',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'English', name: 'English',
code: 'en', code: 'en',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Español', name: 'Español',
code: 'es', code: 'es',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Eesti', name: 'Eesti',
code: 'et', code: 'et',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'فارسی', name: 'فارسی',
code: 'fa-IR', code: 'fa-IR',
dir: 'rtl', dir: 'rtl',

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Suomeksi', name: 'Suomeksi',
code: 'fi', code: 'fi',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Français', name: 'Français',
code: 'fr', code: 'fr',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Hebrew', name: 'Hebrew',
code: 'he', code: 'he',
dir: 'rtl', dir: 'rtl',

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Hindi', name: 'Hindi',
code: 'hi', code: 'hi',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Magyar', name: 'Magyar',
code: 'hu', code: 'hu',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Indonesia', name: 'Indonesia',
code: 'id', code: 'id',
messages: { messages: {

View File

@@ -5,13 +5,15 @@ export { default as cs } from './cs'
export { default as da } from './da' export { default as da } from './da'
export { default as de } from './de' export { default as de } from './de'
export { default as el } from './el' export { default as el } from './el'
export { default as et } from './et'
export { default as en } from './en' export { default as en } from './en'
export { default as es } from './es' export { default as es } from './es'
export { default as et } from './et'
export { default as fa_ir } from './fa_ir' export { default as fa_ir } from './fa_ir'
export { default as fi } from './fi' export { default as fi } from './fi'
export { default as fr } from './fr' export { default as fr } from './fr'
export { default as he } from './he'
export { default as hi } from './hi' export { default as hi } from './hi'
export { default as hu } from './hu'
export { default as id } from './id' export { default as id } from './id'
export { default as it } from './it' export { default as it } from './it'
export { default as ja } from './ja' export { default as ja } from './ja'
@@ -31,4 +33,3 @@ export { default as uk } from './uk'
export { default as vi } from './vi' export { default as vi } from './vi'
export { default as zh_cn } from './zh_cn' export { default as zh_cn } from './zh_cn'
export { default as zh_tw } from './zh_tw' export { default as zh_tw } from './zh_tw'
export { default as he } from './he'

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Italiano', name: 'Italiano',
code: 'it', code: 'it',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: '日本語', name: '日本語',
code: 'ja', code: 'ja',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'ភាសាខ្មែរ', name: 'ភាសាខ្មែរ',
code: 'km', code: 'km',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: '한국어', name: '한국어',
code: 'ko', code: 'ko',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Norsk Bokmål', name: 'Norsk Bokmål',
code: 'nb-NO', code: 'nb-NO',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Nederlands', name: 'Nederlands',
code: 'nl', code: 'nl',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Polski', name: 'Polski',
code: 'pl', code: 'pl',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Português', name: 'Português',
code: 'pt', code: 'pt',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Português (Brasil)', name: 'Português (Brasil)',
code: 'pt-BR', code: 'pt-BR',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Русский', name: 'Русский',
code: 'ru', code: 'ru',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Slovenčina', name: 'Slovenčina',
code: 'sk', code: 'sk',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Svenska', name: 'Svenska',
code: 'sv', code: 'sv',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'ไทย', name: 'ไทย',
code: 'th', code: 'th',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Türkçe', name: 'Türkçe',
code: 'tr', code: 'tr',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Українська', name: 'Українська',
code: 'uk', code: 'uk',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: 'Tiếng Việt', name: 'Tiếng Việt',
code: 'vi', code: 'vi',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: '简体中文', name: '简体中文',
code: 'zh-CN', code: 'zh-CN',
messages: { messages: {

View File

@@ -1,6 +1,7 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale' import { defineLocale } from '../composables/defineLocale'
export default defineLocale({ export default defineLocale<Messages>({
name: '繁體中文', name: '繁體中文',
code: 'zh-TW', code: 'zh-TW',
messages: { messages: {

View File

@@ -50,9 +50,9 @@ export type Messages = {
export type Direction = 'ltr' | 'rtl' export type Direction = 'ltr' | 'rtl'
export type Locale = { export type Locale<M> = {
name: string name: string
code: string code: string
dir: Direction dir: Direction
messages: Messages messages: M
} }

View File

@@ -6,19 +6,19 @@ import { get } from './index'
export type TranslatorOption = Record<string, string | number> export type TranslatorOption = Record<string, string | number>
export type Translator = (path: string, option?: TranslatorOption) => string export type Translator = (path: string, option?: TranslatorOption) => string
export type LocaleContext = { export type LocaleContext<M> = {
locale: Ref<Locale> locale: Ref<Locale<M>>
lang: Ref<string> lang: Ref<string>
dir: Ref<Direction> dir: Ref<Direction>
code: Ref<string> code: Ref<string>
t: Translator t: Translator
} }
export function buildTranslator(locale: MaybeRef<Locale>): Translator { export function buildTranslator<M>(locale: MaybeRef<Locale<M>>): Translator {
return (path, option) => translate(path, option, unref(locale)) return (path, option) => translate(path, option, unref(locale))
} }
export function translate(path: string, option: undefined | TranslatorOption, locale: Locale): string { export function translate<M>(path: string, option: undefined | TranslatorOption, locale: Locale<M>): string {
const prop: string = get(locale, `messages.${path}`, path) const prop: string = get(locale, `messages.${path}`, path)
return prop.replace( return prop.replace(
@@ -27,11 +27,11 @@ export function translate(path: string, option: undefined | TranslatorOption, lo
) )
} }
export function buildLocaleContext(locale: MaybeRef<Locale>): LocaleContext { export function buildLocaleContext<M>(locale: MaybeRef<Locale<M>>): LocaleContext<M> {
const lang = computed(() => unref(locale).name) const lang = computed(() => unref(locale).name)
const code = computed(() => unref(locale).code) const code = computed(() => unref(locale).code)
const dir = computed(() => unref(locale).dir) const dir = computed(() => unref(locale).dir)
const localeRef = isRef(locale) ? locale : ref(locale) const localeRef = isRef(locale) ? locale : ref(locale) as Ref<Locale<M>>
return { return {
lang, lang,

View File

@@ -9,6 +9,7 @@ export { useHead } from '@unhead/vue'
export { useRoute, useRouter } from 'vue-router' export { useRoute, useRouter } from 'vue-router'
export { defineShortcuts } from '../composables/defineShortcuts' export { defineShortcuts } from '../composables/defineShortcuts'
export { defineLocale } from '../composables/defineLocale'
export { useLocale } from '../composables/useLocale' export { useLocale } from '../composables/useLocale'
export const useColorMode = () => { export const useColorMode = () => {