diff --git a/src/runtime/composables/index.ts b/src/runtime/composables/index.ts index c7aaf94e9..6631cee4b 100644 --- a/src/runtime/composables/index.ts +++ b/src/runtime/composables/index.ts @@ -12,35 +12,33 @@ import { getOgUrl, localeHead } from '../routing/compatibles/head' -import { - getRouteBaseName, - localeLocation, - localePath, - localeRoute, - switchLocalePath -} from '../routing/compatibles/routing' +import { getRouteBaseName, localePath, localeRoute, switchLocalePath } from '../routing/compatibles/routing' import { findBrowserLocale } from '../routing/utils' import { getComposer } from '../compatibility' - import type { Ref } from 'vue' import type { Locale } from 'vue-i18n' -import type { I18nHeadMetaInfo, I18nHeadOptions, SeoAttributesOptions } from '#internal-i18n-types' -import type { RouteLocationAsRelativeI18n, RouteLocationResolvedI18n, RouteMapI18n } from 'vue-router' +import type { resolveRoute } from '../routing/compatibles/routing' +import type { I18nHeadMetaInfo, I18nHeadOptions, LocaleObject, SeoAttributesOptions } from '#internal-i18n-types' import type { HeadParam } from '../utils' +import type { RouteLocationAsRelativeI18n, RouteLocationRaw, RouteLocationResolvedI18n, RouteMapI18n } from 'vue-router' export * from 'vue-i18n' export * from './shared' /** - * Returns a function to set i18n params. + * Used to set i18n params for the current route. + * + * @params params - an object with {@link Locale} keys with localized parameters + */ +export type SetI18nParamsFunction = (params: Partial>) => void + +/** + * Returns a {@link SetI18nParamsFunction} used to set i18n params for the current route. * * @param options - An options object, see {@link SeoAttributesOptions}. * * @returns a {@link SetI18nParamsFunction}. - * - * @public */ -export type SetI18nParamsFunction = (params: Partial>) => void export function useSetI18nParams(seo?: SeoAttributesOptions): SetI18nParamsFunction { const common = initCommonComposableOptions() const nuxtApp = useNuxtApp() @@ -76,8 +74,7 @@ export function useSetI18nParams(seo?: SeoAttributesOptions): SetI18nParamsFunct stop() }) - const currentLocale = getNormalizedLocales(locales).find(l => l.code === locale) || { code: locale } - const currentLocaleLanguage = currentLocale.language + const currentLocale: LocaleObject = getNormalizedLocales(locales).find(l => l.code === locale) || { code: locale } if (!unref(nuxtApp.$i18n.baseUrl)) { console.warn('I18n `baseUrl` is required to generate valid SEO tag links.') @@ -102,8 +99,8 @@ export function useSetI18nParams(seo?: SeoAttributesOptions): SetI18nParamsFunct metaObject.meta.push( ...getOgUrl(common, key, seo), - ...getCurrentOgLocale(currentLocale, currentLocaleLanguage, key), - ...getAlternateOgLocales(locales, currentLocaleLanguage, key) + ...getCurrentOgLocale(currentLocale, currentLocale.language, key), + ...getAlternateOgLocales(locales, currentLocale.language, key) ) } @@ -117,29 +114,20 @@ export function useSetI18nParams(seo?: SeoAttributesOptions): SetI18nParamsFunct } /** - * The `localeHead` function returns localized head properties for locale-related aspects. + * Returns localized head properties for locale-related aspects. * - * @remarks - * The parameter signature of this function is the same as {@link localeHead}. + * @param options - An options object, see {@link I18nHeadOptions}. * - * @param options - An options object, see {@link I18nHeadOptions} - * - * @returns the route object for a given route, the route object is resolved by vue-router rather than just a full route path. - * - * @see {@link localeHead} - * - * @public + * @returns The localized head properties. */ export type LocaleHeadFunction = (options: I18nHeadOptions) => ReturnType /** - * The `useLocaleHead` composable returns localized head properties for locale-related aspects. + * Returns localized head properties for locale-related aspects. * * @param options - An options object, see {@link I18nHeadOptions} * * @returns The localized {@link I18nHeadMetaInfo | head properties} with Vue `ref`. - * - * @public */ export function useLocaleHead({ dir = true, @@ -185,39 +173,41 @@ export function useLocaleHead({ } /** - * The function that resolves the route base name. + * NOTE: regarding composables accepting narrowed route arguments + * route path string autocompletion is disabled as this can break depending on `strategy` + * if route resolve is improved to work regardless of strategy this can be enabled again * - * @remarks - * The parameter signatures of this function is the same as {@link getRouteBaseName}. - * - * @param givenRoute - A route location. The path or name of the route or an object for more complex routes. + * the following would be the complete narrowed type + * route: Name | RouteLocationAsRelativeI18n | RouteLocationAsStringI18n | RouteLocationAsPathI18n + */ + +type RouteLocationI18nGenericPath = Omit & { path?: string } + +/** + * Revoles a localized route object for the passed route. * - * @returns The route base name, if route name is not defined, return `null`. + * @param route - a route name or route object. + * @param locale - (default: current locale). * - * @see {@link useRouteBaseName} + * @returns Localized route object * - * @public + * @deprecated use {@link useLocalePath}/{@link LocalePathFunction $localePath} or {@link useLocaleRoute}/{@link LocaleRouteFunction $localeRoute} instead */ -export type RouteBaseNameFunction = ( - route: Name | (Omit & { path?: string }), - /** - * Note: disabled route path string autocompletion, this can break depending on `strategy` - * this can be enabled again after route resolve has been improved. - */ - // | RouteLocationAsStringI18n - // | RouteLocationAsPathI18n - locale?: Locale -) => string +export type ResolveRouteFunction = (route: RouteLocationRaw, locale?: Locale) => ReturnType /** - * The `useRouteBaseName` composable returns a function which returns the route base name. - * - * @remarks - * The function returned by `useRouteBaseName` is the wrapper function with the same signature as {@link getRouteBaseName}. + * Resolves the route base name for the given route. * - * @returns A {@link RouteBaseNameFunction}. + * @param route - a route name or route object. * - * @public + * @returns Route base name (without localization suffix) or `undefined` if no name was found. + */ +export type RouteBaseNameFunction = ( + route: Name | RouteLocationI18nGenericPath +) => string | undefined + +/** + * Returns a {@link RouteBaseNameFunction} used get the base name of a route. */ export function useRouteBaseName(): RouteBaseNameFunction { // @ts-expect-error - generated types conflict with the generic types we accept @@ -225,41 +215,20 @@ export function useRouteBaseName(): RouteBaseNameFunction { } /** - * The function that resolve locale path. + * Resolves a localized path for the given route. * - * @remarks - * The parameter signature of this function is same as {@link localePath}. - * - * @param route - A route location. The path or name of the route or an object for more complex routes. - * @param locale - A locale optional, if not specified, uses the current locale. + * @param route - a route name or route object. + * @param locale - (default: current locale). * * @returns Returns the localized URL for a given route. - * - * @see {@link useLocalePath} - * - * @public */ - export type LocalePathFunction = ( - route: Name | (Omit & { path?: string }), - /** - * Note: disabled route path string autocompletion, this can break depending on `strategy` - * this can be enabled again after route resolve has been improved. - */ - // | RouteLocationAsStringI18n - // | RouteLocationAsPathI18n + route: Name | RouteLocationI18nGenericPath, locale?: Locale ) => string /** - * The `useLocalePath` composable returns function that resolve the locale path. - * - * @remarks - * The function returned by `useLocalePath` is the wrapper function with the same signature as {@link localePath}. - * - * @returns A {@link LocalePathFunction}. - * - * @public + * Returns a {@link LocalePathFunction} used to resolve a localized path. */ export function useLocalePath(): LocalePathFunction { // @ts-expect-error - generated types conflict with the generic types we accept @@ -267,39 +236,20 @@ export function useLocalePath(): LocalePathFunction { } /** - * The function that resolve route. - * - * @remarks - * The parameter signature of this function is same as {@link localeRoute}. - * - * @param route - A route location. The path or name of the route or an object for more complex routes. - * @param locale - A locale optional, if not specified, uses the current locale. + * Resolves a localized route object for the given route. * - * @returns the route object for a given route, the route object is resolved by vue-router rather than just a full route path. + * @param route - a route name or route object. + * @param locale - (default: current locale). * - * @see {@link useLocaleRoute} - * - * @public + * @returns A route. if cannot resolve, `undefined` is returned. */ export type LocaleRouteFunction = ( - route: Name | (Omit & { path?: string }), - /** - * Note: disabled route path string autocompletion, this can break depending on `strategy` - * this can be enabled again after route resolve has been improved. - */ - // | RouteLocationAsStringI18n - // | RouteLocationAsPathI18n + route: Name | RouteLocationI18nGenericPath, locale?: Locale ) => RouteLocationResolvedI18n | undefined + /** - * The `useLocaleRoute` composable returns function that resolve the locale route. - * - * @remarks - * The function returned by `useLocaleRoute` is the wrapper function with the same signature as {@link localeRoute}. - * - * @returns A {@link LocaleRouteFunction}. - * - * @public + * Returns a {@link LocaleRouteFunction} used to resolve localized route objects. */ export function useLocaleRoute(): LocaleRouteFunction { // @ts-expect-error - generated types conflict with the generic types we accept @@ -307,86 +257,49 @@ export function useLocaleRoute(): LocaleRouteFunction { } /** - * The function that resolve locale location. - * - * @remarks - * The parameter signature of this function is same as {@link localeLocation}. + * Resolves a localized variant of the passed route. * - * @param route - A route location. The path or name of the route or an object for more complex routes. - * @param locale - A locale optional, if not specified, uses the current locale. + * @param route - a route name or route object. + * @param locale - (default: current locale). * - * @returns the location object for a given route, the location object is resolved by vue-router rather than just a full route path. + * @returns A resolved route object * - * @see {@link useLocaleLocation} - * - * @public + * @deprecated use {@link useLocaleRoute}/{@link LocaleRouteFunction $localeRoute} instead */ export type LocaleLocationFunction = ( - route: Name | (Omit & { path?: string }), - /** - * Note: disabled route path string autocompletion, this can break depending on `strategy` - * this can be enabled again after route resolve has been improved. - */ - // | RouteLocationAsStringI18n - // | RouteLocationAsPathI18n + route: Name | RouteLocationI18nGenericPath, locale?: Locale ) => RouteLocationResolvedI18n | undefined /** - * The `useLocaleLocation` composable returns function that resolve the locale location. - * - * @remarks - * The function returned by `useLocaleLocation` is the wrapper function with the same signature as {@link localeLocation}. + * Returns a {@link LocaleLocationFunction} used to resolve localized route objects. * - * @returns A {@link LocaleLocationFunction}. - * - * @public + * @deprecated use {@link useLocaleRoute}/{@link LocaleRouteFunction $localeRoute} instead */ export function useLocaleLocation(): LocaleLocationFunction { + // we wrap `localeRoute` as the implementation is identical // @ts-expect-error - generated types conflict with the generic types we accept - return wrapComposable(localeLocation) + return wrapComposable(localeRoute) } /** - * The function that switch locale path. - * - * @remarks - * The parameter signature of this function is same as {@link switchLocalePath}. - * - * @param locale - A locale optional, if not specified, uses the current locale. - * - * @returns A link to the current route in another language. + * Resolves a localized variant of the current path. * - * @see {@link useSwitchLocalePath} - * - * @public + * @param locale - (default: current locale). */ export type SwitchLocalePathFunction = (locale: Locale) => string /** - * The `useSwitchLocalePath` composable returns function that resolve the locale location. - * - * @remarks - * The function returned by `useSwitchLocalePath` is the wrapper function with the same signature as {@link switchLocalePath}. - * - * @returns A {@link SwitchLocalePathFunction}. - * - * @public + * Returns a {@link SwitchLocalePathFunction} used to resolve a localized variant of the current path. */ - export function useSwitchLocalePath(): SwitchLocalePathFunction { return wrapComposable(switchLocalePath) } /** - * The `useBrowserLocale` composable returns the browser locale. - * - * @remarks - * if this composable function is called on client-side, it detects the locale from the value of `navigator.languages`. Else on the server side, the locale is detected from the value of `accept-language` header. + * Return the browser locale based on `navigator.languages` (client-side) or `accept-language` header (server-side). * * @returns the browser locale, if not detected, return `null`. - * - * @public */ export function useBrowserLocale(): string | null { const headers = useRequestHeaders(['accept-language']) @@ -399,19 +312,14 @@ export function useBrowserLocale(): string | null { } /** - * The `useCookieLocale` composable returns the cookie locale. - * - * @remarks - * If this composable function is called client-side, it detects the locale from the value of `document.cookie` via `useCookie`. Otherwise when used server-side, it detects the locale from the value of the `cookie` header. + * Returns the locale cookie based on `document.cookie` (client-side) or `cookie` header (server-side). * - * Note that if the value of `detectBrowserLanguage.useCookie` is `false`, an empty string is always returned. + * @remark + * If `detectBrowserLanguage.useCookie` is `false` this will always return an empty string. * - * @returns the cookie locale with Vue `ref`. if not detected, return **empty string** with `ref`. - * - * @public + * @returns a `Ref` with the detected cookie or an empty string if none is detected. */ export function useCookieLocale(): Ref { - // Support for importing from `#imports` is generated by auto `imports` nuxt module, so `ref` is imported from `vue` const locale: Ref = ref('') const detect = runtimeDetectBrowserLanguage() @@ -443,12 +351,6 @@ const warnRuntimeUsage = (method: string) => 'compiled away and passing it at runtime has no effect.' ) -/** - * TODO: - * `paths`, `locales` completions like `unplugin-vue-router` - * ref: https://github.com/posva/unplugin-vue-router - */ - /** * The i18n custom route for page components */ @@ -460,7 +362,7 @@ export interface I18nRoute { */ paths?: Partial> /** - * Some locales to which the page component should be localized. + * Locales in which the page component should be localized. */ locales?: Locale[] } diff --git a/src/runtime/injections.ts b/src/runtime/injections.ts deleted file mode 100644 index a9f80d693..000000000 --- a/src/runtime/injections.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { - LocaleHeadFunction, - LocalePathFunction, - LocaleRouteFunction, - RouteBaseNameFunction, - SwitchLocalePathFunction -} from '#i18n' -import type { localeHead } from './routing/compatibles/head' -import type { - getRouteBaseName, - localeLocation, - localePath, - localeRoute, - switchLocalePath -} from './routing/compatibles/routing' - -export type NuxtI18nPluginInjections = { - /** - * Returns base name of current (if argument not provided) or passed in route. - * - * @remarks - * Base name is name of the route without locale suffix and other metadata added by nuxt i18n module - * - * @param givenRoute - A route. - * - * @returns The route base name. if cannot get, `undefined` is returned. - */ - getRouteBaseName: (...args: Parameters) => ReturnType - /** - * Returns localized path for passed in route. - * - * @remarks - * If locale is not specified, uses current locale. - * - * @param route - A route. - * @param locale - A locale, optional. - * - * @returns A path of the current route. - */ - localePath: (...args: Parameters) => ReturnType - /** - * Returns localized route for passed in `route` parameters. - * - * @remarks - * If `locale` is not specified, uses current locale. - * - * @param route - A route. - * @param locale - A {@link Locale | locale}, optional. - * - * @returns A route. if cannot resolve, `undefined` is returned. - */ - localeRoute: (...args: Parameters) => ReturnType - /** - * Returns localized head properties for locale-related aspects. - * - * @param options - An options object, see `I18nHeadOptions`. - * - * @returns The localized head properties. - */ - localeHead: (...args: Parameters) => ReturnType - /** - * Returns path of the current route for specified locale - * - * @param locale - A {@link Locale} - * - * @returns A path of the current route - */ - switchLocalePath: (...args: Parameters) => ReturnType - /** - * @deprecated use {@link localePath} or {@link localeRoute} instead - */ - resolveRoute: (...args: Parameters) => ReturnType - /** - * @deprecated use {@link localeRoute} instead - */ - localeLocation: (...args: Parameters) => ReturnType -} diff --git a/src/runtime/internal.ts b/src/runtime/internal.ts index 18cabafdb..3751065c1 100644 --- a/src/runtime/internal.ts +++ b/src/runtime/internal.ts @@ -32,11 +32,10 @@ export function defineGetter(obj: Record< type TailParameters = T extends (first: CommonComposableOptions, ...rest: infer R) => unknown ? R : never -export function wrapComposable any>( +export function wrapComposable ReturnType>( fn: F, common = initCommonComposableOptions() ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- FIXME return (...args: TailParameters) => fn(common, ...args) } diff --git a/src/runtime/plugins/i18n.ts b/src/runtime/plugins/i18n.ts index 3d255d4bd..7a9ce4b6a 100644 --- a/src/runtime/plugins/i18n.ts +++ b/src/runtime/plugins/i18n.ts @@ -28,21 +28,15 @@ import { extendI18n } from '../routing/extends/i18n' import { createLocaleFromRouteGetter } from '../routing/extends/router' import { createLogger } from 'virtual:nuxt-i18n-logger' import { getI18nTarget } from '../compatibility' -import { - getRouteBaseName, - localeLocation, - localePath, - localeRoute, - resolveRoute, - switchLocalePath -} from '../routing/compatibles/routing' +import { resolveRoute } from '../routing/compatibles/routing' import { localeHead } from '../routing/compatibles/head' +import { useLocalePath, useLocaleRoute, useRouteBaseName, useSwitchLocalePath, useLocaleLocation } from '../composables' -import type { NuxtI18nPluginInjections } from '../injections' import type { Locale, I18nOptions, Composer, I18n } from 'vue-i18n' import type { NuxtApp } from '#app' import type { LocaleObject } from '#internal-i18n-types' import type { I18nPublicRuntimeConfig } from '#internal-i18n-types' +import type { LocaleHeadFunction, ResolveRouteFunction } from '../composables' // TODO: use @nuxt/module-builder to stub/prepare types declare module '#app' { @@ -229,15 +223,15 @@ export default defineNuxtPlugin({ /** * TODO: remove type assertions while type narrowing based on generated types */ - localeHead: wrapComposable(localeHead) as NuxtI18nPluginInjections['localeHead'], - localePath: wrapComposable(localePath) as NuxtI18nPluginInjections['localePath'], - localeRoute: wrapComposable(localeRoute) as NuxtI18nPluginInjections['localeRoute'], - getRouteBaseName: wrapComposable(getRouteBaseName) as NuxtI18nPluginInjections['getRouteBaseName'], - switchLocalePath: wrapComposable(switchLocalePath) as NuxtI18nPluginInjections['switchLocalePath'], + localeHead: wrapComposable(localeHead) as LocaleHeadFunction, + localePath: useLocalePath(), + localeRoute: useLocaleRoute(), + getRouteBaseName: useRouteBaseName(), + switchLocalePath: useSwitchLocalePath(), // TODO: remove in v10 - resolveRoute: wrapComposable(resolveRoute) as NuxtI18nPluginInjections['resolveRoute'], + resolveRoute: wrapComposable(resolveRoute) as ResolveRouteFunction, // TODO: remove in v10 - localeLocation: wrapComposable(localeLocation) as NuxtI18nPluginInjections['localeLocation'] + localeLocation: useLocaleLocation() } } }