From 757195a65a842065a793c8c5a3de605a51ccb96a Mon Sep 17 00:00:00 2001 From: Bobbie Goede Date: Thu, 26 Dec 2024 12:41:02 +0100 Subject: [PATCH] refactor: merge types and move prefixable util (#3284) --- src/internal-global-types.d.ts | 7 +- src/runtime/plugins/i18n.ts | 9 +-- src/runtime/routing/routing.ts | 17 +---- src/runtime/types.ts | 125 ++++++++------------------------- src/runtime/utils.ts | 15 +++- 5 files changed, 45 insertions(+), 128 deletions(-) diff --git a/src/internal-global-types.d.ts b/src/internal-global-types.d.ts index cce768e84..5ab9ebff8 100644 --- a/src/internal-global-types.d.ts +++ b/src/internal-global-types.d.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-var, @typescript-eslint/no-redundant-type-constituents */ import type { Composer, ExportedGlobalComposer, VueI18n } from 'vue-i18n' import type { ComposerCustomProperties, NuxtI18nRoutingCustomProperties } from './runtime/types' @@ -10,10 +9,11 @@ declare module 'vue-i18n' { declare module '#app' { interface NuxtApp { - $i18n: VueI18n & ExportedGlobalComposer & Composer & NuxtI18nRoutingCustomProperties & I18nRoutingCustomProperties + $i18n: VueI18n & ExportedGlobalComposer & Composer & NuxtI18nRoutingCustomProperties } } +/* eslint-disable no-var */ declare global { var $t: Composer['t'] var $rt: Composer['rt'] @@ -22,7 +22,6 @@ declare global { var $tm: Composer['tm'] var $te: Composer['te'] } +/* eslint-enable no-var */ export {} - -/* eslint-enable no-var, @typescript-eslint/no-redundant-type-constituents */ diff --git a/src/runtime/plugins/i18n.ts b/src/runtime/plugins/i18n.ts index c345bd957..ab0490e34 100644 --- a/src/runtime/plugins/i18n.ts +++ b/src/runtime/plugins/i18n.ts @@ -31,19 +31,12 @@ import { resolveRoute } from '../routing/routing' import { localeHead } from '../routing/head' import { useLocalePath, useLocaleRoute, useRouteBaseName, useSwitchLocalePath, useLocaleLocation } from '../composables' -import type { Locale, I18nOptions, Composer, I18n } from 'vue-i18n' +import type { Locale, I18nOptions, Composer } 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' { - interface NuxtApp { - _vueI18n: I18n - } -} - export default defineNuxtPlugin({ name: 'i18n:plugin', parallel: parallelPlugin, diff --git a/src/runtime/routing/routing.ts b/src/runtime/routing/routing.ts index 08a1c4ef9..6b6cccc2b 100644 --- a/src/runtime/routing/routing.ts +++ b/src/runtime/routing/routing.ts @@ -9,24 +9,9 @@ import { extendPrefixable, extendSwitchLocalePathIntercepter, type CommonComposa import type { Locale } from 'vue-i18n' import type { RouteLocationRaw, RouteLocationPathRaw, RouteLocationNamedRaw, RouteRecordNameGeneric } from 'vue-router' -import type { I18nPublicRuntimeConfig, PrefixableOptions, Strategies } from '#internal-i18n-types' +import type { I18nPublicRuntimeConfig } from '#internal-i18n-types' import type { CompatRoute } from '../types' -const RESOLVED_PREFIXED = new Set(['prefix_and_default', 'prefix_except_default']) - -function prefixable(options: PrefixableOptions): boolean { - const { currentLocale, defaultLocale, strategy } = options - const isDefaultLocale = currentLocale === defaultLocale - // don't prefix default locale - return ( - !(isDefaultLocale && RESOLVED_PREFIXED.has(strategy)) && - // no prefix for any language - !(strategy === 'no_prefix') - ) -} - -export const DefaultPrefixable = prefixable - /** * Returns base name of current (if argument not provided) or passed in route. * diff --git a/src/runtime/types.ts b/src/runtime/types.ts index 296eb4e01..2778d46f4 100644 --- a/src/runtime/types.ts +++ b/src/runtime/types.ts @@ -1,7 +1,7 @@ import type { NuxtApp } from '#app' import type { ComputedRef } from 'vue' import type { Directions, LocaleObject, Strategies } from '#internal-i18n-types' -import type { Locale } from 'vue-i18n' +import type { I18n, Locale } from 'vue-i18n' import type { RouteLocationNormalizedGeneric, RouteRecordNameGeneric } from 'vue-router' export type CompatRoute = Omit & { @@ -36,32 +36,11 @@ type BeforeLanguageSwitchHandler = ( */ type LanguageSwitchedHandler = (oldLocale: Locale, newLocale: Locale) => Promise -export interface ComposerCustomProperties< - ConfiguredLocaleType extends Locale[] | LocaleObject[] = Locale[] | LocaleObject[] -> { - /** - * 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 +interface SharedProperties { /** * Routing strategy. */ strategy: Strategies - /** - * Current locale properties. - */ - localeProperties: ComputedRef /** * Whether differentDomains option is enabled. */ @@ -143,107 +122,59 @@ export interface ComposerCustomProperties< waitForPendingLocaleChange: () => Promise } -export interface NuxtI18nRoutingCustomProperties< +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 */ - readonly locales: ConfiguredLocaleType + locales: ComputedRef /** * List of locale codes */ - readonly localeCodes: Locale[] + localeCodes: ComputedRef /** * Base URL that is used in generating canonical links */ - baseUrl: string - /** - * Routing strategy. - */ - readonly strategy: Strategies + baseUrl: ComputedRef /** * Current locale properties. */ - localeProperties: LocaleObject - /** - * Whether differentDomains option is enabled. - */ - readonly differentDomains: boolean - /** - * Default direction as specified in options. - */ - readonly defaultDirection: Directions - /** - * Default locale as specified in options. - */ - readonly defaultLocale: Locale - /** - * Switches locale of the app to specified locale code. - * - * @remarks - * If `useCookie` option is enabled, locale cookie will be updated with new value. - * - * If prefixes are enabled (`strategy` other than `no_prefix`), will navigate to new locale's route. - * - * @param locale - A {@link Locale} - */ - setLocale: (locale: Locale) => Promise - /** - * Returns browser locale code filtered against the ones defined in options. - * - * @returns The browser locale. - */ - getBrowserLocale: () => string | undefined - /** - * Returns locale code from stored locale cookie. - * - * @returns The locale cookie - */ - getLocaleCookie: () => string | undefined - /** - * Updates stored locale cookie with specified locale code. - * - * @remarks - * Consider using `setLocale` instead if you want to switch locale. - * - * @param locale - A {@link Locale} - */ - setLocaleCookie: (locale: Locale) => void + localeProperties: ComputedRef +} + +export interface NuxtI18nRoutingCustomProperties< + ConfiguredLocaleType extends Locale[] | LocaleObject[] = Locale[] | LocaleObject[] +> extends SharedProperties { /** - * Called before the app's locale is switched. + * List of locales * * @remarks - * Can be used to override the new locale by returning a new locale code. - * - * @param oldLocale - The app's locale before the switch. - * @param newLocale - The app's locale after the switch. - * @param initialSetup - Set to `true` if it's the initial locale switch that triggers on app load. It's a special case since the locale is not technically set yet so we're switching from no locale to locale. - * @param context - the Nuxt app instance. - * - * @returns The new locale to switch, or `undefined` to keep the new locale. + * Can either be an array of string codes (e.g. `['en', 'fr']`) or an array of {@link LocaleObject} for more complex configurations */ - onBeforeLanguageSwitch: BeforeLanguageSwitchHandler + readonly locales: ConfiguredLocaleType /** - * Called after the app's locale is switched. - * - * @param oldLocale - The app's locale before the switch - * @param newLocale - The app's locale after the switch. + * List of locale codes */ - onLanguageSwitched: LanguageSwitchedHandler + readonly localeCodes: Locale[] /** - * Switches to the pending locale that would have been set on navigate, but was prevented by the `skipSettingLocaleOnNavigate` option. + * Base URL that is used in generating canonical links */ - finalizePendingLocaleChange: () => Promise + baseUrl: string /** - * Returns a promise that will be resolved once the pending locale is set. + * Current locale properties. */ - waitForPendingLocaleChange: () => Promise + localeProperties: LocaleObject +} - loadLocaleMessages: (locale: Locale) => Promise +declare module '#app' { + interface NuxtApp { + /** @internal */ + _vueI18n: I18n + } } declare module 'vue-i18n' { diff --git a/src/runtime/utils.ts b/src/runtime/utils.ts index a98be5725..c18f07fef 100644 --- a/src/runtime/utils.ts +++ b/src/runtime/utils.ts @@ -11,7 +11,7 @@ import { getHost } from './internal' import { loadLocale, makeFallbackLocaleCodes } from './messages' -import { localePath, switchLocalePath, DefaultPrefixable } from './routing/routing' +import { localePath, switchLocalePath } from './routing/routing' import { createLogger } from 'virtual:nuxt-i18n-logger' import { unref } from 'vue' @@ -327,13 +327,22 @@ export async function navigate( } } +function prefixable({ currentLocale, defaultLocale, strategy }: PrefixableOptions): boolean { + return ( + // strategy has no prefixes + strategy !== 'no_prefix' && + // strategy should not prefix default locale + !(currentLocale === defaultLocale && (strategy === 'prefix_and_default' || strategy === 'prefix_except_default')) + ) +} + // override prefix for route path, support domain export function extendPrefixable(runtimeConfig = useRuntimeConfig()) { const logger = /*#__PURE__*/ createLogger('extendPrefixable') return (opts: PrefixableOptions): boolean => { - __DEBUG__ && logger.log(DefaultPrefixable(opts)) + __DEBUG__ && logger.log(prefixable(opts)) - return DefaultPrefixable(opts) && !runtimeConfig.public.i18n.differentDomains + return prefixable(opts) && !runtimeConfig.public.i18n.differentDomains } }