Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 14 additions & 23 deletions examples/composable/scope/global.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
<div id="app">
<h1>Root</h1>
<form>
<label>{{ t('message.language') }}</label>
<select v-model="locale">
<label>{{ $t('message.language') }}</label>
<select v-model="$i18n.locale">
<option value="en">en</option>
<option value="ja">ja</option>
</select>
</form>
<p>{{ t('message.hello') }}</p>
<p>{{ $t('message.hello') }}</p>
<Child />
</div>
<script>
const { createApp } = Vue
const { createI18n, useI18n } = VueI18n
const { createI18n } = VueI18n

const SlotChild = {
template: `
Expand All @@ -34,18 +34,15 @@ <h1>Root</h1>
<div class="sub-child">
<h1>Sub Child</h1>
<form>
<label>{{ t('message.language') }}</label>
<select v-model="locale">
<label>{{ $t('message.language') }}</label>
<select v-model="$i18n.locale">
<option value="en">en</option>
<option value="ja">ja</option>
</select>
</form>
<p>{{ t('message.hi') }}</p>
<p>{{ $t('message.hi') }}</p>
</div>
`,
setup() {
return useI18n()
}
`
}

const Child = {
Expand All @@ -57,27 +54,24 @@ <h1>Sub Child</h1>
<div class="child">
<h1>Child</h1>
<form>
<label>{{ t('message.language') }}</label>
<select v-model="locale">
<label>{{ $t('message.language') }}</label>
<select v-model="$i18n.locale">
<option value="en">en</option>
<option value="ja">ja</option>
</select>
</form>
<p>{{ t('message.hi') }}</p>
<p>{{ $t('message.hi') }}</p>
<SubChild />
t inside of slot
<SlotChild>
{{ t('message.hi') }}
{{ $t('message.hi') }}
</SlotChild>
i18n-t inside of slot
<SlotChild>
<i18n-t keypath='message.hi'/>
</SlotChild>
</div>
`,
setup() {
return useI18n()
}
`
}

const i18n = createI18n({
Expand All @@ -101,10 +95,7 @@ <h1>Child</h1>
})

const app = createApp({
components: { Child },
setup() {
return useI18n()
}
components: { Child }
})
app.use(i18n)
app.mount('#app')
Expand Down
11 changes: 4 additions & 7 deletions examples/composable/scope/inherit-locale.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
<div id="app">
<h1>Root</h1>
<form>
<label>{{ t('message.language') }}</label>
<select v-model="locale">
<label>{{ $t('message.language') }}</label>
<select v-model="$i18n.locale">
<option value="en">en</option>
<option value="ja">ja</option>
</select>
</form>
<p>{{ t("message.hello") }}</p>
<p>{{ $t("message.hello") }}</p>
<Child />
</div>
<script>
Expand Down Expand Up @@ -86,10 +86,7 @@ <h1>Child</h1>
})

const app = createApp({
components: { Child },
setup() {
return useI18n()
}
components: { Child }
})
app.use(i18n)
app.mount('#app')
Expand Down
11 changes: 4 additions & 7 deletions examples/composable/scope/local.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
<div id="app">
<h1>Root</h1>
<form>
<label>{{ t('message.language') }}</label>
<select v-model="locale">
<label>{{ $t('message.language') }}</label>
<select v-model="$i18n.locale">
<option value="en">en</option>
<option value="ja">ja</option>
</select>
</form>
<p>{{ t("message.hello") }}</p>
<p>{{ $t("message.hello") }}</p>
<Child />
</div>
<script>
Expand Down Expand Up @@ -81,10 +81,7 @@ <h1>Child</h1>
})

const app = createApp({
components: { Child },
setup() {
return useI18n()
}
components: { Child }
})
app.use(i18n)
app.mount('#app')
Expand Down
1 change: 1 addition & 0 deletions examples/composable/started.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

const app = createApp({
setup() {
// `useI18n` return the global compser that is created at `createI18n`
return useI18n()
}
})
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
"benchmark": "yarn build && node ./benchmark/index.js",
"build": "node ./scripts/build.js",
"build:sourcemap": "yarn build --sourcemap",
"build:type": "yarn build --types && tail -n +11 src/vue.d.ts >> ./dist/vue-i18n.d.ts",
"build:type": "yarn build --types && tail -n +14 src/vue.d.ts >> ./dist/vue-i18n.d.ts",
"build:watch": "tsc -p . --watch",
"clean": "npm-run-all --parallel clean:*",
"clean:cache": "yarn clean:cache:rollup && yarn clean:cache:jest",
Expand Down
6 changes: 1 addition & 5 deletions src/directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type VTDirectiveValue = {
function getComposer<Messages, DateTimeFormats, NumberFormats>(
i18n: I18n<Messages, DateTimeFormats, NumberFormats>,
instance: ComponentInternalInstance
): Composer<Messages, DateTimeFormats, NumberFormats> | null {
): Composer<Messages, DateTimeFormats, NumberFormats> {
const i18nInternal = (i18n as unknown) as I18nInternal
if (i18n.mode === 'composable') {
return (i18nInternal.__getInstance<
Expand Down Expand Up @@ -66,10 +66,6 @@ export function vTDirective<Messages, DateTimeFormats, NumberFormats>(
}

const composer = getComposer(i18n, instance.$)
if (!composer) {
throw createI18nError(I18nErrorCodes.NOT_FOUND_COMPOSER)
}

if (__DEV__ && modifiers.preserve) {
warn(getWarnMessage(I18nWarnCodes.NOT_SUPPORTED_PRESERVE))
}
Expand Down
4 changes: 1 addition & 3 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export const enum I18nErrorCodes {
// diretive module errors
REQUIRED_VALUE,
INVALID_VALUE,
NOT_FOUND_COMPOSER,
// for enhancement
__EXTEND_POINT__
}
Expand All @@ -43,6 +42,5 @@ export const errorMessages: { [code: number]: string } = {
[I18nErrorCodes.UNEXPECTED_ERROR]: 'Unexpeced error',
[I18nErrorCodes.NOT_AVAILABLE_IN_LEGACY_MODE]: 'Not available in legacy mode',
[I18nErrorCodes.REQUIRED_VALUE]: `Required in value: {0}`,
[I18nErrorCodes.INVALID_VALUE]: `Invalid value`,
[I18nErrorCodes.NOT_FOUND_COMPOSER]: `Not found Composer`
[I18nErrorCodes.INVALID_VALUE]: `Invalid value`
}
100 changes: 95 additions & 5 deletions src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import {
getCurrentInstance,
ComponentInternalInstance,
ComponentOptions,
App
App,
isRef
} from 'vue'
import { LocaleMessageDictionary } from './core/context'
import { Locale, FallbackLocale, LocaleMessageDictionary } from './core/context'
import { DateTimeFormat, NumberFormat } from './core/types'
import {
VueMessageType,
Expand Down Expand Up @@ -55,15 +56,21 @@ export type I18nOptions = I18nAdditionalOptions &
*/
export interface I18nAdditionalOptions {
/**
* Whether vue-i18n legacy API use on your Vue App.
* Whether vue-i18n legacy API use on your Vue App
*
* @default false
*/
legacy?: boolean
/**
* Whether Whether to inject global props & methods into for each component
*
* @default true
*/
globalInjection?: boolean
}

/**
* I18n API mode
* Vue I18n API mode
*/
export type I18nMode = 'legacy' | 'composable'

Expand All @@ -72,7 +79,7 @@ export type I18nMode = 'legacy' | 'composable'
*/
export interface I18n<Messages = {}, DateTimeFormats = {}, NumberFormats = {}> {
/**
* I18n API mode
* Vue I18n API mode
*
* @remarks
* if you specified `legacy: true` option in `createI18n`, return `legacy`,
Expand Down Expand Up @@ -238,6 +245,7 @@ export function createI18n<
Options['numberFormats']
> {
const __legacyMode = !!options.legacy
const __globalInjection = !options.globalInjection
const __instances = new Map<
ComponentInternalInstance,
VueI18n<Messages> | Composer<Messages>
Expand All @@ -264,6 +272,13 @@ export function createI18n<
app.__VUE_I18N_SYMBOL__ = symbol
app.provide(app.__VUE_I18N_SYMBOL__, i18n)

if (!__legacyMode && __globalInjection) {
injectGlobalFields<Messages, DateTimeFormats, NumberFormats>(
app,
i18n.global
)
}

if (__FEATURE_FULL_INSTALL__) {
apply<Messages, DateTimeFormats, NumberFormats>(app, i18n, ...options)
}
Expand Down Expand Up @@ -545,3 +560,78 @@ function setupLifeCycle<Messages, DateTimeFormats, NumberFormats>(
i18n.__deleteInstance(target)
}, target)
}

/**
* Exported composer interface
*
* @remarks
* This interface is the {@link I18n.global | global composer } that is provided interface that is injected into each component with `app.config.globalProperties`.
*/
export interface ExportedComposer {
/**
* Locale
*
* @remarks
* This property is proxy-like property for `composer#locale`. About details, see the {@link Composer | Composer#locale } property
*/
locale: Locale
/**
* Fallback locale
*
* @remarks
* This property is proxy-like property for `composer#fallbackLocale`. About details, see the {@link Composer | Composer#fallbackLocale } property
*/
fallbackLocale: FallbackLocale
/**
* Available locales
*
* @remarks
* This property is proxy-like property for `composer#availableLocales`. About details, see the {@link Composer | Composer#availableLocales } property
*/
readonly availableLocales: Locale[]
}

const globalExportProps = [
'locale',
'fallbackLocale',
'availableLocales'
] as const
const globalExportMethods = ['t', 'd', 'n', 'tm'] as const

function injectGlobalFields<Messages, DateTimeFormats, NumberFormats>(
app: App,
composer: Composer<Messages, DateTimeFormats, NumberFormats>
): void {
const i18n = Object.create(null)
globalExportProps.forEach(prop => {
const desc = Object.getOwnPropertyDescriptor(composer, prop)
if (!desc) {
throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR)
}
const wrap = isRef(desc.value) // check computed props
? {
get() {
return desc.value.value
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
set(val: any) {
desc.value.value = val
}
}
: {
get() {
return desc.get && desc.get()
}
}
Object.defineProperty(i18n, prop, wrap)
})
app.config.globalProperties.$i18n = i18n

globalExportMethods.forEach(method => {
const desc = Object.getOwnPropertyDescriptor(composer, method)
if (!desc) {
throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR)
}
Object.defineProperty(app.config.globalProperties, `$${method}`, desc)
})
}
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export {
I18nMode,
I18nScope,
ComposerAdditionalOptions,
UseI18nOptions
UseI18nOptions,
ExportedComposer
} from './i18n'
export {
Translation,
Expand Down
Loading