nuxt-i18n-micro 3.30.3 → 4.0.1

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.
Files changed (111) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -2
  3. package/dist/client/200.html +1 -1
  4. package/dist/client/404.html +1 -1
  5. package/dist/client/_nuxt/BVna_KKx.js +3 -0
  6. package/dist/client/_nuxt/Bw81RhAv.js +1 -0
  7. package/dist/client/_nuxt/CPz_jhsD.js +1 -0
  8. package/dist/client/_nuxt/CmvObVGq.js +1 -0
  9. package/dist/client/_nuxt/DKUOBR6F.js +5 -0
  10. package/dist/client/_nuxt/builds/latest.json +1 -1
  11. package/dist/client/_nuxt/builds/meta/356b87e3-45dd-4f80-a40a-b649665c1844.json +1 -0
  12. package/dist/client/_nuxt/{entry.BM-mexAv.css → entry.PSWtHhay.css} +1 -1
  13. package/dist/client/_nuxt/error-404.xs3fxhVJ.css +1 -0
  14. package/dist/client/_nuxt/error-500.C2S-4iLg.css +1 -0
  15. package/dist/client/index.html +1 -1
  16. package/dist/module.d.mts +14 -5
  17. package/dist/module.json +4 -1
  18. package/dist/module.mjs +857 -476
  19. package/dist/runtime/components/i18n-group.d.vue.ts +17 -9
  20. package/dist/runtime/components/i18n-group.vue +2 -4
  21. package/dist/runtime/components/i18n-group.vue.d.ts +17 -9
  22. package/dist/runtime/components/i18n-link.d.vue.ts +9 -6
  23. package/dist/runtime/components/i18n-link.vue +7 -28
  24. package/dist/runtime/components/i18n-link.vue.d.ts +9 -6
  25. package/dist/runtime/components/i18n-switcher.d.vue.ts +128 -54
  26. package/dist/runtime/components/i18n-switcher.vue +56 -156
  27. package/dist/runtime/components/i18n-switcher.vue.d.ts +128 -54
  28. package/dist/runtime/components/i18n-t.d.vue.ts +59 -116
  29. package/dist/runtime/components/i18n-t.vue +24 -71
  30. package/dist/runtime/components/i18n-t.vue.d.ts +59 -116
  31. package/dist/runtime/composables/useI18n.js +2 -38
  32. package/dist/runtime/composables/useI18nHead.js +21 -6
  33. package/dist/runtime/composables/useI18nLocale.d.ts +4 -1
  34. package/dist/runtime/composables/useI18nLocale.js +20 -22
  35. package/dist/runtime/composables/useLocaleHead.d.ts +26 -31
  36. package/dist/runtime/composables/useLocaleHead.js +47 -167
  37. package/dist/runtime/devtools/bridge.d.ts +2 -2
  38. package/dist/runtime/devtools/vue-devtools.d.ts +2 -2
  39. package/dist/runtime/devtools/vue-devtools.js +5 -5
  40. package/dist/runtime/middleware/i18n-redirect.global.d.ts +3 -2
  41. package/dist/runtime/middleware/i18n-redirect.global.js +30 -41
  42. package/dist/runtime/plugins/01.plugin.d.ts +156 -34
  43. package/dist/runtime/plugins/01.plugin.js +184 -138
  44. package/dist/runtime/plugins/02.meta.js +36 -43
  45. package/dist/runtime/plugins/04.vue-devtools.js +1 -1
  46. package/dist/runtime/plugins/06.redirect.d.ts +3 -3
  47. package/dist/runtime/plugins/06.redirect.js +65 -91
  48. package/dist/runtime/server/{utils → internal}/dev-live-translations.js +4 -3
  49. package/dist/runtime/server/internal/server-translation-cache.d.ts +9 -0
  50. package/dist/runtime/server/internal/server-translation-cache.js +10 -0
  51. package/dist/runtime/server/internal/shared-cache.d.ts +24 -0
  52. package/dist/runtime/server/internal/shared-cache.js +71 -0
  53. package/dist/runtime/server/internal/translation-watcher.d.ts +79 -0
  54. package/dist/runtime/server/internal/translation-watcher.js +105 -0
  55. package/dist/runtime/server/middleware/i18n.global.js +24 -37
  56. package/dist/runtime/server/payload-source.assets.d.ts +1 -0
  57. package/dist/runtime/server/payload-source.assets.js +3 -8
  58. package/dist/runtime/server/payload-source.fs.d.ts +1 -0
  59. package/dist/runtime/server/payload-source.fs.js +18 -7
  60. package/dist/runtime/server/plugins/failed-read.d.ts +7 -0
  61. package/dist/runtime/server/plugins/failed-read.js +23 -0
  62. package/dist/runtime/server/plugins/payload-cache.d.ts +6 -0
  63. package/dist/runtime/server/plugins/payload-cache.js +16 -0
  64. package/dist/runtime/server/plugins/watcher.dev.js +15 -79
  65. package/dist/runtime/server/routes/i18n.js +13 -14
  66. package/dist/runtime/server/utils/locale-detector.d.ts +32 -2
  67. package/dist/runtime/server/utils/locale-detector.js +48 -27
  68. package/dist/runtime/server/utils/locale-server-middleware.js +14 -33
  69. package/dist/runtime/server/utils/payload-cache.d.ts +4 -0
  70. package/dist/runtime/server/utils/payload-cache.js +13 -0
  71. package/dist/runtime/server/utils/server-loader.d.ts +17 -6
  72. package/dist/runtime/server/utils/server-loader.js +105 -51
  73. package/dist/runtime/server/utils/translation-server-middleware.js +18 -35
  74. package/dist/runtime/utils/cache-keys.d.ts +6 -0
  75. package/dist/runtime/utils/cache-keys.js +2 -0
  76. package/dist/runtime/utils/i18n-api.d.ts +185 -0
  77. package/dist/runtime/utils/i18n-api.js +196 -0
  78. package/dist/runtime/utils/i18n-config.d.ts +18 -0
  79. package/dist/runtime/utils/i18n-config.js +47 -0
  80. package/dist/runtime/utils/i18n-navigation.d.ts +26 -0
  81. package/dist/runtime/utils/i18n-navigation.js +96 -0
  82. package/dist/runtime/utils/nuxt-i18n-server.d.ts +26 -0
  83. package/dist/runtime/utils/nuxt-i18n-server.js +83 -0
  84. package/dist/runtime/utils/nuxt-i18n.d.ts +81 -96
  85. package/dist/runtime/utils/nuxt-i18n.js +180 -252
  86. package/dist/runtime/utils/page-head.d.ts +12 -0
  87. package/dist/runtime/utils/page-head.js +6 -0
  88. package/dist/runtime/utils/request-url.d.ts +6 -0
  89. package/dist/runtime/utils/request-url.js +11 -0
  90. package/dist/runtime/utils/storage.d.ts +31 -19
  91. package/dist/runtime/utils/storage.js +100 -49
  92. package/dist/runtime/utils/translation-entry.d.ts +6 -0
  93. package/dist/runtime/utils/translation-entry.js +16 -0
  94. package/dist/types.d.mts +4 -6
  95. package/internals.d.mts +9 -2
  96. package/package.json +78 -79
  97. package/dist/client/_nuxt/BOxWElQP.js +0 -21
  98. package/dist/client/_nuxt/CUWB4CwN.js +0 -3
  99. package/dist/client/_nuxt/CmUbe-uv.js +0 -1
  100. package/dist/client/_nuxt/DAzShkZF.js +0 -1
  101. package/dist/client/_nuxt/MokPP5zi.js +0 -1
  102. package/dist/client/_nuxt/builds/meta/60974e48-d00e-4f9b-9467-9d4b322519da.json +0 -1
  103. package/dist/client/_nuxt/error-404.D9Svp6Hk.css +0 -1
  104. package/dist/client/_nuxt/error-500.B-mjI9_9.css +0 -1
  105. package/dist/runtime/plugins/03.define.d.ts +0 -7
  106. package/dist/runtime/plugins/03.define.js +0 -42
  107. package/dist/runtime/plugins/05.hooks.d.ts +0 -2
  108. package/dist/runtime/plugins/05.hooks.js +0 -47
  109. package/dist/runtime/server/utils/server-translation-cache.d.ts +0 -11
  110. package/dist/runtime/server/utils/server-translation-cache.js +0 -20
  111. /package/dist/runtime/server/{utils → internal}/dev-live-translations.d.ts +0 -0
@@ -1,9 +1,23 @@
1
1
  declare const _default: typeof __VLS_export;
2
2
  export default _default;
3
+ export type __VLS_LocalComponents = {};
4
+ export type __VLS_GlobalComponents = import("vue").GlobalComponents;
5
+ export type __VLS_LocalDirectives = {};
6
+ export type __VLS_Slots = ReturnType<typeof __VLS_template>["__VLS_Slots"];
7
+ export type __VLS_WithSlots<T, S> = T & {
8
+ new (): {
9
+ $slots: S;
10
+ };
11
+ };
3
12
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
4
- type __VLS_WithSlots<T, S> = T & (new () => {
5
- $slots: S;
6
- });
13
+ declare function __VLS_template(): {
14
+ __VLS_Slots: {
15
+ default?: (props: {
16
+ prefix: string;
17
+ t: (key: any, params?: {}) => any;
18
+ }) => any;
19
+ };
20
+ };
7
21
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
8
22
  /** Key prefix every lookup inside the slot is resolved against. */
9
23
  prefix: {
@@ -29,9 +43,3 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
29
43
  }>> & Readonly<{}>, {
30
44
  groupClass: string;
31
45
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
32
- type __VLS_Slots = {
33
- default?: ((props: {
34
- prefix: string;
35
- t: (key: any, params?: {}) => any;
36
- }) => any) | undefined;
37
- };
@@ -6,7 +6,7 @@
6
6
  </template>
7
7
 
8
8
  <script setup>
9
- import { useNuxtApp, useRoute } from "#imports";
9
+ import { useNuxtApp } from "#imports";
10
10
  defineOptions({ name: "I18nGroup" });
11
11
  const props = defineProps({
12
12
  /** Key prefix every lookup inside the slot is resolved against. */
@@ -14,8 +14,6 @@ const props = defineProps({
14
14
  /** Extra class on the wrapper element. */
15
15
  groupClass: { type: String, default: "" }
16
16
  });
17
- const { $_t } = useNuxtApp();
18
- const route = useRoute();
19
- const $t = $_t(route);
17
+ const { $t } = useNuxtApp();
20
18
  const translate = (key, params = {}) => $t(`${props.prefix}.${key}`, params);
21
19
  </script>
@@ -1,9 +1,23 @@
1
1
  declare const _default: typeof __VLS_export;
2
2
  export default _default;
3
+ export type __VLS_LocalComponents = {};
4
+ export type __VLS_GlobalComponents = import("vue").GlobalComponents;
5
+ export type __VLS_LocalDirectives = {};
6
+ export type __VLS_Slots = ReturnType<typeof __VLS_template>["__VLS_Slots"];
7
+ export type __VLS_WithSlots<T, S> = T & {
8
+ new (): {
9
+ $slots: S;
10
+ };
11
+ };
3
12
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
4
- type __VLS_WithSlots<T, S> = T & (new () => {
5
- $slots: S;
6
- });
13
+ declare function __VLS_template(): {
14
+ __VLS_Slots: {
15
+ default?: (props: {
16
+ prefix: string;
17
+ t: (key: any, params?: {}) => any;
18
+ }) => any;
19
+ };
20
+ };
7
21
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
8
22
  /** Key prefix every lookup inside the slot is resolved against. */
9
23
  prefix: {
@@ -29,9 +43,3 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
29
43
  }>> & Readonly<{}>, {
30
44
  groupClass: string;
31
45
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
32
- type __VLS_Slots = {
33
- default?: ((props: {
34
- prefix: string;
35
- t: (key: any, params?: {}) => any;
36
- }) => any) | undefined;
37
- };
@@ -1,16 +1,19 @@
1
+ import type { CSSProperties } from 'vue';
1
2
  import type { RouteLocationNamedRaw, RouteLocationResolvedGeneric } from 'vue-router';
2
3
  interface Props {
3
4
  /** Target route. Localized automatically; an external URL is passed through unchanged. */
4
5
  to: RouteLocationNamedRaw | RouteLocationResolvedGeneric | string;
5
6
  /** Inline style applied while the link points at the current route. */
6
- activeStyle?: Partial<CSSStyleValue>;
7
+ activeStyle?: CSSProperties;
7
8
  }
8
- declare var __VLS_1: {}, __VLS_10: {};
9
- type __VLS_Slots = {} & {
10
- default?: (props: typeof __VLS_1) => any;
11
- } & {
12
- default?: (props: typeof __VLS_10) => any;
9
+ declare const __VLS_template: () => {
10
+ __VLS_Slots: {
11
+ default?: (props: {}) => any;
12
+ } & {
13
+ default?: (props: {}) => any;
14
+ };
13
15
  };
16
+ type __VLS_Slots = ReturnType<typeof __VLS_template>['__VLS_Slots'];
14
17
  declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
18
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
16
19
  declare const _default: typeof __VLS_export;
@@ -4,14 +4,15 @@
4
4
  <slot />
5
5
  </a>
6
6
 
7
- <NuxtLink v-else :to="$localePath(to)" :style="computedStyle">
7
+ <NuxtLink v-else :to="localizedPath" :style="computedStyle">
8
8
  <slot />
9
9
  </NuxtLink>
10
10
  </template>
11
11
 
12
12
  <script setup>
13
+ import { externalLinkHref, isSamePage } from "@i18n-micro/core";
13
14
  import { computed } from "vue";
14
- import { useNuxtApp, useRoute, useRouter } from "#imports";
15
+ import { useNuxtApp, useRoute } from "#imports";
15
16
  defineOptions({ name: "I18nLink" });
16
17
  const { $localePath } = useNuxtApp();
17
18
  const props = defineProps({
@@ -19,32 +20,10 @@ const props = defineProps({
19
20
  activeStyle: { type: Object, required: false }
20
21
  });
21
22
  const route = useRoute();
22
- const router = useRouter();
23
- const isExternalLink = computed(() => {
24
- if (typeof props.to === "string") {
25
- return /^(?:https?:\/\/|\/\/|[a-zA-Z0-9-]+\.[a-zA-Z]{2,})|tel:|mailto:/.test(props.to);
26
- }
27
- return false;
28
- });
29
- const externalHref = computed(() => {
30
- if (isExternalLink.value && typeof props.to === "string") {
31
- if (props.to.startsWith("//")) {
32
- return props.to;
33
- }
34
- if (!/^https?:\/\//.test(props.to)) {
35
- return `https://${props.to}`;
36
- }
37
- return props.to;
38
- }
39
- return void 0;
40
- });
41
- const isActive = computed(() => {
42
- if (isExternalLink.value) {
43
- return false;
44
- }
45
- const pathStr = $localePath(props.to);
46
- return route.path === router.resolve(pathStr).path;
47
- });
23
+ const externalHref = computed(() => externalLinkHref(props.to));
24
+ const isExternalLink = computed(() => externalHref.value !== void 0);
25
+ const localizedPath = computed(() => isExternalLink.value ? "" : $localePath(props.to));
26
+ const isActive = computed(() => !isExternalLink.value && isSamePage(route.path, localizedPath.value));
48
27
  const computedStyle = computed(() => {
49
28
  return isActive.value ? { ...props.activeStyle } : {};
50
29
  });
@@ -1,16 +1,19 @@
1
+ import type { CSSProperties } from 'vue';
1
2
  import type { RouteLocationNamedRaw, RouteLocationResolvedGeneric } from 'vue-router';
2
3
  interface Props {
3
4
  /** Target route. Localized automatically; an external URL is passed through unchanged. */
4
5
  to: RouteLocationNamedRaw | RouteLocationResolvedGeneric | string;
5
6
  /** Inline style applied while the link points at the current route. */
6
- activeStyle?: Partial<CSSStyleValue>;
7
+ activeStyle?: CSSProperties;
7
8
  }
8
- declare var __VLS_1: {}, __VLS_10: {};
9
- type __VLS_Slots = {} & {
10
- default?: (props: typeof __VLS_1) => any;
11
- } & {
12
- default?: (props: typeof __VLS_10) => any;
9
+ declare const __VLS_template: () => {
10
+ __VLS_Slots: {
11
+ default?: (props: {}) => any;
12
+ } & {
13
+ default?: (props: {}) => any;
14
+ };
13
15
  };
16
+ type __VLS_Slots = ReturnType<typeof __VLS_template>['__VLS_Slots'];
14
17
  declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
18
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
16
19
  declare const _default: typeof __VLS_export;
@@ -1,57 +1,108 @@
1
- import type { CSSProperties } from 'vue';
2
- interface Props {
1
+ import type { Locale } from '@i18n-micro/types';
2
+ import type { CSSProperties, PropType, SlotsType } from 'vue';
3
+ /**
4
+ * A locale switcher: a button showing the current locale and a dropdown of the rest,
5
+ * each linking to the equivalent route in that locale.
6
+ *
7
+ * It ships small inline default styles; each `custom*Style` prop is merged on top of the
8
+ * matching part, and the slots add markup around it. Locales with `disabled: true` are not listed.
9
+ * A click on a link is one navigation; with a modifier key it is the browser's (a new tab).
10
+ */
11
+ declare const _default: typeof __VLS_export;
12
+ export default _default;
13
+ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
14
+ /** Display name per locale code, overriding the `displayName` from the locale config. */
15
+ customLabels: {
16
+ type: PropType<Record<string, string>>;
17
+ default: () => {};
18
+ };
19
+ /** Inline style for the outer wrapper. */
20
+ customWrapperStyle: {
21
+ type: PropType<CSSProperties>;
22
+ default: () => {};
23
+ };
24
+ /** Inline style for the button that opens the dropdown. */
25
+ customButtonStyle: {
26
+ type: PropType<CSSProperties>;
27
+ default: () => {};
28
+ };
29
+ /** Inline style for the dropdown panel. */
30
+ customDropdownStyle: {
31
+ type: PropType<CSSProperties>;
32
+ default: () => {};
33
+ };
34
+ /** Inline style for each item in the dropdown. */
35
+ customItemStyle: {
36
+ type: PropType<CSSProperties>;
37
+ default: () => {};
38
+ };
39
+ /** Inline style for the link inside an item. */
40
+ customLinkStyle: {
41
+ type: PropType<CSSProperties>;
42
+ default: () => {};
43
+ };
44
+ /** Inline style for the link of the currently active locale. */
45
+ customActiveLinkStyle: {
46
+ type: PropType<CSSProperties>;
47
+ default: () => {};
48
+ };
49
+ /** Inline style for the *current* locale button when it is `disabled: true` in config. */
50
+ customDisabledLinkStyle: {
51
+ type: PropType<CSSProperties>;
52
+ default: () => {};
53
+ };
54
+ /** Inline style for the caret icon on the button. */
55
+ customIconStyle: {
56
+ type: PropType<CSSProperties>;
57
+ default: () => {};
58
+ };
59
+ }>, () => unknown, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
3
60
  /** Display name per locale code, overriding the `displayName` from the locale config. */
4
- customLabels?: Record<string, string>;
61
+ customLabels: {
62
+ type: PropType<Record<string, string>>;
63
+ default: () => {};
64
+ };
5
65
  /** Inline style for the outer wrapper. */
6
- customWrapperStyle?: CSSProperties;
66
+ customWrapperStyle: {
67
+ type: PropType<CSSProperties>;
68
+ default: () => {};
69
+ };
7
70
  /** Inline style for the button that opens the dropdown. */
8
- customButtonStyle?: CSSProperties;
71
+ customButtonStyle: {
72
+ type: PropType<CSSProperties>;
73
+ default: () => {};
74
+ };
9
75
  /** Inline style for the dropdown panel. */
10
- customDropdownStyle?: CSSProperties;
76
+ customDropdownStyle: {
77
+ type: PropType<CSSProperties>;
78
+ default: () => {};
79
+ };
11
80
  /** Inline style for each item in the dropdown. */
12
- customItemStyle?: CSSProperties;
81
+ customItemStyle: {
82
+ type: PropType<CSSProperties>;
83
+ default: () => {};
84
+ };
13
85
  /** Inline style for the link inside an item. */
14
- customLinkStyle?: CSSProperties;
86
+ customLinkStyle: {
87
+ type: PropType<CSSProperties>;
88
+ default: () => {};
89
+ };
15
90
  /** Inline style for the link of the currently active locale. */
16
- customActiveLinkStyle?: CSSProperties;
91
+ customActiveLinkStyle: {
92
+ type: PropType<CSSProperties>;
93
+ default: () => {};
94
+ };
17
95
  /** Inline style for the *current* locale button when it is `disabled: true` in config. */
18
- customDisabledLinkStyle?: CSSProperties;
96
+ customDisabledLinkStyle: {
97
+ type: PropType<CSSProperties>;
98
+ default: () => {};
99
+ };
19
100
  /** Inline style for the caret icon on the button. */
20
- customIconStyle?: CSSProperties;
21
- }
22
- declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {}, __VLS_7: {}, __VLS_9: {}, __VLS_11: {
23
- locale: any;
24
- }, __VLS_21: {
25
- locale: any;
26
- }, __VLS_23: {
27
- locale: any;
28
- }, __VLS_25: {
29
- locale: any;
30
- }, __VLS_27: {}, __VLS_29: {};
31
- type __VLS_Slots = {} & {
32
- 'before-button'?: (props: typeof __VLS_1) => any;
33
- } & {
34
- 'before-selected-locale'?: (props: typeof __VLS_3) => any;
35
- } & {
36
- 'after-selected-locale'?: (props: typeof __VLS_5) => any;
37
- } & {
38
- 'before-dropdown'?: (props: typeof __VLS_7) => any;
39
- } & {
40
- 'before-dropdown-items'?: (props: typeof __VLS_9) => any;
41
- } & {
42
- 'before-item'?: (props: typeof __VLS_11) => any;
43
- } & {
44
- 'before-link-content'?: (props: typeof __VLS_21) => any;
45
- } & {
46
- 'after-link-content'?: (props: typeof __VLS_23) => any;
47
- } & {
48
- 'after-item'?: (props: typeof __VLS_25) => any;
49
- } & {
50
- 'after-dropdown-items'?: (props: typeof __VLS_27) => any;
51
- } & {
52
- 'after-dropdown'?: (props: typeof __VLS_29) => any;
53
- };
54
- declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
101
+ customIconStyle: {
102
+ type: PropType<CSSProperties>;
103
+ default: () => {};
104
+ };
105
+ }>> & Readonly<{}>, {
55
106
  customLabels: Record<string, string>;
56
107
  customWrapperStyle: CSSProperties;
57
108
  customButtonStyle: CSSProperties;
@@ -61,12 +112,35 @@ declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, i
61
112
  customActiveLinkStyle: CSSProperties;
62
113
  customDisabledLinkStyle: CSSProperties;
63
114
  customIconStyle: CSSProperties;
64
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
65
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
66
- declare const _default: typeof __VLS_export;
67
- export default _default;
68
- type __VLS_WithSlots<T, S> = T & {
69
- new (): {
70
- $slots: S;
71
- };
72
- };
115
+ }, SlotsType<{
116
+ /** Content before the button that opens the dropdown. */
117
+ 'before-button': () => unknown;
118
+ /** Content before the active locale label inside the button. */
119
+ 'before-selected-locale': () => unknown;
120
+ /** Content after the active locale label inside the button. */
121
+ 'after-selected-locale': () => unknown;
122
+ /** Content between the button and the dropdown panel. */
123
+ 'before-dropdown': () => unknown;
124
+ /** Content at the top of the dropdown, above the locale list. */
125
+ 'before-dropdown-items': () => unknown;
126
+ /** Content before each locale entry. */
127
+ 'before-item': (scope: {
128
+ locale: Locale;
129
+ }) => unknown;
130
+ /** Content before a locale's label inside its link. */
131
+ 'before-link-content': (scope: {
132
+ locale: Locale;
133
+ }) => unknown;
134
+ /** Content after a locale's label inside its link. */
135
+ 'after-link-content': (scope: {
136
+ locale: Locale;
137
+ }) => unknown;
138
+ /** Content after each locale entry. */
139
+ 'after-item': (scope: {
140
+ locale: Locale;
141
+ }) => unknown;
142
+ /** Content at the bottom of the dropdown, below the locale list. */
143
+ 'after-dropdown-items': () => unknown;
144
+ /** Content after the dropdown panel. */
145
+ 'after-dropdown': () => unknown;
146
+ }>, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -1,159 +1,59 @@
1
- <template>
2
- <div :style="[wrapperStyle, customWrapperStyle]">
3
- <!-- @slot Content before the button that opens the dropdown. -->
4
- <slot name="before-button" />
5
-
6
- <button
7
- class="language-switcher"
8
- :style="[buttonStyle, customButtonStyle, currentLocaleDisabled ? customDisabledLinkStyle : {}]"
9
- @click="toggleDropdown"
10
- >
11
- <!-- @slot Content before the active locale label inside the button. -->
12
- <slot name="before-selected-locale" />
13
- {{ currentLocaleLabel }}
14
- <!-- @slot Content after the active locale label inside the button. -->
15
- <slot name="after-selected-locale" />
16
- <span :style="[iconStyle, dropdownOpen ? openIconStyle : {}, customIconStyle]">&#9662;</span>
17
- </button>
18
-
19
- <!-- @slot Content between the button and the dropdown panel. -->
20
- <slot name="before-dropdown" />
21
-
22
- <ul v-show="dropdownOpen" :style="[dropdownStyle, customDropdownStyle]">
23
- <!-- @slot Content at the top of the dropdown, above the locale list. -->
24
- <slot name="before-dropdown-items" />
25
-
26
- <li v-for="locale in locales" :key="locale.code" :style="[itemStyle, customItemStyle]">
27
- <!-- @slot Content before each locale entry. -->
28
- <slot name="before-item" :locale="locale" />
29
-
30
- <NuxtLink
31
- :class="`switcher-locale-${locale.code}`"
32
- :to="switchLocaleRoute(locale.code)"
33
- :style="[
34
- linkStyle,
35
- locale.code === currentLocale ? activeLinkStyle : {},
36
- customLinkStyle,
37
- locale.code === currentLocale ? customActiveLinkStyle : {}
38
- ]"
39
- :hreflang="locale.iso || locale.code"
40
- @click="switchLocale(locale.code)"
41
- >
42
- <!-- @slot Content before a locale's label inside its link. -->
43
- <slot name="before-link-content" :locale="locale" />
44
- {{ localeLabel(locale) }}
45
- <!-- @slot Content after a locale's label inside its link. -->
46
- <slot name="after-link-content" :locale="locale" />
47
- </NuxtLink>
48
-
49
- <!-- @slot Content after each locale entry. -->
50
- <slot name="after-item" :locale="locale" />
51
- </li>
52
-
53
- <!-- @slot Content at the bottom of the dropdown, below the locale list. -->
54
- <slot name="after-dropdown-items" />
55
- </ul>
56
-
57
- <!-- @slot Content after the dropdown panel. -->
58
- <slot name="after-dropdown" />
59
- </div>
60
- </template>
61
-
62
- <script setup>
63
- import { computed, ref } from "vue";
64
- import { useNuxtApp } from "#imports";
65
- defineOptions({ name: "I18nSwitcher" });
66
- const props = defineProps({
67
- customLabels: { type: Object, required: false, default: () => ({}) },
68
- customWrapperStyle: { type: Object, required: false, default: () => ({}) },
69
- customButtonStyle: { type: Object, required: false, default: () => ({}) },
70
- customDropdownStyle: { type: Object, required: false, default: () => ({}) },
71
- customItemStyle: { type: Object, required: false, default: () => ({}) },
72
- customLinkStyle: { type: Object, required: false, default: () => ({}) },
73
- customActiveLinkStyle: { type: Object, required: false, default: () => ({}) },
74
- customDisabledLinkStyle: { type: Object, required: false, default: () => ({}) },
75
- customIconStyle: { type: Object, required: false, default: () => ({}) }
76
- });
77
- const { $switchLocaleRoute, $switchLocale, $getLocales, $getLocale, $getLocaleName } = useNuxtApp();
78
- const allLocales = computed(() => $getLocales() ?? []);
79
- const locales = computed(() => allLocales.value.filter((locale) => !locale.disabled));
80
- const currentLocale = computed(() => $getLocale());
81
- const currentLocaleDisabled = computed(() => allLocales.value.some((l) => l.code === currentLocale.value && l.disabled));
82
- const currentLocaleName = computed(() => $getLocaleName());
83
- const dropdownOpen = ref(false);
84
- const toggleDropdown = () => {
85
- dropdownOpen.value = !dropdownOpen.value;
86
- };
87
- const switchLocaleRoute = (code) => {
88
- return $switchLocaleRoute(code);
89
- };
90
- const localeLabel = (locale) => {
91
- const current = props.customLabels[locale.code] || locale.displayName;
92
- if (!current && import.meta.dev) {
93
- console.warn(
94
- `[i18n-switcher] No label for "${locale.code}" \u2014 set a customLabels entry or a displayName in nuxt.config.i18n. Falling back to the code.`
1
+ <script>
2
+ import { createLocaleSwitcher } from "@i18n-micro/core/render";
3
+ import { hasProtocol } from "ufo";
4
+ import { defineComponent, Fragment, h, onMounted, onUnmounted, ref } from "vue";
5
+ import { useNuxtApp, useRouter } from "#imports";
6
+ export default defineComponent({
7
+ name: "I18nSwitcher",
8
+ props: {
9
+ /** Display name per locale code, overriding the `displayName` from the locale config. */
10
+ customLabels: { type: Object, default: () => ({}) },
11
+ /** Inline style for the outer wrapper. */
12
+ customWrapperStyle: { type: Object, default: () => ({}) },
13
+ /** Inline style for the button that opens the dropdown. */
14
+ customButtonStyle: { type: Object, default: () => ({}) },
15
+ /** Inline style for the dropdown panel. */
16
+ customDropdownStyle: { type: Object, default: () => ({}) },
17
+ /** Inline style for each item in the dropdown. */
18
+ customItemStyle: { type: Object, default: () => ({}) },
19
+ /** Inline style for the link inside an item. */
20
+ customLinkStyle: { type: Object, default: () => ({}) },
21
+ /** Inline style for the link of the currently active locale. */
22
+ customActiveLinkStyle: { type: Object, default: () => ({}) },
23
+ /** Inline style for the *current* locale button when it is `disabled: true` in config. */
24
+ customDisabledLinkStyle: { type: Object, default: () => ({}) },
25
+ /** Inline style for the caret icon on the button. */
26
+ customIconStyle: { type: Object, default: () => ({}) }
27
+ },
28
+ slots: Object,
29
+ setup(props, { slots }) {
30
+ const { $switchLocalePath, $switchLocale, $getLocales, $getLocale, $getLocaleName } = useNuxtApp();
31
+ const router = useRouter();
32
+ return createLocaleSwitcher(
33
+ { h, Fragment, ref, onMounted, onUnmounted },
34
+ {
35
+ // `$getLocales()` stays complete for SEO/meta; the switcher lists only the enabled ones
36
+ locales: () => $getLocales() ?? [],
37
+ locale: () => $getLocale(),
38
+ localeName: () => $getLocaleName(),
39
+ // the router adds `app.baseURL`; a URL of another domain is complete already
40
+ href: (code) => {
41
+ const path = $switchLocalePath(code);
42
+ return hasProtocol(path) ? path : router.resolve(path).href;
43
+ },
44
+ select: (code) => void $switchLocale(code),
45
+ // in the server HTML, for crawlers
46
+ keepList: true,
47
+ onMissingLabel: (code) => {
48
+ if (!import.meta.dev) return;
49
+ console.warn(
50
+ `[i18n-switcher] No label for "${code}" \u2014 set a customLabels entry or a displayName in nuxt.config.i18n. Falling back to the code.`
51
+ );
52
+ }
53
+ },
54
+ props,
55
+ slots
95
56
  );
96
57
  }
97
- return current || locale.code;
98
- };
99
- const currentLocaleLabel = computed(
100
- () => localeLabel({
101
- code: currentLocale.value,
102
- displayName: currentLocaleName.value ?? void 0
103
- })
104
- );
105
- const switchLocale = (code) => {
106
- toggleDropdown();
107
- $switchLocale(code);
108
- };
109
- const wrapperStyle = {
110
- position: "relative",
111
- display: "inline-block"
112
- };
113
- const buttonStyle = {
114
- padding: "4px 12px",
115
- fontSize: "16px",
116
- cursor: "pointer",
117
- backgroundColor: "#fff",
118
- border: "1px solid #333",
119
- transition: "background-color 0.3s ease",
120
- display: "flex",
121
- alignItems: "center",
122
- justifyContent: "space-between"
123
- };
124
- const dropdownStyle = {
125
- position: "absolute",
126
- top: "100%",
127
- left: "0",
128
- zIndex: "10",
129
- backgroundColor: "#fff",
130
- border: "1px solid #333",
131
- listStyle: "none",
132
- padding: "0",
133
- margin: "4px 0 0 0"
134
- };
135
- const itemStyle = {
136
- margin: "0",
137
- padding: "0"
138
- };
139
- const linkStyle = {
140
- display: "block",
141
- padding: "8px 12px",
142
- color: "#333",
143
- textDecoration: "none",
144
- transition: "background-color 0.3s ease"
145
- };
146
- const activeLinkStyle = {
147
- fontWeight: "bold",
148
- color: "#007bff",
149
- // Current locale is not a meaningful switch target
150
- cursor: "not-allowed"
151
- };
152
- const iconStyle = {
153
- marginLeft: "8px",
154
- transition: "transform 0.3s ease"
155
- };
156
- const openIconStyle = {
157
- transform: "rotate(180deg)"
158
- };
58
+ });
159
59
  </script>