nuxt-i18n-micro 3.29.3 → 3.29.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BAu8wLxk.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.BRCCa7jH.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BlsWt_np.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bo5omLnI.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.C7JgQlK0.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CSbZDNyO.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"652a5b66-66b7-45f2-a0fb-ea5f21477cbe",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789144005641,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BAu8wLxk.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.BRCCa7jH.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BlsWt_np.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bo5omLnI.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.C7JgQlK0.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CSbZDNyO.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"6385e487-b291-4cb4-8a64-ef47f393c2be",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789398317458,false]</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BAu8wLxk.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.BRCCa7jH.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BlsWt_np.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bo5omLnI.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.C7JgQlK0.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CSbZDNyO.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"652a5b66-66b7-45f2-a0fb-ea5f21477cbe",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789144005641,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BAu8wLxk.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.BRCCa7jH.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BlsWt_np.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bo5omLnI.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.C7JgQlK0.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CSbZDNyO.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"6385e487-b291-4cb4-8a64-ef47f393c2be",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789398317459,false]</script></body></html>
@@ -1 +1 @@
1
- {"id":"652a5b66-66b7-45f2-a0fb-ea5f21477cbe","timestamp":1789144002062}
1
+ {"id":"6385e487-b291-4cb4-8a64-ef47f393c2be","timestamp":1789398315001}
@@ -0,0 +1 @@
1
+ {"id":"6385e487-b291-4cb4-8a64-ef47f393c2be","timestamp":1789398315001,"prerendered":[]}
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BAu8wLxk.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.BRCCa7jH.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BlsWt_np.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bo5omLnI.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.C7JgQlK0.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CSbZDNyO.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"652a5b66-66b7-45f2-a0fb-ea5f21477cbe",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789144005641,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BAu8wLxk.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/CZxMDymS.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.BRCCa7jH.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BlsWt_np.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bo5omLnI.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.C7JgQlK0.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CSbZDNyO.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"6385e487-b291-4cb4-8a64-ef47f393c2be",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789398317459,false]</script></body></html>
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
3
  "configKey": "i18n",
4
- "version": "3.29.3",
4
+ "version": "3.29.5",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -539,6 +539,7 @@ function buildFullConfig(params) {
539
539
  strategy: options.strategy ?? "prefix_except_default",
540
540
  dateBuild,
541
541
  hashMode: nuxt.options?.router?.options?.hashMode ?? false,
542
+ trailingSlash: options.trailingSlash ?? nuxt.options.experimental?.defaults?.nuxtLink?.trailingSlash,
542
543
  apiBaseUrl: apiConfig.apiBaseUrl,
543
544
  apiBaseClientHost: apiConfig.apiBaseClientHost,
544
545
  isSSG,
@@ -5,6 +5,7 @@ import { resolveOgLocale, warnUnresolvedOgLocale } from "@i18n-micro/utils/resol
5
5
  import { joinURL, parseURL, withQuery } from "ufo";
6
6
  import { ref, unref, watch } from "vue";
7
7
  import { useNuxtApp, useRoute, useState } from "#app";
8
+ import { applyTrailingSlash } from "../utils/trailing-slash.js";
8
9
  export const useLocaleHead = ({
9
10
  addDirAttribute = true,
10
11
  identifierAttribute = "id",
@@ -74,17 +75,32 @@ export const useLocaleHead = ({
74
75
  if (!fullPath.startsWith("/")) {
75
76
  fullPath = `/${fullPath}`;
76
77
  }
77
- const matchedLocale = [...locales].sort((a, b) => b.code.length - a.code.length).find((locale2) => fullPath.startsWith(`/${locale2.code}`));
78
- let localizedPath = fullPath;
78
+ const whitelist = canonicalQueryWhitelist ?? [];
79
+ const trailingSlash = i18nConfig.trailingSlash;
80
+ const toSeoHref = (pathOrUrl) => {
81
+ if (!pathOrUrl) return "";
82
+ let href;
83
+ if (pathOrUrl.startsWith("http://") || pathOrUrl.startsWith("https://")) {
84
+ href = filterLocalizedHref(pathOrUrl, whitelist);
85
+ } else {
86
+ const filteredPath = filterLocalizedHref(pathOrUrl, whitelist);
87
+ href = joinURL(unref(baseUrl), filteredPath.startsWith("/") ? filteredPath : `/${filteredPath}`);
88
+ }
89
+ return applyTrailingSlash(href, trailingSlash);
90
+ };
91
+ const currentSwitchedPath = switchLocalePath(locale);
79
92
  let ogUrl;
80
- let canonicalPath;
81
- if (routeName.startsWith(localizedRouteNamePrefixResolved) && matchedLocale) {
82
- localizedPath = fullPath.slice(matchedLocale.code.length + 1);
83
- canonicalPath = filterQuery(localizedPath, canonicalQueryWhitelist ?? []);
84
- ogUrl = joinURL(unref(baseUrl), locale, canonicalPath);
93
+ if (currentSwitchedPath) {
94
+ ogUrl = toSeoHref(currentSwitchedPath);
85
95
  } else {
86
- canonicalPath = filterQuery(fullPath, canonicalQueryWhitelist ?? []);
87
- ogUrl = joinURL(unref(baseUrl), canonicalPath);
96
+ const matchedLocale = [...locales].sort((a, b) => b.code.length - a.code.length).find((localeItem) => fullPath.startsWith(`/${localeItem.code}`));
97
+ let localizedPath = fullPath;
98
+ if (routeName.startsWith(localizedRouteNamePrefixResolved) && matchedLocale) {
99
+ localizedPath = fullPath.slice(matchedLocale.code.length + 1);
100
+ ogUrl = applyTrailingSlash(joinURL(unref(baseUrl), locale, filterQuery(localizedPath, whitelist)), trailingSlash);
101
+ } else {
102
+ ogUrl = applyTrailingSlash(joinURL(unref(baseUrl), filterQuery(fullPath, whitelist)), trailingSlash);
103
+ }
88
104
  }
89
105
  const htmlAttrs = {
90
106
  lang: currentIso,
@@ -127,20 +143,12 @@ export const useLocaleHead = ({
127
143
  };
128
144
  const defaultLocale = i18nConfig.defaultLocale || "en";
129
145
  const defaultLocaleObj = allLocales.find((loc) => loc.code === defaultLocale);
130
- const whitelist = canonicalQueryWhitelist ?? [];
131
146
  const alternateLinks = isNoPrefixStrategy(strategy) ? [] : (() => {
132
147
  const hrefByCode = /* @__PURE__ */ new Map();
133
148
  for (const loc of localesForSeo) {
134
149
  const switchedPath = switchLocalePath(loc.code);
135
150
  if (!switchedPath) continue;
136
- let href;
137
- if (switchedPath.startsWith("http://") || switchedPath.startsWith("https://")) {
138
- href = filterLocalizedHref(switchedPath, whitelist);
139
- } else {
140
- const filteredPath = filterLocalizedHref(switchedPath, whitelist);
141
- href = joinURL(unref(baseUrl), filteredPath.startsWith("/") ? filteredPath : `/${filteredPath}`);
142
- }
143
- hrefByCode.set(String(loc.code), href);
151
+ hrefByCode.set(String(loc.code), toSeoHref(switchedPath));
144
152
  }
145
153
  return resolveHreflangAlternates(localesForSeo, {
146
154
  hreflangBaseLanguage: i18nConfig.hreflangBaseLanguage ?? false
@@ -161,17 +169,10 @@ export const useLocaleHead = ({
161
169
  if (!isNoPrefixStrategy(strategy) && defaultLocaleObj?.seo !== false) {
162
170
  const defaultSwitchedPath = switchLocalePath(defaultLocale);
163
171
  if (defaultSwitchedPath) {
164
- let xDefaultHref;
165
- if (defaultSwitchedPath.startsWith("http://") || defaultSwitchedPath.startsWith("https://")) {
166
- xDefaultHref = filterLocalizedHref(defaultSwitchedPath, whitelist);
167
- } else {
168
- const filteredPath = filterLocalizedHref(defaultSwitchedPath, whitelist);
169
- xDefaultHref = joinURL(unref(baseUrl), filteredPath.startsWith("/") ? filteredPath : `/${filteredPath}`);
170
- }
171
172
  xDefaultLink = {
172
173
  [identifierAttribute]: "i18n-xd",
173
174
  rel: "alternate",
174
- href: xDefaultHref,
175
+ href: toSeoHref(defaultSwitchedPath),
175
176
  hreflang: "x-default"
176
177
  };
177
178
  }
@@ -1,6 +1,8 @@
1
1
  import type { PathStrategy } from '@i18n-micro/path-strategy';
2
2
  import type { CleanTranslation, DefineI18nRouteConfig, I18nRouteParams, Locale, MissingHandler, ModuleOptionsExtend, Params, Translations, TranslationKey } from '@i18n-micro/types';
3
3
  import type { RouteLocationNamedRaw, RouteLocationNormalizedLoaded, RouteLocationRaw, RouteLocationResolved, RouteLocationResolvedGeneric } from 'vue-router';
4
+ import { type TranslationFn } from '../utils/nuxt-i18n.js';
5
+ export type { TranslationFn };
4
6
  declare const _default: import("nuxt/app").Plugin<{
5
7
  getI18nConfig: () => ModuleOptionsExtend;
6
8
  helper: {
@@ -15,9 +17,9 @@ declare const _default: import("nuxt/app").Plugin<{
15
17
  getLocales: () => Locale[];
16
18
  getRouteName: (route?: RouteLocationNormalizedLoaded | RouteLocationResolvedGeneric, locale?: string) => string;
17
19
  t: (key: TranslationKey, params?: Params, defaultValue?: string | null, routeContext?: unknown) => CleanTranslation;
18
- ts: (key: string, params?: Params, defaultValue?: string, route?: RouteLocationNormalizedLoaded) => string;
19
- _t: (route: RouteLocationNormalizedLoaded) => (key: string, params?: Params, defaultValue?: string | null) => CleanTranslation;
20
- _ts: (route: RouteLocationNormalizedLoaded) => (key: string, params?: Params, defaultValue?: string) => string;
20
+ ts: (key: TranslationKey, params?: Params, defaultValue?: string, route?: RouteLocationNormalizedLoaded) => string;
21
+ _t: (route: RouteLocationNormalizedLoaded) => TranslationFn<CleanTranslation>;
22
+ _ts: (route: RouteLocationNormalizedLoaded) => TranslationFn<string>;
21
23
  tc: (key: TranslationKey, count: number | Params, defaultValue?: string) => string;
22
24
  tn: {
23
25
  (value: number, options?: Intl.NumberFormatOptions): string;
@@ -58,9 +60,9 @@ declare const _default: import("nuxt/app").Plugin<{
58
60
  getLocales: () => Locale[];
59
61
  getRouteName: (route?: RouteLocationNormalizedLoaded | RouteLocationResolvedGeneric, locale?: string) => string;
60
62
  t: (key: TranslationKey, params?: Params, defaultValue?: string | null, routeContext?: unknown) => CleanTranslation;
61
- ts: (key: string, params?: Params, defaultValue?: string, route?: RouteLocationNormalizedLoaded) => string;
62
- _t: (route: RouteLocationNormalizedLoaded) => (key: string, params?: Params, defaultValue?: string | null) => CleanTranslation;
63
- _ts: (route: RouteLocationNormalizedLoaded) => (key: string, params?: Params, defaultValue?: string) => string;
63
+ ts: (key: TranslationKey, params?: Params, defaultValue?: string, route?: RouteLocationNormalizedLoaded) => string;
64
+ _t: (route: RouteLocationNormalizedLoaded) => TranslationFn<CleanTranslation>;
65
+ _ts: (route: RouteLocationNormalizedLoaded) => TranslationFn<string>;
64
66
  tc: (key: TranslationKey, count: number | Params, defaultValue?: string) => string;
65
67
  tn: {
66
68
  (value: number, options?: Intl.NumberFormatOptions): string;
@@ -89,7 +91,6 @@ declare const _default: import("nuxt/app").Plugin<{
89
91
  setMissingHandler: (handler: MissingHandler | null) => void;
90
92
  }>;
91
93
  export default _default;
92
- export type TranslationFn<T extends CleanTranslation> = (key: TranslationKey, params?: Params, defaultValue?: string | null) => T;
93
94
  export interface PluginsInjections {
94
95
  /** The active routing strategy, resolving locales to and from paths. */
95
96
  $i18nStrategy: PathStrategy;
@@ -4,6 +4,7 @@ import type { CleanTranslation, I18nRouteParams, MissingHandler, ModuleOptionsEx
4
4
  import type { RouteLocationNamedRaw, RouteLocationNormalizedLoaded, RouteLocationRaw, RouteLocationResolved, RouteLocationResolvedGeneric, Router } from 'vue-router';
5
5
  import type { GetLocaleFromRoute } from '../composables/useI18nLocale.js';
6
6
  import { type LoadOptions } from './storage.js';
7
+ export type TranslationFn<T extends CleanTranslation> = (key: TranslationKey, params?: Params, defaultValue?: string | null) => T;
7
8
  export interface RouteTranslationContext {
8
9
  locale: string;
9
10
  routeName: string;
@@ -86,8 +87,8 @@ export declare class NuxtI18n extends BaseI18n {
86
87
  mergeTranslations(newTranslations: Translations): void;
87
88
  loadPageTranslations(locale: string, routeName: string, translations: Translations): Promise<void>;
88
89
  mergeTranslationAsync(locale: string, routeName: string, newTranslations: Translations, loadIfMissing: LoadTranslationsChunk): Promise<void>;
89
- tForRoute(route: unknown): (key: string, params?: Params, defaultValue?: string | null) => CleanTranslation;
90
- tsForRoute(route: unknown): (key: string, params?: Params, defaultValue?: string) => string;
90
+ tForRoute(route: unknown): TranslationFn<CleanTranslation>;
91
+ tsForRoute(route: unknown): TranslationFn<string>;
91
92
  protected touch(): void;
92
93
  protected resolveLookup(key: TranslationKey, routeContext?: unknown): unknown | null;
93
94
  protected resolveHas(key: TranslationKey): boolean;
@@ -174,9 +175,9 @@ export declare function createNuxtI18nPluginApi(deps: NuxtI18nPluginApiDeps): {
174
175
  getLocales: () => import("@i18n-micro/types").Locale[];
175
176
  getRouteName: (route?: RouteLocationNormalizedLoaded | RouteLocationResolvedGeneric, locale?: string) => string;
176
177
  t: (key: TranslationKey, params?: Params, defaultValue?: string | null, routeContext?: unknown) => CleanTranslation;
177
- ts: (key: string, params?: Params, defaultValue?: string, route?: RouteLocationNormalizedLoaded) => string;
178
- _t: (route: RouteLocationNormalizedLoaded) => (key: string, params?: Params, defaultValue?: string | null) => CleanTranslation;
179
- _ts: (route: RouteLocationNormalizedLoaded) => (key: string, params?: Params, defaultValue?: string) => string;
178
+ ts: (key: TranslationKey, params?: Params, defaultValue?: string, route?: RouteLocationNormalizedLoaded) => string;
179
+ _t: (route: RouteLocationNormalizedLoaded) => TranslationFn<CleanTranslation>;
180
+ _ts: (route: RouteLocationNormalizedLoaded) => TranslationFn<string>;
180
181
  tc: (key: TranslationKey, count: number | Params, defaultValue?: string) => string;
181
182
  tn: {
182
183
  (value: number, options?: Intl.NumberFormatOptions): string;
@@ -9,6 +9,7 @@ import {
9
9
  import { deepMergeTranslationsRecursive } from "@i18n-micro/utils/deep-merge";
10
10
  import { shallowRef, triggerRef, unref } from "vue";
11
11
  import { translationStorage } from "./storage.js";
12
+ import { applyTrailingSlash } from "./trailing-slash.js";
12
13
  function toRouteLocationResolved(result) {
13
14
  const fullPath = result.fullPath ?? result.path ?? "";
14
15
  const path = result.path ?? fullPath.split("?")[0]?.split("#")[0] ?? fullPath;
@@ -214,7 +215,7 @@ export class NuxtI18n extends BaseI18n {
214
215
  return (key, params, defaultValue) => this.t(key, params, defaultValue, route);
215
216
  }
216
217
  tsForRoute(route) {
217
- return (key, params, defaultValue) => this.ts(key, params, defaultValue, route);
218
+ return (key, params, defaultValue) => this.ts(key, params, defaultValue ?? void 0, route);
218
219
  }
219
220
  touch() {
220
221
  this.contextSignal.value;
@@ -438,7 +439,7 @@ export function createNuxtI18nPluginApi(deps) {
438
439
  const route = router.currentRoute.value;
439
440
  const fromLocale = getCurrentLocale(route);
440
441
  const switched = i18nStrategy.switchLocaleRoute(fromLocale, toLocale, route, { i18nRouteParams: unref(i18nRouteParams.value) });
441
- return extractSwitchLocalePath(switched, router);
442
+ return applyTrailingSlash(extractSwitchLocalePath(switched, router), i18nConfig.trailingSlash);
442
443
  },
443
444
  switchLocale: async (toLocale) => {
444
445
  if (!isValidLocale(toLocale)) {
@@ -465,7 +466,7 @@ export function createNuxtI18nPluginApi(deps) {
465
466
  localePath(to, locale) {
466
467
  const targetLocale = locale !== void 0 && locale !== "" ? String(locale) : getCurrentLocale();
467
468
  const result = i18nStrategy.localeRoute(targetLocale, to, router.currentRoute.value);
468
- return result.fullPath ?? result.path ?? "";
469
+ return applyTrailingSlash(result.fullPath ?? result.path ?? "", i18nConfig.trailingSlash);
469
470
  },
470
471
  setI18nRouteParams: (value) => {
471
472
  i18nRouteParams.value = value;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Same rule as NuxtLink (`applyTrailingSlashBehavior`).
3
+ * Pass resolved `i18n.trailingSlash` (or Nuxt `experimental.defaults.nuxtLink.trailingSlash`).
4
+ */
5
+ export declare function applyTrailingSlash(to: string, trailingSlash?: 'append' | 'remove'): string;
@@ -0,0 +1,6 @@
1
+ import { hasProtocol, withTrailingSlash, withoutTrailingSlash } from "ufo";
2
+ export function applyTrailingSlash(to, trailingSlash) {
3
+ if (trailingSlash !== "append" && trailingSlash !== "remove") return to;
4
+ if (hasProtocol(to) && !to.startsWith("http")) return to;
5
+ return (trailingSlash === "append" ? withTrailingSlash : withoutTrailingSlash)(to, true);
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
- "version": "3.29.3",
3
+ "version": "3.29.5",
4
4
  "description": "Fast, lightweight i18n for Nuxt with strategy-based routing and minimal overhead.",
5
5
  "keywords": [
6
6
  "i18n",
@@ -82,13 +82,13 @@
82
82
  "sirv": "^2.0.3",
83
83
  "ufo": "^1.6.4",
84
84
  "unplugin": "^1.16.1 || ^2.0.0 || ^3.3.0",
85
- "@i18n-micro/core": "^1.3.17",
86
- "@i18n-micro/test-utils": "^1.2.14",
87
- "@i18n-micro/types": "^1.2.14",
88
- "@i18n-micro/route-strategy": "^1.1.24",
89
- "@i18n-micro/utils": "^1.0.22",
90
- "@i18n-micro/path-strategy": "^1.3.16",
91
- "@i18n-micro/hmr": "^1.0.14"
85
+ "@i18n-micro/hmr": "^1.0.15",
86
+ "@i18n-micro/test-utils": "^1.2.15",
87
+ "@i18n-micro/route-strategy": "^1.1.25",
88
+ "@i18n-micro/path-strategy": "^1.3.17",
89
+ "@i18n-micro/types": "^1.2.15",
90
+ "@i18n-micro/utils": "^1.0.23",
91
+ "@i18n-micro/core": "^1.3.18"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@nuxt/devtools": "^3.4.2",
@@ -1 +0,0 @@
1
- {"id":"652a5b66-66b7-45f2-a0fb-ea5f21477cbe","timestamp":1789144002062,"prerendered":[]}