Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: narrow legacy or composition vue-i18n types #3341

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
21 changes: 13 additions & 8 deletions src/gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand All @@ -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')
)}'
Expand All @@ -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' {
Expand All @@ -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 {
Expand Down
10 changes: 5 additions & 5 deletions src/internal-global-types.d.ts
Original file line number Diff line number Diff line change
@@ -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<LocaleObject[] | Locale[], true> {}
interface VueI18n extends ComposerCustomProperties {}
}

declare module '#app' {
interface NuxtApp {
$i18n: VueI18n & ExportedGlobalComposer & Composer & NuxtI18nRoutingCustomProperties
$i18n: VueI18n & Composer
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/runtime/plugins/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down
10 changes: 7 additions & 3 deletions src/runtime/routing/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

/**
Expand Down Expand Up @@ -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
Expand Down
74 changes: 25 additions & 49 deletions src/runtime/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,31 @@ type BeforeLanguageSwitchHandler = (
*/
type LanguageSwitchedHandler = (oldLocale: Locale, newLocale: Locale) => Promise<void>

interface SharedProperties {
type MaybeWrapped<Unwrap, T> = Unwrap extends undefined ? T | ComputedRef<T> : Unwrap extends true ? T : ComputedRef<T>

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<UnwrapProperties, ConfiguredLocaleType>
/**
* List of locale codes
*/
localeCodes: MaybeWrapped<UnwrapProperties, Locale[]>
/**
* Base URL that is used in generating canonical links
*/
baseUrl: MaybeWrapped<UnwrapProperties, string>
/**
* Current locale properties.
*/
localeProperties: MaybeWrapped<UnwrapProperties, LocaleObject>
/**
* Routing strategy.
*/
Expand Down Expand Up @@ -122,54 +146,6 @@ interface SharedProperties {
waitForPendingLocaleChange: () => Promise<void>
}

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<ConfiguredLocaleType>
/**
* List of locale codes
*/
localeCodes: ComputedRef<Locale[]>
/**
* Base URL that is used in generating canonical links
*/
baseUrl: ComputedRef<string>
/**
* Current locale properties.
*/
localeProperties: ComputedRef<LocaleObject>
}

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 */
Expand Down