diff --git a/src/gen.ts b/src/gen.ts index 0f7b62ade..949f900ef 100644 --- a/src/gen.ts +++ b/src/gen.ts @@ -284,14 +284,13 @@ declare module 'vue-router' { }` export function generateI18nTypes(nuxt: Nuxt, options: NuxtI18nOptions) { - const vueI18nTypes = options.types === 'legacy' ? ['VueI18n'] : ['ExportedGlobalComposer', 'Composer'] + const legacyTypes = options.types === 'legacy' + const i18nType = legacyTypes ? 'VueI18n' : 'Composer' const generatedLocales = simplifyLocaleOptions(nuxt, options) const resolvedLocaleType = typeof generatedLocales === 'string' ? 'Locale[]' : 'LocaleObject[]' const localeCodeStrings = getNormalizedLocales(options.locales).map(x => JSON.stringify(x.code)) const narrowedLocaleType = localeCodeStrings.join(' | ') || 'string' - const i18nType = `${vueI18nTypes.join(' & ')} & NuxtI18nRoutingCustomProperties<${resolvedLocaleType}>` - const globalTranslationTypes = ` declare global { var $t: (${i18nType})['t'] @@ -304,8 +303,8 @@ declare global { // prettier-ignore return `// Generated by @nuxtjs/i18n -import type { ${vueI18nTypes.join(', ')} } from 'vue-i18n' -import type { NuxtI18nRoutingCustomProperties, ComposerCustomProperties } from '${relative( +import type { ${ i18nType } } from 'vue-i18n' +import type { ComposerCustomProperties } from '${relative( join(nuxt.options.buildDir, 'types'), resolve(runtimeDir, 'types.ts') )}' @@ -315,9 +314,9 @@ import type { Strategies, Directions, LocaleObject } from '${relative( )}' declare module 'vue-i18n' { - interface ComposerCustom extends ComposerCustomProperties<${resolvedLocaleType}> {} - interface ExportedGlobalComposer extends NuxtI18nRoutingCustomProperties<${resolvedLocaleType}> {} - interface VueI18n extends NuxtI18nRoutingCustomProperties<${resolvedLocaleType}> {} + interface ComposerCustom extends ComposerCustomProperties<${resolvedLocaleType}, false> {} + interface ExportedGlobalComposer extends ComposerCustomProperties<${resolvedLocaleType}, true> {} + interface VueI18n extends ComposerCustomProperties<${resolvedLocaleType}, false> {} } declare module '@intlify/core-base' { @@ -327,6 +326,12 @@ declare module '@intlify/core-base' { } } +declare module '@intlify/vue-i18n-core' { + // generated based on configured locales + interface GeneratedTypeConfig { + legacy: ${legacyTypes} + } +} declare module '#app' { interface NuxtApp { diff --git a/src/internal-global-types.d.ts b/src/internal-global-types.d.ts index 5ab9ebff8..37364a022 100644 --- a/src/internal-global-types.d.ts +++ b/src/internal-global-types.d.ts @@ -1,15 +1,15 @@ -import type { Composer, ExportedGlobalComposer, VueI18n } from 'vue-i18n' -import type { ComposerCustomProperties, NuxtI18nRoutingCustomProperties } from './runtime/types' +import type { Composer, Locale, VueI18n } from 'vue-i18n' +import type { ComposerCustomProperties } from './runtime/types' declare module 'vue-i18n' { interface ComposerCustom extends ComposerCustomProperties {} - interface ExportedGlobalComposer extends NuxtI18nRoutingCustomProperties {} - interface VueI18n extends NuxtI18nRoutingCustomProperties {} + interface ExportedGlobalComposer extends ComposerCustomProperties {} + interface VueI18n extends ComposerCustomProperties {} } declare module '#app' { interface NuxtApp { - $i18n: VueI18n & ExportedGlobalComposer & Composer & NuxtI18nRoutingCustomProperties + $i18n: VueI18n & Composer } } diff --git a/src/runtime/plugins/i18n.ts b/src/runtime/plugins/i18n.ts index 4e0761393..be93b4923 100644 --- a/src/runtime/plugins/i18n.ts +++ b/src/runtime/plugins/i18n.ts @@ -168,14 +168,14 @@ export default defineNuxtPlugin({ } } }, - extendComposerInstance(instance, c) { - // Set the extended properties on local scope composer instance + extendComposerInstance(instance, c, unwrap = false) { + // Set the extended properties on local scope composer instance or custom component properties const props: [keyof Composer, PropertyDescriptor['get']][] = [ - ['locales', () => c.locales], - ['localeCodes', () => c.localeCodes], - ['baseUrl', () => c.baseUrl], + ['locales', unwrap ? () => c.locales.value : () => c.locales], + ['localeCodes', unwrap ? () => c.localeCodes.value : () => c.localeCodes], + ['baseUrl', unwrap ? () => c.baseUrl.value : () => c.baseUrl], ['strategy', () => c.strategy], - ['localeProperties', () => c.localeProperties], + ['localeProperties', unwrap ? () => c.localeProperties.value : () => c.localeProperties], ['setLocale', () => async (locale: string) => Reflect.apply(c.setLocale, c, [locale])], ['loadLocaleMessages', () => async (locale: string) => Reflect.apply(c.loadLocaleMessages, c, [locale])], ['differentDomains', () => c.differentDomains], diff --git a/src/runtime/routing/i18n.ts b/src/runtime/routing/i18n.ts index 0b659f227..fb4b33e3e 100644 --- a/src/runtime/routing/i18n.ts +++ b/src/runtime/routing/i18n.ts @@ -20,7 +20,11 @@ interface VueI18nInternalPluginOptions { type VueI18nExtendOptions = { extendComposer: (composer: Composer) => void - extendComposerInstance: (instance: Composer | VueI18n | ExportedGlobalComposer, composer: Composer) => void + extendComposerInstance: ( + instance: Composer | VueI18n | ExportedGlobalComposer, + composer: Composer, + unwrap?: boolean + ) => void } /** @@ -57,13 +61,13 @@ export function extendI18n(i18n: I18n, { extendComposer, extendComposerInstance scope.run(() => { extendComposer(globalComposer) if (i18n.mode === 'legacy' && isVueI18n(i18n.global)) { - extendComposerInstance(i18n.global, getComposer(i18n.global)) + extendComposerInstance(i18n.global, getComposer(i18n.global), true) } }) // extend Vue component instance for Vue 3 if (i18n.mode === 'composition' && app.config.globalProperties.$i18n != null) { - extendComposerInstance(app.config.globalProperties.$i18n, globalComposer) + extendComposerInstance(app.config.globalProperties.$i18n, globalComposer, true) } // dispose effectScope during app unmount diff --git a/src/runtime/types.ts b/src/runtime/types.ts index 2778d46f4..fd6cbc52a 100644 --- a/src/runtime/types.ts +++ b/src/runtime/types.ts @@ -36,7 +36,31 @@ type BeforeLanguageSwitchHandler = ( */ type LanguageSwitchedHandler = (oldLocale: Locale, newLocale: Locale) => Promise -interface SharedProperties { +type MaybeWrapped = Unwrap extends undefined ? T | ComputedRef : Unwrap extends true ? T : ComputedRef + +export interface ComposerCustomProperties< + ConfiguredLocaleType extends Locale[] | LocaleObject[] = Locale[] | LocaleObject[], + UnwrapProperties extends boolean | undefined = false +> { + /** + * List of locales + * + * @remarks + * Can either be an array of string codes (e.g. `['en', 'fr']`) or an array of {@link LocaleObject} for more complex configurations + */ + locales: MaybeWrapped + /** + * List of locale codes + */ + localeCodes: MaybeWrapped + /** + * Base URL that is used in generating canonical links + */ + baseUrl: MaybeWrapped + /** + * Current locale properties. + */ + localeProperties: MaybeWrapped /** * Routing strategy. */ @@ -122,54 +146,6 @@ interface SharedProperties { waitForPendingLocaleChange: () => Promise } -export interface ComposerCustomProperties< - ConfiguredLocaleType extends Locale[] | LocaleObject[] = Locale[] | LocaleObject[] -> extends SharedProperties { - /** - * List of locales - * - * @remarks - * Can either be an array of string codes (e.g. `['en', 'fr']`) or an array of {@link LocaleObject} for more complex configurations - */ - locales: ComputedRef - /** - * List of locale codes - */ - localeCodes: ComputedRef - /** - * Base URL that is used in generating canonical links - */ - baseUrl: ComputedRef - /** - * Current locale properties. - */ - localeProperties: ComputedRef -} - -export interface NuxtI18nRoutingCustomProperties< - ConfiguredLocaleType extends Locale[] | LocaleObject[] = Locale[] | LocaleObject[] -> extends SharedProperties { - /** - * List of locales - * - * @remarks - * Can either be an array of string codes (e.g. `['en', 'fr']`) or an array of {@link LocaleObject} for more complex configurations - */ - readonly locales: ConfiguredLocaleType - /** - * List of locale codes - */ - readonly localeCodes: Locale[] - /** - * Base URL that is used in generating canonical links - */ - baseUrl: string - /** - * Current locale properties. - */ - localeProperties: LocaleObject -} - declare module '#app' { interface NuxtApp { /** @internal */