diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/1.65.0.jpg b/1.65.0.jpg new file mode 100644 index 00000000..e9bd9f4f Binary files /dev/null and b/1.65.0.jpg differ diff --git a/404.html b/404.html new file mode 100644 index 00000000..f73591cb --- /dev/null +++ b/404.html @@ -0,0 +1,22 @@ + + + + + + 404 | Nuxt I18n Micro + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/api/events.html b/api/events.html new file mode 100644 index 00000000..c3a658bb --- /dev/null +++ b/api/events.html @@ -0,0 +1,55 @@ + + + + + + 📢 Events | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

📢 Events

🔄 i18n:register

The i18n:register event in Nuxt I18n Micro enables dynamic addition of translations to your application's global i18n context, making the internationalization process seamless and flexible. This event allows you to integrate new translations as needed, enhancing your application's localization capabilities.

📝 Event Details

  • Purpose:

    • Allows dynamic incorporation of additional translations into the existing set for a specific locale.
  • Payload:

    • register:
      • A function provided by the event that takes two arguments:
        • translations (Translations):
          • An object containing key-value pairs representing translations, organized according to the Translations interface.
        • locale (string, optional):
          • The locale code (e.g., 'en', 'ru') for which the translations are registered. Defaults to the locale provided by the event if not specified.
  • Behavior:

    • When triggered, the register function merges the new translations into the global context for the specified locale, updating the available translations across the application.

💡 Example Usage

The following example demonstrates how to use the i18n:register event to dynamically add translations:

typescript
nuxt.hook('i18n:register', async (register: (translations: unknown, locale?: string) => void, locale: string) => {
+  register({
+    "greeting": "Hello",
+    "farewell": "Goodbye"
+  }, locale);
+});

🛠️ Explanation

  • Triggering the Event:

    • The event is hooked into the i18n:register lifecycle event provided by Nuxt I18n Micro.
  • Adding Translations:

    • The example registers English translations for "greeting" and "farewell".
    • The register function merges these translations into the existing set for the provided locale.

🔗 Key Benefits

  • Dynamic Updates:

    • Easily update or add translations without needing to redeploy your entire application.
  • Localization Flexibility:

    • Supports real-time localization adjustments based on user or application needs.

Using the i18n:register event, you can ensure that your application's localization strategy remains flexible and adaptable, enhancing the overall user experience.


🛠️ Modifying Translations with Plugins

To modify translations dynamically in your Nuxt application, using plugins is recommended. Plugins provide a structured way to handle localization updates, especially when working with modules or external translation files.

Registering the Plugin

If you're using a module, register the plugin where translation modifications will occur by adding it to your module’s configuration:

javascript
addPlugin({
+  src: resolve('./plugins/extend_locales'),
+})

This registers the plugin located at ./plugins/extend_locales, which will handle dynamic loading and registration of translations.

Implementing the Plugin

In the plugin, you can manage locale modifications. Here's an example implementation in a Nuxt plugin:

typescript
import { defineNuxtPlugin } from '#app'
+
+export default defineNuxtPlugin(async (nuxtApp) => {
+  // Function to load translations from JSON files and register them
+  const loadTranslations = async (lang: string) => {
+    try {
+      const translations = await import(`../locales/${lang}.json`)
+      return translations.default
+    } catch (error) {
+      console.error(`Error loading translations for language: ${lang}`, error)
+      return null
+    }
+  }
+
+  // Hook into the 'i18n:register' event to dynamically add translations
+  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+  // @ts-expect-error
+  nuxtApp.hook('i18n:register', async (register: (translations: unknown, locale?: string) => void, locale: string) => {
+    const translations = await loadTranslations(locale)
+    if (translations) {
+      register(translations, locale)
+    }
+  })
+})

📝 Detailed Explanation

  1. Loading Translations:
  • The loadTranslations function dynamically imports translation files based on the locale. The files are expected to be in the locales directory and named according to locale codes (e.g., en.json, de.json).
  • On successful loading, translations are returned; otherwise, an error is logged.
  1. Registering Translations:
  • The plugin hooks into the i18n:register event using nuxtApp.hook.
  • When the event is triggered, the register function is called with the loaded translations and the corresponding locale.
  • This merges the new translations into the global i18n context for the specified locale, updating the available translations throughout the application.

🔗 Benefits of Using Plugins for Translation Modifications

  • Separation of Concerns:

    • Encapsulate localization logic separately from the main application code, making management and maintenance easier.
  • Dynamic and Scalable:

    • By dynamically loading and registering translations, you can update content without requiring a full application redeployment, which is especially useful for applications with frequently updated or multilingual content.
  • Enhanced Localization Flexibility:

    • Plugins allow you to modify or extend translations as needed, providing a more adaptable and responsive localization strategy that meets user preferences or business requirements.

By adopting this approach, you can efficiently expand and modify your application's localization through a structured and maintainable process using plugins, keeping internationalization adaptive to changing needs and improving the overall user experience.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/api/methods.html b/api/methods.html new file mode 100644 index 00000000..1cb9d5a8 --- /dev/null +++ b/api/methods.html @@ -0,0 +1,152 @@ + + + + + + 🛠️ Methods | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🛠️ Methods

🌍 $getLocale

  • Type: () => string
  • Description: Returns the current locale code.
  • Example:
typescript
const locale = $getLocale()
+// Output: 'en' (assuming the current locale is English)

🌍 $getLocaleName

Version introduced: v1.28.0

  • Type: () => string | null
  • Description: Returns the current locale name from displayName config.
  • Example:
typescript
const locale = $getLocaleName()
+// Output: 'English'

🌍 $getLocales

  • Type: () => Array<{ code: string; iso?: string; dir?: string }>
  • Description: Returns an array of all available locales configured in the module.
  • Example:
typescript
const locales = $getLocales()
+// Output: [{ code: 'en', iso: 'en-US', dir: 'ltr' }, { code: 'fr', iso: 'fr-FR', dir: 'ltr' }]

🔍 $getRouteName

Version introduced: v1.28.0

  • Type: (route?: RouteLocationNormalizedLoaded | RouteLocationResolvedGeneric, locale?: string) => string
  • Description: Retrieves the base route name without any locale-specific prefixes or suffixes.
  • Parameters:
    • route: RouteLocationNormalizedLoaded | RouteLocationResolvedGeneric | undefined — Optional. The route object from which to extract the name.
    • locale: string | undefined — Optional. The locale code to consider when extracting the route name.
  • Example:
typescript
const routeName = $getRouteName(routeObject, 'fr')
+// Output: 'index' (assuming the base route name is 'index')

🔍 $t

  • Type: (key: string, params?: Record<string, any>, defaultValue?: string) => string | number | boolean | Translations | PluralTranslations | unknown | null

  • Description: Fetches a translation for the given key. Optionally interpolates parameters.

  • Parameters:

    • key: string — The translation key.
    • params: Record<string, any> | undefined — Optional. A record of key-value pairs to interpolate into the translation.
    • defaultValue: string | undefined — Optional. The default value to return if the translation is not found.
  • Example:

typescript
const welcomeMessage = $t('welcome', { username: 'Alice', unreadCount: 5 })
+// Output: "Welcome, Alice! You have 5 unread messages."

🔍 $ts

  • Type: (key: string, params?: Record<string, any>, defaultValue?: string) => string
  • Description: A variant of $t that always returns a string. Fetches a translation for the given key and optionally interpolates parameters.
  • Parameters:
    • key: string — The translation key.
    • params: Record<string, any> | undefined — Optional. A record of key-value pairs to interpolate into the translation.
    • defaultValue: string | undefined — Optional. The default value to return if the translation is not found.
  • Example:
typescript
const welcomeMessage = $ts('welcome', { username: 'Alice', unreadCount: 5 })
+// Output: "Welcome, Alice! You have 5 unread messages."

🔢 $tc

  • Type: (key: string, count: number, defaultValue?: string) => string
  • Description: Fetches a pluralized translation for the given key based on the count.
  • Parameters:
    • key: string — The translation key.
    • params: number | Record<string, any> — The count for pluralization or a record of key-value pairs with a 'count' property and additional values to interpolate into the translation.
    • defaultValue: string | undefined — Optional. The default value to return if the translation is not found.
  • Example:
typescript
const appleCountMessage = $tc('apples', 10)
+// Output: "10 apples" (assuming the plural rule for 'apples' is defined correctly)

🔢 $tn

  • Type: (value: number, options?: Intl.NumberFormatOptions) => string
  • Description: Formats a number according to the current locale using Intl.NumberFormat.
  • Parameters:
    • value: number — The number to format.
    • options: Intl.NumberFormatOptions | undefined — Optional. Intl.NumberFormatOptions to customize the formatting.
  • Example:
typescript
const formattedNumber = $tn(1234567.89, { style: 'currency', currency: 'USD' })
+// Output: "$1,234,567.89" in the 'en-US' locale

Use Cases:

  • Formatting numbers as currency, percentages, or decimals in the appropriate locale format.
  • Customizing the number format using Intl.NumberFormatOptions such as currency, minimum fraction digits, etc.

📅 $td

  • Type: (value: Date | number | string, options?: Intl.DateTimeFormatOptions) => string
  • Description: Formats a date according to the current locale using Intl.DateTimeFormat.
  • Parameters:
    • value: Date | number | string — The date to format, which can be a Date object, a timestamp, or a date string.
    • options: Intl.DateTimeFormatOptions | undefined — Optional. Intl.DateTimeFormatOptions to customize the formatting.
  • Example:
typescript
const formattedDate = $td(new Date(), { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })
+// Output: "Friday, September 1, 2023" in the 'en-US' locale

Use Cases:

  • Displaying dates in a format that aligns with the user's locale, including long or short date formats.
  • Customizing date output using options like weekday names, time formats, and timezone settings.

📅 $tn

  • Type: (value: number | string, options?: Intl.NumberFormatOptions) => string
  • Description: Formats a number according to the current locale using Intl.NumberFormat.
  • Parameters:
  • value: number | string — The number to format, which can be a number or a numeric string.
  • options: Intl.NumberFormatOptions | undefined — Optional. Intl.NumberFormatOptions to customize the number formatting.
  • Example:
typescript
const formattedNumber = $tn(1234567.89, { style: 'currency', currency: 'USD' })
+// Output: "$1,234,567.89" in the 'en-US' locale

📅 $tdr

  • Type: (value: Date | number | string, options?: Intl.RelativeTimeFormatOptions) => string
  • Description: Formats a date as a relative time (e.g., "5 minutes ago") according to the current locale using Intl.RelativeTimeFormat.
  • Parameters:
  • value: Date | number | string — The date to compare against the current time, which can be a Date object, a timestamp, or a date string.
  • options: Intl.RelativeTimeFormatOptions | undefined — Optional. Intl.RelativeTimeFormatOptions to customize the relative time formatting.
  • Example:
typescript
const relativeDate = $tdr(new Date(Date.now() - 1000 * 60 * 5))
+// Output: "5 minutes ago" in the 'en-US' locale

🔄 $switchLocaleRoute

  • Type: (locale: string) => RouteLocationRaw
  • Description: Return current route with the given locale
  • Parameters:
    • locale: string — Target locale.
  • Example:
typescript
// on /en/news
+const routeFr = $switchLocaleRoute('fr')
+// Output: A route object with the new locale applied, e.g., { name: 'localized-news', params: { locale: 'fr' } }

🔄 $switchLocalePath

  • Type: (locale: string) => string
  • Description: Return url of current route with the given locale
  • Parameters:
    • locale: string — Target locale.
  • Example:
typescript
// on /en/news
+const routeFr = $switchLocalePath('fr')
+window.location.href = routeFr
+// Output: url with new locale applied, e.g., '/fr/nouvelles'

🔄 $switchLocale

  • Type: (locale: string) => void
  • Description: Switches to the given locale and redirects the user to the appropriate localized route.
  • Parameters:
    • locale: string — The locale to switch to.
  • Example:
typescript
$switchLocale('fr')
+// Output: Redirects the user to the French version of the route

🔄 $switchRoute

Version introduced: v1.27.0

  • Type: (route: RouteLocationNormalizedLoaded | RouteLocationResolvedGeneric | string, toLocale?: string) => void
  • Description: Switches the route to a new specified destination and changes the locale if needed, redirecting the user to the appropriate localized route.
  • Parameters:
    • route: RouteLocationNormalizedLoaded | RouteLocationResolvedGeneric | string — The route to which you want to switch. It can be:
      • A RouteLocationNormalizedLoaded or RouteLocationResolvedGeneric object.
      • A string representing the route path.
  • toLocale (optional): string — The locale to switch to for the target route. If not provided, the current locale is used.

Info: This method facilitates seamless switching between routes, accommodating the current locale configuration. Depending on the input, it resolves the intended route and determines the appropriate locale for redirecting the user to a localized route.

Examples:

  • String Path:

    typescript
    // Switches to the given path with the current locale
    +switchRoute('/about')
  • String Path with Locale:

    typescript
    // Switches to the given path with French locale
    +switchRoute('/about', 'fr')
  • Named Route:

    typescript
    // Switches to a named route with the current locale
    +switchRoute({ name: 'page' })
  • Named Route with Locale:

    typescript
    // Switches to a named route and changes the locale to Spanish
    +switchRoute({ name: 'page' }, 'es')

🔄 $setI18nRouteParams

  • Type: (value: Record<LocaleCode, Record<string, string>> | null) => Record<LocaleCode, Record<string, string>> | null
  • Description: set localized versions of params for all switchLocale* methods and returns passed value. MUST be called inside useAsyncData
  • Parameters:
    • value: Record<LocaleCode, Record<string, string>> | null — params of current route for other locale
  • Example:
typescript
// in pages/news/[id].vue
+// for en/news/1-first-article
+const { $switchLocaleRoute, $setI18nRouteParams, $defineI18nRoute } = useI18n();
+// OR
+const { $switchLocaleRoute, $setI18nRouteParams, $defineI18nRoute } = useNuxtApp();
+$defineI18nRoute({
+  localeRoutes: {
+    en: '/news/:id()',
+    fr: '/nouvelles/:id()',
+    de: '/Nachricht/:id()',
+  },
+})
+const { data: news } = await useAsyncData(`news-${params.id}`, async () => {
+  let response = await $fetch("/api/getNews", {
+    query: {
+      id: params.id,
+    },
+  });
+  if (response?.localeSlugs) {
+    response.localeSlugs = {
+      en: {
+        id: '1-first-article'
+      }
+      fr: {
+        id: '1-premier-article'
+      }
+      de: {
+        id: '1-erster-Artikel'
+      }
+    }
+    $setI18nRouteParams(response?.localeSlugs);
+  }
+  return response;
+});
+$switchLocalePath('fr') // === 'fr/nouvelles/1-premier-article'
+$switchLocalePath('de') // === 'de/Nachricht/1-erster-Artikel'

🌐 $localeRoute

  • Type: (to: RouteLocationRaw, locale?: string) => RouteLocationResolved
  • Description: Generates a localized route object based on the target route.
  • Parameters:
    • to: RouteLocationRaw — The target route object.
    • locale: string | undefined — Optional. The locale for the generated route.
  • Example:
typescript
const localizedRoute = $localeRoute({ name: 'index' })
+// Output: A route object with the current locale applied, e.g., { name: 'index', params: { locale: 'fr' } }

🔄 $localePath

  • Type: (to: RouteLocationRaw, locale?: string) => string
  • Description: Return url based on the target route
  • Parameters:
    • to: RouteLocationRaw — The target route object.
    • locale: string | undefined — Optional. The locale for the generated route.
  • Example:
typescript
const localizedRoute = $localeRoute({ name: 'news' })
+// Output: url with new locale applied, e.g., '/en/nouvelles'

🗂️ $mergeTranslations

  • Type: (newTranslations: Record<string, string>) => void
  • Description: Merges new translations into the existing translation cache for the current route and locale.
  • Parameters:
    • newTranslations: Record<string, string> — The new translations to merge.
  • Example:
typescript
$mergeTranslations({
+  welcome: 'Bienvenue, {username}!'
+})
+// Output: Updates the translation cache with the new French translation

🚦 $defineI18nRoute

  • Type: (routeDefinition: { locales?: string[] | Record<string, Record<string, TranslationObject>>, localeRoutes?: Record<string, string> }) => void
  • Description: Defines route behavior based on the current locale. This method can be used to control access to specific routes based on available locales, provide translations for specific locales, or set custom routes for different locales.
  • Parameters:
    • locales: string[] | Record<string, Record<string, TranslationObject>> — This property determines which locales are available for the route.
    • localeRoutes: Record<string, string> | undefined — Optional. Custom routes for specific locales.
  • Example:
typescript
$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    ru: { greeting: 'Привет', farewell: 'До свидания' },
+  },
+  localeRoutes: {
+    ru: '/localesubpage',
+  },
+})

Use Cases:

  • Controlling Access: By specifying available locales, you can control which routes are accessible based on the current locale, ensuring that users only see content relevant to their language.

  • Providing Translations: The locales object allows for providing specific translations for each route, enhancing the user experience by delivering content in the user's preferred language.

  • Custom Routing: The localeRoutes property offers flexibility in defining different paths for specific locales, which can be particularly useful in cases where certain languages or regions require unique navigational flows or URLs.

This function offers a flexible way to manage routing and localization in your Nuxt application, making it easy to tailor the user experience based on the language and region settings of your audience.

Example 1: Controlling Access Based on Locales

typescript
import { useNuxtApp } from '#imports'
+
+const { $defineI18nRoute } = useNuxtApp()
+
+$defineI18nRoute({
+  locales: ['en', 'fr', 'de'] // Only these locales are allowed for this route
+})

Example 2: Providing Translations for Locales

typescript
import { useNuxtApp } from '#imports'
+
+const { $defineI18nRoute } = useNuxtApp()
+
+$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    fr: { greeting: 'Bonjour', farewell: 'Au revoir' },
+    de: { greeting: 'Hallo', farewell: { aaa: { bbb: "Auf Wiedersehen" } } },
+    ru: {} // Russian locale is allowed but no translations are provided
+  }
+})

📝 Explanation:

  • Locales Array: If you only want to specify which locales are allowed for a route, pass an array of locale codes. The user will only be able to access this route if the current locale is in this list.
  • Locales Object: If you want to provide specific translations for each locale, pass an object where each key is a locale code. The value should be an object with key-value pairs for translations. If you do not wish to provide translations for a locale but still want to allow access, pass an empty object ({}) for that locale.

💻 Example Usage in a Component

Here's an example of how to use these methods in a Nuxt component:

vue
<template>
+  <div>
+    <p>{{ $t('key2.key2.key2.key2.key2') }}</p>
+    <p>Current Locale: {{ $getLocale() }}</p>
+
+    <div>
+      {{ $t('welcome', { username: 'Alice', unreadCount: 5 }) }}
+    </div>
+    <div>
+      {{ $tc('apples', 10) }}
+    </div>
+
+    <div>
+      <button
+        v-for="locale in $getLocales()"
+        :key="locale"
+        :disabled="locale === $getLocale()"
+        @click="() => $switchLocale(locale.code)"
+      >
+        Switch to {{ locale.code }}
+      </button>
+    </div>
+
+    <div>
+      <NuxtLink :to="$localeRoute({ name: 'index' })">
+        Go to Index
+      </NuxtLink>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useI18n } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t, $tc } = useI18n()
+</script>

🛠️ useNuxtApp

Example:

typescript
import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t } = useNuxtApp()

🧩 useI18n Composable

Example:

typescript
import { useI18n } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t } = useI18n()
+// or
+const i18n = useI18n()

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/assets/api_events.md.bHhRa_Pw.js b/assets/api_events.md.bHhRa_Pw.js new file mode 100644 index 00000000..08a72755 --- /dev/null +++ b/assets/api_events.md.bHhRa_Pw.js @@ -0,0 +1,31 @@ +import{_ as s,c as a,a2 as n,o as t}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"📢 Events","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"api/events.md","filePath":"api/events.md","lastUpdated":1727601432000}'),e={name:"api/events.md"};function l(h,i,p,r,o,k){return t(),a("div",null,i[0]||(i[0]=[n(`

📢 Events

🔄 i18n:register

The i18n:register event in Nuxt I18n Micro enables dynamic addition of translations to your application's global i18n context, making the internationalization process seamless and flexible. This event allows you to integrate new translations as needed, enhancing your application's localization capabilities.

📝 Event Details

💡 Example Usage

The following example demonstrates how to use the i18n:register event to dynamically add translations:

typescript
nuxt.hook('i18n:register', async (register: (translations: unknown, locale?: string) => void, locale: string) => {
+  register({
+    "greeting": "Hello",
+    "farewell": "Goodbye"
+  }, locale);
+});

🛠️ Explanation

🔗 Key Benefits

Using the i18n:register event, you can ensure that your application's localization strategy remains flexible and adaptable, enhancing the overall user experience.


🛠️ Modifying Translations with Plugins

To modify translations dynamically in your Nuxt application, using plugins is recommended. Plugins provide a structured way to handle localization updates, especially when working with modules or external translation files.

Registering the Plugin

If you're using a module, register the plugin where translation modifications will occur by adding it to your module’s configuration:

javascript
addPlugin({
+  src: resolve('./plugins/extend_locales'),
+})

This registers the plugin located at ./plugins/extend_locales, which will handle dynamic loading and registration of translations.

Implementing the Plugin

In the plugin, you can manage locale modifications. Here's an example implementation in a Nuxt plugin:

typescript
import { defineNuxtPlugin } from '#app'
+
+export default defineNuxtPlugin(async (nuxtApp) => {
+  // Function to load translations from JSON files and register them
+  const loadTranslations = async (lang: string) => {
+    try {
+      const translations = await import(\`../locales/\${lang}.json\`)
+      return translations.default
+    } catch (error) {
+      console.error(\`Error loading translations for language: \${lang}\`, error)
+      return null
+    }
+  }
+
+  // Hook into the 'i18n:register' event to dynamically add translations
+  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+  // @ts-expect-error
+  nuxtApp.hook('i18n:register', async (register: (translations: unknown, locale?: string) => void, locale: string) => {
+    const translations = await loadTranslations(locale)
+    if (translations) {
+      register(translations, locale)
+    }
+  })
+})

📝 Detailed Explanation

  1. Loading Translations:
  1. Registering Translations:

🔗 Benefits of Using Plugins for Translation Modifications

By adopting this approach, you can efficiently expand and modify your application's localization through a structured and maintainable process using plugins, keeping internationalization adaptive to changing needs and improving the overall user experience.

`,31)]))}const c=s(e,[["render",l]]);export{g as __pageData,c as default}; diff --git a/assets/api_events.md.bHhRa_Pw.lean.js b/assets/api_events.md.bHhRa_Pw.lean.js new file mode 100644 index 00000000..08a72755 --- /dev/null +++ b/assets/api_events.md.bHhRa_Pw.lean.js @@ -0,0 +1,31 @@ +import{_ as s,c as a,a2 as n,o as t}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"📢 Events","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"api/events.md","filePath":"api/events.md","lastUpdated":1727601432000}'),e={name:"api/events.md"};function l(h,i,p,r,o,k){return t(),a("div",null,i[0]||(i[0]=[n(`

📢 Events

🔄 i18n:register

The i18n:register event in Nuxt I18n Micro enables dynamic addition of translations to your application's global i18n context, making the internationalization process seamless and flexible. This event allows you to integrate new translations as needed, enhancing your application's localization capabilities.

📝 Event Details

💡 Example Usage

The following example demonstrates how to use the i18n:register event to dynamically add translations:

typescript
nuxt.hook('i18n:register', async (register: (translations: unknown, locale?: string) => void, locale: string) => {
+  register({
+    "greeting": "Hello",
+    "farewell": "Goodbye"
+  }, locale);
+});

🛠️ Explanation

🔗 Key Benefits

Using the i18n:register event, you can ensure that your application's localization strategy remains flexible and adaptable, enhancing the overall user experience.


🛠️ Modifying Translations with Plugins

To modify translations dynamically in your Nuxt application, using plugins is recommended. Plugins provide a structured way to handle localization updates, especially when working with modules or external translation files.

Registering the Plugin

If you're using a module, register the plugin where translation modifications will occur by adding it to your module’s configuration:

javascript
addPlugin({
+  src: resolve('./plugins/extend_locales'),
+})

This registers the plugin located at ./plugins/extend_locales, which will handle dynamic loading and registration of translations.

Implementing the Plugin

In the plugin, you can manage locale modifications. Here's an example implementation in a Nuxt plugin:

typescript
import { defineNuxtPlugin } from '#app'
+
+export default defineNuxtPlugin(async (nuxtApp) => {
+  // Function to load translations from JSON files and register them
+  const loadTranslations = async (lang: string) => {
+    try {
+      const translations = await import(\`../locales/\${lang}.json\`)
+      return translations.default
+    } catch (error) {
+      console.error(\`Error loading translations for language: \${lang}\`, error)
+      return null
+    }
+  }
+
+  // Hook into the 'i18n:register' event to dynamically add translations
+  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+  // @ts-expect-error
+  nuxtApp.hook('i18n:register', async (register: (translations: unknown, locale?: string) => void, locale: string) => {
+    const translations = await loadTranslations(locale)
+    if (translations) {
+      register(translations, locale)
+    }
+  })
+})

📝 Detailed Explanation

  1. Loading Translations:
  1. Registering Translations:

🔗 Benefits of Using Plugins for Translation Modifications

By adopting this approach, you can efficiently expand and modify your application's localization through a structured and maintainable process using plugins, keeping internationalization adaptive to changing needs and improving the overall user experience.

`,31)]))}const c=s(e,[["render",l]]);export{g as __pageData,c as default}; diff --git a/assets/api_methods.md.VL5OYeZ9.js b/assets/api_methods.md.VL5OYeZ9.js new file mode 100644 index 00000000..7fb69d25 --- /dev/null +++ b/assets/api_methods.md.VL5OYeZ9.js @@ -0,0 +1,128 @@ +import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🛠️ Methods","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"api/methods.md","filePath":"api/methods.md","lastUpdated":1736500399000}'),e={name:"api/methods.md"};function l(h,s,p,k,r,o){return n(),a("div",null,s[0]||(s[0]=[t(`

🛠️ Methods

🌍 $getLocale

typescript
const locale = $getLocale()
+// Output: 'en' (assuming the current locale is English)

🌍 $getLocaleName

Version introduced: v1.28.0

typescript
const locale = $getLocaleName()
+// Output: 'English'

🌍 $getLocales

typescript
const locales = $getLocales()
+// Output: [{ code: 'en', iso: 'en-US', dir: 'ltr' }, { code: 'fr', iso: 'fr-FR', dir: 'ltr' }]

🔍 $getRouteName

Version introduced: v1.28.0

typescript
const routeName = $getRouteName(routeObject, 'fr')
+// Output: 'index' (assuming the base route name is 'index')

🔍 $t

typescript
const welcomeMessage = $t('welcome', { username: 'Alice', unreadCount: 5 })
+// Output: "Welcome, Alice! You have 5 unread messages."

🔍 $ts

typescript
const welcomeMessage = $ts('welcome', { username: 'Alice', unreadCount: 5 })
+// Output: "Welcome, Alice! You have 5 unread messages."

🔢 $tc

typescript
const appleCountMessage = $tc('apples', 10)
+// Output: "10 apples" (assuming the plural rule for 'apples' is defined correctly)

🔢 $tn

typescript
const formattedNumber = $tn(1234567.89, { style: 'currency', currency: 'USD' })
+// Output: "$1,234,567.89" in the 'en-US' locale

Use Cases:

📅 $td

typescript
const formattedDate = $td(new Date(), { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })
+// Output: "Friday, September 1, 2023" in the 'en-US' locale

Use Cases:

📅 $tn

typescript
const formattedNumber = $tn(1234567.89, { style: 'currency', currency: 'USD' })
+// Output: "$1,234,567.89" in the 'en-US' locale

📅 $tdr

typescript
const relativeDate = $tdr(new Date(Date.now() - 1000 * 60 * 5))
+// Output: "5 minutes ago" in the 'en-US' locale

🔄 $switchLocaleRoute

typescript
// on /en/news
+const routeFr = $switchLocaleRoute('fr')
+// Output: A route object with the new locale applied, e.g., { name: 'localized-news', params: { locale: 'fr' } }

🔄 $switchLocalePath

typescript
// on /en/news
+const routeFr = $switchLocalePath('fr')
+window.location.href = routeFr
+// Output: url with new locale applied, e.g., '/fr/nouvelles'

🔄 $switchLocale

typescript
$switchLocale('fr')
+// Output: Redirects the user to the French version of the route

🔄 $switchRoute

Version introduced: v1.27.0

Info: This method facilitates seamless switching between routes, accommodating the current locale configuration. Depending on the input, it resolves the intended route and determines the appropriate locale for redirecting the user to a localized route.

Examples:

🔄 $setI18nRouteParams

typescript
// in pages/news/[id].vue
+// for en/news/1-first-article
+const { $switchLocaleRoute, $setI18nRouteParams, $defineI18nRoute } = useI18n();
+// OR
+const { $switchLocaleRoute, $setI18nRouteParams, $defineI18nRoute } = useNuxtApp();
+$defineI18nRoute({
+  localeRoutes: {
+    en: '/news/:id()',
+    fr: '/nouvelles/:id()',
+    de: '/Nachricht/:id()',
+  },
+})
+const { data: news } = await useAsyncData(\`news-\${params.id}\`, async () => {
+  let response = await $fetch("/api/getNews", {
+    query: {
+      id: params.id,
+    },
+  });
+  if (response?.localeSlugs) {
+    response.localeSlugs = {
+      en: {
+        id: '1-first-article'
+      }
+      fr: {
+        id: '1-premier-article'
+      }
+      de: {
+        id: '1-erster-Artikel'
+      }
+    }
+    $setI18nRouteParams(response?.localeSlugs);
+  }
+  return response;
+});
+$switchLocalePath('fr') // === 'fr/nouvelles/1-premier-article'
+$switchLocalePath('de') // === 'de/Nachricht/1-erster-Artikel'

🌐 $localeRoute

typescript
const localizedRoute = $localeRoute({ name: 'index' })
+// Output: A route object with the current locale applied, e.g., { name: 'index', params: { locale: 'fr' } }

🔄 $localePath

typescript
const localizedRoute = $localeRoute({ name: 'news' })
+// Output: url with new locale applied, e.g., '/en/nouvelles'

🗂️ $mergeTranslations

typescript
$mergeTranslations({
+  welcome: 'Bienvenue, {username}!'
+})
+// Output: Updates the translation cache with the new French translation

🚦 $defineI18nRoute

typescript
$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    ru: { greeting: 'Привет', farewell: 'До свидания' },
+  },
+  localeRoutes: {
+    ru: '/localesubpage',
+  },
+})

Use Cases:

This function offers a flexible way to manage routing and localization in your Nuxt application, making it easy to tailor the user experience based on the language and region settings of your audience.

Example 1: Controlling Access Based on Locales

typescript
import { useNuxtApp } from '#imports'
+
+const { $defineI18nRoute } = useNuxtApp()
+
+$defineI18nRoute({
+  locales: ['en', 'fr', 'de'] // Only these locales are allowed for this route
+})

Example 2: Providing Translations for Locales

typescript
import { useNuxtApp } from '#imports'
+
+const { $defineI18nRoute } = useNuxtApp()
+
+$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    fr: { greeting: 'Bonjour', farewell: 'Au revoir' },
+    de: { greeting: 'Hallo', farewell: { aaa: { bbb: "Auf Wiedersehen" } } },
+    ru: {} // Russian locale is allowed but no translations are provided
+  }
+})

📝 Explanation:

💻 Example Usage in a Component

Here's an example of how to use these methods in a Nuxt component:

vue
<template>
+  <div>
+    <p>{{ $t('key2.key2.key2.key2.key2') }}</p>
+    <p>Current Locale: {{ $getLocale() }}</p>
+
+    <div>
+      {{ $t('welcome', { username: 'Alice', unreadCount: 5 }) }}
+    </div>
+    <div>
+      {{ $tc('apples', 10) }}
+    </div>
+
+    <div>
+      <button
+        v-for="locale in $getLocales()"
+        :key="locale"
+        :disabled="locale === $getLocale()"
+        @click="() => $switchLocale(locale.code)"
+      >
+        Switch to {{ locale.code }}
+      </button>
+    </div>
+
+    <div>
+      <NuxtLink :to="$localeRoute({ name: 'index' })">
+        Go to Index
+      </NuxtLink>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useI18n } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t, $tc } = useI18n()
+</script>

🛠️ useNuxtApp

Example:

typescript
import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t } = useNuxtApp()

🧩 useI18n Composable

Example:

typescript
import { useI18n } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t } = useI18n()
+// or
+const i18n = useI18n()
`,88)]))}const c=i(e,[["render",l]]);export{g as __pageData,c as default}; diff --git a/assets/api_methods.md.VL5OYeZ9.lean.js b/assets/api_methods.md.VL5OYeZ9.lean.js new file mode 100644 index 00000000..7fb69d25 --- /dev/null +++ b/assets/api_methods.md.VL5OYeZ9.lean.js @@ -0,0 +1,128 @@ +import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🛠️ Methods","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"api/methods.md","filePath":"api/methods.md","lastUpdated":1736500399000}'),e={name:"api/methods.md"};function l(h,s,p,k,r,o){return n(),a("div",null,s[0]||(s[0]=[t(`

🛠️ Methods

🌍 $getLocale

typescript
const locale = $getLocale()
+// Output: 'en' (assuming the current locale is English)

🌍 $getLocaleName

Version introduced: v1.28.0

typescript
const locale = $getLocaleName()
+// Output: 'English'

🌍 $getLocales

typescript
const locales = $getLocales()
+// Output: [{ code: 'en', iso: 'en-US', dir: 'ltr' }, { code: 'fr', iso: 'fr-FR', dir: 'ltr' }]

🔍 $getRouteName

Version introduced: v1.28.0

typescript
const routeName = $getRouteName(routeObject, 'fr')
+// Output: 'index' (assuming the base route name is 'index')

🔍 $t

typescript
const welcomeMessage = $t('welcome', { username: 'Alice', unreadCount: 5 })
+// Output: "Welcome, Alice! You have 5 unread messages."

🔍 $ts

typescript
const welcomeMessage = $ts('welcome', { username: 'Alice', unreadCount: 5 })
+// Output: "Welcome, Alice! You have 5 unread messages."

🔢 $tc

typescript
const appleCountMessage = $tc('apples', 10)
+// Output: "10 apples" (assuming the plural rule for 'apples' is defined correctly)

🔢 $tn

typescript
const formattedNumber = $tn(1234567.89, { style: 'currency', currency: 'USD' })
+// Output: "$1,234,567.89" in the 'en-US' locale

Use Cases:

📅 $td

typescript
const formattedDate = $td(new Date(), { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })
+// Output: "Friday, September 1, 2023" in the 'en-US' locale

Use Cases:

📅 $tn

typescript
const formattedNumber = $tn(1234567.89, { style: 'currency', currency: 'USD' })
+// Output: "$1,234,567.89" in the 'en-US' locale

📅 $tdr

typescript
const relativeDate = $tdr(new Date(Date.now() - 1000 * 60 * 5))
+// Output: "5 minutes ago" in the 'en-US' locale

🔄 $switchLocaleRoute

typescript
// on /en/news
+const routeFr = $switchLocaleRoute('fr')
+// Output: A route object with the new locale applied, e.g., { name: 'localized-news', params: { locale: 'fr' } }

🔄 $switchLocalePath

typescript
// on /en/news
+const routeFr = $switchLocalePath('fr')
+window.location.href = routeFr
+// Output: url with new locale applied, e.g., '/fr/nouvelles'

🔄 $switchLocale

typescript
$switchLocale('fr')
+// Output: Redirects the user to the French version of the route

🔄 $switchRoute

Version introduced: v1.27.0

Info: This method facilitates seamless switching between routes, accommodating the current locale configuration. Depending on the input, it resolves the intended route and determines the appropriate locale for redirecting the user to a localized route.

Examples:

🔄 $setI18nRouteParams

typescript
// in pages/news/[id].vue
+// for en/news/1-first-article
+const { $switchLocaleRoute, $setI18nRouteParams, $defineI18nRoute } = useI18n();
+// OR
+const { $switchLocaleRoute, $setI18nRouteParams, $defineI18nRoute } = useNuxtApp();
+$defineI18nRoute({
+  localeRoutes: {
+    en: '/news/:id()',
+    fr: '/nouvelles/:id()',
+    de: '/Nachricht/:id()',
+  },
+})
+const { data: news } = await useAsyncData(\`news-\${params.id}\`, async () => {
+  let response = await $fetch("/api/getNews", {
+    query: {
+      id: params.id,
+    },
+  });
+  if (response?.localeSlugs) {
+    response.localeSlugs = {
+      en: {
+        id: '1-first-article'
+      }
+      fr: {
+        id: '1-premier-article'
+      }
+      de: {
+        id: '1-erster-Artikel'
+      }
+    }
+    $setI18nRouteParams(response?.localeSlugs);
+  }
+  return response;
+});
+$switchLocalePath('fr') // === 'fr/nouvelles/1-premier-article'
+$switchLocalePath('de') // === 'de/Nachricht/1-erster-Artikel'

🌐 $localeRoute

typescript
const localizedRoute = $localeRoute({ name: 'index' })
+// Output: A route object with the current locale applied, e.g., { name: 'index', params: { locale: 'fr' } }

🔄 $localePath

typescript
const localizedRoute = $localeRoute({ name: 'news' })
+// Output: url with new locale applied, e.g., '/en/nouvelles'

🗂️ $mergeTranslations

typescript
$mergeTranslations({
+  welcome: 'Bienvenue, {username}!'
+})
+// Output: Updates the translation cache with the new French translation

🚦 $defineI18nRoute

typescript
$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    ru: { greeting: 'Привет', farewell: 'До свидания' },
+  },
+  localeRoutes: {
+    ru: '/localesubpage',
+  },
+})

Use Cases:

This function offers a flexible way to manage routing and localization in your Nuxt application, making it easy to tailor the user experience based on the language and region settings of your audience.

Example 1: Controlling Access Based on Locales

typescript
import { useNuxtApp } from '#imports'
+
+const { $defineI18nRoute } = useNuxtApp()
+
+$defineI18nRoute({
+  locales: ['en', 'fr', 'de'] // Only these locales are allowed for this route
+})

Example 2: Providing Translations for Locales

typescript
import { useNuxtApp } from '#imports'
+
+const { $defineI18nRoute } = useNuxtApp()
+
+$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    fr: { greeting: 'Bonjour', farewell: 'Au revoir' },
+    de: { greeting: 'Hallo', farewell: { aaa: { bbb: "Auf Wiedersehen" } } },
+    ru: {} // Russian locale is allowed but no translations are provided
+  }
+})

📝 Explanation:

💻 Example Usage in a Component

Here's an example of how to use these methods in a Nuxt component:

vue
<template>
+  <div>
+    <p>{{ $t('key2.key2.key2.key2.key2') }}</p>
+    <p>Current Locale: {{ $getLocale() }}</p>
+
+    <div>
+      {{ $t('welcome', { username: 'Alice', unreadCount: 5 }) }}
+    </div>
+    <div>
+      {{ $tc('apples', 10) }}
+    </div>
+
+    <div>
+      <button
+        v-for="locale in $getLocales()"
+        :key="locale"
+        :disabled="locale === $getLocale()"
+        @click="() => $switchLocale(locale.code)"
+      >
+        Switch to {{ locale.code }}
+      </button>
+    </div>
+
+    <div>
+      <NuxtLink :to="$localeRoute({ name: 'index' })">
+        Go to Index
+      </NuxtLink>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useI18n } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t, $tc } = useI18n()
+</script>

🛠️ useNuxtApp

Example:

typescript
import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t } = useNuxtApp()

🧩 useI18n Composable

Example:

typescript
import { useI18n } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t } = useI18n()
+// or
+const i18n = useI18n()
`,88)]))}const c=i(e,[["render",l]]);export{g as __pageData,c as default}; diff --git a/assets/app.sQHFs_9H.js b/assets/app.sQHFs_9H.js new file mode 100644 index 00000000..6ec991b2 --- /dev/null +++ b/assets/app.sQHFs_9H.js @@ -0,0 +1 @@ +import{R as i}from"./chunks/theme.CPkZdxnZ.js";import{R as o,a3 as u,a4 as c,a5 as l,a6 as f,a7 as d,a8 as m,a9 as h,aa as g,ab as A,ac as v,d as P,u as R,v as w,s as y,ad as C,ae as b,af as E,ag as S}from"./chunks/framework.Gfs4HC1t.js";function p(e){if(e.extends){const a=p(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const s=p(i),T=P({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=R();return w(()=>{y(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&C(),b(),E(),s.setup&&s.setup(),()=>S(s.Layout)}});async function D(){globalThis.__VITEPRESS__=!0;const e=j(),a=_();a.provide(c,e);const t=l(e.route);return a.provide(f,t),a.component("Content",d),a.component("ClientOnly",m),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),s.enhanceApp&&await s.enhanceApp({app:a,router:e,siteData:h}),{app:a,router:e,data:t}}function _(){return g(T)}function j(){let e=o,a;return A(t=>{let n=v(t),r=null;return n&&(e&&(a=n),(e||a===n)&&(n=n.replace(/\.js$/,".lean.js")),r=import(n)),o&&(e=!1),r},s.NotFound)}o&&D().then(({app:e,router:a,data:t})=>{a.go().then(()=>{u(a.route,t.site),e.mount("#app")})});export{D as createApp}; diff --git a/assets/chunks/@localSearchIndexroot.D3nW01Zu.js b/assets/chunks/@localSearchIndexroot.D3nW01Zu.js new file mode 100644 index 00000000..13e597ef --- /dev/null +++ b/assets/chunks/@localSearchIndexroot.D3nW01Zu.js @@ -0,0 +1 @@ +const t='{"documentCount":487,"nextId":487,"documentIds":{"0":"/nuxt-i18n-micro/api/events#📢-events","1":"/nuxt-i18n-micro/api/events#🔄-i18n-register","2":"/nuxt-i18n-micro/api/events#📝-event-details","3":"/nuxt-i18n-micro/api/events#💡-example-usage","4":"/nuxt-i18n-micro/api/events#🛠️-explanation","5":"/nuxt-i18n-micro/api/events#🔗-key-benefits","6":"/nuxt-i18n-micro/api/events#🛠️-modifying-translations-with-plugins","7":"/nuxt-i18n-micro/api/events#registering-the-plugin","8":"/nuxt-i18n-micro/api/events#implementing-the-plugin","9":"/nuxt-i18n-micro/api/events#📝-detailed-explanation","10":"/nuxt-i18n-micro/api/events#🔗-benefits-of-using-plugins-for-translation-modifications","11":"/nuxt-i18n-micro/api/methods#🛠️-methods","12":"/nuxt-i18n-micro/api/methods#🌍-getlocale","13":"/nuxt-i18n-micro/api/methods#🌍-getlocalename","14":"/nuxt-i18n-micro/api/methods#🌍-getlocales","15":"/nuxt-i18n-micro/api/methods#🔍-getroutename","16":"/nuxt-i18n-micro/api/methods#🔍-t","17":"/nuxt-i18n-micro/api/methods#🔍-ts","18":"/nuxt-i18n-micro/api/methods#🔢-tc","19":"/nuxt-i18n-micro/api/methods#🔢-tn","20":"/nuxt-i18n-micro/api/methods#📅-td","21":"/nuxt-i18n-micro/api/methods#📅-tn","22":"/nuxt-i18n-micro/api/methods#📅-tdr","23":"/nuxt-i18n-micro/api/methods#🔄-switchlocaleroute","24":"/nuxt-i18n-micro/api/methods#🔄-switchlocalepath","25":"/nuxt-i18n-micro/api/methods#🔄-switchlocale","26":"/nuxt-i18n-micro/api/methods#🔄-switchroute","27":"/nuxt-i18n-micro/api/methods#🔄-seti18nrouteparams","28":"/nuxt-i18n-micro/api/methods#🌐-localeroute","29":"/nuxt-i18n-micro/api/methods#🔄-localepath","30":"/nuxt-i18n-micro/api/methods#🗂️-mergetranslations","31":"/nuxt-i18n-micro/api/methods#🚦-definei18nroute","32":"/nuxt-i18n-micro/api/methods#💻-example-usage-in-a-component","33":"/nuxt-i18n-micro/api/methods#🛠️-usenuxtapp","34":"/nuxt-i18n-micro/api/methods#🧩-usei18n-composable","35":"/nuxt-i18n-micro/components/i18n-group#🌍-i18n-group-component","36":"/nuxt-i18n-micro/components/i18n-group#⚙️-props","37":"/nuxt-i18n-micro/components/i18n-group#prefix","38":"/nuxt-i18n-micro/components/i18n-group#groupclass","39":"/nuxt-i18n-micro/components/i18n-group#🎯-slots","40":"/nuxt-i18n-micro/components/i18n-group#default-slot","41":"/nuxt-i18n-micro/components/i18n-group#🛠️-example-usage","42":"/nuxt-i18n-micro/components/i18n-group#basic-usage","43":"/nuxt-i18n-micro/components/i18n-group#with-custom-class","44":"/nuxt-i18n-micro/components/i18n-group#with-dynamic-content","45":"/nuxt-i18n-micro/components/i18n-group#🎨-styling","46":"/nuxt-i18n-micro/components/i18n-group#🚀-best-practices","47":"/nuxt-i18n-micro/components/i18n-link#🌍-i18n-link-component","48":"/nuxt-i18n-micro/components/i18n-link#⚙️-props","49":"/nuxt-i18n-micro/components/i18n-link#to","50":"/nuxt-i18n-micro/components/i18n-link#activestyle","51":"/nuxt-i18n-micro/components/i18n-link#🛠️-example-usages","52":"/nuxt-i18n-micro/components/i18n-link#basic-usage","53":"/nuxt-i18n-micro/components/i18n-link#active-link-styling-with-inline-styles","54":"/nuxt-i18n-micro/components/i18n-link#external-links-handling","55":"/nuxt-i18n-micro/components/i18n-link#🎨-styles","56":"/nuxt-i18n-micro/components/i18n-link#default-active-styles","57":"/nuxt-i18n-micro/components/i18n-link#custom-active-styles","58":"/nuxt-i18n-micro/components/i18n-link#🚀-additional-features","59":"/nuxt-i18n-micro/components/i18n-link#slot-for-custom-content","60":"/nuxt-i18n-micro/components/i18n-link#accessibility-enhancements","61":"/nuxt-i18n-micro/components/i18n-switcher#🌍-i18n-switcher-component","62":"/nuxt-i18n-micro/components/i18n-switcher#⚙️-props","63":"/nuxt-i18n-micro/components/i18n-switcher#customlabels","64":"/nuxt-i18n-micro/components/i18n-switcher#customwrapperstyle","65":"/nuxt-i18n-micro/components/i18n-switcher#custombuttonstyle","66":"/nuxt-i18n-micro/components/i18n-switcher#customdropdownstyle","67":"/nuxt-i18n-micro/components/i18n-switcher#customitemstyle","68":"/nuxt-i18n-micro/components/i18n-switcher#customlinkstyle","69":"/nuxt-i18n-micro/components/i18n-switcher#customactivelinkstyle","70":"/nuxt-i18n-micro/components/i18n-switcher#customdisabledlinkstyle","71":"/nuxt-i18n-micro/components/i18n-switcher#customiconstyle","72":"/nuxt-i18n-micro/components/i18n-switcher#🛠️-example-usages","73":"/nuxt-i18n-micro/components/i18n-switcher#basic-usage","74":"/nuxt-i18n-micro/components/i18n-switcher#custom-labels-and-inline-styles","75":"/nuxt-i18n-micro/components/i18n-switcher#🔌-slots","76":"/nuxt-i18n-micro/components/i18n-switcher#before-button","77":"/nuxt-i18n-micro/components/i18n-switcher#before-selected-locale","78":"/nuxt-i18n-micro/components/i18n-switcher#after-selected-locale","79":"/nuxt-i18n-micro/components/i18n-switcher#before-dropdown","80":"/nuxt-i18n-micro/components/i18n-switcher#after-dropdown","81":"/nuxt-i18n-micro/components/i18n-switcher#before-dropdown-items","82":"/nuxt-i18n-micro/components/i18n-switcher#after-dropdown-items","83":"/nuxt-i18n-micro/components/i18n-switcher#before-item","84":"/nuxt-i18n-micro/components/i18n-switcher#after-item","85":"/nuxt-i18n-micro/components/i18n-switcher#before-link-content","86":"/nuxt-i18n-micro/components/i18n-switcher#after-link-content","87":"/nuxt-i18n-micro/components/i18n-switcher#summary-of-slots","88":"/nuxt-i18n-micro/components/i18n-switcher#🎨-styles-overview","89":"/nuxt-i18n-micro/components/i18n-t#🌍-i18n-t-component","90":"/nuxt-i18n-micro/components/i18n-t#⚙️-props","91":"/nuxt-i18n-micro/components/i18n-t#keypath","92":"/nuxt-i18n-micro/components/i18n-t#plural","93":"/nuxt-i18n-micro/components/i18n-t#number","94":"/nuxt-i18n-micro/components/i18n-t#date","95":"/nuxt-i18n-micro/components/i18n-t#relativedate","96":"/nuxt-i18n-micro/components/i18n-t#tag","97":"/nuxt-i18n-micro/components/i18n-t#params","98":"/nuxt-i18n-micro/components/i18n-t#defaultvalue","99":"/nuxt-i18n-micro/components/i18n-t#html","100":"/nuxt-i18n-micro/components/i18n-t#hideifempty","101":"/nuxt-i18n-micro/components/i18n-t#custompluralrule","102":"/nuxt-i18n-micro/components/i18n-t#🛠️-example-usages","103":"/nuxt-i18n-micro/components/i18n-t#basic-usage","104":"/nuxt-i18n-micro/components/i18n-t#using-slots-for-dynamic-content","105":"/nuxt-i18n-micro/components/i18n-t#pluralization","106":"/nuxt-i18n-micro/components/i18n-t#🚀-additional-features","107":"/nuxt-i18n-micro/components/i18n-t#default-slot","108":"/nuxt-i18n-micro/components/i18n-t#conditional-rendering","109":"/nuxt-i18n-micro/components/i18n-t#custom-pluralization-rule","110":"/nuxt-i18n-micro/components/i18n-t#advanced-example-with-slots","111":"/nuxt-i18n-micro/composables/useI18n#🛠️-usei18n-composable","112":"/nuxt-i18n-micro/composables/useI18n#⚙️-return-values","113":"/nuxt-i18n-micro/composables/useI18n#getlocale","114":"/nuxt-i18n-micro/composables/useI18n#🌍-getlocalename","115":"/nuxt-i18n-micro/composables/useI18n#getlocales","116":"/nuxt-i18n-micro/composables/useI18n#t","117":"/nuxt-i18n-micro/composables/useI18n#tc","118":"/nuxt-i18n-micro/composables/useI18n#has","119":"/nuxt-i18n-micro/composables/useI18n#mergetranslations","120":"/nuxt-i18n-micro/composables/useI18n#switchlocale","121":"/nuxt-i18n-micro/composables/useI18n#localeroute","122":"/nuxt-i18n-micro/composables/useI18n#loadpagetranslations","123":"/nuxt-i18n-micro/composables/useI18n#🛠️-example-usages","124":"/nuxt-i18n-micro/composables/useI18n#basic-locale-retrieval","125":"/nuxt-i18n-micro/composables/useI18n#translation-with-parameters","126":"/nuxt-i18n-micro/composables/useI18n#switching-locales","127":"/nuxt-i18n-micro/composables/useI18n#generating-a-localized-route","128":"/nuxt-i18n-micro/composables/useI18n#loading-page-specific-translations","129":"/nuxt-i18n-micro/composables/useLocaleHead#🌍-uselocalehead-composable","130":"/nuxt-i18n-micro/composables/useLocaleHead#⚙️-options","131":"/nuxt-i18n-micro/composables/useLocaleHead#adddirattribute","132":"/nuxt-i18n-micro/composables/useLocaleHead#identifierattribute","133":"/nuxt-i18n-micro/composables/useLocaleHead#addseoattributes","134":"/nuxt-i18n-micro/composables/useLocaleHead#baseurl","135":"/nuxt-i18n-micro/composables/useLocaleHead#🛠️-return-values","136":"/nuxt-i18n-micro/composables/useLocaleHead#htmlattrs","137":"/nuxt-i18n-micro/composables/useLocaleHead#meta","138":"/nuxt-i18n-micro/composables/useLocaleHead#link","139":"/nuxt-i18n-micro/composables/useLocaleHead#🛠️-example-usages","140":"/nuxt-i18n-micro/composables/useLocaleHead#basic-usage","141":"/nuxt-i18n-micro/composables/useLocaleHead#customize-identifier-attribute","142":"/nuxt-i18n-micro/composables/useLocaleHead#disable-seo-attributes","143":"/nuxt-i18n-micro/composables/useLocaleHead#specify-a-base-url","144":"/nuxt-i18n-micro/composables/useLocaleHead#🚀-additional-features","145":"/nuxt-i18n-micro/composables/useLocaleHead#seo-meta-and-link-tags","146":"/nuxt-i18n-micro/composables/useLocaleHead#dynamic-locale-and-direction","147":"/nuxt-i18n-micro/composables/useLocaleHead#handling-localized-routes","148":"/nuxt-i18n-micro/composables/useLocaleHead#🛠️-example-usage","149":"/nuxt-i18n-micro/composables/useLocaleHead#explanation-of-the-code","150":"/nuxt-i18n-micro/composables/useLocaleHead#📝-notes","151":"/nuxt-i18n-micro/examples#📚-nuxt-i18n-micro-examples-and-usage","152":"/nuxt-i18n-micro/examples#🛠️-basic-setup","153":"/nuxt-i18n-micro/examples#🌍-locale-switching","154":"/nuxt-i18n-micro/examples#switching-locales-programmatically","155":"/nuxt-i18n-micro/examples#example-json-for-locale-switching","156":"/nuxt-i18n-micro/examples#using-i18n-switcher-component","157":"/nuxt-i18n-micro/examples#🌐-using-i18n-link-for-localized-navigation","158":"/nuxt-i18n-micro/examples#example-json-for-navigation-links","159":"/nuxt-i18n-micro/examples#example-with-active-link-styling","160":"/nuxt-i18n-micro/examples#example-json-for-active-link-styling","161":"/nuxt-i18n-micro/examples#📝-rendering-dynamic-keys-from-translation-files","162":"/nuxt-i18n-micro/examples#example-rendering-dynamic-keys","163":"/nuxt-i18n-micro/examples#example-translation-file-en-json","164":"/nuxt-i18n-micro/examples#example-rendering-dynamic-keys-from-an-object","165":"/nuxt-i18n-micro/examples#example-translation-file-en-json-1","166":"/nuxt-i18n-micro/examples#🌟-using-i18n-t-for-translations-with-slots-and-interpolation","167":"/nuxt-i18n-micro/examples#example-json-for-i18n-t","168":"/nuxt-i18n-micro/examples#with-interpolation","169":"/nuxt-i18n-micro/examples#example-json-for-interpolation","170":"/nuxt-i18n-micro/examples#📝-comprehensive-example-with-nested-sections","171":"/nuxt-i18n-micro/examples#example-json-for-nested-sections","172":"/nuxt-i18n-micro/examples#🌟-using-tc-for-pluralization","173":"/nuxt-i18n-micro/examples#example-using-tc-for-pluralization","174":"/nuxt-i18n-micro/examples#example-json-for-pluralization","175":"/nuxt-i18n-micro/examples#explanation","176":"/nuxt-i18n-micro/examples#additional-example-with-more-complex-pluralization","177":"/nuxt-i18n-micro/examples#🌐-using-tn-for-number-formatting","178":"/nuxt-i18n-micro/examples#example-using-tn-for-number-formatting","179":"/nuxt-i18n-micro/examples#🗓️-using-td-for-date-and-time-formatting","180":"/nuxt-i18n-micro/examples#example-using-td-for-date-and-time-formatting","181":"/nuxt-i18n-micro/examples#🗓️-using-tdr-for-relative-date-formatting","182":"/nuxt-i18n-micro/examples#example-using-tdr-for-relative-date-formatting","183":"/nuxt-i18n-micro/guide/cli#🌐-nuxt-i18n-micro-cli-guide","184":"/nuxt-i18n-micro/guide/cli#📖-introduction","185":"/nuxt-i18n-micro/guide/cli#🔧-installation-and-setup","186":"/nuxt-i18n-micro/guide/cli#📦-installing-nuxt-i18n-micro-cli","187":"/nuxt-i18n-micro/guide/cli#🛠-initializing-in-your-project","188":"/nuxt-i18n-micro/guide/cli#📄-common-arguments","189":"/nuxt-i18n-micro/guide/cli#📋-commands","190":"/nuxt-i18n-micro/guide/cli#🔄-text-to-i18n-command","191":"/nuxt-i18n-micro/guide/cli#📊-stats-command","192":"/nuxt-i18n-micro/guide/cli#🌍-translate-command","193":"/nuxt-i18n-micro/guide/cli#🌐-supported-translation-services","194":"/nuxt-i18n-micro/guide/cli#⚙️-service-configuration","195":"/nuxt-i18n-micro/guide/cli#🛠️-extract-command","196":"/nuxt-i18n-micro/guide/cli#🔄-sync-command","197":"/nuxt-i18n-micro/guide/cli#✅-validate-command","198":"/nuxt-i18n-micro/guide/cli#🧹-clean-command","199":"/nuxt-i18n-micro/guide/cli#📤-import-command","200":"/nuxt-i18n-micro/guide/cli#📥-export-command","201":"/nuxt-i18n-micro/guide/cli#🗂️-export-csv-command","202":"/nuxt-i18n-micro/guide/cli#📑-import-csv-command","203":"/nuxt-i18n-micro/guide/cli#🧾-diff-command","204":"/nuxt-i18n-micro/guide/cli#🔍-check-duplicates-command","205":"/nuxt-i18n-micro/guide/cli#🔄-replace-values-command","206":"/nuxt-i18n-micro/guide/cli#🛠-examples","207":"/nuxt-i18n-micro/guide/cli#⚙️-configuration-guide","208":"/nuxt-i18n-micro/guide/cli#🔑-nuxt-config-js-example","209":"/nuxt-i18n-micro/guide/cli#📝-best-practices","210":"/nuxt-i18n-micro/guide/cli#🔑-consistent-key-naming","211":"/nuxt-i18n-micro/guide/cli#🧹-regular-maintenance","212":"/nuxt-i18n-micro/guide/cli#🛠-automate-translation-workflow","213":"/nuxt-i18n-micro/guide/cli#🛡️-secure-api-keys","214":"/nuxt-i18n-micro/guide/cli#📞-support-and-contributions","215":"/nuxt-i18n-micro/guide/contribution#🤝-contribution-guide","216":"/nuxt-i18n-micro/guide/contribution#📖-introduction","217":"/nuxt-i18n-micro/guide/contribution#🚀-getting-started","218":"/nuxt-i18n-micro/guide/contribution#_1-📚-familiarize-yourself-with-the-project","219":"/nuxt-i18n-micro/guide/contribution#_2-🍴-fork-the-repository","220":"/nuxt-i18n-micro/guide/contribution#_3-📥-clone-your-fork","221":"/nuxt-i18n-micro/guide/contribution#_4-🌱-create-a-branch","222":"/nuxt-i18n-micro/guide/contribution#🛠️-local-development-setup","223":"/nuxt-i18n-micro/guide/contribution#🛠-prerequisites","224":"/nuxt-i18n-micro/guide/contribution#🚀-getting-started-1","225":"/nuxt-i18n-micro/guide/contribution#_1-📥-clone-the-repository","226":"/nuxt-i18n-micro/guide/contribution#_2-📦-install-dependencies","227":"/nuxt-i18n-micro/guide/contribution#_3-🖥️-run-the-development-server","228":"/nuxt-i18n-micro/guide/contribution#_4-🏗️-building-the-module","229":"/nuxt-i18n-micro/guide/contribution#_5-🧹-linting-the-code","230":"/nuxt-i18n-micro/guide/contribution#_6-✅-running-tests","231":"/nuxt-i18n-micro/guide/contribution#_7-🔍-type-checking","232":"/nuxt-i18n-micro/guide/contribution#_8-📚-building-and-previewing-the-documentation","233":"/nuxt-i18n-micro/guide/contribution#_9-🎮-running-the-playground","234":"/nuxt-i18n-micro/guide/contribution#🔧-summary-of-common-scripts","235":"/nuxt-i18n-micro/guide/contribution#🚧-making-changes","236":"/nuxt-i18n-micro/guide/contribution#_1-💻-code","237":"/nuxt-i18n-micro/guide/contribution#_2-🧹-run-linting","238":"/nuxt-i18n-micro/guide/contribution#_3-🧪-test-your-changes","239":"/nuxt-i18n-micro/guide/contribution#_4-📝-commit-your-changes","240":"/nuxt-i18n-micro/guide/contribution#✅-commit-message-format","241":"/nuxt-i18n-micro/guide/contribution#📋-examples","242":"/nuxt-i18n-micro/guide/contribution#🛠️-commit-types","243":"/nuxt-i18n-micro/guide/contribution#_5-🚀-push-to-github","244":"/nuxt-i18n-micro/guide/contribution#_6-🔄-create-a-pull-request","245":"/nuxt-i18n-micro/guide/contribution#_7-🕵️‍♂️-await-feedback","246":"/nuxt-i18n-micro/guide/contribution#💡-contribution-tips","247":"/nuxt-i18n-micro/guide/crowdin#🌐-crowdin-integration-guide","248":"/nuxt-i18n-micro/guide/crowdin#📖-introduction","249":"/nuxt-i18n-micro/guide/crowdin#🔧-installation-and-setup","250":"/nuxt-i18n-micro/guide/crowdin#📦-installing-crowdin-cli","251":"/nuxt-i18n-micro/guide/crowdin#🛠-initializing-crowdin-in-your-project","252":"/nuxt-i18n-micro/guide/crowdin#🗂️-configuration-guide","253":"/nuxt-i18n-micro/guide/crowdin#📄-crowdin-configuration-file-crowdin-yml","254":"/nuxt-i18n-micro/guide/crowdin#📂-key-configuration-parameters","255":"/nuxt-i18n-micro/guide/crowdin#📂-files-configuration","256":"/nuxt-i18n-micro/guide/crowdin#⬆️-uploading-source-files-to-crowdin","257":"/nuxt-i18n-micro/guide/crowdin#⬇️-downloading-translations-from-crowdin","258":"/nuxt-i18n-micro/guide/crowdin#⚙️-best-practices","259":"/nuxt-i18n-micro/guide/crowdin#🔑-consistent-key-naming","260":"/nuxt-i18n-micro/guide/crowdin#🧹-regular-maintenance","261":"/nuxt-i18n-micro/guide/crowdin#🛠-automate-uploads-and-downloads","262":"/nuxt-i18n-micro/guide/custom-locale-routes#🔗-custom-localized-routes-with-localeroutes-in-nuxt-i18n-micro","263":"/nuxt-i18n-micro/guide/custom-locale-routes#📖-introduction-to-localeroutes","264":"/nuxt-i18n-micro/guide/custom-locale-routes#🚀-primary-use-case-of-localeroutes","265":"/nuxt-i18n-micro/guide/custom-locale-routes#📄-example-defining-localeroutes-in-definei18nroute","266":"/nuxt-i18n-micro/guide/custom-locale-routes#🔄-how-localeroutes-work","267":"/nuxt-i18n-micro/guide/custom-locale-routes#🌱-use-cases-for-localeroutes","268":"/nuxt-i18n-micro/guide/custom-locale-routes#📄-example-using-localeroutes-in-a-page","269":"/nuxt-i18n-micro/guide/custom-locale-routes#🛠️-using-localeroutes-in-different-contexts","270":"/nuxt-i18n-micro/guide/custom-locale-routes#📝-best-practices-for-using-localeroutes","271":"/nuxt-i18n-micro/guide/devtools#🛠️-devtools-in-nuxt-i18n-micro","272":"/nuxt-i18n-micro/guide/devtools#📖-what-is-nuxt-devtools","273":"/nuxt-i18n-micro/guide/devtools#🌟-key-features-of-devtools-in-nuxt-i18n-micro","274":"/nuxt-i18n-micro/guide/devtools#_1-locale-management","275":"/nuxt-i18n-micro/guide/devtools#_2-translation-editing","276":"/nuxt-i18n-micro/guide/devtools#_3-file-import-and-export","277":"/nuxt-i18n-micro/guide/devtools#_4-real-time-previews","278":"/nuxt-i18n-micro/guide/devtools#_5-seamless-nuxt-integration","279":"/nuxt-i18n-micro/guide/devtools#🛠️-why-use-devtools","280":"/nuxt-i18n-micro/guide/devtools#🚀-take-control-of-localization","281":"/nuxt-i18n-micro/guide/faq#faq-common-issues-solutions","282":"/nuxt-i18n-micro/guide/faq#❓-what-if-a-route-doesn-t-load","283":"/nuxt-i18n-micro/guide/faq#❓-why-is-the-assets-locales-folder-added-to-the-server-folder","284":"/nuxt-i18n-micro/guide/faq#❓-is-nuxt-i18n-micro-inspired-by-vue-i18n-what-about-modifiers","285":"/nuxt-i18n-micro/guide/faq#❓-can-i-use-nuxtlink-or-i18nlink-directly-in-translation-strings","286":"/nuxt-i18n-micro/guide/faq#❓-why-are-translation-keys-not-resolving-during-ssr-on-vercel-and-how-can-i-fix-the-locale-path-issue","287":"/nuxt-i18n-micro/guide/faq#fetch-limitations-on-ssr","288":"/nuxt-i18n-micro/guide/faq#fix-by-setting-apibaseurl","289":"/nuxt-i18n-micro/guide/faq#❓-why-does-t-or-other-i18n-composables-not-work-in-nuxt-plugins","290":"/nuxt-i18n-micro/guide/folder-structure#📂-folder-structure-guide","291":"/nuxt-i18n-micro/guide/folder-structure#📖-introduction","292":"/nuxt-i18n-micro/guide/folder-structure#🗂️-recommended-folder-structure","293":"/nuxt-i18n-micro/guide/folder-structure#🔧-basic-structure","294":"/nuxt-i18n-micro/guide/folder-structure#📄-explanation-of-structure","295":"/nuxt-i18n-micro/guide/folder-structure#_1-🌍-global-translation-files","296":"/nuxt-i18n-micro/guide/folder-structure#_2-📄-page-specific-translation-files","297":"/nuxt-i18n-micro/guide/folder-structure#📂-handling-dynamic-routes-and-nested-paths","298":"/nuxt-i18n-micro/guide/folder-structure#dynamic-route-translation-folder-structure","299":"/nuxt-i18n-micro/guide/folder-structure#🛠-customizing-the-directory-structure","300":"/nuxt-i18n-micro/guide/folder-structure#⚙️-how-translations-are-loaded","301":"/nuxt-i18n-micro/guide/folder-structure#🌍-dynamic-locale-routes","302":"/nuxt-i18n-micro/guide/folder-structure#💾-caching-and-pre-rendering","303":"/nuxt-i18n-micro/guide/folder-structure#📝-best-practices","304":"/nuxt-i18n-micro/guide/folder-structure#📂-use-page-specific-files-wisely","305":"/nuxt-i18n-micro/guide/folder-structure#🔑-keep-translation-keys-consistent","306":"/nuxt-i18n-micro/guide/folder-structure#🗂️-organize-translations-by-context","307":"/nuxt-i18n-micro/guide/folder-structure#🧹-regularly-clean-up-unused-translations","308":"/nuxt-i18n-micro/guide/getting-started#🌐-getting-started-with-nuxt-i18n-micro","309":"/nuxt-i18n-micro/guide/getting-started#📖-overview","310":"/nuxt-i18n-micro/guide/getting-started#🤔-why-choose-nuxt-i18n-micro","311":"/nuxt-i18n-micro/guide/getting-started#🛠-installation","312":"/nuxt-i18n-micro/guide/getting-started#⚙️-basic-setup","313":"/nuxt-i18n-micro/guide/getting-started#📂-folder-structure","314":"/nuxt-i18n-micro/guide/getting-started#⚙️-module-configuration-options","315":"/nuxt-i18n-micro/guide/getting-started#🌍-locales","316":"/nuxt-i18n-micro/guide/getting-started#🌐-defaultlocale","317":"/nuxt-i18n-micro/guide/getting-started#🗂-translationdir","318":"/nuxt-i18n-micro/guide/getting-started#🔍-meta","319":"/nuxt-i18n-micro/guide/getting-started#🐛-debug","320":"/nuxt-i18n-micro/guide/getting-started#🐛-types","321":"/nuxt-i18n-micro/guide/getting-started#🔗-metabaseurl","322":"/nuxt-i18n-micro/guide/getting-started#🌍-autodetectlanguage","323":"/nuxt-i18n-micro/guide/getting-started#🔍-autodetectpath","324":"/nuxt-i18n-micro/guide/getting-started#🔢-plural","325":"/nuxt-i18n-micro/guide/getting-started#🚦-includedefaultlocaleroute","326":"/nuxt-i18n-micro/guide/getting-started#🚦-strategy","327":"/nuxt-i18n-micro/guide/getting-started#🚦-customregexmatcher","328":"/nuxt-i18n-micro/guide/getting-started#🔗-routeslocalelinks","329":"/nuxt-i18n-micro/guide/getting-started#🧩-define","330":"/nuxt-i18n-micro/guide/getting-started#🧩-plugin","331":"/nuxt-i18n-micro/guide/getting-started#🔄-disablepagelocales","332":"/nuxt-i18n-micro/guide/getting-started#📂-folder-structure-with-disablepagelocales-true","333":"/nuxt-i18n-micro/guide/getting-started#👀-disablewatcher","334":"/nuxt-i18n-micro/guide/getting-started#👀-disableupdater","335":"/nuxt-i18n-micro/guide/getting-started#🔗-apibaseurl","336":"/nuxt-i18n-micro/guide/getting-started#🍪-localecookie","337":"/nuxt-i18n-micro/guide/getting-started#🌐-fallbacklocale","338":"/nuxt-i18n-micro/guide/getting-started#🌐-globallocaleroutes","339":"/nuxt-i18n-micro/guide/getting-started#usage","340":"/nuxt-i18n-micro/guide/getting-started#🔄-caching-mechanism","341":"/nuxt-i18n-micro/guide/migration#🔄-migration-from-nuxt-i18n-to-nuxt-i18n-micro","342":"/nuxt-i18n-micro/guide/migration#📖-introduction","343":"/nuxt-i18n-micro/guide/migration#🚀-why-migrate","344":"/nuxt-i18n-micro/guide/migration#🔍-key-differences","345":"/nuxt-i18n-micro/guide/migration#🛠️-step-by-step-migration","346":"/nuxt-i18n-micro/guide/migration#_1-🛠️-install-nuxt-i18n-micro","347":"/nuxt-i18n-micro/guide/migration#_2-🔄-update-configuration","348":"/nuxt-i18n-micro/guide/migration#_3-🗂️-reorganize-translation-files","349":"/nuxt-i18n-micro/guide/migration#_4-🔗-replace-nuxt-link-with-nuxtlink","350":"/nuxt-i18n-micro/guide/migration#_5-🛠️-handle-seo-configurations","351":"/nuxt-i18n-micro/guide/migration#_6-🧪-test-your-application","352":"/nuxt-i18n-micro/guide/migration#🛡️-common-issues-and-troubleshooting","353":"/nuxt-i18n-micro/guide/migration#❌-translation-files-not-loading","354":"/nuxt-i18n-micro/guide/migration#⚠️-route-not-found-errors","355":"/nuxt-i18n-micro/guide/migration#🏷️-missing-seo-tags","356":"/nuxt-i18n-micro/guide/layers#🗂️-layers-in-nuxt-i18n-micro","357":"/nuxt-i18n-micro/guide/layers#📖-introduction-to-layers","358":"/nuxt-i18n-micro/guide/layers#🛠️-primary-configuration-layer","359":"/nuxt-i18n-micro/guide/layers#📄-example-defining-the-primary-configuration-layer","360":"/nuxt-i18n-micro/guide/layers#🌱-child-layers","361":"/nuxt-i18n-micro/guide/layers#📄-example-extending-the-primary-layer-in-a-child-layer","362":"/nuxt-i18n-micro/guide/layers#🌐-using-layers-in-a-modular-application","363":"/nuxt-i18n-micro/guide/layers#📄-example-layered-configuration-in-a-modular-application","364":"/nuxt-i18n-micro/guide/layers#primary-layer-global-configuration","365":"/nuxt-i18n-micro/guide/layers#child-layer-for-admin-panel","366":"/nuxt-i18n-micro/guide/layers#child-layer-for-customer-support-portal","367":"/nuxt-i18n-micro/guide/layers#📝-best-practices-for-using-layers","368":"/nuxt-i18n-micro/guide/multi-domain-locales#🌍-setting-up-multi-domain-locales-with-nuxt-i18n-micro-using-layers","369":"/nuxt-i18n-micro/guide/multi-domain-locales#📝-introduction","370":"/nuxt-i18n-micro/guide/multi-domain-locales#🎯-objective","371":"/nuxt-i18n-micro/guide/multi-domain-locales#🛠-steps-to-implement-multi-domain-locales","372":"/nuxt-i18n-micro/guide/multi-domain-locales#_1-create-the-base-layer","373":"/nuxt-i18n-micro/guide/multi-domain-locales#base-layer-configuration","374":"/nuxt-i18n-micro/guide/multi-domain-locales#_2-create-domain-specific-child-layers","375":"/nuxt-i18n-micro/guide/multi-domain-locales#example-configuration-for-the-french-domain","376":"/nuxt-i18n-micro/guide/multi-domain-locales#example-configuration-for-the-german-domain","377":"/nuxt-i18n-micro/guide/multi-domain-locales#_3-deploy-the-application-for-each-domain","378":"/nuxt-i18n-micro/guide/multi-domain-locales#_4-set-up-multiple-projects-for-different-locales","379":"/nuxt-i18n-micro/guide/multi-domain-locales#_5-configure-routing-based-on-domain","380":"/nuxt-i18n-micro/guide/multi-domain-locales#_6-deploy-and-verify","381":"/nuxt-i18n-micro/guide/multi-domain-locales#📝-best-practices","382":"/nuxt-i18n-micro/guide/multi-domain-locales#🎉-conclusion","383":"/nuxt-i18n-micro/guide/per-component-translations#📖-per-component-translations-in-nuxt-i18n-micro","384":"/nuxt-i18n-micro/guide/per-component-translations#overview","385":"/nuxt-i18n-micro/guide/per-component-translations#definei18nroute-function","386":"/nuxt-i18n-micro/guide/per-component-translations#method-signature","387":"/nuxt-i18n-micro/guide/per-component-translations#parameters","388":"/nuxt-i18n-micro/guide/per-component-translations#example-usage","389":"/nuxt-i18n-micro/guide/per-component-translations#use-cases","390":"/nuxt-i18n-micro/guide/per-component-translations#best-practices","391":"/nuxt-i18n-micro/guide/per-component-translations#example-vue-page-with-per-component-translations","392":"/nuxt-i18n-micro/guide/per-component-translations#explanation","393":"/nuxt-i18n-micro/guide/per-component-translations#summary","394":"/nuxt-i18n-micro/guide/performance-results#performance-test-results","395":"/nuxt-i18n-micro/guide/performance-results#project-information","396":"/nuxt-i18n-micro/guide/performance-results#description","397":"/nuxt-i18n-micro/guide/performance-results#important-note","398":"/nuxt-i18n-micro/guide/performance-results#dependency-versions","399":"/nuxt-i18n-micro/guide/performance-results#build-performance-for-test-fixtures-i18n","400":"/nuxt-i18n-micro/guide/performance-results#build-performance-for-test-fixtures-i18n-micro","401":"/nuxt-i18n-micro/guide/performance-results#⏱️-build-time-and-resource-consumption","402":"/nuxt-i18n-micro/guide/performance-results#performance-comparison","403":"/nuxt-i18n-micro/guide/performance-results#stress-test-with-artillery-for-test-fixtures-i18n","404":"/nuxt-i18n-micro/guide/performance-results#stress-test-with-artillery-for-test-fixtures-i18n-micro","405":"/nuxt-i18n-micro/guide/performance-results#comparison-between-i18n-v9-and-i18n-micro","406":"/nuxt-i18n-micro/guide/performance-results#📊-detailed-performance-analysis","407":"/nuxt-i18n-micro/guide/performance-results#🔍-test-logic-explanation","408":"/nuxt-i18n-micro/guide/performance-results#🛠-why-this-approach","409":"/nuxt-i18n-micro/guide/performance#🚀-performance-guide","410":"/nuxt-i18n-micro/guide/performance#📖-introduction","411":"/nuxt-i18n-micro/guide/performance#🤔-why-focus-on-performance","412":"/nuxt-i18n-micro/guide/performance#📊-performance-comparison","413":"/nuxt-i18n-micro/guide/performance#⏱️-build-time-and-resource-consumption","414":"/nuxt-i18n-micro/guide/performance#🌐-server-performance-under-load","415":"/nuxt-i18n-micro/guide/performance#🔍-interpretation-of-results","416":"/nuxt-i18n-micro/guide/performance#⚙️-key-optimizations","417":"/nuxt-i18n-micro/guide/performance#🛠️-minimalist-design","418":"/nuxt-i18n-micro/guide/performance#🚦-efficient-routing","419":"/nuxt-i18n-micro/guide/performance#📂-streamlined-translation-loading","420":"/nuxt-i18n-micro/guide/performance#💾-caching-and-pre-rendering","421":"/nuxt-i18n-micro/guide/performance#📝-tips-for-maximizing-performance","422":"/nuxt-i18n-micro/guide/seo#🌐-seo-guide-for-nuxt-i18n-micro","423":"/nuxt-i18n-micro/guide/seo#📖-introduction","424":"/nuxt-i18n-micro/guide/seo#⚙️-automatic-seo-handling","425":"/nuxt-i18n-micro/guide/seo#🔑-key-seo-features","426":"/nuxt-i18n-micro/guide/seo#🛠️-configuration","427":"/nuxt-i18n-micro/guide/seo#🎯-benefits","428":"/nuxt-i18n-micro/guide/server-side-translations#🌍-server-side-translations-in-nuxt-i18n-micro","429":"/nuxt-i18n-micro/guide/server-side-translations#📖-overview","430":"/nuxt-i18n-micro/guide/server-side-translations#🛠️-setting-up-server-side-translations","431":"/nuxt-i18n-micro/guide/server-side-translations#✨-using-translations-in-server-handlers","432":"/nuxt-i18n-micro/guide/server-side-translations#example-basic-usage","433":"/nuxt-i18n-micro/guide/server-side-translations#🌐-providing-a-custom-locale","434":"/nuxt-i18n-micro/guide/server-side-translations#example-custom-locale","435":"/nuxt-i18n-micro/guide/server-side-translations#📋-detecting-locale","436":"/nuxt-i18n-micro/guide/strategy#🗂️-strategies-for-locale-prefix-handling-in-nuxt-i18n-version-1-50-0","437":"/nuxt-i18n-micro/guide/strategy#📖-introduction-to-locale-prefix-strategies","438":"/nuxt-i18n-micro/guide/strategy#🚦-strategy-new-in-version-1-50-0","439":"/nuxt-i18n-micro/guide/strategy#available-strategies","440":"/nuxt-i18n-micro/guide/strategy#🛑-no-prefix","441":"/nuxt-i18n-micro/guide/strategy#🚧-prefix-except-default","442":"/nuxt-i18n-micro/guide/strategy#🌍-prefix","443":"/nuxt-i18n-micro/guide/strategy#🔄-prefix-and-default","444":"/nuxt-i18n-micro/guide/strategy#⚠️-known-issues-and-best-practices","445":"/nuxt-i18n-micro/guide/strategy#_1-hydration-mismatch-in-no-prefix-strategy-with-static-generation","446":"/nuxt-i18n-micro/guide/strategy#_2-issues-with-localeroute-and-route-resolution","447":"/nuxt-i18n-micro/guide/strategy#_3-rendering-issues-with-locale-dependent-content-in-no-prefix-strategy","448":"/nuxt-i18n-micro/guide/strategy#📝-conclusion","449":"/nuxt-i18n-micro/guide/strategy#📚-best-practices","450":"/nuxt-i18n-micro/guide/testing#🧪-testing-nuxt-i18n-micro-module","451":"/nuxt-i18n-micro/guide/testing#📖-introduction-to-testing","452":"/nuxt-i18n-micro/guide/testing#🛠️-setting-up-the-testing-environment","453":"/nuxt-i18n-micro/guide/testing#_1-install-nuxt-i18n-micro-test-utils","454":"/nuxt-i18n-micro/guide/testing#_2-create-a-mock-configuration-file","455":"/nuxt-i18n-micro/guide/testing#_3-configure-vitest","456":"/nuxt-i18n-micro/guide/testing#🧪-writing-tests","457":"/nuxt-i18n-micro/guide/testing#example-component","458":"/nuxt-i18n-micro/guide/testing#test-file","459":"/nuxt-i18n-micro/guide/testing#📝-best-practices-for-testing","460":"/nuxt-i18n-micro/guide/testing#📊-i18n-utility-methods","461":"/nuxt-i18n-micro/#✨-introduction","462":"/nuxt-i18n-micro/#📝-why-nuxt-i18n-micro","463":"/nuxt-i18n-micro/#🏁-performance-comparison","464":"/nuxt-i18n-micro/#⏱️-build-time-and-resource-consumption","465":"/nuxt-i18n-micro/#🌐-server-performance-10k-requests","466":"/nuxt-i18n-micro/#🔑-key-features","467":"/nuxt-i18n-micro/#⚙️-quick-setup","468":"/nuxt-i18n-micro/#🗂-folder-structure","469":"/nuxt-i18n-micro/news/#news","470":"/nuxt-i18n-micro/news/#major-release-nuxt-i18n-micro-v1-65-0","471":"/nuxt-i18n-micro/news/#optimized-translation-loading-algorithm-released","472":"/nuxt-i18n-micro/news/#what-s-new","473":"/nuxt-i18n-micro/news/#key-benefits","474":"/nuxt-i18n-micro/news/#_1-faster-build-times","475":"/nuxt-i18n-micro/news/#_2-reduced-cpu-usage","476":"/nuxt-i18n-micro/news/#_3-lower-memory-usage","477":"/nuxt-i18n-micro/news/#_4-enhanced-response-times","478":"/nuxt-i18n-micro/news/#_5-increased-request-throughput","479":"/nuxt-i18n-micro/news/#why-it-s-important","480":"/nuxt-i18n-micro/news/#how-it-works","481":"/nuxt-i18n-micro/news/#key-benefits-1","482":"/nuxt-i18n-micro/news/#how-it-works-1","483":"/nuxt-i18n-micro/news/#usage","484":"/nuxt-i18n-micro/news/#example-transformations","485":"/nuxt-i18n-micro/news/#before","486":"/nuxt-i18n-micro/news/#after"},"fieldIds":{"title":0,"titles":1,"text":2},"fieldLength":{"0":[2,1,1],"1":[3,2,37],"2":[3,5,65],"3":[3,5,27],"4":[2,5,34],"5":[3,5,44],"6":[5,2,31],"7":[3,7,40],"8":[3,7,75],"9":[3,7,67],"10":[8,7,87],"11":[2,1,1],"12":[2,2,19],"13":[2,2,26],"14":[2,2,31],"15":[2,2,49],"16":[2,2,61],"17":[2,2,61],"18":[2,2,60],"19":[2,2,59],"20":[2,2,75],"21":[2,2,49],"22":[2,2,58],"23":[2,2,35],"24":[2,2,35],"25":[2,2,29],"26":[2,2,91],"27":[2,2,78],"28":[2,2,41],"29":[2,2,38],"30":[2,2,36],"31":[2,2,184],"32":[6,2,65],"33":[2,2,13],"34":[3,2,15],"35":[6,1,26],"36":[2,6,1],"37":[1,8,27],"38":[1,8,19],"39":[2,6,1],"40":[2,8,35],"41":[3,6,1],"42":[2,9,35],"43":[3,9,38],"44":[3,9,51],"45":[2,6,30],"46":[3,6,63],"47":[6,1,40],"48":[2,6,1],"49":[1,8,38],"50":[1,8,52],"51":[3,6,1],"52":[2,9,20],"53":[6,9,32],"54":[3,9,38],"55":[2,6,22],"56":[3,8,27],"57":[3,8,25],"58":[3,6,1],"59":[4,9,28],"60":[2,9,29],"61":[6,1,36],"62":[2,6,1],"63":[1,8,37],"64":[1,8,32],"65":[1,8,32],"66":[1,8,37],"67":[1,8,30],"68":[1,8,35],"69":[1,8,34],"70":[1,8,33],"71":[1,8,35],"72":[3,6,1],"73":[2,9,16],"74":[5,9,67],"75":[2,6,36],"76":[2,8,21],"77":[3,8,27],"78":[3,8,27],"79":[2,8,24],"80":[2,8,25],"81":[3,8,26],"82":[3,8,26],"83":[2,8,34],"84":[2,8,29],"85":[3,8,36],"86":[3,8,31],"87":[3,8,27],"88":[3,6,66],"89":[6,1,38],"90":[2,6,1],"91":[1,8,25],"92":[1,8,28],"93":[1,8,38],"94":[1,8,41],"95":[1,8,44],"96":[1,8,27],"97":[1,8,33],"98":[1,8,30],"99":[1,8,26],"100":[1,8,30],"101":[1,8,63],"102":[3,6,1],"103":[2,9,20],"104":[5,9,52],"105":[1,9,20],"106":[3,6,1],"107":[2,9,34],"108":[2,9,23],"109":[3,9,31],"110":[4,9,23],"111":[3,1,50],"112":[3,3,16],"113":[1,6,22],"114":[2,3,26],"115":[1,5,31],"116":[1,5,56],"117":[1,5,41],"118":[1,5,28],"119":[1,5,25],"120":[1,5,19],"121":[1,5,26],"122":[1,5,29],"123":[3,3,1],"124":[3,5,12],"125":[3,5,20],"126":[2,5,13],"127":[4,5,18],"128":[4,5,17],"129":[3,1,38],"130":[2,3,12],"131":[1,5,30],"132":[1,5,33],"133":[1,5,31],"134":[1,5,30],"135":[3,3,28],"136":[1,6,31],"137":[1,6,34],"138":[1,6,37],"139":[3,3,1],"140":[2,6,12],"141":[3,6,17],"142":[3,6,17],"143":[4,6,19],"144":[3,3,1],"145":[5,6,29],"146":[4,6,27],"147":[3,6,46],"148":[3,3,34],"149":[4,6,78],"150":[2,6,72],"151":[7,1,35],"152":[3,7,41],"153":[3,7,1],"154":[3,10,45],"155":[5,10,8],"156":[6,10,29],"157":[9,7,36],"158":[5,16,7],"159":[5,16,14],"160":[6,16,16],"161":[7,7,33],"162":[4,14,56],"163":[6,14,15],"164":[7,14,52],"165":[6,14,20],"166":[12,7,34],"167":[8,18,7],"168":[2,18,15],"169":[4,18,10],"170":[6,7,78],"171":[5,13,61],"172":[5,7,37],"173":[5,12,51],"174":[4,12,25],"175":[1,12,26],"176":[6,12,48],"177":[6,7,36],"178":[6,13,43],"179":[8,7,31],"180":[8,14,50],"181":[7,7,35],"182":[7,14,44],"183":[6,1,1],"184":[2,6,57],"185":[4,6,1],"186":[6,10,21],"187":[5,10,28],"188":[3,10,24],"189":[2,6,1],"190":[5,8,192],"191":[3,8,50],"192":[3,8,87],"193":[4,11,52],"194":[3,11,43],"195":[3,8,26],"196":[3,8,19],"197":[3,8,21],"198":[3,8,14],"199":[3,8,28],"200":[3,8,23],"201":[4,8,52],"202":[4,8,43],"203":[3,8,40],"204":[4,8,81],"205":[4,8,174],"206":[2,6,35],"207":[3,6,21],"208":[5,8,41],"209":[3,6,1],"210":[4,9,12],"211":[3,9,15],"212":[4,9,24],"213":[4,9,28],"214":[4,6,52],"215":[3,1,1],"216":[2,3,44],"217":[3,3,1],"218":[7,6,33],"219":[5,6,23],"220":[5,6,27],"221":[5,6,26],"222":[4,1,1],"223":[2,4,22],"224":[3,4,1],"225":[5,7,21],"226":[4,7,18],"227":[6,7,37],"228":[5,7,27],"229":[5,7,28],"230":[4,7,24],"231":[4,7,21],"232":[7,7,26],"233":[5,7,36],"234":[5,4,49],"235":[3,1,1],"236":[3,3,30],"237":[4,3,27],"238":[5,3,37],"239":[5,3,20],"240":[4,7,14],"241":[3,7,23],"242":[4,7,45],"243":[5,3,13],"244":[6,3,35],"245":[4,3,28],"246":[3,3,50],"247":[4,1,1],"248":[2,4,38],"249":[4,4,23],"250":[4,8,13],"251":[6,8,28],"252":[3,4,1],"253":[7,6,49],"254":[4,6,54],"255":[3,6,40],"256":[6,4,30],"257":[5,4,31],"258":[3,4,1],"259":[4,7,14],"260":[3,7,15],"261":[5,7,43],"262":[10,1,1],"263":[4,10,46],"264":[6,10,45],"265":[6,15,33],"266":[4,15,31],"267":[5,10,1],"268":[7,14,69],"269":[6,14,42],"270":[6,10,69],"271":[6,1,1],"272":[6,6,44],"273":[9,6,1],"274":[3,10,29],"275":[3,10,27],"276":[5,10,30],"277":[4,10,19],"278":[4,10,29],"279":[5,6,49],"280":[5,6,37],"281":[5,1,1],"282":[9,5,53],"283":[11,5,70],"284":[13,5,81],"285":[12,5,67],"286":[21,5,1],"287":[4,26,33],"288":[4,26,26],"289":[14,5,143],"290":[4,1,1],"291":[2,4,47],"292":[4,4,31],"293":[3,6,25],"294":[4,6,1],"295":[5,9,54],"296":[6,9,71],"297":[7,6,33],"298":[5,12,57],"299":[5,6,50],"300":[5,4,1],"301":[4,9,56],"302":[5,9,57],"303":[3,4,1],"304":[6,7,30],"305":[5,7,25],"306":[5,7,37],"307":[6,7,28],"308":[7,1,1],"309":[2,7,36],"310":[7,7,45],"311":[2,7,16],"312":[3,7,34],"313":[3,10,35],"314":[4,7,31],"315":[2,11,177],"316":[2,11,17],"317":[2,11,18],"318":[2,11,23],"319":[2,11,22],"320":[2,11,24],"321":[2,11,25],"322":[2,11,28],"323":[2,11,53],"324":[2,11,46],"325":[2,11,34],"326":[2,11,94],"327":[2,11,48],"328":[2,11,25],"329":[2,11,35],"330":[2,11,25],"331":[2,11,25],"332":[6,11,32],"333":[2,11,17],"334":[2,11,23],"335":[2,11,57],"336":[2,11,16],"337":[2,11,41],"338":[2,11,80],"339":[2,11,52],"340":[3,1,58],"341":[9,1,1],"342":[2,9,39],"343":[4,9,52],"344":[3,9,83],"345":[4,9,1],"346":[6,12,14],"347":[4,12,41],"348":[5,12,32],"349":[10,12,35],"350":[5,12,27],"351":[5,12,34],"352":[5,9,1],"353":[5,14,23],"354":[5,14,21],"355":[4,14,26],"356":[6,1,1],"357":[4,6,47],"358":[4,6,34],"359":[7,10,64],"360":[3,6,43],"361":[9,8,78],"362":[7,8,28],"363":[8,8,34],"364":[5,15,23],"365":[6,15,37],"366":[7,15,73],"367":[6,6,70],"368":[12,1,1],"369":[2,12,64],"370":[2,12,38],"371":[7,12,1],"372":[5,16,27],"373":[3,21,30],"374":[6,16,26],"375":[6,20,54],"376":[6,20,53],"377":[7,16,17],"378":[8,16,45],"379":[6,16,35],"380":[4,16,27],"381":[3,12,33],"382":[2,12,63],"383":[8,1,1],"384":[1,8,44],"385":[2,8,29],"386":[2,10,11],"387":[1,10,55],"388":[2,10,25],"389":[2,8,92],"390":[2,8,64],"391":[7,8,77],"392":[1,8,68],"393":[1,8,48],"394":[3,1,1],"395":[2,3,12],"396":[2,5,55],"397":[3,5,70],"398":[2,3,17],"399":[6,3,24],"400":[7,3,25],"401":[6,9,24],"402":[2,3,28],"403":[8,3,38],"404":[9,3,36],"405":[6,3,37],"406":[4,3,1],"407":[4,6,119],"408":[5,6,84],"409":[3,1,1],"410":[2,3,39],"411":[6,3,57],"412":[3,3,38],"413":[6,5,40],"414":[5,5,50],"415":[4,5,81],"416":[3,3,1],"417":[3,6,30],"418":[3,6,41],"419":[4,6,34],"420":[5,6,54],"421":[5,3,81],"422":[7,1,1],"423":[2,7,56],"424":[4,7,1],"425":[4,10,103],"426":[2,10,43],"427":[2,10,63],"428":[8,1,1],"429":[2,8,78],"430":[6,8,25],"431":[6,8,13],"432":[3,11,43],"433":[5,8,21],"434":[3,13,43],"435":[3,8,28],"436":[14,1,1],"437":[6,14,64],"438":[9,14,33],"439":[3,14,1],"440":[3,15,103],"441":[4,15,66],"442":[2,15,58],"443":[4,15,75],"444":[6,14,23],"445":[10,19,68],"446":[7,19,53],"447":[11,19,97],"448":[2,14,48],"449":[4,15,97],"450":[6,1,1],"451":[4,6,48],"452":[6,6,1],"453":[7,11,30],"454":[6,11,98],"455":[3,11,35],"456":[3,6,1],"457":[2,8,53],"458":[2,8,67],"459":[5,6,61],"460":[4,6,100],"461":[2,1,57],"462":[6,1,76],"463":[3,6,27],"464":[6,8,41],"465":[6,8,52],"466":[3,1,116],"467":[3,1,50],"468":[3,1,22],"469":[1,1,1],"470":[8,1,47],"471":[5,1,41],"472":[4,6,41],"473":[2,6,1],"474":[4,8,29],"475":[4,8,31],"476":[4,8,32],"477":[4,8,27],"478":[4,8,22],"479":[4,6,46],"480":[3,6,61],"481":[2,6,32],"482":[3,6,34],"483":[1,6,14],"484":[2,6,1],"485":[1,8,15],"486":[1,8,24]},"averageFieldLength":[3.858316221765914,7.402464065708422,35.59753593429158],"storedFields":{"0":{"title":"📢 Events","titles":[]},"1":{"title":"🔄 i18n:register","titles":["📢 Events"]},"2":{"title":"📝 Event Details","titles":["📢 Events","🔄 i18n:register"]},"3":{"title":"💡 Example Usage","titles":["📢 Events","🔄 i18n:register"]},"4":{"title":"🛠️ Explanation","titles":["📢 Events","🔄 i18n:register"]},"5":{"title":"🔗 Key Benefits","titles":["📢 Events","🔄 i18n:register"]},"6":{"title":"🛠️ Modifying Translations with Plugins","titles":["📢 Events"]},"7":{"title":"Registering the Plugin","titles":["📢 Events","🛠️ Modifying Translations with Plugins"]},"8":{"title":"Implementing the Plugin","titles":["📢 Events","🛠️ Modifying Translations with Plugins"]},"9":{"title":"📝 Detailed Explanation","titles":["📢 Events","🛠️ Modifying Translations with Plugins"]},"10":{"title":"🔗 Benefits of Using Plugins for Translation Modifications","titles":["📢 Events","🛠️ Modifying Translations with Plugins"]},"11":{"title":"🛠️ Methods","titles":[]},"12":{"title":"🌍 $getLocale","titles":["🛠️ Methods"]},"13":{"title":"🌍 $getLocaleName","titles":["🛠️ Methods"]},"14":{"title":"🌍 $getLocales","titles":["🛠️ Methods"]},"15":{"title":"🔍 $getRouteName","titles":["🛠️ Methods"]},"16":{"title":"🔍 $t","titles":["🛠️ Methods"]},"17":{"title":"🔍 $ts","titles":["🛠️ Methods"]},"18":{"title":"🔢 $tc","titles":["🛠️ Methods"]},"19":{"title":"🔢 $tn","titles":["🛠️ Methods"]},"20":{"title":"📅 $td","titles":["🛠️ Methods"]},"21":{"title":"📅 $tn","titles":["🛠️ Methods"]},"22":{"title":"📅 $tdr","titles":["🛠️ Methods"]},"23":{"title":"🔄 $switchLocaleRoute","titles":["🛠️ Methods"]},"24":{"title":"🔄 $switchLocalePath","titles":["🛠️ Methods"]},"25":{"title":"🔄 $switchLocale","titles":["🛠️ Methods"]},"26":{"title":"🔄 $switchRoute","titles":["🛠️ Methods"]},"27":{"title":"🔄 $setI18nRouteParams","titles":["🛠️ Methods"]},"28":{"title":"🌐 $localeRoute","titles":["🛠️ Methods"]},"29":{"title":"🔄 $localePath","titles":["🛠️ Methods"]},"30":{"title":"🗂️ $mergeTranslations","titles":["🛠️ Methods"]},"31":{"title":"🚦 $defineI18nRoute","titles":["🛠️ Methods"]},"32":{"title":"💻 Example Usage in a Component","titles":["🛠️ Methods"]},"33":{"title":"🛠️ useNuxtApp","titles":["🛠️ Methods"]},"34":{"title":"🧩 useI18n Composable","titles":["🛠️ Methods"]},"35":{"title":"🌍 <i18n-group> Component","titles":[]},"36":{"title":"⚙️ Props","titles":["🌍 <i18n-group> Component"]},"37":{"title":"prefix","titles":["🌍 <i18n-group> Component","⚙️ Props"]},"38":{"title":"groupClass","titles":["🌍 <i18n-group> Component","⚙️ Props"]},"39":{"title":"🎯 Slots","titles":["🌍 <i18n-group> Component"]},"40":{"title":"Default Slot","titles":["🌍 <i18n-group> Component","🎯 Slots"]},"41":{"title":"🛠️ Example Usage","titles":["🌍 <i18n-group> Component"]},"42":{"title":"Basic Usage","titles":["🌍 <i18n-group> Component","🛠️ Example Usage"]},"43":{"title":"With Custom Class","titles":["🌍 <i18n-group> Component","🛠️ Example Usage"]},"44":{"title":"With Dynamic Content","titles":["🌍 <i18n-group> Component","🛠️ Example Usage"]},"45":{"title":"🎨 Styling","titles":["🌍 <i18n-group> Component"]},"46":{"title":"🚀 Best Practices","titles":["🌍 <i18n-group> Component"]},"47":{"title":"🌍 <i18n-link> Component","titles":[]},"48":{"title":"⚙️ Props","titles":["🌍 <i18n-link> Component"]},"49":{"title":"to","titles":["🌍 <i18n-link> Component","⚙️ Props"]},"50":{"title":"activeStyle","titles":["🌍 <i18n-link> Component","⚙️ Props"]},"51":{"title":"🛠️ Example Usages","titles":["🌍 <i18n-link> Component"]},"52":{"title":"Basic Usage","titles":["🌍 <i18n-link> Component","🛠️ Example Usages"]},"53":{"title":"Active Link Styling with Inline Styles","titles":["🌍 <i18n-link> Component","🛠️ Example Usages"]},"54":{"title":"External Links Handling","titles":["🌍 <i18n-link> Component","🛠️ Example Usages"]},"55":{"title":"🎨 Styles","titles":["🌍 <i18n-link> Component"]},"56":{"title":"Default Active Styles","titles":["🌍 <i18n-link> Component","🎨 Styles"]},"57":{"title":"Custom Active Styles","titles":["🌍 <i18n-link> Component","🎨 Styles"]},"58":{"title":"🚀 Additional Features","titles":["🌍 <i18n-link> Component"]},"59":{"title":"Slot for Custom Content","titles":["🌍 <i18n-link> Component","🚀 Additional Features"]},"60":{"title":"Accessibility Enhancements","titles":["🌍 <i18n-link> Component","🚀 Additional Features"]},"61":{"title":"🌍 <i18n-switcher> Component","titles":[]},"62":{"title":"⚙️ Props","titles":["🌍 <i18n-switcher> Component"]},"63":{"title":"customLabels","titles":["🌍 <i18n-switcher> Component","⚙️ Props"]},"64":{"title":"customWrapperStyle","titles":["🌍 <i18n-switcher> Component","⚙️ Props"]},"65":{"title":"customButtonStyle","titles":["🌍 <i18n-switcher> Component","⚙️ Props"]},"66":{"title":"customDropdownStyle","titles":["🌍 <i18n-switcher> Component","⚙️ Props"]},"67":{"title":"customItemStyle","titles":["🌍 <i18n-switcher> Component","⚙️ Props"]},"68":{"title":"customLinkStyle","titles":["🌍 <i18n-switcher> Component","⚙️ Props"]},"69":{"title":"customActiveLinkStyle","titles":["🌍 <i18n-switcher> Component","⚙️ Props"]},"70":{"title":"customDisabledLinkStyle","titles":["🌍 <i18n-switcher> Component","⚙️ Props"]},"71":{"title":"customIconStyle","titles":["🌍 <i18n-switcher> Component","⚙️ Props"]},"72":{"title":"🛠️ Example Usages","titles":["🌍 <i18n-switcher> Component"]},"73":{"title":"Basic Usage","titles":["🌍 <i18n-switcher> Component","🛠️ Example Usages"]},"74":{"title":"Custom Labels and Inline Styles","titles":["🌍 <i18n-switcher> Component","🛠️ Example Usages"]},"75":{"title":"🔌 Slots","titles":["🌍 <i18n-switcher> Component"]},"76":{"title":"before-button","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"77":{"title":"before-selected-locale","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"78":{"title":"after-selected-locale","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"79":{"title":"before-dropdown","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"80":{"title":"after-dropdown","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"81":{"title":"before-dropdown-items","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"82":{"title":"after-dropdown-items","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"83":{"title":"before-item","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"84":{"title":"after-item","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"85":{"title":"before-link-content","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"86":{"title":"after-link-content","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"87":{"title":"Summary of Slots","titles":["🌍 <i18n-switcher> Component","🔌 Slots"]},"88":{"title":"🎨 Styles Overview","titles":["🌍 <i18n-switcher> Component"]},"89":{"title":"🌍 <i18n-t> Component","titles":[]},"90":{"title":"⚙️ Props","titles":["🌍 <i18n-t> Component"]},"91":{"title":"keypath","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"92":{"title":"plural","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"93":{"title":"number","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"94":{"title":"date","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"95":{"title":"relativeDate","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"96":{"title":"tag","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"97":{"title":"params","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"98":{"title":"defaultValue","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"99":{"title":"html","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"100":{"title":"hideIfEmpty","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"101":{"title":"customPluralRule","titles":["🌍 <i18n-t> Component","⚙️ Props"]},"102":{"title":"🛠️ Example Usages","titles":["🌍 <i18n-t> Component"]},"103":{"title":"Basic Usage","titles":["🌍 <i18n-t> Component","🛠️ Example Usages"]},"104":{"title":"Using Slots for Dynamic Content","titles":["🌍 <i18n-t> Component","🛠️ Example Usages"]},"105":{"title":"Pluralization","titles":["🌍 <i18n-t> Component","🛠️ Example Usages"]},"106":{"title":"🚀 Additional Features","titles":["🌍 <i18n-t> Component"]},"107":{"title":"Default Slot","titles":["🌍 <i18n-t> Component","🚀 Additional Features"]},"108":{"title":"Conditional Rendering","titles":["🌍 <i18n-t> Component","🚀 Additional Features"]},"109":{"title":"Custom Pluralization Rule","titles":["🌍 <i18n-t> Component","🚀 Additional Features"]},"110":{"title":"Advanced Example with Slots","titles":["🌍 <i18n-t> Component","🚀 Additional Features"]},"111":{"title":"🛠️ useI18n Composable","titles":[]},"112":{"title":"⚙️ Return Values","titles":["🛠️ useI18n Composable"]},"113":{"title":"$getLocale","titles":["🛠️ useI18n Composable","⚙️ Return Values"]},"114":{"title":"🌍 $getLocaleName","titles":["🛠️ useI18n Composable"]},"115":{"title":"$getLocales","titles":["🛠️ useI18n Composable","🌍 $getLocaleName"]},"116":{"title":"$t","titles":["🛠️ useI18n Composable","🌍 $getLocaleName"]},"117":{"title":"$tc","titles":["🛠️ useI18n Composable","🌍 $getLocaleName"]},"118":{"title":"$has","titles":["🛠️ useI18n Composable","🌍 $getLocaleName"]},"119":{"title":"$mergeTranslations","titles":["🛠️ useI18n Composable","🌍 $getLocaleName"]},"120":{"title":"$switchLocale","titles":["🛠️ useI18n Composable","🌍 $getLocaleName"]},"121":{"title":"$localeRoute","titles":["🛠️ useI18n Composable","🌍 $getLocaleName"]},"122":{"title":"$loadPageTranslations","titles":["🛠️ useI18n Composable","🌍 $getLocaleName"]},"123":{"title":"🛠️ Example Usages","titles":["🛠️ useI18n Composable"]},"124":{"title":"Basic Locale Retrieval","titles":["🛠️ useI18n Composable","🛠️ Example Usages"]},"125":{"title":"Translation with Parameters","titles":["🛠️ useI18n Composable","🛠️ Example Usages"]},"126":{"title":"Switching Locales","titles":["🛠️ useI18n Composable","🛠️ Example Usages"]},"127":{"title":"Generating a Localized Route","titles":["🛠️ useI18n Composable","🛠️ Example Usages"]},"128":{"title":"Loading Page-Specific Translations","titles":["🛠️ useI18n Composable","🛠️ Example Usages"]},"129":{"title":"🌍 useLocaleHead Composable","titles":[]},"130":{"title":"⚙️ Options","titles":["🌍 useLocaleHead Composable"]},"131":{"title":"addDirAttribute","titles":["🌍 useLocaleHead Composable","⚙️ Options"]},"132":{"title":"identifierAttribute","titles":["🌍 useLocaleHead Composable","⚙️ Options"]},"133":{"title":"addSeoAttributes","titles":["🌍 useLocaleHead Composable","⚙️ Options"]},"134":{"title":"baseUrl","titles":["🌍 useLocaleHead Composable","⚙️ Options"]},"135":{"title":"🛠️ Return Values","titles":["🌍 useLocaleHead Composable"]},"136":{"title":"htmlAttrs","titles":["🌍 useLocaleHead Composable","🛠️ Return Values"]},"137":{"title":"meta","titles":["🌍 useLocaleHead Composable","🛠️ Return Values"]},"138":{"title":"link","titles":["🌍 useLocaleHead Composable","🛠️ Return Values"]},"139":{"title":"🛠️ Example Usages","titles":["🌍 useLocaleHead Composable"]},"140":{"title":"Basic Usage","titles":["🌍 useLocaleHead Composable","🛠️ Example Usages"]},"141":{"title":"Customize Identifier Attribute","titles":["🌍 useLocaleHead Composable","🛠️ Example Usages"]},"142":{"title":"Disable SEO Attributes","titles":["🌍 useLocaleHead Composable","🛠️ Example Usages"]},"143":{"title":"Specify a Base URL","titles":["🌍 useLocaleHead Composable","🛠️ Example Usages"]},"144":{"title":"🚀 Additional Features","titles":["🌍 useLocaleHead Composable"]},"145":{"title":"SEO Meta and Link Tags","titles":["🌍 useLocaleHead Composable","🚀 Additional Features"]},"146":{"title":"Dynamic Locale and Direction","titles":["🌍 useLocaleHead Composable","🚀 Additional Features"]},"147":{"title":"Handling Localized Routes","titles":["🌍 useLocaleHead Composable","🚀 Additional Features"]},"148":{"title":"🛠️ Example Usage","titles":["🌍 useLocaleHead Composable"]},"149":{"title":"Explanation of the Code","titles":["🌍 useLocaleHead Composable","🛠️ Example Usage"]},"150":{"title":"📝 Notes","titles":["🌍 useLocaleHead Composable","🛠️ Example Usage"]},"151":{"title":"📚 Nuxt I18n Micro Examples and Usage","titles":[]},"152":{"title":"🛠️ Basic Setup","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"153":{"title":"🌍 Locale Switching","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"154":{"title":"Switching Locales Programmatically","titles":["📚 Nuxt I18n Micro Examples and Usage","🌍 Locale Switching"]},"155":{"title":"Example JSON for Locale Switching","titles":["📚 Nuxt I18n Micro Examples and Usage","🌍 Locale Switching"]},"156":{"title":"Using <i18n-switcher> Component","titles":["📚 Nuxt I18n Micro Examples and Usage","🌍 Locale Switching"]},"157":{"title":"🌐 Using <i18n-link> for Localized Navigation","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"158":{"title":"Example JSON for Navigation Links","titles":["📚 Nuxt I18n Micro Examples and Usage","🌐 Using <i18n-link> for Localized Navigation"]},"159":{"title":"Example with Active Link Styling","titles":["📚 Nuxt I18n Micro Examples and Usage","🌐 Using <i18n-link> for Localized Navigation"]},"160":{"title":"Example JSON for Active Link Styling","titles":["📚 Nuxt I18n Micro Examples and Usage","🌐 Using <i18n-link> for Localized Navigation"]},"161":{"title":"📝 Rendering Dynamic Keys from Translation Files","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"162":{"title":"Example: Rendering Dynamic Keys","titles":["📚 Nuxt I18n Micro Examples and Usage","📝 Rendering Dynamic Keys from Translation Files"]},"163":{"title":"Example Translation File (en.json)","titles":["📚 Nuxt I18n Micro Examples and Usage","📝 Rendering Dynamic Keys from Translation Files"]},"164":{"title":"Example: Rendering Dynamic Keys from an Object","titles":["📚 Nuxt I18n Micro Examples and Usage","📝 Rendering Dynamic Keys from Translation Files"]},"165":{"title":"Example Translation File (en.json)","titles":["📚 Nuxt I18n Micro Examples and Usage","📝 Rendering Dynamic Keys from Translation Files"]},"166":{"title":"🌟 Using <i18n-t> for Translations with Slots and Interpolation","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"167":{"title":"Example JSON for <i18n-t>","titles":["📚 Nuxt I18n Micro Examples and Usage","🌟 Using <i18n-t> for Translations with Slots and Interpolation"]},"168":{"title":"With Interpolation","titles":["📚 Nuxt I18n Micro Examples and Usage","🌟 Using <i18n-t> for Translations with Slots and Interpolation"]},"169":{"title":"Example JSON for Interpolation","titles":["📚 Nuxt I18n Micro Examples and Usage","🌟 Using <i18n-t> for Translations with Slots and Interpolation"]},"170":{"title":"📝 Comprehensive Example with Nested Sections","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"171":{"title":"Example JSON for Nested Sections","titles":["📚 Nuxt I18n Micro Examples and Usage","📝 Comprehensive Example with Nested Sections"]},"172":{"title":"🌟 Using $tc for Pluralization","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"173":{"title":"Example: Using $tc for Pluralization","titles":["📚 Nuxt I18n Micro Examples and Usage","🌟 Using $tc for Pluralization"]},"174":{"title":"Example JSON for Pluralization","titles":["📚 Nuxt I18n Micro Examples and Usage","🌟 Using $tc for Pluralization"]},"175":{"title":"Explanation","titles":["📚 Nuxt I18n Micro Examples and Usage","🌟 Using $tc for Pluralization"]},"176":{"title":"Additional Example with More Complex Pluralization","titles":["📚 Nuxt I18n Micro Examples and Usage","🌟 Using $tc for Pluralization"]},"177":{"title":"🌐 Using $tn for Number Formatting","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"178":{"title":"Example: Using $tn for Number Formatting","titles":["📚 Nuxt I18n Micro Examples and Usage","🌐 Using $tn for Number Formatting"]},"179":{"title":"🗓️ Using $td for Date and Time Formatting","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"180":{"title":"Example: Using $td for Date and Time Formatting","titles":["📚 Nuxt I18n Micro Examples and Usage","🗓️ Using $td for Date and Time Formatting"]},"181":{"title":"🗓️ Using $tdr for Relative Date Formatting","titles":["📚 Nuxt I18n Micro Examples and Usage"]},"182":{"title":"Example: Using $tdr for Relative Date Formatting","titles":["📚 Nuxt I18n Micro Examples and Usage","🗓️ Using $tdr for Relative Date Formatting"]},"183":{"title":"🌐 nuxt-i18n-micro-cli Guide","titles":[]},"184":{"title":"📖 Introduction","titles":["🌐 nuxt-i18n-micro-cli Guide"]},"185":{"title":"🔧 Installation and Setup","titles":["🌐 nuxt-i18n-micro-cli Guide"]},"186":{"title":"📦 Installing nuxt-i18n-micro-cli","titles":["🌐 nuxt-i18n-micro-cli Guide","🔧 Installation and Setup"]},"187":{"title":"🛠 Initializing in Your Project","titles":["🌐 nuxt-i18n-micro-cli Guide","🔧 Installation and Setup"]},"188":{"title":"📄 Common Arguments","titles":["🌐 nuxt-i18n-micro-cli Guide","🔧 Installation and Setup"]},"189":{"title":"📋 Commands","titles":["🌐 nuxt-i18n-micro-cli Guide"]},"190":{"title":"🔄 text-to-i18n Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"191":{"title":"📊 stats Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"192":{"title":"🌍 translate Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"193":{"title":"🌐 Supported Translation Services","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands","🌍 translate Command"]},"194":{"title":"⚙️ Service Configuration","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands","🌍 translate Command"]},"195":{"title":"🛠️ extract Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"196":{"title":"🔄 sync Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"197":{"title":"✅ validate Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"198":{"title":"🧹 clean Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"199":{"title":"📤 import Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"200":{"title":"📥 export Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"201":{"title":"🗂️ export-csv Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"202":{"title":"📑 import-csv Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"203":{"title":"🧾 diff Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"204":{"title":"🔍 check-duplicates Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"205":{"title":"🔄 replace-values Command","titles":["🌐 nuxt-i18n-micro-cli Guide","📋 Commands"]},"206":{"title":"🛠 Examples","titles":["🌐 nuxt-i18n-micro-cli Guide"]},"207":{"title":"⚙️ Configuration Guide","titles":["🌐 nuxt-i18n-micro-cli Guide"]},"208":{"title":"🔑 nuxt.config.js Example","titles":["🌐 nuxt-i18n-micro-cli Guide","⚙️ Configuration Guide"]},"209":{"title":"📝 Best Practices","titles":["🌐 nuxt-i18n-micro-cli Guide"]},"210":{"title":"🔑 Consistent Key Naming","titles":["🌐 nuxt-i18n-micro-cli Guide","📝 Best Practices"]},"211":{"title":"🧹 Regular Maintenance","titles":["🌐 nuxt-i18n-micro-cli Guide","📝 Best Practices"]},"212":{"title":"🛠 Automate Translation Workflow","titles":["🌐 nuxt-i18n-micro-cli Guide","📝 Best Practices"]},"213":{"title":"🛡️ Secure API Keys","titles":["🌐 nuxt-i18n-micro-cli Guide","📝 Best Practices"]},"214":{"title":"📞 Support and Contributions","titles":["🌐 nuxt-i18n-micro-cli Guide"]},"215":{"title":"🤝 Contribution Guide","titles":[]},"216":{"title":"📖 Introduction","titles":["🤝 Contribution Guide"]},"217":{"title":"🚀 Getting Started","titles":["🤝 Contribution Guide"]},"218":{"title":"1. 📚 Familiarize Yourself with the Project","titles":["🤝 Contribution Guide","🚀 Getting Started"]},"219":{"title":"2. 🍴 Fork the Repository","titles":["🤝 Contribution Guide","🚀 Getting Started"]},"220":{"title":"3. 📥 Clone Your Fork","titles":["🤝 Contribution Guide","🚀 Getting Started"]},"221":{"title":"4. 🌱 Create a Branch","titles":["🤝 Contribution Guide","🚀 Getting Started"]},"222":{"title":"🛠️ Local Development Setup","titles":[]},"223":{"title":"🛠 Prerequisites","titles":["🛠️ Local Development Setup"]},"224":{"title":"🚀 Getting Started","titles":["🛠️ Local Development Setup"]},"225":{"title":"1. 📥 Clone the Repository","titles":["🛠️ Local Development Setup","🚀 Getting Started"]},"226":{"title":"2. 📦 Install Dependencies","titles":["🛠️ Local Development Setup","🚀 Getting Started"]},"227":{"title":"3. 🖥️ Run the Development Server","titles":["🛠️ Local Development Setup","🚀 Getting Started"]},"228":{"title":"4. 🏗️ Building the Module","titles":["🛠️ Local Development Setup","🚀 Getting Started"]},"229":{"title":"5. 🧹 Linting the Code","titles":["🛠️ Local Development Setup","🚀 Getting Started"]},"230":{"title":"6. ✅ Running Tests","titles":["🛠️ Local Development Setup","🚀 Getting Started"]},"231":{"title":"7. 🔍 Type Checking","titles":["🛠️ Local Development Setup","🚀 Getting Started"]},"232":{"title":"8. 📚 Building and Previewing the Documentation","titles":["🛠️ Local Development Setup","🚀 Getting Started"]},"233":{"title":"9. 🎮 Running the Playground","titles":["🛠️ Local Development Setup","🚀 Getting Started"]},"234":{"title":"🔧 Summary of Common Scripts","titles":["🛠️ Local Development Setup"]},"235":{"title":"🚧 Making Changes","titles":[]},"236":{"title":"1. 💻 Code","titles":["🚧 Making Changes"]},"237":{"title":"2. 🧹 Run Linting","titles":["🚧 Making Changes"]},"238":{"title":"3. 🧪 Test Your Changes","titles":["🚧 Making Changes"]},"239":{"title":"4. 📝 Commit Your Changes","titles":["🚧 Making Changes"]},"240":{"title":"✅ Commit Message Format","titles":["🚧 Making Changes","4. 📝 Commit Your Changes"]},"241":{"title":"📋 Examples:","titles":["🚧 Making Changes","4. 📝 Commit Your Changes"]},"242":{"title":"🛠️ Commit Types:","titles":["🚧 Making Changes","4. 📝 Commit Your Changes"]},"243":{"title":"5. 🚀 Push to GitHub","titles":["🚧 Making Changes"]},"244":{"title":"6. 🔄 Create a Pull Request","titles":["🚧 Making Changes"]},"245":{"title":"7. 🕵️‍♂️ Await Feedback","titles":["🚧 Making Changes"]},"246":{"title":"💡 Contribution Tips","titles":["🚧 Making Changes"]},"247":{"title":"🌐 Crowdin Integration Guide","titles":[]},"248":{"title":"📖 Introduction","titles":["🌐 Crowdin Integration Guide"]},"249":{"title":"🔧 Installation and Setup","titles":["🌐 Crowdin Integration Guide"]},"250":{"title":"📦 Installing Crowdin CLI","titles":["🌐 Crowdin Integration Guide","🔧 Installation and Setup"]},"251":{"title":"🛠 Initializing Crowdin in Your Project","titles":["🌐 Crowdin Integration Guide","🔧 Installation and Setup"]},"252":{"title":"🗂️ Configuration Guide","titles":["🌐 Crowdin Integration Guide"]},"253":{"title":"📄 Crowdin Configuration File (crowdin.yml)","titles":["🌐 Crowdin Integration Guide","🗂️ Configuration Guide"]},"254":{"title":"📂 Key Configuration Parameters","titles":["🌐 Crowdin Integration Guide","🗂️ Configuration Guide"]},"255":{"title":"📂 Files Configuration","titles":["🌐 Crowdin Integration Guide","🗂️ Configuration Guide"]},"256":{"title":"⬆️ Uploading Source Files to Crowdin","titles":["🌐 Crowdin Integration Guide"]},"257":{"title":"⬇️ Downloading Translations from Crowdin","titles":["🌐 Crowdin Integration Guide"]},"258":{"title":"⚙️ Best Practices","titles":["🌐 Crowdin Integration Guide"]},"259":{"title":"🔑 Consistent Key Naming","titles":["🌐 Crowdin Integration Guide","⚙️ Best Practices"]},"260":{"title":"🧹 Regular Maintenance","titles":["🌐 Crowdin Integration Guide","⚙️ Best Practices"]},"261":{"title":"🛠 Automate Uploads and Downloads","titles":["🌐 Crowdin Integration Guide","⚙️ Best Practices"]},"262":{"title":"🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro","titles":[]},"263":{"title":"📖 Introduction to localeRoutes","titles":["🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro"]},"264":{"title":"🚀 Primary Use Case of localeRoutes","titles":["🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro"]},"265":{"title":"📄 Example: Defining localeRoutes in $defineI18nRoute","titles":["🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro","🚀 Primary Use Case of localeRoutes"]},"266":{"title":"🔄 How localeRoutes Work","titles":["🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro","🚀 Primary Use Case of localeRoutes"]},"267":{"title":"🌱 Use Cases for localeRoutes","titles":["🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro"]},"268":{"title":"📄 Example: Using localeRoutes in a Page","titles":["🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro","🌱 Use Cases for localeRoutes"]},"269":{"title":"🛠️ Using localeRoutes in Different Contexts","titles":["🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro","🌱 Use Cases for localeRoutes"]},"270":{"title":"📝 Best Practices for Using localeRoutes","titles":["🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro"]},"271":{"title":"🛠️ DevTools in nuxt-i18n-micro","titles":[]},"272":{"title":"📖 What Is Nuxt DevTools?","titles":["🛠️ DevTools in nuxt-i18n-micro"]},"273":{"title":"🌟 Key Features of DevTools in nuxt-i18n-micro","titles":["🛠️ DevTools in nuxt-i18n-micro"]},"274":{"title":"1. Locale Management","titles":["🛠️ DevTools in nuxt-i18n-micro","🌟 Key Features of DevTools in nuxt-i18n-micro"]},"275":{"title":"2. Translation Editing","titles":["🛠️ DevTools in nuxt-i18n-micro","🌟 Key Features of DevTools in nuxt-i18n-micro"]},"276":{"title":"3. File Import and Export","titles":["🛠️ DevTools in nuxt-i18n-micro","🌟 Key Features of DevTools in nuxt-i18n-micro"]},"277":{"title":"4. Real-Time Previews","titles":["🛠️ DevTools in nuxt-i18n-micro","🌟 Key Features of DevTools in nuxt-i18n-micro"]},"278":{"title":"5. Seamless Nuxt Integration","titles":["🛠️ DevTools in nuxt-i18n-micro","🌟 Key Features of DevTools in nuxt-i18n-micro"]},"279":{"title":"🛠️ Why Use DevTools?","titles":["🛠️ DevTools in nuxt-i18n-micro"]},"280":{"title":"🚀 Take Control of Localization","titles":["🛠️ DevTools in nuxt-i18n-micro"]},"281":{"title":"FAQ: Common Issues & Solutions","titles":[]},"282":{"title":"❓ What if a route doesn\'t load?","titles":["FAQ: Common Issues & Solutions"]},"283":{"title":"❓ Why is the assets/_locales/ folder added to the server folder?","titles":["FAQ: Common Issues & Solutions"]},"284":{"title":"❓ Is Nuxt I18n Micro inspired by vue-i18n? What about modifiers?","titles":["FAQ: Common Issues & Solutions"]},"285":{"title":"❓ Can I use NuxtLink or i18nLink directly in translation strings?","titles":["FAQ: Common Issues & Solutions"]},"286":{"title":"❓ Why are translation keys not resolving during SSR on Vercel, and how can I fix the locale path issue?","titles":["FAQ: Common Issues & Solutions"]},"287":{"title":"$fetch limitations on SSR","titles":["FAQ: Common Issues & Solutions","❓ Why are translation keys not resolving during SSR on Vercel, and how can I fix the locale path issue?"]},"288":{"title":"Fix by setting apiBaseUrl","titles":["FAQ: Common Issues & Solutions","❓ Why are translation keys not resolving during SSR on Vercel, and how can I fix the locale path issue?"]},"289":{"title":"❓ Why does $t or other i18n composables not work in Nuxt plugins?","titles":["FAQ: Common Issues & Solutions"]},"290":{"title":"📂 Folder Structure Guide","titles":[]},"291":{"title":"📖 Introduction","titles":["📂 Folder Structure Guide"]},"292":{"title":"🗂️ Recommended Folder Structure","titles":["📂 Folder Structure Guide"]},"293":{"title":"🔧 Basic Structure","titles":["📂 Folder Structure Guide","🗂️ Recommended Folder Structure"]},"294":{"title":"📄 Explanation of Structure","titles":["📂 Folder Structure Guide","🗂️ Recommended Folder Structure"]},"295":{"title":"1. 🌍 Global Translation Files","titles":["📂 Folder Structure Guide","🗂️ Recommended Folder Structure","📄 Explanation of Structure"]},"296":{"title":"2. 📄 Page-Specific Translation Files","titles":["📂 Folder Structure Guide","🗂️ Recommended Folder Structure","📄 Explanation of Structure"]},"297":{"title":"📂 Handling Dynamic Routes and Nested Paths","titles":["📂 Folder Structure Guide","🗂️ Recommended Folder Structure"]},"298":{"title":"Dynamic Route Translation Folder Structure","titles":["📂 Folder Structure Guide","🗂️ Recommended Folder Structure","📂 Handling Dynamic Routes and Nested Paths"]},"299":{"title":"🛠 Customizing the Directory Structure","titles":["📂 Folder Structure Guide","🗂️ Recommended Folder Structure"]},"300":{"title":"⚙️ How Translations are Loaded","titles":["📂 Folder Structure Guide"]},"301":{"title":"🌍 Dynamic Locale Routes","titles":["📂 Folder Structure Guide","⚙️ How Translations are Loaded"]},"302":{"title":"💾 Caching and Pre-rendering","titles":["📂 Folder Structure Guide","⚙️ How Translations are Loaded"]},"303":{"title":"📝 Best Practices","titles":["📂 Folder Structure Guide"]},"304":{"title":"📂 Use Page-Specific Files Wisely","titles":["📂 Folder Structure Guide","📝 Best Practices"]},"305":{"title":"🔑 Keep Translation Keys Consistent","titles":["📂 Folder Structure Guide","📝 Best Practices"]},"306":{"title":"🗂️ Organize Translations by Context","titles":["📂 Folder Structure Guide","📝 Best Practices"]},"307":{"title":"🧹 Regularly Clean Up Unused Translations","titles":["📂 Folder Structure Guide","📝 Best Practices"]},"308":{"title":"🌐 Getting Started with Nuxt I18n Micro","titles":[]},"309":{"title":"📖 Overview","titles":["🌐 Getting Started with Nuxt I18n Micro"]},"310":{"title":"🤔 Why Choose Nuxt I18n Micro?","titles":["🌐 Getting Started with Nuxt I18n Micro"]},"311":{"title":"🛠 Installation","titles":["🌐 Getting Started with Nuxt I18n Micro"]},"312":{"title":"⚙️ Basic Setup","titles":["🌐 Getting Started with Nuxt I18n Micro"]},"313":{"title":"📂 Folder Structure","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Basic Setup"]},"314":{"title":"⚙️ Module Configuration Options","titles":["🌐 Getting Started with Nuxt I18n Micro"]},"315":{"title":"🌍 locales","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"316":{"title":"🌐 defaultLocale","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"317":{"title":"🗂 translationDir","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"318":{"title":"🔍 meta","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"319":{"title":"🐛 debug","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"320":{"title":"🐛 types","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"321":{"title":"🔗 metaBaseUrl","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"322":{"title":"🌍 autoDetectLanguage","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"323":{"title":"🔍 autoDetectPath","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"324":{"title":"🔢 plural","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"325":{"title":"🚦 includeDefaultLocaleRoute","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"326":{"title":"🚦 strategy","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"327":{"title":"🚦 customRegexMatcher","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"328":{"title":"🔗 routesLocaleLinks","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"329":{"title":"🧩 define","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"330":{"title":"🧩 plugin","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"331":{"title":"🔄 disablePageLocales","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"332":{"title":"📂 Folder Structure with disablePageLocales: true","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"333":{"title":"👀 disableWatcher","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"334":{"title":"👀 disableUpdater","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"335":{"title":"🔗 apiBaseUrl","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"336":{"title":"🍪 localeCookie","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"337":{"title":"🌐 fallbackLocale","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"338":{"title":"🌐 globalLocaleRoutes","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"339":{"title":"Usage:","titles":["🌐 Getting Started with Nuxt I18n Micro","⚙️ Module Configuration Options"]},"340":{"title":"🔄 Caching Mechanism","titles":[]},"341":{"title":"🔄 Migration from nuxt-i18n to Nuxt I18n Micro","titles":[]},"342":{"title":"📖 Introduction","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro"]},"343":{"title":"🚀 Why Migrate?","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro"]},"344":{"title":"🔍 Key Differences","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro"]},"345":{"title":"🛠️ Step-by-Step Migration","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro"]},"346":{"title":"1. 🛠️ Install Nuxt I18n Micro","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro","🛠️ Step-by-Step Migration"]},"347":{"title":"2. 🔄 Update Configuration","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro","🛠️ Step-by-Step Migration"]},"348":{"title":"3. 🗂️ Reorganize Translation Files","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro","🛠️ Step-by-Step Migration"]},"349":{"title":"4. 🔗 Replace <nuxt-link> with <NuxtLink>","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro","🛠️ Step-by-Step Migration"]},"350":{"title":"5. 🛠️ Handle SEO Configurations","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro","🛠️ Step-by-Step Migration"]},"351":{"title":"6. 🧪 Test Your Application","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro","🛠️ Step-by-Step Migration"]},"352":{"title":"🛡️ Common Issues and Troubleshooting","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro"]},"353":{"title":"❌ Translation Files Not Loading","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro","🛡️ Common Issues and Troubleshooting"]},"354":{"title":"⚠️ Route Not Found Errors","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro","🛡️ Common Issues and Troubleshooting"]},"355":{"title":"🏷️ Missing SEO Tags","titles":["🔄 Migration from nuxt-i18n to Nuxt I18n Micro","🛡️ Common Issues and Troubleshooting"]},"356":{"title":"🗂️ Layers in Nuxt I18n Micro","titles":[]},"357":{"title":"📖 Introduction to Layers","titles":["🗂️ Layers in Nuxt I18n Micro"]},"358":{"title":"🛠️ Primary Configuration Layer","titles":["🗂️ Layers in Nuxt I18n Micro"]},"359":{"title":"📄 Example: Defining the Primary Configuration Layer","titles":["🗂️ Layers in Nuxt I18n Micro","🛠️ Primary Configuration Layer"]},"360":{"title":"🌱 Child Layers","titles":["🗂️ Layers in Nuxt I18n Micro"]},"361":{"title":"📄 Example: Extending the Primary Layer in a Child Layer","titles":["🗂️ Layers in Nuxt I18n Micro","🌱 Child Layers"]},"362":{"title":"🌐 Using Layers in a Modular Application","titles":["🗂️ Layers in Nuxt I18n Micro","🌱 Child Layers"]},"363":{"title":"📄 Example: Layered Configuration in a Modular Application","titles":["🗂️ Layers in Nuxt I18n Micro","🌱 Child Layers"]},"364":{"title":"Primary Layer (Global Configuration):","titles":["🗂️ Layers in Nuxt I18n Micro","🌱 Child Layers","📄 Example: Layered Configuration in a Modular Application"]},"365":{"title":"Child Layer for Admin Panel:","titles":["🗂️ Layers in Nuxt I18n Micro","🌱 Child Layers","📄 Example: Layered Configuration in a Modular Application"]},"366":{"title":"Child Layer for Customer Support Portal:","titles":["🗂️ Layers in Nuxt I18n Micro","🌱 Child Layers","📄 Example: Layered Configuration in a Modular Application"]},"367":{"title":"📝 Best Practices for Using Layers","titles":["🗂️ Layers in Nuxt I18n Micro"]},"368":{"title":"🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","titles":[]},"369":{"title":"📝 Introduction","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers"]},"370":{"title":"🎯 Objective","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers"]},"371":{"title":"🛠 Steps to Implement Multi-Domain Locales","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers"]},"372":{"title":"1. Create the Base Layer","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","🛠 Steps to Implement Multi-Domain Locales"]},"373":{"title":"Base Layer Configuration","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","🛠 Steps to Implement Multi-Domain Locales","1. Create the Base Layer"]},"374":{"title":"2. Create Domain-Specific Child Layers","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","🛠 Steps to Implement Multi-Domain Locales"]},"375":{"title":"Example: Configuration for the French Domain","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","🛠 Steps to Implement Multi-Domain Locales","2. Create Domain-Specific Child Layers"]},"376":{"title":"Example: Configuration for the German Domain","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","🛠 Steps to Implement Multi-Domain Locales","2. Create Domain-Specific Child Layers"]},"377":{"title":"3. Deploy the Application for Each Domain","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","🛠 Steps to Implement Multi-Domain Locales"]},"378":{"title":"4. Set Up Multiple Projects for Different Locales","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","🛠 Steps to Implement Multi-Domain Locales"]},"379":{"title":"5. Configure Routing Based on Domain","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","🛠 Steps to Implement Multi-Domain Locales"]},"380":{"title":"6. Deploy and Verify","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","🛠 Steps to Implement Multi-Domain Locales"]},"381":{"title":"📝 Best Practices","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers"]},"382":{"title":"🎉 Conclusion","titles":["🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers"]},"383":{"title":"📖 Per-Component Translations in Nuxt I18n Micro","titles":[]},"384":{"title":"Overview","titles":["📖 Per-Component Translations in Nuxt I18n Micro"]},"385":{"title":"$defineI18nRoute Function","titles":["📖 Per-Component Translations in Nuxt I18n Micro"]},"386":{"title":"Method Signature","titles":["📖 Per-Component Translations in Nuxt I18n Micro","$defineI18nRoute Function"]},"387":{"title":"Parameters","titles":["📖 Per-Component Translations in Nuxt I18n Micro","$defineI18nRoute Function"]},"388":{"title":"Example Usage","titles":["📖 Per-Component Translations in Nuxt I18n Micro","$defineI18nRoute Function"]},"389":{"title":"Use Cases","titles":["📖 Per-Component Translations in Nuxt I18n Micro"]},"390":{"title":"Best Practices","titles":["📖 Per-Component Translations in Nuxt I18n Micro"]},"391":{"title":"Example: Vue Page with Per-Component Translations","titles":["📖 Per-Component Translations in Nuxt I18n Micro"]},"392":{"title":"Explanation","titles":["📖 Per-Component Translations in Nuxt I18n Micro"]},"393":{"title":"Summary","titles":["📖 Per-Component Translations in Nuxt I18n Micro"]},"394":{"title":"Performance Test Results","titles":[]},"395":{"title":"Project Information","titles":["Performance Test Results"]},"396":{"title":"Description:","titles":["Performance Test Results","Project Information"]},"397":{"title":"Important Note:","titles":["Performance Test Results","Project Information"]},"398":{"title":"Dependency Versions","titles":["Performance Test Results"]},"399":{"title":"Build Performance for ./test/fixtures/i18n","titles":["Performance Test Results"]},"400":{"title":"Build Performance for ./test/fixtures/i18n-micro","titles":["Performance Test Results"]},"401":{"title":"⏱️ Build Time and Resource Consumption","titles":["Performance Test Results","Build Performance for ./test/fixtures/i18n-micro"]},"402":{"title":"Performance Comparison","titles":["Performance Test Results"]},"403":{"title":"Stress Test with Artillery for ./test/fixtures/i18n","titles":["Performance Test Results"]},"404":{"title":"Stress Test with Artillery for ./test/fixtures/i18n-micro","titles":["Performance Test Results"]},"405":{"title":"Comparison between i18n v9 and i18n-micro","titles":["Performance Test Results"]},"406":{"title":"📊 Detailed Performance Analysis","titles":["Performance Test Results"]},"407":{"title":"🔍 Test Logic Explanation","titles":["Performance Test Results","📊 Detailed Performance Analysis"]},"408":{"title":"🛠 Why This Approach?","titles":["Performance Test Results","📊 Detailed Performance Analysis"]},"409":{"title":"🚀 Performance Guide","titles":[]},"410":{"title":"📖 Introduction","titles":["🚀 Performance Guide"]},"411":{"title":"🤔 Why Focus on Performance?","titles":["🚀 Performance Guide"]},"412":{"title":"📊 Performance Comparison","titles":["🚀 Performance Guide"]},"413":{"title":"⏱️ Build Time and Resource Consumption","titles":["🚀 Performance Guide","📊 Performance Comparison"]},"414":{"title":"🌐 Server Performance Under Load","titles":["🚀 Performance Guide","📊 Performance Comparison"]},"415":{"title":"🔍 Interpretation of Results","titles":["🚀 Performance Guide","📊 Performance Comparison"]},"416":{"title":"⚙️ Key Optimizations","titles":["🚀 Performance Guide"]},"417":{"title":"🛠️ Minimalist Design","titles":["🚀 Performance Guide","⚙️ Key Optimizations"]},"418":{"title":"🚦 Efficient Routing","titles":["🚀 Performance Guide","⚙️ Key Optimizations"]},"419":{"title":"📂 Streamlined Translation Loading","titles":["🚀 Performance Guide","⚙️ Key Optimizations"]},"420":{"title":"💾 Caching and Pre-rendering","titles":["🚀 Performance Guide","⚙️ Key Optimizations"]},"421":{"title":"📝 Tips for Maximizing Performance","titles":["🚀 Performance Guide"]},"422":{"title":"🌐 SEO Guide for Nuxt I18n Micro","titles":[]},"423":{"title":"📖 Introduction","titles":["🌐 SEO Guide for Nuxt I18n Micro"]},"424":{"title":"⚙️ Automatic SEO Handling","titles":["🌐 SEO Guide for Nuxt I18n Micro"]},"425":{"title":"🔑 Key SEO Features","titles":["🌐 SEO Guide for Nuxt I18n Micro","⚙️ Automatic SEO Handling"]},"426":{"title":"🛠️ Configuration","titles":["🌐 SEO Guide for Nuxt I18n Micro","⚙️ Automatic SEO Handling"]},"427":{"title":"🎯 Benefits","titles":["🌐 SEO Guide for Nuxt I18n Micro","⚙️ Automatic SEO Handling"]},"428":{"title":"🌍 Server-Side Translations in Nuxt I18n Micro","titles":[]},"429":{"title":"📖 Overview","titles":["🌍 Server-Side Translations in Nuxt I18n Micro"]},"430":{"title":"🛠️ Setting Up Server-Side Translations","titles":["🌍 Server-Side Translations in Nuxt I18n Micro"]},"431":{"title":"✨ Using Translations in Server Handlers","titles":["🌍 Server-Side Translations in Nuxt I18n Micro"]},"432":{"title":"Example: Basic Usage","titles":["🌍 Server-Side Translations in Nuxt I18n Micro","✨ Using Translations in Server Handlers"]},"433":{"title":"🌐 Providing a Custom Locale","titles":["🌍 Server-Side Translations in Nuxt I18n Micro"]},"434":{"title":"Example: Custom Locale","titles":["🌍 Server-Side Translations in Nuxt I18n Micro","🌐 Providing a Custom Locale"]},"435":{"title":"📋 Detecting Locale","titles":["🌍 Server-Side Translations in Nuxt I18n Micro"]},"436":{"title":"🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","titles":[]},"437":{"title":"📖 Introduction to Locale Prefix Strategies","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)"]},"438":{"title":"🚦 strategy (New in Version 1.50.0)","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)"]},"439":{"title":"Available Strategies:","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)"]},"440":{"title":"🛑 no_prefix","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","Available Strategies:"]},"441":{"title":"🚧 prefix_except_default","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","Available Strategies:"]},"442":{"title":"🌍 prefix","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","Available Strategies:"]},"443":{"title":"🔄 prefix_and_default","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","Available Strategies:"]},"444":{"title":"⚠️ Known Issues and Best Practices","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)"]},"445":{"title":"1. Hydration Mismatch in no_prefix Strategy with Static Generation","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","⚠️ Known Issues and Best Practices"]},"446":{"title":"2. Issues with localeRoute and Route Resolution","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","⚠️ Known Issues and Best Practices"]},"447":{"title":"3. Rendering Issues with Locale-Dependent Content in no_prefix Strategy","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","⚠️ Known Issues and Best Practices"]},"448":{"title":"📝 Conclusion","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)"]},"449":{"title":"📚 Best Practices:","titles":["🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","📝 Conclusion"]},"450":{"title":"🧪 Testing Nuxt I18n Micro Module","titles":[]},"451":{"title":"📖 Introduction to Testing","titles":["🧪 Testing Nuxt I18n Micro Module"]},"452":{"title":"🛠️ Setting Up the Testing Environment","titles":["🧪 Testing Nuxt I18n Micro Module"]},"453":{"title":"1. Install nuxt-i18n-micro-test-utils","titles":["🧪 Testing Nuxt I18n Micro Module","🛠️ Setting Up the Testing Environment"]},"454":{"title":"2. Create a Mock Configuration File","titles":["🧪 Testing Nuxt I18n Micro Module","🛠️ Setting Up the Testing Environment"]},"455":{"title":"3. Configure Vitest","titles":["🧪 Testing Nuxt I18n Micro Module","🛠️ Setting Up the Testing Environment"]},"456":{"title":"🧪 Writing Tests","titles":["🧪 Testing Nuxt I18n Micro Module"]},"457":{"title":"Example Component","titles":["🧪 Testing Nuxt I18n Micro Module","🧪 Writing Tests"]},"458":{"title":"Test File","titles":["🧪 Testing Nuxt I18n Micro Module","🧪 Writing Tests"]},"459":{"title":"📝 Best Practices for Testing","titles":["🧪 Testing Nuxt I18n Micro Module"]},"460":{"title":"📊 i18n Utility Methods","titles":["🧪 Testing Nuxt I18n Micro Module"]},"461":{"title":"✨ Introduction","titles":[]},"462":{"title":"📝 Why Nuxt I18n Micro?","titles":[]},"463":{"title":"🏁 Performance Comparison","titles":["📝 Why Nuxt I18n Micro?"]},"464":{"title":"⏱️ Build Time and Resource Consumption","titles":["📝 Why Nuxt I18n Micro?","🏁 Performance Comparison"]},"465":{"title":"🌐 Server Performance (10k Requests)","titles":["📝 Why Nuxt I18n Micro?","🏁 Performance Comparison"]},"466":{"title":"🔑 Key Features","titles":[]},"467":{"title":"⚙️ Quick Setup","titles":[]},"468":{"title":"🗂 Folder Structure","titles":[]},"469":{"title":"News","titles":[]},"470":{"title":"Major Release: Nuxt I18n Micro v1.65.0","titles":["News"]},"471":{"title":"Optimized Translation Loading Algorithm Released","titles":["News"]},"472":{"title":"What’s New?","titles":["News","Optimized Translation Loading Algorithm Released"]},"473":{"title":"Key Benefits","titles":["News","Optimized Translation Loading Algorithm Released"]},"474":{"title":"1. Faster Build Times","titles":["News","Optimized Translation Loading Algorithm Released","Key Benefits"]},"475":{"title":"2. Reduced CPU Usage","titles":["News","Optimized Translation Loading Algorithm Released","Key Benefits"]},"476":{"title":"3. Lower Memory Usage","titles":["News","Optimized Translation Loading Algorithm Released","Key Benefits"]},"477":{"title":"4. Enhanced Response Times","titles":["News","Optimized Translation Loading Algorithm Released","Key Benefits"]},"478":{"title":"5. Increased Request Throughput","titles":["News","Optimized Translation Loading Algorithm Released","Key Benefits"]},"479":{"title":"Why It’s Important","titles":["News","Optimized Translation Loading Algorithm Released"]},"480":{"title":"How It Works","titles":["News","Optimized Translation Loading Algorithm Released"]},"481":{"title":"Key Benefits","titles":["News","Optimized Translation Loading Algorithm Released"]},"482":{"title":"How It Works","titles":["News","Optimized Translation Loading Algorithm Released"]},"483":{"title":"Usage","titles":["News","Optimized Translation Loading Algorithm Released"]},"484":{"title":"Example Transformations","titles":["News","Optimized Translation Loading Algorithm Released"]},"485":{"title":"Before","titles":["News","Optimized Translation Loading Algorithm Released","Example Transformations"]},"486":{"title":"After","titles":["News","Optimized Translation Loading Algorithm Released","Example Transformations"]}},"dirtCount":0,"index":[["→",{"2":{"475":2,"476":2,"477":2,"478":1}}],["✨",{"0":{"431":1,"461":1},"1":{"432":1}}],["known",{"0":{"444":1},"1":{"445":1,"446":1,"447":1},"2":{"444":1,"462":1}}],["kb",{"2":{"413":1,"464":1}}],["kept",{"2":{"213":1}}],["keeps",{"2":{"304":1,"392":1}}],["keep",{"0":{"305":1},"2":{"205":1,"211":1,"246":1,"260":1,"270":1,"276":1,"307":1,"367":2,"381":2,"390":2,"421":1,"444":1}}],["keeping",{"2":{"10":1,"205":1}}],["key3",{"2":{"163":2}}],["key1",{"2":{"163":2}}],["keys",{"0":{"161":1,"162":1,"164":1,"213":1,"286":1,"305":1},"1":{"162":1,"163":1,"164":1,"165":1,"287":1,"288":1},"2":{"151":1,"161":1,"162":1,"164":1,"184":1,"190":7,"191":2,"192":2,"194":1,"195":1,"196":1,"197":1,"198":1,"201":1,"203":1,"204":2,"206":3,"210":1,"211":1,"213":2,"259":1,"260":1,"289":2,"305":1,"307":1,"481":1,"482":2}}],["keypath=",{"2":{"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"103":1,"104":2,"105":1,"107":1,"108":1,"109":1,"110":1,"166":1,"168":1,"284":2,"285":2}}],["keypath",{"0":{"91":1}}],["key=",{"2":{"32":1,"44":1,"154":1,"162":1,"164":1,"170":1,"447":2}}],["key2",{"2":{"32":5,"163":2}}],["key",{"0":{"5":1,"210":1,"254":1,"259":1,"273":1,"344":1,"416":1,"425":1,"466":1,"473":1,"481":1},"1":{"274":1,"275":1,"276":1,"277":1,"278":1,"417":1,"418":1,"419":1,"420":1,"474":1,"475":1,"476":1,"477":1,"478":1},"2":{"2":1,"16":5,"17":5,"18":5,"31":2,"37":1,"91":1,"98":1,"101":2,"109":1,"112":1,"116":3,"117":3,"118":2,"162":6,"163":3,"164":4,"173":1,"192":3,"194":2,"204":1,"205":2,"206":2,"213":1,"289":1,"298":3,"306":2,"310":1,"324":5,"338":1,"344":1,"387":2,"407":1,"432":1,"460":8,"462":1,"481":1,"482":1}}],["⏱️",{"0":{"401":1,"413":1,"464":1}}],["^9",{"2":{"398":1}}],["^3",{"2":{"398":1}}],["⚠️",{"0":{"354":1,"444":1},"1":{"445":1,"446":1,"447":1}}],["❌",{"0":{"353":1}}],["⚡",{"2":{"343":1,"466":1}}],["z",{"2":{"327":2}}],["zero",{"2":{"175":1,"176":1}}],["©",{"2":{"295":1}}],["└──",{"2":{"293":3,"298":3,"313":3,"332":1,"348":3,"468":3}}],["│",{"2":{"293":14,"298":9,"313":14,"348":14,"468":14}}],["├──",{"2":{"293":9,"298":9,"313":9,"332":2,"348":9,"468":9}}],["❓",{"0":{"282":1,"283":1,"284":1,"285":1,"286":1,"289":1},"1":{"287":1,"288":1}}],["⬇️",{"0":{"257":1}}],["⬆️",{"0":{"256":1}}],["97",{"2":{"477":1}}],["91",{"2":{"474":1}}],["94",{"2":{"413":1,"464":1}}],["92",{"2":{"413":1,"464":1}}],["96",{"2":{"413":1,"464":1}}],["93",{"2":{"413":1,"464":1,"475":1,"477":1}}],["90",{"2":{"400":1,"404":1,"478":1}}],["95",{"2":{"400":1,"405":1}}],["98",{"2":{"399":1}}],["9",{"0":{"233":1},"2":{"477":1}}],["9965",{"2":{"403":1}}],["99",{"2":{"42":2}}],["624",{"2":{"476":1}}],["65",{"0":{"470":1},"2":{"470":2}}],["655",{"2":{"413":1,"464":1}}],["61",{"2":{"414":1,"465":1}}],["611",{"2":{"414":1,"465":1}}],["618",{"2":{"400":1}}],["68",{"2":{"404":1}}],["6910",{"2":{"405":1}}],["69",{"2":{"403":1,"405":1}}],["64",{"2":{"398":1}}],["6",{"0":{"230":1,"244":1,"351":1,"380":1},"2":{"407":2,"474":1}}],["60",{"2":{"22":1,"182":3,"334":1,"400":1,"407":2,"475":1}}],["x26",{"2":{"226":6}}],["x3c",{"2":{"32":22,"40":3,"42":12,"43":18,"44":20,"46":12,"49":4,"50":2,"52":2,"53":2,"54":2,"57":2,"59":4,"60":2,"63":2,"64":2,"65":2,"66":2,"67":2,"68":2,"69":2,"70":2,"71":2,"73":3,"74":3,"76":6,"77":6,"78":6,"79":6,"80":6,"81":6,"82":6,"83":6,"84":6,"85":6,"86":6,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":2,"99":1,"100":2,"101":2,"103":1,"104":7,"105":1,"107":4,"108":2,"109":2,"110":6,"148":6,"154":12,"156":5,"157":10,"159":6,"162":12,"164":10,"166":10,"168":4,"170":64,"173":16,"178":14,"180":14,"182":14,"190":16,"220":1,"240":3,"268":16,"284":9,"285":9,"324":3,"349":7,"386":3,"391":10,"447":6,"454":2,"457":10,"485":8,"486":8}}],["🧠",{"2":{"415":1}}],["🤔",{"0":{"310":1,"411":1}}],["🧼",{"2":{"246":1}}],["🧪",{"0":{"238":1,"351":1,"450":1,"456":1},"1":{"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":2,"458":2,"459":1,"460":1}}],["🤝",{"0":{"215":1},"1":{"216":1,"217":1,"218":1,"219":1,"220":1,"221":1}}],["🧾",{"0":{"203":1}}],["🧹",{"0":{"198":1,"211":1,"229":1,"237":1,"260":1,"307":1}}],["🧩",{"0":{"34":1,"329":1,"330":1}}],["✅",{"0":{"197":1,"230":1,"240":1}}],["+",{"2":{"182":1}}],["+1",{"2":{"171":1}}],["74",{"2":{"405":1,"477":1}}],["73",{"2":{"403":1,"414":1,"465":1}}],["703",{"2":{"414":1,"465":1}}],["70",{"2":{"403":1}}],["75",{"2":{"403":1}}],["796",{"2":{"403":1}}],["72",{"2":{"402":1,"403":1}}],["7",{"0":{"231":1,"245":1},"2":{"178":1,"400":1,"401":1,"402":1,"413":1,"464":1,"474":1}}],["323",{"2":{"414":1,"465":1}}],["379",{"2":{"414":1,"465":1}}],["391",{"2":{"413":1,"464":1}}],["34",{"2":{"405":2}}],["355",{"2":{"404":1}}],["387",{"2":{"403":1}}],["36",{"2":{"400":1}}],["305",{"2":{"478":1}}],["3055",{"2":{"404":1}}],["3000",{"2":{"227":1,"233":1}}],["30",{"2":{"180":1,"399":1,"477":1}}],["3",{"0":{"220":1,"227":1,"238":1,"276":1,"348":1,"377":1,"447":1,"455":1,"476":1},"2":{"117":3,"176":1,"192":1,"194":1,"205":1,"289":1,"413":1,"464":1}}],["31s",{"2":{"413":1,"464":1}}],["31",{"2":{"94":1,"95":1,"413":1,"464":1,"476":2}}],["333",{"2":{"68":1,"74":1}}],["885",{"2":{"476":1}}],["85",{"2":{"475":1}}],["8305",{"2":{"413":1,"464":1}}],["83",{"2":{"400":1}}],["8",{"0":{"232":1}}],["8px",{"2":{"66":1,"68":1,"74":2}}],["89",{"2":{"19":2,"21":2,"93":1,"178":2,"404":1,"475":1}}],["490",{"2":{"414":1,"465":1}}],["49",{"2":{"414":1,"465":1}}],["40",{"2":{"405":1}}],["473",{"2":{"413":1,"464":1}}],["47",{"2":{"405":1}}],["429",{"2":{"476":1}}],["422",{"2":{"404":1}}],["42b983",{"2":{"57":1}}],["411",{"2":{"477":1}}],["41",{"2":{"404":1}}],["48",{"2":{"403":1,"404":1}}],["441",{"2":{"405":1}}],["44",{"2":{"399":1,"403":1,"413":1,"464":1}}],["4",{"0":{"221":1,"228":1,"239":1,"277":1,"349":1,"378":1,"477":1},"1":{"240":1,"241":1,"242":1},"2":{"413":1,"417":1,"464":1,"466":1,"474":1}}],["4567",{"2":{"171":1}}],["4px",{"2":{"65":1,"74":1}}],["⚙️",{"0":{"36":1,"48":1,"62":1,"90":1,"112":1,"130":1,"194":1,"207":1,"258":1,"300":1,"312":1,"314":1,"416":1,"424":1,"467":1},"1":{"37":1,"38":1,"49":1,"50":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"113":1,"131":1,"132":1,"133":1,"134":1,"208":1,"259":1,"260":1,"261":1,"301":1,"302":1,"313":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"417":1,"418":1,"419":1,"420":1,"425":1,"426":1,"427":1},"2":{"310":1,"367":1,"459":1}}],[">powered",{"2":{"80":1}}],[">select",{"2":{"79":1}}],[">visit",{"2":{"54":1}}],[">home",{"2":{"49":1,"349":3}}],[">about",{"2":{"49":1,"50":1,"52":1,"53":1,"57":1,"159":1}}],[">",{"2":{"32":2,"40":2,"42":3,"43":4,"44":4,"46":12,"59":1,"60":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"73":1,"74":1,"77":1,"78":1,"81":1,"82":1,"83":2,"84":1,"85":2,"86":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"103":1,"104":3,"105":1,"107":2,"108":1,"109":1,"110":2,"154":1,"156":1,"157":2,"162":2,"164":1,"166":2,"168":1,"170":5,"173":4,"178":4,"180":4,"182":4,"268":4,"284":3,"285":3,"349":1,"391":1,"447":3,"457":2}}],["свидания",{"2":{"31":1,"388":1,"391":1}}],["до",{"2":{"31":1,"388":1,"391":1}}],["привет",{"2":{"31":1,"388":1,"391":1}}],["🏁",{"0":{"463":1},"1":{"464":1,"465":1},"2":{"420":1,"421":1}}],["🎉",{"0":{"382":1}}],["🏷️",{"0":{"355":1}}],["🍪",{"0":{"336":1}}],["🎮",{"0":{"233":1}}],["🏗️",{"0":{"228":1}}],["🌱",{"0":{"221":1,"267":1,"360":1},"1":{"268":1,"269":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1}}],["🍴",{"0":{"219":1}}],["🌟",{"0":{"166":1,"172":1,"273":1},"1":{"167":1,"168":1,"169":1,"173":1,"174":1,"175":1,"176":1,"274":1,"275":1,"276":1,"277":1,"278":1}}],["🎨",{"0":{"45":1,"55":1,"88":1},"1":{"56":1,"57":1}}],["🎯",{"0":{"39":1,"370":1,"427":1},"1":{"40":1}}],["🌐",{"0":{"28":1,"157":1,"177":1,"183":1,"193":1,"247":1,"308":1,"316":1,"337":1,"338":1,"362":1,"414":1,"422":1,"433":1,"465":1},"1":{"158":1,"159":1,"160":1,"178":1,"184":1,"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1,"209":1,"210":1,"211":1,"212":1,"213":1,"214":1,"248":1,"249":1,"250":1,"251":1,"252":1,"253":1,"254":1,"255":1,"256":1,"257":1,"258":1,"259":1,"260":1,"261":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"423":1,"424":1,"425":1,"426":1,"427":1,"434":1},"2":{"344":1,"425":1,"466":1}}],["🌍",{"0":{"12":1,"13":1,"14":1,"35":1,"47":1,"61":1,"89":1,"114":1,"129":1,"153":1,"192":1,"295":1,"301":1,"315":1,"322":1,"368":1,"428":1,"442":1},"1":{"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1,"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"130":1,"131":1,"132":1,"133":1,"134":1,"135":1,"136":1,"137":1,"138":1,"139":1,"140":1,"141":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"154":1,"155":1,"156":1,"193":1,"194":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"435":1},"2":{"425":1}}],["quick",{"0":{"467":1}}],["quickly",{"2":{"420":1}}],["quality",{"2":{"234":1}}],["query",{"2":{"27":1,"432":1,"435":1}}],["quot",{"2":{"4":4,"22":2,"37":4,"38":2,"54":2,"145":4,"149":4,"175":6,"176":4,"181":4,"205":16,"219":2,"234":2,"244":2,"323":8,"425":6}}],["yml",{"0":{"253":1},"2":{"253":2}}],["yandexcloud",{"2":{"193":1}}],["yandex",{"2":{"192":1,"193":3}}],["yet",{"2":{"466":1}}],["yes",{"2":{"37":1,"49":1,"50":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"285":1}}],["year",{"2":{"20":1,"180":1}}],["you",{"2":{"1":1,"5":1,"7":1,"8":1,"10":3,"16":1,"17":1,"26":1,"31":4,"50":1,"53":1,"55":1,"56":1,"59":1,"63":1,"64":1,"65":1,"68":1,"75":2,"88":1,"89":1,"101":1,"129":1,"150":1,"151":1,"161":1,"165":1,"169":1,"174":1,"176":1,"184":1,"187":1,"191":1,"192":2,"194":1,"205":3,"207":1,"214":2,"216":2,"223":2,"225":1,"227":1,"229":1,"232":1,"233":2,"236":1,"238":1,"246":2,"249":1,"251":1,"256":1,"257":1,"261":1,"263":1,"264":1,"265":1,"270":1,"274":1,"280":2,"291":1,"293":1,"296":1,"299":3,"302":1,"320":2,"326":1,"327":2,"329":1,"331":1,"335":2,"338":4,"342":1,"344":1,"349":1,"357":2,"358":1,"359":1,"360":1,"361":3,"362":2,"363":1,"367":1,"369":1,"370":1,"374":1,"378":2,"382":2,"389":1,"421":2,"427":2,"429":1,"431":1,"433":2,"437":2,"438":1,"440":2,"441":1,"442":1,"445":1,"446":1,"447":1,"448":2,"449":3,"451":2,"453":1,"459":1,"460":1,"467":1}}],["yourself",{"0":{"218":1},"2":{"218":1}}],["your",{"0":{"187":1,"220":1,"238":1,"239":1,"251":1,"351":1},"1":{"240":1,"241":1,"242":1},"2":{"1":2,"5":2,"6":1,"7":1,"10":1,"31":2,"40":1,"45":1,"46":1,"61":2,"75":1,"88":1,"91":1,"101":1,"111":1,"129":1,"134":1,"135":1,"146":1,"147":3,"150":2,"151":1,"161":1,"164":1,"171":1,"174":1,"176":1,"184":2,"186":1,"187":2,"190":3,"191":2,"192":1,"194":1,"195":1,"204":1,"205":1,"206":2,"207":1,"208":1,"211":1,"212":1,"213":1,"214":2,"216":2,"219":1,"220":4,"221":2,"223":1,"225":1,"227":1,"229":1,"232":1,"233":1,"236":1,"237":2,"238":1,"243":3,"244":3,"245":3,"246":2,"248":2,"249":2,"251":2,"253":3,"254":2,"255":1,"256":3,"257":2,"260":1,"261":4,"263":1,"265":1,"272":1,"274":1,"275":1,"278":1,"285":1,"291":1,"295":1,"296":1,"299":1,"305":2,"306":1,"307":2,"310":1,"311":1,"312":1,"314":1,"315":1,"326":1,"329":1,"330":1,"342":1,"346":1,"347":1,"348":1,"350":1,"351":1,"353":3,"354":1,"355":1,"357":3,"358":1,"359":1,"360":2,"361":1,"367":4,"369":1,"372":1,"379":1,"382":1,"393":2,"411":1,"415":3,"418":1,"421":3,"423":3,"425":1,"426":1,"427":1,"437":2,"438":1,"440":1,"441":1,"442":1,"448":3,"449":3,"451":2,"453":1,"454":1,"459":2,"460":1,"467":3,"481":1,"482":1}}],["22",{"2":{"476":1}}],["220",{"2":{"413":1,"464":1}}],["218",{"2":{"405":1}}],["291",{"2":{"404":2}}],["23",{"2":{"404":1,"475":1}}],["239",{"2":{"400":1,"401":1,"402":1}}],["234",{"2":{"19":1,"21":1,"178":1}}],["257",{"2":{"475":1}}],["25",{"2":{"399":1,"401":1,"402":1,"414":1,"465":1}}],["24",{"2":{"182":1,"399":1}}],["20",{"2":{"399":2,"401":1,"402":1,"405":1,"414":1,"465":1,"470":1,"474":1,"475":1,"476":1}}],["20px",{"2":{"71":1,"74":1}}],["2025",{"2":{"470":1,"471":1}}],["2024",{"2":{"44":1,"295":1}}],["2023",{"2":{"20":1,"94":1,"95":1,"180":1}}],["2px",{"2":{"66":1,"74":1}}],["2",{"0":{"219":1,"226":1,"237":1,"275":1,"296":1,"347":1,"374":1,"446":1,"454":1,"475":1},"1":{"375":1,"376":1},"2":{"31":1,"176":1,"180":3,"181":1,"205":1,"289":1,"398":1,"466":1}}],["2723",{"2":{"477":1}}],["27",{"2":{"26":1}}],["288",{"2":{"478":1}}],["2819",{"2":{"399":1,"401":1,"402":1}}],["28",{"2":{"13":1,"15":1,"114":1}}],["13",{"2":{"477":1}}],["19",{"2":{"476":1}}],["198",{"2":{"475":1}}],["14",{"2":{"475":1}}],["1m",{"2":{"413":1,"464":1}}],["1124",{"2":{"405":1}}],["11",{"2":{"404":1,"405":1}}],["1155",{"2":{"400":1,"401":1,"402":1}}],["1663",{"2":{"402":1}}],["16px",{"2":{"68":1,"74":1}}],["176",{"2":{"400":1}}],["174",{"2":{"400":1,"403":1}}],["17",{"2":{"399":1}}],["182",{"2":{"399":1}}],["187",{"2":{"399":1,"401":1,"402":1,"477":1}}],["18",{"2":{"398":1,"414":1,"465":1}}],["1547",{"2":{"403":1}}],["15",{"2":{"180":1,"398":1,"403":1,"476":1}}],["1286",{"2":{"476":1}}],["127",{"2":{"404":1}}],["129",{"2":{"403":1}}],["1265",{"2":{"399":1}}],["123",{"2":{"171":2}}],["1234567",{"2":{"19":1,"21":1,"93":1,"178":1}}],["12",{"2":{"94":1,"95":1,"399":1,"401":1,"402":2}}],["1px",{"2":{"66":1,"74":1}}],["1",{"0":{"218":1,"225":1,"236":1,"274":1,"295":1,"346":1,"372":1,"436":1,"438":1,"445":1,"453":1,"474":1},"1":{"373":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"20":1,"27":6,"31":1,"66":1,"74":1,"101":1,"109":1,"173":1,"175":1,"178":1,"180":1,"182":1,"190":1,"205":1,"289":1,"324":1,"325":1,"398":3,"404":1,"413":2,"417":1,"434":1,"437":1,"448":1,"464":2,"466":1}}],["10k",{"0":{"465":1}}],["10mb",{"2":{"412":1,"463":1}}],["10px",{"2":{"64":1,"74":1}}],["1000",{"2":{"22":1,"182":2,"192":1,"194":1}}],["10",{"2":{"18":2,"32":1,"92":1,"173":2,"175":2,"180":1,"400":1,"401":1,"402":2,"403":1,"414":1,"471":1}}],["599",{"2":{"414":1,"465":1}}],["5s",{"2":{"413":1,"464":1}}],["54",{"2":{"413":1,"414":1,"464":1,"465":1}}],["58",{"2":{"403":1,"404":1,"471":1}}],["52",{"2":{"402":1,"476":1}}],["57",{"2":{"402":1}}],["53",{"2":{"400":1,"401":1,"402":1}}],["55",{"2":{"400":1,"401":1,"402":1}}],["555",{"2":{"171":1}}],["50",{"0":{"436":1,"438":1},"1":{"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"325":1,"326":1,"403":1,"405":1,"437":1,"448":1,"477":1}}],["56",{"2":{"178":1}}],["567",{"2":{"19":1,"21":1,"178":2}}],["5px",{"2":{"67":2,"74":2}}],["5",{"0":{"229":1,"243":1,"278":1,"350":1,"379":1,"478":1},"2":{"16":2,"17":2,"22":3,"32":1,"168":1,"181":1,"182":2,"192":1,"194":1,"417":1,"466":1,"475":1,"478":1}}],["||",{"2":{"457":1}}],["|",{"2":{"13":1,"15":4,"16":8,"17":2,"18":2,"19":1,"20":5,"21":3,"22":5,"26":4,"27":3,"28":1,"29":1,"31":3,"44":1,"49":1,"92":1,"93":1,"94":2,"95":2,"97":2,"101":2,"114":1,"116":9,"174":2,"176":5,"268":1,"324":7,"327":1,"337":1,"338":1,"386":1,"434":1}}],["06",{"2":{"475":1}}],["03",{"2":{"474":1}}],["0h",{"2":{"464":2}}],["0+",{"0":{"436":1},"1":{"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1}}],["05",{"2":{"414":1,"465":1}}],["0m",{"2":{"413":1,"464":1}}],["09",{"2":{"404":1}}],["000",{"2":{"414":1}}],["00",{"2":{"399":1,"401":1,"402":1,"403":5,"404":6,"405":6,"414":1,"465":1,"476":1,"477":2,"478":2}}],["007bff",{"2":{"65":1,"66":1,"71":1,"74":3}}],["01",{"2":{"44":2,"470":1,"471":1,"475":1}}],["0",{"0":{"438":1,"470":1},"2":{"13":1,"15":1,"26":1,"66":5,"67":1,"74":6,"114":1,"173":1,"175":1,"178":1,"190":1,"325":1,"326":1,"334":1,"398":2,"403":2,"404":2,"405":4,"437":1,"448":1,"470":2,"471":1}}],["$defaultlocale",{"2":{"454":1}}],["$definei18nroute",{"0":{"31":1,"265":1,"385":1},"1":{"386":1,"387":1,"388":1},"2":{"27":3,"31":4,"265":1,"268":3,"384":1,"385":1,"389":4,"391":4,"392":1,"393":1}}],["$2",{"2":{"205":1}}],["$loadpagetranslations",{"0":{"122":1},"2":{"122":2,"128":2}}],["$localepath",{"0":{"29":1},"2":{"289":1,"454":1}}],["$localeroute",{"0":{"28":1,"121":1},"2":{"28":1,"29":1,"32":2,"33":1,"34":1,"121":2,"127":2,"268":3,"349":1,"454":1}}],["$has",{"0":{"118":1},"2":{"118":2,"162":3,"454":1}}],["$mergetranslations",{"0":{"30":1,"119":1},"2":{"119":2,"454":1}}],["$fetch",{"0":{"287":1},"2":{"27":1,"283":1,"287":1,"288":1}}],["$settroutename",{"2":{"454":1}}],["$setdefaultlocale",{"2":{"454":1}}],["$setlocales",{"2":{"454":1}}],["$setlocalename",{"2":{"454":1}}],["$setlocale",{"2":{"454":1}}],["$seti18nrouteparams",{"0":{"27":1},"2":{"27":3,"454":1}}],["$switchroute",{"0":{"26":1},"2":{"454":1}}],["$switchlocale",{"0":{"25":1,"120":1},"2":{"32":2,"33":1,"34":1,"120":2,"126":2,"154":2,"157":1,"170":2,"268":1,"447":2,"454":1}}],["$switchlocalepath",{"0":{"24":1},"2":{"24":1,"27":2,"454":1}}],["$switchlocaleroute",{"0":{"23":1},"2":{"23":1,"27":2,"454":1}}],["$1",{"2":{"19":1,"21":1,"178":1,"205":3}}],["$tdr",{"0":{"22":1,"181":1,"182":1},"1":{"182":1},"2":{"22":1,"181":1,"182":3}}],["$td",{"0":{"20":1,"179":1,"180":1},"1":{"180":1},"2":{"20":1,"179":1,"180":3,"454":1}}],["$tn",{"0":{"19":1,"21":1,"177":1,"178":1},"1":{"178":1},"2":{"19":1,"21":1,"177":1,"178":3,"454":1}}],["$tc",{"0":{"18":1,"117":1,"172":1,"173":1},"1":{"173":1,"174":1,"175":1,"176":1},"2":{"18":1,"32":2,"117":2,"172":1,"173":5,"175":3,"176":2,"454":1}}],["$ts",{"0":{"17":1},"2":{"17":1,"454":1}}],["$t",{"0":{"16":1,"116":1,"289":1},"2":{"16":1,"17":1,"32":3,"33":1,"34":1,"116":2,"125":2,"154":2,"157":3,"162":4,"164":2,"170":18,"190":2,"268":2,"289":4,"391":1,"454":1,"457":4,"486":2}}],["$getroutename",{"0":{"15":1},"2":{"15":1,"454":1}}],["$getlocales",{"0":{"14":1,"115":1},"2":{"14":1,"32":2,"33":1,"34":1,"115":2,"154":2,"157":1,"170":2,"268":1,"454":1}}],["$getlocalename",{"0":{"13":1,"114":1},"1":{"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1},"2":{"13":1,"114":1,"454":1}}],["$getlocale",{"0":{"12":1,"113":1},"2":{"12":1,"32":3,"33":1,"34":1,"113":2,"124":2,"154":3,"157":1,"170":2,"268":1,"289":1,"454":1}}],["$",{"2":{"8":2,"27":1,"42":1,"44":2,"83":1,"85":1,"101":1,"111":1}}],["`alternate`",{"2":{"359":1}}],["`$",{"2":{"101":1,"109":1}}],["`icon",{"2":{"85":1}}],["`flag",{"2":{"83":1}}],["`sections",{"2":{"44":2}}],["`news",{"2":{"27":1}}],["`error",{"2":{"8":1}}],["`",{"2":{"8":2,"27":1,"83":1,"85":1,"101":1}}],["===",{"2":{"27":2,"32":1,"101":1,"109":1,"154":1,"170":1}}],["=",{"2":{"8":3,"12":2,"13":2,"14":2,"15":2,"16":2,"17":2,"18":2,"19":2,"20":2,"21":2,"22":2,"23":2,"24":3,"25":1,"26":1,"27":6,"28":2,"29":2,"30":1,"31":3,"32":1,"33":1,"34":2,"44":3,"101":2,"113":3,"114":2,"115":3,"116":3,"117":3,"118":3,"119":2,"120":2,"121":3,"122":2,"124":2,"125":2,"126":1,"127":2,"128":1,"131":1,"132":1,"133":1,"134":1,"136":1,"137":1,"138":1,"140":1,"141":1,"142":1,"143":1,"148":1,"154":1,"157":1,"162":1,"164":1,"170":1,"173":1,"178":1,"180":1,"182":1,"268":1,"289":1,"324":4,"389":2,"391":1,"432":1,"434":3,"454":1,"457":3,"458":4}}],["=>",{"2":{"3":2,"8":4,"27":1,"32":1,"101":1,"109":1,"154":1,"170":1,"289":1,"324":2,"432":1,"434":1,"447":2,"454":3,"458":5}}],["just",{"2":{"466":1}}],["join",{"2":{"458":1}}],["john",{"2":{"44":1,"116":2}}],["jp",{"2":{"315":1}}],["ja",{"2":{"315":4}}],["javascriptshowerror",{"2":{"289":1}}],["javascriptconst",{"2":{"289":1}}],["javascriptawait",{"2":{"289":1}}],["javascriptaddplugin",{"2":{"7":1}}],["javascriptdefinepagemeta",{"2":{"282":1}}],["javascript",{"2":{"190":2,"481":1}}],["jane",{"2":{"125":1}}],["jsexport",{"2":{"208":1}}],["js",{"0":{"208":1},"2":{"151":1,"184":1,"187":2,"190":1,"191":1,"207":2,"214":1,"223":1,"288":1,"347":1}}],["jsconst",{"2":{"113":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"124":1,"125":1,"126":1,"127":1,"128":1,"131":1,"132":1,"133":1,"134":1,"136":1,"137":1,"138":1,"140":1,"141":1,"142":1,"143":1}}],["json`",{"2":{"8":1}}],["json",{"0":{"155":1,"158":1,"160":1,"163":1,"165":1,"167":1,"169":1,"171":1,"174":1},"2":{"8":1,"9":2,"42":1,"43":1,"92":1,"93":1,"94":1,"95":1,"155":1,"158":1,"160":1,"163":1,"165":1,"167":1,"169":1,"171":1,"174":2,"176":1,"188":1,"190":3,"199":1,"201":1,"202":1,"253":4,"275":1,"276":1,"285":1,"293":9,"295":4,"296":6,"298":9,"301":2,"313":9,"332":3,"344":1,"348":10,"353":1,"419":1,"458":2,"460":1,"466":1,"468":9,"483":1}}],["write",{"2":{"458":1,"459":1}}],["writing",{"0":{"456":1},"1":{"457":1,"458":1},"2":{"236":1,"451":1}}],["wrap",{"2":{"96":1}}],["wraps",{"2":{"45":1}}],["wrapper",{"2":{"38":1,"47":1,"64":1,"88":1,"458":6}}],["w+",{"2":{"205":1}}],["won",{"2":{"440":1}}],["would",{"2":{"190":1,"298":3}}],["workaround",{"2":{"445":1}}],["workloads",{"2":{"415":1}}],["work",{"0":{"266":1,"289":1},"2":{"218":1,"221":1,"227":1,"238":1,"283":1,"289":1,"451":1,"460":1}}],["workflows",{"2":{"279":1,"479":1}}],["workflow",{"0":{"212":1},"2":{"212":1,"272":1,"275":1}}],["workspaces",{"2":{"230":1,"234":1,"238":1}}],["works",{"0":{"480":1,"482":1},"2":{"190":1,"204":1,"205":1,"278":1,"315":1,"351":1,"457":1}}],["working",{"2":{"6":1,"188":1,"201":1,"246":1,"274":1}}],["worldwide",{"2":{"423":1}}],["world",{"2":{"119":1,"397":1,"407":1}}],["warm",{"2":{"407":1}}],["watch",{"2":{"455":1}}],["watcher",{"2":{"334":2}}],["watson",{"2":{"193":1}}],["was",{"2":{"289":1,"411":1,"461":1,"462":1}}],["walkthrough",{"2":{"248":1}}],["walk",{"2":{"184":1,"291":1}}],["want",{"2":{"26":1,"31":3,"161":1,"233":1,"335":1,"338":1,"360":1,"361":1,"440":1,"441":1,"442":1,"443":1,"449":1}}],["way",{"2":{"6":1,"31":1,"35":1,"111":1,"177":1,"393":1,"437":1,"480":1}}],["were",{"2":{"205":2,"350":1,"463":1}}],["website",{"2":{"296":1,"363":1}}],["web",{"2":{"171":1}}],["we",{"2":{"164":2,"171":1,"173":1,"216":1,"239":1,"246":1,"296":1,"412":1,"414":1,"463":1,"470":1,"471":1}}],["well",{"2":{"147":1,"457":1}}],["welcome",{"2":{"16":2,"17":2,"30":1,"32":1,"107":1,"125":2,"165":1,"167":1,"168":1,"169":1,"171":1,"190":1,"216":1,"296":1,"434":2,"457":1,"458":2,"486":1}}],["welcomemessage",{"2":{"16":1,"17":1,"110":1,"125":1}}],["weight",{"2":{"56":1}}],["weekday",{"2":{"20":2,"180":1}}],["wisely",{"0":{"304":1}}],["wish",{"2":{"31":1}}],["wide",{"2":{"171":1,"296":1}}],["wiedersehen",{"2":{"31":1,"388":1,"389":1,"391":1}}],["window",{"2":{"24":1}}],["will",{"2":{"7":2,"31":1,"37":1,"53":1,"54":1,"57":1,"63":1,"100":1,"184":1,"186":1,"192":2,"201":1,"205":2,"227":1,"230":1,"232":1,"245":2,"251":1,"254":1,"255":2,"291":1,"299":1,"301":2,"315":5,"326":8,"332":2,"335":2,"338":2,"339":2,"367":1,"372":1,"379":1,"408":1,"429":1,"440":1,"441":4,"442":3,"443":1,"451":1,"454":1,"459":1}}],["within",{"2":{"37":1,"75":1,"77":1,"78":1,"81":1,"82":1,"87":4,"103":1,"111":1,"148":1,"161":1,"164":1,"170":1,"203":1,"204":4,"249":1,"254":1,"277":1,"282":1,"285":2,"289":1,"292":1,"298":1,"306":1,"315":1,"384":1,"390":1,"391":1,"393":1}}],["with",{"0":{"6":1,"43":1,"44":1,"53":1,"110":1,"125":1,"159":1,"166":1,"168":1,"170":1,"176":1,"218":1,"262":1,"308":1,"332":1,"349":1,"368":1,"391":1,"403":1,"404":1,"445":1,"446":1,"447":1},"1":{"7":1,"8":1,"9":1,"10":1,"167":1,"168":1,"169":1,"171":1,"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1},"2":{"6":1,"9":1,"10":1,"18":1,"20":1,"23":2,"24":2,"26":5,"28":1,"29":1,"30":1,"31":1,"45":1,"46":1,"53":1,"54":1,"61":1,"73":1,"74":1,"88":1,"89":1,"111":1,"116":1,"117":1,"125":2,"135":1,"140":1,"147":1,"148":1,"152":1,"156":1,"162":1,"166":1,"175":1,"178":1,"180":2,"187":1,"190":4,"201":1,"204":1,"205":7,"218":1,"220":1,"241":2,"248":1,"249":1,"266":2,"268":1,"269":1,"270":1,"274":1,"278":1,"280":2,"283":1,"285":1,"298":1,"304":1,"310":1,"315":4,"319":1,"320":1,"323":1,"338":1,"342":1,"343":1,"344":1,"347":1,"349":2,"363":1,"377":1,"391":1,"407":1,"408":1,"410":1,"411":1,"412":1,"419":1,"437":1,"441":2,"442":1,"443":2,"445":1,"446":3,"449":4,"460":2,"461":1,"462":3,"463":1,"466":1,"467":1}}],["without",{"2":{"5":1,"10":1,"15":1,"50":1,"111":1,"142":1,"190":2,"266":1,"275":1,"278":1,"285":1,"302":1,"325":1,"326":1,"339":1,"423":1,"440":1,"441":3}}],["why",{"0":{"279":1,"283":1,"286":1,"289":1,"310":1,"343":1,"408":1,"411":1,"462":1,"479":1},"1":{"287":1,"288":1,"463":1,"464":1,"465":1}}],["while",{"2":{"205":1,"278":1,"284":2,"285":1,"326":1,"338":1,"370":1,"441":1,"443":1,"444":1,"449":1,"481":1}}],["which",{"2":{"2":1,"7":1,"10":1,"15":1,"20":1,"21":1,"22":1,"26":1,"31":4,"63":1,"104":1,"107":1,"135":1,"205":1,"285":1,"296":1,"304":1,"315":1,"323":1,"344":2,"387":1,"389":1,"396":1,"415":1,"425":2,"466":1,"480":1}}],["who",{"2":{"201":1,"272":1}}],["what",{"0":{"272":1,"282":1,"284":1,"472":1},"2":{"190":1,"205":1}}],["whether",{"2":{"216":1,"274":1,"280":1,"448":1}}],["where",{"2":{"7":1,"31":2,"201":1,"204":1,"205":1,"208":1,"253":1,"254":1,"255":2,"264":1,"270":1,"283":1,"299":1,"317":1,"323":1,"358":1,"359":1,"360":1,"370":1,"387":3,"397":1,"429":1,"442":1}}],["when",{"2":{"2":1,"6":1,"9":1,"15":1,"50":1,"53":1,"57":1,"71":1,"132":1,"145":1,"175":3,"190":1,"194":1,"205":2,"213":1,"239":1,"254":1,"263":1,"282":1,"292":1,"296":1,"298":1,"301":1,"305":1,"315":1,"332":1,"335":1,"337":1,"340":1,"367":1,"390":1,"425":1,"440":1,"441":1,"443":2,"444":1,"445":1,"446":1,"447":2,"449":2}}],["ll",{"2":{"151":1,"214":1,"249":1,"261":1,"378":1}}],["less",{"2":{"413":1,"414":1,"464":1,"465":1}}],["length",{"2":{"324":2}}],["left",{"2":{"315":2}}],["leaks",{"2":{"415":1,"462":2}}],["leaving",{"2":{"338":1}}],["lean",{"2":{"304":1,"307":1}}],["leading",{"2":{"415":1,"417":1,"427":1,"445":1,"462":1}}],["lead",{"2":{"283":1,"315":1,"411":1,"447":1,"479":1}}],["learn",{"2":{"60":1,"296":1,"470":1}}],["leveraged",{"2":{"472":1}}],["leverages",{"2":{"370":1}}],["leverage",{"2":{"304":1,"421":1}}],["leveraging",{"2":{"192":1,"362":1,"369":1,"382":1}}],["levels",{"2":{"438":1}}],["level",{"2":{"188":1,"298":1,"392":1,"393":1,"429":1}}],["letters",{"2":{"253":2,"255":1}}],["let",{"2":{"27":1,"458":1}}],["layering",{"2":{"370":1}}],["layered",{"0":{"363":1},"1":{"364":1,"365":1,"366":1}}],["layer",{"0":{"358":1,"359":1,"361":2,"364":1,"365":1,"366":1,"372":1,"373":1},"1":{"359":1,"373":1},"2":{"358":2,"359":1,"361":7,"367":3,"372":1,"374":1,"375":1,"376":1,"377":2}}],["layers",{"0":{"356":1,"357":1,"360":1,"362":1,"367":1,"368":1,"374":1},"1":{"357":1,"358":1,"359":1,"360":1,"361":2,"362":2,"363":2,"364":2,"365":2,"366":2,"367":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":2,"376":2,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1},"2":{"315":1,"357":2,"360":2,"362":1,"367":3,"369":1,"370":1,"380":1,"381":1,"382":1}}],["layout",{"2":{"61":1}}],["larger",{"2":{"362":1,"415":1}}],["large",{"2":{"304":1,"309":1,"310":1,"342":1,"343":1,"397":1,"407":1,"408":2,"411":2,"461":1,"462":4,"466":1}}],["landing",{"2":{"269":2}}],["lang=",{"2":{"391":1,"457":1}}],["languages",{"2":{"31":1,"133":1,"248":1,"389":1,"441":1,"442":3,"443":2,"447":1,"448":1,"449":1}}],["language",{"2":{"8":1,"31":3,"76":1,"79":1,"87":1,"138":1,"145":1,"149":2,"204":1,"255":1,"274":1,"285":1,"315":1,"322":2,"326":6,"358":1,"359":1,"361":1,"366":1,"375":1,"376":1,"389":2,"392":2,"393":1,"425":3,"427":2,"435":1,"437":1,"440":6,"441":5,"442":1,"443":8,"449":3}}],["lang",{"2":{"8":3,"129":1,"136":2,"146":1,"149":1,"150":1,"315":1,"425":1}}],["latest",{"2":{"257":1}}],["later",{"2":{"223":3}}],["lazy",{"2":{"122":1,"128":1}}],["labels=",{"2":{"156":1}}],["labels",{"0":{"74":1},"2":{"63":1,"74":1,"156":1,"306":1}}],["label=",{"2":{"60":1}}],["label",{"2":{"60":1,"77":1,"78":1,"85":1,"86":1,"87":4}}],["ltr",{"2":{"14":2,"131":1,"136":1,"152":3,"312":2,"315":6,"337":3,"347":2,"359":2,"361":5,"364":2,"365":3,"366":3,"373":3,"375":4,"376":4,"425":1,"426":2,"467":2}}],["lt",{"0":{"35":1,"47":1,"61":1,"89":1,"156":1,"157":1,"166":1,"167":1,"349":2},"1":{"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1,"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":1,"158":1,"159":1,"160":1,"167":1,"168":1,"169":1},"2":{"14":1,"16":2,"17":2,"18":1,"27":6,"30":2,"31":6,"35":1,"47":2,"50":1,"61":1,"63":1,"64":1,"66":1,"67":1,"68":1,"75":1,"88":1,"89":1,"97":1,"101":1,"103":1,"104":2,"116":2,"122":1,"135":1,"136":2,"137":2,"138":2,"149":5,"151":3,"156":1,"157":1,"166":1,"220":1,"284":2,"285":1,"324":1,"328":1,"338":3,"349":2,"425":3,"447":1,"449":1}}],["limit",{"2":{"421":1}}],["limiting",{"2":{"331":1}}],["limitations",{"0":{"287":1}}],["lightweight",{"2":{"309":1,"461":1}}],["live",{"2":{"277":1}}],["lilt",{"2":{"193":2}}],["libretranslate",{"2":{"193":2}}],["li>",{"2":{"79":1,"80":1,"81":1,"82":1,"170":14}}],["li",{"2":{"67":1,"79":1,"80":1,"81":1,"82":1}}],["linguistic",{"2":{"263":1}}],["lingvatranslate",{"2":{"193":1}}],["lingva",{"2":{"193":1}}],["lint",{"2":{"229":2,"234":2,"237":1}}],["linter",{"2":{"229":1,"234":2,"237":1}}],["linting",{"0":{"229":1,"237":1},"2":{"237":1}}],["link>",{"2":{"49":2,"50":1,"52":1,"53":1,"54":1,"57":1,"59":1,"60":1,"104":2,"157":2,"159":1,"284":2,"285":2,"349":2}}],["links",{"0":{"54":1,"158":1},"2":{"47":1,"54":1,"88":2,"145":1,"149":2,"150":1,"268":1,"285":1,"315":3,"318":1,"328":1,"425":1,"446":1}}],["link",{"0":{"47":1,"53":1,"85":1,"86":1,"138":1,"145":1,"157":1,"159":1,"160":1,"349":1},"1":{"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"158":1,"159":1,"160":1},"2":{"47":3,"49":3,"50":3,"52":2,"53":3,"54":2,"57":2,"59":2,"60":1,"70":1,"85":2,"86":2,"87":4,"104":4,"129":1,"132":1,"133":1,"135":1,"138":3,"142":1,"149":2,"151":1,"157":3,"159":1,"244":1,"284":3,"285":5,"349":3,"425":3}}],["line",{"2":{"8":1,"184":1}}],["list",{"2":{"31":1,"66":1,"81":1,"82":1,"87":2,"88":2,"460":2}}],["likely",{"2":{"408":1}}],["like",{"2":{"20":1,"192":1,"255":1,"279":1,"283":1,"284":1,"287":1,"295":1,"298":3,"321":1,"326":1,"339":1,"359":1,"363":1,"410":1,"440":1,"445":1,"461":1,"482":1}}],["lifecycle",{"2":{"4":1}}],["loop",{"2":{"447":1}}],["look",{"2":{"218":1,"299":1,"410":1}}],["lower",{"0":{"476":1},"2":{"343":1,"396":1,"408":1,"413":1,"415":1,"464":1,"475":3,"476":2,"479":1}}],["lowers",{"2":{"340":1,"415":1}}],["lot",{"2":{"327":1}}],["lokaleseite",{"2":{"265":1}}],["long",{"2":{"20":3,"180":2}}],["logs",{"2":{"205":2}}],["logging",{"2":{"205":1,"319":2}}],["logged",{"2":{"9":1,"205":1}}],["loglevel",{"2":{"188":1}}],["log",{"2":{"113":1,"115":1,"116":1,"117":1,"118":1,"136":1,"137":1,"138":1,"188":1}}],["logical",{"2":{"46":1}}],["logic",{"0":{"407":1},"2":{"10":1,"101":1,"270":1,"381":1,"417":1,"470":1}}],["loads",{"2":{"122":1,"301":1,"421":1,"460":1}}],["loaded",{"0":{"300":1},"1":{"301":1,"302":1},"2":{"9":1,"292":1,"296":1,"301":1,"302":1,"380":1,"419":1,"480":1}}],["loadtranslations",{"2":{"8":2,"9":1}}],["load",{"0":{"282":1,"414":1},"2":{"8":1,"128":1,"276":1,"282":1,"296":1,"301":4,"304":1,"309":1,"310":1,"335":1,"343":1,"369":1,"378":1,"382":1,"407":3,"408":1,"415":2,"420":1,"421":1,"461":1,"462":1,"466":1}}],["loading",{"0":{"128":1,"353":1,"419":1,"471":1},"1":{"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1},"2":{"7":1,"8":1,"9":2,"10":1,"122":1,"351":1,"421":1,"466":1,"471":1,"472":1,"479":1,"480":1}}],["locations",{"2":{"204":1}}],["location",{"2":{"24":1,"255":1,"353":1,"395":1}}],["located",{"2":{"7":1,"332":2}}],["locally",{"2":{"232":2,"234":1}}],["localhost",{"2":{"227":1,"233":1}}],["local",{"0":{"222":1},"1":{"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1},"2":{"220":1,"225":1,"283":1,"434":1}}],["localize",{"2":{"269":1,"338":1}}],["localizes",{"2":{"47":1}}],["localizedroute",{"2":{"28":1,"29":1}}],["localized",{"0":{"127":1,"147":1,"157":1,"262":1},"1":{"158":1,"159":1,"160":1,"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1},"2":{"23":1,"25":1,"26":2,"27":1,"28":1,"52":1,"93":1,"94":1,"95":1,"116":1,"121":1,"127":1,"129":2,"150":1,"264":1,"269":1,"338":3,"339":2,"384":1,"390":1,"392":1,"393":1}}],["localization",{"0":{"280":1},"2":{"1":1,"5":3,"6":1,"10":4,"31":1,"89":1,"91":1,"111":1,"184":1,"248":1,"272":1,"274":1,"278":1,"279":2,"283":3,"285":1,"338":4,"339":1,"357":1,"358":1,"360":1,"369":1,"382":1,"393":1,"429":1,"437":1,"449":1,"451":1,"460":1,"479":1}}],["localepath",{"2":{"454":1}}],["localeroute",{"0":{"446":1},"2":{"446":2,"449":1,"454":1}}],["localeroutes",{"0":{"262":1,"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1},"1":{"263":1,"264":1,"265":2,"266":2,"267":1,"268":2,"269":2,"270":1},"2":{"27":1,"31":4,"263":1,"264":1,"265":2,"266":2,"268":2,"270":2,"386":1,"387":1,"388":1,"389":1,"391":1,"392":1}}],["locale=de",{"2":{"440":2}}],["locale=fr",{"2":{"435":1}}],["localefromquery",{"2":{"434":3}}],["localecookie",{"0":{"336":1}}],["localecode",{"2":{"27":3}}],["locale>",{"2":{"77":1,"78":1}}],["localesubpage",{"2":{"31":1,"265":1,"268":1,"388":1}}],["localeslugs",{"2":{"27":3}}],["locales",{"0":{"126":1,"154":1,"283":1,"315":1,"368":1,"371":1,"378":1},"1":{"369":1,"370":1,"371":1,"372":2,"373":2,"374":2,"375":2,"376":2,"377":2,"378":2,"379":2,"380":2,"381":1,"382":1},"2":{"7":2,"8":1,"9":1,"14":2,"31":19,"61":1,"66":1,"68":1,"115":3,"137":1,"151":1,"152":2,"154":1,"184":1,"188":1,"190":2,"196":2,"203":2,"205":3,"208":4,"214":1,"253":1,"254":1,"263":2,"264":1,"265":1,"266":2,"268":1,"270":2,"274":1,"280":1,"288":2,"293":1,"295":3,"296":4,"298":3,"299":1,"301":2,"302":1,"306":1,"312":2,"313":1,"314":1,"315":4,"317":1,"318":1,"327":2,"332":3,"335":5,"337":1,"344":1,"347":3,"348":2,"351":1,"354":1,"358":1,"359":2,"360":1,"361":4,"363":1,"364":2,"365":1,"366":1,"369":1,"370":1,"373":2,"374":1,"375":1,"376":1,"382":1,"385":3,"386":1,"387":4,"388":1,"389":9,"390":3,"391":2,"392":3,"418":1,"420":1,"421":1,"425":1,"426":2,"441":1,"458":1,"460":2,"466":1,"467":2,"468":1,"483":1}}],["locale",{"0":{"77":1,"78":1,"124":1,"146":1,"153":1,"155":1,"274":1,"286":1,"301":1,"433":1,"434":1,"435":1,"436":1,"437":1,"447":1},"1":{"154":1,"155":1,"156":1,"287":1,"288":1,"434":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"2":5,"3":3,"4":1,"8":5,"9":4,"12":3,"13":2,"15":4,"19":3,"20":3,"21":2,"22":2,"23":6,"24":5,"25":4,"26":11,"27":1,"28":5,"29":4,"30":1,"31":9,"32":6,"47":1,"52":1,"63":2,"64":1,"67":1,"69":1,"70":1,"73":1,"74":1,"77":1,"78":1,"81":1,"82":1,"83":6,"84":6,"85":6,"86":6,"87":14,"88":1,"101":2,"109":1,"111":1,"113":3,"114":2,"115":1,"118":1,"119":1,"120":3,"121":2,"122":2,"124":2,"126":1,"127":1,"128":1,"131":1,"133":1,"137":2,"140":1,"145":3,"146":1,"147":1,"149":2,"150":1,"154":6,"156":1,"157":1,"170":5,"172":1,"177":1,"178":2,"179":2,"180":2,"181":1,"182":2,"191":1,"197":1,"203":2,"204":4,"205":1,"221":1,"241":2,"264":1,"265":2,"266":1,"268":2,"269":2,"295":1,"296":1,"301":3,"315":15,"316":2,"322":1,"323":5,"324":3,"325":2,"326":8,"327":1,"328":1,"333":2,"336":2,"337":3,"338":2,"339":2,"344":1,"348":1,"354":1,"355":1,"359":1,"360":1,"361":2,"366":2,"369":1,"372":1,"375":2,"376":2,"378":3,"379":1,"380":2,"382":1,"385":1,"387":4,"388":1,"389":1,"390":1,"391":3,"392":1,"418":1,"421":1,"425":3,"429":2,"430":1,"432":2,"433":1,"434":2,"435":3,"437":2,"438":2,"440":8,"441":6,"442":5,"443":4,"445":2,"446":1,"447":16,"448":2,"449":4,"460":10,"466":1,"470":1}}],["hydration",{"0":{"445":1},"2":{"445":3,"447":3,"449":2}}],["h3",{"2":{"432":1,"434":1}}],["h3>",{"2":{"170":4}}],["hub",{"2":{"274":1}}],["h4>",{"2":{"170":2}}],["h1",{"2":{"166":1}}],["h1>welcome",{"2":{"190":1,"485":1}}],["h1>",{"2":{"42":2,"44":2,"170":2,"190":3,"391":2,"485":1,"486":2}}],["high",{"2":{"309":1,"310":1,"342":1,"407":1,"408":1,"411":1,"462":2,"466":1,"479":1}}],["highlight",{"2":{"69":1}}],["highlighting",{"2":{"50":1}}],["highly",{"2":{"61":1,"393":1,"461":1}}],["hierarchy",{"2":{"253":1,"254":1}}],["history",{"2":{"205":1}}],["hi",{"2":{"205":6}}],["hideifempty=",{"2":{"100":1,"108":1}}],["hideifempty",{"0":{"100":1},"2":{"108":1}}],["http",{"2":{"227":1,"233":1,"315":1,"435":1}}],["https",{"2":{"54":2,"134":1,"138":1,"143":1,"220":1,"225":1,"253":1,"288":2,"289":1,"315":7,"321":1}}],["htmlattrs",{"0":{"136":1},"2":{"135":1,"136":2,"149":1}}],["html",{"0":{"99":1},"2":{"89":1,"96":1,"99":2,"129":2,"131":1,"136":1,"146":1,"149":3,"166":1,"315":1,"425":1}}],["h2>",{"2":{"43":2,"44":2,"170":2}}],["href=",{"2":{"170":4}}],["hreflang=",{"2":{"425":1}}],["hreflang",{"2":{"133":1,"150":1,"344":1,"425":1}}],["href",{"2":{"24":1,"138":1,"150":1}}],["hardware",{"2":{"412":1,"463":1}}],["hardcoded",{"2":{"190":1}}],["happens",{"2":{"323":1,"445":1}}],["has",{"2":{"187":1,"254":1,"310":1,"355":1,"366":1,"441":1,"443":3,"454":1,"460":1,"476":1,"480":1}}],["handling",{"0":{"54":1,"147":1,"297":1,"424":1,"436":1},"1":{"298":1,"425":1,"426":1,"427":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"274":1,"285":1,"289":1,"324":1,"325":1,"343":1,"384":1,"408":1,"429":1,"441":1,"442":1,"443":1,"470":1,"474":1,"479":1,"480":1}}],["handlers",{"0":{"431":1},"1":{"432":1}}],["handled",{"2":{"315":1,"326":1,"396":1,"437":1,"448":1,"478":1}}],["handles",{"2":{"157":1,"172":1,"173":1,"190":1,"291":1,"407":1,"423":1,"427":1}}],["handle",{"0":{"350":1},"2":{"6":1,"7":1,"109":1,"111":1,"151":1,"164":1,"174":1,"176":1,"391":1,"396":1,"407":1,"415":1,"430":1,"449":1,"472":1,"480":1}}],["hallo",{"2":{"31":1,"388":1,"389":1,"391":1}}],["have",{"2":{"16":1,"17":1,"53":1,"92":2,"169":1,"196":1,"207":1,"214":1,"223":1,"264":1,"266":1,"315":2,"326":3,"327":1,"337":1,"339":1,"360":1,"361":1,"362":1,"363":1,"440":1,"441":2,"442":1,"443":1,"479":1}}],["heavy",{"2":{"462":1}}],["head",{"2":{"131":1,"132":2,"133":1,"134":1,"135":1,"140":2,"141":1,"142":2,"143":1,"148":2,"149":1,"411":1}}],["headers",{"2":{"295":1,"432":1}}],["header",{"2":{"79":1,"149":1,"170":4,"171":4,"435":1}}],["helpful",{"2":{"285":1}}],["help",{"2":{"216":1,"289":1,"315":1,"319":1,"342":1,"367":1,"459":1}}],["helping",{"2":{"204":1}}],["helps",{"2":{"129":1,"190":1,"191":1,"204":1,"270":1,"279":1,"305":1,"393":1,"425":1}}],["hello123",{"2":{"205":1}}],["hello",{"2":{"3":1,"31":2,"116":3,"118":1,"119":2,"169":1,"205":7,"388":1,"389":1,"391":1}}],["here",{"2":{"8":1,"32":1,"40":1,"43":1,"88":1,"149":1,"152":1,"170":1,"174":1,"265":1,"268":1,"293":1,"310":1,"314":1,"347":1,"359":1,"361":1,"390":1,"421":1,"457":1}}],["hosted",{"2":{"288":1}}],["hour",{"2":{"180":1}}],["home",{"2":{"122":1,"157":1,"158":2,"170":1,"171":2,"190":2,"295":2,"323":1,"486":2}}],["hooks",{"2":{"9":1,"289":1}}],["hooked",{"2":{"4":1}}],["hook",{"2":{"3":1,"8":2,"9":1,"289":1}}],["however",{"2":{"283":1,"284":1,"315":1,"323":1,"326":1,"397":1}}],["how",{"0":{"266":1,"286":1,"300":1,"480":1,"482":1},"1":{"287":1,"288":1,"301":1,"302":1},"2":{"3":1,"32":1,"110":1,"148":1,"150":1,"151":2,"154":1,"161":1,"174":1,"190":1,"191":1,"204":1,"205":2,"253":1,"265":1,"291":1,"326":1,"359":1,"361":1,"391":1,"396":2,"407":2,"408":1,"410":1,"423":1,"437":3,"438":2,"448":1}}],["v20",{"2":{"398":1}}],["v9",{"0":{"405":1},"2":{"223":1,"401":1,"402":1,"407":1}}],["v7",{"2":{"223":1}}],["vercel",{"0":{"286":1},"1":{"287":1,"288":1},"2":{"287":1}}],["verify",{"0":{"380":1},"2":{"190":1,"355":1}}],["verbose",{"2":{"188":1,"190":2}}],["versatile",{"2":{"47":1,"385":1}}],["versions",{"0":{"398":1},"2":{"27":1,"138":1,"145":1,"149":2,"264":1,"425":1,"427":1}}],["version",{"0":{"436":1,"438":1},"1":{"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"13":1,"15":1,"25":1,"26":1,"114":1,"190":2,"213":1,"325":1,"326":3,"334":1,"398":1,"425":1,"427":1,"437":1,"443":4,"448":1,"470":1,"471":1}}],["vi",{"2":{"454":26}}],["vitest",{"0":{"455":1},"2":{"451":1,"454":1,"455":2,"458":1,"459":2}}],["visibility",{"2":{"423":1}}],["visible",{"2":{"423":1}}],["vision",{"2":{"296":1}}],["visits",{"2":{"296":1,"301":1}}],["visiting",{"2":{"165":1,"301":2}}],["view",{"2":{"227":1,"232":1,"277":1,"408":1}}],["via",{"2":{"88":1,"89":1,"107":1,"327":2,"445":1}}],["v",{"2":{"32":1,"44":1,"154":1,"162":2,"164":1,"170":1,"447":3}}],["vuei18n",{"2":{"208":1,"347":1}}],["vue",{"0":{"284":1,"391":1},"2":{"27":1,"32":1,"40":1,"42":1,"43":1,"44":1,"46":6,"49":1,"50":1,"52":1,"53":1,"54":1,"57":1,"59":1,"60":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"73":1,"74":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"89":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"103":1,"104":2,"105":1,"107":2,"108":1,"109":1,"110":1,"148":2,"154":1,"156":1,"157":1,"159":1,"162":1,"164":1,"166":1,"168":1,"170":1,"173":1,"178":1,"180":1,"182":1,"190":7,"268":2,"282":1,"284":2,"285":2,"289":3,"327":1,"349":2,"390":1,"391":2,"447":4,"457":1,"458":2,"459":1,"481":1,"485":1,"486":1}}],["valid",{"2":{"355":1}}],["validation",{"2":{"212":1,"279":1}}],["validating",{"2":{"206":1}}],["validates",{"2":{"197":1}}],["validate",{"0":{"197":1},"2":{"197":2,"206":1}}],["val",{"2":{"289":2,"460":5}}],["value=",{"2":{"447":1}}],["values",{"0":{"112":1,"135":1,"205":1},"1":{"113":1,"136":1,"137":1,"138":1},"2":{"18":1,"97":1,"161":1,"164":1,"201":1,"203":1,"204":5,"205":6,"296":1}}],["value",{"2":{"2":1,"16":2,"17":2,"18":2,"19":2,"20":2,"21":2,"22":2,"27":3,"31":2,"42":2,"98":1,"101":1,"105":1,"109":1,"116":1,"117":1,"125":1,"162":1,"163":3,"164":2,"175":1,"192":1,"204":1,"205":3,"272":1,"289":2,"338":1,"387":2,"432":1,"447":1,"460":3}}],["varying",{"2":{"369":1,"438":1}}],["vary",{"2":{"172":1}}],["variable",{"2":{"440":1}}],["variables",{"2":{"213":1}}],["variant",{"2":{"17":1}}],["variety",{"2":{"111":1}}],["various",{"2":{"75":1,"151":1,"171":1,"357":1,"382":1,"407":1}}],["v16",{"2":{"223":1}}],["v1",{"0":{"470":1},"2":{"13":1,"15":1,"26":1,"114":1,"190":1,"326":1,"334":1,"470":2,"471":1}}],["void",{"2":{"3":1,"8":1,"25":1,"26":1,"30":1,"31":1,"119":1,"120":1,"122":1}}],["utils",{"0":{"453":1},"2":{"453":1,"454":2,"455":1,"458":1,"459":1,"460":1}}],["utilities",{"2":{"184":1,"453":1,"454":1}}],["utility",{"0":{"460":1},"2":{"129":1,"289":4,"460":1}}],["utilized",{"2":{"429":1}}],["utilize",{"2":{"110":1,"390":1}}],["upgrade",{"2":{"470":1}}],["uploads",{"0":{"261":1},"2":{"256":1}}],["upload",{"2":{"254":1,"256":2,"261":1}}],["uploading",{"0":{"256":1},"2":{"248":1}}],["upper",{"2":{"219":1}}],["up",{"0":{"307":1,"368":1,"378":1,"430":1,"452":1},"1":{"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"453":1,"454":1,"455":1},"2":{"176":1,"187":1,"248":1,"256":1,"260":1,"261":1,"276":1,"307":1,"354":1,"358":1,"407":1,"418":1,"421":1,"451":1,"454":1,"455":1,"461":1}}],["updated",{"2":{"10":1,"257":1,"276":1,"314":1,"350":1}}],["update",{"0":{"347":1},"2":{"5":1,"10":1,"241":1,"246":1,"392":1,"447":1,"471":1}}],["updates",{"2":{"5":1,"6":1,"30":1,"190":1,"202":1,"242":1,"275":1,"447":1,"481":1,"482":1}}],["updating",{"2":{"2":1,"9":1,"190":1,"202":1,"242":2,"334":2}}],["ui",{"2":{"88":1,"447":1}}],["ul>",{"2":{"170":4}}],["ul",{"2":{"66":1}}],["urlsearchparams",{"2":{"434":3}}],["urls",{"2":{"31":1,"134":1,"138":1,"143":1,"147":1,"264":1,"269":2,"315":3,"321":1,"326":3,"407":1,"425":1,"437":2,"438":1,"441":1,"443":2}}],["url",{"0":{"143":1},"2":{"24":2,"29":2,"133":1,"134":1,"143":1,"145":2,"149":1,"150":2,"253":1,"254":2,"263":1,"264":1,"270":1,"287":1,"288":1,"315":2,"321":2,"326":1,"335":4,"339":1,"389":1,"425":1,"434":1,"440":4,"441":1,"442":3,"443":3,"448":2,"449":2}}],["unpredictable",{"2":{"462":1}}],["unifying",{"2":{"480":1}}],["unit",{"2":{"454":1,"455":1,"458":2,"459":2}}],["unique",{"2":{"31":1,"190":1,"204":1,"313":1,"315":1,"384":1,"387":1,"389":1,"392":1,"482":1}}],["unlike",{"2":{"344":1,"418":1,"466":1}}],["unlocalized",{"2":{"338":2,"339":2}}],["unless",{"2":{"270":1,"287":1}}],["unaffected",{"2":{"338":1}}],["unexpected",{"2":{"323":1}}],["unnecessary",{"2":{"284":1,"367":1,"421":1,"446":1}}],["unused",{"0":{"307":1},"2":{"198":1,"206":1,"211":1,"260":1,"307":1}}],["unbabel",{"2":{"193":2}}],["underlying",{"2":{"284":1}}],["understanding",{"2":{"427":1,"449":1}}],["understand",{"2":{"191":1,"218":1,"270":1,"344":1,"367":1,"425":1,"459":1,"466":1}}],["under",{"0":{"414":1},"2":{"35":1,"46":1,"306":2,"332":1,"396":1,"407":2,"408":1,"462":1,"463":1}}],["undefined",{"2":{"15":2,"16":2,"17":2,"18":1,"19":1,"20":1,"21":1,"22":1,"28":1,"29":1,"31":1,"337":2}}],["unread",{"2":{"16":1,"17":1,"169":1}}],["unreadcount",{"2":{"16":1,"17":1,"32":1,"168":1,"169":1}}],["unknown",{"2":{"3":1,"8":1,"16":1,"116":2,"289":3,"324":1}}],["usa",{"2":{"171":1}}],["usages",{"0":{"51":1,"72":1,"102":1,"123":1,"139":1},"1":{"52":1,"53":1,"54":1,"73":1,"74":1,"103":1,"104":1,"105":1,"124":1,"125":1,"126":1,"127":1,"128":1,"140":1,"141":1,"142":1,"143":1}}],["usage",{"0":{"3":1,"32":1,"41":1,"42":1,"52":1,"73":1,"103":1,"140":1,"148":1,"151":1,"339":1,"388":1,"432":1,"475":1,"476":1,"483":1},"1":{"42":1,"43":1,"44":1,"149":1,"150":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1},"2":{"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"190":1,"191":1,"192":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"309":1,"343":1,"396":2,"397":1,"399":6,"400":6,"401":4,"402":1,"403":6,"404":6,"405":3,"407":3,"408":2,"411":1,"413":4,"414":3,"415":2,"464":4,"465":3,"466":1,"471":1,"475":1,"479":1}}],["usually",{"2":{"69":1}}],["usd",{"2":{"19":1,"21":1,"178":1}}],["us",{"2":{"14":1,"19":1,"20":1,"21":1,"22":1,"49":1,"50":1,"52":1,"53":1,"57":1,"59":1,"60":2,"115":1,"136":1,"137":1,"152":1,"158":1,"159":1,"171":2,"178":2,"180":2,"182":2,"208":1,"295":1,"296":1,"312":1,"315":2,"327":1,"328":1,"337":1,"347":2,"373":1,"375":1,"376":1,"426":1,"467":1}}],["using",{"0":{"10":1,"104":1,"156":1,"157":1,"166":1,"172":1,"173":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1,"268":1,"269":1,"270":1,"362":1,"367":1,"368":1,"431":1},"1":{"158":1,"159":1,"160":1,"167":1,"168":1,"169":1,"173":1,"174":1,"175":1,"176":1,"178":1,"180":1,"182":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"432":1},"2":{"5":1,"6":1,"7":1,"9":1,"10":1,"19":2,"20":2,"21":1,"22":1,"55":1,"59":1,"88":1,"108":1,"150":1,"154":1,"161":1,"162":1,"173":1,"177":1,"179":1,"181":1,"184":3,"186":1,"192":1,"194":1,"205":5,"206":1,"213":2,"214":1,"226":1,"227":1,"229":1,"234":1,"250":1,"256":1,"257":1,"265":1,"282":1,"289":1,"297":1,"310":1,"315":1,"323":1,"331":1,"335":1,"349":1,"384":1,"389":1,"390":1,"392":1,"410":1,"417":1,"431":1,"435":1,"440":1,"444":1,"445":2,"446":1,"449":1,"459":1}}],["usetranslationservermiddleware",{"2":{"430":1,"432":1,"434":1,"435":1}}],["usehead",{"2":{"148":1}}],["uselocalehead",{"0":{"129":1},"1":{"130":1,"131":1,"132":1,"133":1,"134":1,"135":1,"136":1,"137":1,"138":1,"139":1,"140":1,"141":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1},"2":{"129":1,"130":1,"131":1,"132":1,"133":1,"134":1,"135":1,"136":1,"137":1,"138":1,"140":1,"141":1,"142":1,"143":1,"148":2,"149":1,"150":2}}],["uses",{"2":{"55":1,"170":1,"301":1,"344":1,"418":1,"457":1}}],["usenuxtapp",{"0":{"33":1},"2":{"27":1,"31":4,"33":2,"154":2,"157":2,"162":2,"164":2,"170":2,"173":2,"178":2,"180":2,"182":2,"268":2,"389":4,"391":2}}],["usei18n",{"0":{"34":1,"111":1},"1":{"112":1,"113":1,"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"123":1,"124":1,"125":1,"126":1,"127":1,"128":1},"2":{"27":1,"32":2,"34":3,"111":1,"112":1,"113":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"124":1,"125":1,"126":1,"127":1,"128":1,"454":1,"457":2}}],["useasyncdata",{"2":{"27":2}}],["used",{"2":{"26":1,"31":1,"68":1,"93":1,"94":1,"95":1,"132":1,"134":1,"135":1,"149":1,"150":1,"160":1,"175":3,"191":1,"202":1,"205":2,"208":1,"254":1,"255":1,"289":1,"296":1,"315":2,"336":1,"337":1,"360":1,"367":1,"392":1,"397":2,"405":3,"429":1,"454":1,"480":1}}],["useful",{"2":{"10":1,"31":1,"50":1,"101":1,"132":1,"166":1,"172":1,"177":1,"179":1,"181":1,"201":1,"202":1,"263":1,"295":1,"360":1,"387":1,"425":1,"429":1,"441":1}}],["useregex",{"2":{"205":3}}],["userprofile",{"2":{"46":1}}],["usersettings",{"2":{"46":1}}],["users",{"2":{"31":1,"70":1,"146":1,"147":1,"214":1,"315":1,"379":1,"389":1,"407":1,"423":1,"427":1}}],["username>",{"2":{"220":1}}],["username",{"2":{"16":1,"17":1,"30":1,"32":1,"97":1,"168":1,"169":1,"220":2}}],["user",{"2":{"5":2,"10":2,"20":1,"25":2,"26":2,"31":4,"37":1,"43":5,"46":2,"53":1,"61":1,"97":1,"177":1,"179":1,"264":1,"269":1,"270":1,"280":1,"296":1,"301":1,"316":1,"322":1,"323":1,"336":2,"359":1,"366":1,"379":1,"389":2,"392":2,"393":1,"415":1,"423":1,"425":1,"427":1,"432":1,"435":2,"437":1,"440":2,"449":1,"479":2}}],["use",{"0":{"264":1,"267":1,"279":1,"285":1,"304":1,"389":1},"1":{"265":1,"266":1,"268":1,"269":1},"2":{"3":1,"19":1,"20":1,"31":1,"32":1,"46":1,"59":1,"98":1,"104":1,"109":1,"141":1,"148":1,"151":2,"190":2,"192":1,"205":2,"211":1,"221":1,"228":1,"230":1,"232":1,"239":1,"264":1,"266":1,"268":1,"269":1,"270":1,"276":1,"285":1,"289":2,"305":1,"325":1,"326":1,"329":1,"331":1,"332":1,"335":2,"337":1,"359":1,"367":1,"376":1,"389":1,"390":1,"391":1,"421":2,"429":1,"430":1,"440":1,"441":1,"442":1,"443":1,"446":1,"447":2,"449":4,"455":1,"459":2,"467":1}}],["bloating",{"2":{"304":1}}],["blog",{"2":{"44":1}}],["b",{"2":{"221":1}}],["browse",{"2":{"274":1}}],["browser",{"2":{"56":1,"227":1,"232":1,"322":1,"326":1,"440":2,"443":1,"445":1,"449":1}}],["brings",{"2":{"412":1}}],["bridges",{"2":{"272":1}}],["brief",{"2":{"88":1,"165":1}}],["break",{"2":{"238":1}}],["branch",{"0":{"221":1},"2":{"221":2,"244":1,"245":1}}],["br>",{"2":{"170":2}}],["biography",{"2":{"43":1}}],["bio",{"2":{"43":2}}],["bienvenue",{"2":{"30":1}}],["bundle",{"2":{"310":1,"343":1,"411":1,"415":2,"421":1,"461":1,"462":2}}],["built",{"2":{"234":1,"284":1,"344":1,"411":1,"417":1,"461":1}}],["builds",{"2":{"475":1,"476":1}}],["building",{"0":{"228":1,"232":1},"2":{"228":1}}],["build",{"0":{"399":1,"400":1,"401":1,"413":1,"464":1,"474":1},"1":{"401":1},"2":{"226":1,"228":1,"232":3,"233":1,"234":7,"242":1,"283":3,"302":1,"309":1,"310":1,"343":1,"396":1,"399":1,"400":1,"401":2,"407":3,"408":3,"411":1,"415":2,"420":1,"440":1,"461":1,"462":2,"466":2,"474":3,"475":1,"476":1,"479":1}}],["bugs",{"2":{"462":1}}],["bugfix",{"2":{"221":1}}],["bug",{"2":{"216":1,"238":1,"242":2,"289":1}}],["bulk",{"2":{"202":1,"205":1}}],["buttons",{"2":{"154":1,"306":1,"447":2}}],["button>",{"2":{"32":1,"76":1,"154":1,"170":1,"447":1}}],["button",{"0":{"76":1},"2":{"32":1,"65":1,"76":1,"77":1,"78":1,"87":4,"88":2,"154":1,"170":1,"219":1,"244":1,"306":1,"447":1}}],["but",{"2":{"31":2,"284":1,"306":1,"335":1,"366":1,"369":1,"382":1,"389":1,"441":1,"443":3,"445":1}}],["business",{"2":{"10":1}}],["bbb",{"2":{"31":1,"389":1}}],["boosts",{"2":{"478":1}}],["boolean>",{"2":{"324":2}}],["boolean",{"2":{"16":1,"97":1,"99":1,"100":1,"101":1,"116":2,"118":1,"131":1,"133":1,"315":2,"318":1,"319":1,"320":1,"322":1,"324":1,"325":1,"329":1,"330":1,"331":1,"333":1,"334":1}}],["bottlenecks",{"2":{"411":1,"462":1}}],["both",{"2":{"111":1,"164":1,"190":1,"204":2,"205":2,"292":1,"301":1,"326":1,"443":3,"462":1,"463":1}}],["body",{"2":{"149":1}}],["boxshadow",{"2":{"66":1,"74":1}}],["border",{"2":{"66":1,"74":1}}],["borderradius",{"2":{"65":1,"74":1}}],["bold",{"2":{"50":1,"53":2,"56":1,"57":2,"69":1,"74":1}}],["bonjour",{"2":{"31":1,"389":1,"391":1}}],["baidu",{"2":{"193":2}}],["backups",{"2":{"276":1}}],["backup",{"2":{"190":2}}],["back",{"2":{"116":1,"117":1,"199":1}}],["backgroundcolor",{"2":{"64":1,"65":1,"69":1,"74":3}}],["basis",{"2":{"397":1}}],["basic",{"0":{"42":1,"52":1,"73":1,"103":1,"124":1,"140":1,"152":1,"293":1,"312":1,"432":1},"1":{"313":1},"2":{"88":1,"152":1,"293":1,"361":3}}],["bashcrowdin",{"2":{"251":1,"256":1,"257":1}}],["bashpnpm",{"2":{"226":1,"227":1,"228":1,"229":2,"230":1,"231":1,"232":1,"233":1,"237":1,"238":1}}],["bashgit",{"2":{"220":1,"221":1,"225":1,"243":1}}],["bashi18n",{"2":{"190":4,"191":2,"192":2,"194":1,"195":2,"196":2,"197":2,"198":2,"199":2,"200":2,"201":2,"202":2,"203":2,"204":2,"205":4,"206":6,"483":2}}],["bashnpm",{"2":{"186":1,"250":1,"311":1,"346":1,"453":1,"467":1}}],["baseurl",{"0":{"134":1},"2":{"134":1,"143":1,"150":1,"314":1,"315":11}}],["base",{"0":{"143":1,"372":1,"373":1},"1":{"373":1},"2":{"15":2,"45":1,"134":1,"143":1,"150":2,"253":2,"254":4,"287":1,"315":1,"321":2,"335":2,"357":1,"361":3,"366":1,"370":1,"372":1,"373":3,"374":1,"375":2,"376":2,"381":2}}],["basedefault",{"2":{"314":1,"315":6}}],["based",{"0":{"379":1},"2":{"5":1,"9":1,"18":1,"28":1,"29":1,"31":5,"47":1,"105":1,"111":1,"117":1,"121":1,"131":1,"146":1,"149":1,"172":1,"173":1,"179":1,"190":2,"205":1,"245":1,"268":1,"301":1,"322":1,"324":1,"344":1,"379":1,"385":2,"389":1,"390":1,"391":1,"392":2,"412":1,"418":1,"427":1,"429":1,"437":1,"440":2,"446":1,"466":1,"481":1}}],["ban",{"2":{"8":1}}],["been",{"2":{"476":1,"480":1}}],["because",{"2":{"445":1}}],["become",{"2":{"411":1}}],["becomes",{"2":{"280":1}}],["benefit",{"2":{"427":1}}],["benefits",{"0":{"5":1,"10":1,"427":1,"473":1,"481":1},"1":{"474":1,"475":1,"476":1,"477":1,"478":1},"2":{"310":1,"397":1,"410":1}}],["beneficial",{"2":{"415":1}}],["begin",{"2":{"223":1,"344":1}}],["being",{"2":{"205":1,"355":1}}],["better",{"2":{"190":1,"246":1,"269":1,"343":1,"408":1,"415":1,"427":2,"437":1,"449":1,"470":1,"472":1,"479":1}}],["between",{"0":{"405":1},"2":{"26":1,"61":1,"68":1,"203":1,"272":1,"328":1,"344":1,"351":1,"378":1,"412":1,"419":1,"427":1,"437":1,"445":1,"466":1}}],["below",{"2":{"161":1,"253":1,"391":1,"407":1,"412":1,"460":1}}],["beforeeach",{"2":{"458":2}}],["before",{"0":{"76":1,"77":1,"79":1,"81":1,"83":1,"85":1,"485":1},"2":{"76":2,"77":2,"79":2,"81":2,"83":2,"85":2,"87":12,"162":1,"190":2,"205":1,"218":1,"223":1,"237":2,"277":1,"344":1,"347":1,"349":1,"429":1}}],["best",{"0":{"46":1,"209":1,"258":1,"270":1,"303":1,"367":1,"381":1,"390":1,"444":1,"449":1,"459":1},"1":{"210":1,"211":1,"212":1,"213":1,"259":1,"260":1,"261":1,"304":1,"305":1,"306":1,"307":1,"445":1,"446":1,"447":1},"2":{"190":1,"326":1,"421":1,"443":1,"444":1,"446":1,"447":1,"449":1}}],["be",{"2":{"9":1,"20":1,"21":1,"22":1,"26":1,"27":1,"31":4,"37":1,"38":1,"49":1,"50":1,"57":1,"63":1,"88":1,"93":1,"94":1,"95":1,"107":1,"111":1,"135":1,"136":1,"160":1,"176":1,"190":1,"192":1,"201":1,"202":1,"205":2,"214":1,"216":1,"240":1,"245":2,"246":1,"253":1,"255":2,"261":1,"284":2,"287":1,"296":1,"298":3,"302":1,"315":3,"326":4,"332":1,"337":1,"338":2,"339":1,"357":1,"387":1,"393":1,"396":1,"420":1,"438":1,"441":1,"443":1,"446":1,"449":1,"454":1,"461":1}}],["behaviors",{"2":{"326":1,"437":1,"443":1}}],["behavior",{"2":{"2":1,"31":1,"73":1,"130":1,"266":2,"385":1,"440":1,"441":1,"442":1,"443":1,"449":1,"462":1}}],["by",{"0":{"284":1,"288":1,"306":1,"345":1},"1":{"346":1,"347":1,"348":1,"349":1,"350":1,"351":1},"2":{"2":2,"4":1,"7":1,"10":2,"31":2,"56":1,"80":1,"88":2,"104":1,"108":1,"150":1,"190":1,"191":1,"192":2,"195":1,"205":2,"208":1,"214":1,"227":1,"228":1,"237":1,"248":1,"251":1,"261":1,"264":1,"266":1,"279":1,"282":1,"291":1,"296":1,"316":1,"323":1,"335":1,"338":1,"342":1,"348":1,"357":2,"361":1,"362":1,"369":3,"370":1,"372":1,"378":1,"382":1,"389":1,"392":1,"393":2,"397":1,"408":2,"411":1,"414":1,"421":1,"423":1,"427":1,"429":1,"431":1,"449":1,"460":2,"474":1,"480":1}}],["risk",{"2":{"415":1}}],["right",{"2":{"219":1,"315":2}}],["rankings",{"2":{"427":1}}],["range",{"2":{"171":1,"296":1,"314":1}}],["rates",{"2":{"407":1}}],["rate",{"2":{"403":1,"404":1,"405":1}}],["rather",{"2":{"340":1,"440":1}}],["raw",{"2":{"99":1}}],["rtl",{"2":{"131":1,"285":1,"312":1,"315":2,"359":1,"425":1,"426":1,"467":1}}],["root",{"2":{"429":2}}],["robust",{"2":{"369":1,"382":1}}],["rotating",{"2":{"71":1}}],["routing",{"0":{"379":1,"418":1},"2":{"31":2,"157":1,"263":1,"270":2,"315":2,"344":1,"379":1,"387":1,"389":1,"391":1,"392":1,"393":1,"418":2,"446":1,"466":2}}],["router",{"2":{"241":1,"282":1,"327":1}}],["routedefinition",{"2":{"31":1,"386":1}}],["routeslocalelinks",{"0":{"328":1},"2":{"328":1}}],["routes",{"0":{"147":1,"262":1,"297":1,"301":1},"1":{"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"298":1},"2":{"26":1,"31":4,"47":1,"129":1,"147":1,"263":1,"264":1,"265":1,"266":2,"268":1,"269":2,"270":2,"282":1,"297":1,"298":4,"301":1,"302":1,"315":5,"323":1,"325":1,"326":5,"338":1,"344":1,"354":1,"385":2,"387":1,"389":1,"390":2,"392":1,"418":1,"420":1,"437":1,"438":1,"440":4,"441":3,"442":2,"443":1,"446":1,"449":1,"466":2}}],["routefr",{"2":{"23":1,"24":2}}],["routeobject",{"2":{"15":1}}],["routename",{"2":{"15":1,"122":1,"296":1}}],["routelocationresolved",{"2":{"28":1}}],["routelocationresolvedgeneric",{"2":{"15":2,"26":3}}],["routelocationraw",{"2":{"23":1,"28":2,"29":2,"121":2}}],["routelocationnormalizedloaded",{"2":{"15":2,"26":3}}],["route",{"0":{"127":1,"282":1,"298":1,"354":1,"446":1},"2":{"15":6,"23":2,"24":1,"25":2,"26":13,"27":1,"28":5,"29":3,"30":1,"31":6,"49":2,"50":1,"111":1,"121":3,"127":2,"146":1,"265":2,"266":1,"268":1,"282":3,"298":3,"301":1,"323":3,"325":1,"327":1,"344":2,"385":1,"387":2,"388":1,"389":2,"391":3,"418":2,"441":1,"442":3,"446":4,"449":1,"460":2}}],["rgba",{"2":{"66":1,"74":1}}],["runwithcontext",{"2":{"289":3}}],["runtime",{"2":{"272":1,"289":1,"302":1,"329":1,"420":1,"421":1,"454":1,"462":1,"466":1,"476":1,"480":1}}],["running",{"0":{"230":1,"233":1},"2":{"190":1,"237":1,"251":1,"369":1,"378":1,"382":1}}],["run",{"0":{"227":1,"237":1},"2":{"187":1,"190":1,"195":1,"226":3,"227":2,"228":1,"229":3,"230":4,"231":4,"232":2,"233":2,"234":15,"237":1,"238":3,"311":1,"378":1,"440":2}}],["russian",{"2":{"31":1,"264":2,"265":1,"268":1,"339":2,"388":1,"389":1,"391":1,"441":1,"442":1,"443":1}}],["rules",{"2":{"92":1,"101":1,"105":1,"176":2}}],["rule",{"0":{"109":1},"2":{"18":1}}],["ru",{"2":{"2":1,"31":3,"265":1,"268":1,"338":2,"339":3,"388":2,"389":1,"391":3,"440":1,"441":1,"442":1,"443":1}}],["reused",{"2":{"480":1}}],["reusable",{"2":{"46":2,"357":1}}],["rewritten",{"2":{"480":1}}],["rewrite",{"2":{"470":1}}],["req",{"2":{"434":1}}],["requested",{"2":{"340":1}}],["request",{"0":{"244":1,"478":1},"2":{"244":1,"245":1,"335":1,"407":1,"414":2,"465":2}}],["requests",{"0":{"465":1},"2":{"218":1,"302":1,"340":1,"396":2,"403":1,"404":1,"405":1,"407":2,"414":4,"415":1,"420":2,"433":1,"465":3,"478":2}}],["requirement",{"2":{"445":1}}],["requirements",{"2":{"10":1,"285":1,"360":1,"369":1,"374":1,"382":1,"449":1}}],["requires",{"2":{"289":1,"315":1,"396":1}}],["required",{"2":{"37":1,"38":1,"49":1,"91":1,"194":1,"205":2,"292":1,"315":1,"390":1,"407":1}}],["require",{"2":{"31":1,"194":1,"213":1,"263":1,"289":1,"387":1}}],["requiring",{"2":{"10":1,"278":1,"279":1,"362":1,"423":1}}],["reorganize",{"0":{"348":1}}],["renaming",{"2":{"297":1}}],["rendered",{"2":{"110":1,"420":1,"429":1,"445":2,"472":1}}],["rendering",{"0":{"108":1,"161":1,"162":1,"164":1,"302":1,"420":1,"447":1},"1":{"162":1,"163":1,"164":1,"165":1},"2":{"99":1,"162":1,"164":1,"166":1,"283":1,"302":2,"340":1,"420":2,"421":1,"447":1,"449":1,"480":1}}],["render",{"2":{"93":1,"94":1,"95":1,"100":1,"108":1,"161":1,"302":1,"421":1,"447":1}}],["renders",{"2":{"73":1,"103":1,"458":3}}],["reaching",{"2":{"429":1}}],["reason",{"2":{"270":1}}],["reads",{"2":{"480":1}}],["readfilesync",{"2":{"458":1}}],["readability",{"2":{"306":1}}],["ready",{"2":{"228":1,"407":1,"467":1}}],["read",{"2":{"218":1}}],["real",{"0":{"277":1},"2":{"5":1,"275":1,"397":1,"407":1}}],["regarding",{"2":{"437":1}}],["regardless",{"2":{"326":1,"344":1,"418":1,"442":1,"446":1,"466":1}}],["regexp",{"2":{"327":1}}],["regex",{"2":{"205":9,"327":2,"344":1,"418":1,"466":1}}],["regularly",{"0":{"307":1},"2":{"211":1}}],["regular",{"0":{"211":1,"260":1},"2":{"205":2}}],["regional",{"2":{"177":1,"263":1,"393":1}}],["region",{"2":{"31":1}}],["regions",{"2":{"31":1,"379":1,"389":1}}],["registration",{"2":{"7":1}}],["registering",{"0":{"7":1},"2":{"9":1,"10":1}}],["registers",{"2":{"4":1,"7":1}}],["registered",{"2":{"2":1,"282":1}}],["register",{"0":{"1":1},"1":{"2":1,"3":1,"4":1,"5":1},"2":{"1":1,"2":2,"3":4,"4":2,"5":1,"7":1,"8":5,"9":2}}],["remain",{"2":{"338":1,"408":1}}],["remains",{"2":{"5":1,"339":1}}],["removed",{"2":{"307":1}}],["remove",{"2":{"211":1,"350":1}}],["removes",{"2":{"198":1}}],["reverso",{"2":{"193":2}}],["review",{"2":{"190":1,"245":1,"260":1,"307":1}}],["revoir",{"2":{"31":1,"389":1,"391":1}}],["refactor",{"2":{"242":1}}],["referral",{"2":{"285":1}}],["refer",{"2":{"242":1,"421":1,"451":1}}],["referencing",{"2":{"205":1}}],["reference",{"2":{"197":1,"205":1}}],["references",{"2":{"190":1}}],["refers",{"2":{"205":1}}],["reflect",{"2":{"46":1,"408":1}}],["receives",{"2":{"83":1,"84":1,"85":1,"86":1}}],["recognize",{"2":{"397":1,"425":1}}],["record",{"2":{"16":3,"17":3,"18":2,"27":6,"30":2,"31":6,"63":1,"97":1,"101":1,"116":1,"136":1,"137":1,"138":1,"324":3,"328":1,"338":3,"386":3}}],["recommended",{"0":{"292":1},"1":{"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1},"2":{"6":1,"291":1,"315":1}}],["representative",{"2":{"397":1}}],["represents",{"2":{"387":1}}],["representing",{"2":{"2":1,"26":1,"67":1}}],["repeatedly",{"2":{"302":1}}],["repetitive",{"2":{"279":1,"480":1}}],["repetition",{"2":{"35":1,"204":1}}],["repository",{"0":{"219":1,"225":1},"2":{"214":1,"219":2,"220":1,"225":1,"244":2}}],["reports",{"2":{"204":1}}],["replacing",{"2":{"116":1,"192":1,"206":1}}],["replacement",{"2":{"205":12}}],["replacements",{"2":{"205":3}}],["replaces",{"2":{"190":1,"205":1,"437":1}}],["replace",{"0":{"205":1,"349":1},"2":{"107":1,"166":2,"192":1,"205":12,"206":1,"220":1,"324":1,"347":1,"349":1}}],["replaced",{"2":{"104":1,"205":1}}],["rely",{"2":{"446":1,"449":1}}],["relying",{"2":{"50":1,"440":1,"445":1}}],["released",{"0":{"471":1},"1":{"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1}}],["release",{"0":{"470":1},"2":{"470":1,"471":1}}],["releases",{"2":{"284":1}}],["releasing",{"2":{"284":1}}],["relevant",{"2":{"31":1,"147":1,"244":1,"246":1,"264":1,"270":1,"389":1,"390":1}}],["relies",{"2":{"207":1,"326":1}}],["rel",{"2":{"138":1,"150":1}}],["rel=",{"2":{"54":1,"145":2,"149":2,"425":2}}],["relationships",{"2":{"427":1}}],["relativedate",{"0":{"95":1},"2":{"22":1,"95":1}}],["relativetimeformat",{"2":{"22":1,"181":1}}],["relativetimeformatoptions",{"2":{"22":3}}],["relative",{"0":{"181":1,"182":1},"1":{"182":1},"2":{"22":2,"95":4,"181":2,"182":1}}],["related",{"2":{"46":1,"133":1,"142":1,"149":1,"306":2,"318":1,"321":1,"351":1,"359":1,"427":1}}],["redundant",{"2":{"350":1,"472":1}}],["reduced",{"0":{"475":1},"2":{"343":1,"369":1,"415":1,"427":1,"479":1}}],["reduces",{"2":{"310":1,"340":1,"415":2,"417":1,"466":1,"474":1}}],["reduce",{"2":{"289":1,"309":1,"378":1,"382":1,"421":2}}],["reducing",{"2":{"35":1,"270":1,"279":1,"296":1,"302":1,"328":1,"408":1,"418":1,"420":1,"461":1,"472":1}}],["red",{"2":{"50":1}}],["redirection",{"2":{"315":2,"322":1,"470":1}}],["redirecting",{"2":{"26":2}}],["redirects",{"2":{"25":2,"322":1,"325":1,"446":1}}],["redeployment",{"2":{"10":1}}],["redeploy",{"2":{"5":1}}],["retrieve",{"2":{"124":1,"289":2,"340":1,"429":1}}],["retrieves",{"2":{"15":1,"432":1}}],["retrieval",{"0":{"124":1},"2":{"429":1}}],["returntype",{"2":{"454":1}}],["returns",{"2":{"12":1,"13":1,"14":1,"17":1,"27":1,"112":1,"113":1,"114":1,"115":1,"135":1,"149":1,"175":3,"432":1,"434":1,"460":6}}],["returned",{"2":{"9":1,"150":1}}],["return",{"0":{"112":1,"135":1},"1":{"113":1,"136":1,"137":1,"138":1},"2":{"8":2,"16":1,"17":1,"18":1,"23":1,"24":1,"27":1,"29":1,"101":2,"109":1,"176":2,"324":2,"429":1,"430":1,"432":1,"434":3,"454":1}}],["restrictions",{"2":{"440":1}}],["restructured",{"2":{"307":1}}],["resolution",{"0":{"446":1},"2":{"418":1,"446":3,"449":1}}],["resolving",{"0":{"286":1},"1":{"287":1,"288":1}}],["resolved",{"2":{"429":1,"446":1}}],["resolves",{"2":{"26":1}}],["resolve",{"2":{"7":1,"241":1,"283":1}}],["resources",{"2":{"407":1}}],["resource",{"0":{"401":1,"413":1,"464":1},"2":{"340":1,"343":1,"408":2,"479":1}}],["results",{"0":{"394":1,"415":1},"1":{"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1},"2":{"421":2,"459":1,"465":1}}],["result",{"2":{"340":1,"460":1}}],["resulting",{"2":{"289":1}}],["respectful",{"2":{"246":2}}],["respective",{"2":{"88":1,"315":2,"380":1,"381":1}}],["response",{"0":{"477":1},"2":{"27":5,"403":3,"404":3,"405":3,"407":1,"411":1,"420":1,"421":1,"429":1,"462":1,"477":3,"479":1}}],["responsive",{"2":{"10":1,"408":1}}],["re",{"2":{"7":1,"236":1,"238":1,"274":1,"280":1,"467":1,"470":1}}],["gb",{"2":{"458":1}}],["gzip",{"2":{"413":2,"464":2}}],["gap",{"2":{"272":1}}],["give",{"2":{"438":1}}],["gives",{"2":{"338":1,"437":1}}],["given",{"2":{"16":1,"17":1,"18":1,"23":1,"24":1,"25":1,"26":2,"116":1,"117":1,"338":1,"419":1}}],["git",{"2":{"220":1,"225":1}}],["github",{"0":{"243":1},"2":{"219":1,"220":2,"225":1,"243":1,"244":1,"451":1}}],["gpt",{"2":{"192":1,"194":1}}],["guide",{"0":{"183":1,"207":1,"215":1,"247":1,"252":1,"290":1,"409":1,"422":1},"1":{"184":1,"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":2,"209":1,"210":1,"211":1,"212":1,"213":1,"214":1,"216":1,"217":1,"218":1,"219":1,"220":1,"221":1,"248":1,"249":1,"250":1,"251":1,"252":1,"253":2,"254":2,"255":2,"256":1,"257":1,"258":1,"259":1,"260":1,"261":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1,"304":1,"305":1,"306":1,"307":1,"410":1,"411":1,"412":1,"413":1,"414":1,"415":1,"416":1,"417":1,"418":1,"419":1,"420":1,"421":1,"423":1,"424":1,"425":1,"426":1,"427":1},"2":{"184":1,"214":1,"216":1,"241":1,"248":1,"251":1,"261":1,"289":1,"291":1,"342":1,"410":1,"423":1,"451":1}}],["ground",{"2":{"461":1}}],["groups",{"2":{"46":3,"205":5}}],["group>",{"2":{"42":1,"43":1,"44":1}}],["groupclass",{"0":{"38":1},"2":{"45":1}}],["group",{"0":{"35":1},"1":{"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1},"2":{"35":2,"37":1,"42":1,"43":2,"44":1,"45":2,"46":9,"205":2,"306":2}}],["grow",{"2":{"408":1}}],["grows",{"2":{"305":1}}],["grained",{"2":{"437":1}}],["granular",{"2":{"397":1}}],["grammar",{"2":{"285":1}}],["graph",{"2":{"137":1,"425":2}}],["gray",{"2":{"70":1,"74":1}}],["green",{"2":{"57":1,"69":1,"74":1}}],["greetings",{"2":{"392":1}}],["greeting",{"2":{"3":1,"4":1,"31":5,"97":1,"116":2,"166":1,"167":1,"268":2,"388":3,"389":3,"391":5,"432":2}}],["going",{"2":{"277":1}}],["goal",{"2":{"246":1}}],["google",{"2":{"192":2,"193":2,"206":3}}],["good",{"2":{"46":1,"218":1}}],["goodbye",{"2":{"3":1,"31":2,"388":1,"389":1,"391":1}}],["goes",{"2":{"43":1}}],["go",{"2":{"32":1,"244":1,"268":2}}],["generic",{"2":{"381":1}}],["general",{"2":{"381":1}}],["generally",{"2":{"315":1}}],["generation",{"0":{"445":1},"2":{"150":1,"241":1,"318":1,"319":1,"344":1,"350":1,"365":1,"366":1,"445":3,"449":1,"481":1}}],["generating",{"0":{"127":1},"2":{"147":1,"190":1,"321":1,"344":1,"423":1,"482":1}}],["generate",{"2":{"127":1,"134":1,"140":1,"142":1,"150":1,"359":1,"418":1,"445":1,"446":1,"466":1}}],["generated",{"2":{"28":1,"29":1,"132":1,"141":1,"149":1,"190":2,"344":1,"351":1,"355":1,"466":1}}],["generates",{"2":{"28":1,"121":1,"129":1,"145":1,"150":1,"190":1,"318":1,"418":1,"425":3,"462":1,"466":1}}],["german",{"0":{"376":1},"2":{"265":1,"339":2,"366":3,"375":1,"376":3}}],["getroutename",{"2":{"454":1,"460":1}}],["getlocales",{"2":{"454":1,"460":1}}],["getlocalename",{"2":{"454":1,"460":1}}],["getlocale",{"2":{"454":1,"460":1}}],["gets",{"2":{"443":1}}],["getter",{"2":{"324":3}}],["getting",{"0":{"217":1,"224":1,"308":1},"1":{"218":1,"219":1,"220":1,"221":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1}}],["gettranslation",{"2":{"101":2}}],["get",{"2":{"152":1,"216":1,"249":1,"421":1,"434":1}}],["getnews",{"2":{"27":1}}],["gt",{"0":{"35":1,"47":1,"61":1,"89":1,"156":1,"157":1,"166":1,"167":1,"349":2},"1":{"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1,"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":1,"158":1,"159":1,"160":1,"167":1,"168":1,"169":1},"2":{"12":1,"13":1,"14":2,"15":1,"16":3,"17":3,"18":2,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":7,"28":1,"29":1,"30":3,"31":7,"35":1,"47":2,"50":1,"61":1,"63":1,"64":1,"66":1,"67":1,"68":1,"75":1,"88":1,"89":1,"97":1,"101":2,"103":1,"104":2,"113":1,"114":1,"115":1,"116":3,"117":1,"118":1,"119":1,"120":1,"121":1,"122":2,"135":1,"136":2,"137":2,"138":2,"149":5,"151":3,"156":1,"157":1,"166":1,"220":1,"284":2,"285":1,"324":2,"328":1,"338":3,"349":2,"425":3,"447":1,"449":1}}],["g",{"2":{"2":1,"9":1,"22":1,"23":1,"24":1,"28":1,"29":1,"113":1,"115":1,"116":1,"117":1,"118":1,"147":1,"176":1,"181":1,"186":1,"190":1,"192":2,"205":1,"250":1,"288":1,"289":2,"295":1,"296":1,"315":1,"327":1,"387":1,"396":1,"425":1,"433":1,"440":1,"441":1,"443":1,"445":1,"447":1,"466":1}}],["globallocaleroutes",{"0":{"338":1},"2":{"338":1}}],["globally",{"2":{"186":2,"249":1,"250":1,"367":1}}],["global",{"0":{"295":1,"364":1},"2":{"1":1,"2":1,"9":1,"147":1,"204":3,"205":1,"291":1,"292":1,"304":1,"313":2,"331":2,"332":1,"344":1,"358":1,"365":1,"366":1,"369":1,"382":1,"419":1,"425":1,"466":1,"468":1,"479":1}}],["old",{"2":{"205":1,"474":1}}],["outperforms",{"2":{"465":1}}],["outputs",{"2":{"173":3,"178":2,"180":2,"182":2}}],["output",{"2":{"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":2,"21":1,"22":1,"23":1,"24":1,"25":1,"28":1,"29":1,"30":1,"114":1,"136":1,"137":1,"138":1}}],["outcomes",{"2":{"459":1}}],["out",{"2":{"289":1,"421":1,"486":1}}],["outside",{"2":{"289":2,"315":1}}],["outlines",{"2":{"216":1}}],["our",{"2":{"165":2,"171":3,"190":2,"296":2,"485":1,"486":1}}],["og",{"2":{"133":2,"137":2,"145":3,"149":2,"241":1,"425":2}}],["overhead",{"2":{"408":1,"417":1,"421":1,"474":1,"480":1}}],["overuse",{"2":{"270":1}}],["over",{"2":{"161":1,"162":1,"164":1,"263":1,"307":1,"343":1,"407":1,"410":1,"437":2,"438":1,"448":1,"461":1}}],["overriding",{"2":{"266":1,"329":1,"357":1}}],["overridden",{"2":{"88":1}}],["override",{"2":{"56":1,"64":1,"315":1,"360":1,"361":1,"367":1}}],["overview",{"0":{"88":1,"309":1,"384":1,"429":1},"2":{"88":1,"407":1}}],["overall",{"2":{"5":1,"10":1,"378":1,"396":1,"407":1,"415":1}}],["operations",{"2":{"480":1}}],["operation",{"2":{"205":1,"289":1}}],["openaimodel",{"2":{"194":1}}],["openai",{"2":{"193":2,"194":2}}],["opened",{"2":{"71":1}}],["open",{"2":{"54":1,"137":1,"214":1,"218":1,"425":2}}],["optimize",{"2":{"420":1}}],["optimized",{"0":{"471":1},"1":{"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1},"2":{"310":1,"343":1,"397":1,"408":1,"466":1,"472":1,"476":1}}],["optimizing",{"2":{"147":1,"292":1,"301":1,"378":1,"411":1}}],["optimizations",{"0":{"416":1},"1":{"417":1,"418":1,"419":1,"420":1}}],["optimization",{"2":{"145":1,"344":1,"423":1}}],["option>",{"2":{"447":1}}],["option",{"2":{"67":1,"69":1,"150":2,"205":2,"320":1,"325":1,"338":1,"353":1,"355":1,"425":1,"426":1,"427":1,"437":2,"438":1,"444":1,"447":1,"448":1}}],["options",{"0":{"130":1,"314":1},"1":{"131":1,"132":1,"133":1,"134":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1},"2":{"19":2,"20":3,"21":2,"22":2,"130":1,"140":1,"178":1,"180":1,"190":2,"191":2,"192":4,"194":2,"195":2,"196":1,"197":1,"198":1,"199":2,"200":2,"201":2,"202":2,"203":1,"204":1,"205":2,"314":1,"460":2,"483":1}}],["optionalmessage",{"2":{"100":1,"108":1}}],["optionally",{"2":{"16":1,"17":1,"116":1,"117":1,"121":1}}],["optional",{"2":{"2":1,"15":2,"16":2,"17":2,"18":1,"19":1,"20":1,"21":1,"22":1,"26":1,"28":1,"29":1,"31":1,"50":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"315":5,"460":1}}],["own",{"2":{"46":1,"266":1,"315":2,"362":1,"366":1}}],["other2",{"2":{"440":1}}],["others",{"2":{"192":1,"338":1,"367":1,"459":1}}],["other",{"0":{"289":1},"2":{"27":1,"60":1,"104":1,"172":1,"176":1,"177":1,"203":2,"208":1,"251":1,"357":1,"358":1,"363":1,"372":1,"410":1,"418":1,"440":1,"441":1,"443":1,"449":1,"466":1}}],["otherwise",{"2":{"9":1}}],["occur",{"2":{"7":1,"323":1}}],["once",{"2":{"245":2,"256":1,"302":1}}],["ongoing",{"2":{"218":1}}],["ones",{"2":{"119":1}}],["one",{"2":{"109":1,"173":1,"174":1,"175":2,"176":2,"192":1,"340":1,"407":1}}],["only",{"2":{"31":4,"190":1,"191":1,"287":1,"292":1,"296":1,"301":1,"306":1,"315":1,"323":1,"331":2,"332":1,"338":1,"339":1,"344":2,"367":1,"369":1,"382":1,"389":2,"417":1,"418":1,"419":2,"421":1,"429":2,"441":1,"466":2}}],["on",{"0":{"286":1,"287":1,"379":1,"411":1},"1":{"287":1,"288":1},"2":{"5":1,"9":2,"18":1,"23":1,"24":1,"26":1,"28":1,"29":1,"31":5,"47":1,"50":1,"53":1,"105":1,"111":1,"117":1,"121":1,"131":1,"146":1,"149":1,"172":1,"173":1,"176":1,"179":1,"184":1,"186":1,"190":2,"205":1,"207":1,"214":1,"223":1,"227":1,"243":1,"244":1,"245":1,"248":1,"249":1,"268":1,"283":2,"287":1,"295":1,"301":1,"310":2,"322":1,"323":3,"324":1,"326":1,"379":1,"380":1,"385":2,"389":1,"390":1,"391":1,"392":2,"397":1,"407":2,"408":2,"411":2,"412":2,"415":1,"425":1,"427":1,"429":2,"437":1,"440":3,"445":1,"446":1,"447":1,"449":1,"451":1,"461":1,"463":1,"466":1,"472":1,"479":1,"481":1}}],["origin",{"2":{"243":1}}],["original",{"2":{"205":1,"244":1,"255":1,"462":1,"465":1}}],["organizing",{"2":{"291":1}}],["organizes",{"2":{"195":1,"292":1}}],["organize",{"0":{"306":1},"2":{"190":1,"421":1}}],["organized",{"2":{"2":1,"260":1,"261":1,"313":1,"348":1,"390":1,"397":1,"468":1}}],["organization",{"2":{"35":1,"46":1,"190":2,"292":1}}],["or",{"0":{"285":1,"289":1},"2":{"5":2,"6":1,"10":3,"15":1,"18":1,"19":1,"20":2,"21":1,"22":1,"26":1,"27":1,"31":3,"34":1,"49":2,"69":1,"71":1,"89":1,"93":1,"94":1,"95":1,"104":1,"127":1,"131":1,"172":1,"175":1,"177":1,"190":1,"194":1,"197":1,"203":1,"204":1,"205":2,"212":1,"213":1,"214":2,"216":1,"221":1,"223":3,"242":4,"246":1,"257":1,"263":2,"269":1,"270":1,"274":1,"276":1,"280":1,"283":1,"285":1,"289":5,"295":1,"304":1,"307":1,"315":4,"326":1,"329":1,"330":2,"338":2,"339":1,"342":1,"349":1,"357":1,"360":2,"361":1,"363":1,"367":2,"370":1,"384":1,"387":1,"389":2,"390":1,"425":1,"429":2,"432":1,"433":1,"440":3,"445":2,"446":1,"447":1,"448":2,"449":2,"459":1}}],["objects",{"2":{"390":1}}],["objective",{"0":{"370":1}}],["object",{"0":{"164":1},"2":{"2":1,"15":1,"20":1,"22":1,"23":1,"26":1,"28":3,"29":1,"31":5,"49":1,"83":1,"84":1,"85":1,"86":1,"112":1,"130":1,"135":1,"149":1,"150":1,"164":2,"315":1,"387":3,"389":1,"390":1,"460":1}}],["often",{"2":{"315":1}}],["offer",{"2":{"296":1}}],["offering",{"2":{"263":1,"291":1,"369":1,"385":1,"410":1,"461":1}}],["offers",{"2":{"31":2,"111":1,"171":1,"343":1,"344":1,"393":1,"415":1}}],["of",{"0":{"10":1,"87":1,"149":1,"234":1,"264":1,"273":1,"280":1,"294":1,"415":1},"1":{"265":1,"266":1,"274":1,"275":1,"276":1,"277":1,"278":1,"295":1,"296":1},"2":{"1":1,"2":1,"7":1,"10":1,"14":1,"16":1,"17":2,"18":1,"24":1,"25":1,"27":2,"31":2,"32":1,"55":1,"63":1,"66":1,"75":1,"81":1,"82":1,"87":2,"88":2,"99":1,"104":2,"111":1,"113":1,"115":1,"122":1,"124":1,"129":2,"134":1,"135":1,"138":1,"145":1,"147":1,"149":2,"150":1,"162":1,"164":1,"165":1,"171":1,"173":2,"191":2,"193":1,"204":1,"205":4,"212":1,"219":1,"244":1,"246":1,"254":1,"255":1,"261":2,"263":1,"264":1,"265":1,"268":1,"276":1,"284":1,"285":1,"289":3,"293":1,"296":2,"299":1,"302":1,"310":1,"314":1,"315":2,"325":1,"326":1,"327":1,"329":1,"333":2,"335":1,"336":1,"338":2,"339":1,"340":2,"342":1,"343":1,"344":2,"350":1,"353":1,"357":3,"359":1,"360":3,"361":1,"363":1,"367":1,"374":1,"378":2,"381":1,"384":1,"387":1,"390":1,"391":1,"392":1,"393":1,"396":3,"397":2,"407":5,"408":2,"410":1,"412":1,"415":3,"418":3,"420":1,"421":3,"423":2,"425":2,"429":1,"437":1,"438":1,"440":1,"441":1,"442":1,"443":1,"446":1,"457":1,"459":1,"460":2,"463":1,"466":2,"470":1,"471":1,"478":1,"479":1}}],["fs",{"2":{"458":3}}],["fn",{"2":{"454":25}}],["f0f0f0",{"2":{"69":1,"74":1}}],["fff",{"2":{"65":1,"74":1}}],["f8f9fa",{"2":{"64":1,"74":1}}],["featuring",{"2":{"470":1}}],["feature",{"2":{"190":1,"221":3,"236":1,"242":2,"243":2,"246":1,"263":2,"277":1,"393":1,"443":1}}],["features",{"0":{"58":1,"106":1,"144":1,"273":1,"425":1,"466":1},"1":{"59":1,"60":1,"107":1,"108":1,"109":1,"110":1,"145":1,"146":1,"147":1,"274":1,"275":1,"276":1,"277":1,"278":1},"2":{"46":2,"47":1,"216":1,"307":1,"326":1,"330":1,"340":1,"421":1,"426":1,"440":1,"451":1,"460":1}}],["feat",{"2":{"241":1,"242":1}}],["feel",{"2":{"214":1}}],["feedback",{"0":{"245":1},"2":{"91":1,"96":1,"99":1,"103":2,"104":3,"245":1,"284":2}}],["fewer",{"2":{"343":1}}],["few",{"2":{"176":3,"421":1}}],["fetching",{"2":{"335":1}}],["fetch",{"2":{"164":1,"287":1,"289":1,"302":1,"335":1,"340":1}}],["fetches",{"2":{"16":1,"17":1,"18":1,"162":1,"257":1}}],["flat",{"2":{"297":1}}],["flag",{"2":{"77":1}}],["flows",{"2":{"31":1,"389":1,"392":1}}],["flexibly",{"2":{"357":1}}],["flexible",{"2":{"1":1,"5":1,"31":1,"59":1,"89":1,"278":1,"284":1,"325":1,"369":1,"382":1,"393":1,"437":1}}],["flexibility",{"2":{"5":1,"10":1,"31":1,"75":1,"263":1,"289":1,"338":1,"390":1,"444":1,"448":1}}],["find",{"2":{"289":1,"458":2}}],["fine",{"2":{"280":1,"314":1,"437":1}}],["fixtures",{"0":{"399":1,"400":1,"403":1,"404":1},"1":{"401":1},"2":{"395":2}}],["fixing",{"2":{"238":1}}],["fix",{"0":{"286":1,"288":1},"1":{"287":1,"288":1},"2":{"221":1,"229":2,"234":2,"237":1,"238":1,"241":1,"242":3}}],["fixes",{"2":{"216":1}}],["filter",{"2":{"226":1,"234":1}}],["fill",{"2":{"192":1}}],["filecontent",{"2":{"458":2}}],["file",{"0":{"163":1,"165":1,"253":1,"276":1,"454":1,"458":1},"2":{"42":1,"43":1,"160":1,"164":1,"174":1,"190":6,"201":2,"202":1,"204":1,"205":2,"253":1,"255":1,"257":1,"276":1,"279":1,"282":1,"285":1,"298":1,"299":1,"302":1,"312":1,"334":2,"359":1,"373":1,"397":1,"412":1,"426":1,"454":2,"455":1,"463":1,"466":1,"472":2,"480":1,"481":1,"482":1}}],["files",{"0":{"161":1,"255":1,"256":1,"295":1,"296":1,"304":1,"348":1,"353":1},"1":{"162":1,"163":1,"164":1,"165":1},"2":{"6":1,"8":1,"9":2,"91":1,"161":1,"184":1,"188":1,"190":11,"196":1,"197":1,"198":1,"199":2,"200":2,"201":3,"202":4,"203":1,"204":2,"205":2,"206":2,"208":1,"211":1,"212":1,"228":1,"253":2,"254":2,"255":4,"256":2,"259":1,"260":1,"261":1,"275":1,"276":2,"283":5,"287":2,"291":1,"292":2,"295":1,"296":1,"298":3,"299":2,"301":1,"302":2,"304":2,"305":1,"306":1,"307":1,"313":3,"317":2,"328":1,"329":1,"331":1,"332":2,"333":2,"340":1,"342":1,"343":1,"344":3,"348":1,"353":2,"407":1,"411":1,"419":2,"420":2,"421":1,"429":2,"462":2,"466":2,"468":1,"474":1,"480":1,"481":2,"482":2}}],["fits",{"2":{"326":1,"449":1}}],["fit",{"2":{"101":1,"448":1}}],["first",{"2":{"27":2,"163":1,"175":1,"190":1,"205":1,"225":1,"250":1,"289":2,"346":1,"453":1}}],["fast",{"2":{"304":1,"461":1}}],["faster",{"0":{"474":1},"2":{"272":1,"343":1,"408":1,"413":1,"414":1,"415":2,"464":1,"465":1,"470":1,"474":1,"477":2,"479":1,"480":1}}],["faq",{"0":{"281":1},"1":{"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1}}],["familiarize",{"0":{"218":1},"2":{"218":1}}],["familiar",{"2":{"179":1}}],["falling",{"2":{"116":1,"117":1}}],["fallbacklocale",{"0":{"337":1},"2":{"208":1,"337":1}}],["fallback",{"2":{"98":1,"125":1,"337":2,"435":1,"480":1}}],["false",{"2":{"99":1,"100":1,"131":1,"133":1,"142":1,"152":3,"190":2,"191":1,"192":1,"205":1,"319":1,"322":1,"325":1,"327":1,"329":1,"330":1,"331":1,"333":1,"334":1,"338":3,"361":1,"365":1,"366":1,"375":1,"376":1,"455":1}}],["facilitates",{"2":{"26":1}}],["farewells",{"2":{"392":1}}],["farewell",{"2":{"3":1,"4":1,"31":5,"388":3,"389":3,"391":5}}],["framework",{"2":{"459":1}}],["français",{"2":{"63":1,"74":1,"152":1,"155":1,"156":1}}],["fraction",{"2":{"19":1}}],["friends",{"2":{"285":1}}],["friendly",{"2":{"61":1,"246":1,"280":1,"393":1}}],["friday",{"2":{"20":1,"180":1}}],["freeing",{"2":{"427":1}}],["free",{"2":{"204":1,"214":1}}],["french",{"0":{"375":1},"2":{"25":1,"26":1,"30":1,"361":1,"375":3,"376":1,"391":1,"434":2,"441":1,"442":1,"443":1}}],["frequently",{"2":{"10":1}}],["fr",{"2":{"14":3,"15":1,"23":2,"24":2,"25":1,"26":1,"27":4,"28":1,"31":2,"63":1,"74":1,"115":3,"120":1,"121":1,"122":1,"127":1,"152":3,"155":1,"156":1,"208":3,"293":3,"298":3,"301":2,"312":3,"313":3,"315":3,"332":1,"337":3,"347":6,"348":3,"359":3,"361":7,"364":3,"365":3,"366":3,"375":6,"376":3,"377":2,"387":1,"389":2,"391":3,"426":3,"440":1,"441":1,"442":1,"443":1,"467":3,"468":3}}],["from",{"0":{"161":1,"164":1,"257":1,"341":1},"1":{"162":1,"163":1,"164":1,"165":1,"342":1,"343":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"350":1,"351":1,"352":1,"353":1,"354":1,"355":1},"2":{"8":2,"10":1,"13":1,"15":1,"31":2,"32":1,"33":1,"34":1,"70":1,"114":1,"150":1,"154":1,"157":1,"162":2,"164":1,"170":1,"173":1,"178":1,"180":1,"182":1,"184":1,"190":2,"192":1,"195":1,"198":1,"201":1,"202":2,"205":1,"216":1,"257":1,"268":1,"283":2,"287":2,"301":2,"302":1,"315":1,"335":1,"340":1,"342":2,"361":3,"375":1,"376":1,"389":2,"391":2,"427":2,"429":2,"432":2,"434":1,"454":3,"455":1,"457":2,"458":9,"460":1,"461":1,"475":2,"476":2,"477":2,"478":1}}],["further",{"2":{"302":1,"419":1}}],["future",{"2":{"182":1,"284":1,"367":1,"459":1}}],["fully",{"2":{"74":1,"397":1}}],["full",{"2":{"10":1,"147":1,"180":1,"191":2,"288":1}}],["functions",{"2":{"283":1,"289":4,"454":1,"459":2}}],["functional",{"2":{"242":1}}],["functionality",{"2":{"238":1,"284":1,"330":1,"472":1}}],["functionalities",{"2":{"111":1,"369":1,"382":1}}],["functioning",{"2":{"230":1}}],["function",{"0":{"385":1},"1":{"386":1,"387":1,"388":1},"2":{"2":2,"4":1,"8":1,"9":2,"31":1,"40":1,"101":1,"109":1,"172":1,"177":1,"179":1,"181":1,"265":1,"289":2,"324":1,"384":1,"385":1,"391":1,"393":1,"430":1,"432":1,"434":1,"454":1}}],["focuses",{"2":{"472":1}}],["focusing",{"2":{"407":1,"408":1,"461":1,"466":1}}],["focus",{"0":{"411":1},"2":{"310":1,"396":1,"408":1}}],["folders",{"2":{"283":1}}],["folder",{"0":{"283":2,"290":1,"292":1,"298":1,"313":1,"332":1,"468":1},"1":{"291":1,"292":1,"293":2,"294":2,"295":2,"296":2,"297":2,"298":2,"299":2,"300":1,"301":1,"302":1,"303":1,"304":1,"305":1,"306":1,"307":1},"2":{"254":1,"283":1,"291":1,"293":1,"297":1,"298":6,"429":1}}],["follows",{"2":{"240":1,"264":1}}],["follow",{"2":{"236":1,"239":1,"246":1,"263":1,"293":1,"353":1,"442":1}}],["followed",{"2":{"205":1}}],["followers",{"2":{"43":3}}],["following",{"2":{"3":1,"43":3,"145":1,"148":1,"173":1,"214":1,"223":1,"227":1,"228":1,"230":1,"232":1,"233":1,"256":1,"261":1,"282":1,"289":1,"311":1,"315":1,"339":1,"425":1,"460":1}}],["footers",{"2":{"295":1}}],["footer>",{"2":{"170":2}}],["footernote",{"2":{"165":1}}],["footer",{"2":{"80":1,"170":4,"171":1,"295":1}}],["fontsize",{"2":{"71":1,"74":1}}],["font",{"2":{"56":1}}],["fontweight",{"2":{"50":1,"53":1,"57":1,"69":1,"74":1}}],["foundation",{"2":{"372":1}}],["found",{"0":{"354":1},"2":{"16":1,"17":1,"18":1,"98":1,"116":1,"117":1,"204":2,"205":2,"462":1}}],["force",{"2":{"434":1}}],["forked",{"2":{"220":1,"244":1}}],["fork",{"0":{"219":1,"220":1},"2":{"219":1,"243":1}}],["form",{"2":{"175":3,"306":1}}],["forms",{"2":{"173":1,"174":1,"306":1,"324":5}}],["formatteddate",{"2":{"20":1}}],["formattednumber",{"2":{"19":1,"21":1}}],["formatting",{"0":{"177":1,"178":1,"179":1,"180":1,"181":1,"182":1},"1":{"178":1,"180":1,"182":1},"2":{"19":2,"20":1,"21":1,"22":1,"93":1,"94":1,"95":1,"242":1}}],["format",{"0":{"240":1},"2":{"19":3,"20":2,"21":1,"178":2,"180":2,"182":2,"199":1,"201":1,"239":2,"241":1,"264":1,"279":1,"298":1,"348":1,"353":1,"390":1}}],["formats",{"2":{"19":1,"20":3,"21":1,"22":1,"177":2,"179":2,"181":1,"460":2}}],["for=",{"2":{"32":1,"44":1,"154":1,"162":1,"164":1,"170":1,"447":2}}],["for",{"0":{"10":1,"59":1,"104":1,"155":1,"157":1,"158":1,"160":1,"166":1,"167":1,"169":1,"171":1,"172":1,"173":1,"174":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1,"267":1,"270":1,"365":1,"366":1,"367":1,"375":1,"376":1,"377":1,"378":1,"399":1,"400":1,"403":1,"404":1,"421":1,"422":1,"436":1,"459":1},"1":{"158":1,"159":1,"160":1,"167":1,"168":1,"169":1,"173":1,"174":1,"175":1,"176":1,"178":1,"180":1,"182":1,"268":1,"269":1,"401":1,"423":1,"424":1,"425":1,"426":1,"427":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"2":3,"4":2,"8":1,"9":1,"10":1,"16":1,"17":1,"18":3,"26":2,"27":3,"28":1,"29":1,"30":1,"31":14,"45":1,"47":1,"49":2,"50":1,"54":1,"55":1,"59":1,"61":1,"63":1,"66":1,"69":1,"70":1,"71":1,"92":1,"93":1,"94":1,"95":1,"97":1,"103":1,"111":1,"112":1,"118":1,"119":1,"122":1,"128":1,"129":2,"132":1,"133":1,"134":1,"137":1,"138":1,"141":1,"143":1,"145":4,"146":1,"147":3,"149":1,"150":1,"156":1,"160":1,"162":1,"165":1,"166":1,"172":1,"176":2,"177":1,"179":1,"181":1,"190":4,"191":1,"192":1,"194":1,"197":1,"200":1,"201":2,"202":1,"204":2,"205":5,"214":2,"216":1,"221":1,"228":1,"231":1,"234":3,"236":1,"242":1,"254":3,"255":1,"256":1,"263":1,"264":4,"265":3,"268":2,"269":3,"270":2,"272":2,"274":1,"275":1,"276":1,"279":2,"282":1,"284":1,"285":1,"288":1,"289":1,"291":1,"295":1,"296":1,"298":6,"299":1,"301":1,"302":2,"304":1,"305":1,"306":1,"309":2,"310":1,"314":1,"315":11,"317":1,"318":1,"321":2,"324":1,"325":1,"326":5,"329":1,"334":2,"335":1,"338":7,"339":4,"340":1,"344":2,"348":1,"349":1,"357":2,"358":1,"359":1,"360":3,"361":1,"366":1,"367":2,"369":4,"370":1,"372":2,"374":2,"375":1,"376":1,"377":2,"378":1,"382":3,"384":2,"385":2,"387":4,"388":1,"389":7,"390":4,"391":3,"392":3,"396":1,"397":4,"407":3,"408":2,"411":1,"415":1,"418":1,"419":1,"420":3,"421":1,"423":2,"425":7,"429":1,"430":1,"432":2,"433":1,"434":1,"440":5,"441":6,"442":6,"443":7,"446":1,"447":4,"448":1,"449":4,"451":3,"453":1,"458":1,"459":4,"460":1,"461":1,"462":1,"466":4,"470":2,"471":1,"472":2,"479":1,"486":1}}],["pitfalls",{"2":{"449":1}}],["pipeline",{"2":{"212":1,"261":1}}],["phase",{"2":{"407":2}}],["phases",{"2":{"407":1}}],["phone",{"2":{"170":1,"171":1}}],["pnpm",{"2":{"223":1,"226":4,"230":1,"231":2,"232":1,"234":12,"238":1}}],["personalized",{"2":{"427":1}}],["per",{"0":{"383":1,"391":1},"1":{"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1},"2":{"269":1,"384":1,"390":1,"393":1,"397":1,"403":1,"404":1,"405":1,"407":2,"414":5,"465":5,"478":2}}],["periodically",{"2":{"260":1,"307":1}}],["permissions",{"2":{"254":1}}],["performances",{"2":{"327":1}}],["performance",{"0":{"394":1,"399":1,"400":1,"402":1,"406":1,"409":1,"411":1,"412":1,"414":1,"421":1,"463":1,"465":1},"1":{"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":2,"402":1,"403":1,"404":1,"405":1,"406":1,"407":2,"408":2,"410":1,"411":1,"412":1,"413":2,"414":2,"415":2,"416":1,"417":1,"418":1,"419":1,"420":1,"421":1,"464":1,"465":1},"2":{"284":1,"292":1,"296":1,"301":1,"302":1,"309":1,"310":1,"342":1,"343":1,"395":1,"396":2,"397":1,"407":1,"408":1,"410":2,"411":1,"412":1,"414":1,"415":1,"417":1,"419":1,"420":1,"421":3,"461":1,"462":4,"466":1,"470":1,"471":1,"479":1}}],["perform",{"2":{"205":1,"408":1}}],["percent",{"2":{"178":1}}],["percentages",{"2":{"19":1,"177":1}}],["p",{"2":{"195":1,"457":1}}],["plaintext",{"2":{"293":1,"298":3,"348":1,"468":1}}],["placed",{"2":{"253":1}}],["placeholders",{"2":{"116":1,"255":1}}],["placeholder",{"2":{"104":1}}],["platforms",{"2":{"248":1,"283":1,"287":1}}],["playwright",{"2":{"230":1}}],["playground",{"0":{"233":1},"2":{"226":1,"227":1,"233":3,"234":2}}],["please",{"2":{"190":1,"239":1,"421":1,"486":1}}],["plural=",{"2":{"92":1,"101":1,"105":1,"109":1}}],["plural",{"0":{"92":1,"324":1},"2":{"18":1,"173":1,"174":1,"324":1}}],["pluralization",{"0":{"105":1,"109":1,"172":1,"173":1,"174":1,"176":1},"1":{"173":1,"174":1,"175":1,"176":1},"2":{"18":1,"92":1,"101":2,"105":1,"109":1,"117":1,"172":1,"176":1,"324":1,"460":1}}],["pluralized",{"2":{"18":1,"173":1}}],["pluraltranslations",{"2":{"16":1,"116":1}}],["plugin",{"0":{"7":1,"8":1,"330":1},"2":{"7":2,"8":2,"9":1,"289":1,"329":2,"330":2}}],["plugins",{"0":{"6":1,"10":1,"289":1},"1":{"7":1,"8":1,"9":1,"10":1},"2":{"6":2,"7":2,"10":2,"190":1,"289":2,"417":1,"466":1,"482":1}}],["poor",{"2":{"411":1}}],["potential",{"2":{"397":1}}],["pots",{"2":{"199":2,"200":2}}],["potsdir",{"2":{"199":2,"200":2}}],["powered",{"2":{"393":1}}],["powerful",{"2":{"272":1,"393":1,"459":1,"466":1}}],["portal",{"0":{"366":1},"2":{"363":1,"366":3}}],["polished",{"2":{"280":1}}],["po",{"2":{"199":2,"200":2}}],["positioning",{"2":{"88":1}}],["postinstall",{"2":{"320":1}}],["post",{"2":{"44":1}}],["points",{"2":{"75":1}}],["push",{"0":{"243":1},"2":{"243":2}}],["publishing",{"2":{"234":1}}],["publishdate",{"2":{"44":2}}],["pull",{"0":{"244":1},"2":{"218":1,"244":1,"245":1}}],["purposes",{"2":{"134":1,"397":1}}],["purpose",{"2":{"2":1,"295":1,"296":1,"367":1,"430":1,"459":1}}],["p>test",{"2":{"457":1}}],["p>please",{"2":{"190":1,"485":1}}],["p>current",{"2":{"32":1,"154":1}}],["p>",{"2":{"32":3,"42":2,"43":2,"44":2,"154":1,"162":2,"164":2,"170":4,"173":6,"178":4,"180":4,"182":4,"190":3,"268":2,"391":2,"457":2,"485":1,"486":2}}],["practical",{"2":{"451":1}}],["practice",{"2":{"446":1,"447":1}}],["practices",{"0":{"46":1,"209":1,"258":1,"270":1,"303":1,"367":1,"381":1,"390":1,"444":1,"449":1,"459":1},"1":{"210":1,"211":1,"212":1,"213":1,"259":1,"260":1,"261":1,"304":1,"305":1,"306":1,"307":1,"445":1,"446":1,"447":1},"2":{"190":1,"444":1,"449":1}}],["priority",{"2":{"443":1}}],["primarily",{"2":{"270":1}}],["primary",{"0":{"264":1,"358":1,"359":1,"361":1,"364":1},"1":{"265":1,"266":1,"359":1},"2":{"264":1,"266":1,"315":1,"358":1,"359":1,"360":1,"361":2,"367":2,"425":1}}],["pricing",{"2":{"46":1}}],["price",{"2":{"42":4}}],["pr",{"2":{"244":2,"245":1}}],["predictable",{"2":{"459":1,"480":1}}],["present",{"2":{"344":1,"442":1,"466":1}}],["preserving",{"2":{"285":1,"481":1}}],["preserve",{"2":{"253":1,"254":1,"289":1}}],["preserves",{"2":{"190":2}}],["pre",{"0":{"302":1,"420":1},"2":{"302":3,"420":3,"421":2,"472":1,"480":1}}],["prerendering",{"2":{"283":3}}],["prerequisites",{"0":{"223":1}}],["prevents",{"2":{"305":1}}],["preventing",{"2":{"70":1,"204":1,"315":1}}],["previews",{"0":{"277":1}}],["preview",{"2":{"232":1}}],["previewing",{"0":{"232":1}}],["previous",{"2":{"160":1,"326":1}}],["prepares",{"2":{"228":1}}],["prepare",{"2":{"226":1,"234":1}}],["prepared",{"2":{"147":1,"245":1}}],["prepack",{"2":{"226":1,"228":1,"234":1}}],["prepends",{"2":{"40":1}}],["prepended",{"2":{"37":1}}],["premium",{"2":{"42":2}}],["premier",{"2":{"27":2}}],["prefixed",{"2":{"147":1,"326":2,"443":8,"448":1}}],["prefixes",{"2":{"15":1,"46":3,"190":1,"326":1,"339":1,"437":2,"438":1,"448":2,"449":3}}],["prefix=",{"2":{"42":1,"43":1,"44":1,"46":8}}],["prefix",{"0":{"37":1,"436":1,"437":1,"440":1,"441":1,"442":1,"443":1,"445":1,"447":1},"1":{"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"35":1,"37":1,"40":4,"111":1,"190":2,"315":2,"325":1,"326":10,"438":1,"440":3,"441":8,"442":5,"443":7,"445":3,"447":1,"449":5}}],["preference",{"2":{"323":1,"392":1}}],["preferences",{"2":{"10":1,"393":1,"427":1}}],["prefer",{"2":{"201":1,"299":1,"441":1,"448":1}}],["preferred",{"2":{"31":1,"322":1,"326":1,"359":1,"389":1,"392":1,"443":1,"446":1}}],["problematic",{"2":{"447":1}}],["problems",{"2":{"446":1}}],["probably",{"2":{"289":1}}],["pronounced",{"2":{"411":1}}],["protocol",{"2":{"315":1}}],["proceeding",{"2":{"237":1}}],["processes",{"2":{"190":1,"415":1,"482":1}}],["processed",{"2":{"190":1}}],["processing",{"2":{"190":2,"396":1,"415":1,"482":1}}],["process",{"2":{"1":1,"10":1,"147":1,"184":2,"190":1,"192":1,"248":1,"251":1,"276":1,"283":2,"291":1,"302":1,"319":1,"320":1,"343":1,"344":1,"408":1,"420":1,"423":1}}],["prod",{"2":{"195":1}}],["productivity",{"2":{"479":1}}],["production",{"2":{"195":1,"283":2,"408":1}}],["products",{"2":{"296":1,"298":10,"328":2}}],["product",{"2":{"37":1,"42":4,"46":2,"269":1}}],["prompted",{"2":{"192":1}}],["prompt",{"2":{"192":1}}],["promise",{"2":{"122":1}}],["progress",{"2":{"191":1,"203":1}}],["programmatically",{"0":{"154":1},"2":{"154":1}}],["project",{"0":{"187":1,"218":1,"251":1,"395":1},"1":{"396":1,"397":1},"2":{"184":1,"187":2,"191":1,"214":3,"216":1,"218":1,"226":1,"229":1,"236":1,"237":1,"239":1,"246":1,"248":2,"249":1,"251":2,"253":2,"254":4,"257":1,"261":1,"276":1,"315":1,"320":1,"346":1,"367":1,"369":1,"378":1,"379":1,"382":1,"407":1,"421":1,"449":1,"451":1}}],["projects",{"0":{"378":1},"2":{"184":1,"279":1,"309":1,"342":1,"369":1,"378":1,"382":1,"408":1,"411":1,"461":1,"462":1,"466":1}}],["profile",{"2":{"37":1,"43":4,"45":2,"46":1}}],["proper",{"2":{"285":1}}],["properly",{"2":{"282":1}}],["properties",{"2":{"40":2,"112":1,"135":1,"314":1,"315":1}}],["property",{"2":{"18":1,"31":2,"137":1,"150":1,"389":1,"390":1,"392":2}}],["prop",{"2":{"45":1,"55":1,"56":1,"83":1,"84":1,"85":1,"86":1,"93":1,"94":1,"95":1,"108":1}}],["props",{"0":{"36":1,"48":1,"62":1,"90":1},"1":{"37":1,"38":1,"49":1,"50":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1},"2":{"83":1,"84":1,"85":1,"86":1,"87":1,"88":2,"457":3,"458":3}}],["providing",{"0":{"433":1},"1":{"434":1},"2":{"10":1,"31":3,"47":1,"56":1,"205":1,"382":1,"384":1,"389":1,"437":1}}],["provides",{"2":{"35":1,"40":1,"61":1,"75":1,"97":1,"107":1,"151":1,"156":1,"184":1,"248":1,"272":1,"274":1,"279":1,"314":1,"342":1,"410":1,"444":1,"448":1,"453":1}}],["provide",{"2":{"6":1,"31":3,"111":1,"171":1,"194":1,"264":1,"269":1,"385":1,"389":1,"408":1}}],["provided",{"2":{"2":2,"4":2,"26":1,"31":1,"107":1,"116":1,"117":1,"173":1,"190":2,"192":2,"205":1,"315":1,"389":1,"430":1,"460":1}}],["panel",{"0":{"365":1},"2":{"363":1,"365":2,"366":1}}],["packaging",{"2":{"228":1}}],["packages",{"2":{"226":1,"234":3}}],["package",{"2":{"184":1,"453":1}}],["pattern",{"2":{"205":3,"270":1,"327":1,"339":1,"397":1,"442":1}}],["patterns",{"2":{"205":1}}],["paths",{"0":{"297":1},"1":{"298":1},"2":{"31":1,"49":1,"190":1,"201":1,"255":2,"257":1,"263":1,"264":1,"297":1,"326":1,"338":1,"339":2,"389":1,"392":1,"440":1,"472":1,"481":1}}],["path",{"0":{"286":1},"1":{"287":1,"288":1},"2":{"26":5,"49":1,"91":1,"147":1,"162":1,"190":4,"205":2,"253":1,"254":1,"255":2,"265":2,"266":2,"268":1,"295":1,"296":1,"299":1,"315":1,"323":1,"335":1,"338":2,"387":1,"388":1,"391":4,"395":2,"446":1,"458":3}}],["papago",{"2":{"193":2}}],["padding",{"2":{"64":1,"67":1,"68":1,"74":3}}],["pay",{"2":{"351":1}}],["payment",{"2":{"46":1}}],["payload",{"2":{"2":1}}],["passing",{"2":{"88":2}}],["pass",{"2":{"31":3,"59":1,"289":3,"433":1}}],["passed",{"2":{"27":1,"93":1,"94":1,"95":1}}],["parse",{"2":{"458":1}}],["paragraph",{"2":{"149":1}}],["param",{"2":{"435":1}}],["parameter",{"2":{"315":1,"435":1}}],["parameters",{"0":{"125":1,"254":1,"387":1},"2":{"15":1,"16":2,"17":2,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"97":1,"116":1,"125":1,"284":1,"432":1,"460":1}}],["params=",{"2":{"97":1,"168":1}}],["params",{"0":{"97":1},"2":{"16":2,"17":2,"18":1,"23":1,"27":4,"28":1,"101":3,"116":1,"324":3,"460":3}}],["part",{"2":{"205":2,"429":1}}],["parts",{"2":{"104":1,"343":1,"357":2,"360":2}}],["particular",{"2":{"296":1,"360":1,"361":1}}],["particularly",{"2":{"31":1,"263":1,"397":1,"415":1,"425":1,"429":1,"462":1}}],["partial",{"2":{"50":1}}],["page2",{"2":{"338":4,"339":6}}],["pagename",{"2":{"282":1}}],["pages",{"2":{"27":1,"150":1,"190":4,"204":1,"253":2,"269":2,"292":1,"293":1,"295":1,"296":5,"298":3,"301":2,"304":1,"313":2,"328":1,"332":1,"338":3,"348":1,"384":1,"468":1,"482":1,"486":2}}],["page",{"0":{"128":1,"268":1,"296":1,"304":1,"391":1},"2":{"26":2,"52":1,"53":1,"122":1,"128":1,"138":1,"145":1,"149":2,"166":2,"167":1,"170":1,"190":1,"204":2,"205":1,"264":1,"268":1,"282":1,"291":1,"292":1,"296":1,"301":1,"304":2,"313":2,"331":2,"332":1,"338":6,"339":2,"344":1,"390":1,"397":1,"419":1,"421":3,"425":1,"445":1,"446":2,"466":1,"468":1}}],["pairs",{"2":{"2":1,"16":1,"17":1,"18":1,"31":1,"192":1}}],["due",{"2":{"447":1}}],["duplication",{"2":{"210":1,"259":1,"315":1,"328":1}}],["duplicated",{"2":{"204":1}}],["duplicate",{"2":{"204":2}}],["duplicates",{"0":{"204":1},"2":{"204":4}}],["during",{"0":{"286":1},"1":{"287":1,"288":1},"2":{"205":1,"283":4,"288":1,"302":1,"319":1,"320":1,"333":1,"334":1,"340":1,"407":1,"408":1,"415":1,"420":1,"445":1,"447":1,"454":1,"462":1,"475":1,"480":2}}],["d+",{"2":{"205":1}}],["drastic",{"2":{"477":1}}],["drastically",{"2":{"340":1,"415":1}}],["dry",{"2":{"190":1}}],["dryrun",{"2":{"190":2}}],["dropdown>",{"2":{"79":1,"80":1}}],["dropdown",{"0":{"79":1,"80":1,"81":1,"82":1},"2":{"61":1,"65":1,"71":2,"79":2,"80":2,"81":2,"82":2,"87":8,"88":5,"156":1,"315":1}}],["don",{"2":{"449":1}}],["dom",{"2":{"447":1}}],["domain",{"0":{"368":1,"371":1,"374":1,"375":1,"376":1,"377":1,"379":1},"1":{"369":1,"370":1,"371":1,"372":2,"373":2,"374":2,"375":3,"376":3,"377":2,"378":2,"379":2,"380":2,"381":1,"382":1},"2":{"315":1,"369":2,"370":1,"372":1,"374":3,"375":1,"376":1,"377":1,"378":2,"379":2,"380":2,"381":2,"382":2}}],["domains",{"2":{"171":1,"315":1,"369":1,"370":1,"380":1,"381":1,"382":1}}],["downloads",{"0":{"261":1}}],["download",{"2":{"254":1,"257":2,"261":1}}],["downloading",{"0":{"257":1},"2":{"248":1}}],["docs",{"2":{"232":2,"234":3,"241":1,"242":1,"289":1}}],["documentation",{"0":{"232":1},"2":{"216":1,"218":1,"232":2,"234":3,"242":1,"246":2,"269":1,"314":1,"451":1,"486":1}}],["document",{"2":{"129":1,"131":1,"132":1,"146":1,"149":1,"270":2,"367":2,"390":2,"459":2}}],["does",{"0":{"289":1},"2":{"283":1,"326":1,"337":1,"440":1}}],["doesn",{"0":{"282":1},"2":{"282":1}}],["doe",{"2":{"44":1}}],["do",{"2":{"31":1,"101":1,"204":1,"238":1,"315":1}}],["dashboard",{"2":{"128":1}}],["data",{"2":{"27":1,"93":2,"94":2,"95":2,"132":1,"141":1,"201":1,"202":1,"292":1,"296":1,"302":1,"340":1,"419":1,"421":2,"457":1,"458":2}}],["date=",{"2":{"94":1,"95":1}}],["dates",{"2":{"20":1,"95":1,"179":2,"181":1}}],["datetimeformat",{"2":{"20":1,"179":1}}],["datetimeformatoptions",{"2":{"20":3}}],["date",{"0":{"94":1,"179":1,"180":1,"181":1,"182":1},"1":{"180":1,"182":1},"2":{"20":9,"22":8,"44":2,"94":6,"95":4,"180":4,"181":1,"182":6,"261":1,"276":1,"460":1,"470":1,"471":1}}],["days",{"2":{"181":1}}],["day",{"2":{"20":1,"180":1,"182":1}}],["differs",{"2":{"284":1}}],["differ",{"2":{"283":1}}],["difference",{"2":{"396":1,"402":3,"405":12}}],["differences",{"0":{"344":1},"2":{"181":1,"270":1,"344":1}}],["differently",{"2":{"338":1}}],["differentiating",{"2":{"132":1}}],["different",{"0":{"269":1,"378":1},"2":{"31":2,"59":1,"61":1,"126":1,"174":1,"204":2,"214":1,"263":1,"264":2,"299":1,"306":1,"318":1,"328":1,"335":1,"357":2,"360":2,"363":1,"369":1,"370":1,"379":1,"382":2,"385":1,"387":1,"389":1,"390":1,"392":1,"427":1,"437":2,"445":1}}],["diff",{"0":{"203":1},"2":{"203":2}}],["digit",{"2":{"180":3}}],["digits",{"2":{"19":1}}],["divided",{"2":{"407":1}}],["divider",{"2":{"81":1,"82":1}}],["div",{"2":{"38":1,"42":1,"43":2,"44":2,"45":1,"64":1,"96":1,"162":1,"164":1}}],["div>",{"2":{"32":10,"42":1,"43":2,"44":2,"148":2,"154":4,"156":2,"157":2,"159":2,"162":3,"164":3,"170":8,"173":2,"178":2,"180":2,"182":2,"190":4,"268":4,"391":2,"457":2,"485":2,"486":2}}],["dirname",{"2":{"458":1}}],["direct",{"2":{"315":1,"379":1,"447":1,"479":1}}],["directories",{"2":{"190":1,"313":1,"482":1}}],["directory",{"0":{"299":1},"2":{"9":1,"187":1,"188":2,"199":2,"200":1,"201":1,"202":1,"203":1,"208":2,"227":1,"233":1,"249":1,"254":2,"292":1,"299":6,"317":2,"332":1,"348":1,"353":1,"359":1}}],["direction",{"0":{"146":1},"2":{"131":1,"315":1,"425":2}}],["directly",{"0":{"285":1},"2":{"53":1,"135":1,"275":1,"283":1,"287":1,"289":1,"302":1,"315":1,"332":1,"384":1,"390":1,"392":1}}],["dir",{"2":{"14":3,"129":1,"131":1,"136":2,"146":1,"149":1,"150":1,"152":3,"312":3,"315":7,"337":3,"347":2,"359":3,"361":5,"364":2,"365":3,"366":3,"373":3,"375":4,"376":4,"425":1,"426":3,"467":3}}],["distribute",{"2":{"382":1}}],["distribution",{"2":{"369":1,"378":1}}],["distinct",{"2":{"264":1,"269":1,"363":1,"441":1}}],["discrepancies",{"2":{"203":1}}],["display",{"2":{"173":2,"191":2,"268":1,"392":1}}],["displayed",{"2":{"63":1,"149":1}}],["displaying",{"2":{"20":1,"177":1,"179":1,"181":1}}],["displayname",{"2":{"13":1,"114":1,"152":3}}],["disableupdater",{"0":{"334":1}}],["disablewatcher",{"0":{"333":1}}],["disablepagelocales",{"0":{"331":1,"332":1},"2":{"332":1}}],["disables",{"2":{"315":1,"329":1,"330":1,"333":2,"334":2,"366":1}}],["disabled",{"2":{"152":3,"315":3,"323":1,"375":3,"376":3,"447":3}}],["disabled=",{"2":{"32":1,"154":1,"170":1,"447":1}}],["disable",{"0":{"142":1},"2":{"8":1,"70":1,"320":1,"329":1,"330":1,"331":2,"338":3,"361":2,"365":1,"366":1,"374":1,"375":4,"376":4}}],["deep",{"2":{"472":1,"480":1}}],["deepl",{"2":{"192":4,"193":2,"206":2}}],["deeply",{"2":{"46":1}}],["decreases",{"2":{"415":1}}],["decimals",{"2":{"19":1}}],["debugging",{"2":{"319":2}}],["debug",{"0":{"319":1}}],["delays",{"2":{"302":1}}],["delivers",{"2":{"309":1}}],["deliver",{"2":{"280":1}}],["delivering",{"2":{"31":1,"389":1,"392":1}}],["delimiter",{"2":{"201":2,"202":2}}],["dealing",{"2":{"298":1}}],["demand",{"2":{"284":1}}],["demonstrate",{"2":{"412":1,"465":1}}],["demonstrates",{"2":{"3":1,"74":1,"148":1,"150":1,"154":1,"161":1}}],["demonstration",{"2":{"397":1}}],["demonstrating",{"2":{"151":1,"170":1,"268":1}}],["depth",{"2":{"410":1}}],["deploying",{"2":{"380":1}}],["deploy",{"0":{"377":1,"380":1},"2":{"377":3}}],["deployment",{"2":{"283":1}}],["deprecated",{"2":{"325":3,"437":1}}],["depends",{"2":{"447":1}}],["dependent",{"0":{"447":1},"2":{"447":1,"449":2}}],["dependency",{"0":{"398":1},"2":{"398":1}}],["dependencies",{"0":{"226":1},"2":{"226":1,"242":1}}],["depending",{"2":{"26":1,"176":1,"380":1}}],["developer",{"2":{"479":1}}],["developers",{"2":{"272":1,"279":2,"384":1,"408":1}}],["development",{"0":{"222":1,"227":1},"1":{"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1},"2":{"171":2,"212":1,"227":2,"234":2,"272":1,"277":1,"283":1,"333":1,"334":1,"344":1,"390":1,"415":1}}],["devtools",{"0":{"271":1,"272":1,"273":1,"279":1},"1":{"272":1,"273":1,"274":2,"275":2,"276":2,"277":2,"278":2,"279":1,"280":1},"2":{"272":2,"274":1,"278":1,"279":1,"280":2}}],["deviate",{"2":{"270":1}}],["dev",{"2":{"227":1,"233":1,"234":3,"440":1,"453":1,"466":1}}],["deutsch",{"2":{"152":1,"155":1,"156":1}}],["detecting",{"0":{"435":1}}],["detection",{"2":{"322":1,"323":4,"326":1,"361":1,"366":1,"375":1,"376":1,"430":1,"440":2,"449":1}}],["detectlocale",{"2":{"434":2}}],["detect",{"2":{"359":1,"440":1}}],["detectbrowserlanguage",{"2":{"326":1,"443":1}}],["detected",{"2":{"326":1,"429":1,"432":2,"440":1,"443":1}}],["detects",{"2":{"54":1,"322":1}}],["determine",{"2":{"407":1}}],["determined",{"2":{"149":1,"445":1}}],["determines",{"2":{"26":1,"31":1,"146":1,"301":1,"435":1}}],["detailed",{"0":{"9":1,"406":1},"1":{"407":1,"408":1},"2":{"190":2,"412":1,"421":1}}],["details",{"0":{"2":1},"2":{"37":1,"42":2,"46":1,"205":1,"242":1,"251":1,"298":3,"486":1}}],["despite",{"2":{"461":1,"466":1}}],["describing",{"2":{"460":1}}],["describe",{"2":{"244":1,"458":2}}],["descriptive",{"2":{"210":1,"221":1}}],["description>",{"2":{"240":1}}],["description",{"0":{"396":1},"2":{"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"37":1,"38":1,"42":2,"49":1,"50":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"113":1,"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"131":1,"132":1,"133":1,"134":1,"136":1,"137":1,"138":1,"165":2,"190":1,"191":1,"192":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"296":2,"323":1,"460":1}}],["designed",{"2":{"111":1,"184":1,"272":1,"309":1,"407":1,"408":1,"410":1,"430":1,"461":1,"466":1}}],["design",{"0":{"417":1},"2":{"61":1,"466":1}}],["destination",{"2":{"26":1}}],["de",{"2":{"9":1,"27":4,"31":2,"126":1,"128":1,"152":3,"155":1,"156":1,"265":1,"315":6,"327":2,"338":2,"339":3,"361":3,"366":5,"373":3,"375":3,"376":6,"377":2,"387":1,"388":1,"389":2,"391":1}}],["definitions",{"2":{"231":1}}],["defining",{"0":{"265":1,"359":1},"2":{"31":1,"357":1}}],["defineprops",{"2":{"457":1}}],["definevitestconfig",{"2":{"455":2}}],["defineeventhandler",{"2":{"432":2,"434":2}}],["definei18nroute",{"2":{"390":1}}],["definenuxtconfig",{"2":{"152":1,"299":1,"312":1,"347":2,"359":1,"361":2,"364":1,"365":1,"366":1,"373":1,"375":1,"376":1,"426":1,"467":1}}],["definenuxtplugin",{"2":{"8":2}}],["define",{"0":{"329":1},"2":{"63":1,"101":1,"174":1,"263":1,"265":1,"268":1,"270":1,"282":1,"329":2,"338":1,"359":1,"384":1,"389":2,"390":1,"391":1}}],["defines",{"2":{"31":1,"49":1,"71":1,"91":1,"253":1,"255":1,"315":1,"323":1,"326":1,"335":1,"358":1,"387":1,"438":1}}],["defined",{"2":{"18":1,"88":1,"176":1,"266":2,"332":1,"339":1,"392":1,"393":1,"429":1,"435":1}}],["defaultmessage",{"2":{"457":1}}],["defaultlocale",{"0":{"316":1},"2":{"152":1,"208":1,"312":1,"337":1,"347":2,"359":1,"361":2,"364":1,"365":1,"366":1,"373":1,"375":1,"376":1,"426":1,"454":1,"460":1,"467":1}}],["default=",{"2":{"40":1,"42":1,"43":1,"44":1,"107":1,"110":1,"166":1}}],["defaultvalue=",{"2":{"98":1}}],["defaultvalue",{"0":{"98":1},"2":{"16":2,"17":2,"18":2,"116":1,"117":1,"324":1,"460":3}}],["default",{"0":{"40":1,"56":1,"107":1,"441":1,"443":1},"2":{"8":2,"16":1,"17":1,"18":1,"38":1,"40":1,"56":1,"63":1,"64":2,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"73":1,"88":1,"96":1,"98":1,"99":1,"100":1,"101":1,"107":1,"116":1,"117":1,"125":1,"131":1,"132":1,"133":1,"134":1,"140":1,"148":1,"152":1,"188":1,"190":3,"191":1,"192":1,"199":1,"200":1,"201":1,"202":1,"203":2,"205":1,"208":2,"266":2,"299":2,"312":1,"315":3,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":2,"325":2,"326":8,"327":1,"329":1,"330":1,"331":1,"333":1,"334":1,"335":3,"336":1,"337":1,"338":1,"347":2,"358":2,"359":2,"360":1,"361":3,"364":1,"365":1,"366":2,"373":1,"375":2,"376":2,"426":1,"432":1,"434":2,"435":1,"438":2,"440":4,"441":8,"443":8,"445":1,"449":4,"455":1,"457":1,"458":2,"460":3,"467":1}}],["defaults",{"2":{"2":1,"188":1,"366":1}}],["dynamicobject",{"2":{"164":1,"165":1}}],["dynamically",{"2":{"3":1,"6":1,"8":1,"9":1,"10":1,"104":1,"129":1,"146":1,"149":1,"151":1,"164":1,"172":1,"205":1,"255":1,"429":1,"430":1,"445":1}}],["dynamic",{"0":{"44":1,"104":1,"146":1,"161":1,"162":1,"164":1,"297":1,"298":1,"301":1},"1":{"162":1,"163":1,"164":1,"165":1,"298":1},"2":{"1":1,"2":1,"5":1,"7":1,"10":1,"89":1,"97":1,"125":1,"161":1,"162":2,"163":1,"166":1,"285":1,"297":1,"298":4,"301":1,"344":1,"418":1,"445":1,"466":1}}],["cpu",{"0":{"475":1},"2":{"396":1,"399":3,"400":3,"401":2,"402":3,"403":3,"404":3,"405":3,"407":2,"408":2,"413":2,"415":2,"464":2,"475":3}}],["centralized",{"2":{"274":1}}],["certain",{"2":{"31":1,"228":1,"263":1,"282":1,"283":1,"338":2,"361":1,"433":1}}],["crucial",{"2":{"451":1}}],["critical",{"2":{"358":1,"462":1,"465":1}}],["creating",{"2":{"357":1,"372":1,"451":1}}],["creation",{"2":{"333":2}}],["created",{"2":{"462":1}}],["createfakei18n>>",{"2":{"454":1}}],["createfakei18n",{"2":{"454":2}}],["creates",{"2":{"52":1,"129":1,"190":1,"328":1,"344":1,"481":1}}],["create",{"0":{"221":1,"244":1,"372":1,"374":1,"454":1},"1":{"373":1,"375":1,"376":1},"2":{"46":1,"219":1,"221":1,"315":1,"369":1,"370":1,"373":1,"374":1,"375":1,"376":1,"382":1,"389":1,"393":1,"454":1}}],["crowdin",{"0":{"247":1,"250":1,"251":1,"253":2,"256":1,"257":1},"1":{"248":1,"249":1,"250":1,"251":1,"252":1,"253":1,"254":1,"255":1,"256":1,"257":1,"258":1,"259":1,"260":1,"261":1},"2":{"248":2,"249":2,"250":2,"251":1,"253":3,"254":4,"255":1,"256":2,"257":2,"261":2}}],["cdn",{"2":{"287":1}}],["cd",{"2":{"212":1,"220":1,"225":1,"226":2,"261":1,"415":1}}],["ci",{"2":{"212":1,"261":1,"415":1}}],["city",{"2":{"170":1,"171":1}}],["csvdir",{"2":{"201":2,"202":2}}],["csv",{"0":{"201":1,"202":1},"2":{"201":7,"202":7}}],["cssproperties",{"2":{"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1}}],["cssstyledeclaration",{"2":{"50":1}}],["css",{"2":{"38":1,"45":1,"50":1}}],["cwd",{"2":{"188":1}}],["child",{"0":{"360":1,"361":1,"365":1,"366":1,"374":1},"1":{"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"375":1,"376":1},"2":{"360":2,"361":2,"367":2,"370":1,"374":1,"375":1,"376":1}}],["choose",{"0":{"310":1},"2":{"326":1,"437":1}}],["chore",{"2":{"242":1}}],["chosen",{"2":{"192":1,"408":1}}],["chain",{"2":{"435":1}}],["challenges",{"2":{"218":1,"411":1}}],["change=",{"2":{"447":1}}],["changed",{"2":{"326":1,"440":1}}],["change",{"2":{"246":1,"335":1,"440":1}}],["changes",{"0":{"235":1,"238":1,"239":1},"1":{"236":1,"237":1,"238":1,"239":1,"240":2,"241":2,"242":2,"243":1,"244":1,"245":1,"246":1},"2":{"26":2,"190":5,"205":2,"218":1,"233":1,"236":1,"237":1,"238":1,"242":3,"243":1,"244":1,"245":1,"275":1,"277":1,"445":1,"447":2}}],["changing",{"2":{"10":1}}],["checking",{"0":{"231":1},"2":{"231":1}}],["check",{"0":{"204":1},"2":{"190":1,"204":3,"234":2,"354":1,"486":1}}],["checked",{"2":{"162":1}}],["checks",{"2":{"118":1,"204":2,"231":1,"327":1,"460":1}}],["checkout",{"2":{"46":2,"221":1}}],["cluttering",{"2":{"449":1}}],["clearly",{"2":{"270":1,"367":1,"390":1,"415":1,"459":1,"465":1}}],["clear",{"2":{"205":1,"291":1,"419":1}}],["cleaner",{"2":{"440":1,"471":1}}],["cleanliness",{"2":{"246":1}}],["cleaning",{"2":{"206":1}}],["clean",{"0":{"198":1,"307":1},"2":{"198":2,"206":1,"211":2,"246":1,"260":1,"307":1,"362":1,"378":1,"448":1}}],["closely",{"2":{"392":1}}],["close",{"2":{"390":1}}],["closed",{"2":{"71":1}}],["clone",{"0":{"220":1,"225":1},"2":{"220":2,"225":2}}],["cloud",{"2":{"193":1}}],["client",{"2":{"301":1,"429":1,"445":1,"470":1}}],["click",{"2":{"219":1,"244":1}}],["click=",{"2":{"32":1,"154":1,"170":1,"447":1}}],["cli",{"0":{"183":1,"186":1,"250":1},"1":{"184":1,"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1,"209":1,"210":1,"211":1,"212":1,"213":1,"214":1},"2":{"184":2,"186":2,"207":1,"208":1,"212":1,"214":1,"249":1,"250":2,"261":1}}],["clarify",{"2":{"429":1}}],["clarity",{"2":{"46":1,"204":1,"270":1,"305":1,"367":1,"381":1,"390":1,"459":1}}],["classes",{"2":{"45":1,"50":1}}],["class=",{"2":{"42":1,"43":3,"44":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"85":1,"447":1}}],["class",{"0":{"43":1},"2":{"38":1,"45":1,"55":1}}],["cursor",{"2":{"70":1,"74":1}}],["currency",{"2":{"19":4,"21":2,"177":1,"178":3}}],["currently",{"2":{"69":1,"77":1,"78":1,"284":1}}],["current",{"2":{"12":2,"13":1,"19":1,"20":1,"21":1,"22":2,"23":1,"24":1,"26":4,"27":1,"28":1,"30":1,"31":3,"40":1,"47":1,"50":1,"52":1,"70":1,"111":1,"113":1,"114":1,"118":1,"119":1,"124":1,"127":1,"131":1,"145":1,"146":1,"149":1,"150":1,"159":1,"177":1,"179":1,"181":2,"188":1,"268":1,"301":1,"337":1,"385":1,"392":1,"397":1,"425":1,"460":8}}],["customer",{"0":{"366":1},"2":{"363":1}}],["customregexmatcher",{"0":{"327":1}}],["custompluralrule=",{"2":{"101":1,"109":1}}],["custompluralrule",{"0":{"101":1}}],["customdisabledlinkstyle=",{"2":{"70":1,"74":1}}],["customdisabledlinkstyle",{"0":{"70":1}}],["customdropdownstyle=",{"2":{"66":1,"74":1}}],["customdropdownstyle",{"0":{"66":1}}],["customactivelinkstyle=",{"2":{"69":1,"74":1}}],["customactivelinkstyle",{"0":{"69":1}}],["customlinkstyle=",{"2":{"68":1,"74":1}}],["customlinkstyle",{"0":{"68":1}}],["customlabels=",{"2":{"63":1,"74":1}}],["customlabels",{"0":{"63":1}}],["customiconstyle=",{"2":{"71":1,"74":1}}],["customiconstyle",{"0":{"71":1}}],["customitemstyle=",{"2":{"67":1,"74":1}}],["customitemstyle",{"0":{"67":1}}],["customizations",{"2":{"367":1}}],["customization",{"2":{"75":1}}],["customizable",{"2":{"61":1,"156":1,"314":1}}],["customizing",{"0":{"299":1},"2":{"19":1,"20":1,"299":1,"370":1}}],["customized",{"2":{"74":1,"107":1,"393":1}}],["customize",{"0":{"141":1},"2":{"19":1,"20":1,"21":1,"22":1,"50":1,"55":1,"65":1,"68":1,"88":1,"110":1,"130":1,"299":1,"338":1,"357":1,"448":1}}],["custombuttonstyle=",{"2":{"65":1,"74":1}}],["custombuttonstyle",{"0":{"65":1}}],["customwrapperstyle=",{"2":{"64":1,"74":1}}],["customwrapperstyle",{"0":{"64":1}}],["custom",{"0":{"43":1,"57":1,"59":1,"74":1,"109":1,"262":1,"433":1,"434":1},"1":{"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"434":1},"2":{"31":3,"56":1,"59":1,"63":1,"66":1,"67":1,"69":1,"70":1,"71":1,"74":1,"75":1,"88":2,"89":1,"101":1,"109":1,"141":1,"143":1,"150":1,"156":1,"171":1,"178":1,"263":1,"265":3,"266":1,"268":2,"269":1,"270":2,"299":1,"317":1,"321":1,"324":1,"326":1,"327":1,"335":2,"338":6,"339":6,"385":1,"387":2,"388":1,"389":2,"390":2,"391":3,"392":2,"440":1,"458":3}}],["carefully",{"2":{"449":1}}],["caret",{"2":{"78":1}}],["cautious",{"2":{"449":1}}],["causes",{"2":{"462":1}}],["cause",{"2":{"289":1,"323":1,"446":1}}],["causing",{"2":{"283":1}}],["caching",{"0":{"302":1,"340":1,"420":1},"2":{"302":2,"340":2,"420":2,"421":2,"472":1,"480":2}}],["cached",{"2":{"283":1,"302":1,"335":3,"420":1}}],["cache",{"2":{"30":2,"340":2,"480":1}}],["call",{"2":{"289":1}}],["called",{"2":{"9":1,"27":1,"149":1,"289":1}}],["campaigns",{"2":{"269":1}}],["capturing",{"2":{"205":6}}],["capabilities",{"2":{"1":1,"278":1}}],["case",{"0":{"264":1},"1":{"265":1,"266":1},"2":{"162":1,"205":1,"264":1,"326":1,"440":1,"441":1,"442":1,"443":1}}],["cases",{"0":{"267":1,"389":1},"1":{"268":1,"269":1},"2":{"19":1,"20":1,"31":2,"59":1,"176":1}}],["category",{"2":{"46":1,"269":1,"298":3}}],["catch",{"2":{"8":1}}],["canonical",{"2":{"134":1,"138":2,"143":1,"145":2,"149":2,"150":1,"321":1,"425":3}}],["can",{"0":{"285":1,"286":1},"1":{"287":1,"288":1},"2":{"5":1,"8":1,"10":2,"20":1,"21":1,"22":1,"26":1,"31":3,"49":1,"50":1,"55":1,"56":1,"59":1,"88":2,"93":1,"94":1,"95":1,"107":1,"111":1,"135":1,"138":1,"150":1,"160":1,"172":1,"174":1,"176":1,"187":1,"194":1,"205":2,"216":1,"227":1,"229":1,"233":1,"256":1,"257":1,"266":1,"283":1,"287":1,"299":1,"302":1,"315":3,"320":1,"323":1,"327":1,"335":1,"338":1,"340":1,"342":1,"357":2,"361":1,"362":1,"369":2,"374":1,"378":1,"382":2,"387":1,"396":1,"411":1,"420":1,"427":1,"431":1,"433":1,"440":1,"446":1,"447":1,"449":1,"451":1,"460":1,"479":1}}],["cookie",{"2":{"336":1,"435":1}}],["cookies",{"2":{"323":1,"326":1,"432":1,"440":2,"445":1}}],["cover",{"2":{"238":1,"381":1}}],["coding",{"2":{"229":1,"237":1,"246":1,"272":1}}],["codebase",{"2":{"184":1,"190":1,"195":1,"218":1,"236":1,"479":1}}],["codes",{"2":{"9":1,"31":1,"63":1,"147":1,"338":1,"354":1}}],["code",{"0":{"149":1,"229":1,"236":1},"2":{"2":1,"10":1,"12":1,"14":3,"15":1,"31":1,"32":2,"35":1,"83":1,"84":1,"85":1,"86":1,"115":2,"152":3,"154":4,"170":4,"208":3,"229":1,"234":1,"236":1,"237":1,"242":2,"246":2,"253":2,"255":2,"283":1,"312":3,"315":10,"337":3,"347":4,"355":1,"359":3,"361":5,"364":2,"365":3,"366":3,"373":3,"375":4,"376":4,"387":2,"426":3,"447":7,"467":3,"472":1}}],["copyright",{"2":{"295":1}}],["copy",{"2":{"219":1}}],["core",{"2":{"470":1}}],["corner",{"2":{"219":1}}],["correct",{"2":{"150":1,"254":1,"287":1,"353":1,"378":1,"379":1,"380":2,"427":1,"446":1}}],["correctly",{"2":{"18":1,"146":1,"150":1,"288":1,"351":1,"354":1,"447":2,"458":3}}],["corresponding",{"2":{"9":1,"116":1,"192":1,"202":1,"282":1,"301":1,"338":1}}],["collaboration",{"2":{"279":1}}],["collection",{"2":{"190":1}}],["color",{"2":{"50":1,"56":3,"57":1,"65":1,"68":1,"69":1,"70":1,"71":1,"74":5}}],["could",{"2":{"176":2}}],["counts",{"2":{"172":1}}],["count",{"2":{"18":4,"43":2,"92":2,"101":4,"105":1,"109":3,"117":2,"172":1,"173":1,"174":1,"175":4,"176":2,"324":7}}],["combines",{"2":{"326":1,"443":1}}],["combined",{"2":{"191":1}}],["combination",{"2":{"315":1,"445":1}}],["comes",{"2":{"88":1}}],["com",{"2":{"54":2,"134":1,"138":1,"143":1,"184":1,"220":1,"225":1,"253":1,"288":2,"289":1,"315":6,"321":1,"377":2}}],["commerce",{"2":{"269":1,"363":1}}],["comment",{"2":{"8":1}}],["communications",{"2":{"246":1}}],["communication",{"2":{"246":1}}],["community",{"2":{"216":1}}],["commits",{"2":{"239":1,"242":1}}],["commit",{"0":{"239":1,"240":1,"242":1},"1":{"240":1,"241":1,"242":1},"2":{"239":1,"240":1,"241":1}}],["committing",{"2":{"237":1}}],["committed",{"2":{"213":1}}],["commas",{"2":{"192":1}}],["commands",{"0":{"189":1},"1":{"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1},"2":{"187":1,"212":1,"232":1,"261":1}}],["command",{"0":{"190":1,"191":1,"192":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1},"1":{"193":1,"194":1},"2":{"184":1,"186":1,"190":3,"191":1,"192":3,"193":1,"194":1,"201":2,"202":1,"203":1,"204":4,"205":3,"211":1,"227":2,"228":2,"230":1,"233":1,"251":1,"256":2,"257":1,"311":1}}],["commonly",{"2":{"367":1}}],["common",{"0":{"188":1,"234":1,"281":1,"352":1},"1":{"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"353":1,"354":1,"355":1},"2":{"35":1,"246":1,"266":1,"289":3,"295":1,"372":1,"449":1,"466":1}}],["computations",{"2":{"472":1}}],["complicating",{"2":{"315":1}}],["completing",{"2":{"351":1}}],["complete",{"2":{"470":1}}],["completely",{"2":{"339":1}}],["completed",{"2":{"257":1,"445":1}}],["complexity",{"2":{"270":1,"367":1,"369":1,"378":1,"382":1,"418":1}}],["complex",{"0":{"176":1},"2":{"170":1,"176":1,"205":1,"298":1,"304":1,"369":1,"382":1,"411":1}}],["comparison",{"0":{"402":1,"405":1,"412":1,"463":1},"1":{"413":1,"414":1,"415":1,"464":1,"465":1},"2":{"412":1}}],["compares",{"2":{"203":1,"396":1,"410":1}}],["compared",{"2":{"191":1,"197":1,"203":1,"309":1}}],["compare",{"2":{"22":1,"244":1}}],["compatibility",{"2":{"349":1}}],["compact",{"2":{"310":1,"461":1,"466":1}}],["company",{"2":{"295":1}}],["comprehensive",{"0":{"170":1},"1":{"171":1},"2":{"408":1}}],["composables",{"0":{"289":1},"2":{"289":4}}],["composable",{"0":{"34":1,"111":1,"129":1},"1":{"112":1,"113":1,"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"123":1,"124":1,"125":1,"126":1,"127":1,"128":1,"130":1,"131":1,"132":1,"133":1,"134":1,"135":1,"136":1,"137":1,"138":1,"139":1,"140":1,"141":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1},"2":{"111":1,"112":1,"129":1,"130":1,"135":1,"145":1,"146":1,"147":2,"148":1,"149":2,"150":1,"289":1,"457":1}}],["components",{"2":{"46":2,"89":1,"104":1,"150":1,"151":1,"190":1,"228":1,"284":1,"384":2,"390":1,"417":1,"451":1,"458":1,"459":1,"466":1,"482":1}}],["component",{"0":{"32":1,"35":1,"47":1,"61":1,"89":1,"156":1,"383":1,"391":1,"457":1},"1":{"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1,"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1},"2":{"32":1,"35":1,"45":1,"47":3,"54":1,"55":1,"59":1,"60":1,"61":2,"75":2,"88":1,"89":2,"100":1,"104":3,"148":1,"156":1,"157":1,"166":1,"268":1,"285":1,"289":1,"384":1,"390":2,"391":1,"392":4,"393":2,"457":2,"458":2}}],["conditions",{"2":{"412":1,"463":1}}],["conditionally",{"2":{"161":1}}],["conditional",{"0":{"108":1}}],["conducted",{"2":{"407":1,"412":1,"463":1}}],["confusion",{"2":{"210":1,"259":1}}],["confirm",{"2":{"353":1,"380":1}}],["confirms",{"2":{"204":1}}],["configures",{"2":{"385":1}}],["configure",{"0":{"379":1,"455":1},"2":{"299":1,"315":1,"455":1}}],["configured",{"2":{"14":1,"146":1,"207":1,"302":1,"379":1,"420":1}}],["configuring",{"2":{"184":1,"380":1}}],["configurations",{"0":{"350":1},"2":{"194":1,"277":1,"350":2,"357":1,"370":1,"372":1,"378":1,"381":1,"451":1,"453":1}}],["configuration",{"0":{"194":1,"207":1,"252":1,"253":1,"254":1,"255":1,"314":1,"347":1,"358":1,"359":1,"363":1,"364":1,"373":1,"375":1,"376":1,"426":1,"454":1},"1":{"208":1,"253":1,"254":1,"255":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"359":1,"364":1,"365":1,"366":1},"2":{"7":1,"26":1,"187":1,"207":1,"248":1,"251":1,"253":2,"256":2,"257":1,"266":1,"315":1,"329":1,"343":1,"347":2,"353":1,"354":1,"355":1,"357":1,"358":2,"359":1,"360":1,"361":2,"362":1,"366":1,"367":2,"370":1,"372":2,"373":1,"374":1,"375":2,"376":2,"377":3,"378":1,"381":2,"418":1,"423":1,"427":1,"429":1,"454":1,"455":1}}],["config",{"0":{"208":1},"2":{"13":1,"114":1,"187":1,"207":1,"299":1,"312":1,"347":2,"359":1,"361":2,"364":1,"365":2,"366":2,"373":2,"375":2,"376":2,"426":1,"455":2,"467":1}}],["convention",{"2":{"297":1}}],["conventional",{"2":{"242":1}}],["conventions",{"2":{"236":1,"263":1,"305":1}}],["convenience",{"2":{"111":1,"272":1}}],["convenient",{"2":{"35":1}}],["converts",{"2":{"199":1,"298":1}}],["concurrent",{"2":{"407":1}}],["concepts",{"2":{"289":1}}],["concerns",{"2":{"10":1,"381":1}}],["concluded",{"2":{"284":1}}],["conclusion",{"0":{"382":1,"448":1},"1":{"449":1},"2":{"44":1}}],["consumes",{"2":{"462":1}}],["consumption",{"0":{"401":1,"413":1,"464":1},"2":{"310":2,"340":1,"407":1,"408":1,"415":1,"462":1,"476":1}}],["consulting",{"2":{"171":2}}],["consolidating",{"2":{"397":1}}],["consolidates",{"2":{"279":1}}],["console",{"2":{"8":1,"113":1,"115":1,"116":1,"117":1,"118":1,"136":1,"137":1,"138":1,"289":1}}],["consistency",{"2":{"204":1,"239":1,"270":1,"367":1,"379":1,"449":1}}],["consistent",{"0":{"210":1,"259":1,"305":1},"2":{"46":2,"210":1,"259":1,"270":1,"297":1,"305":1,"429":1,"442":2,"449":1,"459":1}}],["considered",{"2":{"284":1}}],["consider",{"2":{"15":1,"213":1,"236":1,"445":1,"449":1}}],["constrained",{"2":{"408":1}}],["const",{"2":{"8":3,"23":1,"24":1,"27":3,"31":2,"32":1,"33":1,"34":2,"44":3,"101":1,"113":1,"115":1,"116":1,"117":1,"118":1,"121":1,"124":1,"125":1,"127":1,"148":1,"154":1,"157":1,"162":1,"164":1,"170":1,"173":1,"178":1,"180":1,"182":1,"268":1,"324":2,"389":2,"391":1,"432":1,"434":3,"454":1,"457":3,"458":4}}],["contributing",{"2":{"216":1}}],["contribution",{"0":{"215":1,"246":1},"1":{"216":1,"217":1,"218":1,"219":1,"220":1,"221":1},"2":{"241":2}}],["contributions",{"0":{"214":1},"2":{"216":2}}],["contribute",{"2":{"214":1}}],["controls",{"2":{"88":1}}],["controlling",{"2":{"31":2,"389":1}}],["control",{"0":{"280":1},"2":{"31":2,"190":1,"213":1,"263":1,"385":1,"390":1,"397":1,"437":2,"438":1,"448":1}}],["continue",{"2":{"190":1,"485":1}}],["contact",{"2":{"170":5,"171":4,"295":2,"440":1}}],["contain",{"2":{"295":1,"313":2,"367":1}}],["contains",{"2":{"64":1,"66":1,"104":1,"136":1,"137":1,"138":1,"445":1}}],["containing",{"2":{"2":1,"49":1,"112":1,"149":1,"188":1,"190":1,"199":1,"202":1,"387":1}}],["content=",{"2":{"85":1,"86":1}}],["content`",{"2":{"44":1}}],["content",{"0":{"44":1,"59":1,"85":1,"86":1,"104":1,"447":1},"2":{"10":2,"31":2,"40":1,"45":1,"59":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":13,"89":2,"96":1,"104":1,"110":1,"129":1,"137":1,"149":1,"150":1,"166":1,"170":1,"171":1,"190":2,"269":1,"276":1,"295":1,"296":2,"304":1,"384":1,"389":2,"390":1,"392":1,"393":1,"423":1,"425":2,"429":1,"431":1,"445":1,"447":2,"449":2,"481":1}}],["contexts",{"0":{"269":1},"2":{"289":2,"357":1}}],["context",{"0":{"306":1},"2":{"1":1,"2":1,"9":1,"190":6,"289":2,"361":1,"391":1,"429":1,"483":1}}],["nitro",{"2":{"283":1,"287":1}}],["npm",{"2":{"186":1,"223":1,"250":1,"440":2}}],["npmjs",{"2":{"184":1}}],["natively",{"2":{"278":1}}],["naming",{"0":{"210":1,"259":1},"2":{"305":1}}],["names",{"2":{"20":1,"164":1,"221":1,"284":1}}],["name",{"2":{"13":1,"15":4,"23":1,"26":2,"28":2,"29":1,"32":1,"44":1,"49":1,"87":1,"97":1,"104":1,"114":1,"116":1,"125":1,"157":1,"205":5,"221":1,"243":1,"268":2,"282":3,"284":1,"285":1,"336":1,"338":1,"349":3,"446":1,"460":4}}],["named",{"2":{"9":1,"26":4,"298":3,"446":1,"449":1}}],["navigating",{"2":{"227":1}}],["navigation",{"0":{"157":1,"158":1},"1":{"158":1,"159":1,"160":1},"2":{"50":1,"268":1,"282":1,"295":1,"349":1,"351":1}}],["navigational",{"2":{"31":1,"389":1,"392":1}}],["navigate",{"2":{"219":1}}],["nav",{"2":{"170":4,"171":1}}],["nav>",{"2":{"170":2}}],["nachricht",{"2":{"27":2}}],["non",{"2":{"279":1,"326":1,"441":1,"443":4,"448":1}}],["nonexistentkey",{"2":{"98":1}}],["none",{"2":{"68":1,"74":1,"87":7}}],["nor",{"2":{"242":1}}],["noreferrer",{"2":{"54":1}}],["node",{"2":{"223":1,"398":1,"434":1}}],["noopener",{"2":{"54":1}}],["no",{"0":{"440":1,"445":1,"447":1},"2":{"31":1,"38":1,"56":1,"101":1,"107":1,"173":1,"174":1,"175":1,"176":1,"204":1,"231":1,"238":1,"242":1,"316":1,"326":1,"387":1,"389":1,"440":2,"445":1,"447":1,"449":2}}],["nouvelles",{"2":{"24":1,"27":2,"29":1}}],["now",{"2":{"22":1,"55":1,"182":2,"455":1,"458":1,"467":1,"470":1,"480":1}}],["noticeable",{"2":{"462":1}}],["notifications",{"2":{"172":1}}],["note",{"0":{"397":1},"2":{"315":1,"326":1}}],["notes",{"0":{"150":1},"2":{"190":1,"315":1}}],["nothing",{"2":{"108":1}}],["nothing|you",{"2":{"92":1}}],["not",{"0":{"286":1,"289":1,"353":1,"354":1},"1":{"287":1,"288":1},"2":{"2":1,"16":1,"17":1,"18":1,"26":1,"31":1,"70":1,"74":1,"98":1,"100":1,"101":1,"116":1,"117":1,"192":2,"204":1,"213":1,"238":1,"282":1,"283":1,"287":2,"289":2,"306":1,"315":3,"326":3,"337":1,"338":2,"339":1,"344":1,"355":1,"369":1,"374":1,"382":1,"397":2,"429":1,"440":1,"447":1,"466":1}}],["numeric",{"2":{"20":2,"21":1,"180":2}}],["number=",{"2":{"93":1}}],["numbers",{"2":{"19":1,"177":2,"205":1}}],["numberformat",{"2":{"19":1,"21":1,"177":1}}],["numberformatoptions",{"2":{"19":4,"21":3}}],["number",{"0":{"93":1,"177":1,"178":1},"1":{"178":1},"2":{"16":1,"18":2,"19":5,"20":2,"21":6,"22":2,"92":2,"93":6,"94":2,"95":2,"97":1,"101":2,"116":2,"117":1,"172":1,"173":2,"177":1,"178":2,"191":1,"324":5,"344":1,"418":1,"460":1,"466":1,"478":1}}],["null",{"2":{"8":1,"13":1,"16":1,"27":3,"101":1,"114":1,"116":1,"434":1,"457":1}}],["nuxtjs",{"2":{"208":1,"398":1}}],["nuxtlinkprops",{"2":{"49":1}}],["nuxtlink>",{"2":{"32":1,"268":2,"349":1}}],["nuxtlink",{"0":{"285":1,"349":1},"2":{"32":1,"47":1,"68":1,"268":2,"285":1,"349":2}}],["nuxtapp",{"2":{"8":2,"9":1,"289":2}}],["nuxt",{"0":{"151":1,"183":1,"186":1,"208":1,"262":1,"271":1,"272":1,"273":1,"278":1,"284":1,"289":1,"308":1,"310":1,"341":2,"346":1,"349":1,"356":1,"368":1,"383":1,"422":1,"428":1,"436":1,"450":1,"453":1,"462":1,"470":1},"1":{"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1,"184":1,"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1,"209":1,"210":1,"211":1,"212":1,"213":1,"214":1,"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"272":1,"273":1,"274":2,"275":2,"276":2,"277":2,"278":2,"279":1,"280":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"342":2,"343":2,"344":2,"345":2,"346":2,"347":2,"348":2,"349":2,"350":2,"351":2,"352":2,"353":2,"354":2,"355":2,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"423":1,"424":1,"425":1,"426":1,"427":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"435":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"463":1,"464":1,"465":1},"2":{"1":1,"4":1,"6":1,"8":1,"31":1,"32":1,"35":1,"47":1,"61":1,"80":1,"89":1,"104":3,"107":1,"111":2,"129":1,"135":1,"147":1,"151":2,"152":2,"161":1,"172":1,"184":4,"186":2,"187":3,"191":1,"207":4,"208":1,"212":1,"214":2,"216":1,"219":1,"220":2,"225":3,"227":1,"233":1,"244":1,"246":1,"263":1,"272":2,"278":2,"279":1,"280":2,"282":1,"284":4,"285":3,"289":12,"291":2,"292":1,"297":1,"299":3,"301":1,"302":1,"309":2,"310":1,"311":2,"312":2,"314":1,"329":1,"330":1,"335":1,"340":1,"342":5,"343":2,"344":6,"346":3,"347":7,"349":3,"350":2,"357":1,"359":1,"361":2,"362":1,"364":1,"365":2,"366":2,"369":1,"370":1,"373":2,"375":2,"376":2,"382":1,"384":2,"391":1,"393":1,"398":2,"407":2,"408":1,"410":3,"411":1,"412":3,"413":2,"414":2,"415":1,"417":1,"418":1,"420":1,"421":1,"423":2,"425":1,"426":2,"429":3,"437":1,"451":1,"453":2,"454":2,"455":1,"459":1,"460":2,"461":3,"462":3,"463":1,"464":2,"465":3,"466":1,"467":6,"471":1}}],["negatively",{"2":{"462":1}}],["netlify",{"2":{"283":2}}],["neither",{"2":{"242":1}}],["necessary",{"2":{"54":1,"187":1,"228":1,"289":1,"292":1,"296":1,"301":1,"354":1,"367":1,"419":1,"453":1}}],["nesting",{"2":{"46":1}}],["nested",{"0":{"170":1,"171":1,"297":1},"1":{"171":1,"298":1},"2":{"46":1,"190":2,"297":1,"298":4,"429":1,"482":1}}],["next",{"2":{"8":1,"226":1,"454":1}}],["need",{"2":{"225":1,"249":1,"263":1,"275":1,"302":1,"326":1,"363":1,"369":1,"378":1,"382":1,"420":2,"421":1,"427":1,"433":1,"448":1,"449":1,"453":1}}],["needs",{"2":{"5":1,"10":1,"75":1,"101":1,"171":1,"176":1,"278":1,"284":1,"296":2,"361":1,"448":1}}],["needing",{"2":{"5":1}}],["needed",{"2":{"1":1,"10":1,"26":1,"194":1,"208":1,"280":1,"340":1,"374":1,"387":1,"429":1}}],["newtranslations",{"2":{"30":2,"119":1}}],["news",{"0":{"469":1},"1":{"470":1,"471":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1},"2":{"23":2,"24":1,"27":4,"29":1}}],["new",{"0":{"438":1,"472":1},"2":{"1":1,"2":1,"9":1,"20":1,"22":1,"23":1,"24":1,"26":1,"29":1,"30":3,"54":1,"180":2,"182":2,"190":2,"205":1,"216":1,"221":2,"236":1,"242":1,"280":1,"314":1,"315":2,"349":1,"434":1,"437":1,"448":1,"471":1,"472":1,"474":2,"478":1,"482":1}}],["ms",{"2":{"403":3,"404":3,"405":3,"414":2,"465":2,"477":4}}],["mb",{"2":{"399":3,"400":3,"401":2,"402":3,"403":3,"404":3,"405":3,"413":5,"414":2,"464":5,"465":2,"476":4}}],["mymemory",{"2":{"193":2}}],["mywebsite",{"2":{"143":1}}],["multi",{"0":{"368":1,"371":1},"1":{"369":1,"370":1,"371":1,"372":2,"373":2,"374":2,"375":2,"376":2,"377":2,"378":2,"379":2,"380":2,"381":1,"382":1},"2":{"298":1,"369":1,"382":1}}],["multiple",{"0":{"378":1},"2":{"170":1,"173":1,"193":1,"204":1,"248":1,"274":1,"279":1,"295":1,"362":1,"369":1,"378":1,"415":1}}],["multilingual",{"2":{"10":1,"280":1,"423":2}}],["must",{"2":{"27":1}}],["migrate",{"0":{"343":1}}],["migrating",{"2":{"342":1}}],["migration",{"0":{"341":1,"345":1},"1":{"342":1,"343":1,"344":1,"345":1,"346":2,"347":2,"348":2,"349":2,"350":2,"351":2,"352":1,"353":1,"354":1,"355":1},"2":{"344":1,"351":1}}],["might",{"2":{"264":1,"265":1,"282":1,"283":1,"289":1,"307":1,"359":1,"360":2,"362":1,"363":1}}],["middleware",{"2":{"283":1,"289":1,"430":1,"431":1,"433":1,"435":1}}],["mismatches",{"2":{"445":1,"447":1,"449":1}}],["mismatch",{"0":{"445":1},"2":{"445":2}}],["mission",{"2":{"296":1}}],["missing",{"0":{"355":1},"2":{"192":2,"197":1,"203":1,"206":1,"283":1}}],["miss",{"2":{"283":1}}],["miscellaneous",{"2":{"242":1}}],["mind",{"2":{"410":1,"444":1,"461":1}}],["min",{"2":{"399":2,"400":2,"403":3,"404":3,"405":3}}],["minimizing",{"2":{"408":1,"415":1,"461":1,"474":1}}],["minimalist",{"0":{"417":1},"2":{"417":1,"466":1}}],["minimal",{"2":{"310":1,"411":1,"480":1}}],["minimumfractiondigits",{"2":{"178":1}}],["minimum",{"2":{"19":1}}],["minor",{"2":{"270":1}}],["minute",{"2":{"180":1}}],["minutes",{"2":{"22":2,"181":1,"182":1}}],["micro",{"0":{"151":1,"183":1,"186":1,"262":1,"271":1,"273":1,"284":1,"308":1,"310":1,"341":1,"346":1,"356":1,"368":1,"383":1,"400":1,"404":1,"405":1,"422":1,"428":1,"450":1,"453":1,"462":1,"470":1},"1":{"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1,"184":1,"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1,"209":1,"210":1,"211":1,"212":1,"213":1,"214":1,"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"272":1,"273":1,"274":2,"275":2,"276":2,"277":2,"278":2,"279":1,"280":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"342":1,"343":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"350":1,"351":1,"352":1,"353":1,"354":1,"355":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"401":1,"423":1,"424":1,"425":1,"426":1,"427":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"435":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"463":1,"464":1,"465":1},"2":{"1":1,"4":1,"35":1,"47":1,"61":1,"89":1,"111":1,"129":1,"151":1,"152":2,"161":1,"172":1,"184":2,"186":3,"187":1,"190":4,"191":2,"192":2,"194":1,"195":2,"196":2,"197":2,"198":2,"199":2,"200":2,"201":2,"202":2,"203":2,"204":2,"205":4,"206":6,"207":1,"208":1,"212":1,"214":1,"216":1,"219":1,"220":2,"225":3,"244":1,"246":1,"263":1,"272":1,"278":1,"280":1,"282":1,"284":1,"285":1,"291":2,"292":1,"297":1,"299":2,"301":1,"302":1,"309":1,"310":1,"311":1,"312":1,"314":1,"327":1,"340":1,"342":2,"343":1,"344":4,"346":2,"347":3,"350":1,"357":1,"369":1,"382":1,"384":1,"395":2,"396":2,"397":3,"398":1,"401":1,"402":1,"407":1,"408":1,"410":2,"411":1,"412":2,"413":1,"414":1,"415":1,"417":1,"418":1,"420":1,"421":1,"423":2,"425":1,"426":1,"429":2,"451":1,"453":2,"454":1,"459":1,"460":2,"461":1,"462":1,"463":1,"464":1,"465":2,"466":1,"467":3,"471":1,"483":2}}],["media",{"2":{"425":1}}],["measure",{"2":{"407":1}}],["measures",{"2":{"407":1}}],["mean",{"2":{"414":4,"465":4}}],["meaning",{"2":{"315":2}}],["meaningful",{"2":{"46":1}}],["means",{"2":{"287":1,"315":1,"340":1}}],["merging",{"2":{"472":1,"480":2}}],["mergetranslations",{"2":{"454":1}}],["merged",{"2":{"245":1}}],["merge",{"2":{"30":1,"472":1}}],["merges",{"2":{"2":1,"4":1,"9":1,"30":1,"119":1,"480":1}}],["merely",{"2":{"397":1}}],["mechanism",{"0":{"340":1},"2":{"340":1}}],["memory",{"0":{"476":1},"2":{"309":1,"310":2,"343":1,"396":1,"399":3,"400":3,"401":2,"402":3,"403":3,"404":3,"405":3,"407":3,"408":2,"411":2,"413":3,"414":3,"415":3,"462":4,"464":3,"465":3,"466":1,"471":1,"474":1,"476":3,"480":1}}],["members",{"2":{"270":1}}],["meet",{"2":{"171":1,"296":1,"374":1}}],["meets",{"2":{"10":1}}],["message",{"0":{"240":1},"2":{"107":1,"117":2,"173":2,"239":1,"240":1,"241":1,"268":1,"289":2,"432":1,"434":1,"457":6,"458":11}}],["messages",{"2":{"16":1,"17":1,"169":1,"172":1,"429":1,"457":1}}],["menu",{"2":{"65":1,"79":1,"80":1,"87":2,"295":1}}],["menus",{"2":{"50":1,"295":1,"466":1}}],["metrics",{"2":{"415":1}}],["meticulously",{"2":{"327":1}}],["metadata",{"2":{"425":1}}],["metabaseurl",{"0":{"321":1}}],["meta",{"0":{"137":1,"145":1,"318":1},"2":{"44":3,"129":2,"132":1,"133":1,"135":1,"137":3,"142":1,"149":3,"152":1,"241":1,"312":1,"318":2,"321":2,"344":1,"347":1,"350":1,"355":1,"359":2,"361":1,"364":1,"365":2,"366":1,"373":1,"423":1,"425":2,"426":2,"427":2,"467":1}}],["methodology",{"2":{"407":1,"408":1}}],["method",{"0":{"386":1},"2":{"26":1,"31":1,"284":1,"301":1,"370":1,"384":1,"460":1}}],["methods",{"0":{"11":1,"460":1},"1":{"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1},"2":{"27":1,"32":1,"111":2,"112":1,"460":1}}],["mount",{"2":{"458":4}}],["mocknuxtimport",{"2":{"454":2}}],["mock",{"0":{"454":1},"2":{"451":1,"453":1,"454":2,"455":1,"459":2}}],["monitors",{"2":{"407":1}}],["month",{"2":{"20":1,"180":1}}],["most",{"2":{"367":1}}],["move",{"2":{"348":1}}],["moves",{"2":{"283":1}}],["moving",{"2":{"343":1}}],["mobile",{"2":{"171":1}}],["more",{"0":{"176":1},"2":{"10":1,"60":2,"175":1,"176":1,"205":1,"242":1,"272":1,"289":1,"296":1,"298":1,"315":1,"325":1,"343":1,"384":1,"396":1,"397":1,"411":1,"414":1,"415":1,"427":1,"437":2,"448":1,"465":1,"470":1,"471":1,"472":1,"480":2,"486":1}}],["modernmt",{"2":{"193":2}}],["model",{"2":{"192":1}}],["mode",{"2":{"190":2,"195":1,"234":1,"344":1,"445":1,"449":1,"466":1}}],["modular",{"0":{"362":1,"363":1},"1":{"364":1,"365":1,"366":1},"2":{"46":1,"270":1,"278":1,"360":1,"362":1,"366":1,"384":1}}],["module",{"0":{"228":1,"314":1,"450":1},"1":{"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1},"2":{"7":2,"14":1,"184":1,"207":1,"227":1,"228":2,"234":1,"272":1,"298":1,"301":1,"309":1,"311":1,"312":1,"314":1,"331":1,"332":1,"335":1,"343":1,"349":1,"407":2,"408":1,"412":1,"414":1,"417":1,"419":1,"425":5,"427":1,"451":1,"460":1,"461":2,"462":2,"465":1,"466":2,"467":1}}],["modules",{"2":{"6":1,"152":1,"208":1,"312":1,"347":2,"410":1,"418":1,"426":1,"463":1,"466":1,"467":1}}],["modifies",{"2":{"374":1}}],["modifiers",{"0":{"284":1},"2":{"284":4}}],["modified",{"2":{"205":1}}],["modifications",{"0":{"10":1},"2":{"7":1,"8":1,"205":1}}],["modify",{"2":{"6":1,"10":2,"360":1}}],["modifying",{"0":{"6":1},"1":{"7":1,"8":1,"9":1,"10":1},"2":{"190":2,"326":1,"370":1,"440":1}}],["major",{"0":{"470":1}}],["marketing",{"2":{"269":1}}],["margin",{"2":{"67":1,"74":1}}],["maps",{"2":{"255":1}}],["mapped",{"2":{"253":1}}],["machine",{"2":{"220":1,"223":1,"225":1,"249":1}}],["matching",{"2":{"327":1}}],["match",{"2":{"205":1,"269":1}}],["matcher",{"2":{"327":1}}],["matched",{"2":{"205":2}}],["matches",{"2":{"50":1,"177":1,"205":2,"208":1,"327":1,"353":1}}],["maximizing",{"0":{"421":1}}],["maximum",{"2":{"407":1,"475":1}}],["max",{"2":{"192":1,"194":1,"399":2,"400":2,"401":4,"402":4,"403":3,"404":3,"405":3,"413":4,"414":2,"464":4,"465":2,"475":1,"476":2,"477":1}}],["made",{"2":{"190":1,"205":1}}],["makes",{"2":{"306":1}}],["make",{"2":{"186":1,"236":1,"238":1,"245":1,"367":1,"421":1,"459":1}}],["making",{"0":{"235":1},"1":{"236":1,"237":1,"238":1,"239":1,"240":1,"241":1,"242":1,"243":1,"244":1,"245":1,"246":1},"2":{"1":1,"10":1,"31":1,"59":1,"203":1,"205":1,"218":1,"239":1,"246":1,"248":1,"256":1,"272":1,"309":1,"315":2,"392":1,"408":1,"466":2}}],["manipulation",{"2":{"447":1}}],["manual",{"2":{"427":1}}],["manually",{"2":{"282":1,"427":1,"433":1}}],["manner",{"2":{"297":1}}],["many",{"2":{"176":2,"191":1,"396":1}}],["managing",{"2":{"112":1,"261":1,"272":1,"276":1,"280":1,"291":1,"305":1,"384":1,"423":1}}],["manages",{"2":{"407":1,"425":1}}],["manageable",{"2":{"260":1,"315":1,"429":1}}],["managed",{"2":{"254":1,"438":1}}],["management",{"0":{"274":1},"2":{"10":1,"111":1,"190":1,"200":1,"213":1,"272":1,"279":1,"343":1,"344":1,"369":1,"382":1,"426":1,"481":1}}],["manage",{"2":{"8":1,"31":1,"129":1,"184":2,"214":1,"248":1,"274":1,"279":1,"306":1,"326":1,"357":1,"392":1,"393":1,"437":1}}],["may",{"2":{"161":1,"284":2,"287":1,"289":1,"323":1,"397":1,"445":1,"446":1,"447":3}}],["mainheader",{"2":{"170":1,"171":1}}],["maintainability",{"2":{"470":1,"472":1}}],["maintainable",{"2":{"10":1,"307":1,"369":1,"382":1,"384":1,"390":1,"480":1}}],["maintaining",{"2":{"270":1,"278":1,"291":1,"379":1,"443":1}}],["maintainer",{"2":{"245":1,"284":1}}],["maintains",{"2":{"190":2,"482":1}}],["maintain",{"2":{"46":1,"204":2,"254":1,"270":1,"289":1,"305":1,"362":1,"367":1,"370":1,"378":1,"381":1,"390":1,"459":1,"466":1}}],["maintenance",{"0":{"211":1,"260":1},"2":{"10":1,"315":1,"390":1}}],["main",{"2":{"10":1,"44":1,"149":1,"171":1,"244":1,"245":1,"363":1,"396":1,"407":2}}],["slowdowns",{"2":{"462":1}}],["slow",{"2":{"411":1,"462":1}}],["slot",{"0":{"40":1,"59":1,"107":1},"2":{"40":2,"83":1,"84":1,"85":1,"86":1,"87":1,"107":2}}],["slots",{"0":{"39":1,"75":1,"87":1,"104":1,"110":1,"166":1},"1":{"40":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"167":1,"168":1,"169":1},"2":{"40":1,"59":1,"75":2,"89":1,"104":1,"110":1}}],["slightly",{"2":{"396":1}}],["smart",{"2":{"480":1}}],["small",{"2":{"421":1,"466":1}}],["smaller",{"2":{"343":1,"413":1,"415":1,"464":1}}],["smoother",{"2":{"470":1,"479":1}}],["smoothly",{"2":{"342":1}}],["smooth",{"2":{"214":1}}],["ssr",{"0":{"286":1,"287":1},"1":{"287":1,"288":1},"2":{"283":2,"288":1,"340":1}}],["s00d",{"2":{"225":1,"244":1}}],["saw",{"2":{"477":1}}],["sa",{"2":{"312":1,"315":1,"359":1,"426":1,"467":1}}],["safe",{"2":{"279":1}}],["saving",{"2":{"279":1}}],["saved",{"2":{"201":1,"283":1}}],["save",{"2":{"200":1,"276":1,"453":1}}],["saves",{"2":{"199":1,"257":1}}],["sandbox",{"2":{"233":1}}],["sample",{"2":{"233":1}}],["same",{"2":{"160":1,"196":1,"203":1,"204":2,"302":1,"340":1,"412":1,"463":1}}],["systran",{"2":{"193":2}}],["systems",{"2":{"213":1}}],["system",{"2":{"186":1,"291":1,"340":1,"370":1,"429":1}}],["synchronization",{"2":{"212":1}}],["synchronizing",{"2":{"206":1}}],["synchronizes",{"2":{"196":1}}],["synchronize",{"2":{"184":1}}],["sync",{"0":{"196":1},"2":{"196":2,"206":1}}],["syntax",{"2":{"190":1}}],["social",{"2":{"425":1}}],["so",{"2":{"284":1,"339":1}}],["sourced",{"2":{"429":1}}],["source",{"0":{"256":1},"2":{"253":3,"254":2,"255":2,"256":2,"261":1}}],["sources",{"2":{"248":1,"256":1}}],["solution",{"2":{"282":1,"289":4,"369":1,"382":1,"385":1}}],["solutions",{"0":{"281":1},"1":{"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1},"2":{"213":1,"289":1,"309":1,"410":1,"461":1}}],["solid",{"2":{"66":1,"74":1}}],["software",{"2":{"171":1,"201":1}}],["sometimes",{"2":{"283":1}}],["some",{"2":{"161":1,"193":1,"194":1,"284":1,"310":1,"444":1,"448":1}}],["situations",{"2":{"442":1}}],["sites",{"2":{"269":2,"423":1}}],["site",{"2":{"147":1,"165":1,"190":2,"234":3,"357":1,"360":1,"361":1,"363":1,"423":3,"427":1,"445":1,"485":1,"486":1}}],["sizes",{"2":{"343":1,"461":1}}],["size",{"2":{"310":2,"411":1,"413":2,"415":2,"421":1,"461":1,"462":1,"464":2,"466":1}}],["simulating",{"2":{"414":1}}],["simulates",{"2":{"407":1}}],["simulate",{"2":{"407":1}}],["similarly",{"2":{"376":1}}],["similar",{"2":{"284":1}}],["simplicity",{"2":{"449":1}}],["simplified",{"2":{"343":1,"472":1,"479":1}}],["simplifies",{"2":{"147":1,"192":1,"291":1,"369":1,"397":1,"417":1,"423":1}}],["simplifying",{"2":{"378":1}}],["simplify",{"2":{"276":1,"390":1}}],["simpler",{"2":{"315":1}}],["simple",{"2":{"49":1,"149":1,"190":1,"205":2,"268":1,"367":1,"457":1,"461":1}}],["side",{"0":{"428":1,"430":1},"1":{"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"435":1},"2":{"283":1,"301":1,"340":1,"429":3,"430":1,"445":1,"470":1,"480":1}}],["significant",{"2":{"410":1,"461":1,"462":1,"471":1}}],["significantly",{"2":{"270":1,"284":1,"310":1,"340":1,"342":1,"415":1,"418":1,"465":1,"476":1}}],["signature",{"0":{"386":1}}],["sign",{"2":{"190":2,"485":1,"486":1}}],["silent",{"2":{"188":1}}],["single",{"2":{"170":1,"274":1,"279":1,"397":1}}],["shrinking",{"2":{"461":1}}],["sharing",{"2":{"425":1}}],["shared",{"2":{"295":1,"313":1}}],["share",{"2":{"204":1,"285":1,"328":1}}],["shipping",{"2":{"46":1}}],["showcase",{"2":{"397":1,"463":1}}],["showerror",{"2":{"289":1}}],["showing",{"2":{"191":1,"205":1}}],["shows",{"2":{"190":1,"396":1}}],["show",{"2":{"190":2,"205":1}}],["shop",{"2":{"46":2}}],["should",{"2":{"31":1,"240":1,"253":1,"293":1,"315":2,"323":1,"326":1,"338":1,"367":1,"381":1,"438":1}}],["short",{"2":{"20":1,"240":1}}],["scope>",{"2":{"240":1}}],["scope",{"2":{"195":1}}],["scoped",{"2":{"40":1}}],["scanning",{"2":{"482":1}}],["scans",{"2":{"190":2,"205":1,"481":1}}],["scalability",{"2":{"408":1,"479":1}}],["scalable",{"2":{"10":1,"291":1,"362":1,"369":1,"382":1}}],["scale",{"2":{"310":1,"369":1,"382":1,"397":1,"408":1,"411":1,"466":1}}],["scenario",{"2":{"160":1}}],["scenarios",{"2":{"89":1,"161":1,"205":1,"387":1,"397":1,"407":1,"408":1}}],["scripts",{"0":{"234":1},"2":{"242":1}}],["script>",{"2":{"32":1,"44":1,"148":1,"154":1,"157":1,"162":1,"164":1,"170":1,"173":1,"178":1,"180":1,"182":1,"268":1,"391":1,"457":1}}],["script",{"2":{"32":1,"44":1,"148":1,"149":1,"154":1,"157":1,"162":1,"164":1,"170":1,"173":1,"178":1,"180":1,"182":1,"190":1,"268":1,"391":1,"395":1,"396":1,"457":2}}],["speeding",{"2":{"418":1}}],["speed",{"2":{"411":1,"421":1}}],["spec",{"2":{"395":1,"455":1,"458":1}}],["special",{"2":{"329":1,"330":1,"351":1}}],["specify",{"0":{"143":1},"2":{"31":1,"149":1,"188":1,"194":1,"201":1,"202":1,"208":1,"288":1,"338":1,"433":1}}],["specifying",{"2":{"31":1}}],["specifies",{"2":{"92":1,"96":1,"132":1,"254":1,"255":1,"315":1,"317":1,"323":1,"336":1,"337":1}}],["specified",{"2":{"2":2,"9":1,"26":1,"45":1,"56":1,"120":1,"121":2,"122":1,"127":1,"190":1,"192":1,"256":1,"257":1,"315":2,"335":1,"407":1}}],["specifics",{"2":{"367":1}}],["specification",{"2":{"242":1}}],["specific",{"0":{"128":1,"296":1,"304":1,"374":1},"1":{"375":1,"376":1},"2":{"2":1,"15":1,"31":6,"75":1,"101":1,"104":1,"107":1,"128":1,"140":1,"157":1,"162":1,"176":1,"190":1,"194":1,"204":2,"205":1,"263":2,"265":1,"266":2,"268":1,"289":1,"291":1,"292":1,"296":1,"297":1,"304":1,"313":3,"315":2,"316":1,"331":2,"332":1,"337":1,"338":1,"344":1,"350":1,"357":1,"360":1,"365":1,"366":1,"367":1,"370":1,"372":1,"374":2,"381":2,"384":1,"385":2,"387":1,"389":3,"390":1,"391":3,"392":2,"419":1,"421":1,"441":1,"460":1,"466":1,"468":1}}],["specs",{"2":{"46":1}}],["spread",{"2":{"407":1}}],["spreadsheets",{"2":{"202":1}}],["spreadsheet",{"2":{"201":1}}],["split",{"2":{"324":1,"344":1,"434":1,"466":1}}],["splitting",{"2":{"285":1}}],["span",{"2":{"96":1,"103":1,"162":1}}],["span>🌐",{"2":{"76":1}}],["span>about",{"2":{"59":1}}],["span>",{"2":{"43":4,"59":1,"76":1,"84":2,"86":2,"162":1}}],["spanish",{"2":{"26":1,"366":1,"375":1,"376":1}}],["switcher>",{"2":{"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"76":2,"77":2,"78":2,"79":2,"80":2,"81":2,"82":2,"83":2,"84":2,"85":2,"86":2}}],["switcher",{"0":{"61":1,"156":1},"1":{"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1},"2":{"61":1,"63":1,"64":2,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"73":2,"74":2,"75":2,"76":1,"87":1,"88":2,"151":1,"156":2}}],["switches",{"2":{"25":1,"26":5,"120":1}}],["switchlocalepath",{"2":{"454":1}}],["switchlocaleroute",{"2":{"454":1}}],["switchlocale",{"2":{"27":1,"454":1}}],["switchroute",{"2":{"26":4,"454":1}}],["switching",{"0":{"126":1,"153":1,"154":1,"155":1},"1":{"154":1,"155":1,"156":1},"2":{"26":1,"61":1,"156":1,"241":1,"323":1,"326":1,"447":1}}],["switch",{"2":{"25":1,"26":2,"32":1,"68":1,"126":1,"151":1,"154":2,"170":1,"447":1}}],["storage",{"2":{"472":1,"480":1}}],["store",{"2":{"299":1,"334":2,"336":1}}],["stored",{"2":{"161":1,"164":1,"208":1,"254":1,"255":2,"297":1,"298":3,"299":1,"317":1,"340":1,"359":1}}],["step",{"0":{"345":2},"1":{"346":2,"347":2,"348":2,"349":2,"350":2,"351":2},"2":{"248":2,"342":2}}],["steps",{"0":{"371":1},"1":{"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1},"2":{"216":1,"351":1,"460":1}}],["stubbing",{"2":{"228":1}}],["standout",{"2":{"340":1}}],["standardizes",{"2":{"442":1}}],["standardized",{"2":{"239":1}}],["standard",{"2":{"339":1}}],["standards",{"2":{"229":1,"237":1,"246":1}}],["start",{"2":{"227":2,"233":1,"234":2,"315":2,"372":1}}],["starting",{"2":{"205":1,"437":1}}],["started",{"0":{"217":1,"224":1,"308":1},"1":{"218":1,"219":1,"220":1,"221":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1},"2":{"152":1,"216":1,"249":1}}],["static",{"0":{"445":1},"2":{"287":2,"298":1,"445":4,"449":1}}],["statistics",{"2":{"191":2}}],["state",{"2":{"55":1,"71":1,"205":1}}],["stats",{"0":{"191":1},"2":{"43":4,"191":3}}],["styling",{"0":{"45":1,"53":1,"159":1,"160":1},"2":{"47":1,"73":1,"88":1}}],["styles",{"0":{"53":1,"55":1,"56":1,"57":1,"74":1,"88":1},"1":{"56":1,"57":1},"2":{"45":2,"50":1,"53":1,"55":2,"56":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"74":1,"88":10}}],["style",{"2":{"19":1,"21":1,"53":1,"178":2,"236":1,"242":2}}],["still",{"2":{"31":1}}],["strategies",{"0":{"436":1,"437":1,"439":1},"1":{"437":1,"438":1,"439":1,"440":2,"441":2,"442":2,"443":2,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"326":1,"438":1,"444":1,"448":1,"449":1}}],["strategy",{"0":{"326":1,"438":1,"445":1,"447":1},"2":{"5":1,"10":1,"325":1,"326":2,"437":2,"438":1,"440":3,"441":2,"442":2,"443":2,"444":1,"445":2,"446":1,"447":1,"448":1}}],["straightforward",{"2":{"280":1,"367":1}}],["strong",{"2":{"270":1}}],["strong>",{"2":{"110":2,"166":2}}],["stress",{"0":{"403":1,"404":1},"2":{"396":1,"403":1,"404":1,"405":1,"407":2,"475":2,"476":2,"477":1}}],["streamlining",{"2":{"214":1,"279":1}}],["streamlined",{"0":{"419":1},"2":{"343":1,"466":1,"470":1,"472":1,"480":1}}],["streamlines",{"2":{"248":1}}],["streamline",{"2":{"184":1,"479":1}}],["street",{"2":{"171":1}}],["structures",{"2":{"263":1,"389":1}}],["structure",{"0":{"290":1,"292":1,"293":1,"294":1,"298":1,"299":1,"313":1,"332":1,"468":1},"1":{"291":1,"292":1,"293":2,"294":2,"295":3,"296":3,"297":2,"298":2,"299":2,"300":1,"301":1,"302":1,"303":1,"304":1,"305":1,"306":1,"307":1},"2":{"46":1,"170":1,"190":2,"254":1,"263":1,"266":1,"269":1,"270":1,"278":1,"285":1,"291":1,"293":1,"297":1,"298":4,"315":1,"362":1,"378":1,"392":1,"397":1,"423":1,"440":1,"441":1,"442":2,"448":2,"449":1,"472":1,"482":1}}],["structured",{"2":{"6":1,"10":1,"240":1,"437":1,"466":1,"481":1}}],["string>",{"2":{"386":1}}],["strings",{"0":{"285":1},"2":{"176":1,"190":2,"285":1,"387":1,"482":1}}],["string",{"2":{"2":1,"3":2,"8":3,"12":1,"13":1,"14":3,"15":3,"16":7,"17":8,"18":6,"19":1,"20":4,"21":4,"22":4,"23":2,"24":3,"25":2,"26":7,"27":6,"28":2,"29":3,"30":4,"31":10,"37":1,"38":1,"40":1,"49":2,"63":2,"91":2,"92":1,"93":2,"94":2,"95":2,"96":1,"97":2,"98":1,"101":5,"104":1,"107":1,"108":1,"113":1,"114":1,"116":6,"117":3,"118":1,"120":1,"121":1,"122":2,"125":1,"132":1,"134":1,"136":2,"137":2,"138":2,"205":7,"315":4,"316":1,"317":1,"321":1,"323":1,"324":13,"326":1,"327":1,"328":2,"335":1,"336":1,"337":1,"338":6,"386":4,"387":1,"434":1,"438":1,"457":1,"460":1}}],["suitable",{"2":{"408":1}}],["suite",{"2":{"230":1,"234":2}}],["suppose",{"2":{"361":1}}],["supported",{"0":{"193":1},"2":{"193":1,"344":1,"358":1,"466":1}}],["support",{"0":{"214":1,"366":1},"2":{"47":1,"221":1,"326":1,"344":1,"361":1,"363":1,"366":5,"440":1,"443":1,"460":1,"470":1}}],["supports",{"2":{"5":1,"60":1,"89":1,"104":1,"190":1,"193":1,"205":1,"302":1,"419":1,"420":1,"429":1}}],["superior",{"2":{"309":1,"415":1}}],["sure",{"2":{"238":1}}],["suggestions",{"2":{"214":1}}],["subjected",{"2":{"407":1}}],["subdomains",{"2":{"315":1}}],["subdirectories",{"2":{"203":1,"429":1}}],["subsequent",{"2":{"302":1,"340":1,"420":1}}],["subsection2",{"2":{"170":4,"171":1}}],["subsection1",{"2":{"170":2,"171":1}}],["subfolders",{"2":{"282":1}}],["submitted",{"2":{"245":1}}],["summary",{"0":{"87":1,"234":1,"393":1}}],["such",{"2":{"19":1,"47":1,"71":1,"133":1,"136":1,"172":1,"177":1,"221":1,"242":1,"298":1,"315":1,"318":1,"335":1,"339":1,"357":1}}],["successful",{"2":{"9":1}}],["suffixes",{"2":{"15":1}}],["src",{"2":{"7":1}}],["sent",{"2":{"407":1}}],["series",{"2":{"407":1,"412":1}}],["serving",{"2":{"380":1}}],["service",{"0":{"194":1},"2":{"192":5,"194":2,"206":2}}],["services",{"0":{"193":1},"2":{"165":1,"170":1,"171":5,"184":1,"192":2,"193":2,"194":1,"213":1,"289":2,"296":1}}],["served",{"2":{"302":1,"420":1,"427":1}}],["serves",{"2":{"233":1,"284":1,"378":1,"379":1}}],["serve",{"2":{"232":2,"234":2,"370":1,"372":1}}],["serverless",{"2":{"287":1}}],["server",{"0":{"227":1,"283":1,"414":1,"428":1,"430":1,"431":1,"465":1},"1":{"429":1,"430":1,"431":1,"432":2,"433":1,"434":1,"435":1},"2":{"227":2,"234":1,"283":5,"287":1,"301":1,"302":1,"309":1,"310":1,"335":1,"340":2,"343":1,"396":1,"407":4,"408":1,"411":1,"414":1,"415":1,"421":1,"429":5,"430":1,"445":1,"461":1,"462":1,"466":1,"472":1,"480":1}}],["segment",{"2":{"298":1}}],["segments",{"2":{"297":1}}],["searching",{"2":{"340":1}}],["search",{"2":{"147":1,"150":1,"205":8,"423":3,"425":3,"427":2}}],["seamlessly",{"2":{"88":1,"261":1,"272":1,"431":1}}],["seamless",{"0":{"278":1},"2":{"1":1,"26":1,"61":1,"282":1,"481":1}}],["seo",{"0":{"142":1,"145":1,"350":1,"355":1,"422":1,"424":1,"425":1},"1":{"423":1,"424":1,"425":2,"426":2,"427":2},"2":{"129":2,"133":1,"134":1,"137":1,"142":1,"145":1,"147":1,"149":1,"150":3,"241":1,"269":1,"270":1,"315":1,"318":2,"321":1,"344":2,"350":2,"351":1,"355":1,"359":1,"423":3,"425":1,"426":2,"427":2}}],["several",{"2":{"75":1,"112":1,"343":1}}],["select>",{"2":{"447":1}}],["select",{"2":{"192":1,"274":1,"447":2,"449":1}}],["selecting",{"2":{"70":1,"315":1}}],["selected=",{"2":{"447":1}}],["selected",{"0":{"77":1,"78":1},"2":{"69":1,"77":2,"78":2,"87":4,"316":1,"336":1,"437":1,"447":1}}],["sec",{"2":{"414":2,"465":2}}],["secure",{"0":{"213":1},"2":{"213":2}}],["security",{"2":{"46":1,"54":1}}],["seconds",{"2":{"399":1,"400":1,"401":2,"402":3,"403":1,"404":1,"405":1,"407":2,"474":2}}],["second",{"2":{"163":1,"175":1,"180":1,"403":1,"404":1,"405":1,"407":2,"414":3,"465":3,"478":2}}],["section1",{"2":{"170":8,"171":1}}],["section>",{"2":{"170":2}}],["sections",{"0":{"170":1,"171":1},"1":{"171":1},"2":{"44":2,"45":1,"357":1,"362":1,"363":1}}],["section",{"2":{"43":1,"44":1,"45":1,"135":1,"149":3,"151":1,"190":1,"255":1,"360":1,"361":3,"363":1,"366":1}}],["see",{"2":{"31":1,"151":1,"190":1,"389":1,"457":1}}],["september",{"2":{"20":1,"180":1}}],["separate",{"2":{"344":1,"369":1,"378":1,"382":1,"418":1,"466":1}}],["separated",{"2":{"192":1}}],["separately",{"2":{"10":1}}],["separation",{"2":{"10":1,"378":1,"381":1,"419":1}}],["seti18nrouteparams",{"2":{"454":1}}],["settranslationsfromjson",{"2":{"454":2,"458":2,"460":1}}],["settroutename",{"2":{"454":1,"460":1}}],["setting",{"0":{"288":1,"368":1,"430":1,"452":1},"1":{"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"453":1,"454":1,"455":1},"2":{"248":1,"251":1,"315":1,"323":1,"451":1}}],["settings",{"2":{"20":1,"31":1,"46":1,"148":1,"172":1,"177":1,"179":1,"274":1,"322":1,"329":1,"357":2,"358":2,"362":1,"363":1,"365":1,"366":2,"367":2,"372":1,"381":1,"440":1,"445":1}}],["setdefaultlocale",{"2":{"454":1,"460":1}}],["setlocales",{"2":{"454":1,"460":1}}],["setlocalename",{"2":{"454":1,"460":1}}],["setlocale",{"2":{"454":1,"460":1}}],["setupfiles",{"2":{"455":1}}],["setups",{"2":{"411":1}}],["setup",{"0":{"152":1,"185":1,"222":1,"249":1,"312":1,"467":1},"1":{"186":1,"187":1,"188":1,"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1,"250":1,"251":1,"313":1},"2":{"149":1,"152":1,"251":1,"278":1,"289":2,"314":1,"343":1,"369":1,"370":1,"378":1,"382":1,"391":1,"392":1,"397":1,"454":1,"455":1,"457":2,"458":1}}],["setup>",{"2":{"32":1,"44":1,"148":1,"154":1,"157":1,"162":1,"164":1,"170":1,"173":1,"178":1,"180":1,"182":1,"268":1}}],["sets",{"2":{"66":1,"69":1,"315":1,"316":1,"321":1,"425":1,"460":5}}],["set",{"0":{"378":1},"2":{"2":1,"4":1,"27":1,"31":1,"143":1,"150":2,"176":1,"187":1,"188":1,"254":1,"255":1,"256":1,"287":1,"315":3,"335":2,"338":1,"354":1,"358":1,"363":1,"375":1,"376":1,"385":1,"390":1,"392":1,"426":1,"440":1,"454":1,"455":1}}],["s",{"0":{"472":1,"479":1},"2":{"1":2,"5":1,"7":1,"8":1,"10":1,"20":1,"31":1,"32":1,"46":1,"56":1,"61":1,"75":1,"88":2,"120":1,"131":1,"146":1,"150":1,"152":1,"163":3,"170":1,"174":1,"177":1,"184":1,"214":1,"216":1,"218":2,"229":1,"236":1,"237":1,"246":1,"265":1,"268":1,"270":1,"278":1,"284":1,"293":1,"302":1,"304":1,"309":1,"310":1,"314":1,"315":2,"322":1,"323":3,"329":1,"336":1,"340":1,"344":1,"347":1,"350":1,"359":2,"361":1,"370":1,"378":1,"389":1,"390":1,"391":1,"392":1,"407":1,"411":1,"415":1,"423":1,"432":1,"435":1,"437":1,"440":2,"449":2,"451":1,"457":1,"458":1,"460":1,"461":1,"467":1}}],["azure",{"2":{"193":2}}],["amount",{"2":{"296":1}}],["amp",{"0":{"281":1},"1":{"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1},"2":{"244":1}}],["am",{"2":{"180":1}}],["a>",{"2":{"170":4}}],["after",{"0":{"78":1,"80":1,"82":1,"84":1,"86":1,"486":1},"2":{"78":2,"80":2,"82":2,"84":2,"86":2,"87":10,"187":1,"190":1,"205":3,"257":1,"289":1,"312":1,"347":1,"349":1,"351":1,"380":1,"420":1,"445":1}}],["avg",{"2":{"405":2,"475":1}}],["average",{"2":{"399":2,"400":2,"403":3,"404":3,"405":1,"475":1,"477":1}}],["avoiding",{"2":{"449":1}}],["avoids",{"2":{"367":1,"447":2,"480":1}}],["avoid",{"2":{"46":2,"210":1,"259":1,"270":1,"304":1,"421":1,"445":1,"446":1,"449":3}}],["availablelocales",{"2":{"447":2}}],["available",{"0":{"439":1},"1":{"440":1,"441":1,"442":1,"443":1},"2":{"2":1,"9":1,"14":1,"31":3,"115":1,"186":1,"191":1,"256":1,"315":1,"326":1,"337":1,"385":1,"387":2,"425":2,"438":1,"443":1,"448":1,"460":2}}],["ability",{"2":{"396":1,"407":1}}],["above",{"2":{"339":1}}],["about",{"0":{"284":1},"2":{"26":2,"49":1,"50":1,"52":2,"53":2,"57":1,"59":1,"60":3,"121":1,"127":1,"138":1,"147":1,"157":2,"158":2,"159":1,"170":1,"171":2,"173":1,"268":2,"293":1,"295":2,"296":3,"301":2,"313":1,"328":2,"348":1,"423":1,"440":1,"441":3,"442":3,"443":4,"468":1}}],["able",{"2":{"31":1,"214":1,"261":1}}],["aaa",{"2":{"31":1,"389":1}}],["autodetectpath",{"0":{"323":1}}],["autodetectlanguage",{"0":{"322":1},"2":{"359":1,"361":1,"364":1,"366":1,"373":1,"375":1,"376":1}}],["auto",{"2":{"289":1,"323":1,"344":1,"466":1}}],["automatic",{"0":{"424":1},"1":{"425":1,"426":1,"427":1},"2":{"241":1,"318":1,"322":1,"333":2,"344":1,"350":1,"361":1,"365":1,"366":1,"375":1,"376":1,"426":1,"440":1}}],["automatically",{"2":{"37":1,"40":1,"47":1,"54":1,"105":1,"145":1,"150":1,"157":1,"190":1,"192":1,"229":1,"234":1,"282":1,"297":1,"318":1,"322":1,"325":1,"359":2,"423":1,"425":2,"427":1,"432":1,"435":1,"482":1}}],["automated",{"2":{"481":1}}],["automates",{"2":{"279":1}}],["automate",{"0":{"212":1,"261":1},"2":{"184":1,"212":1,"261":1}}],["authentication",{"2":{"254":1}}],["auth",{"2":{"190":3,"483":1}}],["author",{"2":{"44":3}}],["auf",{"2":{"31":1,"388":1,"389":1,"391":1}}],["au",{"2":{"31":1,"389":1,"391":1}}],["audiences",{"2":{"147":1,"425":1}}],["audience",{"2":{"31":1,"264":1,"393":1}}],["apibaseurl",{"0":{"288":1,"335":1},"2":{"288":1}}],["apis",{"2":{"192":1,"429":1}}],["api",{"0":{"213":1},"2":{"27":1,"177":1,"179":1,"181":1,"192":2,"194":3,"206":2,"213":1,"251":1,"253":3,"254":3,"326":1,"335":2}}],["appear",{"2":{"289":1,"315":1,"441":1}}],["appears",{"2":{"204":1,"295":1,"438":1}}],["apps",{"2":{"171":1}}],["approved",{"2":{"245":1}}],["appropriate",{"2":{"19":1,"25":1,"26":2,"301":1,"322":1,"377":1,"379":1,"432":1}}],["approaches",{"2":{"449":1}}],["approach",{"0":{"408":1},"2":{"10":1,"261":1,"270":1,"284":1,"291":1,"342":1,"367":1,"369":1,"382":1,"384":1,"397":1,"418":1,"429":1,"437":1,"446":1,"447":2}}],["apply",{"2":{"270":1,"367":1,"447":2}}],["applying",{"2":{"202":1,"449":1}}],["applicable",{"2":{"381":1}}],["applications",{"2":{"10":1,"270":1,"280":1,"310":1,"360":1,"369":1,"382":1,"397":2,"408":1,"429":1,"443":1,"459":1,"466":1,"479":1}}],["application",{"0":{"351":1,"362":1,"363":1,"377":1},"1":{"364":1,"365":1,"366":1},"2":{"1":2,"2":1,"5":3,"6":1,"9":1,"10":3,"31":1,"46":1,"61":2,"75":1,"88":1,"111":1,"113":1,"115":1,"120":1,"124":1,"126":1,"134":1,"135":1,"147":1,"150":1,"151":1,"176":1,"233":1,"263":1,"274":1,"282":1,"289":1,"295":1,"305":1,"307":1,"311":1,"315":1,"330":1,"342":1,"351":1,"354":1,"357":2,"358":1,"360":2,"362":1,"367":1,"369":1,"372":1,"377":1,"378":1,"380":1,"382":1,"384":1,"393":1,"408":1,"411":1,"415":2,"437":2,"440":1,"442":1,"448":1,"449":1,"451":1,"460":1,"462":1,"467":1}}],["applies",{"2":{"67":1,"70":1,"105":1}}],["applied",{"2":{"23":1,"24":1,"28":1,"29":1,"38":1,"50":1,"54":1,"64":1,"65":1,"68":1,"149":1,"437":1}}],["apple",{"2":{"173":1,"174":1,"175":1,"176":1}}],["apples",{"2":{"18":3,"32":1,"117":3,"173":7,"174":3,"175":5,"176":10}}],["applecountmessage",{"2":{"18":1}}],["app",{"2":{"8":1,"227":1,"233":1,"310":1,"313":1,"335":1,"359":1,"467":1}}],["again",{"2":{"340":1}}],["against",{"2":{"22":1}}],["ago",{"2":{"22":2,"181":2,"182":1}}],["algorithm",{"0":{"471":1},"1":{"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1},"2":{"471":1,"472":1,"474":1,"478":1,"480":1}}],["altering",{"2":{"440":1}}],["alternatively",{"2":{"289":1}}],["alternative",{"2":{"284":1}}],["alternate",{"2":{"133":1,"134":1,"137":1,"138":1,"143":1,"145":3,"149":3,"150":1,"318":1,"321":1,"425":2}}],["alone",{"2":{"315":1}}],["along",{"2":{"204":1}}],["also",{"2":{"205":1,"306":1,"353":1,"369":1,"382":1,"392":1,"414":1,"443":2}}],["align",{"2":{"269":1}}],["aligns",{"2":{"20":1}}],["alice",{"2":{"16":2,"17":2,"32":1,"168":1}}],["always",{"2":{"17":1,"190":1,"261":1,"446":1,"459":1}}],["all",{"2":{"14":1,"27":1,"37":1,"111":1,"115":1,"192":1,"196":1,"204":1,"205":5,"206":1,"230":1,"238":1,"246":1,"256":1,"259":1,"266":1,"274":1,"297":1,"302":1,"306":2,"315":3,"323":1,"326":2,"351":1,"354":1,"366":1,"372":1,"381":1,"397":1,"420":1,"425":1,"441":4,"442":4,"443":1,"448":1,"449":1,"460":1}}],["allowing",{"2":{"53":1,"61":1,"232":1,"275":1,"289":1,"302":1,"370":1,"393":1,"415":1,"429":1}}],["allowed",{"2":{"31":3,"70":1,"74":1,"389":3}}],["allow",{"2":{"10":1,"31":1,"75":1,"357":1,"448":1}}],["allows",{"2":{"1":1,"2":1,"31":1,"50":1,"63":1,"64":1,"65":1,"68":1,"89":1,"101":1,"205":2,"263":1,"285":2,"296":1,"299":1,"329":1,"331":1,"338":1,"369":1,"382":1,"384":1,"387":1,"389":1,"392":2,"397":1,"437":1,"479":1}}],["await",{"0":{"245":1},"2":{"8":2,"27":2,"122":1,"128":1,"432":1,"434":1,"458":1}}],["attention",{"2":{"351":1}}],["attempt",{"2":{"229":1}}],["attributed",{"2":{"396":1}}],["attribute",{"0":{"141":1},"2":{"131":1,"132":1,"141":1,"190":1,"315":1,"447":2}}],["attributes",{"0":{"142":1},"2":{"54":1,"60":1,"129":2,"133":1,"136":1,"140":1,"142":1,"146":1,"147":1,"149":1,"150":3,"423":1,"425":2,"427":1}}],["at",{"2":{"7":1,"75":1,"218":1,"233":1,"289":1,"339":1,"393":1,"410":1,"419":1}}],["admin",{"0":{"365":1},"2":{"363":1,"365":3,"366":2}}],["advantage",{"2":{"350":1}}],["advantages",{"2":{"343":1}}],["advanced",{"0":{"110":1},"2":{"89":1,"205":1}}],["adheres",{"2":{"229":1,"237":1}}],["adjust",{"2":{"357":1}}],["adjusting",{"2":{"172":1}}],["adjusts",{"2":{"147":1}}],["adjustments",{"2":{"5":1,"245":1}}],["adapt",{"2":{"369":1,"382":1}}],["adapts",{"2":{"278":1}}],["adaptive",{"2":{"10":1}}],["adaptable",{"2":{"5":1,"10":1}}],["adopting",{"2":{"10":1}}],["address",{"2":{"170":1,"171":1,"282":1,"284":1,"411":1,"462":1}}],["address>",{"2":{"170":2}}],["added",{"0":{"283":1},"2":{"136":1,"284":1,"326":1,"361":1,"440":1}}],["adddirattribute",{"0":{"131":1},"2":{"131":1,"148":1}}],["addseoattributes",{"0":{"133":1},"2":{"133":1,"142":1,"145":1,"148":1,"150":1}}],["adds",{"2":{"54":1,"131":1,"320":1,"366":2}}],["adding",{"2":{"4":1,"7":1,"142":1,"236":1,"242":1,"280":1,"282":1,"315":1}}],["additionally",{"2":{"315":1}}],["additional",{"0":{"58":1,"106":1,"144":1,"176":1},"1":{"59":1,"60":1,"107":1,"108":1,"109":1,"110":1,"145":1,"146":1,"147":1},"2":{"2":1,"18":1,"38":1,"45":2,"47":1,"119":1,"192":1,"194":1,"278":1,"315":1,"330":1,"360":1,"361":1,"396":1,"423":1}}],["addition",{"2":{"1":1,"279":1,"329":1}}],["add",{"2":{"3":1,"5":1,"8":1,"208":1,"221":1,"238":1,"241":1,"242":1,"246":1,"312":1,"346":1,"360":1,"375":1,"427":1,"448":1,"467":1}}],["achieve",{"2":{"161":1,"361":1}}],["actual",{"2":{"315":1}}],["activeclass=",{"2":{"159":1}}],["activestyle=",{"2":{"50":1,"53":1,"57":1}}],["activestyle",{"0":{"50":1},"2":{"55":1,"56":2}}],["active",{"0":{"53":1,"56":1,"57":1,"159":1,"160":1},"2":{"47":1,"50":1,"53":1,"55":1,"57":1,"69":1,"323":1}}],["acts",{"2":{"47":1}}],["accumulate",{"2":{"307":1}}],["accuracy",{"2":{"190":1}}],["accurate",{"2":{"147":1,"277":1}}],["accidental",{"2":{"204":1}}],["accept",{"2":{"435":1}}],["accepts",{"2":{"130":1}}],["accessing",{"2":{"379":1}}],["accessibility",{"0":{"60":1},"2":{"60":1,"315":1}}],["accessible",{"2":{"31":1,"60":1,"283":1,"287":1,"297":1,"338":1,"339":1,"423":1,"441":1}}],["accessed",{"2":{"111":1}}],["access",{"2":{"31":5,"40":1,"111":1,"233":1,"288":1,"289":2,"385":1,"389":1,"390":1,"391":1}}],["account",{"2":{"219":1}}],["accommodating",{"2":{"26":1}}],["accordingly",{"2":{"176":1}}],["according",{"2":{"2":1,"9":1,"19":1,"20":1,"21":1,"22":1,"177":1,"179":1,"181":1,"236":1,"257":1,"425":1,"460":2}}],["across",{"2":{"2":1,"184":1,"196":1,"204":2,"205":4,"239":1,"248":1,"259":1,"270":1,"289":1,"295":1,"305":1,"306":1,"313":1,"357":1,"367":1,"369":1,"379":1,"382":1,"407":1,"415":1,"438":1,"442":1,"449":1,"476":1}}],["arabic",{"2":{"425":1}}],["ar",{"2":{"293":3,"298":3,"312":2,"313":3,"315":3,"332":1,"348":3,"359":2,"426":2,"467":2,"468":3}}],["architecture",{"2":{"218":1,"236":1,"417":1,"471":1}}],["aria",{"2":{"60":2}}],["around",{"2":{"47":1,"417":1,"466":1}}],["artillery",{"0":{"403":1,"404":1}}],["artikel",{"2":{"27":2}}],["article>",{"2":{"44":2}}],["article",{"2":{"27":4}}],["array",{"2":{"14":2,"31":2,"115":1,"137":1,"138":1,"162":1,"354":1,"387":1}}],["area",{"2":{"465":1}}],["are",{"0":{"286":1,"300":1},"1":{"287":1,"288":1,"301":1,"302":1},"2":{"2":1,"9":2,"31":5,"147":2,"149":5,"150":1,"179":1,"190":1,"191":1,"193":1,"204":2,"205":1,"208":1,"210":1,"213":1,"229":1,"231":1,"238":1,"246":1,"253":1,"254":2,"255":1,"257":1,"259":1,"261":1,"264":1,"277":1,"283":4,"288":1,"295":1,"296":2,"297":1,"299":1,"301":1,"307":1,"310":1,"313":1,"317":1,"323":1,"339":1,"344":3,"348":1,"349":1,"350":1,"351":2,"353":1,"354":1,"355":1,"359":1,"360":2,"374":1,"379":1,"387":2,"389":3,"390":1,"392":1,"397":1,"407":1,"408":1,"420":2,"421":1,"425":1,"427":1,"429":3,"437":2,"440":1,"444":1,"448":1,"466":2,"468":1,"471":1,"480":2}}],["arguments",{"0":{"188":1},"2":{"2":1}}],["announce",{"2":{"470":1,"471":1}}],["analysis",{"0":{"406":1},"1":{"407":1,"408":1}}],["another",{"2":{"104":1,"447":1}}],["anytown",{"2":{"171":1}}],["anything",{"2":{"100":1}}],["any",{"2":{"15":1,"16":2,"17":2,"18":1,"45":1,"205":1,"229":1,"237":1,"238":1,"244":1,"270":1,"295":1,"335":1,"339":1,"350":1,"390":1,"419":1,"429":1,"431":1,"440":5,"441":1}}],["an",{"0":{"164":1},"2":{"2":1,"8":1,"9":1,"14":1,"31":4,"32":1,"49":1,"111":1,"112":1,"115":1,"130":1,"135":1,"149":1,"162":1,"164":1,"214":1,"253":1,"261":1,"265":1,"272":1,"275":1,"279":1,"289":1,"315":1,"347":1,"359":1,"363":1,"387":5,"390":1,"391":1,"407":1,"410":1,"440":1,"457":1}}],["and",{"0":{"74":1,"145":1,"146":1,"151":1,"166":1,"179":1,"180":1,"185":1,"214":1,"232":1,"249":1,"261":1,"276":1,"286":1,"297":1,"302":1,"352":1,"380":1,"401":1,"405":1,"413":1,"420":1,"443":1,"444":1,"446":1,"464":1},"1":{"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":2,"168":2,"169":2,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":2,"181":1,"182":1,"186":1,"187":1,"188":1,"250":1,"251":1,"287":1,"288":1,"298":1,"353":1,"354":1,"355":1,"445":1,"446":1,"447":1},"2":{"1":1,"4":1,"5":1,"7":1,"8":1,"9":2,"10":7,"17":1,"18":1,"20":1,"25":1,"26":3,"27":1,"30":1,"31":2,"35":1,"45":1,"46":1,"47":1,"54":1,"57":1,"60":1,"61":1,"73":1,"74":1,"75":1,"111":3,"112":1,"116":1,"121":1,"122":1,"128":1,"129":4,"132":1,"133":2,"134":1,"135":1,"136":1,"137":1,"138":1,"142":1,"143":1,"145":1,"146":1,"147":2,"149":8,"150":2,"151":2,"161":1,"162":1,"164":2,"166":1,"172":1,"179":2,"181":1,"184":3,"187":1,"190":10,"192":1,"194":2,"195":1,"199":1,"201":1,"203":2,"204":4,"205":9,"207":1,"210":2,"211":1,"212":1,"213":1,"214":1,"216":1,"218":4,"227":1,"228":1,"232":2,"234":1,"236":1,"238":1,"244":1,"246":2,"248":3,"249":1,"251":1,"253":1,"254":1,"257":1,"259":1,"260":2,"261":2,"263":1,"264":2,"268":1,"269":1,"270":1,"272":3,"274":1,"275":1,"277":1,"278":1,"279":1,"280":1,"284":2,"285":1,"287":1,"289":3,"291":3,"292":2,"296":2,"297":2,"301":3,"302":2,"304":1,"305":1,"306":1,"307":2,"309":2,"310":2,"313":1,"314":1,"315":5,"319":2,"321":1,"322":2,"323":1,"324":1,"326":5,"338":1,"339":2,"340":1,"343":2,"344":3,"348":1,"351":2,"353":1,"354":1,"355":1,"357":1,"358":1,"359":1,"362":1,"363":1,"366":2,"367":2,"369":4,"375":1,"378":3,"379":1,"380":1,"381":1,"382":4,"384":1,"387":2,"390":3,"391":1,"392":4,"393":4,"396":3,"397":2,"407":3,"408":3,"410":1,"411":3,"412":1,"415":3,"417":2,"418":1,"419":1,"420":4,"421":2,"423":4,"425":4,"427":1,"429":3,"430":1,"437":2,"438":1,"440":3,"443":4,"444":1,"445":1,"447":2,"448":1,"449":5,"451":1,"453":1,"454":1,"455":1,"459":3,"460":3,"461":2,"462":5,"466":6,"468":1,"470":2,"471":1,"472":1,"474":1,"475":2,"476":1,"479":2,"480":4,"481":2,"482":3}}],["a",{"0":{"32":1,"127":1,"143":1,"221":1,"244":1,"268":1,"282":1,"361":1,"362":1,"363":1,"433":1,"454":1},"1":{"364":1,"365":1,"366":1,"434":1},"2":{"2":2,"6":1,"7":1,"8":1,"10":3,"16":2,"17":4,"18":3,"19":1,"20":5,"21":3,"22":5,"23":1,"26":6,"28":2,"31":4,"32":1,"35":2,"40":1,"42":1,"45":1,"47":2,"49":1,"52":1,"54":1,"55":1,"60":1,"61":1,"67":1,"73":1,"74":1,"83":1,"84":1,"85":1,"86":1,"88":1,"89":1,"92":1,"93":2,"94":2,"95":2,"101":1,"103":1,"109":1,"111":1,"116":2,"117":2,"118":1,"121":1,"125":2,"126":1,"127":1,"128":1,"129":1,"141":1,"143":1,"148":1,"149":1,"152":1,"156":1,"162":1,"165":1,"170":6,"171":1,"173":2,"176":2,"177":1,"178":2,"180":2,"182":3,"184":1,"190":1,"201":2,"202":1,"204":1,"205":5,"214":1,"218":2,"219":1,"221":1,"233":2,"236":1,"238":1,"239":1,"242":4,"245":1,"246":1,"248":1,"264":2,"266":1,"268":1,"270":2,"272":1,"274":2,"276":1,"279":2,"282":2,"284":1,"289":4,"291":2,"293":1,"296":3,"297":3,"298":7,"299":1,"301":2,"302":1,"306":2,"309":1,"310":1,"314":1,"315":2,"325":1,"326":6,"327":4,"329":1,"330":1,"335":1,"337":3,"338":3,"339":1,"340":2,"342":1,"343":1,"344":1,"355":1,"360":1,"361":3,"362":2,"363":1,"366":2,"369":2,"370":2,"372":1,"374":2,"375":1,"376":1,"378":2,"382":2,"384":2,"385":1,"387":2,"390":1,"391":1,"393":2,"397":2,"407":2,"408":3,"410":1,"412":3,"417":1,"418":1,"419":1,"421":1,"425":1,"427":1,"429":1,"433":1,"435":1,"437":1,"440":1,"441":6,"442":5,"443":7,"445":4,"447":2,"448":1,"449":1,"451":1,"454":1,"457":1,"458":1,"459":1,"460":11,"461":1,"462":1,"463":1,"466":1,"470":2,"471":2,"479":3,"480":1}}],["aspects",{"2":{"407":1,"425":1}}],["assess",{"2":{"407":1}}],["assets",{"0":{"283":1},"2":{"283":3}}],["assign",{"2":{"282":1}}],["assistant",{"2":{"272":1}}],["associated",{"2":{"164":1}}],["assuming",{"2":{"12":1,"15":1,"18":1}}],["asynchronous",{"2":{"289":1}}],["async",{"2":{"3":1,"8":3,"27":1,"432":1,"434":1,"458":1}}],["as",{"2":{"1":1,"10":1,"19":2,"22":1,"47":2,"71":1,"83":1,"84":1,"85":1,"86":1,"93":1,"94":1,"95":1,"99":1,"133":1,"136":1,"160":1,"172":1,"177":1,"178":1,"181":1,"182":1,"192":1,"208":1,"221":1,"227":1,"230":1,"233":1,"240":1,"242":1,"276":1,"282":1,"284":1,"289":1,"298":1,"305":1,"315":5,"318":1,"323":1,"325":1,"335":1,"337":1,"339":1,"351":2,"357":1,"358":1,"366":2,"372":1,"375":1,"376":1,"408":1,"429":1,"435":1,"451":1,"457":2,"460":2}}],["td",{"2":{"454":1,"460":1}}],["tn",{"2":{"454":1,"460":1}}],["tc",{"2":{"454":1,"460":1}}],["tune",{"2":{"314":1}}],["tuning",{"2":{"280":1}}],["turbo",{"2":{"192":1,"194":1}}],["t>",{"2":{"98":1,"100":1,"101":1,"104":1,"107":1,"108":1,"109":1,"110":1,"166":1,"168":1,"284":1,"285":1}}],["tencent",{"2":{"193":2}}],["testid=",{"2":{"457":1,"458":2}}],["testing",{"0":{"450":1,"451":1,"452":1,"459":1},"1":{"451":1,"452":1,"453":2,"454":2,"455":2,"456":1,"457":1,"458":1,"459":1,"460":1},"2":{"227":1,"407":1,"408":1,"433":1,"451":2,"453":1,"455":1,"459":1}}],["tested",{"2":{"414":1,"463":1}}],["tests",{"0":{"230":1,"456":1},"1":{"457":1,"458":1},"2":{"230":1,"236":1,"238":2,"242":1,"407":2,"408":1,"412":1,"415":1,"421":1,"451":1,"454":2,"455":1,"458":1,"459":4,"463":1,"475":1,"476":1}}],["test",{"0":{"238":1,"351":1,"394":1,"399":1,"400":1,"403":2,"404":2,"407":1,"453":1,"458":1},"1":{"395":1,"396":1,"397":1,"398":1,"399":1,"400":1,"401":2,"402":1,"403":1,"404":1,"405":1,"406":1,"407":1,"408":1},"2":{"190":1,"230":3,"231":2,"233":1,"234":4,"238":2,"242":1,"289":1,"351":1,"380":1,"395":4,"396":2,"397":1,"403":1,"404":1,"405":1,"407":4,"421":1,"453":2,"454":2,"455":2,"457":2,"458":5,"459":3,"460":2,"475":1,"476":1,"477":1}}],["teams",{"2":{"201":1}}],["team",{"2":{"171":1,"270":1}}],["texts",{"2":{"306":1,"466":1}}],["textdecoration",{"2":{"68":1,"74":1}}],["text",{"0":{"190":1},"2":{"53":1,"91":1,"96":1,"98":1,"99":1,"103":2,"104":2,"190":13,"205":4,"284":1,"285":2,"295":1,"315":1,"425":1,"458":3,"481":1,"482":1,"483":2}}],["templates",{"2":{"190":2,"481":1}}],["template",{"2":{"40":1,"42":1,"43":1,"44":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"104":1,"107":1,"110":1,"166":1,"190":1,"284":1,"285":2,"457":1}}],["template>",{"2":{"32":2,"40":1,"42":3,"43":3,"44":3,"73":2,"74":2,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"104":1,"107":1,"110":1,"148":2,"154":2,"156":2,"157":2,"159":2,"162":2,"164":2,"166":3,"168":2,"170":2,"173":2,"178":2,"180":2,"182":2,"190":4,"268":2,"284":3,"285":3,"391":2,"457":2,"485":2,"486":2}}],["tied",{"2":{"392":1}}],["tips",{"0":{"246":1,"421":1},"2":{"421":1}}],["title`",{"2":{"44":1}}],["title",{"2":{"42":2,"43":2,"44":1,"165":1,"289":4,"296":2}}],["times",{"0":{"474":1,"477":1},"2":{"179":2,"181":1,"309":1,"310":1,"343":1,"396":2,"407":1,"408":1,"411":2,"415":3,"420":1,"421":1,"461":1,"462":1,"466":1,"474":1,"477":1,"479":2}}],["timestamp",{"2":{"20":1,"22":1}}],["timezone",{"2":{"20":1}}],["time",{"0":{"179":1,"180":1,"277":1,"401":1,"413":1,"464":1},"1":{"180":1},"2":{"5":1,"20":1,"22":3,"180":1,"181":2,"182":1,"275":1,"279":1,"307":1,"340":1,"396":1,"399":1,"400":1,"401":2,"402":1,"403":4,"404":4,"405":4,"407":2,"408":1,"413":2,"414":2,"419":1,"464":2,"465":2,"474":2,"477":2}}],["t",{"0":{"89":1,"166":1,"167":1,"282":1},"1":{"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":1,"167":1,"168":1,"169":1},"2":{"40":2,"42":4,"43":5,"44":6,"89":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"103":1,"104":3,"105":1,"107":1,"108":1,"109":1,"110":1,"116":2,"151":1,"166":2,"168":1,"282":1,"284":3,"285":3,"324":3,"391":3,"432":3,"434":2,"440":1,"449":1,"454":1,"460":1}}],["tasks",{"2":{"242":1,"272":1,"279":2,"427":1}}],["take",{"0":{"280":1},"2":{"218":1,"350":1}}],["takes",{"2":{"2":1,"443":1}}],["tags",{"0":{"145":1,"355":1},"2":{"129":2,"132":2,"133":1,"137":2,"138":1,"141":1,"142":1,"145":1,"149":4,"150":2,"166":1,"318":2,"321":2,"344":1,"351":1,"355":1,"359":1,"423":1,"425":2,"427":1}}],["tag=",{"2":{"96":1,"166":1}}],["tag",{"0":{"96":1},"2":{"96":1,"103":1,"136":1,"149":2,"241":1,"344":1,"350":1,"366":1,"425":1}}],["table",{"2":{"412":1,"460":1}}],["tab",{"2":{"54":1}}],["tailored",{"2":{"263":1,"378":1,"392":1,"393":1}}],["tailor",{"2":{"31":1,"75":1,"269":1}}],["targets",{"2":{"244":1}}],["target",{"2":{"23":1,"24":1,"26":1,"28":2,"29":2,"49":1,"264":1,"447":1}}],["typeof",{"2":{"454":1}}],["type>",{"2":{"240":1}}],["types",{"0":{"242":1,"320":1},"2":{"231":1,"234":1,"320":2}}],["typescriptlocaleroute",{"2":{"446":2}}],["typescriptlocales",{"2":{"315":1}}],["typescripti18n",{"2":{"440":1,"441":1,"442":1,"443":1}}],["typescriptimport",{"2":{"8":1,"31":2,"33":1,"34":1,"389":2,"432":1,"434":1}}],["typescriptapibaseurl",{"2":{"335":1}}],["typescriptautodetectlanguage",{"2":{"322":1}}],["typescriptdisableupdater",{"2":{"334":1}}],["typescriptdisablewatcher",{"2":{"333":1}}],["typescriptdisablepagelocales",{"2":{"331":1}}],["typescriptdefine",{"2":{"329":1}}],["typescriptdefaultlocale",{"2":{"316":1}}],["typescriptdebug",{"2":{"319":1}}],["typescriptplugin",{"2":{"330":1}}],["typescriptcustomregexmatcher",{"2":{"327":1}}],["typescriptconst",{"2":{"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"28":1,"29":1,"114":1}}],["typescripttypes",{"2":{"320":1}}],["typescripttranslationdir",{"2":{"317":1}}],["typescriptmetabaseurl",{"2":{"321":1}}],["typescriptmeta",{"2":{"318":1}}],["typescriptexport",{"2":{"152":1,"299":1,"312":1,"324":1,"347":2,"359":1,"426":1,"467":1}}],["typescript$definei18nroute",{"2":{"31":1,"265":1,"386":1,"388":1}}],["typescript$mergetranslations",{"2":{"30":1}}],["typescript$switchlocale",{"2":{"25":1}}],["typescript",{"2":{"8":1,"23":1,"24":1,"26":4,"27":1,"190":2,"231":1,"234":1,"328":1,"337":1,"338":1,"361":2,"364":1,"365":1,"366":1,"373":1,"375":1,"376":1,"454":1,"455":1,"458":1,"470":1,"481":1}}],["typescriptnuxt",{"2":{"3":1}}],["typecheck",{"2":{"231":1,"234":1}}],["type",{"0":{"231":1},"2":{"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"37":1,"38":1,"49":1,"50":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"113":1,"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"131":1,"132":1,"133":1,"134":1,"136":1,"137":1,"138":1,"231":3,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":2,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"438":1,"457":1}}],["ts",{"2":{"8":2,"190":1,"299":1,"312":1,"347":1,"359":1,"361":2,"364":1,"365":1,"366":1,"373":2,"375":2,"376":2,"391":1,"395":1,"426":1,"454":2,"455":3,"457":1,"458":1,"460":1,"467":1}}],["trim",{"2":{"324":2}}],["triggering",{"2":{"4":1}}],["triggered",{"2":{"2":1,"9":1}}],["troubleshooting",{"0":{"352":1},"1":{"353":1,"354":1,"355":1},"2":{"319":1}}],["traffic",{"2":{"309":1,"342":1,"407":1,"408":1,"411":1,"462":1,"466":1,"479":1}}],["traditional",{"2":{"309":1,"343":1,"410":1,"412":1,"461":1}}],["tracks",{"2":{"407":1}}],["tracking",{"2":{"323":1}}],["track",{"2":{"190":1,"203":1,"205":1}}],["transition",{"2":{"342":1}}],["transforms",{"2":{"297":1}}],["transformations",{"0":{"484":1},"1":{"485":1,"486":1},"2":{"190":1}}],["translating",{"2":{"206":2}}],["translationfile",{"2":{"190":2,"483":1}}],["translationdir",{"0":{"317":1},"2":{"152":1,"188":1,"208":2,"299":1,"312":1,"347":1,"353":1,"359":1,"361":1,"364":1,"373":1,"426":1,"467":1}}],["translationobject>>",{"2":{"386":1}}],["translationobject",{"2":{"31":2}}],["translation",{"0":{"10":1,"125":1,"161":1,"163":1,"165":1,"193":1,"212":1,"275":1,"285":1,"286":1,"295":1,"296":1,"298":1,"305":1,"348":1,"353":1,"419":1,"471":1},"1":{"162":1,"163":1,"164":1,"165":1,"287":1,"288":1,"472":1,"473":1,"474":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1},"2":{"6":1,"7":1,"9":1,"16":4,"17":4,"18":4,"30":3,"37":1,"40":1,"42":1,"43":1,"46":1,"89":1,"91":1,"97":1,"98":1,"99":1,"100":1,"101":3,"103":1,"104":3,"107":3,"108":1,"110":3,"111":1,"118":1,"151":1,"161":1,"162":1,"164":1,"166":2,"170":1,"173":1,"174":1,"176":1,"184":4,"188":1,"190":12,"191":1,"192":5,"193":1,"195":1,"196":1,"197":1,"198":2,"199":1,"200":1,"201":2,"202":2,"203":2,"204":7,"205":6,"206":3,"208":1,"210":1,"211":2,"212":2,"213":1,"221":1,"248":1,"253":2,"255":2,"256":1,"259":1,"260":1,"272":1,"275":1,"276":2,"283":1,"285":3,"287":1,"289":4,"291":1,"292":1,"298":3,"299":3,"301":1,"302":3,"304":1,"305":1,"307":2,"313":1,"317":2,"324":3,"329":1,"331":1,"332":1,"337":1,"340":3,"342":1,"343":1,"344":1,"348":1,"353":2,"397":1,"407":1,"411":1,"412":1,"419":1,"420":2,"421":1,"429":3,"432":1,"434":1,"460":1,"462":2,"463":1,"466":1,"470":1,"472":1,"474":1,"479":1,"480":2,"481":3,"482":2}}],["translations",{"0":{"6":1,"128":1,"166":1,"257":1,"300":1,"306":1,"307":1,"383":1,"391":1,"428":1,"430":1,"431":1},"1":{"7":1,"8":1,"9":1,"10":1,"167":1,"168":1,"169":1,"301":1,"302":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"429":1,"430":1,"431":1,"432":2,"433":1,"434":1,"435":1},"2":{"1":2,"2":8,"3":2,"4":3,"5":1,"6":1,"7":1,"8":9,"9":6,"10":2,"16":1,"30":2,"31":8,"35":1,"37":1,"46":1,"89":1,"116":1,"119":2,"122":2,"128":1,"166":1,"184":2,"190":5,"191":2,"192":2,"200":1,"204":3,"205":2,"206":2,"214":1,"248":2,"253":1,"254":3,"255":1,"257":2,"261":2,"268":1,"276":1,"277":1,"279":2,"280":1,"285":2,"288":2,"289":1,"291":2,"292":1,"295":1,"296":2,"297":1,"299":1,"301":4,"304":1,"305":1,"306":2,"313":2,"324":1,"328":1,"331":3,"332":1,"335":4,"340":1,"344":1,"351":1,"359":1,"384":3,"385":1,"387":2,"389":3,"390":4,"391":2,"392":3,"393":1,"397":2,"419":1,"420":2,"421":2,"429":4,"430":2,"460":2,"466":1,"468":1,"471":1,"472":2,"480":1}}],["translator",{"2":{"193":1}}],["translatable",{"2":{"190":1,"482":1}}],["translate",{"0":{"192":1},"1":{"193":1,"194":1},"2":{"125":1,"192":5,"193":9,"194":2,"206":3,"429":1,"431":1,"457":1}}],["translates",{"2":{"116":1,"117":1,"192":1,"460":3}}],["translated",{"2":{"96":1,"107":1,"191":1,"255":1,"432":1}}],["true",{"0":{"332":1},"2":{"100":2,"108":1,"118":1,"131":2,"133":2,"148":2,"150":1,"152":1,"253":1,"254":1,"289":1,"312":1,"315":6,"318":2,"319":1,"320":2,"322":1,"329":1,"330":1,"331":1,"333":1,"334":1,"347":1,"359":2,"361":1,"364":2,"373":2,"375":3,"376":3,"426":2,"467":1}}],["try",{"2":{"8":1}}],["two",{"2":{"2":1,"40":1,"175":1,"176":3,"253":2,"255":1,"344":1,"396":1,"407":1,"418":1}}],["thrilled",{"2":{"470":1,"471":1}}],["throughput",{"0":{"478":1},"2":{"407":1}}],["through",{"2":{"10":1,"40":1,"56":1,"88":1,"184":1,"205":1,"218":1,"251":1,"275":1,"285":1,"291":1,"326":1,"338":1,"340":1,"423":1,"437":1,"451":1}}],["throughout",{"2":{"9":1}}],["thoroughly",{"2":{"351":1,"380":1}}],["those",{"2":{"284":1}}],["than",{"2":{"340":1,"440":1}}],["thanks",{"2":{"466":1}}],["thank",{"2":{"165":1,"216":1}}],["that",{"2":{"2":1,"5":1,"10":1,"17":1,"20":1,"31":2,"37":1,"40":1,"46":1,"47":1,"64":1,"65":1,"66":1,"71":1,"75":1,"88":2,"89":1,"101":1,"129":1,"146":1,"147":2,"172":2,"177":1,"179":1,"182":1,"187":1,"204":3,"208":1,"213":1,"216":1,"223":1,"237":1,"242":1,"246":1,"284":1,"289":1,"292":1,"295":2,"296":2,"297":1,"301":1,"309":1,"315":2,"326":1,"329":1,"330":1,"335":1,"340":1,"350":2,"351":3,"353":2,"354":2,"355":2,"357":1,"361":2,"367":1,"372":1,"374":3,"378":1,"379":2,"380":1,"382":1,"384":1,"387":1,"397":1,"407":1,"408":2,"412":1,"415":1,"418":1,"419":1,"420":1,"423":2,"425":1,"440":1,"441":1,"442":1,"443":2,"446":1,"447":3,"449":1,"451":1,"457":2,"460":1,"465":1,"466":1,"467":1}}],["third",{"2":{"163":1,"175":1}}],["this",{"0":{"408":1},"2":{"1":1,"7":1,"9":1,"10":1,"26":1,"31":6,"42":1,"50":1,"52":1,"54":1,"57":1,"61":1,"73":1,"74":1,"93":1,"94":1,"95":1,"103":1,"104":1,"105":1,"132":1,"147":1,"149":2,"150":1,"151":1,"154":1,"160":1,"161":1,"162":2,"163":3,"164":1,"165":1,"172":1,"177":1,"179":1,"181":1,"184":1,"186":1,"190":1,"192":1,"201":1,"202":1,"204":1,"205":4,"214":1,"216":1,"227":1,"228":1,"230":1,"231":1,"232":1,"239":1,"248":1,"251":1,"254":3,"256":1,"257":1,"261":1,"263":1,"270":1,"275":1,"277":1,"282":2,"283":2,"284":1,"285":1,"287":1,"289":1,"291":2,"292":1,"295":1,"296":1,"297":1,"299":2,"301":1,"304":1,"305":1,"306":1,"315":4,"320":1,"323":2,"326":1,"327":1,"335":1,"338":2,"339":1,"340":2,"342":1,"358":1,"361":2,"366":1,"367":2,"369":1,"370":1,"372":1,"378":1,"379":1,"382":1,"384":1,"387":2,"389":2,"392":3,"396":2,"397":2,"410":1,"417":1,"418":1,"419":1,"420":1,"423":1,"425":1,"429":2,"430":1,"432":1,"437":1,"440":2,"441":2,"442":1,"443":1,"445":1,"446":1,"447":1,"451":1,"453":1,"454":1,"458":1,"459":1,"470":1,"471":1,"480":1}}],["then",{"2":{"283":1,"289":2,"467":1,"480":1}}],["there",{"2":{"229":1,"231":1,"238":1,"270":1,"284":1,"444":1,"446":1}}],["they",{"2":{"204":1,"205":1,"269":1,"283":1,"348":1,"351":1,"366":1,"379":1,"408":1,"437":1}}],["their",{"2":{"31":1,"46":1,"161":1,"164":1,"179":1,"201":1,"203":1,"266":1,"315":4,"380":1,"381":1,"389":1,"427":1,"443":1,"482":1}}],["them",{"2":{"8":1,"162":1,"190":1,"195":1,"199":1,"205":2,"229":1,"256":1,"257":2,"302":1,"307":1,"380":1,"392":1}}],["these",{"2":{"4":1,"31":1,"32":1,"40":1,"55":1,"56":1,"75":1,"88":1,"289":2,"291":1,"295":1,"296":1,"315":2,"389":1,"411":2,"415":1,"426":1,"444":1,"449":1,"460":1,"465":1}}],["the",{"0":{"7":1,"8":1,"149":1,"218":1,"219":1,"225":1,"227":1,"228":1,"229":1,"232":1,"233":1,"283":2,"286":1,"299":1,"359":1,"361":1,"372":1,"375":1,"376":1,"377":1,"452":1},"1":{"287":1,"288":1,"373":1,"453":1,"454":1,"455":1},"2":{"1":2,"2":13,"3":2,"4":7,"5":2,"7":2,"8":2,"9":15,"10":2,"12":2,"13":1,"14":1,"15":6,"16":5,"17":5,"18":8,"19":6,"20":5,"21":4,"22":5,"23":2,"24":1,"25":7,"26":19,"28":5,"29":4,"30":5,"31":12,"35":1,"37":2,"38":1,"40":4,"45":3,"47":3,"49":2,"50":4,"52":2,"53":4,"54":2,"55":3,"56":2,"57":1,"59":2,"60":1,"61":1,"63":1,"64":3,"65":3,"66":3,"68":2,"69":3,"70":2,"71":4,"75":4,"76":1,"77":2,"78":2,"79":1,"80":1,"81":2,"82":2,"83":1,"84":1,"85":2,"86":2,"87":13,"88":11,"89":1,"91":2,"93":1,"94":1,"95":1,"96":2,"97":1,"98":2,"99":2,"100":2,"101":1,"103":1,"104":6,"105":1,"107":3,"108":2,"110":1,"111":3,"112":1,"113":2,"114":1,"115":1,"116":2,"117":2,"118":1,"119":2,"120":2,"121":2,"122":1,"124":2,"126":1,"127":1,"129":4,"130":1,"131":3,"132":3,"134":1,"135":2,"136":1,"138":1,"141":1,"145":5,"146":3,"147":3,"148":2,"149":8,"150":7,"151":1,"156":1,"157":1,"160":2,"161":1,"163":3,"164":3,"166":1,"167":1,"172":2,"173":5,"174":1,"175":7,"176":3,"177":4,"179":4,"181":4,"182":1,"184":3,"186":1,"187":1,"188":2,"190":5,"191":3,"192":5,"193":2,"194":3,"196":1,"197":1,"199":1,"201":3,"202":4,"203":4,"204":8,"205":29,"207":1,"208":3,"211":1,"214":2,"216":4,"218":2,"219":4,"220":1,"223":1,"225":1,"226":1,"227":7,"228":4,"229":2,"230":3,"231":1,"232":3,"233":4,"234":11,"236":3,"237":2,"238":1,"239":1,"242":1,"244":4,"245":1,"246":3,"248":1,"249":1,"250":1,"251":1,"253":1,"254":9,"255":7,"256":1,"257":2,"261":2,"263":2,"264":4,"265":2,"266":3,"268":2,"269":1,"270":3,"272":2,"275":1,"276":2,"277":1,"280":1,"282":7,"283":4,"284":2,"285":2,"287":3,"288":2,"289":10,"291":1,"292":2,"293":1,"295":1,"296":2,"298":6,"299":4,"301":5,"302":4,"311":2,"312":1,"313":1,"314":3,"315":24,"316":2,"317":1,"319":1,"320":2,"321":1,"322":2,"323":4,"325":2,"326":11,"329":2,"330":1,"331":1,"332":4,"333":2,"334":2,"335":5,"336":3,"337":1,"338":5,"339":3,"340":8,"342":1,"343":2,"344":4,"347":1,"348":1,"349":1,"351":1,"353":4,"354":3,"355":1,"357":1,"358":4,"359":4,"360":3,"361":7,"363":1,"365":3,"366":7,"367":5,"369":1,"372":2,"373":1,"374":2,"375":4,"376":4,"377":4,"378":6,"379":3,"380":5,"381":1,"382":2,"384":1,"385":2,"387":4,"388":1,"389":4,"390":3,"391":3,"392":10,"393":4,"396":5,"397":6,"407":14,"408":5,"410":1,"412":4,"415":3,"417":1,"418":2,"419":2,"420":4,"421":6,"423":2,"425":13,"426":1,"427":5,"429":10,"430":2,"431":1,"432":6,"433":1,"434":1,"435":2,"437":5,"438":4,"440":9,"441":8,"442":4,"443":11,"444":1,"445":5,"446":2,"447":7,"448":2,"449":1,"451":3,"453":2,"454":2,"455":2,"457":2,"458":3,"459":3,"460":15,"461":2,"462":2,"463":2,"465":1,"466":3,"467":1,"471":1,"472":2,"474":1,"478":2,"480":1,"486":1}}],["tocontain",{"2":{"458":3}}],["tostring",{"2":{"324":2,"458":1}}],["towards",{"2":{"246":1}}],["tokens",{"2":{"192":1,"194":1}}],["token",{"2":{"192":2,"194":2,"206":2,"251":1,"253":2,"254":3}}],["total",{"2":{"191":1,"413":2,"464":2}}],["tools",{"2":{"275":1,"280":1,"453":1}}],["tool",{"2":{"184":1}}],["toggle",{"2":{"88":1}}],["toggles",{"2":{"65":1}}],["together",{"2":{"46":1,"306":1}}],["to=",{"2":{"32":1,"49":2,"50":1,"52":1,"53":1,"54":1,"57":1,"59":1,"60":1,"104":1,"157":2,"159":1,"268":2,"284":1,"285":1,"349":3}}],["tolocale",{"2":{"26":2}}],["to",{"0":{"49":1,"190":1,"243":1,"256":1,"263":1,"283":1,"341":1,"357":1,"371":1,"437":1,"451":1},"1":{"342":1,"343":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"350":1,"351":1,"352":1,"353":1,"354":1,"355":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1},"2":{"1":2,"2":2,"3":2,"5":1,"6":2,"7":1,"8":2,"9":2,"10":2,"15":2,"16":2,"17":2,"18":2,"19":3,"20":3,"21":3,"22":3,"25":5,"26":12,"28":2,"29":2,"30":1,"31":10,"32":3,"35":1,"37":1,"38":2,"40":1,"46":1,"50":2,"52":2,"53":1,"60":1,"63":1,"64":2,"65":2,"67":1,"68":3,"69":1,"70":1,"75":3,"89":1,"91":1,"93":1,"94":1,"95":1,"96":1,"98":1,"101":1,"104":1,"109":1,"110":1,"111":3,"116":2,"117":1,"120":1,"121":1,"126":1,"127":1,"129":1,"130":1,"131":1,"132":1,"134":1,"136":2,"148":1,"149":3,"150":4,"151":2,"152":1,"154":2,"161":2,"165":1,"167":1,"170":1,"171":2,"174":1,"176":2,"177":1,"179":2,"181":2,"184":3,"188":1,"190":13,"191":2,"192":5,"197":1,"199":1,"200":2,"202":1,"203":2,"205":6,"210":1,"211":1,"212":1,"213":1,"214":3,"216":3,"218":2,"219":2,"220":1,"225":2,"227":2,"228":1,"229":3,"230":2,"231":1,"232":2,"233":2,"234":1,"236":1,"237":1,"238":2,"239":1,"242":1,"243":1,"244":2,"245":1,"248":1,"249":2,"254":2,"255":2,"256":1,"257":2,"259":1,"260":1,"261":4,"263":2,"264":2,"268":2,"269":2,"270":2,"276":2,"278":1,"279":1,"280":1,"282":3,"283":4,"284":1,"288":1,"289":5,"291":1,"296":5,"299":3,"301":1,"302":3,"304":2,"306":1,"307":1,"309":2,"311":1,"312":1,"313":1,"314":1,"315":11,"319":1,"320":1,"322":1,"323":1,"325":1,"326":2,"328":1,"329":1,"331":2,"335":5,"336":1,"337":1,"338":3,"340":1,"342":3,"344":1,"346":1,"348":1,"349":1,"350":2,"351":2,"357":1,"360":2,"361":3,"365":1,"366":3,"367":2,"369":1,"370":2,"374":1,"377":2,"378":2,"379":2,"380":2,"381":2,"382":2,"384":2,"385":2,"389":4,"390":3,"391":2,"392":5,"393":3,"396":3,"397":1,"407":10,"408":2,"410":1,"411":2,"412":2,"414":1,"415":2,"417":1,"420":1,"421":6,"423":2,"425":1,"426":2,"427":2,"429":3,"430":2,"433":2,"437":3,"440":1,"441":2,"443":1,"444":1,"445":1,"446":2,"447":4,"448":3,"449":2,"451":2,"453":2,"454":2,"455":1,"457":2,"459":3,"460":2,"461":1,"462":2,"463":1,"466":2,"467":2,"470":1,"471":1,"472":1,"479":1,"480":2,"483":2,"485":2,"486":1}}],["evaluate",{"2":{"396":1,"407":1}}],["even",{"2":{"408":1}}],["eventhandler",{"2":{"431":1}}],["event",{"0":{"2":1},"2":{"1":2,"2":2,"3":1,"4":3,"5":1,"8":1,"9":2,"432":2,"434":5}}],["events",{"0":{"0":1},"1":{"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1}}],["every",{"2":{"326":1,"442":3,"443":1,"465":1}}],["everything",{"2":{"228":1,"230":1}}],["equips",{"2":{"280":1}}],["elapsed",{"2":{"413":2,"464":2}}],["eliminating",{"2":{"369":1}}],["eliminates",{"2":{"275":1,"382":1,"420":1}}],["elements",{"2":{"68":1,"295":1}}],["element",{"2":{"38":1,"65":1,"66":1,"67":1,"447":1}}],["editor",{"2":{"275":1}}],["edit",{"2":{"275":1}}],["editing",{"0":{"275":1},"2":{"279":1}}],["either",{"2":{"204":1,"315":2}}],["effective",{"2":{"423":1}}],["effectively",{"2":{"184":1,"214":1,"284":1,"291":1,"460":1}}],["efficiency",{"2":{"310":1,"397":1,"411":1,"463":1,"466":1}}],["efficient",{"0":{"418":1},"2":{"111":1,"261":1,"272":1,"280":1,"291":1,"369":1,"415":1,"461":1,"466":1,"471":1,"480":1,"481":1}}],["efficiently",{"2":{"10":1,"301":1,"382":1,"396":1,"407":1,"420":1,"472":1,"474":1}}],["effortlessly",{"2":{"274":1}}],["efforts",{"2":{"214":1,"261":1}}],["empty",{"2":{"31":1,"100":1,"108":1,"387":1}}],["easy",{"2":{"31":1,"111":1,"150":1,"392":1,"466":1}}],["easier",{"2":{"10":1,"203":1,"248":1,"306":1,"367":1,"459":1}}],["easily",{"2":{"5":1,"88":1,"216":1,"279":1,"297":1,"369":1,"382":1}}],["each",{"0":{"377":1},"2":{"31":3,"63":1,"67":1,"83":1,"84":1,"85":1,"86":1,"87":4,"88":2,"162":1,"191":1,"204":2,"205":1,"240":1,"269":1,"304":1,"315":3,"327":1,"338":1,"339":1,"344":1,"355":1,"362":1,"363":1,"366":1,"367":1,"370":1,"374":1,"377":1,"378":3,"379":1,"380":1,"387":3,"389":1,"407":3,"408":1,"414":1,"418":1,"425":2,"459":1,"466":1}}],["erster",{"2":{"27":2}}],["errors",{"0":{"354":1},"2":{"231":1,"237":1,"238":1,"279":1,"289":5}}],["error",{"2":{"8":4,"9":1,"221":1,"289":1,"403":1,"404":1,"405":1,"407":1,"445":2}}],["etc",{"2":{"19":1,"205":1,"289":1,"327":1,"425":1,"440":1}}],["essential",{"2":{"291":1,"344":1,"358":1,"397":1,"423":2,"479":1}}],["es",{"2":{"26":1,"38":1,"208":3,"315":6,"337":3,"365":3,"366":1,"373":3,"375":3,"376":3}}],["eslint",{"2":{"8":2}}],["especially",{"2":{"6":1,"10":1,"270":1,"282":1,"283":1,"285":1,"304":1,"305":1,"307":1,"323":1,"342":1,"360":1,"407":1,"446":1,"462":1}}],["execution",{"2":{"396":1}}],["except",{"0":{"441":1},"2":{"326":2,"441":3,"443":1,"445":1,"449":1}}],["exactly",{"2":{"205":1}}],["examplecomponent",{"2":{"458":6}}],["examples",{"0":{"151":1,"206":1,"241":1},"1":{"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1},"2":{"26":1,"151":1}}],["example",{"0":{"3":1,"32":1,"41":1,"51":1,"72":1,"102":1,"110":1,"123":1,"139":1,"148":1,"155":1,"158":1,"159":1,"160":1,"162":1,"163":1,"164":1,"165":1,"167":1,"169":1,"170":1,"171":1,"173":1,"174":1,"176":1,"178":1,"180":1,"182":1,"208":1,"265":1,"268":1,"359":1,"361":1,"363":1,"375":1,"376":1,"388":1,"391":1,"432":1,"434":1,"457":1,"484":1},"1":{"42":1,"43":1,"44":1,"52":1,"53":1,"54":1,"73":1,"74":1,"103":1,"104":1,"105":1,"124":1,"125":1,"126":1,"127":1,"128":1,"140":1,"141":1,"142":1,"143":1,"149":1,"150":1,"171":1,"364":1,"365":1,"366":1,"485":1,"486":1},"2":{"3":1,"4":1,"8":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"27":1,"28":1,"29":1,"30":1,"31":3,"32":1,"33":1,"34":1,"37":1,"49":1,"50":1,"52":1,"54":3,"57":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"74":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"104":1,"113":1,"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"131":1,"132":1,"133":1,"134":2,"136":1,"137":1,"138":2,"148":1,"149":1,"150":1,"154":1,"160":1,"161":1,"162":1,"164":1,"173":1,"190":2,"191":1,"192":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":4,"253":1,"254":1,"255":1,"264":1,"265":1,"284":1,"285":3,"288":3,"289":3,"293":1,"295":1,"296":2,"298":3,"299":1,"301":1,"306":1,"315":8,"316":1,"317":1,"318":1,"319":1,"320":1,"321":2,"322":1,"324":1,"327":1,"328":1,"329":1,"330":1,"331":1,"333":1,"334":1,"335":1,"337":1,"338":1,"339":1,"347":1,"348":1,"359":1,"366":1,"377":3,"390":1,"391":1,"397":2,"432":1,"440":2,"441":1,"442":1,"443":1,"445":1,"446":1,"447":2,"451":2,"457":1,"458":1,"483":1}}],["existence",{"2":{"162":1}}],["exists",{"2":{"118":3,"460":1}}],["existing",{"2":{"2":1,"4":1,"30":1,"119":1,"190":2,"192":1,"206":1,"218":1,"236":1,"238":1,"347":1,"481":1}}],["extra",{"2":{"197":1}}],["extraction",{"2":{"212":1,"481":1}}],["extracting",{"2":{"15":1,"206":1}}],["extracts",{"2":{"190":2,"195":1,"482":1}}],["extracted",{"2":{"150":1,"190":1}}],["extract",{"0":{"195":1},"2":{"15":1,"184":1,"195":2,"206":1}}],["extensions",{"2":{"190":1}}],["extending",{"0":{"361":1},"2":{"361":1,"370":1}}],["extended",{"2":{"357":1,"361":1}}],["extends",{"2":{"116":1,"361":1,"365":1,"366":1,"375":1,"376":1}}],["extend",{"2":{"7":2,"10":1,"176":1,"360":1,"367":1,"466":1}}],["externally",{"2":{"288":1}}],["external",{"0":{"54":1},"2":{"6":1,"47":1,"54":1,"184":1,"192":1,"200":1,"275":1,"276":1,"315":2}}],["explicit",{"2":{"315":1,"440":1}}],["explains",{"2":{"423":1}}],["explain",{"2":{"291":1}}],["explanation",{"0":{"4":1,"9":1,"149":1,"175":1,"294":1,"392":1,"407":1},"1":{"295":1,"296":1},"2":{"31":1,"283":1}}],["expression",{"2":{"205":1}}],["expressions",{"2":{"205":1}}],["exposes",{"2":{"40":1}}],["exported",{"2":{"201":1}}],["exports",{"2":{"200":1,"201":1}}],["export",{"0":{"200":1,"201":1,"276":1},"2":{"8":1,"200":2,"201":3,"276":1,"361":2,"364":1,"365":1,"366":1,"373":1,"375":1,"376":1,"432":1,"434":1,"454":2,"455":1}}],["expand",{"2":{"10":1}}],["expert",{"2":{"171":1}}],["expertise",{"2":{"171":1}}],["experiences",{"2":{"280":1}}],["experience",{"2":{"5":1,"10":1,"31":2,"60":1,"214":1,"264":1,"269":1,"270":1,"379":1,"389":1,"392":1,"393":1,"415":1,"423":1,"425":1,"427":2,"449":1,"470":1,"479":2}}],["expected",{"2":{"9":1,"230":1,"282":1,"289":1,"351":1,"451":1,"459":1,"460":1}}],["expect",{"2":{"8":1,"458":4}}],["e",{"2":{"2":1,"9":1,"22":1,"23":1,"24":1,"28":1,"29":1,"113":1,"115":1,"116":1,"117":1,"118":1,"147":1,"176":1,"181":1,"190":1,"192":2,"205":1,"269":1,"288":1,"289":2,"295":1,"296":1,"315":1,"327":1,"363":1,"387":1,"396":1,"425":1,"433":1,"440":1,"441":1,"443":1,"445":1,"447":3,"466":1}}],["endpoints",{"2":{"407":1}}],["endpoint",{"2":{"335":1}}],["env",{"2":{"335":1}}],["environments",{"2":{"342":1,"408":2,"411":1,"462":1}}],["environment",{"0":{"452":1},"1":{"453":1,"454":1,"455":1},"2":{"213":1,"227":1,"233":1,"234":1,"277":1,"279":1,"440":1,"451":1,"455":1}}],["encounter",{"2":{"214":1,"320":1,"408":1,"445":1}}],["encapsulate",{"2":{"10":1}}],["enter",{"2":{"192":1}}],["entries",{"2":{"190":2,"481":1}}],["entities",{"2":{"172":1}}],["entirely",{"2":{"338":2,"397":1}}],["entire",{"2":{"5":1,"107":1,"295":1,"313":1,"358":1,"359":1}}],["engine",{"2":{"150":1,"423":1,"425":1,"427":1}}],["engines",{"2":{"147":1,"423":2,"425":2,"427":1}}],["english",{"2":{"4":1,"12":1,"13":1,"63":1,"74":1,"114":1,"152":1,"155":1,"156":1,"264":1,"315":1,"337":1,"339":2,"375":1,"376":1,"425":1,"442":1,"443":1}}],["enable",{"2":{"190":1,"205":2,"318":1,"319":1,"322":1,"375":1,"421":1,"426":1,"430":1}}],["enabled",{"2":{"145":1,"326":1,"332":1,"355":1,"425":1,"443":1}}],["enables",{"2":{"1":1,"99":1,"279":1,"319":1,"323":1,"329":1,"330":1,"392":1,"426":1}}],["enabling",{"2":{"75":1,"89":1,"122":1,"282":1,"415":1,"427":1}}],["ensuring",{"2":{"31":1,"88":1,"146":1,"147":2,"196":1,"214":1,"228":1,"261":2,"264":1,"269":1,"408":1,"420":1,"423":1,"425":1,"429":1,"442":1,"480":1}}],["ensures",{"2":{"204":1,"216":1,"277":1,"282":1,"292":1,"297":1,"301":1,"378":1,"382":1,"419":1,"440":1,"441":1,"442":1,"443":1,"446":1,"447":1}}],["ensure",{"2":{"5":1,"60":1,"150":1,"187":1,"204":1,"207":1,"208":1,"210":1,"213":1,"223":1,"229":1,"230":1,"231":1,"237":1,"238":1,"239":1,"244":1,"246":1,"254":1,"259":1,"270":1,"348":1,"349":1,"350":1,"351":2,"353":1,"367":1,"379":2,"380":1,"389":1,"407":1,"421":1,"426":1,"449":1,"451":1,"459":1,"460":1}}],["enhances",{"2":{"296":1}}],["enhance",{"2":{"75":1,"302":1,"423":1}}],["enhancements",{"0":{"60":1},"2":{"472":1}}],["enhanced",{"0":{"477":1},"2":{"10":1,"470":1,"472":1}}],["enhancing",{"2":{"1":1,"5":1,"31":1,"264":1,"278":1,"379":1,"389":1,"392":1,"419":1}}],["en",{"0":{"163":1,"165":1},"2":{"2":1,"9":1,"12":1,"14":2,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"27":3,"29":1,"31":3,"63":1,"74":1,"113":1,"115":2,"136":1,"137":1,"147":1,"152":3,"155":1,"156":1,"178":2,"180":2,"182":2,"190":2,"208":4,"253":2,"293":3,"295":2,"296":3,"298":3,"301":2,"312":3,"313":3,"315":4,"316":1,"327":1,"332":1,"337":4,"338":2,"339":4,"347":6,"348":3,"359":4,"361":7,"364":4,"365":4,"366":3,"373":3,"375":2,"376":2,"387":1,"388":1,"389":2,"391":1,"426":3,"434":3,"440":1,"441":1,"442":1,"443":2,"458":2,"467":3,"468":3,"483":1}}],["ignored",{"2":{"332":1}}],["ignore",{"2":{"326":1,"440":1}}],["ibm",{"2":{"193":2}}],["i>",{"2":{"77":1,"78":1,"83":1,"85":1,"166":2}}],["i",{"0":{"285":1,"286":1},"1":{"287":1,"288":1},"2":{"77":1,"78":1,"83":1,"85":1}}],["imagine",{"2":{"363":1}}],["immediately",{"2":{"76":1,"79":1,"80":1,"277":1}}],["impacting",{"2":{"462":1}}],["impacts",{"2":{"270":1}}],["impact",{"2":{"242":1,"310":1,"407":1,"411":1,"479":1}}],["improvement",{"2":{"410":1,"474":1,"477":1}}],["improvements",{"2":{"214":1,"216":1,"412":1,"461":1,"471":1}}],["improves",{"2":{"306":1}}],["improved",{"2":{"269":1,"343":1,"417":1,"427":1}}],["improve",{"2":{"129":1,"150":1,"327":1,"342":1,"421":1}}],["improving",{"2":{"10":1,"35":1,"279":1,"420":1,"425":1,"479":1}}],["imported",{"2":{"202":1}}],["important",{"0":{"397":1,"479":1},"2":{"40":1,"304":1}}],["imports",{"2":{"9":1,"31":2,"32":1,"33":1,"34":1,"154":1,"157":1,"162":1,"164":1,"170":1,"173":1,"178":1,"180":1,"182":1,"202":1,"268":1,"289":1,"389":2,"391":1}}],["import",{"0":{"199":1,"202":1,"276":1},"2":{"8":1,"32":1,"154":1,"157":1,"162":1,"164":1,"170":1,"173":1,"178":1,"180":1,"182":1,"199":2,"202":3,"268":1,"276":1,"391":1,"454":3,"455":1,"458":6}}],["implements",{"2":{"420":1}}],["implement",{"0":{"371":1},"1":{"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1}}],["implementations",{"2":{"396":1}}],["implementation",{"2":{"8":1,"315":1,"396":1}}],["implementing",{"0":{"8":1}}],["icon",{"2":{"71":2,"77":1,"78":1,"88":2}}],["idea",{"2":{"218":1}}],["ideal",{"2":{"205":1,"309":1,"384":1,"440":1,"442":1,"466":1}}],["identical",{"2":{"204":1,"412":1,"463":1}}],["identifies",{"2":{"190":1,"203":1,"254":1,"482":1}}],["identifiers",{"2":{"440":1}}],["identifier",{"0":{"141":1},"2":{"141":1,"315":1}}],["identifierattribute",{"0":{"132":1},"2":{"132":1,"141":1,"148":1}}],["identify",{"2":{"132":1}}],["id",{"2":{"27":10,"132":1,"137":1,"138":1,"148":1,"251":1,"253":2,"254":2,"298":11,"328":1}}],["iterates",{"2":{"162":1}}],["iterate",{"2":{"161":1,"164":1}}],["item3",{"2":{"170":1,"171":1}}],["item2",{"2":{"170":1,"171":1}}],["item1",{"2":{"170":1,"171":1}}],["itemcount",{"2":{"101":1,"105":2,"109":1}}],["item|you",{"2":{"92":1}}],["item=",{"2":{"83":1,"84":1}}],["item",{"0":{"83":1,"84":1},"2":{"83":1,"84":1,"87":4,"88":2,"93":2,"94":2,"95":2,"109":1}}],["items`",{"2":{"109":1}}],["items>",{"2":{"81":1,"82":1}}],["items",{"0":{"81":1,"82":1},"2":{"81":1,"82":1,"87":4,"88":1,"92":3,"101":2,"105":1,"109":1,"172":1,"334":2}}],["itself",{"2":{"104":1}}],["its",{"2":{"45":1,"130":1,"162":2,"278":1,"338":1,"340":1,"362":1,"366":1,"396":1,"461":1,"466":1}}],["it",{"0":{"479":1,"480":1,"482":1},"2":{"7":1,"26":2,"31":1,"47":1,"49":1,"50":1,"70":1,"75":1,"89":1,"93":1,"94":1,"95":1,"111":1,"129":1,"150":1,"184":1,"190":2,"191":1,"192":1,"203":1,"204":3,"205":4,"216":1,"218":1,"232":2,"234":1,"236":1,"248":1,"249":1,"272":1,"278":1,"279":1,"284":1,"289":1,"302":1,"306":1,"309":2,"315":6,"335":1,"338":1,"339":1,"344":1,"349":1,"358":1,"367":2,"370":1,"392":1,"393":1,"397":1,"408":1,"410":1,"429":1,"433":1,"440":1,"442":1,"443":1,"447":1,"458":4,"459":2,"461":1,"462":1,"466":2,"467":2}}],["isactive",{"2":{"447":3}}],["issue",{"0":{"286":1},"1":{"287":1,"288":1},"2":{"214":1,"241":1,"447":1}}],["issues",{"0":{"281":1,"352":1,"444":1,"446":1,"447":1},"1":{"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1,"289":1,"353":1,"354":1,"355":1,"445":1,"446":1,"447":1},"2":{"214":1,"218":1,"229":1,"234":2,"244":1,"283":1,"305":1,"320":1,"323":1,"411":1,"444":1,"446":2,"447":2,"449":1,"462":2}}],["isolate",{"2":{"381":1}}],["isolating",{"2":{"283":1}}],["isocode",{"2":{"327":1}}],["iso",{"2":{"14":3,"115":2,"152":3,"208":3,"312":3,"315":8,"337":3,"347":4,"355":1,"359":3,"361":5,"364":2,"365":3,"366":3,"373":3,"375":4,"376":4,"426":3,"467":3}}],["is",{"0":{"272":1,"283":1,"284":1},"2":{"4":1,"6":1,"9":3,"10":1,"12":1,"15":1,"16":1,"17":1,"18":2,"26":1,"31":3,"42":1,"47":1,"53":1,"56":1,"61":1,"71":1,"89":1,"93":2,"94":2,"95":2,"98":1,"100":1,"104":1,"107":1,"108":1,"110":1,"111":1,"116":1,"117":1,"129":1,"132":1,"145":1,"146":1,"147":1,"149":2,"150":2,"162":1,"163":3,"165":1,"166":1,"172":1,"175":3,"177":1,"179":1,"181":1,"182":1,"184":1,"187":1,"190":1,"191":1,"201":1,"202":1,"204":1,"205":3,"208":1,"228":1,"230":1,"245":1,"253":1,"256":1,"263":1,"264":1,"272":1,"279":1,"282":1,"284":3,"285":1,"287":1,"289":1,"291":1,"292":1,"295":1,"302":1,"304":1,"309":1,"315":5,"316":1,"323":1,"325":1,"326":1,"332":1,"335":1,"340":3,"355":1,"358":2,"379":1,"380":2,"384":2,"387":5,"389":1,"391":1,"392":1,"396":2,"397":4,"407":5,"408":2,"410":1,"412":1,"415":1,"417":1,"419":1,"423":2,"425":2,"426":1,"429":2,"430":1,"432":1,"437":1,"440":3,"443":2,"445":3,"446":1,"451":1,"459":1,"460":1,"461":1,"466":2,"479":1,"480":1}}],["if=",{"2":{"162":1}}],["if",{"0":{"282":1},"2":{"2":1,"7":1,"8":1,"16":1,"17":1,"18":1,"26":2,"27":1,"31":4,"56":1,"98":1,"100":2,"101":2,"107":1,"108":1,"116":1,"117":1,"118":1,"131":1,"133":1,"147":1,"150":1,"176":1,"190":1,"192":2,"194":1,"204":2,"205":1,"214":1,"229":1,"233":1,"236":1,"238":1,"246":1,"282":1,"284":1,"288":1,"289":1,"299":1,"307":1,"315":3,"316":1,"320":1,"323":1,"324":1,"326":1,"327":1,"335":1,"344":1,"349":1,"355":1,"387":1,"433":1,"434":1,"445":1,"446":1,"447":1,"449":1,"460":1,"466":1}}],["involving",{"2":{"411":1}}],["involve",{"2":{"172":1}}],["inherited",{"2":{"361":2,"365":2,"366":2}}],["inherit",{"2":{"361":1,"365":1,"366":2,"375":1,"376":1}}],["inherits",{"2":{"56":1}}],["initial",{"2":{"420":1}}],["initially",{"2":{"284":1}}],["initialize",{"2":{"249":1,"251":1}}],["initializing",{"0":{"187":1,"251":1}}],["init",{"2":{"251":1}}],["independently",{"2":{"284":1}}],["indexing",{"2":{"150":1,"425":1}}],["index",{"2":{"15":2,"28":2,"32":2,"44":4,"49":1,"104":1,"157":1,"268":2,"284":1,"293":1,"296":2,"301":2,"313":1,"348":1,"349":3,"427":1,"468":1}}],["individual",{"2":{"296":1,"384":1}}],["indispensable",{"2":{"279":1}}],["indicating",{"2":{"173":1}}],["indicator",{"2":{"88":1}}],["indicates",{"2":{"71":1}}],["indicate",{"2":{"69":1,"415":1}}],["inspired",{"0":{"284":1}}],["inspecting",{"2":{"132":1}}],["instruct",{"2":{"299":1}}],["instance",{"2":{"289":2,"360":1,"378":1}}],["installed",{"2":{"207":1,"223":1}}],["install",{"0":{"226":1,"346":1,"453":1},"2":{"186":2,"226":2,"249":1,"250":2,"311":2,"346":1,"453":2,"467":2}}],["installation",{"0":{"185":1,"249":1,"311":1},"1":{"186":1,"187":1,"188":1,"250":1,"251":1},"2":{"312":1}}],["installing",{"0":{"186":1,"250":1},"2":{"184":1,"187":1}}],["instead",{"2":{"55":1,"63":1,"289":1,"299":1,"315":1,"325":1,"335":1,"339":1,"440":1}}],["insertion",{"2":{"89":1}}],["inserts",{"2":{"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"482":1}}],["insert",{"2":{"75":1,"104":1,"205":1}}],["inside",{"2":{"27":1,"59":1,"85":1,"86":1,"87":2,"88":1}}],["inline",{"0":{"53":1,"74":1},"2":{"50":1,"53":1,"55":1,"74":1,"88":1}}],["input",{"2":{"26":1}}],["inform",{"2":{"423":1}}],["information",{"0":{"395":1},"1":{"396":1,"397":1},"2":{"49":1,"190":1,"319":2}}],["info",{"2":{"26":1,"43":1,"188":1}}],["increase",{"2":{"478":1}}],["increased",{"0":{"478":1},"2":{"411":1}}],["incorrectly",{"2":{"447":2}}],["incorporation",{"2":{"2":1}}],["include",{"2":{"315":3,"326":2,"421":1,"441":2,"442":1,"455":1,"462":1}}],["includedefaultlocaleroute",{"0":{"325":1},"2":{"325":1,"437":1}}],["included",{"2":{"149":1}}],["includes",{"2":{"133":1,"354":1,"372":1,"442":1,"470":1}}],["including",{"2":{"20":1,"137":1,"149":1,"201":1,"203":1,"204":1,"205":1,"248":1,"251":1,"314":1,"358":1}}],["intuitive",{"2":{"264":1,"272":1,"279":1}}],["intact",{"2":{"205":1}}],["introduces",{"2":{"437":1,"471":1}}],["introduced",{"2":{"13":1,"15":1,"26":1,"114":1,"190":1,"326":1,"334":1,"448":1,"471":1}}],["introduction",{"0":{"184":1,"216":1,"248":1,"263":1,"291":1,"342":1,"357":1,"369":1,"410":1,"423":1,"437":1,"451":1,"461":1}}],["intro",{"2":{"44":1,"170":1,"171":1}}],["intl",{"2":{"19":5,"20":4,"21":4,"22":4,"177":1,"179":1,"181":1}}],["into",{"2":{"2":2,"4":2,"8":1,"9":2,"16":1,"17":1,"18":1,"30":1,"88":1,"104":1,"119":1,"150":1,"201":1,"205":1,"212":1,"216":1,"245":1,"248":1,"261":2,"272":1,"276":1,"279":1,"280":1,"292":1,"297":1,"298":1,"313":1,"330":1,"344":1,"397":1,"407":1,"468":1,"482":1}}],["intelligent",{"2":{"340":1}}],["intelligently",{"2":{"147":1,"480":1}}],["integrating",{"2":{"248":1}}],["integration",{"0":{"247":1,"278":1},"1":{"248":1,"249":1,"250":1,"251":1,"252":1,"253":1,"254":1,"255":1,"256":1,"257":1,"258":1,"259":1,"260":1,"261":1},"2":{"61":1,"344":1}}],["integrated",{"2":{"216":1,"272":1,"275":1,"280":1}}],["integrates",{"2":{"88":1,"330":1}}],["integrate",{"2":{"1":1,"150":1,"212":1,"261":2}}],["intended",{"2":{"26":1,"351":1,"397":1}}],["interpretation",{"0":{"415":1}}],["interpolation",{"0":{"166":1,"168":1,"169":1},"1":{"167":1,"168":1,"169":1}}],["interpolating",{"2":{"97":1}}],["interpolate",{"2":{"16":1,"17":1,"18":1,"89":1}}],["interpolates",{"2":{"16":1,"17":1}}],["interfere",{"2":{"323":1}}],["interface",{"2":{"2":1,"61":1,"272":1,"279":1,"366":1}}],["internal",{"2":{"287":1,"315":1,"417":1}}],["international",{"2":{"146":1,"147":1}}],["internationalization",{"2":{"1":1,"10":1,"111":1,"112":1,"184":1,"214":1,"261":1,"291":1,"309":1,"314":1,"396":1,"410":1,"461":1}}],["interrupting",{"2":{"275":1}}],["interest",{"2":{"216":1}}],["in",{"0":{"32":1,"187":1,"251":1,"262":1,"265":1,"268":1,"269":1,"271":1,"273":1,"285":1,"289":1,"356":1,"361":1,"362":1,"363":1,"383":1,"428":1,"431":1,"436":1,"438":1,"445":1,"447":1},"1":{"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"272":1,"273":1,"274":2,"275":2,"276":2,"277":2,"278":2,"279":1,"280":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":2,"365":2,"366":2,"367":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"429":1,"430":1,"431":1,"432":2,"433":1,"434":1,"435":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"1":1,"6":1,"8":2,"9":1,"14":1,"19":2,"20":2,"21":1,"22":1,"27":1,"31":5,"32":2,"35":1,"44":1,"45":2,"47":1,"50":1,"54":1,"56":1,"57":1,"61":2,"88":1,"89":1,"91":1,"97":1,"104":2,"111":1,"115":1,"129":1,"135":1,"149":2,"151":1,"154":1,"160":1,"161":1,"162":2,"164":2,"170":1,"171":1,"172":2,"173":1,"174":1,"177":1,"178":2,"179":1,"180":2,"182":4,"184":1,"187":2,"190":4,"191":1,"192":1,"195":1,"199":1,"201":1,"202":1,"203":1,"204":2,"205":5,"207":1,"214":2,"216":1,"219":2,"227":1,"232":1,"233":1,"234":1,"236":1,"244":1,"246":1,"251":1,"254":3,"255":2,"256":1,"257":2,"263":1,"265":1,"266":1,"270":2,"274":1,"282":1,"283":4,"284":1,"289":7,"297":2,"298":3,"299":3,"311":1,"315":7,"324":1,"326":1,"327":1,"329":1,"332":2,"339":2,"340":1,"342":1,"344":3,"347":1,"348":1,"353":2,"354":2,"355":1,"357":1,"359":1,"360":1,"361":3,"362":1,"365":1,"366":2,"367":3,"369":1,"370":1,"375":1,"376":1,"381":1,"382":1,"384":1,"389":1,"392":2,"397":3,"408":2,"410":2,"411":1,"421":1,"425":1,"426":1,"429":3,"431":1,"432":1,"435":1,"437":2,"438":1,"440":1,"442":2,"443":1,"444":1,"445":1,"447":3,"448":2,"449":1,"457":1,"461":1,"462":3,"465":1,"466":1,"467":2,"471":1,"480":1,"482":1,"485":1,"486":1}}],["i18nutils",{"2":{"454":26}}],["i18nlink",{"0":{"285":1},"2":{"285":1}}],["i18n",{"0":{"1":1,"35":1,"47":1,"61":1,"89":1,"151":1,"156":1,"157":1,"166":1,"167":1,"183":1,"186":1,"190":1,"262":1,"271":1,"273":1,"284":2,"289":1,"308":1,"310":1,"341":2,"346":1,"356":1,"368":1,"383":1,"399":1,"400":1,"403":1,"404":1,"405":2,"422":1,"428":1,"436":1,"450":1,"453":1,"460":1,"462":1,"470":1},"1":{"2":1,"3":1,"4":1,"5":1,"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"71":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1,"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":1,"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":2,"159":2,"160":2,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":2,"168":2,"169":2,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1,"184":1,"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1,"209":1,"210":1,"211":1,"212":1,"213":1,"214":1,"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"272":1,"273":1,"274":2,"275":2,"276":2,"277":2,"278":2,"279":1,"280":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"327":1,"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":1,"337":1,"338":1,"339":1,"342":2,"343":2,"344":2,"345":2,"346":2,"347":2,"348":2,"349":2,"350":2,"351":2,"352":2,"353":2,"354":2,"355":2,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"369":1,"370":1,"371":1,"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1,"401":1,"423":1,"424":1,"425":1,"426":1,"427":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"435":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"463":1,"464":1,"465":1},"2":{"1":3,"3":2,"4":2,"5":1,"8":2,"9":2,"34":1,"35":2,"42":2,"43":2,"44":2,"45":2,"46":8,"47":2,"49":4,"50":2,"52":2,"53":2,"54":2,"57":2,"59":2,"60":2,"61":2,"63":2,"64":2,"65":2,"66":2,"67":2,"68":2,"69":2,"70":2,"71":2,"73":1,"74":1,"75":1,"76":2,"77":2,"78":2,"79":2,"80":2,"81":2,"82":2,"83":2,"84":2,"85":2,"86":2,"88":1,"89":2,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"98":2,"99":1,"100":2,"101":2,"103":1,"104":4,"105":1,"107":2,"108":2,"109":2,"110":2,"111":1,"129":1,"132":1,"137":1,"138":1,"141":1,"151":4,"152":3,"156":2,"157":5,"159":2,"161":1,"166":3,"168":2,"172":1,"184":3,"186":3,"187":2,"190":6,"207":3,"208":3,"212":1,"214":1,"216":1,"219":1,"220":2,"225":3,"244":1,"246":1,"263":1,"272":1,"278":1,"280":1,"282":1,"284":8,"285":5,"289":3,"291":3,"292":1,"297":1,"299":5,"301":1,"302":1,"309":1,"310":1,"311":1,"312":2,"314":1,"317":1,"326":1,"327":1,"335":1,"337":1,"340":1,"342":4,"343":2,"344":6,"346":2,"347":9,"349":2,"350":2,"357":1,"358":1,"359":1,"361":2,"362":1,"363":1,"364":1,"365":1,"366":2,"369":1,"373":1,"375":1,"376":1,"382":1,"384":1,"391":1,"395":4,"396":3,"397":3,"398":2,"401":2,"402":2,"407":2,"408":1,"410":4,"411":2,"412":3,"413":2,"414":2,"415":1,"417":1,"418":2,"420":1,"421":1,"423":2,"425":1,"426":2,"429":3,"437":1,"451":1,"453":3,"454":3,"459":3,"460":2,"461":4,"462":3,"463":1,"464":2,"465":3,"466":2,"467":4,"471":1,"483":2}}],["📏",{"2":{"466":1}}],["💼",{"2":{"462":1}}],["🐢",{"2":{"462":1}}],["🚨",{"2":{"462":1}}],["🛑",{"0":{"440":1}}],["👥",{"2":{"427":1}}],["🔖",{"2":{"425":1}}],["🗄️",{"2":{"420":1}}],["🕒",{"2":{"415":1}}],["🔋",{"2":{"415":1}}],["🗜️",{"2":{"415":1}}],["📈",{"2":{"344":1,"427":1}}],["📉",{"2":{"343":1,"421":1}}],["👀",{"0":{"333":1,"334":1}}],["🐛",{"0":{"319":1,"320":1},"2":{"462":1}}],["🗂",{"0":{"317":1,"468":1},"2":{"466":1}}],["🗂️",{"0":{"30":1,"201":1,"252":1,"292":1,"306":1,"348":1,"356":1,"436":1},"1":{"253":1,"254":1,"255":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"437":1,"438":1,"439":1,"440":1,"441":1,"442":1,"443":1,"444":1,"445":1,"446":1,"447":1,"448":1,"449":1},"2":{"344":1,"421":1}}],["💾",{"0":{"302":1,"420":1},"2":{"421":1}}],["📂",{"0":{"254":1,"255":1,"290":1,"297":1,"304":1,"313":1,"332":1,"419":1},"1":{"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":2,"299":1,"300":1,"301":1,"302":1,"303":1,"304":1,"305":1,"306":1,"307":1}}],["💬",{"2":{"246":1}}],["🕵️‍♂️",{"0":{"245":1}}],["🚧",{"0":{"235":1,"441":1},"1":{"236":1,"237":1,"238":1,"239":1,"240":1,"241":1,"242":1,"243":1,"244":1,"245":1,"246":1}}],["🖥️",{"0":{"227":1}}],["📞",{"0":{"214":1}}],["🛡️",{"0":{"213":1,"352":1},"1":{"353":1,"354":1,"355":1}}],["🔑",{"0":{"208":1,"210":1,"259":1,"305":1,"425":1,"466":1}}],["📑",{"0":{"202":1}}],["📥",{"0":{"200":1,"220":1,"225":1}}],["📤",{"0":{"199":1}}],["📊",{"0":{"191":1,"406":1,"412":1,"460":1},"1":{"407":1,"408":1,"413":1,"414":1,"415":1}}],["📋",{"0":{"189":1,"241":1,"435":1},"1":{"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1}}],["📄",{"0":{"188":1,"253":1,"265":1,"268":1,"294":1,"296":1,"359":1,"361":1,"363":1},"1":{"295":1,"296":1,"364":1,"365":1,"366":1}}],["🛠",{"0":{"187":1,"206":1,"212":1,"223":1,"251":1,"261":1,"299":1,"311":1,"371":1,"408":1},"1":{"372":1,"373":1,"374":1,"375":1,"376":1,"377":1,"378":1,"379":1,"380":1}}],["🛠️",{"0":{"4":1,"6":1,"11":1,"33":1,"41":1,"51":1,"72":1,"102":1,"111":1,"123":1,"135":1,"139":1,"148":1,"152":1,"195":1,"222":1,"242":1,"269":1,"271":1,"279":1,"345":1,"346":1,"350":1,"358":1,"417":1,"426":1,"430":1,"452":1},"1":{"7":1,"8":1,"9":1,"10":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"42":1,"43":1,"44":1,"52":1,"53":1,"54":1,"73":1,"74":1,"103":1,"104":1,"105":1,"112":1,"113":1,"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"123":1,"124":2,"125":2,"126":2,"127":2,"128":2,"136":1,"137":1,"138":1,"140":1,"141":1,"142":1,"143":1,"149":1,"150":1,"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1,"272":1,"273":1,"274":1,"275":1,"276":1,"277":1,"278":1,"279":1,"280":1,"346":1,"347":1,"348":1,"349":1,"350":1,"351":1,"359":1,"453":1,"454":1,"455":1},"2":{"466":1}}],["📦",{"0":{"186":1,"226":1,"250":1},"2":{"310":1}}],["🔧",{"0":{"185":1,"234":1,"249":1,"293":1},"1":{"186":1,"187":1,"188":1,"250":1,"251":1},"2":{"270":1,"343":1,"367":1,"427":1,"459":1}}],["📖",{"0":{"184":1,"216":1,"248":1,"263":1,"272":1,"291":1,"309":1,"342":1,"357":1,"383":1,"410":1,"423":1,"429":1,"437":1,"451":1},"1":{"384":1,"385":1,"386":1,"387":1,"388":1,"389":1,"390":1,"391":1,"392":1,"393":1}}],["🗓️",{"0":{"179":1,"181":1},"1":{"180":1,"182":1}}],["📚",{"0":{"151":1,"218":1,"232":1,"449":1},"1":{"152":1,"153":1,"154":1,"155":1,"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"174":1,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"181":1,"182":1},"2":{"270":1,"367":1,"459":1}}],["🔌",{"0":{"75":1},"1":{"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1}}],["🚀",{"0":{"46":1,"58":1,"106":1,"144":1,"217":1,"224":1,"243":1,"264":1,"280":1,"343":1,"409":1},"1":{"59":1,"60":1,"107":1,"108":1,"109":1,"110":1,"145":1,"146":1,"147":1,"218":1,"219":1,"220":1,"221":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"265":1,"266":1,"410":1,"411":1,"412":1,"413":1,"414":1,"415":1,"416":1,"417":1,"418":1,"419":1,"420":1,"421":1},"2":{"270":1,"310":1,"470":1}}],["💻",{"0":{"32":1,"236":1}}],["🚦",{"0":{"31":1,"325":1,"326":1,"327":1,"418":1,"438":1}}],["📅",{"0":{"20":1,"21":1,"22":1}}],["🔢",{"0":{"18":1,"19":1,"324":1}}],["🔍",{"0":{"15":1,"16":1,"17":1,"204":1,"231":1,"318":1,"323":1,"344":1,"407":1,"415":1}}],["🔗",{"0":{"5":1,"10":1,"262":1,"321":1,"328":1,"335":1,"349":1},"1":{"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1},"2":{"425":1}}],["💡",{"0":{"3":1,"246":1}}],["📝",{"0":{"2":1,"9":1,"150":1,"161":1,"170":1,"209":1,"239":1,"270":1,"303":1,"367":1,"369":1,"381":1,"421":1,"448":1,"459":1,"462":1},"1":{"162":1,"163":1,"164":1,"165":1,"171":1,"210":1,"211":1,"212":1,"213":1,"240":1,"241":1,"242":1,"304":1,"305":1,"306":1,"307":1,"449":1,"463":1,"464":1,"465":1},"2":{"31":1,"246":1}}],["🔄",{"0":{"1":1,"23":1,"24":1,"25":1,"26":1,"27":1,"29":1,"190":1,"196":1,"205":1,"244":1,"266":1,"331":1,"340":1,"341":1,"347":1,"443":1},"1":{"2":1,"3":1,"4":1,"5":1,"342":1,"343":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"350":1,"351":1,"352":1,"353":1,"354":1,"355":1}}],["📢",{"0":{"0":1},"1":{"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1}}]],"serializationVersion":2}';export{t as default}; diff --git a/assets/chunks/VPLocalSearchBox.DD0Puzcb.js b/assets/chunks/VPLocalSearchBox.DD0Puzcb.js new file mode 100644 index 00000000..ad50cba9 --- /dev/null +++ b/assets/chunks/VPLocalSearchBox.DD0Puzcb.js @@ -0,0 +1,8 @@ +var Ft=Object.defineProperty;var Ot=(a,e,t)=>e in a?Ft(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var Ae=(a,e,t)=>Ot(a,typeof e!="symbol"?e+"":e,t);import{V as Ct,p as ie,h as ge,ah as tt,ai as Rt,aj as At,q as $e,ak as Mt,d as Lt,D as xe,al as nt,am as Dt,an as zt,s as Pt,ao as jt,v as Me,P as fe,O as _e,ap as Vt,aq as $t,W as Bt,R as Wt,$ as Kt,o as H,b as Jt,j as _,a0 as Ut,k as L,ar as qt,as as Gt,at as Ht,c as Z,n as st,e as Se,C as it,F as rt,a as he,t as pe,au as Qt,av as at,aw as Yt,a6 as Zt,ac as Xt,ax as en,_ as tn}from"./framework.Gfs4HC1t.js";import{u as nn,c as sn}from"./theme.CPkZdxnZ.js";const rn={root:()=>Ct(()=>import("./@localSearchIndexroot.D3nW01Zu.js"),[])};/*! +* tabbable 6.2.0 +* @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE +*/var gt=["input:not([inert])","select:not([inert])","textarea:not([inert])","a[href]:not([inert])","button:not([inert])","[tabindex]:not(slot):not([inert])","audio[controls]:not([inert])","video[controls]:not([inert])",'[contenteditable]:not([contenteditable="false"]):not([inert])',"details>summary:first-of-type:not([inert])","details:not([inert])"],Ne=gt.join(","),vt=typeof Element>"u",ae=vt?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,Fe=!vt&&Element.prototype.getRootNode?function(a){var e;return a==null||(e=a.getRootNode)===null||e===void 0?void 0:e.call(a)}:function(a){return a==null?void 0:a.ownerDocument},Oe=function a(e,t){var n;t===void 0&&(t=!0);var s=e==null||(n=e.getAttribute)===null||n===void 0?void 0:n.call(e,"inert"),r=s===""||s==="true",i=r||t&&e&&a(e.parentNode);return i},an=function(e){var t,n=e==null||(t=e.getAttribute)===null||t===void 0?void 0:t.call(e,"contenteditable");return n===""||n==="true"},bt=function(e,t,n){if(Oe(e))return[];var s=Array.prototype.slice.apply(e.querySelectorAll(Ne));return t&&ae.call(e,Ne)&&s.unshift(e),s=s.filter(n),s},yt=function a(e,t,n){for(var s=[],r=Array.from(e);r.length;){var i=r.shift();if(!Oe(i,!1))if(i.tagName==="SLOT"){var o=i.assignedElements(),l=o.length?o:i.children,c=a(l,!0,n);n.flatten?s.push.apply(s,c):s.push({scopeParent:i,candidates:c})}else{var f=ae.call(i,Ne);f&&n.filter(i)&&(t||!e.includes(i))&&s.push(i);var g=i.shadowRoot||typeof n.getShadowRoot=="function"&&n.getShadowRoot(i),h=!Oe(g,!1)&&(!n.shadowRootFilter||n.shadowRootFilter(i));if(g&&h){var b=a(g===!0?i.children:g.children,!0,n);n.flatten?s.push.apply(s,b):s.push({scopeParent:i,candidates:b})}else r.unshift.apply(r,i.children)}}return s},wt=function(e){return!isNaN(parseInt(e.getAttribute("tabindex"),10))},re=function(e){if(!e)throw new Error("No node provided");return e.tabIndex<0&&(/^(AUDIO|VIDEO|DETAILS)$/.test(e.tagName)||an(e))&&!wt(e)?0:e.tabIndex},on=function(e,t){var n=re(e);return n<0&&t&&!wt(e)?0:n},ln=function(e,t){return e.tabIndex===t.tabIndex?e.documentOrder-t.documentOrder:e.tabIndex-t.tabIndex},xt=function(e){return e.tagName==="INPUT"},cn=function(e){return xt(e)&&e.type==="hidden"},un=function(e){var t=e.tagName==="DETAILS"&&Array.prototype.slice.apply(e.children).some(function(n){return n.tagName==="SUMMARY"});return t},dn=function(e,t){for(var n=0;nsummary:first-of-type"),i=r?e.parentElement:e;if(ae.call(i,"details:not([open]) *"))return!0;if(!n||n==="full"||n==="legacy-full"){if(typeof s=="function"){for(var o=e;e;){var l=e.parentElement,c=Fe(e);if(l&&!l.shadowRoot&&s(l)===!0)return ot(e);e.assignedSlot?e=e.assignedSlot:!l&&c!==e.ownerDocument?e=c.host:e=l}e=o}if(mn(e))return!e.getClientRects().length;if(n!=="legacy-full")return!0}else if(n==="non-zero-area")return ot(e);return!1},vn=function(e){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName))for(var t=e.parentElement;t;){if(t.tagName==="FIELDSET"&&t.disabled){for(var n=0;n=0)},yn=function a(e){var t=[],n=[];return e.forEach(function(s,r){var i=!!s.scopeParent,o=i?s.scopeParent:s,l=on(o,i),c=i?a(s.candidates):o;l===0?i?t.push.apply(t,c):t.push(o):n.push({documentOrder:r,tabIndex:l,item:s,isScope:i,content:c})}),n.sort(ln).reduce(function(s,r){return r.isScope?s.push.apply(s,r.content):s.push(r.content),s},[]).concat(t)},wn=function(e,t){t=t||{};var n;return t.getShadowRoot?n=yt([e],t.includeContainer,{filter:Be.bind(null,t),flatten:!1,getShadowRoot:t.getShadowRoot,shadowRootFilter:bn}):n=bt(e,t.includeContainer,Be.bind(null,t)),yn(n)},xn=function(e,t){t=t||{};var n;return t.getShadowRoot?n=yt([e],t.includeContainer,{filter:Ce.bind(null,t),flatten:!0,getShadowRoot:t.getShadowRoot}):n=bt(e,t.includeContainer,Ce.bind(null,t)),n},oe=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ae.call(e,Ne)===!1?!1:Be(t,e)},_n=gt.concat("iframe").join(","),Le=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ae.call(e,_n)===!1?!1:Ce(t,e)};/*! +* focus-trap 7.6.2 +* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE +*/function We(a,e){(e==null||e>a.length)&&(e=a.length);for(var t=0,n=Array(e);t0){var n=e[e.length-1];n!==t&&n.pause()}var s=e.indexOf(t);s===-1||e.splice(s,1),e.push(t)},deactivateTrap:function(e,t){var n=e.indexOf(t);n!==-1&&e.splice(n,1),e.length>0&&e[e.length-1].unpause()}},Cn=function(e){return e.tagName&&e.tagName.toLowerCase()==="input"&&typeof e.select=="function"},Rn=function(e){return(e==null?void 0:e.key)==="Escape"||(e==null?void 0:e.key)==="Esc"||(e==null?void 0:e.keyCode)===27},ve=function(e){return(e==null?void 0:e.key)==="Tab"||(e==null?void 0:e.keyCode)===9},An=function(e){return ve(e)&&!e.shiftKey},Mn=function(e){return ve(e)&&e.shiftKey},dt=function(e){return setTimeout(e,0)},me=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),s=1;s1&&arguments[1]!==void 0?arguments[1]:{},v=d.hasFallback,T=v===void 0?!1:v,k=d.params,O=k===void 0?[]:k,S=r[u];if(typeof S=="function"&&(S=S.apply(void 0,kn(O))),S===!0&&(S=void 0),!S){if(S===void 0||S===!1)return S;throw new Error("`".concat(u,"` was specified but was not a node, or did not return a node"))}var C=S;if(typeof S=="string"){try{C=n.querySelector(S)}catch(m){throw new Error("`".concat(u,'` appears to be an invalid selector; error="').concat(m.message,'"'))}if(!C&&!T)throw new Error("`".concat(u,"` as selector refers to no known node"))}return C},g=function(){var u=f("initialFocus",{hasFallback:!0});if(u===!1)return!1;if(u===void 0||u&&!Le(u,r.tabbableOptions))if(c(n.activeElement)>=0)u=n.activeElement;else{var d=i.tabbableGroups[0],v=d&&d.firstTabbableNode;u=v||f("fallbackFocus")}else u===null&&(u=f("fallbackFocus"));if(!u)throw new Error("Your focus-trap needs to have at least one focusable element");return u},h=function(){if(i.containerGroups=i.containers.map(function(u){var d=wn(u,r.tabbableOptions),v=xn(u,r.tabbableOptions),T=d.length>0?d[0]:void 0,k=d.length>0?d[d.length-1]:void 0,O=v.find(function(m){return oe(m)}),S=v.slice().reverse().find(function(m){return oe(m)}),C=!!d.find(function(m){return re(m)>0});return{container:u,tabbableNodes:d,focusableNodes:v,posTabIndexesFound:C,firstTabbableNode:T,lastTabbableNode:k,firstDomTabbableNode:O,lastDomTabbableNode:S,nextTabbableNode:function(p){var E=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,F=d.indexOf(p);return F<0?E?v.slice(v.indexOf(p)+1).find(function(z){return oe(z)}):v.slice(0,v.indexOf(p)).reverse().find(function(z){return oe(z)}):d[F+(E?1:-1)]}}}),i.tabbableGroups=i.containerGroups.filter(function(u){return u.tabbableNodes.length>0}),i.tabbableGroups.length<=0&&!f("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");if(i.containerGroups.find(function(u){return u.posTabIndexesFound})&&i.containerGroups.length>1)throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.")},b=function(u){var d=u.activeElement;if(d)return d.shadowRoot&&d.shadowRoot.activeElement!==null?b(d.shadowRoot):d},y=function(u){if(u!==!1&&u!==b(document)){if(!u||!u.focus){y(g());return}u.focus({preventScroll:!!r.preventScroll}),i.mostRecentlyFocusedNode=u,Cn(u)&&u.select()}},x=function(u){var d=f("setReturnFocus",{params:[u]});return d||(d===!1?!1:u)},w=function(u){var d=u.target,v=u.event,T=u.isBackward,k=T===void 0?!1:T;d=d||Ee(v),h();var O=null;if(i.tabbableGroups.length>0){var S=c(d,v),C=S>=0?i.containerGroups[S]:void 0;if(S<0)k?O=i.tabbableGroups[i.tabbableGroups.length-1].lastTabbableNode:O=i.tabbableGroups[0].firstTabbableNode;else if(k){var m=i.tabbableGroups.findIndex(function(j){var I=j.firstTabbableNode;return d===I});if(m<0&&(C.container===d||Le(d,r.tabbableOptions)&&!oe(d,r.tabbableOptions)&&!C.nextTabbableNode(d,!1))&&(m=S),m>=0){var p=m===0?i.tabbableGroups.length-1:m-1,E=i.tabbableGroups[p];O=re(d)>=0?E.lastTabbableNode:E.lastDomTabbableNode}else ve(v)||(O=C.nextTabbableNode(d,!1))}else{var F=i.tabbableGroups.findIndex(function(j){var I=j.lastTabbableNode;return d===I});if(F<0&&(C.container===d||Le(d,r.tabbableOptions)&&!oe(d,r.tabbableOptions)&&!C.nextTabbableNode(d))&&(F=S),F>=0){var z=F===i.tabbableGroups.length-1?0:F+1,P=i.tabbableGroups[z];O=re(d)>=0?P.firstTabbableNode:P.firstDomTabbableNode}else ve(v)||(O=C.nextTabbableNode(d))}}else O=f("fallbackFocus");return O},R=function(u){var d=Ee(u);if(!(c(d,u)>=0)){if(me(r.clickOutsideDeactivates,u)){o.deactivate({returnFocus:r.returnFocusOnDeactivate});return}me(r.allowOutsideClick,u)||u.preventDefault()}},A=function(u){var d=Ee(u),v=c(d,u)>=0;if(v||d instanceof Document)v&&(i.mostRecentlyFocusedNode=d);else{u.stopImmediatePropagation();var T,k=!0;if(i.mostRecentlyFocusedNode)if(re(i.mostRecentlyFocusedNode)>0){var O=c(i.mostRecentlyFocusedNode),S=i.containerGroups[O].tabbableNodes;if(S.length>0){var C=S.findIndex(function(m){return m===i.mostRecentlyFocusedNode});C>=0&&(r.isKeyForward(i.recentNavEvent)?C+1=0&&(T=S[C-1],k=!1))}}else i.containerGroups.some(function(m){return m.tabbableNodes.some(function(p){return re(p)>0})})||(k=!1);else k=!1;k&&(T=w({target:i.mostRecentlyFocusedNode,isBackward:r.isKeyBackward(i.recentNavEvent)})),y(T||i.mostRecentlyFocusedNode||g())}i.recentNavEvent=void 0},J=function(u){var d=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;i.recentNavEvent=u;var v=w({event:u,isBackward:d});v&&(ve(u)&&u.preventDefault(),y(v))},Q=function(u){(r.isKeyForward(u)||r.isKeyBackward(u))&&J(u,r.isKeyBackward(u))},W=function(u){Rn(u)&&me(r.escapeDeactivates,u)!==!1&&(u.preventDefault(),o.deactivate())},V=function(u){var d=Ee(u);c(d,u)>=0||me(r.clickOutsideDeactivates,u)||me(r.allowOutsideClick,u)||(u.preventDefault(),u.stopImmediatePropagation())},$=function(){if(i.active)return ut.activateTrap(s,o),i.delayInitialFocusTimer=r.delayInitialFocus?dt(function(){y(g())}):y(g()),n.addEventListener("focusin",A,!0),n.addEventListener("mousedown",R,{capture:!0,passive:!1}),n.addEventListener("touchstart",R,{capture:!0,passive:!1}),n.addEventListener("click",V,{capture:!0,passive:!1}),n.addEventListener("keydown",Q,{capture:!0,passive:!1}),n.addEventListener("keydown",W),o},be=function(){if(i.active)return n.removeEventListener("focusin",A,!0),n.removeEventListener("mousedown",R,!0),n.removeEventListener("touchstart",R,!0),n.removeEventListener("click",V,!0),n.removeEventListener("keydown",Q,!0),n.removeEventListener("keydown",W),o},M=function(u){var d=u.some(function(v){var T=Array.from(v.removedNodes);return T.some(function(k){return k===i.mostRecentlyFocusedNode})});d&&y(g())},U=typeof window<"u"&&"MutationObserver"in window?new MutationObserver(M):void 0,q=function(){U&&(U.disconnect(),i.active&&!i.paused&&i.containers.map(function(u){U.observe(u,{subtree:!0,childList:!0})}))};return o={get active(){return i.active},get paused(){return i.paused},activate:function(u){if(i.active)return this;var d=l(u,"onActivate"),v=l(u,"onPostActivate"),T=l(u,"checkCanFocusTrap");T||h(),i.active=!0,i.paused=!1,i.nodeFocusedBeforeActivation=n.activeElement,d==null||d();var k=function(){T&&h(),$(),q(),v==null||v()};return T?(T(i.containers.concat()).then(k,k),this):(k(),this)},deactivate:function(u){if(!i.active)return this;var d=ct({onDeactivate:r.onDeactivate,onPostDeactivate:r.onPostDeactivate,checkCanReturnFocus:r.checkCanReturnFocus},u);clearTimeout(i.delayInitialFocusTimer),i.delayInitialFocusTimer=void 0,be(),i.active=!1,i.paused=!1,q(),ut.deactivateTrap(s,o);var v=l(d,"onDeactivate"),T=l(d,"onPostDeactivate"),k=l(d,"checkCanReturnFocus"),O=l(d,"returnFocus","returnFocusOnDeactivate");v==null||v();var S=function(){dt(function(){O&&y(x(i.nodeFocusedBeforeActivation)),T==null||T()})};return O&&k?(k(x(i.nodeFocusedBeforeActivation)).then(S,S),this):(S(),this)},pause:function(u){if(i.paused||!i.active)return this;var d=l(u,"onPause"),v=l(u,"onPostPause");return i.paused=!0,d==null||d(),be(),q(),v==null||v(),this},unpause:function(u){if(!i.paused||!i.active)return this;var d=l(u,"onUnpause"),v=l(u,"onPostUnpause");return i.paused=!1,d==null||d(),h(),$(),q(),v==null||v(),this},updateContainerElements:function(u){var d=[].concat(u).filter(Boolean);return i.containers=d.map(function(v){return typeof v=="string"?n.querySelector(v):v}),i.active&&h(),q(),this}},o.updateContainerElements(e),o};function zn(a,e={}){let t;const{immediate:n,...s}=e,r=ie(!1),i=ie(!1),o=h=>t&&t.activate(h),l=h=>t&&t.deactivate(h),c=()=>{t&&(t.pause(),i.value=!0)},f=()=>{t&&(t.unpause(),i.value=!1)},g=ge(()=>{const h=tt(a);return(Array.isArray(h)?h:[h]).map(b=>{const y=tt(b);return typeof y=="string"?y:Rt(y)}).filter(At)});return $e(g,h=>{h.length&&(t=Dn(h,{...s,onActivate(){r.value=!0,e.onActivate&&e.onActivate()},onDeactivate(){r.value=!1,e.onDeactivate&&e.onDeactivate()}}),n&&o())},{flush:"post"}),Mt(()=>l()),{hasFocus:r,isPaused:i,activate:o,deactivate:l,pause:c,unpause:f}}class ce{constructor(e,t=!0,n=[],s=5e3){this.ctx=e,this.iframes=t,this.exclude=n,this.iframesTimeout=s}static matches(e,t){const n=typeof t=="string"?[t]:t,s=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(s){let r=!1;return n.every(i=>s.call(e,i)?(r=!0,!1):!0),r}else return!1}getContexts(){let e,t=[];return typeof this.ctx>"u"||!this.ctx?e=[]:NodeList.prototype.isPrototypeOf(this.ctx)?e=Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?e=this.ctx:typeof this.ctx=="string"?e=Array.prototype.slice.call(document.querySelectorAll(this.ctx)):e=[this.ctx],e.forEach(n=>{const s=t.filter(r=>r.contains(n)).length>0;t.indexOf(n)===-1&&!s&&t.push(n)}),t}getIframeContents(e,t,n=()=>{}){let s;try{const r=e.contentWindow;if(s=r.document,!r||!s)throw new Error("iframe inaccessible")}catch{n()}s&&t(s)}isIframeBlank(e){const t="about:blank",n=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&n!==t&&n}observeIframeLoad(e,t,n){let s=!1,r=null;const i=()=>{if(!s){s=!0,clearTimeout(r);try{this.isIframeBlank(e)||(e.removeEventListener("load",i),this.getIframeContents(e,t,n))}catch{n()}}};e.addEventListener("load",i),r=setTimeout(i,this.iframesTimeout)}onIframeReady(e,t,n){try{e.contentWindow.document.readyState==="complete"?this.isIframeBlank(e)?this.observeIframeLoad(e,t,n):this.getIframeContents(e,t,n):this.observeIframeLoad(e,t,n)}catch{n()}}waitForIframes(e,t){let n=0;this.forEachIframe(e,()=>!0,s=>{n++,this.waitForIframes(s.querySelector("html"),()=>{--n||t()})},s=>{s||t()})}forEachIframe(e,t,n,s=()=>{}){let r=e.querySelectorAll("iframe"),i=r.length,o=0;r=Array.prototype.slice.call(r);const l=()=>{--i<=0&&s(o)};i||l(),r.forEach(c=>{ce.matches(c,this.exclude)?l():this.onIframeReady(c,f=>{t(c)&&(o++,n(f)),l()},l)})}createIterator(e,t,n){return document.createNodeIterator(e,t,n,!1)}createInstanceOnIframe(e){return new ce(e.querySelector("html"),this.iframes)}compareNodeIframe(e,t,n){const s=e.compareDocumentPosition(n),r=Node.DOCUMENT_POSITION_PRECEDING;if(s&r)if(t!==null){const i=t.compareDocumentPosition(n),o=Node.DOCUMENT_POSITION_FOLLOWING;if(i&o)return!0}else return!0;return!1}getIteratorNode(e){const t=e.previousNode();let n;return t===null?n=e.nextNode():n=e.nextNode()&&e.nextNode(),{prevNode:t,node:n}}checkIframeFilter(e,t,n,s){let r=!1,i=!1;return s.forEach((o,l)=>{o.val===n&&(r=l,i=o.handled)}),this.compareNodeIframe(e,t,n)?(r===!1&&!i?s.push({val:n,handled:!0}):r!==!1&&!i&&(s[r].handled=!0),!0):(r===!1&&s.push({val:n,handled:!1}),!1)}handleOpenIframes(e,t,n,s){e.forEach(r=>{r.handled||this.getIframeContents(r.val,i=>{this.createInstanceOnIframe(i).forEachNode(t,n,s)})})}iterateThroughNodes(e,t,n,s,r){const i=this.createIterator(t,e,s);let o=[],l=[],c,f,g=()=>({prevNode:f,node:c}=this.getIteratorNode(i),c);for(;g();)this.iframes&&this.forEachIframe(t,h=>this.checkIframeFilter(c,f,h,o),h=>{this.createInstanceOnIframe(h).forEachNode(e,b=>l.push(b),s)}),l.push(c);l.forEach(h=>{n(h)}),this.iframes&&this.handleOpenIframes(o,e,n,s),r()}forEachNode(e,t,n,s=()=>{}){const r=this.getContexts();let i=r.length;i||s(),r.forEach(o=>{const l=()=>{this.iterateThroughNodes(e,o,t,n,()=>{--i<=0&&s()})};this.iframes?this.waitForIframes(o,l):l()})}}let Pn=class{constructor(e){this.ctx=e,this.ie=!1;const t=window.navigator.userAgent;(t.indexOf("MSIE")>-1||t.indexOf("Trident")>-1)&&(this.ie=!0)}set opt(e){this._opt=Object.assign({},{element:"",className:"",exclude:[],iframes:!1,iframesTimeout:5e3,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:"partially",acrossElements:!1,caseSensitive:!1,ignoreJoiners:!1,ignoreGroups:0,ignorePunctuation:[],wildcards:"disabled",each:()=>{},noMatch:()=>{},filter:()=>!0,done:()=>{},debug:!1,log:window.console},e)}get opt(){return this._opt}get iterator(){return new ce(this.ctx,this.opt.iframes,this.opt.exclude,this.opt.iframesTimeout)}log(e,t="debug"){const n=this.opt.log;this.opt.debug&&typeof n=="object"&&typeof n[t]=="function"&&n[t](`mark.js: ${e}`)}escapeStr(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}createRegExp(e){return this.opt.wildcards!=="disabled"&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),this.opt.wildcards!=="disabled"&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e),e}createSynonymsRegExp(e){const t=this.opt.synonyms,n=this.opt.caseSensitive?"":"i",s=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(let r in t)if(t.hasOwnProperty(r)){const i=t[r],o=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(r):this.escapeStr(r),l=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(i):this.escapeStr(i);o!==""&&l!==""&&(e=e.replace(new RegExp(`(${this.escapeStr(o)}|${this.escapeStr(l)})`,`gm${n}`),s+`(${this.processSynomyms(o)}|${this.processSynomyms(l)})`+s))}return e}processSynomyms(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}setupWildcardsRegExp(e){return e=e.replace(/(?:\\)*\?/g,t=>t.charAt(0)==="\\"?"?":""),e.replace(/(?:\\)*\*/g,t=>t.charAt(0)==="\\"?"*":"")}createWildcardsRegExp(e){let t=this.opt.wildcards==="withSpaces";return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}setupIgnoreJoinersRegExp(e){return e.replace(/[^(|)\\]/g,(t,n,s)=>{let r=s.charAt(n+1);return/[(|)\\]/.test(r)||r===""?t:t+"\0"})}createJoinersRegExp(e){let t=[];const n=this.opt.ignorePunctuation;return Array.isArray(n)&&n.length&&t.push(this.escapeStr(n.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join(`[${t.join("")}]*`):e}createDiacriticsRegExp(e){const t=this.opt.caseSensitive?"":"i",n=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"];let s=[];return e.split("").forEach(r=>{n.every(i=>{if(i.indexOf(r)!==-1){if(s.indexOf(i)>-1)return!1;e=e.replace(new RegExp(`[${i}]`,`gm${t}`),`[${i}]`),s.push(i)}return!0})}),e}createMergedBlanksRegExp(e){return e.replace(/[\s]+/gmi,"[\\s]+")}createAccuracyRegExp(e){const t="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿";let n=this.opt.accuracy,s=typeof n=="string"?n:n.value,r=typeof n=="string"?[]:n.limiters,i="";switch(r.forEach(o=>{i+=`|${this.escapeStr(o)}`}),s){case"partially":default:return`()(${e})`;case"complementary":return i="\\s"+(i||this.escapeStr(t)),`()([^${i}]*${e}[^${i}]*)`;case"exactly":return`(^|\\s${i})(${e})(?=$|\\s${i})`}}getSeparatedKeywords(e){let t=[];return e.forEach(n=>{this.opt.separateWordSearch?n.split(" ").forEach(s=>{s.trim()&&t.indexOf(s)===-1&&t.push(s)}):n.trim()&&t.indexOf(n)===-1&&t.push(n)}),{keywords:t.sort((n,s)=>s.length-n.length),length:t.length}}isNumeric(e){return Number(parseFloat(e))==e}checkRanges(e){if(!Array.isArray(e)||Object.prototype.toString.call(e[0])!=="[object Object]")return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];const t=[];let n=0;return e.sort((s,r)=>s.start-r.start).forEach(s=>{let{start:r,end:i,valid:o}=this.callNoMatchOnInvalidRanges(s,n);o&&(s.start=r,s.length=i-r,t.push(s),n=i)}),t}callNoMatchOnInvalidRanges(e,t){let n,s,r=!1;return e&&typeof e.start<"u"?(n=parseInt(e.start,10),s=n+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&s-t>0&&s-n>0?r=!0:(this.log(`Ignoring invalid or overlapping range: ${JSON.stringify(e)}`),this.opt.noMatch(e))):(this.log(`Ignoring invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)),{start:n,end:s,valid:r}}checkWhitespaceRanges(e,t,n){let s,r=!0,i=n.length,o=t-i,l=parseInt(e.start,10)-o;return l=l>i?i:l,s=l+parseInt(e.length,10),s>i&&(s=i,this.log(`End range automatically set to the max value of ${i}`)),l<0||s-l<0||l>i||s>i?(r=!1,this.log(`Invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)):n.substring(l,s).replace(/\s+/g,"")===""&&(r=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:l,end:s,valid:r}}getTextNodes(e){let t="",n=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,s=>{n.push({start:t.length,end:(t+=s.textContent).length,node:s})},s=>this.matchesExclude(s.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT,()=>{e({value:t,nodes:n})})}matchesExclude(e){return ce.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}wrapRangeInTextNode(e,t,n){const s=this.opt.element?this.opt.element:"mark",r=e.splitText(t),i=r.splitText(n-t);let o=document.createElement(s);return o.setAttribute("data-markjs","true"),this.opt.className&&o.setAttribute("class",this.opt.className),o.textContent=r.textContent,r.parentNode.replaceChild(o,r),i}wrapRangeInMappedTextNode(e,t,n,s,r){e.nodes.every((i,o)=>{const l=e.nodes[o+1];if(typeof l>"u"||l.start>t){if(!s(i.node))return!1;const c=t-i.start,f=(n>i.end?i.end:n)-i.start,g=e.value.substr(0,i.start),h=e.value.substr(f+i.start);if(i.node=this.wrapRangeInTextNode(i.node,c,f),e.value=g+h,e.nodes.forEach((b,y)=>{y>=o&&(e.nodes[y].start>0&&y!==o&&(e.nodes[y].start-=f),e.nodes[y].end-=f)}),n-=f,r(i.node.previousSibling,i.start),n>i.end)t=i.end;else return!1}return!0})}wrapMatches(e,t,n,s,r){const i=t===0?0:t+1;this.getTextNodes(o=>{o.nodes.forEach(l=>{l=l.node;let c;for(;(c=e.exec(l.textContent))!==null&&c[i]!=="";){if(!n(c[i],l))continue;let f=c.index;if(i!==0)for(let g=1;g{let l;for(;(l=e.exec(o.value))!==null&&l[i]!=="";){let c=l.index;if(i!==0)for(let g=1;gn(l[i],g),(g,h)=>{e.lastIndex=h,s(g)})}r()})}wrapRangeFromIndex(e,t,n,s){this.getTextNodes(r=>{const i=r.value.length;e.forEach((o,l)=>{let{start:c,end:f,valid:g}=this.checkWhitespaceRanges(o,i,r.value);g&&this.wrapRangeInMappedTextNode(r,c,f,h=>t(h,o,r.value.substring(c,f),l),h=>{n(h,o)})}),s()})}unwrapMatches(e){const t=e.parentNode;let n=document.createDocumentFragment();for(;e.firstChild;)n.appendChild(e.removeChild(e.firstChild));t.replaceChild(n,e),this.ie?this.normalizeTextNode(t):t.normalize()}normalizeTextNode(e){if(e){if(e.nodeType===3)for(;e.nextSibling&&e.nextSibling.nodeType===3;)e.nodeValue+=e.nextSibling.nodeValue,e.parentNode.removeChild(e.nextSibling);else this.normalizeTextNode(e.firstChild);this.normalizeTextNode(e.nextSibling)}}markRegExp(e,t){this.opt=t,this.log(`Searching with expression "${e}"`);let n=0,s="wrapMatches";const r=i=>{n++,this.opt.each(i)};this.opt.acrossElements&&(s="wrapMatchesAcrossElements"),this[s](e,this.opt.ignoreGroups,(i,o)=>this.opt.filter(o,i,n),r,()=>{n===0&&this.opt.noMatch(e),this.opt.done(n)})}mark(e,t){this.opt=t;let n=0,s="wrapMatches";const{keywords:r,length:i}=this.getSeparatedKeywords(typeof e=="string"?[e]:e),o=this.opt.caseSensitive?"":"i",l=c=>{let f=new RegExp(this.createRegExp(c),`gm${o}`),g=0;this.log(`Searching with expression "${f}"`),this[s](f,1,(h,b)=>this.opt.filter(b,c,n,g),h=>{g++,n++,this.opt.each(h)},()=>{g===0&&this.opt.noMatch(c),r[i-1]===c?this.opt.done(n):l(r[r.indexOf(c)+1])})};this.opt.acrossElements&&(s="wrapMatchesAcrossElements"),i===0?this.opt.done(n):l(r[0])}markRanges(e,t){this.opt=t;let n=0,s=this.checkRanges(e);s&&s.length?(this.log("Starting to mark with the following ranges: "+JSON.stringify(s)),this.wrapRangeFromIndex(s,(r,i,o,l)=>this.opt.filter(r,i,o,l),(r,i)=>{n++,this.opt.each(r,i)},()=>{this.opt.done(n)})):this.opt.done(n)}unmark(e){this.opt=e;let t=this.opt.element?this.opt.element:"*";t+="[data-markjs]",this.opt.className&&(t+=`.${this.opt.className}`),this.log(`Removal selector "${t}"`),this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,n=>{this.unwrapMatches(n)},n=>{const s=ce.matches(n,t),r=this.matchesExclude(n);return!s||r?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},this.opt.done)}};function jn(a){const e=new Pn(a);return this.mark=(t,n)=>(e.mark(t,n),this),this.markRegExp=(t,n)=>(e.markRegExp(t,n),this),this.markRanges=(t,n)=>(e.markRanges(t,n),this),this.unmark=t=>(e.unmark(t),this),this}function ke(a,e,t,n){function s(r){return r instanceof t?r:new t(function(i){i(r)})}return new(t||(t=Promise))(function(r,i){function o(f){try{c(n.next(f))}catch(g){i(g)}}function l(f){try{c(n.throw(f))}catch(g){i(g)}}function c(f){f.done?r(f.value):s(f.value).then(o,l)}c((n=n.apply(a,[])).next())})}const Vn="ENTRIES",_t="KEYS",St="VALUES",D="";class De{constructor(e,t){const n=e._tree,s=Array.from(n.keys());this.set=e,this._type=t,this._path=s.length>0?[{node:n,keys:s}]:[]}next(){const e=this.dive();return this.backtrack(),e}dive(){if(this._path.length===0)return{done:!0,value:void 0};const{node:e,keys:t}=le(this._path);if(le(t)===D)return{done:!1,value:this.result()};const n=e.get(le(t));return this._path.push({node:n,keys:Array.from(n.keys())}),this.dive()}backtrack(){if(this._path.length===0)return;const e=le(this._path).keys;e.pop(),!(e.length>0)&&(this._path.pop(),this.backtrack())}key(){return this.set._prefix+this._path.map(({keys:e})=>le(e)).filter(e=>e!==D).join("")}value(){return le(this._path).node.get(D)}result(){switch(this._type){case St:return this.value();case _t:return this.key();default:return[this.key(),this.value()]}}[Symbol.iterator](){return this}}const le=a=>a[a.length-1],$n=(a,e,t)=>{const n=new Map;if(e===void 0)return n;const s=e.length+1,r=s+t,i=new Uint8Array(r*s).fill(t+1);for(let o=0;o{const l=r*i;e:for(const c of a.keys())if(c===D){const f=s[l-1];f<=t&&n.set(o,[a.get(c),f])}else{let f=r;for(let g=0;gt)continue e}Et(a.get(c),e,t,n,s,f,i,o+c)}};class X{constructor(e=new Map,t=""){this._size=void 0,this._tree=e,this._prefix=t}atPrefix(e){if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");const[t,n]=Re(this._tree,e.slice(this._prefix.length));if(t===void 0){const[s,r]=qe(n);for(const i of s.keys())if(i!==D&&i.startsWith(r)){const o=new Map;return o.set(i.slice(r.length),s.get(i)),new X(o,e)}}return new X(t,e)}clear(){this._size=void 0,this._tree.clear()}delete(e){return this._size=void 0,Bn(this._tree,e)}entries(){return new De(this,Vn)}forEach(e){for(const[t,n]of this)e(t,n,this)}fuzzyGet(e,t){return $n(this._tree,e,t)}get(e){const t=Ke(this._tree,e);return t!==void 0?t.get(D):void 0}has(e){const t=Ke(this._tree,e);return t!==void 0&&t.has(D)}keys(){return new De(this,_t)}set(e,t){if(typeof e!="string")throw new Error("key must be a string");return this._size=void 0,ze(this._tree,e).set(D,t),this}get size(){if(this._size)return this._size;this._size=0;const e=this.entries();for(;!e.next().done;)this._size+=1;return this._size}update(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;const n=ze(this._tree,e);return n.set(D,t(n.get(D))),this}fetch(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;const n=ze(this._tree,e);let s=n.get(D);return s===void 0&&n.set(D,s=t()),s}values(){return new De(this,St)}[Symbol.iterator](){return this.entries()}static from(e){const t=new X;for(const[n,s]of e)t.set(n,s);return t}static fromObject(e){return X.from(Object.entries(e))}}const Re=(a,e,t=[])=>{if(e.length===0||a==null)return[a,t];for(const n of a.keys())if(n!==D&&e.startsWith(n))return t.push([a,n]),Re(a.get(n),e.slice(n.length),t);return t.push([a,e]),Re(void 0,"",t)},Ke=(a,e)=>{if(e.length===0||a==null)return a;for(const t of a.keys())if(t!==D&&e.startsWith(t))return Ke(a.get(t),e.slice(t.length))},ze=(a,e)=>{const t=e.length;e:for(let n=0;a&&n{const[t,n]=Re(a,e);if(t!==void 0){if(t.delete(D),t.size===0)Tt(n);else if(t.size===1){const[s,r]=t.entries().next().value;It(n,s,r)}}},Tt=a=>{if(a.length===0)return;const[e,t]=qe(a);if(e.delete(t),e.size===0)Tt(a.slice(0,-1));else if(e.size===1){const[n,s]=e.entries().next().value;n!==D&&It(a.slice(0,-1),n,s)}},It=(a,e,t)=>{if(a.length===0)return;const[n,s]=qe(a);n.set(s+e,t),n.delete(s)},qe=a=>a[a.length-1],Ge="or",kt="and",Wn="and_not";class ue{constructor(e){if((e==null?void 0:e.fields)==null)throw new Error('MiniSearch: option "fields" must be provided');const t=e.autoVacuum==null||e.autoVacuum===!0?Ve:e.autoVacuum;this._options=Object.assign(Object.assign(Object.assign({},je),e),{autoVacuum:t,searchOptions:Object.assign(Object.assign({},ft),e.searchOptions||{}),autoSuggestOptions:Object.assign(Object.assign({},Gn),e.autoSuggestOptions||{})}),this._index=new X,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldIds={},this._fieldLength=new Map,this._avgFieldLength=[],this._nextId=0,this._storedFields=new Map,this._dirtCount=0,this._currentVacuum=null,this._enqueuedVacuum=null,this._enqueuedVacuumConditions=Ue,this.addFields(this._options.fields)}add(e){const{extractField:t,tokenize:n,processTerm:s,fields:r,idField:i}=this._options,o=t(e,i);if(o==null)throw new Error(`MiniSearch: document does not have ID field "${i}"`);if(this._idToShortId.has(o))throw new Error(`MiniSearch: duplicate ID ${o}`);const l=this.addDocumentId(o);this.saveStoredFields(l,e);for(const c of r){const f=t(e,c);if(f==null)continue;const g=n(f.toString(),c),h=this._fieldIds[c],b=new Set(g).size;this.addFieldLength(l,h,this._documentCount-1,b);for(const y of g){const x=s(y,c);if(Array.isArray(x))for(const w of x)this.addTerm(h,l,w);else x&&this.addTerm(h,l,x)}}}addAll(e){for(const t of e)this.add(t)}addAllAsync(e,t={}){const{chunkSize:n=10}=t,s={chunk:[],promise:Promise.resolve()},{chunk:r,promise:i}=e.reduce(({chunk:o,promise:l},c,f)=>(o.push(c),(f+1)%n===0?{chunk:[],promise:l.then(()=>new Promise(g=>setTimeout(g,0))).then(()=>this.addAll(o))}:{chunk:o,promise:l}),s);return i.then(()=>this.addAll(r))}remove(e){const{tokenize:t,processTerm:n,extractField:s,fields:r,idField:i}=this._options,o=s(e,i);if(o==null)throw new Error(`MiniSearch: document does not have ID field "${i}"`);const l=this._idToShortId.get(o);if(l==null)throw new Error(`MiniSearch: cannot remove document with ID ${o}: it is not in the index`);for(const c of r){const f=s(e,c);if(f==null)continue;const g=t(f.toString(),c),h=this._fieldIds[c],b=new Set(g).size;this.removeFieldLength(l,h,this._documentCount,b);for(const y of g){const x=n(y,c);if(Array.isArray(x))for(const w of x)this.removeTerm(h,l,w);else x&&this.removeTerm(h,l,x)}}this._storedFields.delete(l),this._documentIds.delete(l),this._idToShortId.delete(o),this._fieldLength.delete(l),this._documentCount-=1}removeAll(e){if(e)for(const t of e)this.remove(t);else{if(arguments.length>0)throw new Error("Expected documents to be present. Omit the argument to remove all documents.");this._index=new X,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}}discard(e){const t=this._idToShortId.get(e);if(t==null)throw new Error(`MiniSearch: cannot discard document with ID ${e}: it is not in the index`);this._idToShortId.delete(e),this._documentIds.delete(t),this._storedFields.delete(t),(this._fieldLength.get(t)||[]).forEach((n,s)=>{this.removeFieldLength(t,s,this._documentCount,n)}),this._fieldLength.delete(t),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()}maybeAutoVacuum(){if(this._options.autoVacuum===!1)return;const{minDirtFactor:e,minDirtCount:t,batchSize:n,batchWait:s}=this._options.autoVacuum;this.conditionalVacuum({batchSize:n,batchWait:s},{minDirtCount:t,minDirtFactor:e})}discardAll(e){const t=this._options.autoVacuum;try{this._options.autoVacuum=!1;for(const n of e)this.discard(n)}finally{this._options.autoVacuum=t}this.maybeAutoVacuum()}replace(e){const{idField:t,extractField:n}=this._options,s=n(e,t);this.discard(s),this.add(e)}vacuum(e={}){return this.conditionalVacuum(e)}conditionalVacuum(e,t){return this._currentVacuum?(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&t,this._enqueuedVacuum!=null?this._enqueuedVacuum:(this._enqueuedVacuum=this._currentVacuum.then(()=>{const n=this._enqueuedVacuumConditions;return this._enqueuedVacuumConditions=Ue,this.performVacuuming(e,n)}),this._enqueuedVacuum)):this.vacuumConditionsMet(t)===!1?Promise.resolve():(this._currentVacuum=this.performVacuuming(e),this._currentVacuum)}performVacuuming(e,t){return ke(this,void 0,void 0,function*(){const n=this._dirtCount;if(this.vacuumConditionsMet(t)){const s=e.batchSize||Je.batchSize,r=e.batchWait||Je.batchWait;let i=1;for(const[o,l]of this._index){for(const[c,f]of l)for(const[g]of f)this._documentIds.has(g)||(f.size<=1?l.delete(c):f.delete(g));this._index.get(o).size===0&&this._index.delete(o),i%s===0&&(yield new Promise(c=>setTimeout(c,r))),i+=1}this._dirtCount-=n}yield null,this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null})}vacuumConditionsMet(e){if(e==null)return!0;let{minDirtCount:t,minDirtFactor:n}=e;return t=t||Ve.minDirtCount,n=n||Ve.minDirtFactor,this.dirtCount>=t&&this.dirtFactor>=n}get isVacuuming(){return this._currentVacuum!=null}get dirtCount(){return this._dirtCount}get dirtFactor(){return this._dirtCount/(1+this._documentCount+this._dirtCount)}has(e){return this._idToShortId.has(e)}getStoredFields(e){const t=this._idToShortId.get(e);if(t!=null)return this._storedFields.get(t)}search(e,t={}){const{searchOptions:n}=this._options,s=Object.assign(Object.assign({},n),t),r=this.executeQuery(e,t),i=[];for(const[o,{score:l,terms:c,match:f}]of r){const g=c.length||1,h={id:this._documentIds.get(o),score:l*g,terms:Object.keys(f),queryTerms:c,match:f};Object.assign(h,this._storedFields.get(o)),(s.filter==null||s.filter(h))&&i.push(h)}return e===ue.wildcard&&s.boostDocument==null||i.sort(pt),i}autoSuggest(e,t={}){t=Object.assign(Object.assign({},this._options.autoSuggestOptions),t);const n=new Map;for(const{score:r,terms:i}of this.search(e,t)){const o=i.join(" "),l=n.get(o);l!=null?(l.score+=r,l.count+=1):n.set(o,{score:r,terms:i,count:1})}const s=[];for(const[r,{score:i,terms:o,count:l}]of n)s.push({suggestion:r,terms:o,score:i/l});return s.sort(pt),s}get documentCount(){return this._documentCount}get termCount(){return this._index.size}static loadJSON(e,t){if(t==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(e),t)}static loadJSONAsync(e,t){return ke(this,void 0,void 0,function*(){if(t==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJSAsync(JSON.parse(e),t)})}static getDefault(e){if(je.hasOwnProperty(e))return Pe(je,e);throw new Error(`MiniSearch: unknown option "${e}"`)}static loadJS(e,t){const{index:n,documentIds:s,fieldLength:r,storedFields:i,serializationVersion:o}=e,l=this.instantiateMiniSearch(e,t);l._documentIds=Te(s),l._fieldLength=Te(r),l._storedFields=Te(i);for(const[c,f]of l._documentIds)l._idToShortId.set(f,c);for(const[c,f]of n){const g=new Map;for(const h of Object.keys(f)){let b=f[h];o===1&&(b=b.ds),g.set(parseInt(h,10),Te(b))}l._index.set(c,g)}return l}static loadJSAsync(e,t){return ke(this,void 0,void 0,function*(){const{index:n,documentIds:s,fieldLength:r,storedFields:i,serializationVersion:o}=e,l=this.instantiateMiniSearch(e,t);l._documentIds=yield Ie(s),l._fieldLength=yield Ie(r),l._storedFields=yield Ie(i);for(const[f,g]of l._documentIds)l._idToShortId.set(g,f);let c=0;for(const[f,g]of n){const h=new Map;for(const b of Object.keys(g)){let y=g[b];o===1&&(y=y.ds),h.set(parseInt(b,10),yield Ie(y))}++c%1e3===0&&(yield Nt(0)),l._index.set(f,h)}return l})}static instantiateMiniSearch(e,t){const{documentCount:n,nextId:s,fieldIds:r,averageFieldLength:i,dirtCount:o,serializationVersion:l}=e;if(l!==1&&l!==2)throw new Error("MiniSearch: cannot deserialize an index created with an incompatible version");const c=new ue(t);return c._documentCount=n,c._nextId=s,c._idToShortId=new Map,c._fieldIds=r,c._avgFieldLength=i,c._dirtCount=o||0,c._index=new X,c}executeQuery(e,t={}){if(e===ue.wildcard)return this.executeWildcardQuery(t);if(typeof e!="string"){const h=Object.assign(Object.assign(Object.assign({},t),e),{queries:void 0}),b=e.queries.map(y=>this.executeQuery(y,h));return this.combineResults(b,h.combineWith)}const{tokenize:n,processTerm:s,searchOptions:r}=this._options,i=Object.assign(Object.assign({tokenize:n,processTerm:s},r),t),{tokenize:o,processTerm:l}=i,g=o(e).flatMap(h=>l(h)).filter(h=>!!h).map(qn(i)).map(h=>this.executeQuerySpec(h,i));return this.combineResults(g,i.combineWith)}executeQuerySpec(e,t){const n=Object.assign(Object.assign({},this._options.searchOptions),t),s=(n.fields||this._options.fields).reduce((x,w)=>Object.assign(Object.assign({},x),{[w]:Pe(n.boost,w)||1}),{}),{boostDocument:r,weights:i,maxFuzzy:o,bm25:l}=n,{fuzzy:c,prefix:f}=Object.assign(Object.assign({},ft.weights),i),g=this._index.get(e.term),h=this.termResults(e.term,e.term,1,e.termBoost,g,s,r,l);let b,y;if(e.prefix&&(b=this._index.atPrefix(e.term)),e.fuzzy){const x=e.fuzzy===!0?.2:e.fuzzy,w=x<1?Math.min(o,Math.round(e.term.length*x)):x;w&&(y=this._index.fuzzyGet(e.term,w))}if(b)for(const[x,w]of b){const R=x.length-e.term.length;if(!R)continue;y==null||y.delete(x);const A=f*x.length/(x.length+.3*R);this.termResults(e.term,x,A,e.termBoost,w,s,r,l,h)}if(y)for(const x of y.keys()){const[w,R]=y.get(x);if(!R)continue;const A=c*x.length/(x.length+R);this.termResults(e.term,x,A,e.termBoost,w,s,r,l,h)}return h}executeWildcardQuery(e){const t=new Map,n=Object.assign(Object.assign({},this._options.searchOptions),e);for(const[s,r]of this._documentIds){const i=n.boostDocument?n.boostDocument(r,"",this._storedFields.get(s)):1;t.set(s,{score:i,terms:[],match:{}})}return t}combineResults(e,t=Ge){if(e.length===0)return new Map;const n=t.toLowerCase(),s=Kn[n];if(!s)throw new Error(`Invalid combination operator: ${t}`);return e.reduce(s)||new Map}toJSON(){const e=[];for(const[t,n]of this._index){const s={};for(const[r,i]of n)s[r]=Object.fromEntries(i);e.push([t,s])}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:e,serializationVersion:2}}termResults(e,t,n,s,r,i,o,l,c=new Map){if(r==null)return c;for(const f of Object.keys(i)){const g=i[f],h=this._fieldIds[f],b=r.get(h);if(b==null)continue;let y=b.size;const x=this._avgFieldLength[h];for(const w of b.keys()){if(!this._documentIds.has(w)){this.removeTerm(h,w,t),y-=1;continue}const R=o?o(this._documentIds.get(w),t,this._storedFields.get(w)):1;if(!R)continue;const A=b.get(w),J=this._fieldLength.get(w)[h],Q=Un(A,y,this._documentCount,J,x,l),W=n*s*g*R*Q,V=c.get(w);if(V){V.score+=W,Hn(V.terms,e);const $=Pe(V.match,t);$?$.push(f):V.match[t]=[f]}else c.set(w,{score:W,terms:[e],match:{[t]:[f]}})}}return c}addTerm(e,t,n){const s=this._index.fetch(n,mt);let r=s.get(e);if(r==null)r=new Map,r.set(t,1),s.set(e,r);else{const i=r.get(t);r.set(t,(i||0)+1)}}removeTerm(e,t,n){if(!this._index.has(n)){this.warnDocumentChanged(t,e,n);return}const s=this._index.fetch(n,mt),r=s.get(e);r==null||r.get(t)==null?this.warnDocumentChanged(t,e,n):r.get(t)<=1?r.size<=1?s.delete(e):r.delete(t):r.set(t,r.get(t)-1),this._index.get(n).size===0&&this._index.delete(n)}warnDocumentChanged(e,t,n){for(const s of Object.keys(this._fieldIds))if(this._fieldIds[s]===t){this._options.logger("warn",`MiniSearch: document with ID ${this._documentIds.get(e)} has changed before removal: term "${n}" was not present in field "${s}". Removing a document after it has changed can corrupt the index!`,"version_conflict");return}}addDocumentId(e){const t=this._nextId;return this._idToShortId.set(e,t),this._documentIds.set(t,e),this._documentCount+=1,this._nextId+=1,t}addFields(e){for(let t=0;tObject.prototype.hasOwnProperty.call(a,e)?a[e]:void 0,Kn={[Ge]:(a,e)=>{for(const t of e.keys()){const n=a.get(t);if(n==null)a.set(t,e.get(t));else{const{score:s,terms:r,match:i}=e.get(t);n.score=n.score+s,n.match=Object.assign(n.match,i),ht(n.terms,r)}}return a},[kt]:(a,e)=>{const t=new Map;for(const n of e.keys()){const s=a.get(n);if(s==null)continue;const{score:r,terms:i,match:o}=e.get(n);ht(s.terms,i),t.set(n,{score:s.score+r,terms:s.terms,match:Object.assign(s.match,o)})}return t},[Wn]:(a,e)=>{for(const t of e.keys())a.delete(t);return a}},Jn={k:1.2,b:.7,d:.5},Un=(a,e,t,n,s,r)=>{const{k:i,b:o,d:l}=r;return Math.log(1+(t-e+.5)/(e+.5))*(l+a*(i+1)/(a+i*(1-o+o*n/s)))},qn=a=>(e,t,n)=>{const s=typeof a.fuzzy=="function"?a.fuzzy(e,t,n):a.fuzzy||!1,r=typeof a.prefix=="function"?a.prefix(e,t,n):a.prefix===!0,i=typeof a.boostTerm=="function"?a.boostTerm(e,t,n):1;return{term:e,fuzzy:s,prefix:r,termBoost:i}},je={idField:"id",extractField:(a,e)=>a[e],tokenize:a=>a.split(Qn),processTerm:a=>a.toLowerCase(),fields:void 0,searchOptions:void 0,storeFields:[],logger:(a,e)=>{typeof(console==null?void 0:console[a])=="function"&&console[a](e)},autoVacuum:!0},ft={combineWith:Ge,prefix:!1,fuzzy:!1,maxFuzzy:6,boost:{},weights:{fuzzy:.45,prefix:.375},bm25:Jn},Gn={combineWith:kt,prefix:(a,e,t)=>e===t.length-1},Je={batchSize:1e3,batchWait:10},Ue={minDirtFactor:.1,minDirtCount:20},Ve=Object.assign(Object.assign({},Je),Ue),Hn=(a,e)=>{a.includes(e)||a.push(e)},ht=(a,e)=>{for(const t of e)a.includes(t)||a.push(t)},pt=({score:a},{score:e})=>e-a,mt=()=>new Map,Te=a=>{const e=new Map;for(const t of Object.keys(a))e.set(parseInt(t,10),a[t]);return e},Ie=a=>ke(void 0,void 0,void 0,function*(){const e=new Map;let t=0;for(const n of Object.keys(a))e.set(parseInt(n,10),a[n]),++t%1e3===0&&(yield Nt(0));return e}),Nt=a=>new Promise(e=>setTimeout(e,a)),Qn=/[\n\r\p{Z}\p{P}]+/u;class Yn{constructor(e=10){Ae(this,"max");Ae(this,"cache");this.max=e,this.cache=new Map}get(e){let t=this.cache.get(e);return t!==void 0&&(this.cache.delete(e),this.cache.set(e,t)),t}set(e,t){this.cache.has(e)?this.cache.delete(e):this.cache.size===this.max&&this.cache.delete(this.first()),this.cache.set(e,t)}first(){return this.cache.keys().next().value}clear(){this.cache.clear()}}const Zn=["aria-owns"],Xn={class:"shell"},es=["title"],ts={class:"search-actions before"},ns=["title"],ss=["aria-activedescendant","aria-controls","placeholder"],is={class:"search-actions"},rs=["title"],as=["disabled","title"],os=["id","role","aria-labelledby"],ls=["id","aria-selected"],cs=["href","aria-label","onMouseenter","onFocusin","data-index"],us={class:"titles"},ds=["innerHTML"],fs={class:"title main"},hs=["innerHTML"],ps={key:0,class:"excerpt-wrapper"},ms={key:0,class:"excerpt",inert:""},gs=["innerHTML"],vs={key:0,class:"no-results"},bs={class:"search-keyboard-shortcuts"},ys=["aria-label"],ws=["aria-label"],xs=["aria-label"],_s=["aria-label"],Ss=Lt({__name:"VPLocalSearchBox",emits:["close"],setup(a,{emit:e}){var S,C;const t=e,n=xe(),s=xe(),r=xe(rn),i=nn(),{activate:o}=zn(n,{immediate:!0,allowOutsideClick:!0,clickOutsideDeactivates:!0,escapeDeactivates:!0}),{localeIndex:l,theme:c}=i,f=nt(async()=>{var m,p,E,F,z,P,j,I,K;return at(ue.loadJSON((E=await((p=(m=r.value)[l.value])==null?void 0:p.call(m)))==null?void 0:E.default,{fields:["title","titles","text"],storeFields:["title","titles"],searchOptions:{fuzzy:.2,prefix:!0,boost:{title:4,text:2,titles:1},...((F=c.value.search)==null?void 0:F.provider)==="local"&&((P=(z=c.value.search.options)==null?void 0:z.miniSearch)==null?void 0:P.searchOptions)},...((j=c.value.search)==null?void 0:j.provider)==="local"&&((K=(I=c.value.search.options)==null?void 0:I.miniSearch)==null?void 0:K.options)}))}),h=ge(()=>{var m,p;return((m=c.value.search)==null?void 0:m.provider)==="local"&&((p=c.value.search.options)==null?void 0:p.disableQueryPersistence)===!0}).value?ie(""):Dt("vitepress:local-search-filter",""),b=zt("vitepress:local-search-detailed-list",((S=c.value.search)==null?void 0:S.provider)==="local"&&((C=c.value.search.options)==null?void 0:C.detailedView)===!0),y=ge(()=>{var m,p,E;return((m=c.value.search)==null?void 0:m.provider)==="local"&&(((p=c.value.search.options)==null?void 0:p.disableDetailedView)===!0||((E=c.value.search.options)==null?void 0:E.detailedView)===!1)}),x=ge(()=>{var p,E,F,z,P,j,I;const m=((p=c.value.search)==null?void 0:p.options)??c.value.algolia;return((P=(z=(F=(E=m==null?void 0:m.locales)==null?void 0:E[l.value])==null?void 0:F.translations)==null?void 0:z.button)==null?void 0:P.buttonText)||((I=(j=m==null?void 0:m.translations)==null?void 0:j.button)==null?void 0:I.buttonText)||"Search"});Pt(()=>{y.value&&(b.value=!1)});const w=xe([]),R=ie(!1);$e(h,()=>{R.value=!1});const A=nt(async()=>{if(s.value)return at(new jn(s.value))},null),J=new Yn(16);jt(()=>[f.value,h.value,b.value],async([m,p,E],F,z)=>{var ee,ye,He,Qe;(F==null?void 0:F[0])!==m&&J.clear();let P=!1;if(z(()=>{P=!0}),!m)return;w.value=m.search(p).slice(0,16),R.value=!0;const j=E?await Promise.all(w.value.map(B=>Q(B.id))):[];if(P)return;for(const{id:B,mod:te}of j){const ne=B.slice(0,B.indexOf("#"));let Y=J.get(ne);if(Y)continue;Y=new Map,J.set(ne,Y);const G=te.default??te;if(G!=null&&G.render||G!=null&&G.setup){const se=Yt(G);se.config.warnHandler=()=>{},se.provide(Zt,i),Object.defineProperties(se.config.globalProperties,{$frontmatter:{get(){return i.frontmatter.value}},$params:{get(){return i.page.value.params}}});const Ye=document.createElement("div");se.mount(Ye),Ye.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(de=>{var et;const we=(et=de.querySelector("a"))==null?void 0:et.getAttribute("href"),Ze=(we==null?void 0:we.startsWith("#"))&&we.slice(1);if(!Ze)return;let Xe="";for(;(de=de.nextElementSibling)&&!/^h[1-6]$/i.test(de.tagName);)Xe+=de.outerHTML;Y.set(Ze,Xe)}),se.unmount()}if(P)return}const I=new Set;if(w.value=w.value.map(B=>{const[te,ne]=B.id.split("#"),Y=J.get(te),G=(Y==null?void 0:Y.get(ne))??"";for(const se in B.match)I.add(se);return{...B,text:G}}),await fe(),P)return;await new Promise(B=>{var te;(te=A.value)==null||te.unmark({done:()=>{var ne;(ne=A.value)==null||ne.markRegExp(k(I),{done:B})}})});const K=((ee=n.value)==null?void 0:ee.querySelectorAll(".result .excerpt"))??[];for(const B of K)(ye=B.querySelector('mark[data-markjs="true"]'))==null||ye.scrollIntoView({block:"center"});(Qe=(He=s.value)==null?void 0:He.firstElementChild)==null||Qe.scrollIntoView({block:"start"})},{debounce:200,immediate:!0});async function Q(m){const p=Xt(m.slice(0,m.indexOf("#")));try{if(!p)throw new Error(`Cannot find file for id: ${m}`);return{id:m,mod:await import(p)}}catch(E){return console.error(E),{id:m,mod:{}}}}const W=ie(),V=ge(()=>{var m;return((m=h.value)==null?void 0:m.length)<=0});function $(m=!0){var p,E;(p=W.value)==null||p.focus(),m&&((E=W.value)==null||E.select())}Me(()=>{$()});function be(m){m.pointerType==="mouse"&&$()}const M=ie(-1),U=ie(!0);$e(w,m=>{M.value=m.length?0:-1,q()});function q(){fe(()=>{const m=document.querySelector(".result.selected");m==null||m.scrollIntoView({block:"nearest"})})}_e("ArrowUp",m=>{m.preventDefault(),M.value--,M.value<0&&(M.value=w.value.length-1),U.value=!0,q()}),_e("ArrowDown",m=>{m.preventDefault(),M.value++,M.value>=w.value.length&&(M.value=0),U.value=!0,q()});const N=Vt();_e("Enter",m=>{if(m.isComposing||m.target instanceof HTMLButtonElement&&m.target.type!=="submit")return;const p=w.value[M.value];if(m.target instanceof HTMLInputElement&&!p){m.preventDefault();return}p&&(N.go(p.id),t("close"))}),_e("Escape",()=>{t("close")});const d=sn({modal:{displayDetails:"Display detailed list",resetButtonTitle:"Reset search",backButtonTitle:"Close search",noResultsText:"No results for",footer:{selectText:"to select",selectKeyAriaLabel:"enter",navigateText:"to navigate",navigateUpKeyAriaLabel:"up arrow",navigateDownKeyAriaLabel:"down arrow",closeText:"to close",closeKeyAriaLabel:"escape"}}});Me(()=>{window.history.pushState(null,"",null)}),$t("popstate",m=>{m.preventDefault(),t("close")});const v=Bt(Wt?document.body:null);Me(()=>{fe(()=>{v.value=!0,fe().then(()=>o())})}),Kt(()=>{v.value=!1});function T(){h.value="",fe().then(()=>$(!1))}function k(m){return new RegExp([...m].sort((p,E)=>E.length-p.length).map(p=>`(${en(p)})`).join("|"),"gi")}function O(m){var F;if(!U.value)return;const p=(F=m.target)==null?void 0:F.closest(".result"),E=Number.parseInt(p==null?void 0:p.dataset.index);E>=0&&E!==M.value&&(M.value=E),U.value=!1}return(m,p)=>{var E,F,z,P,j;return H(),Jt(Qt,{to:"body"},[_("div",{ref_key:"el",ref:n,role:"button","aria-owns":(E=w.value)!=null&&E.length?"localsearch-list":void 0,"aria-expanded":"true","aria-haspopup":"listbox","aria-labelledby":"localsearch-label",class:"VPLocalSearchBox"},[_("div",{class:"backdrop",onClick:p[0]||(p[0]=I=>m.$emit("close"))}),_("div",Xn,[_("form",{class:"search-bar",onPointerup:p[4]||(p[4]=I=>be(I)),onSubmit:p[5]||(p[5]=Ut(()=>{},["prevent"]))},[_("label",{title:x.value,id:"localsearch-label",for:"localsearch-input"},p[7]||(p[7]=[_("span",{"aria-hidden":"true",class:"vpi-search search-icon local-search-icon"},null,-1)]),8,es),_("div",ts,[_("button",{class:"back-button",title:L(d)("modal.backButtonTitle"),onClick:p[1]||(p[1]=I=>m.$emit("close"))},p[8]||(p[8]=[_("span",{class:"vpi-arrow-left local-search-icon"},null,-1)]),8,ns)]),qt(_("input",{ref_key:"searchInput",ref:W,"onUpdate:modelValue":p[2]||(p[2]=I=>Ht(h)?h.value=I:null),"aria-activedescendant":M.value>-1?"localsearch-item-"+M.value:void 0,"aria-autocomplete":"both","aria-controls":(F=w.value)!=null&&F.length?"localsearch-list":void 0,"aria-labelledby":"localsearch-label",autocapitalize:"off",autocomplete:"off",autocorrect:"off",class:"search-input",id:"localsearch-input",enterkeyhint:"go",maxlength:"64",placeholder:x.value,spellcheck:"false",type:"search"},null,8,ss),[[Gt,L(h)]]),_("div",is,[y.value?Se("",!0):(H(),Z("button",{key:0,class:st(["toggle-layout-button",{"detailed-list":L(b)}]),type:"button",title:L(d)("modal.displayDetails"),onClick:p[3]||(p[3]=I=>M.value>-1&&(b.value=!L(b)))},p[9]||(p[9]=[_("span",{class:"vpi-layout-list local-search-icon"},null,-1)]),10,rs)),_("button",{class:"clear-button",type:"reset",disabled:V.value,title:L(d)("modal.resetButtonTitle"),onClick:T},p[10]||(p[10]=[_("span",{class:"vpi-delete local-search-icon"},null,-1)]),8,as)])],32),_("ul",{ref_key:"resultsEl",ref:s,id:(z=w.value)!=null&&z.length?"localsearch-list":void 0,role:(P=w.value)!=null&&P.length?"listbox":void 0,"aria-labelledby":(j=w.value)!=null&&j.length?"localsearch-label":void 0,class:"results",onMousemove:O},[(H(!0),Z(rt,null,it(w.value,(I,K)=>(H(),Z("li",{key:I.id,id:"localsearch-item-"+K,"aria-selected":M.value===K?"true":"false",role:"option"},[_("a",{href:I.id,class:st(["result",{selected:M.value===K}]),"aria-label":[...I.titles,I.title].join(" > "),onMouseenter:ee=>!U.value&&(M.value=K),onFocusin:ee=>M.value=K,onClick:p[6]||(p[6]=ee=>m.$emit("close")),"data-index":K},[_("div",null,[_("div",us,[p[12]||(p[12]=_("span",{class:"title-icon"},"#",-1)),(H(!0),Z(rt,null,it(I.titles,(ee,ye)=>(H(),Z("span",{key:ye,class:"title"},[_("span",{class:"text",innerHTML:ee},null,8,ds),p[11]||(p[11]=_("span",{class:"vpi-chevron-right local-search-icon"},null,-1))]))),128)),_("span",fs,[_("span",{class:"text",innerHTML:I.title},null,8,hs)])]),L(b)?(H(),Z("div",ps,[I.text?(H(),Z("div",ms,[_("div",{class:"vp-doc",innerHTML:I.text},null,8,gs)])):Se("",!0),p[13]||(p[13]=_("div",{class:"excerpt-gradient-bottom"},null,-1)),p[14]||(p[14]=_("div",{class:"excerpt-gradient-top"},null,-1))])):Se("",!0)])],42,cs)],8,ls))),128)),L(h)&&!w.value.length&&R.value?(H(),Z("li",vs,[he(pe(L(d)("modal.noResultsText"))+' "',1),_("strong",null,pe(L(h)),1),p[15]||(p[15]=he('" '))])):Se("",!0)],40,os),_("div",bs,[_("span",null,[_("kbd",{"aria-label":L(d)("modal.footer.navigateUpKeyAriaLabel")},p[16]||(p[16]=[_("span",{class:"vpi-arrow-up navigate-icon"},null,-1)]),8,ys),_("kbd",{"aria-label":L(d)("modal.footer.navigateDownKeyAriaLabel")},p[17]||(p[17]=[_("span",{class:"vpi-arrow-down navigate-icon"},null,-1)]),8,ws),he(" "+pe(L(d)("modal.footer.navigateText")),1)]),_("span",null,[_("kbd",{"aria-label":L(d)("modal.footer.selectKeyAriaLabel")},p[18]||(p[18]=[_("span",{class:"vpi-corner-down-left navigate-icon"},null,-1)]),8,xs),he(" "+pe(L(d)("modal.footer.selectText")),1)]),_("span",null,[_("kbd",{"aria-label":L(d)("modal.footer.closeKeyAriaLabel")},"esc",8,_s),he(" "+pe(L(d)("modal.footer.closeText")),1)])])])],8,Zn)])}}}),Fs=tn(Ss,[["__scopeId","data-v-c4217006"]]);export{Fs as default}; diff --git a/assets/chunks/framework.Gfs4HC1t.js b/assets/chunks/framework.Gfs4HC1t.js new file mode 100644 index 00000000..32a1e307 --- /dev/null +++ b/assets/chunks/framework.Gfs4HC1t.js @@ -0,0 +1,18 @@ +/** +* @vue/shared v3.5.13 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**//*! #__NO_SIDE_EFFECTS__ */function Ns(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const Z={},Et=[],ke=()=>{},Wo=()=>!1,en=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Fs=e=>e.startsWith("onUpdate:"),de=Object.assign,Hs=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Ko=Object.prototype.hasOwnProperty,z=(e,t)=>Ko.call(e,t),W=Array.isArray,Tt=e=>In(e)==="[object Map]",si=e=>In(e)==="[object Set]",q=e=>typeof e=="function",re=e=>typeof e=="string",Xe=e=>typeof e=="symbol",ne=e=>e!==null&&typeof e=="object",ri=e=>(ne(e)||q(e))&&q(e.then)&&q(e.catch),ii=Object.prototype.toString,In=e=>ii.call(e),qo=e=>In(e).slice(8,-1),oi=e=>In(e)==="[object Object]",$s=e=>re(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Ct=Ns(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Nn=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Go=/-(\w)/g,Le=Nn(e=>e.replace(Go,(t,n)=>n?n.toUpperCase():"")),Yo=/\B([A-Z])/g,st=Nn(e=>e.replace(Yo,"-$1").toLowerCase()),Fn=Nn(e=>e.charAt(0).toUpperCase()+e.slice(1)),bn=Nn(e=>e?`on${Fn(e)}`:""),tt=(e,t)=>!Object.is(e,t),wn=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:s,value:n})},_s=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Xo=e=>{const t=re(e)?Number(e):NaN;return isNaN(t)?e:t};let cr;const Hn=()=>cr||(cr=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Ds(e){if(W(e)){const t={};for(let n=0;n{if(n){const s=n.split(zo);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function js(e){let t="";if(re(e))t=e;else if(W(e))for(let n=0;n!!(e&&e.__v_isRef===!0),nl=e=>re(e)?e:e==null?"":W(e)||ne(e)&&(e.toString===ii||!q(e.toString))?ai(e)?nl(e.value):JSON.stringify(e,fi,2):String(e),fi=(e,t)=>ai(t)?fi(e,t.value):Tt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,r],i)=>(n[zn(s,i)+" =>"]=r,n),{})}:si(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>zn(n))}:Xe(t)?zn(t):ne(t)&&!W(t)&&!oi(t)?String(t):t,zn=(e,t="")=>{var n;return Xe(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/** +* @vue/reactivity v3.5.13 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let ve;class sl{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=ve,!t&&ve&&(this.index=(ve.scopes||(ve.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes)for(t=0,n=this.scopes.length;t0)return;if(jt){let t=jt;for(jt=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;Dt;){let t=Dt;for(Dt=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function gi(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function mi(e){let t,n=e.depsTail,s=n;for(;s;){const r=s.prevDep;s.version===-1?(s===n&&(n=r),ks(s),il(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=r}e.deps=t,e.depsTail=n}function bs(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(yi(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function yi(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Kt))return;e.globalVersion=Kt;const t=e.dep;if(e.flags|=2,t.version>0&&!e.isSSR&&e.deps&&!bs(e)){e.flags&=-3;return}const n=te,s=Ne;te=e,Ne=!0;try{gi(e);const r=e.fn(e._value);(t.version===0||tt(r,e._value))&&(e._value=r,t.version++)}catch(r){throw t.version++,r}finally{te=n,Ne=s,mi(e),e.flags&=-3}}function ks(e,t=!1){const{dep:n,prevSub:s,nextSub:r}=e;if(s&&(s.nextSub=r,e.prevSub=void 0),r&&(r.prevSub=s,e.nextSub=void 0),n.subs===e&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let i=n.computed.deps;i;i=i.nextDep)ks(i,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function il(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}let Ne=!0;const _i=[];function rt(){_i.push(Ne),Ne=!1}function it(){const e=_i.pop();Ne=e===void 0?!0:e}function ar(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=te;te=void 0;try{t()}finally{te=n}}}let Kt=0;class ol{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class $n{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0}track(t){if(!te||!Ne||te===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==te)n=this.activeLink=new ol(te,this),te.deps?(n.prevDep=te.depsTail,te.depsTail.nextDep=n,te.depsTail=n):te.deps=te.depsTail=n,bi(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=te.depsTail,n.nextDep=void 0,te.depsTail.nextDep=n,te.depsTail=n,te.deps===n&&(te.deps=s)}return n}trigger(t){this.version++,Kt++,this.notify(t)}notify(t){Vs();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Us()}}}function bi(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)bi(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const Cn=new WeakMap,dt=Symbol(""),ws=Symbol(""),qt=Symbol("");function me(e,t,n){if(Ne&&te){let s=Cn.get(e);s||Cn.set(e,s=new Map);let r=s.get(n);r||(s.set(n,r=new $n),r.map=s,r.key=n),r.track()}}function Ge(e,t,n,s,r,i){const o=Cn.get(e);if(!o){Kt++;return}const l=c=>{c&&c.trigger()};if(Vs(),t==="clear")o.forEach(l);else{const c=W(e),f=c&&$s(n);if(c&&n==="length"){const a=Number(s);o.forEach((h,y)=>{(y==="length"||y===qt||!Xe(y)&&y>=a)&&l(h)})}else switch((n!==void 0||o.has(void 0))&&l(o.get(n)),f&&l(o.get(qt)),t){case"add":c?f&&l(o.get("length")):(l(o.get(dt)),Tt(e)&&l(o.get(ws)));break;case"delete":c||(l(o.get(dt)),Tt(e)&&l(o.get(ws)));break;case"set":Tt(e)&&l(o.get(dt));break}}Us()}function ll(e,t){const n=Cn.get(e);return n&&n.get(t)}function bt(e){const t=J(e);return t===e?t:(me(t,"iterate",qt),Pe(e)?t:t.map(ye))}function Dn(e){return me(e=J(e),"iterate",qt),e}const cl={__proto__:null,[Symbol.iterator](){return Zn(this,Symbol.iterator,ye)},concat(...e){return bt(this).concat(...e.map(t=>W(t)?bt(t):t))},entries(){return Zn(this,"entries",e=>(e[1]=ye(e[1]),e))},every(e,t){return We(this,"every",e,t,void 0,arguments)},filter(e,t){return We(this,"filter",e,t,n=>n.map(ye),arguments)},find(e,t){return We(this,"find",e,t,ye,arguments)},findIndex(e,t){return We(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return We(this,"findLast",e,t,ye,arguments)},findLastIndex(e,t){return We(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return We(this,"forEach",e,t,void 0,arguments)},includes(...e){return es(this,"includes",e)},indexOf(...e){return es(this,"indexOf",e)},join(e){return bt(this).join(e)},lastIndexOf(...e){return es(this,"lastIndexOf",e)},map(e,t){return We(this,"map",e,t,void 0,arguments)},pop(){return Ft(this,"pop")},push(...e){return Ft(this,"push",e)},reduce(e,...t){return fr(this,"reduce",e,t)},reduceRight(e,...t){return fr(this,"reduceRight",e,t)},shift(){return Ft(this,"shift")},some(e,t){return We(this,"some",e,t,void 0,arguments)},splice(...e){return Ft(this,"splice",e)},toReversed(){return bt(this).toReversed()},toSorted(e){return bt(this).toSorted(e)},toSpliced(...e){return bt(this).toSpliced(...e)},unshift(...e){return Ft(this,"unshift",e)},values(){return Zn(this,"values",ye)}};function Zn(e,t,n){const s=Dn(e),r=s[t]();return s!==e&&!Pe(e)&&(r._next=r.next,r.next=()=>{const i=r._next();return i.value&&(i.value=n(i.value)),i}),r}const al=Array.prototype;function We(e,t,n,s,r,i){const o=Dn(e),l=o!==e&&!Pe(e),c=o[t];if(c!==al[t]){const h=c.apply(e,i);return l?ye(h):h}let f=n;o!==e&&(l?f=function(h,y){return n.call(this,ye(h),y,e)}:n.length>2&&(f=function(h,y){return n.call(this,h,y,e)}));const a=c.call(o,f,s);return l&&r?r(a):a}function fr(e,t,n,s){const r=Dn(e);let i=n;return r!==e&&(Pe(e)?n.length>3&&(i=function(o,l,c){return n.call(this,o,l,c,e)}):i=function(o,l,c){return n.call(this,o,ye(l),c,e)}),r[t](i,...s)}function es(e,t,n){const s=J(e);me(s,"iterate",qt);const r=s[t](...n);return(r===-1||r===!1)&&Ks(n[0])?(n[0]=J(n[0]),s[t](...n)):r}function Ft(e,t,n=[]){rt(),Vs();const s=J(e)[t].apply(e,n);return Us(),it(),s}const fl=Ns("__proto__,__v_isRef,__isVue"),wi=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Xe));function ul(e){Xe(e)||(e=String(e));const t=J(this);return me(t,"has",e),t.hasOwnProperty(e)}class vi{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){if(n==="__v_skip")return t.__v_skip;const r=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!r;if(n==="__v_isReadonly")return r;if(n==="__v_isShallow")return i;if(n==="__v_raw")return s===(r?i?vl:Ti:i?Ei:xi).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const o=W(t);if(!r){let c;if(o&&(c=cl[n]))return c;if(n==="hasOwnProperty")return ul}const l=Reflect.get(t,n,ae(t)?t:s);return(Xe(n)?wi.has(n):fl(n))||(r||me(t,"get",n),i)?l:ae(l)?o&&$s(n)?l:l.value:ne(l)?r?Vn(l):jn(l):l}}class Si extends vi{constructor(t=!1){super(!1,t)}set(t,n,s,r){let i=t[n];if(!this._isShallow){const c=yt(i);if(!Pe(s)&&!yt(s)&&(i=J(i),s=J(s)),!W(t)&&ae(i)&&!ae(s))return c?!1:(i.value=s,!0)}const o=W(t)&&$s(n)?Number(n)e,cn=e=>Reflect.getPrototypeOf(e);function ml(e,t,n){return function(...s){const r=this.__v_raw,i=J(r),o=Tt(i),l=e==="entries"||e===Symbol.iterator&&o,c=e==="keys"&&o,f=r[e](...s),a=n?vs:t?Ss:ye;return!t&&me(i,"iterate",c?ws:dt),{next(){const{value:h,done:y}=f.next();return y?{value:h,done:y}:{value:l?[a(h[0]),a(h[1])]:a(h),done:y}},[Symbol.iterator](){return this}}}}function an(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function yl(e,t){const n={get(r){const i=this.__v_raw,o=J(i),l=J(r);e||(tt(r,l)&&me(o,"get",r),me(o,"get",l));const{has:c}=cn(o),f=t?vs:e?Ss:ye;if(c.call(o,r))return f(i.get(r));if(c.call(o,l))return f(i.get(l));i!==o&&i.get(r)},get size(){const r=this.__v_raw;return!e&&me(J(r),"iterate",dt),Reflect.get(r,"size",r)},has(r){const i=this.__v_raw,o=J(i),l=J(r);return e||(tt(r,l)&&me(o,"has",r),me(o,"has",l)),r===l?i.has(r):i.has(r)||i.has(l)},forEach(r,i){const o=this,l=o.__v_raw,c=J(l),f=t?vs:e?Ss:ye;return!e&&me(c,"iterate",dt),l.forEach((a,h)=>r.call(i,f(a),f(h),o))}};return de(n,e?{add:an("add"),set:an("set"),delete:an("delete"),clear:an("clear")}:{add(r){!t&&!Pe(r)&&!yt(r)&&(r=J(r));const i=J(this);return cn(i).has.call(i,r)||(i.add(r),Ge(i,"add",r,r)),this},set(r,i){!t&&!Pe(i)&&!yt(i)&&(i=J(i));const o=J(this),{has:l,get:c}=cn(o);let f=l.call(o,r);f||(r=J(r),f=l.call(o,r));const a=c.call(o,r);return o.set(r,i),f?tt(i,a)&&Ge(o,"set",r,i):Ge(o,"add",r,i),this},delete(r){const i=J(this),{has:o,get:l}=cn(i);let c=o.call(i,r);c||(r=J(r),c=o.call(i,r)),l&&l.call(i,r);const f=i.delete(r);return c&&Ge(i,"delete",r,void 0),f},clear(){const r=J(this),i=r.size!==0,o=r.clear();return i&&Ge(r,"clear",void 0,void 0),o}}),["keys","values","entries",Symbol.iterator].forEach(r=>{n[r]=ml(r,e,t)}),n}function Bs(e,t){const n=yl(e,t);return(s,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?s:Reflect.get(z(n,r)&&r in s?n:s,r,i)}const _l={get:Bs(!1,!1)},bl={get:Bs(!1,!0)},wl={get:Bs(!0,!1)};const xi=new WeakMap,Ei=new WeakMap,Ti=new WeakMap,vl=new WeakMap;function Sl(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function xl(e){return e.__v_skip||!Object.isExtensible(e)?0:Sl(qo(e))}function jn(e){return yt(e)?e:Ws(e,!1,hl,_l,xi)}function El(e){return Ws(e,!1,gl,bl,Ei)}function Vn(e){return Ws(e,!0,pl,wl,Ti)}function Ws(e,t,n,s,r){if(!ne(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=r.get(e);if(i)return i;const o=xl(e);if(o===0)return e;const l=new Proxy(e,o===2?s:n);return r.set(e,l),l}function ht(e){return yt(e)?ht(e.__v_raw):!!(e&&e.__v_isReactive)}function yt(e){return!!(e&&e.__v_isReadonly)}function Pe(e){return!!(e&&e.__v_isShallow)}function Ks(e){return e?!!e.__v_raw:!1}function J(e){const t=e&&e.__v_raw;return t?J(t):e}function vn(e){return!z(e,"__v_skip")&&Object.isExtensible(e)&&li(e,"__v_skip",!0),e}const ye=e=>ne(e)?jn(e):e,Ss=e=>ne(e)?Vn(e):e;function ae(e){return e?e.__v_isRef===!0:!1}function oe(e){return Ci(e,!1)}function qs(e){return Ci(e,!0)}function Ci(e,t){return ae(e)?e:new Tl(e,t)}class Tl{constructor(t,n){this.dep=new $n,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:J(t),this._value=n?t:ye(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,s=this.__v_isShallow||Pe(t)||yt(t);t=s?t:J(t),tt(t,n)&&(this._rawValue=t,this._value=s?t:ye(t),this.dep.trigger())}}function Ai(e){return ae(e)?e.value:e}const Cl={get:(e,t,n)=>t==="__v_raw"?e:Ai(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const r=e[t];return ae(r)&&!ae(n)?(r.value=n,!0):Reflect.set(e,t,n,s)}};function Ri(e){return ht(e)?e:new Proxy(e,Cl)}class Al{constructor(t){this.__v_isRef=!0,this._value=void 0;const n=this.dep=new $n,{get:s,set:r}=t(n.track.bind(n),n.trigger.bind(n));this._get=s,this._set=r}get value(){return this._value=this._get()}set value(t){this._set(t)}}function Rl(e){return new Al(e)}class Ol{constructor(t,n,s){this._object=t,this._key=n,this._defaultValue=s,this.__v_isRef=!0,this._value=void 0}get value(){const t=this._object[this._key];return this._value=t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return ll(J(this._object),this._key)}}class Ml{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function Pl(e,t,n){return ae(e)?e:q(e)?new Ml(e):ne(e)&&arguments.length>1?Ll(e,t,n):oe(e)}function Ll(e,t,n){const s=e[t];return ae(s)?s:new Ol(e,t,n)}class Il{constructor(t,n,s){this.fn=t,this.setter=n,this._value=void 0,this.dep=new $n(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Kt-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&te!==this)return pi(this,!0),!0}get value(){const t=this.dep.track();return yi(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function Nl(e,t,n=!1){let s,r;return q(e)?s=e:(s=e.get,r=e.set),new Il(s,r,n)}const fn={},An=new WeakMap;let ft;function Fl(e,t=!1,n=ft){if(n){let s=An.get(n);s||An.set(n,s=[]),s.push(e)}}function Hl(e,t,n=Z){const{immediate:s,deep:r,once:i,scheduler:o,augmentJob:l,call:c}=n,f=g=>r?g:Pe(g)||r===!1||r===0?Ye(g,1):Ye(g);let a,h,y,_,S=!1,b=!1;if(ae(e)?(h=()=>e.value,S=Pe(e)):ht(e)?(h=()=>f(e),S=!0):W(e)?(b=!0,S=e.some(g=>ht(g)||Pe(g)),h=()=>e.map(g=>{if(ae(g))return g.value;if(ht(g))return f(g);if(q(g))return c?c(g,2):g()})):q(e)?t?h=c?()=>c(e,2):e:h=()=>{if(y){rt();try{y()}finally{it()}}const g=ft;ft=a;try{return c?c(e,3,[_]):e(_)}finally{ft=g}}:h=ke,t&&r){const g=h,O=r===!0?1/0:r;h=()=>Ye(g(),O)}const K=ui(),N=()=>{a.stop(),K&&K.active&&Hs(K.effects,a)};if(i&&t){const g=t;t=(...O)=>{g(...O),N()}}let j=b?new Array(e.length).fill(fn):fn;const p=g=>{if(!(!(a.flags&1)||!a.dirty&&!g))if(t){const O=a.run();if(r||S||(b?O.some((F,$)=>tt(F,j[$])):tt(O,j))){y&&y();const F=ft;ft=a;try{const $=[O,j===fn?void 0:b&&j[0]===fn?[]:j,_];c?c(t,3,$):t(...$),j=O}finally{ft=F}}}else a.run()};return l&&l(p),a=new di(h),a.scheduler=o?()=>o(p,!1):p,_=g=>Fl(g,!1,a),y=a.onStop=()=>{const g=An.get(a);if(g){if(c)c(g,4);else for(const O of g)O();An.delete(a)}},t?s?p(!0):j=a.run():o?o(p.bind(null,!0),!0):a.run(),N.pause=a.pause.bind(a),N.resume=a.resume.bind(a),N.stop=N,N}function Ye(e,t=1/0,n){if(t<=0||!ne(e)||e.__v_skip||(n=n||new Set,n.has(e)))return e;if(n.add(e),t--,ae(e))Ye(e.value,t,n);else if(W(e))for(let s=0;s{Ye(s,t,n)});else if(oi(e)){for(const s in e)Ye(e[s],t,n);for(const s of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,s)&&Ye(e[s],t,n)}return e}/** +* @vue/runtime-core v3.5.13 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function tn(e,t,n,s){try{return s?e(...s):e()}catch(r){nn(r,t,n)}}function He(e,t,n,s){if(q(e)){const r=tn(e,t,n,s);return r&&ri(r)&&r.catch(i=>{nn(i,t,n)}),r}if(W(e)){const r=[];for(let i=0;i>>1,r=Se[s],i=Gt(r);i=Gt(n)?Se.push(e):Se.splice(Dl(t),0,e),e.flags|=1,Mi()}}function Mi(){Rn||(Rn=Oi.then(Pi))}function jl(e){W(e)?At.push(...e):Qe&&e.id===-1?Qe.splice(vt+1,0,e):e.flags&1||(At.push(e),e.flags|=1),Mi()}function ur(e,t,n=Ve+1){for(;nGt(n)-Gt(s));if(At.length=0,Qe){Qe.push(...t);return}for(Qe=t,vt=0;vte.id==null?e.flags&2?-1:1/0:e.id;function Pi(e){try{for(Ve=0;Ve{s._d&&Cr(-1);const i=Mn(t);let o;try{o=e(...r)}finally{Mn(i),s._d&&Cr(1)}return o};return s._n=!0,s._c=!0,s._d=!0,s}function _f(e,t){if(ue===null)return e;const n=Gn(ue),s=e.dirs||(e.dirs=[]);for(let r=0;re.__isTeleport,Vt=e=>e&&(e.disabled||e.disabled===""),dr=e=>e&&(e.defer||e.defer===""),hr=e=>typeof SVGElement<"u"&&e instanceof SVGElement,pr=e=>typeof MathMLElement=="function"&&e instanceof MathMLElement,xs=(e,t)=>{const n=e&&e.to;return re(n)?t?t(n):null:n},Fi={name:"Teleport",__isTeleport:!0,process(e,t,n,s,r,i,o,l,c,f){const{mc:a,pc:h,pbc:y,o:{insert:_,querySelector:S,createText:b,createComment:K}}=f,N=Vt(t.props);let{shapeFlag:j,children:p,dynamicChildren:g}=t;if(e==null){const O=t.el=b(""),F=t.anchor=b("");_(O,n,s),_(F,n,s);const $=(R,w)=>{j&16&&(r&&r.isCE&&(r.ce._teleportTarget=R),a(p,R,w,r,i,o,l,c))},V=()=>{const R=t.target=xs(t.props,S),w=Hi(R,t,b,_);R&&(o!=="svg"&&hr(R)?o="svg":o!=="mathml"&&pr(R)&&(o="mathml"),N||($(R,w),Sn(t,!1)))};N&&($(n,F),Sn(t,!0)),dr(t.props)?we(()=>{V(),t.el.__isMounted=!0},i):V()}else{if(dr(t.props)&&!e.el.__isMounted){we(()=>{Fi.process(e,t,n,s,r,i,o,l,c,f),delete e.el.__isMounted},i);return}t.el=e.el,t.targetStart=e.targetStart;const O=t.anchor=e.anchor,F=t.target=e.target,$=t.targetAnchor=e.targetAnchor,V=Vt(e.props),R=V?n:F,w=V?O:$;if(o==="svg"||hr(F)?o="svg":(o==="mathml"||pr(F))&&(o="mathml"),g?(y(e.dynamicChildren,g,R,r,i,o,l),zs(e,t,!0)):c||h(e,t,R,w,r,i,o,l,!1),N)V?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):un(t,n,O,f,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const I=t.target=xs(t.props,S);I&&un(t,I,null,f,0)}else V&&un(t,F,$,f,1);Sn(t,N)}},remove(e,t,n,{um:s,o:{remove:r}},i){const{shapeFlag:o,children:l,anchor:c,targetStart:f,targetAnchor:a,target:h,props:y}=e;if(h&&(r(f),r(a)),i&&r(c),o&16){const _=i||!Vt(y);for(let S=0;S{e.isMounted=!0}),Bi(()=>{e.isUnmounting=!0}),e}const Re=[Function,Array],$i={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Re,onEnter:Re,onAfterEnter:Re,onEnterCancelled:Re,onBeforeLeave:Re,onLeave:Re,onAfterLeave:Re,onLeaveCancelled:Re,onBeforeAppear:Re,onAppear:Re,onAfterAppear:Re,onAppearCancelled:Re},Di=e=>{const t=e.subTree;return t.component?Di(t.component):t},Bl={name:"BaseTransition",props:$i,setup(e,{slots:t}){const n=qn(),s=kl();return()=>{const r=t.default&&Ui(t.default(),!0);if(!r||!r.length)return;const i=ji(r),o=J(e),{mode:l}=o;if(s.isLeaving)return ts(i);const c=gr(i);if(!c)return ts(i);let f=Es(c,o,s,n,h=>f=h);c.type!==_e&&Yt(c,f);let a=n.subTree&&gr(n.subTree);if(a&&a.type!==_e&&!ut(c,a)&&Di(n).type!==_e){let h=Es(a,o,s,n);if(Yt(a,h),l==="out-in"&&c.type!==_e)return s.isLeaving=!0,h.afterLeave=()=>{s.isLeaving=!1,n.job.flags&8||n.update(),delete h.afterLeave,a=void 0},ts(i);l==="in-out"&&c.type!==_e?h.delayLeave=(y,_,S)=>{const b=Vi(s,a);b[String(a.key)]=a,y[Ze]=()=>{_(),y[Ze]=void 0,delete f.delayedLeave,a=void 0},f.delayedLeave=()=>{S(),delete f.delayedLeave,a=void 0}}:a=void 0}else a&&(a=void 0);return i}}};function ji(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==_e){t=n;break}}return t}const Wl=Bl;function Vi(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function Es(e,t,n,s,r){const{appear:i,mode:o,persisted:l=!1,onBeforeEnter:c,onEnter:f,onAfterEnter:a,onEnterCancelled:h,onBeforeLeave:y,onLeave:_,onAfterLeave:S,onLeaveCancelled:b,onBeforeAppear:K,onAppear:N,onAfterAppear:j,onAppearCancelled:p}=t,g=String(e.key),O=Vi(n,e),F=(R,w)=>{R&&He(R,s,9,w)},$=(R,w)=>{const I=w[1];F(R,w),W(R)?R.every(x=>x.length<=1)&&I():R.length<=1&&I()},V={mode:o,persisted:l,beforeEnter(R){let w=c;if(!n.isMounted)if(i)w=K||c;else return;R[Ze]&&R[Ze](!0);const I=O[g];I&&ut(e,I)&&I.el[Ze]&&I.el[Ze](),F(w,[R])},enter(R){let w=f,I=a,x=h;if(!n.isMounted)if(i)w=N||f,I=j||a,x=p||h;else return;let B=!1;const se=R[dn]=le=>{B||(B=!0,le?F(x,[R]):F(I,[R]),V.delayedLeave&&V.delayedLeave(),R[dn]=void 0)};w?$(w,[R,se]):se()},leave(R,w){const I=String(e.key);if(R[dn]&&R[dn](!0),n.isUnmounting)return w();F(y,[R]);let x=!1;const B=R[Ze]=se=>{x||(x=!0,w(),se?F(b,[R]):F(S,[R]),R[Ze]=void 0,O[I]===e&&delete O[I])};O[I]=e,_?$(_,[R,B]):B()},clone(R){const w=Es(R,t,n,s,r);return r&&r(w),w}};return V}function ts(e){if(sn(e))return e=nt(e),e.children=null,e}function gr(e){if(!sn(e))return Ni(e.type)&&e.children?ji(e.children):e;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&q(n.default))return n.default()}}function Yt(e,t){e.shapeFlag&6&&e.component?(e.transition=t,Yt(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Ui(e,t=!1,n){let s=[],r=0;for(let i=0;i1)for(let i=0;iXt(S,t&&(W(t)?t[b]:t),n,s,r));return}if(pt(s)&&!r){s.shapeFlag&512&&s.type.__asyncResolved&&s.component.subTree.component&&Xt(e,t,n,s.component.subTree);return}const i=s.shapeFlag&4?Gn(s.component):s.el,o=r?null:i,{i:l,r:c}=e,f=t&&t.r,a=l.refs===Z?l.refs={}:l.refs,h=l.setupState,y=J(h),_=h===Z?()=>!1:S=>z(y,S);if(f!=null&&f!==c&&(re(f)?(a[f]=null,_(f)&&(h[f]=null)):ae(f)&&(f.value=null)),q(c))tn(c,l,12,[o,a]);else{const S=re(c),b=ae(c);if(S||b){const K=()=>{if(e.f){const N=S?_(c)?h[c]:a[c]:c.value;r?W(N)&&Hs(N,i):W(N)?N.includes(i)||N.push(i):S?(a[c]=[i],_(c)&&(h[c]=a[c])):(c.value=[i],e.k&&(a[e.k]=c.value))}else S?(a[c]=o,_(c)&&(h[c]=o)):b&&(c.value=o,e.k&&(a[e.k]=o))};o?(K.id=-1,we(K,n)):K()}}}let mr=!1;const wt=()=>{mr||(console.error("Hydration completed but contains mismatches."),mr=!0)},Kl=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",ql=e=>e.namespaceURI.includes("MathML"),hn=e=>{if(e.nodeType===1){if(Kl(e))return"svg";if(ql(e))return"mathml"}},xt=e=>e.nodeType===8;function Gl(e){const{mt:t,p:n,o:{patchProp:s,createText:r,nextSibling:i,parentNode:o,remove:l,insert:c,createComment:f}}=e,a=(p,g)=>{if(!g.hasChildNodes()){n(null,p,g),On(),g._vnode=p;return}h(g.firstChild,p,null,null,null),On(),g._vnode=p},h=(p,g,O,F,$,V=!1)=>{V=V||!!g.dynamicChildren;const R=xt(p)&&p.data==="[",w=()=>b(p,g,O,F,$,R),{type:I,ref:x,shapeFlag:B,patchFlag:se}=g;let le=p.nodeType;g.el=p,se===-2&&(V=!1,g.dynamicChildren=null);let U=null;switch(I){case gt:le!==3?g.children===""?(c(g.el=r(""),o(p),p),U=p):U=w():(p.data!==g.children&&(wt(),p.data=g.children),U=i(p));break;case _e:j(p)?(U=i(p),N(g.el=p.content.firstChild,p,O)):le!==8||R?U=w():U=i(p);break;case kt:if(R&&(p=i(p),le=p.nodeType),le===1||le===3){U=p;const Y=!g.children.length;for(let D=0;D{V=V||!!g.dynamicChildren;const{type:R,props:w,patchFlag:I,shapeFlag:x,dirs:B,transition:se}=g,le=R==="input"||R==="option";if(le||I!==-1){B&&Ue(g,null,O,"created");let U=!1;if(j(p)){U=lo(null,se)&&O&&O.vnode.props&&O.vnode.props.appear;const D=p.content.firstChild;U&&se.beforeEnter(D),N(D,p,O),g.el=p=D}if(x&16&&!(w&&(w.innerHTML||w.textContent))){let D=_(p.firstChild,g,p,O,F,$,V);for(;D;){pn(p,1)||wt();const he=D;D=D.nextSibling,l(he)}}else if(x&8){let D=g.children;D[0]===` +`&&(p.tagName==="PRE"||p.tagName==="TEXTAREA")&&(D=D.slice(1)),p.textContent!==D&&(pn(p,0)||wt(),p.textContent=g.children)}if(w){if(le||!V||I&48){const D=p.tagName.includes("-");for(const he in w)(le&&(he.endsWith("value")||he==="indeterminate")||en(he)&&!Ct(he)||he[0]==="."||D)&&s(p,he,null,w[he],void 0,O)}else if(w.onClick)s(p,"onClick",null,w.onClick,void 0,O);else if(I&4&&ht(w.style))for(const D in w.style)w.style[D]}let Y;(Y=w&&w.onVnodeBeforeMount)&&Oe(Y,O,g),B&&Ue(g,null,O,"beforeMount"),((Y=w&&w.onVnodeMounted)||B||U)&&po(()=>{Y&&Oe(Y,O,g),U&&se.enter(p),B&&Ue(g,null,O,"mounted")},F)}return p.nextSibling},_=(p,g,O,F,$,V,R)=>{R=R||!!g.dynamicChildren;const w=g.children,I=w.length;for(let x=0;x{const{slotScopeIds:R}=g;R&&($=$?$.concat(R):R);const w=o(p),I=_(i(p),g,w,O,F,$,V);return I&&xt(I)&&I.data==="]"?i(g.anchor=I):(wt(),c(g.anchor=f("]"),w,I),I)},b=(p,g,O,F,$,V)=>{if(pn(p.parentElement,1)||wt(),g.el=null,V){const I=K(p);for(;;){const x=i(p);if(x&&x!==I)l(x);else break}}const R=i(p),w=o(p);return l(p),n(null,g,w,R,O,F,hn(w),$),O&&(O.vnode.el=g.el,uo(O,g.el)),R},K=(p,g="[",O="]")=>{let F=0;for(;p;)if(p=i(p),p&&xt(p)&&(p.data===g&&F++,p.data===O)){if(F===0)return i(p);F--}return p},N=(p,g,O)=>{const F=g.parentNode;F&&F.replaceChild(p,g);let $=O;for(;$;)$.vnode.el===g&&($.vnode.el=$.subTree.el=p),$=$.parent},j=p=>p.nodeType===1&&p.tagName==="TEMPLATE";return[a,h]}const yr="data-allow-mismatch",Yl={0:"text",1:"children",2:"class",3:"style",4:"attribute"};function pn(e,t){if(t===0||t===1)for(;e&&!e.hasAttribute(yr);)e=e.parentElement;const n=e&&e.getAttribute(yr);if(n==null)return!1;if(n==="")return!0;{const s=n.split(",");return t===0&&s.includes("children")?!0:n.split(",").includes(Yl[t])}}Hn().requestIdleCallback;Hn().cancelIdleCallback;function Xl(e,t){if(xt(e)&&e.data==="["){let n=1,s=e.nextSibling;for(;s;){if(s.nodeType===1){if(t(s)===!1)break}else if(xt(s))if(s.data==="]"){if(--n===0)break}else s.data==="["&&n++;s=s.nextSibling}}else t(e)}const pt=e=>!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function wf(e){q(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:s,delay:r=200,hydrate:i,timeout:o,suspensible:l=!0,onError:c}=e;let f=null,a,h=0;const y=()=>(h++,f=null,_()),_=()=>{let S;return f||(S=f=t().catch(b=>{if(b=b instanceof Error?b:new Error(String(b)),c)return new Promise((K,N)=>{c(b,()=>K(y()),()=>N(b),h+1)});throw b}).then(b=>S!==f&&f?f:(b&&(b.__esModule||b[Symbol.toStringTag]==="Module")&&(b=b.default),a=b,b)))};return Ys({name:"AsyncComponentWrapper",__asyncLoader:_,__asyncHydrate(S,b,K){const N=i?()=>{const j=i(K,p=>Xl(S,p));j&&(b.bum||(b.bum=[])).push(j)}:K;a?N():_().then(()=>!b.isUnmounted&&N())},get __asyncResolved(){return a},setup(){const S=fe;if(Xs(S),a)return()=>ns(a,S);const b=p=>{f=null,nn(p,S,13,!s)};if(l&&S.suspense||Mt)return _().then(p=>()=>ns(p,S)).catch(p=>(b(p),()=>s?ce(s,{error:p}):null));const K=oe(!1),N=oe(),j=oe(!!r);return r&&setTimeout(()=>{j.value=!1},r),o!=null&&setTimeout(()=>{if(!K.value&&!N.value){const p=new Error(`Async component timed out after ${o}ms.`);b(p),N.value=p}},o),_().then(()=>{K.value=!0,S.parent&&sn(S.parent.vnode)&&S.parent.update()}).catch(p=>{b(p),N.value=p}),()=>{if(K.value&&a)return ns(a,S);if(N.value&&s)return ce(s,{error:N.value});if(n&&!j.value)return ce(n)}}})}function ns(e,t){const{ref:n,props:s,children:r,ce:i}=t.vnode,o=ce(e,s,r);return o.ref=n,o.ce=i,delete t.vnode.ce,o}const sn=e=>e.type.__isKeepAlive;function Jl(e,t){ki(e,"a",t)}function zl(e,t){ki(e,"da",t)}function ki(e,t,n=fe){const s=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(kn(t,s,n),n){let r=n.parent;for(;r&&r.parent;)sn(r.parent.vnode)&&Ql(s,t,n,r),r=r.parent}}function Ql(e,t,n,s){const r=kn(t,e,s,!0);Bn(()=>{Hs(s[t],r)},n)}function kn(e,t,n=fe,s=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...o)=>{rt();const l=rn(n),c=He(t,n,e,o);return l(),it(),c});return s?r.unshift(i):r.push(i),i}}const Je=e=>(t,n=fe)=>{(!Mt||e==="sp")&&kn(e,(...s)=>t(...s),n)},Zl=Je("bm"),Lt=Je("m"),ec=Je("bu"),tc=Je("u"),Bi=Je("bum"),Bn=Je("um"),nc=Je("sp"),sc=Je("rtg"),rc=Je("rtc");function ic(e,t=fe){kn("ec",e,t)}const Wi="components";function vf(e,t){return qi(Wi,e,!0,t)||e}const Ki=Symbol.for("v-ndc");function Sf(e){return re(e)?qi(Wi,e,!1)||e:e||Ki}function qi(e,t,n=!0,s=!1){const r=ue||fe;if(r){const i=r.type;{const l=Bc(i,!1);if(l&&(l===t||l===Le(t)||l===Fn(Le(t))))return i}const o=_r(r[e]||i[e],t)||_r(r.appContext[e],t);return!o&&s?i:o}}function _r(e,t){return e&&(e[t]||e[Le(t)]||e[Fn(Le(t))])}function xf(e,t,n,s){let r;const i=n,o=W(e);if(o||re(e)){const l=o&&ht(e);let c=!1;l&&(c=!Pe(e),e=Dn(e)),r=new Array(e.length);for(let f=0,a=e.length;ft(l,c,void 0,i));else{const l=Object.keys(e);r=new Array(l.length);for(let c=0,f=l.length;czt(t)?!(t.type===_e||t.type===xe&&!Gi(t.children)):!0)?e:null}function Tf(e,t){const n={};for(const s in e)n[/[A-Z]/.test(s)?`on:${s}`:bn(s)]=e[s];return n}const Ts=e=>e?bo(e)?Gn(e):Ts(e.parent):null,Ut=de(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Ts(e.parent),$root:e=>Ts(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Xi(e),$forceUpdate:e=>e.f||(e.f=()=>{Gs(e.update)}),$nextTick:e=>e.n||(e.n=Un.bind(e.proxy)),$watch:e=>Ac.bind(e)}),ss=(e,t)=>e!==Z&&!e.__isScriptSetup&&z(e,t),oc={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:r,props:i,accessCache:o,type:l,appContext:c}=e;let f;if(t[0]!=="$"){const _=o[t];if(_!==void 0)switch(_){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if(ss(s,t))return o[t]=1,s[t];if(r!==Z&&z(r,t))return o[t]=2,r[t];if((f=e.propsOptions[0])&&z(f,t))return o[t]=3,i[t];if(n!==Z&&z(n,t))return o[t]=4,n[t];Cs&&(o[t]=0)}}const a=Ut[t];let h,y;if(a)return t==="$attrs"&&me(e.attrs,"get",""),a(e);if((h=l.__cssModules)&&(h=h[t]))return h;if(n!==Z&&z(n,t))return o[t]=4,n[t];if(y=c.config.globalProperties,z(y,t))return y[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:i}=e;return ss(r,t)?(r[t]=n,!0):s!==Z&&z(s,t)?(s[t]=n,!0):z(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,propsOptions:i}},o){let l;return!!n[o]||e!==Z&&z(e,o)||ss(t,o)||(l=i[0])&&z(l,o)||z(s,o)||z(Ut,o)||z(r.config.globalProperties,o)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:z(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function Cf(){return lc().slots}function lc(){const e=qn();return e.setupContext||(e.setupContext=vo(e))}function br(e){return W(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Cs=!0;function cc(e){const t=Xi(e),n=e.proxy,s=e.ctx;Cs=!1,t.beforeCreate&&wr(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:o,watch:l,provide:c,inject:f,created:a,beforeMount:h,mounted:y,beforeUpdate:_,updated:S,activated:b,deactivated:K,beforeDestroy:N,beforeUnmount:j,destroyed:p,unmounted:g,render:O,renderTracked:F,renderTriggered:$,errorCaptured:V,serverPrefetch:R,expose:w,inheritAttrs:I,components:x,directives:B,filters:se}=t;if(f&&ac(f,s,null),o)for(const Y in o){const D=o[Y];q(D)&&(s[Y]=D.bind(n))}if(r){const Y=r.call(n,n);ne(Y)&&(e.data=jn(Y))}if(Cs=!0,i)for(const Y in i){const D=i[Y],he=q(D)?D.bind(n,n):q(D.get)?D.get.bind(n,n):ke,on=!q(D)&&q(D.set)?D.set.bind(n):ke,ot=ie({get:he,set:on});Object.defineProperty(s,Y,{enumerable:!0,configurable:!0,get:()=>ot.value,set:De=>ot.value=De})}if(l)for(const Y in l)Yi(l[Y],s,n,Y);if(c){const Y=q(c)?c.call(n):c;Reflect.ownKeys(Y).forEach(D=>{gc(D,Y[D])})}a&&wr(a,e,"c");function U(Y,D){W(D)?D.forEach(he=>Y(he.bind(n))):D&&Y(D.bind(n))}if(U(Zl,h),U(Lt,y),U(ec,_),U(tc,S),U(Jl,b),U(zl,K),U(ic,V),U(rc,F),U(sc,$),U(Bi,j),U(Bn,g),U(nc,R),W(w))if(w.length){const Y=e.exposed||(e.exposed={});w.forEach(D=>{Object.defineProperty(Y,D,{get:()=>n[D],set:he=>n[D]=he})})}else e.exposed||(e.exposed={});O&&e.render===ke&&(e.render=O),I!=null&&(e.inheritAttrs=I),x&&(e.components=x),B&&(e.directives=B),R&&Xs(e)}function ac(e,t,n=ke){W(e)&&(e=As(e));for(const s in e){const r=e[s];let i;ne(r)?"default"in r?i=Ot(r.from||s,r.default,!0):i=Ot(r.from||s):i=Ot(r),ae(i)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>i.value,set:o=>i.value=o}):t[s]=i}}function wr(e,t,n){He(W(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function Yi(e,t,n,s){let r=s.includes(".")?ao(n,s):()=>n[s];if(re(e)){const i=t[e];q(i)&&Fe(r,i)}else if(q(e))Fe(r,e.bind(n));else if(ne(e))if(W(e))e.forEach(i=>Yi(i,t,n,s));else{const i=q(e.handler)?e.handler.bind(n):t[e.handler];q(i)&&Fe(r,i,e)}}function Xi(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:o}}=e.appContext,l=i.get(t);let c;return l?c=l:!r.length&&!n&&!s?c=t:(c={},r.length&&r.forEach(f=>Pn(c,f,o,!0)),Pn(c,t,o)),ne(t)&&i.set(t,c),c}function Pn(e,t,n,s=!1){const{mixins:r,extends:i}=t;i&&Pn(e,i,n,!0),r&&r.forEach(o=>Pn(e,o,n,!0));for(const o in t)if(!(s&&o==="expose")){const l=fc[o]||n&&n[o];e[o]=l?l(e[o],t[o]):t[o]}return e}const fc={data:vr,props:Sr,emits:Sr,methods:$t,computed:$t,beforeCreate:be,created:be,beforeMount:be,mounted:be,beforeUpdate:be,updated:be,beforeDestroy:be,beforeUnmount:be,destroyed:be,unmounted:be,activated:be,deactivated:be,errorCaptured:be,serverPrefetch:be,components:$t,directives:$t,watch:dc,provide:vr,inject:uc};function vr(e,t){return t?e?function(){return de(q(e)?e.call(this,this):e,q(t)?t.call(this,this):t)}:t:e}function uc(e,t){return $t(As(e),As(t))}function As(e){if(W(e)){const t={};for(let n=0;n1)return n&&q(t)?t.call(s&&s.proxy):t}}const zi={},Qi=()=>Object.create(zi),Zi=e=>Object.getPrototypeOf(e)===zi;function mc(e,t,n,s=!1){const r={},i=Qi();e.propsDefaults=Object.create(null),eo(e,t,r,i);for(const o in e.propsOptions[0])o in r||(r[o]=void 0);n?e.props=s?r:El(r):e.type.props?e.props=r:e.props=i,e.attrs=i}function yc(e,t,n,s){const{props:r,attrs:i,vnode:{patchFlag:o}}=e,l=J(r),[c]=e.propsOptions;let f=!1;if((s||o>0)&&!(o&16)){if(o&8){const a=e.vnode.dynamicProps;for(let h=0;h{c=!0;const[y,_]=to(h,t,!0);de(o,y),_&&l.push(..._)};!n&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}if(!i&&!c)return ne(e)&&s.set(e,Et),Et;if(W(i))for(let a=0;ae[0]==="_"||e==="$stable",Js=e=>W(e)?e.map(Me):[Me(e)],bc=(e,t,n)=>{if(t._n)return t;const s=Vl((...r)=>Js(t(...r)),n);return s._c=!1,s},so=(e,t,n)=>{const s=e._ctx;for(const r in e){if(no(r))continue;const i=e[r];if(q(i))t[r]=bc(r,i,s);else if(i!=null){const o=Js(i);t[r]=()=>o}}},ro=(e,t)=>{const n=Js(t);e.slots.default=()=>n},io=(e,t,n)=>{for(const s in t)(n||s!=="_")&&(e[s]=t[s])},wc=(e,t,n)=>{const s=e.slots=Qi();if(e.vnode.shapeFlag&32){const r=t._;r?(io(s,t,n),n&&li(s,"_",r,!0)):so(t,s)}else t&&ro(e,t)},vc=(e,t,n)=>{const{vnode:s,slots:r}=e;let i=!0,o=Z;if(s.shapeFlag&32){const l=t._;l?n&&l===1?i=!1:io(r,t,n):(i=!t.$stable,so(t,r)),o=t}else t&&(ro(e,t),o={default:1});if(i)for(const l in r)!no(l)&&o[l]==null&&delete r[l]},we=po;function Sc(e){return oo(e)}function xc(e){return oo(e,Gl)}function oo(e,t){const n=Hn();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:o,createText:l,createComment:c,setText:f,setElementText:a,parentNode:h,nextSibling:y,setScopeId:_=ke,insertStaticContent:S}=e,b=(u,d,m,T=null,v=null,E=null,P=void 0,M=null,A=!!d.dynamicChildren)=>{if(u===d)return;u&&!ut(u,d)&&(T=ln(u),De(u,v,E,!0),u=null),d.patchFlag===-2&&(A=!1,d.dynamicChildren=null);const{type:C,ref:k,shapeFlag:L}=d;switch(C){case gt:K(u,d,m,T);break;case _e:N(u,d,m,T);break;case kt:u==null&&j(d,m,T,P);break;case xe:x(u,d,m,T,v,E,P,M,A);break;default:L&1?O(u,d,m,T,v,E,P,M,A):L&6?B(u,d,m,T,v,E,P,M,A):(L&64||L&128)&&C.process(u,d,m,T,v,E,P,M,A,_t)}k!=null&&v&&Xt(k,u&&u.ref,E,d||u,!d)},K=(u,d,m,T)=>{if(u==null)s(d.el=l(d.children),m,T);else{const v=d.el=u.el;d.children!==u.children&&f(v,d.children)}},N=(u,d,m,T)=>{u==null?s(d.el=c(d.children||""),m,T):d.el=u.el},j=(u,d,m,T)=>{[u.el,u.anchor]=S(u.children,d,m,T,u.el,u.anchor)},p=({el:u,anchor:d},m,T)=>{let v;for(;u&&u!==d;)v=y(u),s(u,m,T),u=v;s(d,m,T)},g=({el:u,anchor:d})=>{let m;for(;u&&u!==d;)m=y(u),r(u),u=m;r(d)},O=(u,d,m,T,v,E,P,M,A)=>{d.type==="svg"?P="svg":d.type==="math"&&(P="mathml"),u==null?F(d,m,T,v,E,P,M,A):R(u,d,v,E,P,M,A)},F=(u,d,m,T,v,E,P,M)=>{let A,C;const{props:k,shapeFlag:L,transition:H,dirs:G}=u;if(A=u.el=o(u.type,E,k&&k.is,k),L&8?a(A,u.children):L&16&&V(u.children,A,null,T,v,rs(u,E),P,M),G&&Ue(u,null,T,"created"),$(A,u,u.scopeId,P,T),k){for(const ee in k)ee!=="value"&&!Ct(ee)&&i(A,ee,null,k[ee],E,T);"value"in k&&i(A,"value",null,k.value,E),(C=k.onVnodeBeforeMount)&&Oe(C,T,u)}G&&Ue(u,null,T,"beforeMount");const X=lo(v,H);X&&H.beforeEnter(A),s(A,d,m),((C=k&&k.onVnodeMounted)||X||G)&&we(()=>{C&&Oe(C,T,u),X&&H.enter(A),G&&Ue(u,null,T,"mounted")},v)},$=(u,d,m,T,v)=>{if(m&&_(u,m),T)for(let E=0;E{for(let C=A;C{const M=d.el=u.el;let{patchFlag:A,dynamicChildren:C,dirs:k}=d;A|=u.patchFlag&16;const L=u.props||Z,H=d.props||Z;let G;if(m&<(m,!1),(G=H.onVnodeBeforeUpdate)&&Oe(G,m,d,u),k&&Ue(d,u,m,"beforeUpdate"),m&<(m,!0),(L.innerHTML&&H.innerHTML==null||L.textContent&&H.textContent==null)&&a(M,""),C?w(u.dynamicChildren,C,M,m,T,rs(d,v),E):P||D(u,d,M,null,m,T,rs(d,v),E,!1),A>0){if(A&16)I(M,L,H,m,v);else if(A&2&&L.class!==H.class&&i(M,"class",null,H.class,v),A&4&&i(M,"style",L.style,H.style,v),A&8){const X=d.dynamicProps;for(let ee=0;ee{G&&Oe(G,m,d,u),k&&Ue(d,u,m,"updated")},T)},w=(u,d,m,T,v,E,P)=>{for(let M=0;M{if(d!==m){if(d!==Z)for(const E in d)!Ct(E)&&!(E in m)&&i(u,E,d[E],null,v,T);for(const E in m){if(Ct(E))continue;const P=m[E],M=d[E];P!==M&&E!=="value"&&i(u,E,M,P,v,T)}"value"in m&&i(u,"value",d.value,m.value,v)}},x=(u,d,m,T,v,E,P,M,A)=>{const C=d.el=u?u.el:l(""),k=d.anchor=u?u.anchor:l("");let{patchFlag:L,dynamicChildren:H,slotScopeIds:G}=d;G&&(M=M?M.concat(G):G),u==null?(s(C,m,T),s(k,m,T),V(d.children||[],m,k,v,E,P,M,A)):L>0&&L&64&&H&&u.dynamicChildren?(w(u.dynamicChildren,H,m,v,E,P,M),(d.key!=null||v&&d===v.subTree)&&zs(u,d,!0)):D(u,d,m,k,v,E,P,M,A)},B=(u,d,m,T,v,E,P,M,A)=>{d.slotScopeIds=M,u==null?d.shapeFlag&512?v.ctx.activate(d,m,T,P,A):se(d,m,T,v,E,P,A):le(u,d,A)},se=(u,d,m,T,v,E,P)=>{const M=u.component=jc(u,T,v);if(sn(u)&&(M.ctx.renderer=_t),Vc(M,!1,P),M.asyncDep){if(v&&v.registerDep(M,U,P),!u.el){const A=M.subTree=ce(_e);N(null,A,d,m)}}else U(M,u,d,m,v,E,P)},le=(u,d,m)=>{const T=d.component=u.component;if(Lc(u,d,m))if(T.asyncDep&&!T.asyncResolved){Y(T,d,m);return}else T.next=d,T.update();else d.el=u.el,T.vnode=d},U=(u,d,m,T,v,E,P)=>{const M=()=>{if(u.isMounted){let{next:L,bu:H,u:G,parent:X,vnode:ee}=u;{const Te=co(u);if(Te){L&&(L.el=ee.el,Y(u,L,P)),Te.asyncDep.then(()=>{u.isUnmounted||M()});return}}let Q=L,Ee;lt(u,!1),L?(L.el=ee.el,Y(u,L,P)):L=ee,H&&wn(H),(Ee=L.props&&L.props.onVnodeBeforeUpdate)&&Oe(Ee,X,L,ee),lt(u,!0);const pe=is(u),Ie=u.subTree;u.subTree=pe,b(Ie,pe,h(Ie.el),ln(Ie),u,v,E),L.el=pe.el,Q===null&&uo(u,pe.el),G&&we(G,v),(Ee=L.props&&L.props.onVnodeUpdated)&&we(()=>Oe(Ee,X,L,ee),v)}else{let L;const{el:H,props:G}=d,{bm:X,m:ee,parent:Q,root:Ee,type:pe}=u,Ie=pt(d);if(lt(u,!1),X&&wn(X),!Ie&&(L=G&&G.onVnodeBeforeMount)&&Oe(L,Q,d),lt(u,!0),H&&Jn){const Te=()=>{u.subTree=is(u),Jn(H,u.subTree,u,v,null)};Ie&&pe.__asyncHydrate?pe.__asyncHydrate(H,u,Te):Te()}else{Ee.ce&&Ee.ce._injectChildStyle(pe);const Te=u.subTree=is(u);b(null,Te,m,T,u,v,E),d.el=Te.el}if(ee&&we(ee,v),!Ie&&(L=G&&G.onVnodeMounted)){const Te=d;we(()=>Oe(L,Q,Te),v)}(d.shapeFlag&256||Q&&pt(Q.vnode)&&Q.vnode.shapeFlag&256)&&u.a&&we(u.a,v),u.isMounted=!0,d=m=T=null}};u.scope.on();const A=u.effect=new di(M);u.scope.off();const C=u.update=A.run.bind(A),k=u.job=A.runIfDirty.bind(A);k.i=u,k.id=u.uid,A.scheduler=()=>Gs(k),lt(u,!0),C()},Y=(u,d,m)=>{d.component=u;const T=u.vnode.props;u.vnode=d,u.next=null,yc(u,d.props,T,m),vc(u,d.children,m),rt(),ur(u),it()},D=(u,d,m,T,v,E,P,M,A=!1)=>{const C=u&&u.children,k=u?u.shapeFlag:0,L=d.children,{patchFlag:H,shapeFlag:G}=d;if(H>0){if(H&128){on(C,L,m,T,v,E,P,M,A);return}else if(H&256){he(C,L,m,T,v,E,P,M,A);return}}G&8?(k&16&&It(C,v,E),L!==C&&a(m,L)):k&16?G&16?on(C,L,m,T,v,E,P,M,A):It(C,v,E,!0):(k&8&&a(m,""),G&16&&V(L,m,T,v,E,P,M,A))},he=(u,d,m,T,v,E,P,M,A)=>{u=u||Et,d=d||Et;const C=u.length,k=d.length,L=Math.min(C,k);let H;for(H=0;Hk?It(u,v,E,!0,!1,L):V(d,m,T,v,E,P,M,A,L)},on=(u,d,m,T,v,E,P,M,A)=>{let C=0;const k=d.length;let L=u.length-1,H=k-1;for(;C<=L&&C<=H;){const G=u[C],X=d[C]=A?et(d[C]):Me(d[C]);if(ut(G,X))b(G,X,m,null,v,E,P,M,A);else break;C++}for(;C<=L&&C<=H;){const G=u[L],X=d[H]=A?et(d[H]):Me(d[H]);if(ut(G,X))b(G,X,m,null,v,E,P,M,A);else break;L--,H--}if(C>L){if(C<=H){const G=H+1,X=GH)for(;C<=L;)De(u[C],v,E,!0),C++;else{const G=C,X=C,ee=new Map;for(C=X;C<=H;C++){const Ce=d[C]=A?et(d[C]):Me(d[C]);Ce.key!=null&&ee.set(Ce.key,C)}let Q,Ee=0;const pe=H-X+1;let Ie=!1,Te=0;const Nt=new Array(pe);for(C=0;C=pe){De(Ce,v,E,!0);continue}let je;if(Ce.key!=null)je=ee.get(Ce.key);else for(Q=X;Q<=H;Q++)if(Nt[Q-X]===0&&ut(Ce,d[Q])){je=Q;break}je===void 0?De(Ce,v,E,!0):(Nt[je-X]=C+1,je>=Te?Te=je:Ie=!0,b(Ce,d[je],m,null,v,E,P,M,A),Ee++)}const or=Ie?Ec(Nt):Et;for(Q=or.length-1,C=pe-1;C>=0;C--){const Ce=X+C,je=d[Ce],lr=Ce+1{const{el:E,type:P,transition:M,children:A,shapeFlag:C}=u;if(C&6){ot(u.component.subTree,d,m,T);return}if(C&128){u.suspense.move(d,m,T);return}if(C&64){P.move(u,d,m,_t);return}if(P===xe){s(E,d,m);for(let L=0;LM.enter(E),v);else{const{leave:L,delayLeave:H,afterLeave:G}=M,X=()=>s(E,d,m),ee=()=>{L(E,()=>{X(),G&&G()})};H?H(E,X,ee):ee()}else s(E,d,m)},De=(u,d,m,T=!1,v=!1)=>{const{type:E,props:P,ref:M,children:A,dynamicChildren:C,shapeFlag:k,patchFlag:L,dirs:H,cacheIndex:G}=u;if(L===-2&&(v=!1),M!=null&&Xt(M,null,m,u,!0),G!=null&&(d.renderCache[G]=void 0),k&256){d.ctx.deactivate(u);return}const X=k&1&&H,ee=!pt(u);let Q;if(ee&&(Q=P&&P.onVnodeBeforeUnmount)&&Oe(Q,d,u),k&6)Bo(u.component,m,T);else{if(k&128){u.suspense.unmount(m,T);return}X&&Ue(u,null,d,"beforeUnmount"),k&64?u.type.remove(u,d,m,_t,T):C&&!C.hasOnce&&(E!==xe||L>0&&L&64)?It(C,d,m,!1,!0):(E===xe&&L&384||!v&&k&16)&&It(A,d,m),T&&rr(u)}(ee&&(Q=P&&P.onVnodeUnmounted)||X)&&we(()=>{Q&&Oe(Q,d,u),X&&Ue(u,null,d,"unmounted")},m)},rr=u=>{const{type:d,el:m,anchor:T,transition:v}=u;if(d===xe){ko(m,T);return}if(d===kt){g(u);return}const E=()=>{r(m),v&&!v.persisted&&v.afterLeave&&v.afterLeave()};if(u.shapeFlag&1&&v&&!v.persisted){const{leave:P,delayLeave:M}=v,A=()=>P(m,E);M?M(u.el,E,A):A()}else E()},ko=(u,d)=>{let m;for(;u!==d;)m=y(u),r(u),u=m;r(d)},Bo=(u,d,m)=>{const{bum:T,scope:v,job:E,subTree:P,um:M,m:A,a:C}=u;Er(A),Er(C),T&&wn(T),v.stop(),E&&(E.flags|=8,De(P,u,d,m)),M&&we(M,d),we(()=>{u.isUnmounted=!0},d),d&&d.pendingBranch&&!d.isUnmounted&&u.asyncDep&&!u.asyncResolved&&u.suspenseId===d.pendingId&&(d.deps--,d.deps===0&&d.resolve())},It=(u,d,m,T=!1,v=!1,E=0)=>{for(let P=E;P{if(u.shapeFlag&6)return ln(u.component.subTree);if(u.shapeFlag&128)return u.suspense.next();const d=y(u.anchor||u.el),m=d&&d[Ii];return m?y(m):d};let Yn=!1;const ir=(u,d,m)=>{u==null?d._vnode&&De(d._vnode,null,null,!0):b(d._vnode||null,u,d,null,null,null,m),d._vnode=u,Yn||(Yn=!0,ur(),On(),Yn=!1)},_t={p:b,um:De,m:ot,r:rr,mt:se,mc:V,pc:D,pbc:w,n:ln,o:e};let Xn,Jn;return t&&([Xn,Jn]=t(_t)),{render:ir,hydrate:Xn,createApp:pc(ir,Xn)}}function rs({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function lt({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function lo(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function zs(e,t,n=!1){const s=e.children,r=t.children;if(W(s)&&W(r))for(let i=0;i>1,e[n[l]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,o=n[i-1];i-- >0;)n[i]=o,o=t[o];return n}function co(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:co(t)}function Er(e){if(e)for(let t=0;tOt(Tc);function Qs(e,t){return Wn(e,null,t)}function Af(e,t){return Wn(e,null,{flush:"post"})}function Fe(e,t,n){return Wn(e,t,n)}function Wn(e,t,n=Z){const{immediate:s,deep:r,flush:i,once:o}=n,l=de({},n),c=t&&s||!t&&i!=="post";let f;if(Mt){if(i==="sync"){const _=Cc();f=_.__watcherHandles||(_.__watcherHandles=[])}else if(!c){const _=()=>{};return _.stop=ke,_.resume=ke,_.pause=ke,_}}const a=fe;l.call=(_,S,b)=>He(_,a,S,b);let h=!1;i==="post"?l.scheduler=_=>{we(_,a&&a.suspense)}:i!=="sync"&&(h=!0,l.scheduler=(_,S)=>{S?_():Gs(_)}),l.augmentJob=_=>{t&&(_.flags|=4),h&&(_.flags|=2,a&&(_.id=a.uid,_.i=a))};const y=Hl(e,t,l);return Mt&&(f?f.push(y):c&&y()),y}function Ac(e,t,n){const s=this.proxy,r=re(e)?e.includes(".")?ao(s,e):()=>s[e]:e.bind(s,s);let i;q(t)?i=t:(i=t.handler,n=t);const o=rn(this),l=Wn(r,i.bind(s),n);return o(),l}function ao(e,t){const n=t.split(".");return()=>{let s=e;for(let r=0;rt==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Le(t)}Modifiers`]||e[`${st(t)}Modifiers`];function Oc(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||Z;let r=n;const i=t.startsWith("update:"),o=i&&Rc(s,t.slice(7));o&&(o.trim&&(r=n.map(a=>re(a)?a.trim():a)),o.number&&(r=n.map(_s)));let l,c=s[l=bn(t)]||s[l=bn(Le(t))];!c&&i&&(c=s[l=bn(st(t))]),c&&He(c,e,6,r);const f=s[l+"Once"];if(f){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,He(f,e,6,r)}}function fo(e,t,n=!1){const s=t.emitsCache,r=s.get(e);if(r!==void 0)return r;const i=e.emits;let o={},l=!1;if(!q(e)){const c=f=>{const a=fo(f,t,!0);a&&(l=!0,de(o,a))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!i&&!l?(ne(e)&&s.set(e,null),null):(W(i)?i.forEach(c=>o[c]=null):de(o,i),ne(e)&&s.set(e,o),o)}function Kn(e,t){return!e||!en(t)?!1:(t=t.slice(2).replace(/Once$/,""),z(e,t[0].toLowerCase()+t.slice(1))||z(e,st(t))||z(e,t))}function is(e){const{type:t,vnode:n,proxy:s,withProxy:r,propsOptions:[i],slots:o,attrs:l,emit:c,render:f,renderCache:a,props:h,data:y,setupState:_,ctx:S,inheritAttrs:b}=e,K=Mn(e);let N,j;try{if(n.shapeFlag&4){const g=r||s,O=g;N=Me(f.call(O,g,a,h,_,y,S)),j=l}else{const g=t;N=Me(g.length>1?g(h,{attrs:l,slots:o,emit:c}):g(h,null)),j=t.props?l:Mc(l)}}catch(g){Bt.length=0,nn(g,e,1),N=ce(_e)}let p=N;if(j&&b!==!1){const g=Object.keys(j),{shapeFlag:O}=p;g.length&&O&7&&(i&&g.some(Fs)&&(j=Pc(j,i)),p=nt(p,j,!1,!0))}return n.dirs&&(p=nt(p,null,!1,!0),p.dirs=p.dirs?p.dirs.concat(n.dirs):n.dirs),n.transition&&Yt(p,n.transition),N=p,Mn(K),N}const Mc=e=>{let t;for(const n in e)(n==="class"||n==="style"||en(n))&&((t||(t={}))[n]=e[n]);return t},Pc=(e,t)=>{const n={};for(const s in e)(!Fs(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function Lc(e,t,n){const{props:s,children:r,component:i}=e,{props:o,children:l,patchFlag:c}=t,f=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return s?Tr(s,o,f):!!o;if(c&8){const a=t.dynamicProps;for(let h=0;he.__isSuspense;function po(e,t){t&&t.pendingBranch?W(e)?t.effects.push(...e):t.effects.push(e):jl(e)}const xe=Symbol.for("v-fgt"),gt=Symbol.for("v-txt"),_e=Symbol.for("v-cmt"),kt=Symbol.for("v-stc"),Bt=[];let Ae=null;function Os(e=!1){Bt.push(Ae=e?null:[])}function Ic(){Bt.pop(),Ae=Bt[Bt.length-1]||null}let Jt=1;function Cr(e,t=!1){Jt+=e,e<0&&Ae&&t&&(Ae.hasOnce=!0)}function go(e){return e.dynamicChildren=Jt>0?Ae||Et:null,Ic(),Jt>0&&Ae&&Ae.push(e),e}function Rf(e,t,n,s,r,i){return go(yo(e,t,n,s,r,i,!0))}function Ms(e,t,n,s,r){return go(ce(e,t,n,s,r,!0))}function zt(e){return e?e.__v_isVNode===!0:!1}function ut(e,t){return e.type===t.type&&e.key===t.key}const mo=({key:e})=>e??null,xn=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?re(e)||ae(e)||q(e)?{i:ue,r:e,k:t,f:!!n}:e:null);function yo(e,t=null,n=null,s=0,r=null,i=e===xe?0:1,o=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&mo(t),ref:t&&xn(t),scopeId:Li,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:ue};return l?(Zs(c,n),i&128&&e.normalize(c)):n&&(c.shapeFlag|=re(n)?8:16),Jt>0&&!o&&Ae&&(c.patchFlag>0||i&6)&&c.patchFlag!==32&&Ae.push(c),c}const ce=Nc;function Nc(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===Ki)&&(e=_e),zt(e)){const l=nt(e,t,!0);return n&&Zs(l,n),Jt>0&&!i&&Ae&&(l.shapeFlag&6?Ae[Ae.indexOf(e)]=l:Ae.push(l)),l.patchFlag=-2,l}if(Wc(e)&&(e=e.__vccOpts),t){t=Fc(t);let{class:l,style:c}=t;l&&!re(l)&&(t.class=js(l)),ne(c)&&(Ks(c)&&!W(c)&&(c=de({},c)),t.style=Ds(c))}const o=re(e)?1:ho(e)?128:Ni(e)?64:ne(e)?4:q(e)?2:0;return yo(e,t,n,s,r,o,i,!0)}function Fc(e){return e?Ks(e)||Zi(e)?de({},e):e:null}function nt(e,t,n=!1,s=!1){const{props:r,ref:i,patchFlag:o,children:l,transition:c}=e,f=t?Hc(r||{},t):r,a={__v_isVNode:!0,__v_skip:!0,type:e.type,props:f,key:f&&mo(f),ref:t&&t.ref?n&&i?W(i)?i.concat(xn(t)):[i,xn(t)]:xn(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==xe?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&nt(e.ssContent),ssFallback:e.ssFallback&&nt(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&s&&Yt(a,c.clone(a)),a}function _o(e=" ",t=0){return ce(gt,null,e,t)}function Of(e,t){const n=ce(kt,null,e);return n.staticCount=t,n}function Mf(e="",t=!1){return t?(Os(),Ms(_e,null,e)):ce(_e,null,e)}function Me(e){return e==null||typeof e=="boolean"?ce(_e):W(e)?ce(xe,null,e.slice()):zt(e)?et(e):ce(gt,null,String(e))}function et(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:nt(e)}function Zs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(W(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),Zs(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!Zi(t)?t._ctx=ue:r===3&&ue&&(ue.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else q(t)?(t={default:t,_ctx:ue},n=32):(t=String(t),s&64?(n=16,t=[_o(t)]):n=8);e.children=t,e.shapeFlag|=n}function Hc(...e){const t={};for(let n=0;nfe||ue;let Ln,Ps;{const e=Hn(),t=(n,s)=>{let r;return(r=e[n])||(r=e[n]=[]),r.push(s),i=>{r.length>1?r.forEach(o=>o(i)):r[0](i)}};Ln=t("__VUE_INSTANCE_SETTERS__",n=>fe=n),Ps=t("__VUE_SSR_SETTERS__",n=>Mt=n)}const rn=e=>{const t=fe;return Ln(e),e.scope.on(),()=>{e.scope.off(),Ln(t)}},Ar=()=>{fe&&fe.scope.off(),Ln(null)};function bo(e){return e.vnode.shapeFlag&4}let Mt=!1;function Vc(e,t=!1,n=!1){t&&Ps(t);const{props:s,children:r}=e.vnode,i=bo(e);mc(e,s,i,t),wc(e,r,n);const o=i?Uc(e,t):void 0;return t&&Ps(!1),o}function Uc(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,oc);const{setup:s}=n;if(s){rt();const r=e.setupContext=s.length>1?vo(e):null,i=rn(e),o=tn(s,e,0,[e.props,r]),l=ri(o);if(it(),i(),(l||e.sp)&&!pt(e)&&Xs(e),l){if(o.then(Ar,Ar),t)return o.then(c=>{Rr(e,c)}).catch(c=>{nn(c,e,0)});e.asyncDep=o}else Rr(e,o)}else wo(e)}function Rr(e,t,n){q(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ne(t)&&(e.setupState=Ri(t)),wo(e)}function wo(e,t,n){const s=e.type;e.render||(e.render=s.render||ke);{const r=rn(e);rt();try{cc(e)}finally{it(),r()}}}const kc={get(e,t){return me(e,"get",""),e[t]}};function vo(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,kc),slots:e.slots,emit:e.emit,expose:t}}function Gn(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Ri(vn(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Ut)return Ut[n](e)},has(t,n){return n in t||n in Ut}})):e.proxy}function Bc(e,t=!0){return q(e)?e.displayName||e.name:e.name||t&&e.__name}function Wc(e){return q(e)&&"__vccOpts"in e}const ie=(e,t)=>Nl(e,t,Mt);function Ls(e,t,n){const s=arguments.length;return s===2?ne(t)&&!W(t)?zt(t)?ce(e,null,[t]):ce(e,t):ce(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&zt(n)&&(n=[n]),ce(e,t,n))}const Kc="3.5.13";/** +* @vue/runtime-dom v3.5.13 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Is;const Or=typeof window<"u"&&window.trustedTypes;if(Or)try{Is=Or.createPolicy("vue",{createHTML:e=>e})}catch{}const So=Is?e=>Is.createHTML(e):e=>e,qc="http://www.w3.org/2000/svg",Gc="http://www.w3.org/1998/Math/MathML",qe=typeof document<"u"?document:null,Mr=qe&&qe.createElement("template"),Yc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t==="svg"?qe.createElementNS(qc,e):t==="mathml"?qe.createElementNS(Gc,e):n?qe.createElement(e,{is:n}):qe.createElement(e);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>qe.createTextNode(e),createComment:e=>qe.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>qe.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,i){const o=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{Mr.innerHTML=So(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const l=Mr.content;if(s==="svg"||s==="mathml"){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},ze="transition",Ht="animation",Qt=Symbol("_vtc"),xo={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},Xc=de({},$i,xo),Jc=e=>(e.displayName="Transition",e.props=Xc,e),Pf=Jc((e,{slots:t})=>Ls(Wl,zc(e),t)),ct=(e,t=[])=>{W(e)?e.forEach(n=>n(...t)):e&&e(...t)},Pr=e=>e?W(e)?e.some(t=>t.length>1):e.length>1:!1;function zc(e){const t={};for(const x in e)x in xo||(t[x]=e[x]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:i=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=i,appearActiveClass:f=o,appearToClass:a=l,leaveFromClass:h=`${n}-leave-from`,leaveActiveClass:y=`${n}-leave-active`,leaveToClass:_=`${n}-leave-to`}=e,S=Qc(r),b=S&&S[0],K=S&&S[1],{onBeforeEnter:N,onEnter:j,onEnterCancelled:p,onLeave:g,onLeaveCancelled:O,onBeforeAppear:F=N,onAppear:$=j,onAppearCancelled:V=p}=t,R=(x,B,se,le)=>{x._enterCancelled=le,at(x,B?a:l),at(x,B?f:o),se&&se()},w=(x,B)=>{x._isLeaving=!1,at(x,h),at(x,_),at(x,y),B&&B()},I=x=>(B,se)=>{const le=x?$:j,U=()=>R(B,x,se);ct(le,[B,U]),Lr(()=>{at(B,x?c:i),Ke(B,x?a:l),Pr(le)||Ir(B,s,b,U)})};return de(t,{onBeforeEnter(x){ct(N,[x]),Ke(x,i),Ke(x,o)},onBeforeAppear(x){ct(F,[x]),Ke(x,c),Ke(x,f)},onEnter:I(!1),onAppear:I(!0),onLeave(x,B){x._isLeaving=!0;const se=()=>w(x,B);Ke(x,h),x._enterCancelled?(Ke(x,y),Hr()):(Hr(),Ke(x,y)),Lr(()=>{x._isLeaving&&(at(x,h),Ke(x,_),Pr(g)||Ir(x,s,K,se))}),ct(g,[x,se])},onEnterCancelled(x){R(x,!1,void 0,!0),ct(p,[x])},onAppearCancelled(x){R(x,!0,void 0,!0),ct(V,[x])},onLeaveCancelled(x){w(x),ct(O,[x])}})}function Qc(e){if(e==null)return null;if(ne(e))return[os(e.enter),os(e.leave)];{const t=os(e);return[t,t]}}function os(e){return Xo(e)}function Ke(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Qt]||(e[Qt]=new Set)).add(t)}function at(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[Qt];n&&(n.delete(t),n.size||(e[Qt]=void 0))}function Lr(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Zc=0;function Ir(e,t,n,s){const r=e._endId=++Zc,i=()=>{r===e._endId&&s()};if(n!=null)return setTimeout(i,n);const{type:o,timeout:l,propCount:c}=ea(e,t);if(!o)return s();const f=o+"end";let a=0;const h=()=>{e.removeEventListener(f,y),i()},y=_=>{_.target===e&&++a>=c&&h()};setTimeout(()=>{a(n[S]||"").split(", "),r=s(`${ze}Delay`),i=s(`${ze}Duration`),o=Nr(r,i),l=s(`${Ht}Delay`),c=s(`${Ht}Duration`),f=Nr(l,c);let a=null,h=0,y=0;t===ze?o>0&&(a=ze,h=o,y=i.length):t===Ht?f>0&&(a=Ht,h=f,y=c.length):(h=Math.max(o,f),a=h>0?o>f?ze:Ht:null,y=a?a===ze?i.length:c.length:0);const _=a===ze&&/\b(transform|all)(,|$)/.test(s(`${ze}Property`).toString());return{type:a,timeout:h,propCount:y,hasTransform:_}}function Nr(e,t){for(;e.lengthFr(n)+Fr(e[s])))}function Fr(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Hr(){return document.body.offsetHeight}function ta(e,t,n){const s=e[Qt];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const $r=Symbol("_vod"),na=Symbol("_vsh"),sa=Symbol(""),ra=/(^|;)\s*display\s*:/;function ia(e,t,n){const s=e.style,r=re(n);let i=!1;if(n&&!r){if(t)if(re(t))for(const o of t.split(";")){const l=o.slice(0,o.indexOf(":")).trim();n[l]==null&&En(s,l,"")}else for(const o in t)n[o]==null&&En(s,o,"");for(const o in n)o==="display"&&(i=!0),En(s,o,n[o])}else if(r){if(t!==n){const o=s[sa];o&&(n+=";"+o),s.cssText=n,i=ra.test(n)}}else t&&e.removeAttribute("style");$r in e&&(e[$r]=i?s.display:"",e[na]&&(s.display="none"))}const Dr=/\s*!important$/;function En(e,t,n){if(W(n))n.forEach(s=>En(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=oa(e,t);Dr.test(n)?e.setProperty(st(s),n.replace(Dr,""),"important"):e[s]=n}}const jr=["Webkit","Moz","ms"],ls={};function oa(e,t){const n=ls[t];if(n)return n;let s=Le(t);if(s!=="filter"&&s in e)return ls[t]=s;s=Fn(s);for(let r=0;rcs||(fa.then(()=>cs=0),cs=Date.now());function da(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;He(ha(s,n.value),t,5,[s])};return n.value=e,n.attached=ua(),n}function ha(e,t){if(W(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const Kr=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,pa=(e,t,n,s,r,i)=>{const o=r==="svg";t==="class"?ta(e,s,o):t==="style"?ia(e,n,s):en(t)?Fs(t)||ca(e,t,n,s,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):ga(e,t,s,o))?(kr(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Ur(e,t,s,o,i,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!re(s))?kr(e,Le(t),s,i,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Ur(e,t,s,o))};function ga(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Kr(t)&&q(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return Kr(t)&&re(n)?!1:t in e}const qr=e=>{const t=e.props["onUpdate:modelValue"]||!1;return W(t)?n=>wn(t,n):t};function ma(e){e.target.composing=!0}function Gr(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const as=Symbol("_assign"),Lf={created(e,{modifiers:{lazy:t,trim:n,number:s}},r){e[as]=qr(r);const i=s||r.props&&r.props.type==="number";St(e,t?"change":"input",o=>{if(o.target.composing)return;let l=e.value;n&&(l=l.trim()),i&&(l=_s(l)),e[as](l)}),n&&St(e,"change",()=>{e.value=e.value.trim()}),t||(St(e,"compositionstart",ma),St(e,"compositionend",Gr),St(e,"change",Gr))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:s,trim:r,number:i}},o){if(e[as]=qr(o),e.composing)return;const l=(i||e.type==="number")&&!/^0\d/.test(e.value)?_s(e.value):e.value,c=t??"";l!==c&&(document.activeElement===e&&e.type!=="range"&&(s&&t===n||r&&e.value.trim()===c)||(e.value=c))}},ya=["ctrl","shift","alt","meta"],_a={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>ya.some(n=>e[`${n}Key`]&&!t.includes(n))},If=(e,t)=>{const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=(r,...i)=>{for(let o=0;o{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=r=>{if(!("key"in r))return;const i=st(r.key);if(t.some(o=>o===i||ba[o]===i))return e(r)})},Eo=de({patchProp:pa},Yc);let Wt,Yr=!1;function wa(){return Wt||(Wt=Sc(Eo))}function va(){return Wt=Yr?Wt:xc(Eo),Yr=!0,Wt}const Ff=(...e)=>{const t=wa().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=Co(s);if(!r)return;const i=t._component;!q(i)&&!i.render&&!i.template&&(i.template=r.innerHTML),r.nodeType===1&&(r.textContent="");const o=n(r,!1,To(r));return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),o},t},Hf=(...e)=>{const t=va().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=Co(s);if(r)return n(r,!0,To(r))},t};function To(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Co(e){return re(e)?document.querySelector(e):e}const $f=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},Sa=window.__VP_SITE_DATA__;function er(e){return ui()?(rl(e),!0):!1}function Be(e){return typeof e=="function"?e():Ai(e)}const Ao=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Df=e=>e!=null,xa=Object.prototype.toString,Ea=e=>xa.call(e)==="[object Object]",Zt=()=>{},Xr=Ta();function Ta(){var e,t;return Ao&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&(/iP(?:ad|hone|od)/.test(window.navigator.userAgent)||((t=window==null?void 0:window.navigator)==null?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test(window==null?void 0:window.navigator.userAgent))}function Ca(e,t){function n(...s){return new Promise((r,i)=>{Promise.resolve(e(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(r).catch(i)})}return n}const Ro=e=>e();function Aa(e,t={}){let n,s,r=Zt;const i=l=>{clearTimeout(l),r(),r=Zt};return l=>{const c=Be(e),f=Be(t.maxWait);return n&&i(n),c<=0||f!==void 0&&f<=0?(s&&(i(s),s=null),Promise.resolve(l())):new Promise((a,h)=>{r=t.rejectOnCancel?h:a,f&&!s&&(s=setTimeout(()=>{n&&i(n),s=null,a(l())},f)),n=setTimeout(()=>{s&&i(s),s=null,a(l())},c)})}}function Ra(e=Ro){const t=oe(!0);function n(){t.value=!1}function s(){t.value=!0}const r=(...i)=>{t.value&&e(...i)};return{isActive:Vn(t),pause:n,resume:s,eventFilter:r}}function Oa(e){return qn()}function Oo(...e){if(e.length!==1)return Pl(...e);const t=e[0];return typeof t=="function"?Vn(Rl(()=>({get:t,set:Zt}))):oe(t)}function Mo(e,t,n={}){const{eventFilter:s=Ro,...r}=n;return Fe(e,Ca(s,t),r)}function Ma(e,t,n={}){const{eventFilter:s,...r}=n,{eventFilter:i,pause:o,resume:l,isActive:c}=Ra(s);return{stop:Mo(e,t,{...r,eventFilter:i}),pause:o,resume:l,isActive:c}}function tr(e,t=!0,n){Oa()?Lt(e,n):t?e():Un(e)}function jf(e,t,n={}){const{debounce:s=0,maxWait:r=void 0,...i}=n;return Mo(e,t,{...i,eventFilter:Aa(s,{maxWait:r})})}function Vf(e,t,n){let s;ae(n)?s={evaluating:n}:s={};const{lazy:r=!1,evaluating:i=void 0,shallow:o=!0,onError:l=Zt}=s,c=oe(!r),f=o?qs(t):oe(t);let a=0;return Qs(async h=>{if(!c.value)return;a++;const y=a;let _=!1;i&&Promise.resolve().then(()=>{i.value=!0});try{const S=await e(b=>{h(()=>{i&&(i.value=!1),_||b()})});y===a&&(f.value=S)}catch(S){l(S)}finally{i&&y===a&&(i.value=!1),_=!0}}),r?ie(()=>(c.value=!0,f.value)):f}const $e=Ao?window:void 0;function Po(e){var t;const n=Be(e);return(t=n==null?void 0:n.$el)!=null?t:n}function Pt(...e){let t,n,s,r;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,s,r]=e,t=$e):[t,n,s,r]=e,!t)return Zt;Array.isArray(n)||(n=[n]),Array.isArray(s)||(s=[s]);const i=[],o=()=>{i.forEach(a=>a()),i.length=0},l=(a,h,y,_)=>(a.addEventListener(h,y,_),()=>a.removeEventListener(h,y,_)),c=Fe(()=>[Po(t),Be(r)],([a,h])=>{if(o(),!a)return;const y=Ea(h)?{...h}:h;i.push(...n.flatMap(_=>s.map(S=>l(a,_,S,y))))},{immediate:!0,flush:"post"}),f=()=>{c(),o()};return er(f),f}function Pa(e){return typeof e=="function"?e:typeof e=="string"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function Uf(...e){let t,n,s={};e.length===3?(t=e[0],n=e[1],s=e[2]):e.length===2?typeof e[1]=="object"?(t=!0,n=e[0],s=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:r=$e,eventName:i="keydown",passive:o=!1,dedupe:l=!1}=s,c=Pa(t);return Pt(r,i,a=>{a.repeat&&Be(l)||c(a)&&n(a)},o)}function La(){const e=oe(!1),t=qn();return t&&Lt(()=>{e.value=!0},t),e}function Ia(e){const t=La();return ie(()=>(t.value,!!e()))}function Lo(e,t={}){const{window:n=$e}=t,s=Ia(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let r;const i=oe(!1),o=f=>{i.value=f.matches},l=()=>{r&&("removeEventListener"in r?r.removeEventListener("change",o):r.removeListener(o))},c=Qs(()=>{s.value&&(l(),r=n.matchMedia(Be(e)),"addEventListener"in r?r.addEventListener("change",o):r.addListener(o),i.value=r.matches)});return er(()=>{c(),l(),r=void 0}),i}const gn=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},mn="__vueuse_ssr_handlers__",Na=Fa();function Fa(){return mn in gn||(gn[mn]=gn[mn]||{}),gn[mn]}function Io(e,t){return Na[e]||t}function nr(e){return Lo("(prefers-color-scheme: dark)",e)}function Ha(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const $a={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Jr="vueuse-storage";function sr(e,t,n,s={}){var r;const{flush:i="pre",deep:o=!0,listenToStorageChanges:l=!0,writeDefaults:c=!0,mergeDefaults:f=!1,shallow:a,window:h=$e,eventFilter:y,onError:_=w=>{console.error(w)},initOnMounted:S}=s,b=(a?qs:oe)(typeof t=="function"?t():t);if(!n)try{n=Io("getDefaultStorage",()=>{var w;return(w=$e)==null?void 0:w.localStorage})()}catch(w){_(w)}if(!n)return b;const K=Be(t),N=Ha(K),j=(r=s.serializer)!=null?r:$a[N],{pause:p,resume:g}=Ma(b,()=>F(b.value),{flush:i,deep:o,eventFilter:y});h&&l&&tr(()=>{n instanceof Storage?Pt(h,"storage",V):Pt(h,Jr,R),S&&V()}),S||V();function O(w,I){if(h){const x={key:e,oldValue:w,newValue:I,storageArea:n};h.dispatchEvent(n instanceof Storage?new StorageEvent("storage",x):new CustomEvent(Jr,{detail:x}))}}function F(w){try{const I=n.getItem(e);if(w==null)O(I,null),n.removeItem(e);else{const x=j.write(w);I!==x&&(n.setItem(e,x),O(I,x))}}catch(I){_(I)}}function $(w){const I=w?w.newValue:n.getItem(e);if(I==null)return c&&K!=null&&n.setItem(e,j.write(K)),K;if(!w&&f){const x=j.read(I);return typeof f=="function"?f(x,K):N==="object"&&!Array.isArray(x)?{...K,...x}:x}else return typeof I!="string"?I:j.read(I)}function V(w){if(!(w&&w.storageArea!==n)){if(w&&w.key==null){b.value=K;return}if(!(w&&w.key!==e)){p();try{(w==null?void 0:w.newValue)!==j.write(b.value)&&(b.value=$(w))}catch(I){_(I)}finally{w?Un(g):g()}}}}function R(w){V(w.detail)}return b}const Da="*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}";function ja(e={}){const{selector:t="html",attribute:n="class",initialValue:s="auto",window:r=$e,storage:i,storageKey:o="vueuse-color-scheme",listenToStorageChanges:l=!0,storageRef:c,emitAuto:f,disableTransition:a=!0}=e,h={auto:"",light:"light",dark:"dark",...e.modes||{}},y=nr({window:r}),_=ie(()=>y.value?"dark":"light"),S=c||(o==null?Oo(s):sr(o,s,i,{window:r,listenToStorageChanges:l})),b=ie(()=>S.value==="auto"?_.value:S.value),K=Io("updateHTMLAttrs",(g,O,F)=>{const $=typeof g=="string"?r==null?void 0:r.document.querySelector(g):Po(g);if(!$)return;const V=new Set,R=new Set;let w=null;if(O==="class"){const x=F.split(/\s/g);Object.values(h).flatMap(B=>(B||"").split(/\s/g)).filter(Boolean).forEach(B=>{x.includes(B)?V.add(B):R.add(B)})}else w={key:O,value:F};if(V.size===0&&R.size===0&&w===null)return;let I;a&&(I=r.document.createElement("style"),I.appendChild(document.createTextNode(Da)),r.document.head.appendChild(I));for(const x of V)$.classList.add(x);for(const x of R)$.classList.remove(x);w&&$.setAttribute(w.key,w.value),a&&(r.getComputedStyle(I).opacity,document.head.removeChild(I))});function N(g){var O;K(t,n,(O=h[g])!=null?O:g)}function j(g){e.onChanged?e.onChanged(g,N):N(g)}Fe(b,j,{flush:"post",immediate:!0}),tr(()=>j(b.value));const p=ie({get(){return f?S.value:b.value},set(g){S.value=g}});try{return Object.assign(p,{store:S,system:_,state:b})}catch{return p}}function Va(e={}){const{valueDark:t="dark",valueLight:n="",window:s=$e}=e,r=ja({...e,onChanged:(l,c)=>{var f;e.onChanged?(f=e.onChanged)==null||f.call(e,l==="dark",c,l):c(l)},modes:{dark:t,light:n}}),i=ie(()=>r.system?r.system.value:nr({window:s}).value?"dark":"light");return ie({get(){return r.value==="dark"},set(l){const c=l?"dark":"light";i.value===c?r.value="auto":r.value=c}})}function fs(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function kf(e,t,n={}){const{window:s=$e}=n;return sr(e,t,s==null?void 0:s.localStorage,n)}function No(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const us=new WeakMap;function Bf(e,t=!1){const n=oe(t);let s=null,r="";Fe(Oo(e),l=>{const c=fs(Be(l));if(c){const f=c;if(us.get(f)||us.set(f,f.style.overflow),f.style.overflow!=="hidden"&&(r=f.style.overflow),f.style.overflow==="hidden")return n.value=!0;if(n.value)return f.style.overflow="hidden"}},{immediate:!0});const i=()=>{const l=fs(Be(e));!l||n.value||(Xr&&(s=Pt(l,"touchmove",c=>{Ua(c)},{passive:!1})),l.style.overflow="hidden",n.value=!0)},o=()=>{const l=fs(Be(e));!l||!n.value||(Xr&&(s==null||s()),l.style.overflow=r,us.delete(l),n.value=!1)};return er(o),ie({get(){return n.value},set(l){l?i():o()}})}function Wf(e,t,n={}){const{window:s=$e}=n;return sr(e,t,s==null?void 0:s.sessionStorage,n)}function Kf(e={}){const{window:t=$e,behavior:n="auto"}=e;if(!t)return{x:oe(0),y:oe(0)};const s=oe(t.scrollX),r=oe(t.scrollY),i=ie({get(){return s.value},set(l){scrollTo({left:l,behavior:n})}}),o=ie({get(){return r.value},set(l){scrollTo({top:l,behavior:n})}});return Pt(t,"scroll",()=>{s.value=t.scrollX,r.value=t.scrollY},{capture:!1,passive:!0}),{x:i,y:o}}function qf(e={}){const{window:t=$e,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:s=Number.POSITIVE_INFINITY,listenOrientation:r=!0,includeScrollbar:i=!0,type:o="inner"}=e,l=oe(n),c=oe(s),f=()=>{t&&(o==="outer"?(l.value=t.outerWidth,c.value=t.outerHeight):i?(l.value=t.innerWidth,c.value=t.innerHeight):(l.value=t.document.documentElement.clientWidth,c.value=t.document.documentElement.clientHeight))};if(f(),tr(f),Pt("resize",f,{passive:!0}),r){const a=Lo("(orientation: portrait)");Fe(a,()=>f())}return{width:l,height:c}}const ds={BASE_URL:"/nuxt-i18n-micro/",DEV:!1,MODE:"production",PROD:!0,SSR:!1};var hs={};const Fo=/^(?:[a-z]+:|\/\/)/i,ka="vitepress-theme-appearance",Ba=/#.*$/,Wa=/[?#].*$/,Ka=/(?:(^|\/)index)?\.(?:md|html)$/,ge=typeof document<"u",Ho={relativePath:"404.md",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function qa(e,t,n=!1){if(t===void 0)return!1;if(e=zr(`/${e}`),n)return new RegExp(t).test(e);if(zr(t)!==e)return!1;const s=t.match(Ba);return s?(ge?location.hash:"")===s[0]:!0}function zr(e){return decodeURI(e).replace(Wa,"").replace(Ka,"$1")}function Ga(e){return Fo.test(e)}function Ya(e,t){return Object.keys((e==null?void 0:e.locales)||{}).find(n=>n!=="root"&&!Ga(n)&&qa(t,`/${n}/`,!0))||"root"}function Xa(e,t){var s,r,i,o,l,c,f;const n=Ya(e,t);return Object.assign({},e,{localeIndex:n,lang:((s=e.locales[n])==null?void 0:s.lang)??e.lang,dir:((r=e.locales[n])==null?void 0:r.dir)??e.dir,title:((i=e.locales[n])==null?void 0:i.title)??e.title,titleTemplate:((o=e.locales[n])==null?void 0:o.titleTemplate)??e.titleTemplate,description:((l=e.locales[n])==null?void 0:l.description)??e.description,head:Do(e.head,((c=e.locales[n])==null?void 0:c.head)??[]),themeConfig:{...e.themeConfig,...(f=e.locales[n])==null?void 0:f.themeConfig}})}function $o(e,t){const n=t.title||e.title,s=t.titleTemplate??e.titleTemplate;if(typeof s=="string"&&s.includes(":title"))return s.replace(/:title/g,n);const r=Ja(e.title,s);return n===r.slice(3)?n:`${n}${r}`}function Ja(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function za(e,t){const[n,s]=t;if(n!=="meta")return!1;const r=Object.entries(s)[0];return r==null?!1:e.some(([i,o])=>i===n&&o[r[0]]===r[1])}function Do(e,t){return[...e.filter(n=>!za(t,n)),...t]}const Qa=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,Za=/^[a-z]:/i;function Qr(e){const t=Za.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(Qa,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const ps=new Set;function ef(e){if(ps.size===0){const n=typeof process=="object"&&(hs==null?void 0:hs.VITE_EXTRA_EXTENSIONS)||(ds==null?void 0:ds.VITE_EXTRA_EXTENSIONS)||"";("3g2,3gp,aac,ai,apng,au,avif,bin,bmp,cer,class,conf,crl,css,csv,dll,doc,eps,epub,exe,gif,gz,ics,ief,jar,jpe,jpeg,jpg,js,json,jsonld,m4a,man,mid,midi,mjs,mov,mp2,mp3,mp4,mpe,mpeg,mpg,mpp,oga,ogg,ogv,ogx,opus,otf,p10,p7c,p7m,p7s,pdf,png,ps,qt,roff,rtf,rtx,ser,svg,t,tif,tiff,tr,ts,tsv,ttf,txt,vtt,wav,weba,webm,webp,woff,woff2,xhtml,xml,yaml,yml,zip"+(n&&typeof n=="string"?","+n:"")).split(",").forEach(s=>ps.add(s))}const t=e.split(".").pop();return t==null||!ps.has(t.toLowerCase())}function Gf(e){return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}const tf=Symbol(),mt=qs(Sa);function Yf(e){const t=ie(()=>Xa(mt.value,e.data.relativePath)),n=t.value.appearance,s=n==="force-dark"?oe(!0):n==="force-auto"?nr():n?Va({storageKey:ka,initialValue:()=>n==="dark"?"dark":"auto",...typeof n=="object"?n:{}}):oe(!1),r=oe(ge?location.hash:"");return ge&&window.addEventListener("hashchange",()=>{r.value=location.hash}),Fe(()=>e.data,()=>{r.value=ge?location.hash:""}),{site:t,theme:ie(()=>t.value.themeConfig),page:ie(()=>e.data),frontmatter:ie(()=>e.data.frontmatter),params:ie(()=>e.data.params),lang:ie(()=>t.value.lang),dir:ie(()=>e.data.frontmatter.dir||t.value.dir),localeIndex:ie(()=>t.value.localeIndex||"root"),title:ie(()=>$o(t.value,e.data)),description:ie(()=>e.data.description||t.value.description),isDark:s,hash:ie(()=>r.value)}}function nf(){const e=Ot(tf);if(!e)throw new Error("vitepress data not properly injected in app");return e}function sf(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function Zr(e){return Fo.test(e)||!e.startsWith("/")?e:sf(mt.value.base,e)}function rf(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),ge){const n="/nuxt-i18n-micro/";t=Qr(t.slice(n.length).replace(/\//g,"_")||"index")+".md";let s=__VP_HASH_MAP__[t.toLowerCase()];if(s||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",s=__VP_HASH_MAP__[t.toLowerCase()]),!s)return null;t=`${n}assets/${t}.${s}.js`}else t=`./${Qr(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let Tn=[];function Xf(e){Tn.push(e),Bn(()=>{Tn=Tn.filter(t=>t!==e)})}function of(){let e=mt.value.scrollOffset,t=0,n=24;if(typeof e=="object"&&"padding"in e&&(n=e.padding,e=e.selector),typeof e=="number")t=e;else if(typeof e=="string")t=ei(e,n);else if(Array.isArray(e))for(const s of e){const r=ei(s,n);if(r){t=r;break}}return t}function ei(e,t){const n=document.querySelector(e);if(!n)return 0;const s=n.getBoundingClientRect().bottom;return s<0?0:s+t}const lf=Symbol(),jo="http://a.com",cf=()=>({path:"/",component:null,data:Ho});function Jf(e,t){const n=jn(cf()),s={route:n,go:r};async function r(l=ge?location.href:"/"){var c,f;l=gs(l),await((c=s.onBeforeRouteChange)==null?void 0:c.call(s,l))!==!1&&(ge&&l!==gs(location.href)&&(history.replaceState({scrollPosition:window.scrollY},""),history.pushState({},"",l)),await o(l),await((f=s.onAfterRouteChanged)==null?void 0:f.call(s,l)))}let i=null;async function o(l,c=0,f=!1){var y,_;if(await((y=s.onBeforePageLoad)==null?void 0:y.call(s,l))===!1)return;const a=new URL(l,jo),h=i=a.pathname;try{let S=await e(h);if(!S)throw new Error(`Page not found: ${h}`);if(i===h){i=null;const{default:b,__pageData:K}=S;if(!b)throw new Error(`Invalid route component: ${b}`);await((_=s.onAfterPageLoad)==null?void 0:_.call(s,l)),n.path=ge?h:Zr(h),n.component=vn(b),n.data=vn(K),ge&&Un(()=>{let N=mt.value.base+K.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!mt.value.cleanUrls&&!N.endsWith("/")&&(N+=".html"),N!==a.pathname&&(a.pathname=N,l=N+a.search+a.hash,history.replaceState({},"",l)),a.hash&&!c){let j=null;try{j=document.getElementById(decodeURIComponent(a.hash).slice(1))}catch(p){console.warn(p)}if(j){ti(j,a.hash);return}}window.scrollTo(0,c)})}}catch(S){if(!/fetch|Page not found/.test(S.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(S),!f)try{const b=await fetch(mt.value.base+"hashmap.json");window.__VP_HASH_MAP__=await b.json(),await o(l,c,!0);return}catch{}if(i===h){i=null,n.path=ge?h:Zr(h),n.component=t?vn(t):null;const b=ge?h.replace(/(^|\/)$/,"$1index").replace(/(\.html)?$/,".md").replace(/^\//,""):"404.md";n.data={...Ho,relativePath:b}}}}return ge&&(history.state===null&&history.replaceState({},""),window.addEventListener("click",l=>{if(l.defaultPrevented||!(l.target instanceof Element)||l.target.closest("button")||l.button!==0||l.ctrlKey||l.shiftKey||l.altKey||l.metaKey)return;const c=l.target.closest("a");if(!c||c.closest(".vp-raw")||c.hasAttribute("download")||c.hasAttribute("target"))return;const f=c.getAttribute("href")??(c instanceof SVGAElement?c.getAttribute("xlink:href"):null);if(f==null)return;const{href:a,origin:h,pathname:y,hash:_,search:S}=new URL(f,c.baseURI),b=new URL(location.href);h===b.origin&&ef(y)&&(l.preventDefault(),y===b.pathname&&S===b.search?(_!==b.hash&&(history.pushState({},"",a),window.dispatchEvent(new HashChangeEvent("hashchange",{oldURL:b.href,newURL:a}))),_?ti(c,_,c.classList.contains("header-anchor")):window.scrollTo(0,0)):r(a))},{capture:!0}),window.addEventListener("popstate",async l=>{var c;l.state!==null&&(await o(gs(location.href),l.state&&l.state.scrollPosition||0),(c=s.onAfterRouteChanged)==null||c.call(s,location.href))}),window.addEventListener("hashchange",l=>{l.preventDefault()})),s}function af(){const e=Ot(lf);if(!e)throw new Error("useRouter() is called without provider.");return e}function Vo(){return af().route}function ti(e,t,n=!1){let s=null;try{s=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t).slice(1))}catch(r){console.warn(r)}if(s){let r=function(){!n||Math.abs(o-window.scrollY)>window.innerHeight?window.scrollTo(0,o):window.scrollTo({left:0,top:o,behavior:"smooth"})};const i=parseInt(window.getComputedStyle(s).paddingTop,10),o=window.scrollY+s.getBoundingClientRect().top-of()+i;requestAnimationFrame(r)}}function gs(e){const t=new URL(e,jo);return t.pathname=t.pathname.replace(/(^|\/)index(\.html)?$/,"$1"),mt.value.cleanUrls?t.pathname=t.pathname.replace(/\.html$/,""):!t.pathname.endsWith("/")&&!t.pathname.endsWith(".html")&&(t.pathname+=".html"),t.pathname+t.search+t.hash}const yn=()=>Tn.forEach(e=>e()),zf=Ys({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=Vo(),{frontmatter:n,site:s}=nf();return Fe(n,yn,{deep:!0,flush:"post"}),()=>Ls(e.as,s.value.contentProps??{style:{position:"relative"}},[t.component?Ls(t.component,{onVnodeMounted:yn,onVnodeUpdated:yn,onVnodeUnmounted:yn}):"404 Page Not Found"])}}),ff="modulepreload",uf=function(e){return"/nuxt-i18n-micro/"+e},ni={},Qf=function(t,n,s){let r=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const o=document.querySelector("meta[property=csp-nonce]"),l=(o==null?void 0:o.nonce)||(o==null?void 0:o.getAttribute("nonce"));r=Promise.allSettled(n.map(c=>{if(c=uf(c),c in ni)return;ni[c]=!0;const f=c.endsWith(".css"),a=f?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${a}`))return;const h=document.createElement("link");if(h.rel=f?"stylesheet":ff,f||(h.as="script"),h.crossOrigin="",h.href=c,l&&h.setAttribute("nonce",l),document.head.appendChild(h),f)return new Promise((y,_)=>{h.addEventListener("load",y),h.addEventListener("error",()=>_(new Error(`Unable to preload CSS for ${c}`)))})}))}function i(o){const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=o,window.dispatchEvent(l),!l.defaultPrevented)throw o}return r.then(o=>{for(const l of o||[])l.status==="rejected"&&i(l.reason);return t().catch(i)})},Zf=Ys({setup(e,{slots:t}){const n=oe(!1);return Lt(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function eu(){ge&&window.addEventListener("click",e=>{var n;const t=e.target;if(t.matches(".vp-code-group input")){const s=(n=t.parentElement)==null?void 0:n.parentElement;if(!s)return;const r=Array.from(s.querySelectorAll("input")).indexOf(t);if(r<0)return;const i=s.querySelector(".blocks");if(!i)return;const o=Array.from(i.children).find(f=>f.classList.contains("active"));if(!o)return;const l=i.children[r];if(!l||o===l)return;o.classList.remove("active"),l.classList.add("active");const c=s==null?void 0:s.querySelector(`label[for="${t.id}"]`);c==null||c.scrollIntoView({block:"nearest"})}})}function tu(){if(ge){const e=new WeakMap;window.addEventListener("click",t=>{var s;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const r=n.parentElement,i=(s=n.nextElementSibling)==null?void 0:s.nextElementSibling;if(!r||!i)return;const o=/language-(shellscript|shell|bash|sh|zsh)/.test(r.className),l=[".vp-copy-ignore",".diff.remove"],c=i.cloneNode(!0);c.querySelectorAll(l.join(",")).forEach(a=>a.remove());let f=c.textContent||"";o&&(f=f.replace(/^ *(\$|>) /gm,"").trim()),df(f).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const a=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,a)})}})}}async function df(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const s=document.getSelection(),r=s?s.rangeCount>0&&s.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),r&&(s.removeAllRanges(),s.addRange(r)),n&&n.focus()}}function nu(e,t){let n=!0,s=[];const r=i=>{if(n){n=!1,i.forEach(l=>{const c=ms(l);for(const f of document.head.children)if(f.isEqualNode(c)){s.push(f);return}});return}const o=i.map(ms);s.forEach((l,c)=>{const f=o.findIndex(a=>a==null?void 0:a.isEqualNode(l??null));f!==-1?delete o[f]:(l==null||l.remove(),delete s[c])}),o.forEach(l=>l&&document.head.appendChild(l)),s=[...s,...o].filter(Boolean)};Qs(()=>{const i=e.data,o=t.value,l=i&&i.description,c=i&&i.frontmatter.head||[],f=$o(o,i);f!==document.title&&(document.title=f);const a=l||o.description;let h=document.querySelector("meta[name=description]");h?h.getAttribute("content")!==a&&h.setAttribute("content",a):ms(["meta",{name:"description",content:a}]),r(Do(o.head,pf(c)))})}function ms([e,t,n]){const s=document.createElement(e);for(const r in t)s.setAttribute(r,t[r]);return n&&(s.innerHTML=n),e==="script"&&t.async==null&&(s.async=!1),s}function hf(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function pf(e){return e.filter(t=>!hf(t))}const ys=new Set,Uo=()=>document.createElement("link"),gf=e=>{const t=Uo();t.rel="prefetch",t.href=e,document.head.appendChild(t)},mf=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let _n;const yf=ge&&(_n=Uo())&&_n.relList&&_n.relList.supports&&_n.relList.supports("prefetch")?gf:mf;function su(){if(!ge||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const s=()=>{n&&n.disconnect(),n=new IntersectionObserver(i=>{i.forEach(o=>{if(o.isIntersecting){const l=o.target;n.unobserve(l);const{pathname:c}=l;if(!ys.has(c)){ys.add(c);const f=rf(c);f&&yf(f)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(i=>{const{hostname:o,pathname:l}=new URL(i.href instanceof SVGAnimatedString?i.href.animVal:i.href,i.baseURI),c=l.match(/\.\w+$/);c&&c[0]!==".html"||i.target!=="_blank"&&o===location.hostname&&(l!==location.pathname?n.observe(i):ys.add(l))})})};Lt(s);const r=Vo();Fe(()=>r.path,s),Bn(()=>{n&&n.disconnect()})}export{Bi as $,of as A,vf as B,xf as C,qs as D,Xf as E,xe as F,ce as G,Sf as H,Fo as I,Vo as J,Hc as K,Ot as L,qf as M,Ds as N,Uf as O,Un as P,Kf as Q,ge as R,Vn as S,Pf as T,wf as U,Qf as V,Bf as W,gc as X,Nf as Y,Tf as Z,$f as _,_o as a,If as a0,Cf as a1,Of as a2,nu as a3,lf as a4,Yf as a5,tf as a6,zf as a7,Zf as a8,mt as a9,Hf as aa,Jf as ab,rf as ac,su as ad,tu as ae,eu as af,Ls as ag,Be as ah,Po as ai,Df as aj,er as ak,Vf as al,Wf as am,kf as an,jf as ao,af as ap,Pt as aq,_f as ar,Lf as as,ae as at,bf as au,vn as av,Ff as aw,Gf as ax,Ms as b,Rf as c,Ys as d,Mf as e,ef as f,Zr as g,ie as h,Ga as i,yo as j,Ai as k,qa as l,Lo as m,js as n,Os as o,oe as p,Fe as q,Ef as r,Qs as s,nl as t,nf as u,Lt as v,Vl as w,Bn as x,Af as y,tc as z}; diff --git a/assets/chunks/text-to-i18n.CC9iMeyu.js b/assets/chunks/text-to-i18n.CC9iMeyu.js new file mode 100644 index 00000000..ad53e6b0 --- /dev/null +++ b/assets/chunks/text-to-i18n.CC9iMeyu.js @@ -0,0 +1 @@ +const t="/nuxt-i18n-micro/text-to-i18n.gif";export{t as _}; diff --git a/assets/chunks/theme.CPkZdxnZ.js b/assets/chunks/theme.CPkZdxnZ.js new file mode 100644 index 00000000..e2bbb0b9 --- /dev/null +++ b/assets/chunks/theme.CPkZdxnZ.js @@ -0,0 +1,2 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/chunks/VPLocalSearchBox.DD0Puzcb.js","assets/chunks/framework.Gfs4HC1t.js"])))=>i.map(i=>d[i]); +import{d as m,o as a,c,r as u,n as M,a as z,t as I,b as k,w as p,e as h,T as ce,_ as g,u as He,i as Be,f as Ee,g as de,h as y,j as d,k as r,l as K,m as ae,p as T,q as D,s as Y,v as j,x as fe,y as pe,z as Fe,A as De,B as W,F as w,C as H,D as $e,E as Q,G as _,H as E,I as ye,J as Z,K as U,L as x,M as Oe,N as Pe,O as re,P as Le,Q as Ve,R as ee,S as Ge,U as Ue,V as je,W as Se,X as Te,Y as ze,Z as Ke,$ as We,a0 as qe,a1 as Re}from"./framework.Gfs4HC1t.js";const Je=m({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(o){return(e,t)=>(a(),c("span",{class:M(["VPBadge",e.type])},[u(e.$slots,"default",{},()=>[z(I(e.text),1)])],2))}}),Xe={key:0,class:"VPBackdrop"},Ye=m({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(o){return(e,t)=>(a(),k(ce,{name:"fade"},{default:p(()=>[e.show?(a(),c("div",Xe)):h("",!0)]),_:1}))}}),Qe=g(Ye,[["__scopeId","data-v-7c66b226"]]),L=He;function Ze(o,e){let t,s=!1;return()=>{t&&clearTimeout(t),s?t=setTimeout(o,e):(o(),(s=!0)&&setTimeout(()=>s=!1,e))}}function ie(o){return/^\//.test(o)?o:`/${o}`}function ve(o){const{pathname:e,search:t,hash:s,protocol:n}=new URL(o,"http://a.com");if(Be(o)||o.startsWith("#")||!n.startsWith("http")||!Ee(e))return o;const{site:i}=L(),l=e.endsWith("/")||e.endsWith(".html")?o:o.replace(/(?:(^\.+)\/)?.*$/,`$1${e.replace(/(\.md)?$/,i.value.cleanUrls?"":".html")}${t}${s}`);return de(l)}function R({correspondingLink:o=!1}={}){const{site:e,localeIndex:t,page:s,theme:n,hash:i}=L(),l=y(()=>{var f,$;return{label:(f=e.value.locales[t.value])==null?void 0:f.label,link:(($=e.value.locales[t.value])==null?void 0:$.link)||(t.value==="root"?"/":`/${t.value}/`)}});return{localeLinks:y(()=>Object.entries(e.value.locales).flatMap(([f,$])=>l.value.label===$.label?[]:{text:$.label,link:xe($.link||(f==="root"?"/":`/${f}/`),n.value.i18nRouting!==!1&&o,s.value.relativePath.slice(l.value.link.length-1),!e.value.cleanUrls)+i.value})),currentLang:l}}function xe(o,e,t,s){return e?o.replace(/\/$/,"")+ie(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,s?".html":"")):o}const et={class:"NotFound"},tt={class:"code"},nt={class:"title"},st={class:"quote"},ot={class:"action"},at=["href","aria-label"],rt=m({__name:"NotFound",setup(o){const{theme:e}=L(),{currentLang:t}=R();return(s,n)=>{var i,l,v,f,$;return a(),c("div",et,[d("p",tt,I(((i=r(e).notFound)==null?void 0:i.code)??"404"),1),d("h1",nt,I(((l=r(e).notFound)==null?void 0:l.title)??"PAGE NOT FOUND"),1),n[0]||(n[0]=d("div",{class:"divider"},null,-1)),d("blockquote",st,I(((v=r(e).notFound)==null?void 0:v.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),d("div",ot,[d("a",{class:"link",href:r(de)(r(t).link),"aria-label":((f=r(e).notFound)==null?void 0:f.linkLabel)??"go to home"},I((($=r(e).notFound)==null?void 0:$.linkText)??"Take me home"),9,at)])])}}}),it=g(rt,[["__scopeId","data-v-c2fb1638"]]);function Ne(o,e){if(Array.isArray(o))return J(o);if(o==null)return[];e=ie(e);const t=Object.keys(o).sort((n,i)=>i.split("/").length-n.split("/").length).find(n=>e.startsWith(ie(n))),s=t?o[t]:[];return Array.isArray(s)?J(s):J(s.items,s.base)}function lt(o){const e=[];let t=0;for(const s in o){const n=o[s];if(n.items){t=e.push(n);continue}e[t]||e.push({items:[]}),e[t].items.push(n)}return e}function ut(o){const e=[];function t(s){for(const n of s)n.text&&n.link&&e.push({text:n.text,link:n.link,docFooterText:n.docFooterText}),n.items&&t(n.items)}return t(o),e}function le(o,e){return Array.isArray(e)?e.some(t=>le(o,t)):K(o,e.link)?!0:e.items?le(o,e.items):!1}function J(o,e){return[...o].map(t=>{const s={...t},n=s.base||e;return n&&s.link&&(s.link=n+s.link),s.items&&(s.items=J(s.items,n)),s})}function O(){const{frontmatter:o,page:e,theme:t}=L(),s=ae("(min-width: 960px)"),n=T(!1),i=y(()=>{const C=t.value.sidebar,S=e.value.relativePath;return C?Ne(C,S):[]}),l=T(i.value);D(i,(C,S)=>{JSON.stringify(C)!==JSON.stringify(S)&&(l.value=i.value)});const v=y(()=>o.value.sidebar!==!1&&l.value.length>0&&o.value.layout!=="home"),f=y(()=>$?o.value.aside==null?t.value.aside==="left":o.value.aside==="left":!1),$=y(()=>o.value.layout==="home"?!1:o.value.aside!=null?!!o.value.aside:t.value.aside!==!1),V=y(()=>v.value&&s.value),b=y(()=>v.value?lt(l.value):[]);function P(){n.value=!0}function N(){n.value=!1}function A(){n.value?N():P()}return{isOpen:n,sidebar:l,sidebarGroups:b,hasSidebar:v,hasAside:$,leftAside:f,isSidebarEnabled:V,open:P,close:N,toggle:A}}function ct(o,e){let t;Y(()=>{t=o.value?document.activeElement:void 0}),j(()=>{window.addEventListener("keyup",s)}),fe(()=>{window.removeEventListener("keyup",s)});function s(n){n.key==="Escape"&&o.value&&(e(),t==null||t.focus())}}function dt(o){const{page:e,hash:t}=L(),s=T(!1),n=y(()=>o.value.collapsed!=null),i=y(()=>!!o.value.link),l=T(!1),v=()=>{l.value=K(e.value.relativePath,o.value.link)};D([e,o,t],v),j(v);const f=y(()=>l.value?!0:o.value.items?le(e.value.relativePath,o.value.items):!1),$=y(()=>!!(o.value.items&&o.value.items.length));Y(()=>{s.value=!!(n.value&&o.value.collapsed)}),pe(()=>{(l.value||f.value)&&(s.value=!1)});function V(){n.value&&(s.value=!s.value)}return{collapsed:s,collapsible:n,isLink:i,isActiveLink:l,hasActiveLink:f,hasChildren:$,toggle:V}}function ft(){const{hasSidebar:o}=O(),e=ae("(min-width: 960px)"),t=ae("(min-width: 1280px)");return{isAsideEnabled:y(()=>!t.value&&!e.value?!1:o.value?t.value:e.value)}}const ue=[];function Me(o){return typeof o.outline=="object"&&!Array.isArray(o.outline)&&o.outline.label||o.outlineTitle||"On this page"}function he(o){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const s=Number(t.tagName[1]);return{element:t,title:pt(t),link:"#"+t.id,level:s}});return vt(e,o)}function pt(o){let e="";for(const t of o.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor")||t.classList.contains("ignore-header"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function vt(o,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[s,n]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;return _t(o,s,n)}function ht(o,e){const{isAsideEnabled:t}=ft(),s=Ze(i,100);let n=null;j(()=>{requestAnimationFrame(i),window.addEventListener("scroll",s)}),Fe(()=>{l(location.hash)}),fe(()=>{window.removeEventListener("scroll",s)});function i(){if(!t.value)return;const v=window.scrollY,f=window.innerHeight,$=document.body.offsetHeight,V=Math.abs(v+f-$)<1,b=ue.map(({element:N,link:A})=>({link:A,top:mt(N)})).filter(({top:N})=>!Number.isNaN(N)).sort((N,A)=>N.top-A.top);if(!b.length){l(null);return}if(v<1){l(null);return}if(V){l(b[b.length-1].link);return}let P=null;for(const{link:N,top:A}of b){if(A>v+De()+4)break;P=N}l(P)}function l(v){n&&n.classList.remove("active"),v==null?n=null:n=o.value.querySelector(`a[href="${decodeURIComponent(v)}"]`);const f=n;f?(f.classList.add("active"),e.value.style.top=f.offsetTop+39+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function mt(o){let e=0;for(;o!==document.body;){if(o===null)return NaN;e+=o.offsetTop,o=o.offsetParent}return e}function _t(o,e,t){ue.length=0;const s=[],n=[];return o.forEach(i=>{const l={...i,children:[]};let v=n[n.length-1];for(;v&&v.level>=l.level;)n.pop(),v=n[n.length-1];if(l.element.classList.contains("ignore-header")||v&&"shouldIgnore"in v){n.push({level:l.level,shouldIgnore:!0});return}l.level>t||l.level{const n=W("VPDocOutlineItem",!0);return a(),c("ul",{class:M(["VPDocOutlineItem",t.root?"root":"nested"])},[(a(!0),c(w,null,H(t.headers,({children:i,link:l,title:v})=>(a(),c("li",null,[d("a",{class:"outline-link",href:l,onClick:e,title:v},I(v),9,kt),i!=null&&i.length?(a(),k(n,{key:0,headers:i},null,8,["headers"])):h("",!0)]))),256))],2)}}}),Ie=g(bt,[["__scopeId","data-v-94e4ef81"]]),gt={class:"content"},$t={"aria-level":"2",class:"outline-title",id:"doc-outline-aria-label",role:"heading"},yt=m({__name:"VPDocAsideOutline",setup(o){const{frontmatter:e,theme:t}=L(),s=$e([]);Q(()=>{s.value=he(e.value.outline??t.value.outline)});const n=T(),i=T();return ht(n,i),(l,v)=>(a(),c("nav",{"aria-labelledby":"doc-outline-aria-label",class:M(["VPDocAsideOutline",{"has-outline":s.value.length>0}]),ref_key:"container",ref:n},[d("div",gt,[d("div",{class:"outline-marker",ref_key:"marker",ref:i},null,512),d("div",$t,I(r(Me)(r(t))),1),_(Ie,{headers:s.value,root:!0},null,8,["headers"])])],2))}}),Pt=g(yt,[["__scopeId","data-v-8ea6637a"]]),Lt={class:"VPDocAsideCarbonAds"},Vt=m({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(o){const e=()=>null;return(t,s)=>(a(),c("div",Lt,[_(r(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),St={class:"VPDocAside"},Tt=m({__name:"VPDocAside",setup(o){const{theme:e}=L();return(t,s)=>(a(),c("div",St,[u(t.$slots,"aside-top",{},void 0,!0),u(t.$slots,"aside-outline-before",{},void 0,!0),_(Pt),u(t.$slots,"aside-outline-after",{},void 0,!0),s[0]||(s[0]=d("div",{class:"spacer"},null,-1)),u(t.$slots,"aside-ads-before",{},void 0,!0),r(e).carbonAds?(a(),k(Vt,{key:0,"carbon-ads":r(e).carbonAds},null,8,["carbon-ads"])):h("",!0),u(t.$slots,"aside-ads-after",{},void 0,!0),u(t.$slots,"aside-bottom",{},void 0,!0)]))}}),Nt=g(Tt,[["__scopeId","data-v-c6bd40e9"]]);function Mt(){const{theme:o,page:e}=L();return y(()=>{const{text:t="Edit this page",pattern:s=""}=o.value.editLink||{};let n;return typeof s=="function"?n=s(e.value):n=s.replace(/:path/g,e.value.filePath),{url:n,text:t}})}function It(){const{page:o,theme:e,frontmatter:t}=L();return y(()=>{var $,V,b,P,N,A,C,S;const s=Ne(e.value.sidebar,o.value.relativePath),n=ut(s),i=wt(n,B=>B.link.replace(/[?#].*$/,"")),l=i.findIndex(B=>K(o.value.relativePath,B.link)),v=(($=e.value.docFooter)==null?void 0:$.prev)===!1&&!t.value.prev||t.value.prev===!1,f=((V=e.value.docFooter)==null?void 0:V.next)===!1&&!t.value.next||t.value.next===!1;return{prev:v?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((b=i[l-1])==null?void 0:b.docFooterText)??((P=i[l-1])==null?void 0:P.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((N=i[l-1])==null?void 0:N.link)},next:f?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((A=i[l+1])==null?void 0:A.docFooterText)??((C=i[l+1])==null?void 0:C.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((S=i[l+1])==null?void 0:S.link)}}})}function wt(o,e){const t=new Set;return o.filter(s=>{const n=e(s);return t.has(n)?!1:t.add(n)})}const F=m({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(o){const e=o,t=y(()=>e.tag??(e.href?"a":"span")),s=y(()=>e.href&&ye.test(e.href)||e.target==="_blank");return(n,i)=>(a(),k(E(t.value),{class:M(["VPLink",{link:n.href,"vp-external-link-icon":s.value,"no-icon":n.noIcon}]),href:n.href?r(ve)(n.href):void 0,target:n.target??(s.value?"_blank":void 0),rel:n.rel??(s.value?"noreferrer":void 0)},{default:p(()=>[u(n.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),At={class:"VPLastUpdated"},Ct=["datetime"],Ht=m({__name:"VPDocFooterLastUpdated",setup(o){const{theme:e,page:t,lang:s}=L(),n=y(()=>new Date(t.value.lastUpdated)),i=y(()=>n.value.toISOString()),l=T("");return j(()=>{Y(()=>{var v,f,$;l.value=new Intl.DateTimeFormat((f=(v=e.value.lastUpdated)==null?void 0:v.formatOptions)!=null&&f.forceLocale?s.value:void 0,(($=e.value.lastUpdated)==null?void 0:$.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(n.value)})}),(v,f)=>{var $;return a(),c("p",At,[z(I((($=r(e).lastUpdated)==null?void 0:$.text)||r(e).lastUpdatedText||"Last updated")+": ",1),d("time",{datetime:i.value},I(l.value),9,Ct)])}}}),Bt=g(Ht,[["__scopeId","data-v-9c78c02b"]]),Et={key:0,class:"VPDocFooter"},Ft={key:0,class:"edit-info"},Dt={key:0,class:"edit-link"},Ot={key:1,class:"last-updated"},Gt={key:1,class:"prev-next","aria-labelledby":"doc-footer-aria-label"},Ut={class:"pager"},jt=["innerHTML"],zt=["innerHTML"],Kt={class:"pager"},Wt=["innerHTML"],qt=["innerHTML"],Rt=m({__name:"VPDocFooter",setup(o){const{theme:e,page:t,frontmatter:s}=L(),n=Mt(),i=It(),l=y(()=>e.value.editLink&&s.value.editLink!==!1),v=y(()=>t.value.lastUpdated),f=y(()=>l.value||v.value||i.value.prev||i.value.next);return($,V)=>{var b,P,N,A;return f.value?(a(),c("footer",Et,[u($.$slots,"doc-footer-before",{},void 0,!0),l.value||v.value?(a(),c("div",Ft,[l.value?(a(),c("div",Dt,[_(F,{class:"edit-link-button",href:r(n).url,"no-icon":!0},{default:p(()=>[V[0]||(V[0]=d("span",{class:"vpi-square-pen edit-link-icon"},null,-1)),z(" "+I(r(n).text),1)]),_:1},8,["href"])])):h("",!0),v.value?(a(),c("div",Ot,[_(Bt)])):h("",!0)])):h("",!0),(b=r(i).prev)!=null&&b.link||(P=r(i).next)!=null&&P.link?(a(),c("nav",Gt,[V[1]||(V[1]=d("span",{class:"visually-hidden",id:"doc-footer-aria-label"},"Pager",-1)),d("div",Ut,[(N=r(i).prev)!=null&&N.link?(a(),k(F,{key:0,class:"pager-link prev",href:r(i).prev.link},{default:p(()=>{var C;return[d("span",{class:"desc",innerHTML:((C=r(e).docFooter)==null?void 0:C.prev)||"Previous page"},null,8,jt),d("span",{class:"title",innerHTML:r(i).prev.text},null,8,zt)]}),_:1},8,["href"])):h("",!0)]),d("div",Kt,[(A=r(i).next)!=null&&A.link?(a(),k(F,{key:0,class:"pager-link next",href:r(i).next.link},{default:p(()=>{var C;return[d("span",{class:"desc",innerHTML:((C=r(e).docFooter)==null?void 0:C.next)||"Next page"},null,8,Wt),d("span",{class:"title",innerHTML:r(i).next.text},null,8,qt)]}),_:1},8,["href"])):h("",!0)])])):h("",!0)])):h("",!0)}}}),Jt=g(Rt,[["__scopeId","data-v-dd28e2e9"]]),Xt={class:"container"},Yt={class:"aside-container"},Qt={class:"aside-content"},Zt={class:"content"},xt={class:"content-container"},en={class:"main"},tn=m({__name:"VPDoc",setup(o){const{theme:e}=L(),t=Z(),{hasSidebar:s,hasAside:n,leftAside:i}=O(),l=y(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(v,f)=>{const $=W("Content");return a(),c("div",{class:M(["VPDoc",{"has-sidebar":r(s),"has-aside":r(n)}])},[u(v.$slots,"doc-top",{},void 0,!0),d("div",Xt,[r(n)?(a(),c("div",{key:0,class:M(["aside",{"left-aside":r(i)}])},[f[0]||(f[0]=d("div",{class:"aside-curtain"},null,-1)),d("div",Yt,[d("div",Qt,[_(Nt,null,{"aside-top":p(()=>[u(v.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":p(()=>[u(v.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":p(()=>[u(v.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":p(()=>[u(v.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":p(()=>[u(v.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":p(()=>[u(v.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):h("",!0),d("div",Zt,[d("div",xt,[u(v.$slots,"doc-before",{},void 0,!0),d("main",en,[_($,{class:M(["vp-doc",[l.value,r(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),_(Jt,null,{"doc-footer-before":p(()=>[u(v.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),u(v.$slots,"doc-after",{},void 0,!0)])])]),u(v.$slots,"doc-bottom",{},void 0,!0)],2)}}}),nn=g(tn,[["__scopeId","data-v-302c5b4b"]]),sn=m({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{},target:{},rel:{}},setup(o){const e=o,t=y(()=>e.href&&ye.test(e.href)),s=y(()=>e.tag||(e.href?"a":"button"));return(n,i)=>(a(),k(E(s.value),{class:M(["VPButton",[n.size,n.theme]]),href:n.href?r(ve)(n.href):void 0,target:e.target??(t.value?"_blank":void 0),rel:e.rel??(t.value?"noreferrer":void 0)},{default:p(()=>[z(I(n.text),1)]),_:1},8,["class","href","target","rel"]))}}),on=g(sn,[["__scopeId","data-v-45b57181"]]),an=["src","alt"],rn=m({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(o){return(e,t)=>{const s=W("VPImage",!0);return e.image?(a(),c(w,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),c("img",U({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:r(de)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,an)):(a(),c(w,{key:1},[_(s,U({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),_(s,U({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):h("",!0)}}}),X=g(rn,[["__scopeId","data-v-17bebc96"]]),ln={class:"container"},un={class:"main"},cn={key:0,class:"name"},dn=["innerHTML"],fn=["innerHTML"],pn=["innerHTML"],vn={key:0,class:"actions"},hn={key:0,class:"image"},mn={class:"image-container"},_n=m({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(o){const e=x("hero-image-slot-exists");return(t,s)=>(a(),c("div",{class:M(["VPHero",{"has-image":t.image||r(e)}])},[d("div",ln,[d("div",un,[u(t.$slots,"home-hero-info-before",{},void 0,!0),u(t.$slots,"home-hero-info",{},()=>[t.name?(a(),c("h1",cn,[d("span",{innerHTML:t.name,class:"clip"},null,8,dn)])):h("",!0),t.text?(a(),c("p",{key:1,innerHTML:t.text,class:"text"},null,8,fn)):h("",!0),t.tagline?(a(),c("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,pn)):h("",!0)],!0),u(t.$slots,"home-hero-info-after",{},void 0,!0),t.actions?(a(),c("div",vn,[(a(!0),c(w,null,H(t.actions,n=>(a(),c("div",{key:n.link,class:"action"},[_(on,{tag:"a",size:"medium",theme:n.theme,text:n.text,href:n.link,target:n.target,rel:n.rel},null,8,["theme","text","href","target","rel"])]))),128))])):h("",!0),u(t.$slots,"home-hero-actions-after",{},void 0,!0)]),t.image||r(e)?(a(),c("div",hn,[d("div",mn,[s[0]||(s[0]=d("div",{class:"image-bg"},null,-1)),u(t.$slots,"home-hero-image",{},()=>[t.image?(a(),k(X,{key:0,class:"image-src",image:t.image},null,8,["image"])):h("",!0)],!0)])])):h("",!0)])],2))}}),kn=g(_n,[["__scopeId","data-v-9261d9b9"]]),bn=m({__name:"VPHomeHero",setup(o){const{frontmatter:e}=L();return(t,s)=>r(e).hero?(a(),k(kn,{key:0,class:"VPHomeHero",name:r(e).hero.name,text:r(e).hero.text,tagline:r(e).hero.tagline,image:r(e).hero.image,actions:r(e).hero.actions},{"home-hero-info-before":p(()=>[u(t.$slots,"home-hero-info-before")]),"home-hero-info":p(()=>[u(t.$slots,"home-hero-info")]),"home-hero-info-after":p(()=>[u(t.$slots,"home-hero-info-after")]),"home-hero-actions-after":p(()=>[u(t.$slots,"home-hero-actions-after")]),"home-hero-image":p(()=>[u(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):h("",!0)}}),gn={class:"box"},$n={key:0,class:"icon"},yn=["innerHTML"],Pn=["innerHTML"],Ln=["innerHTML"],Vn={key:4,class:"link-text"},Sn={class:"link-text-value"},Tn=m({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(o){return(e,t)=>(a(),k(F,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:p(()=>[d("article",gn,[typeof e.icon=="object"&&e.icon.wrap?(a(),c("div",$n,[_(X,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(a(),k(X,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(a(),c("div",{key:2,class:"icon",innerHTML:e.icon},null,8,yn)):h("",!0),d("h2",{class:"title",innerHTML:e.title},null,8,Pn),e.details?(a(),c("p",{key:3,class:"details",innerHTML:e.details},null,8,Ln)):h("",!0),e.linkText?(a(),c("div",Vn,[d("p",Sn,[z(I(e.linkText)+" ",1),t[0]||(t[0]=d("span",{class:"vpi-arrow-right link-text-icon"},null,-1))])])):h("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),Nn=g(Tn,[["__scopeId","data-v-b73852cc"]]),Mn={key:0,class:"VPFeatures"},In={class:"container"},wn={class:"items"},An=m({__name:"VPFeatures",props:{features:{}},setup(o){const e=o,t=y(()=>{const s=e.features.length;if(s){if(s===2)return"grid-2";if(s===3)return"grid-3";if(s%3===0)return"grid-6";if(s>3)return"grid-4"}else return});return(s,n)=>s.features?(a(),c("div",Mn,[d("div",In,[d("div",wn,[(a(!0),c(w,null,H(s.features,i=>(a(),c("div",{key:i.title,class:M(["item",[t.value]])},[_(Nn,{icon:i.icon,title:i.title,details:i.details,link:i.link,"link-text":i.linkText,rel:i.rel,target:i.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):h("",!0)}}),Cn=g(An,[["__scopeId","data-v-bdcd42a1"]]),Hn=m({__name:"VPHomeFeatures",setup(o){const{frontmatter:e}=L();return(t,s)=>r(e).features?(a(),k(Cn,{key:0,class:"VPHomeFeatures",features:r(e).features},null,8,["features"])):h("",!0)}}),Bn=m({__name:"VPHomeContent",setup(o){const{width:e}=Oe({initialWidth:0,includeScrollbar:!1});return(t,s)=>(a(),c("div",{class:"vp-doc container",style:Pe(r(e)?{"--vp-offset":`calc(50% - ${r(e)/2}px)`}:{})},[u(t.$slots,"default",{},void 0,!0)],4))}}),En=g(Bn,[["__scopeId","data-v-fef19e55"]]),Fn={class:"VPHome"},Dn=m({__name:"VPHome",setup(o){const{frontmatter:e}=L();return(t,s)=>{const n=W("Content");return a(),c("div",Fn,[u(t.$slots,"home-hero-before",{},void 0,!0),_(bn,null,{"home-hero-info-before":p(()=>[u(t.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":p(()=>[u(t.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":p(()=>[u(t.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":p(()=>[u(t.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":p(()=>[u(t.$slots,"home-hero-image",{},void 0,!0)]),_:3}),u(t.$slots,"home-hero-after",{},void 0,!0),u(t.$slots,"home-features-before",{},void 0,!0),_(Hn),u(t.$slots,"home-features-after",{},void 0,!0),r(e).markdownStyles!==!1?(a(),k(En,{key:0},{default:p(()=>[_(n)]),_:1})):(a(),k(n,{key:1}))])}}}),On=g(Dn,[["__scopeId","data-v-9e24ba69"]]),Gn={},Un={class:"VPPage"};function jn(o,e){const t=W("Content");return a(),c("div",Un,[u(o.$slots,"page-top"),_(t),u(o.$slots,"page-bottom")])}const zn=g(Gn,[["render",jn]]),Kn=m({__name:"VPContent",setup(o){const{page:e,frontmatter:t}=L(),{hasSidebar:s}=O();return(n,i)=>(a(),c("div",{class:M(["VPContent",{"has-sidebar":r(s),"is-home":r(t).layout==="home"}]),id:"VPContent"},[r(e).isNotFound?u(n.$slots,"not-found",{key:0},()=>[_(it)],!0):r(t).layout==="page"?(a(),k(zn,{key:1},{"page-top":p(()=>[u(n.$slots,"page-top",{},void 0,!0)]),"page-bottom":p(()=>[u(n.$slots,"page-bottom",{},void 0,!0)]),_:3})):r(t).layout==="home"?(a(),k(On,{key:2},{"home-hero-before":p(()=>[u(n.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":p(()=>[u(n.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":p(()=>[u(n.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":p(()=>[u(n.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":p(()=>[u(n.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":p(()=>[u(n.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":p(()=>[u(n.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":p(()=>[u(n.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":p(()=>[u(n.$slots,"home-features-after",{},void 0,!0)]),_:3})):r(t).layout&&r(t).layout!=="doc"?(a(),k(E(r(t).layout),{key:3})):(a(),k(nn,{key:4},{"doc-top":p(()=>[u(n.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":p(()=>[u(n.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":p(()=>[u(n.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":p(()=>[u(n.$slots,"doc-before",{},void 0,!0)]),"doc-after":p(()=>[u(n.$slots,"doc-after",{},void 0,!0)]),"aside-top":p(()=>[u(n.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":p(()=>[u(n.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":p(()=>[u(n.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":p(()=>[u(n.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":p(()=>[u(n.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":p(()=>[u(n.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),Wn=g(Kn,[["__scopeId","data-v-2f2922de"]]),qn={class:"container"},Rn=["innerHTML"],Jn=["innerHTML"],Xn=m({__name:"VPFooter",setup(o){const{theme:e,frontmatter:t}=L(),{hasSidebar:s}=O();return(n,i)=>r(e).footer&&r(t).footer!==!1?(a(),c("footer",{key:0,class:M(["VPFooter",{"has-sidebar":r(s)}])},[d("div",qn,[r(e).footer.message?(a(),c("p",{key:0,class:"message",innerHTML:r(e).footer.message},null,8,Rn)):h("",!0),r(e).footer.copyright?(a(),c("p",{key:1,class:"copyright",innerHTML:r(e).footer.copyright},null,8,Jn)):h("",!0)])],2)):h("",!0)}}),Yn=g(Xn,[["__scopeId","data-v-63b8cc5c"]]);function Qn(){const{theme:o,frontmatter:e}=L(),t=$e([]),s=y(()=>t.value.length>0);return Q(()=>{t.value=he(e.value.outline??o.value.outline)}),{headers:t,hasLocalNav:s}}const Zn={class:"menu-text"},xn={class:"header"},es={class:"outline"},ts=m({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(o){const e=o,{theme:t}=L(),s=T(!1),n=T(0),i=T(),l=T();function v(b){var P;(P=i.value)!=null&&P.contains(b.target)||(s.value=!1)}D(s,b=>{if(b){document.addEventListener("click",v);return}document.removeEventListener("click",v)}),re("Escape",()=>{s.value=!1}),Q(()=>{s.value=!1});function f(){s.value=!s.value,n.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function $(b){b.target.classList.contains("outline-link")&&(l.value&&(l.value.style.transition="none"),Le(()=>{s.value=!1}))}function V(){s.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(b,P)=>(a(),c("div",{class:"VPLocalNavOutlineDropdown",style:Pe({"--vp-vh":n.value+"px"}),ref_key:"main",ref:i},[b.headers.length>0?(a(),c("button",{key:0,onClick:f,class:M({open:s.value})},[d("span",Zn,I(r(Me)(r(t))),1),P[0]||(P[0]=d("span",{class:"vpi-chevron-right icon"},null,-1))],2)):(a(),c("button",{key:1,onClick:V},I(r(t).returnToTopLabel||"Return to top"),1)),_(ce,{name:"flyout"},{default:p(()=>[s.value?(a(),c("div",{key:0,ref_key:"items",ref:l,class:"items",onClick:$},[d("div",xn,[d("a",{class:"top-link",href:"#",onClick:V},I(r(t).returnToTopLabel||"Return to top"),1)]),d("div",es,[_(Ie,{headers:b.headers},null,8,["headers"])])],512)):h("",!0)]),_:1})],4))}}),ns=g(ts,[["__scopeId","data-v-49916a3f"]]),ss={class:"container"},os=["aria-expanded"],as={class:"menu-text"},rs=m({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(o){const{theme:e,frontmatter:t}=L(),{hasSidebar:s}=O(),{headers:n}=Qn(),{y:i}=Ve(),l=T(0);j(()=>{l.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),Q(()=>{n.value=he(t.value.outline??e.value.outline)});const v=y(()=>n.value.length===0),f=y(()=>v.value&&!s.value),$=y(()=>({VPLocalNav:!0,"has-sidebar":s.value,empty:v.value,fixed:f.value}));return(V,b)=>r(t).layout!=="home"&&(!f.value||r(i)>=l.value)?(a(),c("div",{key:0,class:M($.value)},[d("div",ss,[r(s)?(a(),c("button",{key:0,class:"menu","aria-expanded":V.open,"aria-controls":"VPSidebarNav",onClick:b[0]||(b[0]=P=>V.$emit("open-menu"))},[b[1]||(b[1]=d("span",{class:"vpi-align-left menu-icon"},null,-1)),d("span",as,I(r(e).sidebarMenuLabel||"Menu"),1)],8,os)):h("",!0),_(ns,{headers:r(n),navHeight:l.value},null,8,["headers","navHeight"])])],2)):h("",!0)}}),is=g(rs,[["__scopeId","data-v-df5e51e8"]]);function ls(){const o=T(!1);function e(){o.value=!0,window.addEventListener("resize",n)}function t(){o.value=!1,window.removeEventListener("resize",n)}function s(){o.value?t():e()}function n(){window.outerWidth>=768&&t()}const i=Z();return D(()=>i.path,t),{isScreenOpen:o,openScreen:e,closeScreen:t,toggleScreen:s}}const us={},cs={class:"VPSwitch",type:"button",role:"switch"},ds={class:"check"},fs={key:0,class:"icon"};function ps(o,e){return a(),c("button",cs,[d("span",ds,[o.$slots.default?(a(),c("span",fs,[u(o.$slots,"default",{},void 0,!0)])):h("",!0)])])}const vs=g(us,[["render",ps],["__scopeId","data-v-f77dad60"]]),hs=m({__name:"VPSwitchAppearance",setup(o){const{isDark:e,theme:t}=L(),s=x("toggle-appearance",()=>{e.value=!e.value}),n=T("");return pe(()=>{n.value=e.value?t.value.lightModeSwitchTitle||"Switch to light theme":t.value.darkModeSwitchTitle||"Switch to dark theme"}),(i,l)=>(a(),k(vs,{title:n.value,class:"VPSwitchAppearance","aria-checked":r(e),onClick:r(s)},{default:p(()=>l[0]||(l[0]=[d("span",{class:"vpi-sun sun"},null,-1),d("span",{class:"vpi-moon moon"},null,-1)])),_:1},8,["title","aria-checked","onClick"]))}}),me=g(hs,[["__scopeId","data-v-fa59b7d6"]]),ms={key:0,class:"VPNavBarAppearance"},_s=m({__name:"VPNavBarAppearance",setup(o){const{site:e}=L();return(t,s)=>r(e).appearance&&r(e).appearance!=="force-dark"&&r(e).appearance!=="force-auto"?(a(),c("div",ms,[_(me)])):h("",!0)}}),ks=g(_s,[["__scopeId","data-v-de868ce3"]]),_e=T();let we=!1,oe=0;function bs(o){const e=T(!1);if(ee){!we&&gs(),oe++;const t=D(_e,s=>{var n,i,l;s===o.el.value||(n=o.el.value)!=null&&n.contains(s)?(e.value=!0,(i=o.onFocus)==null||i.call(o)):(e.value=!1,(l=o.onBlur)==null||l.call(o))});fe(()=>{t(),oe--,oe||$s()})}return Ge(e)}function gs(){document.addEventListener("focusin",Ae),we=!0,_e.value=document.activeElement}function $s(){document.removeEventListener("focusin",Ae)}function Ae(){_e.value=document.activeElement}const ys={class:"VPMenuLink"},Ps=["innerHTML"],Ls=m({__name:"VPMenuLink",props:{item:{}},setup(o){const{page:e}=L();return(t,s)=>(a(),c("div",ys,[_(F,{class:M({active:r(K)(r(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,"no-icon":t.item.noIcon},{default:p(()=>[d("span",{innerHTML:t.item.text},null,8,Ps)]),_:1},8,["class","href","target","rel","no-icon"])]))}}),te=g(Ls,[["__scopeId","data-v-7a03c4cb"]]),Vs={class:"VPMenuGroup"},Ss={key:0,class:"title"},Ts=m({__name:"VPMenuGroup",props:{text:{},items:{}},setup(o){return(e,t)=>(a(),c("div",Vs,[e.text?(a(),c("p",Ss,I(e.text),1)):h("",!0),(a(!0),c(w,null,H(e.items,s=>(a(),c(w,null,["link"in s?(a(),k(te,{key:0,item:s},null,8,["item"])):h("",!0)],64))),256))]))}}),Ns=g(Ts,[["__scopeId","data-v-08910976"]]),Ms={class:"VPMenu"},Is={key:0,class:"items"},ws=m({__name:"VPMenu",props:{items:{}},setup(o){return(e,t)=>(a(),c("div",Ms,[e.items?(a(),c("div",Is,[(a(!0),c(w,null,H(e.items,s=>(a(),c(w,{key:JSON.stringify(s)},["link"in s?(a(),k(te,{key:0,item:s},null,8,["item"])):"component"in s?(a(),k(E(s.component),U({key:1,ref_for:!0},s.props),null,16)):(a(),k(Ns,{key:2,text:s.text,items:s.items},null,8,["text","items"]))],64))),128))])):h("",!0),u(e.$slots,"default",{},void 0,!0)]))}}),As=g(ws,[["__scopeId","data-v-f3096789"]]),Cs=["aria-expanded","aria-label"],Hs={key:0,class:"text"},Bs=["innerHTML"],Es={key:1,class:"vpi-more-horizontal icon"},Fs={class:"menu"},Ds=m({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(o){const e=T(!1),t=T();bs({el:t,onBlur:s});function s(){e.value=!1}return(n,i)=>(a(),c("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:i[1]||(i[1]=l=>e.value=!0),onMouseleave:i[2]||(i[2]=l=>e.value=!1)},[d("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":n.label,onClick:i[0]||(i[0]=l=>e.value=!e.value)},[n.button||n.icon?(a(),c("span",Hs,[n.icon?(a(),c("span",{key:0,class:M([n.icon,"option-icon"])},null,2)):h("",!0),n.button?(a(),c("span",{key:1,innerHTML:n.button},null,8,Bs)):h("",!0),i[3]||(i[3]=d("span",{class:"vpi-chevron-down text-icon"},null,-1))])):(a(),c("span",Es))],8,Cs),d("div",Fs,[_(As,{items:n.items},{default:p(()=>[u(n.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),ke=g(Ds,[["__scopeId","data-v-d51b3e8d"]]),Os=["href","aria-label","innerHTML"],Gs=m({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(o){const e=o,t=T();j(async()=>{var i;await Le();const n=(i=t.value)==null?void 0:i.children[0];n instanceof HTMLElement&&n.className.startsWith("vpi-social-")&&(getComputedStyle(n).maskImage||getComputedStyle(n).webkitMaskImage)==="none"&&n.style.setProperty("--icon",`url('https://api.iconify.design/simple-icons/${e.icon}.svg')`)});const s=y(()=>typeof e.icon=="object"?e.icon.svg:``);return(n,i)=>(a(),c("a",{ref_key:"el",ref:t,class:"VPSocialLink no-icon",href:n.link,"aria-label":n.ariaLabel??(typeof n.icon=="string"?n.icon:""),target:"_blank",rel:"noopener",innerHTML:s.value},null,8,Os))}}),Us=g(Gs,[["__scopeId","data-v-0badd679"]]),js={class:"VPSocialLinks"},zs=m({__name:"VPSocialLinks",props:{links:{}},setup(o){return(e,t)=>(a(),c("div",js,[(a(!0),c(w,null,H(e.links,({link:s,icon:n,ariaLabel:i})=>(a(),k(Us,{key:s,icon:n,link:s,ariaLabel:i},null,8,["icon","link","ariaLabel"]))),128))]))}}),be=g(zs,[["__scopeId","data-v-127ec22b"]]),Ks={key:0,class:"group translations"},Ws={class:"trans-title"},qs={key:1,class:"group"},Rs={class:"item appearance"},Js={class:"label"},Xs={class:"appearance-action"},Ys={key:2,class:"group"},Qs={class:"item social-links"},Zs=m({__name:"VPNavBarExtra",setup(o){const{site:e,theme:t}=L(),{localeLinks:s,currentLang:n}=R({correspondingLink:!0}),i=y(()=>s.value.length&&n.value.label||e.value.appearance||t.value.socialLinks);return(l,v)=>i.value?(a(),k(ke,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:p(()=>[r(s).length&&r(n).label?(a(),c("div",Ks,[d("p",Ws,I(r(n).label),1),(a(!0),c(w,null,H(r(s),f=>(a(),k(te,{key:f.link,item:f},null,8,["item"]))),128))])):h("",!0),r(e).appearance&&r(e).appearance!=="force-dark"&&r(e).appearance!=="force-auto"?(a(),c("div",qs,[d("div",Rs,[d("p",Js,I(r(t).darkModeSwitchLabel||"Appearance"),1),d("div",Xs,[_(me)])])])):h("",!0),r(t).socialLinks?(a(),c("div",Ys,[d("div",Qs,[_(be,{class:"social-links-list",links:r(t).socialLinks},null,8,["links"])])])):h("",!0)]),_:1})):h("",!0)}}),xs=g(Zs,[["__scopeId","data-v-559816d6"]]),eo=["aria-expanded"],to=m({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(o){return(e,t)=>(a(),c("button",{type:"button",class:M(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=s=>e.$emit("click"))},t[1]||(t[1]=[d("span",{class:"container"},[d("span",{class:"top"}),d("span",{class:"middle"}),d("span",{class:"bottom"})],-1)]),10,eo))}}),no=g(to,[["__scopeId","data-v-da416740"]]),so=["innerHTML"],oo=m({__name:"VPNavBarMenuLink",props:{item:{}},setup(o){const{page:e}=L();return(t,s)=>(a(),k(F,{class:M({VPNavBarMenuLink:!0,active:r(K)(r(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,"no-icon":t.item.noIcon,tabindex:"0"},{default:p(()=>[d("span",{innerHTML:t.item.text},null,8,so)]),_:1},8,["class","href","target","rel","no-icon"]))}}),ao=g(oo,[["__scopeId","data-v-ae7f79ce"]]),ro=m({__name:"VPNavBarMenuGroup",props:{item:{}},setup(o){const e=o,{page:t}=L(),s=i=>"component"in i?!1:"link"in i?K(t.value.relativePath,i.link,!!e.item.activeMatch):i.items.some(s),n=y(()=>s(e.item));return(i,l)=>(a(),k(ke,{class:M({VPNavBarMenuGroup:!0,active:r(K)(r(t).relativePath,i.item.activeMatch,!!i.item.activeMatch)||n.value}),button:i.item.text,items:i.item.items},null,8,["class","button","items"]))}}),io={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},lo=m({__name:"VPNavBarMenu",setup(o){const{theme:e}=L();return(t,s)=>r(e).nav?(a(),c("nav",io,[s[0]||(s[0]=d("span",{id:"main-nav-aria-label",class:"visually-hidden"}," Main Navigation ",-1)),(a(!0),c(w,null,H(r(e).nav,n=>(a(),c(w,{key:JSON.stringify(n)},["link"in n?(a(),k(ao,{key:0,item:n},null,8,["item"])):"component"in n?(a(),k(E(n.component),U({key:1,ref_for:!0},n.props),null,16)):(a(),k(ro,{key:2,item:n},null,8,["item"]))],64))),128))])):h("",!0)}}),uo=g(lo,[["__scopeId","data-v-3ee2e2ec"]]);function co(o){const{localeIndex:e,theme:t}=L();function s(n){var A,C,S;const i=n.split("."),l=(A=t.value.search)==null?void 0:A.options,v=l&&typeof l=="object",f=v&&((S=(C=l.locales)==null?void 0:C[e.value])==null?void 0:S.translations)||null,$=v&&l.translations||null;let V=f,b=$,P=o;const N=i.pop();for(const B of i){let G=null;const q=P==null?void 0:P[B];q&&(G=P=q);const ne=b==null?void 0:b[B];ne&&(G=b=ne);const se=V==null?void 0:V[B];se&&(G=V=se),q||(P=G),ne||(b=G),se||(V=G)}return(V==null?void 0:V[N])??(b==null?void 0:b[N])??(P==null?void 0:P[N])??""}return s}const fo=["aria-label"],po={class:"DocSearch-Button-Container"},vo={class:"DocSearch-Button-Placeholder"},ge=m({__name:"VPNavBarSearchButton",setup(o){const t=co({button:{buttonText:"Search",buttonAriaLabel:"Search"}});return(s,n)=>(a(),c("button",{type:"button",class:"DocSearch DocSearch-Button","aria-label":r(t)("button.buttonAriaLabel")},[d("span",po,[n[0]||(n[0]=d("span",{class:"vp-icon DocSearch-Search-Icon"},null,-1)),d("span",vo,I(r(t)("button.buttonText")),1)]),n[1]||(n[1]=d("span",{class:"DocSearch-Button-Keys"},[d("kbd",{class:"DocSearch-Button-Key"}),d("kbd",{class:"DocSearch-Button-Key"},"K")],-1))],8,fo))}}),ho={class:"VPNavBarSearch"},mo={id:"local-search"},_o={key:1,id:"docsearch"},ko=m({__name:"VPNavBarSearch",setup(o){const e=Ue(()=>je(()=>import("./VPLocalSearchBox.DD0Puzcb.js"),__vite__mapDeps([0,1]))),t=()=>null,{theme:s}=L(),n=T(!1),i=T(!1);j(()=>{});function l(){n.value||(n.value=!0,setTimeout(v,16))}function v(){const b=new Event("keydown");b.key="k",b.metaKey=!0,window.dispatchEvent(b),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||v()},16)}function f(b){const P=b.target,N=P.tagName;return P.isContentEditable||N==="INPUT"||N==="SELECT"||N==="TEXTAREA"}const $=T(!1);re("k",b=>{(b.ctrlKey||b.metaKey)&&(b.preventDefault(),$.value=!0)}),re("/",b=>{f(b)||(b.preventDefault(),$.value=!0)});const V="local";return(b,P)=>{var N;return a(),c("div",ho,[r(V)==="local"?(a(),c(w,{key:0},[$.value?(a(),k(r(e),{key:0,onClose:P[0]||(P[0]=A=>$.value=!1)})):h("",!0),d("div",mo,[_(ge,{onClick:P[1]||(P[1]=A=>$.value=!0)})])],64)):r(V)==="algolia"?(a(),c(w,{key:1},[n.value?(a(),k(r(t),{key:0,algolia:((N=r(s).search)==null?void 0:N.options)??r(s).algolia,onVnodeBeforeMount:P[2]||(P[2]=A=>i.value=!0)},null,8,["algolia"])):h("",!0),i.value?h("",!0):(a(),c("div",_o,[_(ge,{onClick:l})]))],64)):h("",!0)])}}}),bo=m({__name:"VPNavBarSocialLinks",setup(o){const{theme:e}=L();return(t,s)=>r(e).socialLinks?(a(),k(be,{key:0,class:"VPNavBarSocialLinks",links:r(e).socialLinks},null,8,["links"])):h("",!0)}}),go=g(bo,[["__scopeId","data-v-2fb152af"]]),$o=["href","rel","target"],yo=["innerHTML"],Po={key:2},Lo=m({__name:"VPNavBarTitle",setup(o){const{site:e,theme:t}=L(),{hasSidebar:s}=O(),{currentLang:n}=R(),i=y(()=>{var f;return typeof t.value.logoLink=="string"?t.value.logoLink:(f=t.value.logoLink)==null?void 0:f.link}),l=y(()=>{var f;return typeof t.value.logoLink=="string"||(f=t.value.logoLink)==null?void 0:f.rel}),v=y(()=>{var f;return typeof t.value.logoLink=="string"||(f=t.value.logoLink)==null?void 0:f.target});return(f,$)=>(a(),c("div",{class:M(["VPNavBarTitle",{"has-sidebar":r(s)}])},[d("a",{class:"title",href:i.value??r(ve)(r(n).link),rel:l.value,target:v.value},[u(f.$slots,"nav-bar-title-before",{},void 0,!0),r(t).logo?(a(),k(X,{key:0,class:"logo",image:r(t).logo},null,8,["image"])):h("",!0),r(t).siteTitle?(a(),c("span",{key:1,innerHTML:r(t).siteTitle},null,8,yo)):r(t).siteTitle===void 0?(a(),c("span",Po,I(r(e).title),1)):h("",!0),u(f.$slots,"nav-bar-title-after",{},void 0,!0)],8,$o)],2))}}),Vo=g(Lo,[["__scopeId","data-v-2c4cbfa5"]]),So={class:"items"},To={class:"title"},No=m({__name:"VPNavBarTranslations",setup(o){const{theme:e}=L(),{localeLinks:t,currentLang:s}=R({correspondingLink:!0});return(n,i)=>r(t).length&&r(s).label?(a(),k(ke,{key:0,class:"VPNavBarTranslations",icon:"vpi-languages",label:r(e).langMenuLabel||"Change language"},{default:p(()=>[d("div",So,[d("p",To,I(r(s).label),1),(a(!0),c(w,null,H(r(t),l=>(a(),k(te,{key:l.link,item:l},null,8,["item"]))),128))])]),_:1},8,["label"])):h("",!0)}}),Mo=g(No,[["__scopeId","data-v-20271d71"]]),Io={class:"wrapper"},wo={class:"container"},Ao={class:"title"},Co={class:"content"},Ho={class:"content-body"},Bo=m({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(o){const e=o,{y:t}=Ve(),{hasSidebar:s}=O(),{frontmatter:n}=L(),i=T({});return pe(()=>{i.value={"has-sidebar":s.value,home:n.value.layout==="home",top:t.value===0,"screen-open":e.isScreenOpen}}),(l,v)=>(a(),c("div",{class:M(["VPNavBar",i.value])},[d("div",Io,[d("div",wo,[d("div",Ao,[_(Vo,null,{"nav-bar-title-before":p(()=>[u(l.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":p(()=>[u(l.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),d("div",Co,[d("div",Ho,[u(l.$slots,"nav-bar-content-before",{},void 0,!0),_(ko,{class:"search"}),_(uo,{class:"menu"}),_(Mo,{class:"translations"}),_(ks,{class:"appearance"}),_(go,{class:"social-links"}),_(xs,{class:"extra"}),u(l.$slots,"nav-bar-content-after",{},void 0,!0),_(no,{class:"hamburger",active:l.isScreenOpen,onClick:v[0]||(v[0]=f=>l.$emit("toggle-screen"))},null,8,["active"])])])])]),v[1]||(v[1]=d("div",{class:"divider"},[d("div",{class:"divider-line"})],-1))],2))}}),Eo=g(Bo,[["__scopeId","data-v-2884efbc"]]),Fo={key:0,class:"VPNavScreenAppearance"},Do={class:"text"},Oo=m({__name:"VPNavScreenAppearance",setup(o){const{site:e,theme:t}=L();return(s,n)=>r(e).appearance&&r(e).appearance!=="force-dark"&&r(e).appearance!=="force-auto"?(a(),c("div",Fo,[d("p",Do,I(r(t).darkModeSwitchLabel||"Appearance"),1),_(me)])):h("",!0)}}),Go=g(Oo,[["__scopeId","data-v-8c86ce32"]]),Uo=["innerHTML"],jo=m({__name:"VPNavScreenMenuLink",props:{item:{}},setup(o){const e=x("close-screen");return(t,s)=>(a(),k(F,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,"no-icon":t.item.noIcon,onClick:r(e)},{default:p(()=>[d("span",{innerHTML:t.item.text},null,8,Uo)]),_:1},8,["href","target","rel","no-icon","onClick"]))}}),zo=g(jo,[["__scopeId","data-v-90a9e7b8"]]),Ko=["innerHTML"],Wo=m({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(o){const e=x("close-screen");return(t,s)=>(a(),k(F,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,"no-icon":t.item.noIcon,onClick:r(e)},{default:p(()=>[d("span",{innerHTML:t.item.text},null,8,Ko)]),_:1},8,["href","target","rel","no-icon","onClick"]))}}),Ce=g(Wo,[["__scopeId","data-v-0c33cb66"]]),qo={class:"VPNavScreenMenuGroupSection"},Ro={key:0,class:"title"},Jo=m({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(o){return(e,t)=>(a(),c("div",qo,[e.text?(a(),c("p",Ro,I(e.text),1)):h("",!0),(a(!0),c(w,null,H(e.items,s=>(a(),k(Ce,{key:s.text,item:s},null,8,["item"]))),128))]))}}),Xo=g(Jo,[["__scopeId","data-v-1ac3498f"]]),Yo=["aria-controls","aria-expanded"],Qo=["innerHTML"],Zo=["id"],xo={key:0,class:"item"},ea={key:1,class:"item"},ta={key:2,class:"group"},na=m({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(o){const e=o,t=T(!1),s=y(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function n(){t.value=!t.value}return(i,l)=>(a(),c("div",{class:M(["VPNavScreenMenuGroup",{open:t.value}])},[d("button",{class:"button","aria-controls":s.value,"aria-expanded":t.value,onClick:n},[d("span",{class:"button-text",innerHTML:i.text},null,8,Qo),l[0]||(l[0]=d("span",{class:"vpi-plus button-icon"},null,-1))],8,Yo),d("div",{id:s.value,class:"items"},[(a(!0),c(w,null,H(i.items,v=>(a(),c(w,{key:JSON.stringify(v)},["link"in v?(a(),c("div",xo,[_(Ce,{item:v},null,8,["item"])])):"component"in v?(a(),c("div",ea,[(a(),k(E(v.component),U({ref_for:!0},v.props,{"screen-menu":""}),null,16))])):(a(),c("div",ta,[_(Xo,{text:v.text,items:v.items},null,8,["text","items"])]))],64))),128))],8,Zo)],2))}}),sa=g(na,[["__scopeId","data-v-3c5063dd"]]),oa={key:0,class:"VPNavScreenMenu"},aa=m({__name:"VPNavScreenMenu",setup(o){const{theme:e}=L();return(t,s)=>r(e).nav?(a(),c("nav",oa,[(a(!0),c(w,null,H(r(e).nav,n=>(a(),c(w,{key:JSON.stringify(n)},["link"in n?(a(),k(zo,{key:0,item:n},null,8,["item"])):"component"in n?(a(),k(E(n.component),U({key:1,ref_for:!0},n.props,{"screen-menu":""}),null,16)):(a(),k(sa,{key:2,text:n.text||"",items:n.items},null,8,["text","items"]))],64))),128))])):h("",!0)}}),ra=m({__name:"VPNavScreenSocialLinks",setup(o){const{theme:e}=L();return(t,s)=>r(e).socialLinks?(a(),k(be,{key:0,class:"VPNavScreenSocialLinks",links:r(e).socialLinks},null,8,["links"])):h("",!0)}}),ia={class:"list"},la=m({__name:"VPNavScreenTranslations",setup(o){const{localeLinks:e,currentLang:t}=R({correspondingLink:!0}),s=T(!1);function n(){s.value=!s.value}return(i,l)=>r(e).length&&r(t).label?(a(),c("div",{key:0,class:M(["VPNavScreenTranslations",{open:s.value}])},[d("button",{class:"title",onClick:n},[l[0]||(l[0]=d("span",{class:"vpi-languages icon lang"},null,-1)),z(" "+I(r(t).label)+" ",1),l[1]||(l[1]=d("span",{class:"vpi-chevron-down icon chevron"},null,-1))]),d("ul",ia,[(a(!0),c(w,null,H(r(e),v=>(a(),c("li",{key:v.link,class:"item"},[_(F,{class:"link",href:v.link},{default:p(()=>[z(I(v.text),1)]),_:2},1032,["href"])]))),128))])],2)):h("",!0)}}),ua=g(la,[["__scopeId","data-v-62968728"]]),ca={class:"container"},da=m({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(o){const e=T(null),t=Se(ee?document.body:null);return(s,n)=>(a(),k(ce,{name:"fade",onEnter:n[0]||(n[0]=i=>t.value=!0),onAfterLeave:n[1]||(n[1]=i=>t.value=!1)},{default:p(()=>[s.open?(a(),c("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[d("div",ca,[u(s.$slots,"nav-screen-content-before",{},void 0,!0),_(aa,{class:"menu"}),_(ua,{class:"translations"}),_(Go,{class:"appearance"}),_(ra,{class:"social-links"}),u(s.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):h("",!0)]),_:3}))}}),fa=g(da,[["__scopeId","data-v-abf3412b"]]),pa={key:0,class:"VPNav"},va=m({__name:"VPNav",setup(o){const{isScreenOpen:e,closeScreen:t,toggleScreen:s}=ls(),{frontmatter:n}=L(),i=y(()=>n.value.navbar!==!1);return Te("close-screen",t),Y(()=>{ee&&document.documentElement.classList.toggle("hide-nav",!i.value)}),(l,v)=>i.value?(a(),c("header",pa,[_(Eo,{"is-screen-open":r(e),onToggleScreen:r(s)},{"nav-bar-title-before":p(()=>[u(l.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":p(()=>[u(l.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":p(()=>[u(l.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":p(()=>[u(l.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),_(fa,{open:r(e)},{"nav-screen-content-before":p(()=>[u(l.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":p(()=>[u(l.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):h("",!0)}}),ha=g(va,[["__scopeId","data-v-1c090468"]]),ma=["role","tabindex"],_a={key:1,class:"items"},ka=m({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(o){const e=o,{collapsed:t,collapsible:s,isLink:n,isActiveLink:i,hasActiveLink:l,hasChildren:v,toggle:f}=dt(y(()=>e.item)),$=y(()=>v.value?"section":"div"),V=y(()=>n.value?"a":"div"),b=y(()=>v.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),P=y(()=>n.value?void 0:"button"),N=y(()=>[[`level-${e.depth}`],{collapsible:s.value},{collapsed:t.value},{"is-link":n.value},{"is-active":i.value},{"has-active":l.value}]);function A(S){"key"in S&&S.key!=="Enter"||!e.item.link&&f()}function C(){e.item.link&&f()}return(S,B)=>{const G=W("VPSidebarItem",!0);return a(),k(E($.value),{class:M(["VPSidebarItem",N.value])},{default:p(()=>[S.item.text?(a(),c("div",U({key:0,class:"item",role:P.value},Ke(S.item.items?{click:A,keydown:A}:{},!0),{tabindex:S.item.items&&0}),[B[1]||(B[1]=d("div",{class:"indicator"},null,-1)),S.item.link?(a(),k(F,{key:0,tag:V.value,class:"link",href:S.item.link,rel:S.item.rel,target:S.item.target},{default:p(()=>[(a(),k(E(b.value),{class:"text",innerHTML:S.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(a(),k(E(b.value),{key:1,class:"text",innerHTML:S.item.text},null,8,["innerHTML"])),S.item.collapsed!=null&&S.item.items&&S.item.items.length?(a(),c("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:C,onKeydown:ze(C,["enter"]),tabindex:"0"},B[0]||(B[0]=[d("span",{class:"vpi-chevron-right caret-icon"},null,-1)]),32)):h("",!0)],16,ma)):h("",!0),S.item.items&&S.item.items.length?(a(),c("div",_a,[S.depth<5?(a(!0),c(w,{key:0},H(S.item.items,q=>(a(),k(G,{key:q.text,item:q,depth:S.depth+1},null,8,["item","depth"]))),128)):h("",!0)])):h("",!0)]),_:1},8,["class"])}}}),ba=g(ka,[["__scopeId","data-v-4341e9b0"]]),ga=m({__name:"VPSidebarGroup",props:{items:{}},setup(o){const e=T(!0);let t=null;return j(()=>{t=setTimeout(()=>{t=null,e.value=!1},300)}),We(()=>{t!=null&&(clearTimeout(t),t=null)}),(s,n)=>(a(!0),c(w,null,H(s.items,i=>(a(),c("div",{key:i.text,class:M(["group",{"no-transition":e.value}])},[_(ba,{item:i,depth:0},null,8,["item"])],2))),128))}}),$a=g(ga,[["__scopeId","data-v-c89d9511"]]),ya={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},Pa=m({__name:"VPSidebar",props:{open:{type:Boolean}},setup(o){const{sidebarGroups:e,hasSidebar:t}=O(),s=o,n=T(null),i=Se(ee?document.body:null);D([s,n],()=>{var v;s.open?(i.value=!0,(v=n.value)==null||v.focus()):i.value=!1},{immediate:!0,flush:"post"});const l=T(0);return D(e,()=>{l.value+=1},{deep:!0}),(v,f)=>r(t)?(a(),c("aside",{key:0,class:M(["VPSidebar",{open:v.open}]),ref_key:"navEl",ref:n,onClick:f[0]||(f[0]=qe(()=>{},["stop"]))},[f[2]||(f[2]=d("div",{class:"curtain"},null,-1)),d("nav",ya,[f[1]||(f[1]=d("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),u(v.$slots,"sidebar-nav-before",{},void 0,!0),(a(),k($a,{items:r(e),key:l.value},null,8,["items"])),u(v.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):h("",!0)}}),La=g(Pa,[["__scopeId","data-v-d4c32bb1"]]),Va=m({__name:"VPSkipLink",setup(o){const e=Z(),t=T();D(()=>e.path,()=>t.value.focus());function s({target:n}){const i=document.getElementById(decodeURIComponent(n.hash).slice(1));if(i){const l=()=>{i.removeAttribute("tabindex"),i.removeEventListener("blur",l)};i.setAttribute("tabindex","-1"),i.addEventListener("blur",l),i.focus(),window.scrollTo(0,0)}}return(n,i)=>(a(),c(w,null,[d("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),d("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:s}," Skip to content ")],64))}}),Sa=g(Va,[["__scopeId","data-v-6d95233d"]]),Ta=m({__name:"Layout",setup(o){const{isOpen:e,open:t,close:s}=O(),n=Z();D(()=>n.path,s),ct(e,s);const{frontmatter:i}=L(),l=Re(),v=y(()=>!!l["home-hero-image"]);return Te("hero-image-slot-exists",v),(f,$)=>{const V=W("Content");return r(i).layout!==!1?(a(),c("div",{key:0,class:M(["Layout",r(i).pageClass])},[u(f.$slots,"layout-top",{},void 0,!0),_(Sa),_(Qe,{class:"backdrop",show:r(e),onClick:r(s)},null,8,["show","onClick"]),_(ha,null,{"nav-bar-title-before":p(()=>[u(f.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":p(()=>[u(f.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":p(()=>[u(f.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":p(()=>[u(f.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":p(()=>[u(f.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":p(()=>[u(f.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),_(is,{open:r(e),onOpenMenu:r(t)},null,8,["open","onOpenMenu"]),_(La,{open:r(e)},{"sidebar-nav-before":p(()=>[u(f.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":p(()=>[u(f.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),_(Wn,null,{"page-top":p(()=>[u(f.$slots,"page-top",{},void 0,!0)]),"page-bottom":p(()=>[u(f.$slots,"page-bottom",{},void 0,!0)]),"not-found":p(()=>[u(f.$slots,"not-found",{},void 0,!0)]),"home-hero-before":p(()=>[u(f.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":p(()=>[u(f.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":p(()=>[u(f.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":p(()=>[u(f.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":p(()=>[u(f.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":p(()=>[u(f.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":p(()=>[u(f.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":p(()=>[u(f.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":p(()=>[u(f.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":p(()=>[u(f.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":p(()=>[u(f.$slots,"doc-before",{},void 0,!0)]),"doc-after":p(()=>[u(f.$slots,"doc-after",{},void 0,!0)]),"doc-top":p(()=>[u(f.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":p(()=>[u(f.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":p(()=>[u(f.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":p(()=>[u(f.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":p(()=>[u(f.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":p(()=>[u(f.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":p(()=>[u(f.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":p(()=>[u(f.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),_(Yn),u(f.$slots,"layout-bottom",{},void 0,!0)],2)):(a(),k(V,{key:1}))}}}),Na=g(Ta,[["__scopeId","data-v-20383531"]]),Ma={Layout:Na,enhanceApp:({app:o})=>{o.component("Badge",Je)}},wa={extends:Ma};export{wa as R,co as c,L as u}; diff --git a/assets/components_i18n-group.md.D_KGhnfJ.js b/assets/components_i18n-group.md.D_KGhnfJ.js new file mode 100644 index 00000000..bc5b58e7 --- /dev/null +++ b/assets/components_i18n-group.md.D_KGhnfJ.js @@ -0,0 +1,84 @@ +import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🌍 Component","description":"","frontmatter":{},"headers":[],"relativePath":"components/i18n-group.md","filePath":"components/i18n-group.md","lastUpdated":1731157254000}'),l={name:"components/i18n-group.md"};function h(p,s,k,e,E,r){return n(),a("div",null,s[0]||(s[0]=[t(`

🌍 <i18n-group> Component

The <i18n-group> component in Nuxt I18n Micro provides a convenient way to group translations under a common prefix, reducing repetition and improving code organization.

⚙️ Props

prefix

  • Type: String
  • Required: Yes
  • Description: The translation key prefix that will be automatically prepended to all translations within the group.
  • Example: "product.details", "user.profile"

groupClass

  • Type: String
  • Required: No
  • Default: ""
  • Description: Additional CSS class(es) to be applied to the wrapper div element.

🎯 Slots

Default Slot

The default slot provides access to two important properties:

  • prefix: The current prefix string
  • t: A translation function that automatically prepends the prefix

The slot exposes these properties through scoped slots:

vue
<template #default="{ prefix, t }">
+  <!-- Your content here -->
+</template>

🛠️ Example Usage

Basic Usage

vue
<template>
+  <i18n-group prefix="product.details">
+    <template #default="{ t }">
+      <h1>{{ t('title') }}</h1>
+      <p>{{ t('description') }}</p>
+      <div class="price">{{ t('price', { value: 99.99 }) }}</div>
+    </template>
+  </i18n-group>
+</template>

Translation file:

json
{
+  "product": {
+    "details": {
+      "title": "Premium Product",
+      "description": "This is a premium product",
+      "price": "Price: \${value}"
+    }
+  }
+}

With Custom Class

vue
<template>
+  <i18n-group 
+    prefix="user.profile" 
+    group-class="profile-section"
+  >
+    <template #default="{ t }">
+      <div class="user-info">
+        <h2>{{ t('title') }}</h2>
+        <p>{{ t('bio') }}</p>
+        <div class="stats">
+          <span>{{ t('stats.followers') }}</span>
+          <span>{{ t('stats.following') }}</span>
+        </div>
+      </div>
+    </template>
+  </i18n-group>
+</template>

Translation file:

json
{
+  "user": {
+    "profile": {
+      "title": "User Profile",
+      "bio": "User biography goes here",
+      "stats": {
+        "followers": "Followers: {count}",
+        "following": "Following: {count}"
+      }
+    }
+  }
+}

With Dynamic Content

vue
<template>
+  <i18n-group prefix="blog.post">
+    <template #default="{ t }">
+      <article>
+        <h1>{{ t('title') }}</h1>
+        <div class="meta">
+          {{ t('meta.author', { name: author }) }} |
+          {{ t('meta.date', { date: publishDate }) }}
+        </div>
+        <div v-for="(section, index) in sections" :key="index">
+          <h2>{{ t(\`sections.\${index}.title\`) }}</h2>
+          <p>{{ t(\`sections.\${index}.content\`) }}</p>
+        </div>
+      </article>
+    </template>
+  </i18n-group>
+</template>
+
+<script setup>
+const author = 'John Doe'
+const publishDate = '2024-01-01'
+const sections = ['intro', 'main', 'conclusion']
+</script>

🎨 Styling

The component wraps its content in a div with the class i18n-group and any additional classes specified in the groupClass prop:

css
.i18n-group {
+  /* Your base styles */
+}
+
+.profile-section {
+  /* Additional styles for profile sections */
+}

🚀 Best Practices

  1. Consistent Prefixes: Use consistent and logical prefixes that reflect your application's structure
vue
<i18n-group prefix="features.pricing">
+<i18n-group prefix="features.security">
  1. Modular Organization: Group related translations together under meaningful prefixes
vue
<i18n-group prefix="checkout.payment">
+<i18n-group prefix="checkout.shipping">
  1. Reusable Components: Create reusable components with their own translation groups
vue
<!-- UserProfile.vue -->
+<i18n-group prefix="user.profile">
+
+<!-- UserSettings.vue -->
+<i18n-group prefix="user.settings">
  1. Nested Groups: Avoid deeply nesting groups to maintain clarity
vue
<!-- Good -->
+<i18n-group prefix="shop.product">
+
+<!-- Avoid -->
+<i18n-group prefix="shop.category.product.details.specs">
`,36)]))}const o=i(l,[["render",h]]);export{g as __pageData,o as default}; diff --git a/assets/components_i18n-group.md.D_KGhnfJ.lean.js b/assets/components_i18n-group.md.D_KGhnfJ.lean.js new file mode 100644 index 00000000..bc5b58e7 --- /dev/null +++ b/assets/components_i18n-group.md.D_KGhnfJ.lean.js @@ -0,0 +1,84 @@ +import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🌍 Component","description":"","frontmatter":{},"headers":[],"relativePath":"components/i18n-group.md","filePath":"components/i18n-group.md","lastUpdated":1731157254000}'),l={name:"components/i18n-group.md"};function h(p,s,k,e,E,r){return n(),a("div",null,s[0]||(s[0]=[t(`

🌍 <i18n-group> Component

The <i18n-group> component in Nuxt I18n Micro provides a convenient way to group translations under a common prefix, reducing repetition and improving code organization.

⚙️ Props

prefix

  • Type: String
  • Required: Yes
  • Description: The translation key prefix that will be automatically prepended to all translations within the group.
  • Example: "product.details", "user.profile"

groupClass

  • Type: String
  • Required: No
  • Default: ""
  • Description: Additional CSS class(es) to be applied to the wrapper div element.

🎯 Slots

Default Slot

The default slot provides access to two important properties:

  • prefix: The current prefix string
  • t: A translation function that automatically prepends the prefix

The slot exposes these properties through scoped slots:

vue
<template #default="{ prefix, t }">
+  <!-- Your content here -->
+</template>

🛠️ Example Usage

Basic Usage

vue
<template>
+  <i18n-group prefix="product.details">
+    <template #default="{ t }">
+      <h1>{{ t('title') }}</h1>
+      <p>{{ t('description') }}</p>
+      <div class="price">{{ t('price', { value: 99.99 }) }}</div>
+    </template>
+  </i18n-group>
+</template>

Translation file:

json
{
+  "product": {
+    "details": {
+      "title": "Premium Product",
+      "description": "This is a premium product",
+      "price": "Price: \${value}"
+    }
+  }
+}

With Custom Class

vue
<template>
+  <i18n-group 
+    prefix="user.profile" 
+    group-class="profile-section"
+  >
+    <template #default="{ t }">
+      <div class="user-info">
+        <h2>{{ t('title') }}</h2>
+        <p>{{ t('bio') }}</p>
+        <div class="stats">
+          <span>{{ t('stats.followers') }}</span>
+          <span>{{ t('stats.following') }}</span>
+        </div>
+      </div>
+    </template>
+  </i18n-group>
+</template>

Translation file:

json
{
+  "user": {
+    "profile": {
+      "title": "User Profile",
+      "bio": "User biography goes here",
+      "stats": {
+        "followers": "Followers: {count}",
+        "following": "Following: {count}"
+      }
+    }
+  }
+}

With Dynamic Content

vue
<template>
+  <i18n-group prefix="blog.post">
+    <template #default="{ t }">
+      <article>
+        <h1>{{ t('title') }}</h1>
+        <div class="meta">
+          {{ t('meta.author', { name: author }) }} |
+          {{ t('meta.date', { date: publishDate }) }}
+        </div>
+        <div v-for="(section, index) in sections" :key="index">
+          <h2>{{ t(\`sections.\${index}.title\`) }}</h2>
+          <p>{{ t(\`sections.\${index}.content\`) }}</p>
+        </div>
+      </article>
+    </template>
+  </i18n-group>
+</template>
+
+<script setup>
+const author = 'John Doe'
+const publishDate = '2024-01-01'
+const sections = ['intro', 'main', 'conclusion']
+</script>

🎨 Styling

The component wraps its content in a div with the class i18n-group and any additional classes specified in the groupClass prop:

css
.i18n-group {
+  /* Your base styles */
+}
+
+.profile-section {
+  /* Additional styles for profile sections */
+}

🚀 Best Practices

  1. Consistent Prefixes: Use consistent and logical prefixes that reflect your application's structure
vue
<i18n-group prefix="features.pricing">
+<i18n-group prefix="features.security">
  1. Modular Organization: Group related translations together under meaningful prefixes
vue
<i18n-group prefix="checkout.payment">
+<i18n-group prefix="checkout.shipping">
  1. Reusable Components: Create reusable components with their own translation groups
vue
<!-- UserProfile.vue -->
+<i18n-group prefix="user.profile">
+
+<!-- UserSettings.vue -->
+<i18n-group prefix="user.settings">
  1. Nested Groups: Avoid deeply nesting groups to maintain clarity
vue
<!-- Good -->
+<i18n-group prefix="shop.product">
+
+<!-- Avoid -->
+<i18n-group prefix="shop.category.product.details.specs">
`,36)]))}const o=i(l,[["render",h]]);export{g as __pageData,o as default}; diff --git a/assets/components_i18n-link.md.BWN41WEE.js b/assets/components_i18n-link.md.BWN41WEE.js new file mode 100644 index 00000000..0b493a2f --- /dev/null +++ b/assets/components_i18n-link.md.BWN41WEE.js @@ -0,0 +1 @@ +import{_ as s,c as a,a2 as t,o as e}from"./chunks/framework.Gfs4HC1t.js";const E=JSON.parse('{"title":"🌍 Component","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"components/i18n-link.md","filePath":"components/i18n-link.md","lastUpdated":1724679268000}'),n={name:"components/i18n-link.md"};function l(h,i,k,p,o,r){return e(),a("div",null,i[0]||(i[0]=[t('

🌍 <i18n-link> Component

The <i18n-link> component in Nuxt I18n Micro is a versatile link component that automatically localizes routes based on the current locale. It acts as a wrapper around the <NuxtLink> component, providing additional features such as active link styling and support for external links.

⚙️ Props

to

  • Type: NuxtLinkProps | string
  • Required: Yes
  • Description: Defines the target route or path for the link. It can be a string (for simple paths) or an object containing route information.
  • Example:
    vue
    <i18n-link to="/about">About Us</i18n-link>\n<i18n-link :to="{ name: 'index' }">Home</i18n-link>

activeStyle

  • Type: Partial<CSSStyleDeclaration>
  • Optional: Yes
  • Description: Allows you to customize the inline styles applied to the link when it matches the current route. This can be useful for highlighting the active link in navigation menus without relying on CSS classes.
  • Example:
    vue
    <i18n-link to="/about" :activeStyle="{ fontWeight: 'bold', color: 'red' }">About Us</i18n-link>

🛠️ Example Usages

Basic Usage

vue
<i18n-link to="/about">About Us</i18n-link>

This example creates a link to the /about page, localized to the current locale.

vue
<i18n-link to="/about" :activeStyle="{ fontWeight: 'bold' }">About Us</i18n-link>

The link will have bold text when the user is on the /about page, allowing you to style the active link directly with inline styles.

The component automatically detects external links and adds the necessary attributes for security.

vue
<i18n-link to="https://example.com">Visit Example</i18n-link>

This link will open https://example.com in a new tab with rel="noopener noreferrer" applied.

🎨 Styles

The component now uses inline styles for the active state instead of a class. You can customize these styles using the activeStyle prop.

Default Active Styles

  • Font Weight: bold
  • Color: Inherits the browser's default color (if no color is specified in activeStyle).

You can override these by providing custom styles through the activeStyle prop.

Custom Active Styles

vue
<i18n-link to="/about" :activeStyle="{ fontWeight: 'bold', color: '#42b983' }">About Us</i18n-link>

In this example, the link will be bold and green when active.

🚀 Additional Features

Slot for Custom Content

You can pass custom content inside the link using slots, making the component flexible for different use cases.

vue
<i18n-link to="/about">\n  <span>About Us</span>\n</i18n-link>

Accessibility Enhancements

The component supports aria-label and other accessibility attributes to ensure a more accessible experience.

vue
<i18n-link to="/about" aria-label="Learn more about us">\n  About Us\n</i18n-link>
',33)]))}const c=s(n,[["render",l]]);export{E as __pageData,c as default}; diff --git a/assets/components_i18n-link.md.BWN41WEE.lean.js b/assets/components_i18n-link.md.BWN41WEE.lean.js new file mode 100644 index 00000000..0b493a2f --- /dev/null +++ b/assets/components_i18n-link.md.BWN41WEE.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,a2 as t,o as e}from"./chunks/framework.Gfs4HC1t.js";const E=JSON.parse('{"title":"🌍 Component","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"components/i18n-link.md","filePath":"components/i18n-link.md","lastUpdated":1724679268000}'),n={name:"components/i18n-link.md"};function l(h,i,k,p,o,r){return e(),a("div",null,i[0]||(i[0]=[t('

🌍 <i18n-link> Component

The <i18n-link> component in Nuxt I18n Micro is a versatile link component that automatically localizes routes based on the current locale. It acts as a wrapper around the <NuxtLink> component, providing additional features such as active link styling and support for external links.

⚙️ Props

to

  • Type: NuxtLinkProps | string
  • Required: Yes
  • Description: Defines the target route or path for the link. It can be a string (for simple paths) or an object containing route information.
  • Example:
    vue
    <i18n-link to="/about">About Us</i18n-link>\n<i18n-link :to="{ name: 'index' }">Home</i18n-link>

activeStyle

  • Type: Partial<CSSStyleDeclaration>
  • Optional: Yes
  • Description: Allows you to customize the inline styles applied to the link when it matches the current route. This can be useful for highlighting the active link in navigation menus without relying on CSS classes.
  • Example:
    vue
    <i18n-link to="/about" :activeStyle="{ fontWeight: 'bold', color: 'red' }">About Us</i18n-link>

🛠️ Example Usages

Basic Usage

vue
<i18n-link to="/about">About Us</i18n-link>

This example creates a link to the /about page, localized to the current locale.

vue
<i18n-link to="/about" :activeStyle="{ fontWeight: 'bold' }">About Us</i18n-link>

The link will have bold text when the user is on the /about page, allowing you to style the active link directly with inline styles.

The component automatically detects external links and adds the necessary attributes for security.

vue
<i18n-link to="https://example.com">Visit Example</i18n-link>

This link will open https://example.com in a new tab with rel="noopener noreferrer" applied.

🎨 Styles

The component now uses inline styles for the active state instead of a class. You can customize these styles using the activeStyle prop.

Default Active Styles

  • Font Weight: bold
  • Color: Inherits the browser's default color (if no color is specified in activeStyle).

You can override these by providing custom styles through the activeStyle prop.

Custom Active Styles

vue
<i18n-link to="/about" :activeStyle="{ fontWeight: 'bold', color: '#42b983' }">About Us</i18n-link>

In this example, the link will be bold and green when active.

🚀 Additional Features

Slot for Custom Content

You can pass custom content inside the link using slots, making the component flexible for different use cases.

vue
<i18n-link to="/about">\n  <span>About Us</span>\n</i18n-link>

Accessibility Enhancements

The component supports aria-label and other accessibility attributes to ensure a more accessible experience.

vue
<i18n-link to="/about" aria-label="Learn more about us">\n  About Us\n</i18n-link>
',33)]))}const c=s(n,[["render",l]]);export{E as __pageData,c as default}; diff --git a/assets/components_i18n-switcher.md.BVMz2Cf5.js b/assets/components_i18n-switcher.md.BVMz2Cf5.js new file mode 100644 index 00000000..2db1623e --- /dev/null +++ b/assets/components_i18n-switcher.md.BVMz2Cf5.js @@ -0,0 +1,59 @@ +import{_ as i,c as t,a2 as a,o as e}from"./chunks/framework.Gfs4HC1t.js";const E=JSON.parse('{"title":"🌍 Component","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"components/i18n-switcher.md","filePath":"components/i18n-switcher.md","lastUpdated":1731158111000}'),l={name:"components/i18n-switcher.md"};function n(h,s,p,o,k,r){return e(),t("div",null,s[0]||(s[0]=[a(`

🌍 <i18n-switcher> Component

The <i18n-switcher> component in Nuxt I18n Micro provides a user-friendly dropdown interface for switching between different locales in your application. This component is highly customizable, allowing seamless integration with your application's design and layout.

⚙️ Props

customLabels

  • Type: Record<string, string>
  • Default: {}
  • Description: Allows you to define custom labels for each locale, which will be displayed instead of the locale codes.
  • Example:
    vue
    <i18n-switcher :customLabels="{ en: 'English', fr: 'Français' }"></i18n-switcher>

customWrapperStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Allows you to override the default styles applied to the wrapper <div> that contains the locale switcher.
  • Example:
    vue
    <i18n-switcher :customWrapperStyle="{ backgroundColor: '#f8f9fa', padding: '10px' }"></i18n-switcher>

customButtonStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Allows you to customize the styles applied to the button element that toggles the dropdown menu.
  • Example:
    vue
    <i18n-switcher :customButtonStyle="{ backgroundColor: '#007bff', color: '#fff', borderRadius: '4px' }"></i18n-switcher>

customDropdownStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Sets the custom styles for the <ul> element that contains the list of locales.
  • Example:
    vue
    <i18n-switcher :customDropdownStyle="{ border: '1px solid #007bff', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)' }"></i18n-switcher>

customItemStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Applies custom styles to each <li> element representing a locale option.
  • Example:
    vue
    <i18n-switcher :customItemStyle="{ margin: '5px 0', padding: '5px' }"></i18n-switcher>

customLinkStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Allows you to customize the styles applied to the <NuxtLink> elements used to switch between locales.
  • Example:
    vue
    <i18n-switcher :customLinkStyle="{ padding: '8px 16px', color: '#333', textDecoration: 'none' }"></i18n-switcher>

customActiveLinkStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Sets the custom styles for the currently active locale, usually to highlight or indicate the selected option.
  • Example:
    vue
    <i18n-switcher :customActiveLinkStyle="{ color: 'green', fontWeight: 'bold', backgroundColor: '#f0f0f0' }"></i18n-switcher>

customDisabledLinkStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Applies custom styles to disable the link for the current locale, preventing users from selecting it.
  • Example:
    vue
    <i18n-switcher :customDisabledLinkStyle="{ color: 'gray', cursor: 'not-allowed' }"></i18n-switcher>

customIconStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Defines custom styles for the icon that indicates the dropdown state, such as rotating the icon when the dropdown is opened or closed.
  • Example:
    vue
    <i18n-switcher :customIconStyle="{ fontSize: '20px', color: '#007bff' }"></i18n-switcher>

🛠️ Example Usages

Basic Usage

vue
<template>
+  <i18n-switcher />
+</template>

This renders a locale switcher with default styling and behavior.

Custom Labels and Inline Styles

vue
<template>
+  <i18n-switcher
+    :customLabels="{ en: 'English', fr: 'Français' }"
+    :customWrapperStyle="{ backgroundColor: '#f8f9fa', padding: '10px' }"
+    :customButtonStyle="{ backgroundColor: '#007bff', color: '#fff', borderRadius: '4px' }"
+    :customDropdownStyle="{ border: '1px solid #007bff', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)' }"
+    :customItemStyle="{ margin: '5px 0', padding: '5px' }"
+    :customLinkStyle="{ padding: '8px 16px', color: '#333', textDecoration: 'none' }"
+    :customActiveLinkStyle="{ color: 'green', fontWeight: 'bold', backgroundColor: '#f0f0f0' }"
+    :customDisabledLinkStyle="{ color: 'gray', cursor: 'not-allowed' }"
+    :customIconStyle="{ fontSize: '20px', color: '#007bff' }"
+  />
+</template>

This example demonstrates a fully customized locale switcher with custom labels and inline styles.

🔌 Slots

The <i18n-switcher> component provides several slots that allow you to insert custom content at various points within the component. These slots enhance the flexibility and customization of the switcher, enabling you to tailor it to your application's specific needs.

before-button

  • Description: Inserts content immediately before the language switcher button.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-button>
    +    <span>🌐</span>
    +  </template>
    +</i18n-switcher>

before-selected-locale

  • Description: Inserts content before the currently selected locale label within the button.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-selected-locale>
    +    <i class="icon-flag"></i>
    +  </template>
    +</i18n-switcher>

after-selected-locale

  • Description: Inserts content after the currently selected locale label within the button.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-selected-locale>
    +    <i class="icon-caret"></i>
    +  </template>
    +</i18n-switcher>

before-dropdown

  • Description: Inserts content immediately before the dropdown menu.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-dropdown>
    +    <li class="dropdown-header">Select Language</li>
    +  </template>
    +</i18n-switcher>

after-dropdown

  • Description: Inserts content immediately after the dropdown menu.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-dropdown>
    +    <li class="dropdown-footer">Powered by Nuxt</li>
    +  </template>
    +</i18n-switcher>

before-dropdown-items

  • Description: Inserts content before the list of locale items within the dropdown.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-dropdown-items>
    +    <li class="divider"></li>
    +  </template>
    +</i18n-switcher>

after-dropdown-items

  • Description: Inserts content after the list of locale items within the dropdown.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-dropdown-items>
    +    <li class="divider"></li>
    +  </template>
    +</i18n-switcher>

before-item

  • Description: Inserts content before each locale item. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-item="{ locale }">
    +    <i :class="\`flag-\${locale.code}\`"></i>
    +  </template>
    +</i18n-switcher>

after-item

  • Description: Inserts content after each locale item. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-item="{ locale }">
    +    <span>{{ locale.code }}</span>
    +  </template>
    +</i18n-switcher>
  • Description: Inserts content before the locale label inside each link. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-link-content="{ locale }">
    +    <i :class="\`icon-\${locale.code}\`"></i>
    +  </template>
    +</i18n-switcher>
  • Description: Inserts content after the locale label inside each link. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-link-content="{ locale }">
    +    <span>({{ locale.code }})</span>
    +  </template>
    +</i18n-switcher>

Summary of Slots

Slot NameDescriptionProps
before-buttonContent before the language switcher buttonNone
before-selected-localeContent before the selected locale label within the buttonNone
after-selected-localeContent after the selected locale label within the buttonNone
before-dropdownContent before the dropdown menuNone
after-dropdownContent after the dropdown menuNone
before-dropdown-itemsContent before the list of locale items within the dropdownNone
after-dropdown-itemsContent after the list of locale items within the dropdownNone
before-itemContent before each locale itemlocale
after-itemContent after each locale itemlocale
before-link-contentContent before the locale label inside each linklocale
after-link-contentContent after the locale label inside each linklocale

🎨 Styles Overview

The <i18n-switcher> component comes with basic styles defined using inline styles that can easily be overridden by passing custom styles via props. Here’s a brief overview of the default styling:

  • Wrapper: Controls the positioning of the dropdown.
  • Button: Styles the dropdown toggle button.
  • Dropdown: Styles the dropdown list.
  • Items: Styles each item in the list.
  • Links: Styles the links inside each item.
  • Icon: Styles the dropdown indicator icon.

You can customize these styles by passing custom styles through the respective props, ensuring that the locale switcher integrates seamlessly into your application's UI.

`,58)]))}const c=i(l,[["render",n]]);export{E as __pageData,c as default}; diff --git a/assets/components_i18n-switcher.md.BVMz2Cf5.lean.js b/assets/components_i18n-switcher.md.BVMz2Cf5.lean.js new file mode 100644 index 00000000..2db1623e --- /dev/null +++ b/assets/components_i18n-switcher.md.BVMz2Cf5.lean.js @@ -0,0 +1,59 @@ +import{_ as i,c as t,a2 as a,o as e}from"./chunks/framework.Gfs4HC1t.js";const E=JSON.parse('{"title":"🌍 Component","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"components/i18n-switcher.md","filePath":"components/i18n-switcher.md","lastUpdated":1731158111000}'),l={name:"components/i18n-switcher.md"};function n(h,s,p,o,k,r){return e(),t("div",null,s[0]||(s[0]=[a(`

🌍 <i18n-switcher> Component

The <i18n-switcher> component in Nuxt I18n Micro provides a user-friendly dropdown interface for switching between different locales in your application. This component is highly customizable, allowing seamless integration with your application's design and layout.

⚙️ Props

customLabels

  • Type: Record<string, string>
  • Default: {}
  • Description: Allows you to define custom labels for each locale, which will be displayed instead of the locale codes.
  • Example:
    vue
    <i18n-switcher :customLabels="{ en: 'English', fr: 'Français' }"></i18n-switcher>

customWrapperStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Allows you to override the default styles applied to the wrapper <div> that contains the locale switcher.
  • Example:
    vue
    <i18n-switcher :customWrapperStyle="{ backgroundColor: '#f8f9fa', padding: '10px' }"></i18n-switcher>

customButtonStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Allows you to customize the styles applied to the button element that toggles the dropdown menu.
  • Example:
    vue
    <i18n-switcher :customButtonStyle="{ backgroundColor: '#007bff', color: '#fff', borderRadius: '4px' }"></i18n-switcher>

customDropdownStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Sets the custom styles for the <ul> element that contains the list of locales.
  • Example:
    vue
    <i18n-switcher :customDropdownStyle="{ border: '1px solid #007bff', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)' }"></i18n-switcher>

customItemStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Applies custom styles to each <li> element representing a locale option.
  • Example:
    vue
    <i18n-switcher :customItemStyle="{ margin: '5px 0', padding: '5px' }"></i18n-switcher>

customLinkStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Allows you to customize the styles applied to the <NuxtLink> elements used to switch between locales.
  • Example:
    vue
    <i18n-switcher :customLinkStyle="{ padding: '8px 16px', color: '#333', textDecoration: 'none' }"></i18n-switcher>

customActiveLinkStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Sets the custom styles for the currently active locale, usually to highlight or indicate the selected option.
  • Example:
    vue
    <i18n-switcher :customActiveLinkStyle="{ color: 'green', fontWeight: 'bold', backgroundColor: '#f0f0f0' }"></i18n-switcher>

customDisabledLinkStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Applies custom styles to disable the link for the current locale, preventing users from selecting it.
  • Example:
    vue
    <i18n-switcher :customDisabledLinkStyle="{ color: 'gray', cursor: 'not-allowed' }"></i18n-switcher>

customIconStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Defines custom styles for the icon that indicates the dropdown state, such as rotating the icon when the dropdown is opened or closed.
  • Example:
    vue
    <i18n-switcher :customIconStyle="{ fontSize: '20px', color: '#007bff' }"></i18n-switcher>

🛠️ Example Usages

Basic Usage

vue
<template>
+  <i18n-switcher />
+</template>

This renders a locale switcher with default styling and behavior.

Custom Labels and Inline Styles

vue
<template>
+  <i18n-switcher
+    :customLabels="{ en: 'English', fr: 'Français' }"
+    :customWrapperStyle="{ backgroundColor: '#f8f9fa', padding: '10px' }"
+    :customButtonStyle="{ backgroundColor: '#007bff', color: '#fff', borderRadius: '4px' }"
+    :customDropdownStyle="{ border: '1px solid #007bff', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)' }"
+    :customItemStyle="{ margin: '5px 0', padding: '5px' }"
+    :customLinkStyle="{ padding: '8px 16px', color: '#333', textDecoration: 'none' }"
+    :customActiveLinkStyle="{ color: 'green', fontWeight: 'bold', backgroundColor: '#f0f0f0' }"
+    :customDisabledLinkStyle="{ color: 'gray', cursor: 'not-allowed' }"
+    :customIconStyle="{ fontSize: '20px', color: '#007bff' }"
+  />
+</template>

This example demonstrates a fully customized locale switcher with custom labels and inline styles.

🔌 Slots

The <i18n-switcher> component provides several slots that allow you to insert custom content at various points within the component. These slots enhance the flexibility and customization of the switcher, enabling you to tailor it to your application's specific needs.

before-button

  • Description: Inserts content immediately before the language switcher button.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-button>
    +    <span>🌐</span>
    +  </template>
    +</i18n-switcher>

before-selected-locale

  • Description: Inserts content before the currently selected locale label within the button.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-selected-locale>
    +    <i class="icon-flag"></i>
    +  </template>
    +</i18n-switcher>

after-selected-locale

  • Description: Inserts content after the currently selected locale label within the button.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-selected-locale>
    +    <i class="icon-caret"></i>
    +  </template>
    +</i18n-switcher>

before-dropdown

  • Description: Inserts content immediately before the dropdown menu.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-dropdown>
    +    <li class="dropdown-header">Select Language</li>
    +  </template>
    +</i18n-switcher>

after-dropdown

  • Description: Inserts content immediately after the dropdown menu.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-dropdown>
    +    <li class="dropdown-footer">Powered by Nuxt</li>
    +  </template>
    +</i18n-switcher>

before-dropdown-items

  • Description: Inserts content before the list of locale items within the dropdown.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-dropdown-items>
    +    <li class="divider"></li>
    +  </template>
    +</i18n-switcher>

after-dropdown-items

  • Description: Inserts content after the list of locale items within the dropdown.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-dropdown-items>
    +    <li class="divider"></li>
    +  </template>
    +</i18n-switcher>

before-item

  • Description: Inserts content before each locale item. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-item="{ locale }">
    +    <i :class="\`flag-\${locale.code}\`"></i>
    +  </template>
    +</i18n-switcher>

after-item

  • Description: Inserts content after each locale item. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-item="{ locale }">
    +    <span>{{ locale.code }}</span>
    +  </template>
    +</i18n-switcher>
  • Description: Inserts content before the locale label inside each link. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-link-content="{ locale }">
    +    <i :class="\`icon-\${locale.code}\`"></i>
    +  </template>
    +</i18n-switcher>
  • Description: Inserts content after the locale label inside each link. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-link-content="{ locale }">
    +    <span>({{ locale.code }})</span>
    +  </template>
    +</i18n-switcher>

Summary of Slots

Slot NameDescriptionProps
before-buttonContent before the language switcher buttonNone
before-selected-localeContent before the selected locale label within the buttonNone
after-selected-localeContent after the selected locale label within the buttonNone
before-dropdownContent before the dropdown menuNone
after-dropdownContent after the dropdown menuNone
before-dropdown-itemsContent before the list of locale items within the dropdownNone
after-dropdown-itemsContent after the list of locale items within the dropdownNone
before-itemContent before each locale itemlocale
after-itemContent after each locale itemlocale
before-link-contentContent before the locale label inside each linklocale
after-link-contentContent after the locale label inside each linklocale

🎨 Styles Overview

The <i18n-switcher> component comes with basic styles defined using inline styles that can easily be overridden by passing custom styles via props. Here’s a brief overview of the default styling:

  • Wrapper: Controls the positioning of the dropdown.
  • Button: Styles the dropdown toggle button.
  • Dropdown: Styles the dropdown list.
  • Items: Styles each item in the list.
  • Links: Styles the links inside each item.
  • Icon: Styles the dropdown indicator icon.

You can customize these styles by passing custom styles through the respective props, ensuring that the locale switcher integrates seamlessly into your application's UI.

`,58)]))}const c=i(l,[["render",n]]);export{E as __pageData,c as default}; diff --git a/assets/components_i18n-t.md.C61xRTdL.js b/assets/components_i18n-t.md.C61xRTdL.js new file mode 100644 index 00000000..e59dcdf1 --- /dev/null +++ b/assets/components_i18n-t.md.C61xRTdL.js @@ -0,0 +1,45 @@ +import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const E=JSON.parse('{"title":"🌍 Component","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"components/i18n-t.md","filePath":"components/i18n-t.md","lastUpdated":1736501973000}'),l={name:"components/i18n-t.md"};function e(h,s,p,k,o,r){return n(),a("div",null,s[0]||(s[0]=[t(`

🌍 <i18n-t> Component

The <i18n-t> component in Nuxt I18n Micro is a flexible translation component that supports dynamic content insertion via slots. It allows you to interpolate translations with custom Vue components or HTML content, enabling advanced localization scenarios.

⚙️ Props

keypath

  • Type: string
  • Required: Yes
  • Description: Defines the key path to the translation string in your localization files.
  • Example:
vue
<i18n-t keypath="feedback.text" />

plural

  • Type: number | string
  • Optional: Yes
  • Description: Specifies a number for pluralization rules.
  • Example:
vue
<i18n-t keypath="items" :plural="10" />
json
{
+  "items": "Nothing|You have {count} item|You have {count} items"
+}

number

  • Type: number | string
  • Optional: Yes
  • Description: This prop is used for number formatting. It can be passed as a number or string to render a localized number.
  • Example:
vue
<i18n-t keypath="data.item" :number="1234567.89" />
json
{
+  "data": {
+    "item": "The number is: {number}"
+  }
+}

date

  • Type: Date | string | number
  • Optional: Yes
  • Description: This prop is used for date formatting. It can be passed as a Date, string, or number to render a localized date.
  • Example:
vue
<i18n-t keypath="data.item" :date="'2023-12-31'" />
json
{
+  "data": {
+    "item": "The date is: {date}"
+  }
+}

relativeDate

  • Type: Date | string | number
  • Optional: Yes
  • Description: This prop is used for formatting relative dates. It can be passed as a Date, string, or number to render a localized relative date.
  • Example:
vue
<i18n-t keypath="data.item" :relative-date="'2023-12-31'" />
json
{
+  "data": {
+    "item": "The relative date is: {relativeDate}"
+  }
+}

tag

  • Type: string
  • Optional: Yes
  • Default: 'span'
  • Description: Specifies the HTML tag to wrap the translated content.
  • Example:
vue
<i18n-t keypath="feedback.text" tag="div" />

params

  • Type: Record<string, string | number | boolean>
  • Optional: Yes
  • Description: Provides parameters for interpolating dynamic values in the translation.
  • Example:
vue
<i18n-t keypath="user.greeting" :params="{ name: userName }" />

defaultValue

  • Type: string
  • Optional: Yes
  • Description: The default value to use if the translation key is not found.
  • Example:
vue
<i18n-t keypath="nonExistentKey" defaultValue="Fallback text"></i18n-t>

html

  • Type: boolean
  • Optional: Yes
  • Default: false
  • Description: Enables the rendering of the translation as raw HTML.
  • Example:
vue
<i18n-t keypath="feedback.text" html />

hideIfEmpty

  • Type: boolean
  • Optional: Yes
  • Default: false
  • Description: If true, the component will not render anything if the translation is empty.
  • Example:
vue
<i18n-t keypath="optionalMessage" :hideIfEmpty="true"></i18n-t>

customPluralRule

  • Type: (value: string, count: number, params: Record<string, string | number | boolean>, locale: string) => string
  • Optional: Yes
  • Description: A function that allows you to define custom pluralization logic. Useful if the default pluralization rules do not fit your specific needs.
  • Example:
vue
<i18n-t
+  keypath="items"
+  :plural="itemCount"
+  :customPluralRule="(key, count, params, locale, getTranslation) => {
+    const translation = getTranslation(key, params)
+    if (!translation) {
+      return null
+    }
+    return count === 1 ? 'no items' : \`\${count} \${translation}\`;
+  }"
+></i18n-t>

🛠️ Example Usages

Basic Usage

vue
<i18n-t keypath="feedback.text" />

This renders the translation for feedback.text within a <span> tag.

Using Slots for Dynamic Content

The <i18n-t> component supports the use of slots to dynamically insert Vue components or other content into specific parts of the translation.

vue
<i18n-t keypath="feedback.text">
+  <template #link>
+    <nuxt-link :to="{ name: 'index' }">
+      <i18n-t keypath="feedback.link" />
+    </nuxt-link>
+  </template>
+</i18n-t>

In this example, the {link} placeholder in the feedback.text translation string is replaced by the <nuxt-link> component, which itself contains another translation component.

Pluralization

vue
<i18n-t keypath="items.count" :plural="itemCount" />

This automatically applies pluralization rules based on the itemCount value.

🚀 Additional Features

Default Slot

If no specific slot is provided, the translation can be customized via the default slot, which provides the entire translated string:

vue
<i18n-t keypath="welcome.message">
+  <template #default="{ translation }">
+    {{ translation.replace('Nuxt', 'Vue') }}
+  </template>
+</i18n-t>

Conditional Rendering

Render nothing if the translation string is empty by using the hideIfEmpty prop.

vue
<i18n-t keypath="optionalMessage" :hideIfEmpty="true"></i18n-t>

Custom Pluralization Rule

Use a custom function to handle pluralization.

vue
<i18n-t
+  keypath="items"
+  :plural="itemCount"
+  :customPluralRule="(key, value, count, locale) => {
+    return count === 1 ? 'One item' : \`\${count} items\`;
+  }"
+></i18n-t>

Advanced Example with Slots

Utilize slots to customize how the translation content is rendered.

vue
<i18n-t keypath="welcomeMessage">
+  <template #default="{ translation }">
+    <strong>{{ translation }}</strong>
+  </template>
+</i18n-t>
`,64)]))}const g=i(l,[["render",e]]);export{E as __pageData,g as default}; diff --git a/assets/components_i18n-t.md.C61xRTdL.lean.js b/assets/components_i18n-t.md.C61xRTdL.lean.js new file mode 100644 index 00000000..e59dcdf1 --- /dev/null +++ b/assets/components_i18n-t.md.C61xRTdL.lean.js @@ -0,0 +1,45 @@ +import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const E=JSON.parse('{"title":"🌍 Component","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"components/i18n-t.md","filePath":"components/i18n-t.md","lastUpdated":1736501973000}'),l={name:"components/i18n-t.md"};function e(h,s,p,k,o,r){return n(),a("div",null,s[0]||(s[0]=[t(`

🌍 <i18n-t> Component

The <i18n-t> component in Nuxt I18n Micro is a flexible translation component that supports dynamic content insertion via slots. It allows you to interpolate translations with custom Vue components or HTML content, enabling advanced localization scenarios.

⚙️ Props

keypath

  • Type: string
  • Required: Yes
  • Description: Defines the key path to the translation string in your localization files.
  • Example:
vue
<i18n-t keypath="feedback.text" />

plural

  • Type: number | string
  • Optional: Yes
  • Description: Specifies a number for pluralization rules.
  • Example:
vue
<i18n-t keypath="items" :plural="10" />
json
{
+  "items": "Nothing|You have {count} item|You have {count} items"
+}

number

  • Type: number | string
  • Optional: Yes
  • Description: This prop is used for number formatting. It can be passed as a number or string to render a localized number.
  • Example:
vue
<i18n-t keypath="data.item" :number="1234567.89" />
json
{
+  "data": {
+    "item": "The number is: {number}"
+  }
+}

date

  • Type: Date | string | number
  • Optional: Yes
  • Description: This prop is used for date formatting. It can be passed as a Date, string, or number to render a localized date.
  • Example:
vue
<i18n-t keypath="data.item" :date="'2023-12-31'" />
json
{
+  "data": {
+    "item": "The date is: {date}"
+  }
+}

relativeDate

  • Type: Date | string | number
  • Optional: Yes
  • Description: This prop is used for formatting relative dates. It can be passed as a Date, string, or number to render a localized relative date.
  • Example:
vue
<i18n-t keypath="data.item" :relative-date="'2023-12-31'" />
json
{
+  "data": {
+    "item": "The relative date is: {relativeDate}"
+  }
+}

tag

  • Type: string
  • Optional: Yes
  • Default: 'span'
  • Description: Specifies the HTML tag to wrap the translated content.
  • Example:
vue
<i18n-t keypath="feedback.text" tag="div" />

params

  • Type: Record<string, string | number | boolean>
  • Optional: Yes
  • Description: Provides parameters for interpolating dynamic values in the translation.
  • Example:
vue
<i18n-t keypath="user.greeting" :params="{ name: userName }" />

defaultValue

  • Type: string
  • Optional: Yes
  • Description: The default value to use if the translation key is not found.
  • Example:
vue
<i18n-t keypath="nonExistentKey" defaultValue="Fallback text"></i18n-t>

html

  • Type: boolean
  • Optional: Yes
  • Default: false
  • Description: Enables the rendering of the translation as raw HTML.
  • Example:
vue
<i18n-t keypath="feedback.text" html />

hideIfEmpty

  • Type: boolean
  • Optional: Yes
  • Default: false
  • Description: If true, the component will not render anything if the translation is empty.
  • Example:
vue
<i18n-t keypath="optionalMessage" :hideIfEmpty="true"></i18n-t>

customPluralRule

  • Type: (value: string, count: number, params: Record<string, string | number | boolean>, locale: string) => string
  • Optional: Yes
  • Description: A function that allows you to define custom pluralization logic. Useful if the default pluralization rules do not fit your specific needs.
  • Example:
vue
<i18n-t
+  keypath="items"
+  :plural="itemCount"
+  :customPluralRule="(key, count, params, locale, getTranslation) => {
+    const translation = getTranslation(key, params)
+    if (!translation) {
+      return null
+    }
+    return count === 1 ? 'no items' : \`\${count} \${translation}\`;
+  }"
+></i18n-t>

🛠️ Example Usages

Basic Usage

vue
<i18n-t keypath="feedback.text" />

This renders the translation for feedback.text within a <span> tag.

Using Slots for Dynamic Content

The <i18n-t> component supports the use of slots to dynamically insert Vue components or other content into specific parts of the translation.

vue
<i18n-t keypath="feedback.text">
+  <template #link>
+    <nuxt-link :to="{ name: 'index' }">
+      <i18n-t keypath="feedback.link" />
+    </nuxt-link>
+  </template>
+</i18n-t>

In this example, the {link} placeholder in the feedback.text translation string is replaced by the <nuxt-link> component, which itself contains another translation component.

Pluralization

vue
<i18n-t keypath="items.count" :plural="itemCount" />

This automatically applies pluralization rules based on the itemCount value.

🚀 Additional Features

Default Slot

If no specific slot is provided, the translation can be customized via the default slot, which provides the entire translated string:

vue
<i18n-t keypath="welcome.message">
+  <template #default="{ translation }">
+    {{ translation.replace('Nuxt', 'Vue') }}
+  </template>
+</i18n-t>

Conditional Rendering

Render nothing if the translation string is empty by using the hideIfEmpty prop.

vue
<i18n-t keypath="optionalMessage" :hideIfEmpty="true"></i18n-t>

Custom Pluralization Rule

Use a custom function to handle pluralization.

vue
<i18n-t
+  keypath="items"
+  :plural="itemCount"
+  :customPluralRule="(key, value, count, locale) => {
+    return count === 1 ? 'One item' : \`\${count} items\`;
+  }"
+></i18n-t>

Advanced Example with Slots

Utilize slots to customize how the translation content is rendered.

vue
<i18n-t keypath="welcomeMessage">
+  <template #default="{ translation }">
+    <strong>{{ translation }}</strong>
+  </template>
+</i18n-t>
`,64)]))}const g=i(l,[["render",e]]);export{E as __pageData,g as default}; diff --git a/assets/composables_useI18n.md.CtJaYII6.js b/assets/composables_useI18n.md.CtJaYII6.js new file mode 100644 index 00000000..2ff0d3af --- /dev/null +++ b/assets/composables_useI18n.md.CtJaYII6.js @@ -0,0 +1 @@ +import{_ as i,c as a,a2 as t,o as e}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🛠️ useI18n Composable","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"composables/useI18n.md","filePath":"composables/useI18n.md","lastUpdated":1729326320000}'),n={name:"composables/useI18n.md"};function l(h,s,p,k,o,r){return e(),a("div",null,s[0]||(s[0]=[t('

🛠️ useI18n Composable

The useI18n composable in Nuxt I18n Micro is designed to provide an easy and efficient way to access internationalization functionalities within your Nuxt application. It offers a variety of methods to handle localization, translation, and route management based on the current locale.

All methods can be accessed both with and without the $ prefix for convenience.

⚙️ Return Values

The useI18n composable returns an object containing several key methods and properties for managing internationalization:

$getLocale

  • Type: () => string
  • Description: Returns the current locale of the application.
  • Example:
    js
    const { $getLocale } = useI18n()\nconst locale = $getLocale()\nconsole.log(locale) // e.g., 'en'

🌍 $getLocaleName

Version introduced: v1.28.0

  • Type: () => string | null
  • Description: Returns the current locale name from displayName config.
  • Example:
typescript
const locale = $getLocaleName()\n// Output: 'English'

$getLocales

  • Type: () => Locale[]
  • Description: Returns an array of all available locales in the application.
  • Example:
    js
    const { $getLocales } = useI18n()\nconst locales = $getLocales()\nconsole.log(locales) // e.g., [{ code: 'en', iso: 'en-US' }, { code: 'fr', iso: 'fr-FR' }]

$t

  • Type: <T extends Record<string, string | number | boolean>>(key: string, params?: T, defaultValue?: string) => string | number | boolean | Translations | PluralTranslations | unknown[] | unknown | null
  • Description: Translates a given key to the corresponding localized string, optionally replacing placeholders with provided parameters and falling back to a default value if the key is not found.
  • Example:
    js
    const { $t } = useI18n()\nconst greeting = $t('hello', { name: 'John' }, 'Hello!')\nconsole.log(greeting) // e.g., 'Hello, John'

$tc

  • Type: (key: string, count: number, defaultValue?: string) => string
  • Description: Translates a given key with pluralization based on the provided count, optionally falling back to a default value if the key is not found.
  • Example:
    js
    const { $tc } = useI18n()\nconst message = $tc('apples', 3, '3 apples')\nconsole.log(message) // e.g., '3 apples'

$has

  • Type: (key: string) => boolean
  • Description: Checks if a translation key exists for the current locale.
  • Example:
    js
    const { $has } = useI18n()\nconst exists = $has('hello')\nconsole.log(exists) // e.g., true

$mergeTranslations

  • Type: (newTranslations: Translations) => void
  • Description: Merges additional translations into the existing ones for the current locale.
  • Example:
    js
    const { $mergeTranslations } = useI18n()\n$mergeTranslations({\n  hello: 'Hello World',\n})

$switchLocale

  • Type: (locale: string) => void
  • Description: Switches the application's locale to the specified locale.
  • Example:
    js
    const { $switchLocale } = useI18n()\n$switchLocale('fr')

$localeRoute

  • Type: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw
  • Description: Generates a localized route based on the specified route and optionally the specified locale.
  • Example:
    js
    const { $localeRoute } = useI18n()\nconst route = $localeRoute('/about', 'fr')

$loadPageTranslations

  • Type: (locale: string, routeName: string) => Promise<void>
  • Description: Loads translations for the specified page and locale, enabling lazy-loading of translations.
  • Example:
    js
    const { $loadPageTranslations } = useI18n()\nawait $loadPageTranslations('fr', 'home')

🛠️ Example Usages

Basic Locale Retrieval

Retrieve the current locale of the application.

js
const { $getLocale } = useI18n()\nconst locale = $getLocale()

Translation with Parameters

Translate a string with dynamic parameters, with a fallback default value.

js
const { $t } = useI18n()\nconst welcomeMessage = $t('welcome', { name: 'Jane' }, 'Welcome!')

Switching Locales

Switch the application to a different locale.

js
const { $switchLocale } = useI18n()\n$switchLocale('de')

Generating a Localized Route

Generate a route localized to the current or specified locale.

js
const { $localeRoute } = useI18n()\nconst route = $localeRoute('/about', 'fr')

Loading Page-Specific Translations

Lazy-load translations for a specific page and locale.

js
const { $loadPageTranslations } = useI18n()\nawait $loadPageTranslations('de', 'dashboard')
',43)]))}const c=i(n,[["render",l]]);export{g as __pageData,c as default}; diff --git a/assets/composables_useI18n.md.CtJaYII6.lean.js b/assets/composables_useI18n.md.CtJaYII6.lean.js new file mode 100644 index 00000000..2ff0d3af --- /dev/null +++ b/assets/composables_useI18n.md.CtJaYII6.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,a2 as t,o as e}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🛠️ useI18n Composable","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"composables/useI18n.md","filePath":"composables/useI18n.md","lastUpdated":1729326320000}'),n={name:"composables/useI18n.md"};function l(h,s,p,k,o,r){return e(),a("div",null,s[0]||(s[0]=[t('

🛠️ useI18n Composable

The useI18n composable in Nuxt I18n Micro is designed to provide an easy and efficient way to access internationalization functionalities within your Nuxt application. It offers a variety of methods to handle localization, translation, and route management based on the current locale.

All methods can be accessed both with and without the $ prefix for convenience.

⚙️ Return Values

The useI18n composable returns an object containing several key methods and properties for managing internationalization:

$getLocale

  • Type: () => string
  • Description: Returns the current locale of the application.
  • Example:
    js
    const { $getLocale } = useI18n()\nconst locale = $getLocale()\nconsole.log(locale) // e.g., 'en'

🌍 $getLocaleName

Version introduced: v1.28.0

  • Type: () => string | null
  • Description: Returns the current locale name from displayName config.
  • Example:
typescript
const locale = $getLocaleName()\n// Output: 'English'

$getLocales

  • Type: () => Locale[]
  • Description: Returns an array of all available locales in the application.
  • Example:
    js
    const { $getLocales } = useI18n()\nconst locales = $getLocales()\nconsole.log(locales) // e.g., [{ code: 'en', iso: 'en-US' }, { code: 'fr', iso: 'fr-FR' }]

$t

  • Type: <T extends Record<string, string | number | boolean>>(key: string, params?: T, defaultValue?: string) => string | number | boolean | Translations | PluralTranslations | unknown[] | unknown | null
  • Description: Translates a given key to the corresponding localized string, optionally replacing placeholders with provided parameters and falling back to a default value if the key is not found.
  • Example:
    js
    const { $t } = useI18n()\nconst greeting = $t('hello', { name: 'John' }, 'Hello!')\nconsole.log(greeting) // e.g., 'Hello, John'

$tc

  • Type: (key: string, count: number, defaultValue?: string) => string
  • Description: Translates a given key with pluralization based on the provided count, optionally falling back to a default value if the key is not found.
  • Example:
    js
    const { $tc } = useI18n()\nconst message = $tc('apples', 3, '3 apples')\nconsole.log(message) // e.g., '3 apples'

$has

  • Type: (key: string) => boolean
  • Description: Checks if a translation key exists for the current locale.
  • Example:
    js
    const { $has } = useI18n()\nconst exists = $has('hello')\nconsole.log(exists) // e.g., true

$mergeTranslations

  • Type: (newTranslations: Translations) => void
  • Description: Merges additional translations into the existing ones for the current locale.
  • Example:
    js
    const { $mergeTranslations } = useI18n()\n$mergeTranslations({\n  hello: 'Hello World',\n})

$switchLocale

  • Type: (locale: string) => void
  • Description: Switches the application's locale to the specified locale.
  • Example:
    js
    const { $switchLocale } = useI18n()\n$switchLocale('fr')

$localeRoute

  • Type: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw
  • Description: Generates a localized route based on the specified route and optionally the specified locale.
  • Example:
    js
    const { $localeRoute } = useI18n()\nconst route = $localeRoute('/about', 'fr')

$loadPageTranslations

  • Type: (locale: string, routeName: string) => Promise<void>
  • Description: Loads translations for the specified page and locale, enabling lazy-loading of translations.
  • Example:
    js
    const { $loadPageTranslations } = useI18n()\nawait $loadPageTranslations('fr', 'home')

🛠️ Example Usages

Basic Locale Retrieval

Retrieve the current locale of the application.

js
const { $getLocale } = useI18n()\nconst locale = $getLocale()

Translation with Parameters

Translate a string with dynamic parameters, with a fallback default value.

js
const { $t } = useI18n()\nconst welcomeMessage = $t('welcome', { name: 'Jane' }, 'Welcome!')

Switching Locales

Switch the application to a different locale.

js
const { $switchLocale } = useI18n()\n$switchLocale('de')

Generating a Localized Route

Generate a route localized to the current or specified locale.

js
const { $localeRoute } = useI18n()\nconst route = $localeRoute('/about', 'fr')

Loading Page-Specific Translations

Lazy-load translations for a specific page and locale.

js
const { $loadPageTranslations } = useI18n()\nawait $loadPageTranslations('de', 'dashboard')
',43)]))}const c=i(n,[["render",l]]);export{g as __pageData,c as default}; diff --git a/assets/composables_useLocaleHead.md.Cw60RGsA.js b/assets/composables_useLocaleHead.md.Cw60RGsA.js new file mode 100644 index 00000000..6cea3416 --- /dev/null +++ b/assets/composables_useLocaleHead.md.Cw60RGsA.js @@ -0,0 +1,21 @@ +import{_ as a,c as e,a2 as i,o as t}from"./chunks/framework.Gfs4HC1t.js";const k=JSON.parse('{"title":"🌍 useLocaleHead Composable","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"composables/useLocaleHead.md","filePath":"composables/useLocaleHead.md","lastUpdated":1724679268000}'),n={name:"composables/useLocaleHead.md"};function l(o,s,d,h,r,p){return t(),e("div",null,s[0]||(s[0]=[i(`

🌍 useLocaleHead Composable

The useLocaleHead composable is a utility in Nuxt I18n Micro that helps you manage SEO attributes and HTML meta tags for localized routes. It dynamically generates attributes for the lang and dir of the HTML document and creates meta and link tags to improve the SEO of your localized content.

⚙️ Options

The useLocaleHead composable accepts an options object to customize its behavior:

addDirAttribute

  • Type: boolean
  • Default: true
  • Description: If true, adds the dir attribute to the HTML document based on the current locale's direction (ltr or rtl).
  • Example:
    js
    const head = useLocaleHead({ addDirAttribute: false })

identifierAttribute

  • Type: string
  • Default: 'id'
  • Description: Specifies the attribute used to identify the generated meta and link tags. This is useful for differentiating tags when inspecting the document head.
  • Example:
    js
    const head = useLocaleHead({ identifierAttribute: 'data-i18n' })

addSeoAttributes

  • Type: boolean
  • Default: true
  • Description: If true, includes SEO-related meta and link tags, such as og:locale, og:url, and hreflang attributes for alternate languages.
  • Example:
    js
    const head = useLocaleHead({ addSeoAttributes: false })

baseUrl

  • Type: string
  • Default: '/'
  • Description: The base URL of your application, used to generate canonical and alternate URLs for SEO purposes.
  • Example:
    js
    const head = useLocaleHead({ baseUrl: 'https://example.com' })

🛠️ Return Values

The useLocaleHead composable returns an object with htmlAttrs, meta, and link properties, which can be directly used in the <head> section of your Nuxt application.

htmlAttrs

  • Type: Record<string, string>
  • Description: Contains attributes to be added to the <html> tag, such as lang and dir.
  • Example:
    js
    const { htmlAttrs } = useLocaleHead()
    +console.log(htmlAttrs)
    +// Output: { lang: 'en-US', dir: 'ltr' }

meta

  • Type: Array<Record<string, string>>
  • Description: Contains meta tags for SEO, including Open Graph locale tags and alternate locales.
  • Example:
    js
    const { meta } = useLocaleHead()
    +console.log(meta)
    +// Output: [{ id: 'i18n-og', property: 'og:locale', content: 'en-US' }, ...]
  • Type: Array<Record<string, string>>
  • Description: Contains link tags for canonical URLs and alternate language versions of the page.
  • Example:
    js
    const { link } = useLocaleHead()
    +console.log(link)
    +// Output: [{ id: 'i18n-can', rel: 'canonical', href: 'https://example.com/about' }, ...]

🛠️ Example Usages

Basic Usage

Generate locale-specific head attributes with default options.

js
const head = useLocaleHead()

Customize Identifier Attribute

Use a custom identifier attribute for the generated tags.

js
const head = useLocaleHead({ identifierAttribute: 'data-i18n' })

Disable SEO Attributes

Generate head attributes without adding SEO-related meta and link tags.

js
const head = useLocaleHead({ addSeoAttributes: false })

Specify a Base URL

Set a custom base URL for canonical and alternate URLs.

js
const head = useLocaleHead({ baseUrl: 'https://mywebsite.com' })

🚀 Additional Features

When addSeoAttributes is enabled, the composable automatically generates the following tags:

  • og:locale for the current locale.
  • og:url for the canonical URL of the page.
  • og:locale:alternate for alternate language versions.
  • rel="canonical" and rel="alternate" links for SEO optimization.

Dynamic Locale and Direction

The composable dynamically determines the lang and dir attributes based on the current route's locale, ensuring that your HTML document is correctly configured for international users.

Handling Localized Routes

If your routes are prefixed with locale codes (e.g., /en/about), the composable intelligently adjusts the full path for generating URLs, ensuring that SEO attributes are accurate and relevant.

This composable simplifies the process of optimizing your Nuxt application for international audiences, ensuring that your site is well-prepared for global search engines and users.

🛠️ Example Usage

The following example demonstrates how to use the useLocaleHead composable within a Vue component with default settings:

vue
<script setup>
+const head = useLocaleHead({
+  addDirAttribute: true,
+  identifierAttribute: 'id',
+  addSeoAttributes: true,
+})
+
+useHead(head)
+</script>
+
+<template>
+  <div>
+    
+  </div>
+</template>

Explanation of the Code

  • useLocaleHead Composable: This composable is called in the <script setup> section and returns an object containing htmlAttrs, meta, and link.

  • <html> Tag: The lang and dir attributes for the HTML document are dynamically determined based on the current locale and are applied to the <html> tag.

  • <head> Section:

    • Meta Tags: SEO-related meta tags are generated, including og:locale, og:url, and rel="canonical" and rel="alternate" tags to specify alternate language versions of the page.
    • Link Tags: Canonical links and links to alternate language versions are included.
  • <body> Section: The main content of the page is displayed here. In this example, a simple header and paragraph are used.

📝 Notes

  1. Attributes: The attributes used (lang, dir, rel, href, hreflang, property, content) are extracted from the object returned by useLocaleHead.

  2. SEO Tags Generation: If the addSeoAttributes option is set to true, the composable automatically generates SEO tags for the current locale.

  3. Base URL: You can set your custom base URL using the baseUrl option to correctly generate canonical and alternate links.

This example demonstrates how easy it is to integrate useLocaleHead into your application's components to ensure correct SEO attributes and improve the search engine indexing of localized pages.

`,50)]))}const g=a(n,[["render",l]]);export{k as __pageData,g as default}; diff --git a/assets/composables_useLocaleHead.md.Cw60RGsA.lean.js b/assets/composables_useLocaleHead.md.Cw60RGsA.lean.js new file mode 100644 index 00000000..6cea3416 --- /dev/null +++ b/assets/composables_useLocaleHead.md.Cw60RGsA.lean.js @@ -0,0 +1,21 @@ +import{_ as a,c as e,a2 as i,o as t}from"./chunks/framework.Gfs4HC1t.js";const k=JSON.parse('{"title":"🌍 useLocaleHead Composable","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"composables/useLocaleHead.md","filePath":"composables/useLocaleHead.md","lastUpdated":1724679268000}'),n={name:"composables/useLocaleHead.md"};function l(o,s,d,h,r,p){return t(),e("div",null,s[0]||(s[0]=[i(`

🌍 useLocaleHead Composable

The useLocaleHead composable is a utility in Nuxt I18n Micro that helps you manage SEO attributes and HTML meta tags for localized routes. It dynamically generates attributes for the lang and dir of the HTML document and creates meta and link tags to improve the SEO of your localized content.

⚙️ Options

The useLocaleHead composable accepts an options object to customize its behavior:

addDirAttribute

  • Type: boolean
  • Default: true
  • Description: If true, adds the dir attribute to the HTML document based on the current locale's direction (ltr or rtl).
  • Example:
    js
    const head = useLocaleHead({ addDirAttribute: false })

identifierAttribute

  • Type: string
  • Default: 'id'
  • Description: Specifies the attribute used to identify the generated meta and link tags. This is useful for differentiating tags when inspecting the document head.
  • Example:
    js
    const head = useLocaleHead({ identifierAttribute: 'data-i18n' })

addSeoAttributes

  • Type: boolean
  • Default: true
  • Description: If true, includes SEO-related meta and link tags, such as og:locale, og:url, and hreflang attributes for alternate languages.
  • Example:
    js
    const head = useLocaleHead({ addSeoAttributes: false })

baseUrl

  • Type: string
  • Default: '/'
  • Description: The base URL of your application, used to generate canonical and alternate URLs for SEO purposes.
  • Example:
    js
    const head = useLocaleHead({ baseUrl: 'https://example.com' })

🛠️ Return Values

The useLocaleHead composable returns an object with htmlAttrs, meta, and link properties, which can be directly used in the <head> section of your Nuxt application.

htmlAttrs

  • Type: Record<string, string>
  • Description: Contains attributes to be added to the <html> tag, such as lang and dir.
  • Example:
    js
    const { htmlAttrs } = useLocaleHead()
    +console.log(htmlAttrs)
    +// Output: { lang: 'en-US', dir: 'ltr' }

meta

  • Type: Array<Record<string, string>>
  • Description: Contains meta tags for SEO, including Open Graph locale tags and alternate locales.
  • Example:
    js
    const { meta } = useLocaleHead()
    +console.log(meta)
    +// Output: [{ id: 'i18n-og', property: 'og:locale', content: 'en-US' }, ...]
  • Type: Array<Record<string, string>>
  • Description: Contains link tags for canonical URLs and alternate language versions of the page.
  • Example:
    js
    const { link } = useLocaleHead()
    +console.log(link)
    +// Output: [{ id: 'i18n-can', rel: 'canonical', href: 'https://example.com/about' }, ...]

🛠️ Example Usages

Basic Usage

Generate locale-specific head attributes with default options.

js
const head = useLocaleHead()

Customize Identifier Attribute

Use a custom identifier attribute for the generated tags.

js
const head = useLocaleHead({ identifierAttribute: 'data-i18n' })

Disable SEO Attributes

Generate head attributes without adding SEO-related meta and link tags.

js
const head = useLocaleHead({ addSeoAttributes: false })

Specify a Base URL

Set a custom base URL for canonical and alternate URLs.

js
const head = useLocaleHead({ baseUrl: 'https://mywebsite.com' })

🚀 Additional Features

When addSeoAttributes is enabled, the composable automatically generates the following tags:

  • og:locale for the current locale.
  • og:url for the canonical URL of the page.
  • og:locale:alternate for alternate language versions.
  • rel="canonical" and rel="alternate" links for SEO optimization.

Dynamic Locale and Direction

The composable dynamically determines the lang and dir attributes based on the current route's locale, ensuring that your HTML document is correctly configured for international users.

Handling Localized Routes

If your routes are prefixed with locale codes (e.g., /en/about), the composable intelligently adjusts the full path for generating URLs, ensuring that SEO attributes are accurate and relevant.

This composable simplifies the process of optimizing your Nuxt application for international audiences, ensuring that your site is well-prepared for global search engines and users.

🛠️ Example Usage

The following example demonstrates how to use the useLocaleHead composable within a Vue component with default settings:

vue
<script setup>
+const head = useLocaleHead({
+  addDirAttribute: true,
+  identifierAttribute: 'id',
+  addSeoAttributes: true,
+})
+
+useHead(head)
+</script>
+
+<template>
+  <div>
+    
+  </div>
+</template>

Explanation of the Code

  • useLocaleHead Composable: This composable is called in the <script setup> section and returns an object containing htmlAttrs, meta, and link.

  • <html> Tag: The lang and dir attributes for the HTML document are dynamically determined based on the current locale and are applied to the <html> tag.

  • <head> Section:

    • Meta Tags: SEO-related meta tags are generated, including og:locale, og:url, and rel="canonical" and rel="alternate" tags to specify alternate language versions of the page.
    • Link Tags: Canonical links and links to alternate language versions are included.
  • <body> Section: The main content of the page is displayed here. In this example, a simple header and paragraph are used.

📝 Notes

  1. Attributes: The attributes used (lang, dir, rel, href, hreflang, property, content) are extracted from the object returned by useLocaleHead.

  2. SEO Tags Generation: If the addSeoAttributes option is set to true, the composable automatically generates SEO tags for the current locale.

  3. Base URL: You can set your custom base URL using the baseUrl option to correctly generate canonical and alternate links.

This example demonstrates how easy it is to integrate useLocaleHead into your application's components to ensure correct SEO attributes and improve the search engine indexing of localized pages.

`,50)]))}const g=a(n,[["render",l]]);export{k as __pageData,g as default}; diff --git a/assets/examples.md.DfpJSwPq.js b/assets/examples.md.DfpJSwPq.js new file mode 100644 index 00000000..e739ac33 --- /dev/null +++ b/assets/examples.md.DfpJSwPq.js @@ -0,0 +1,260 @@ +import{_ as i,c as a,a2 as n,o as t}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"📚 Nuxt I18n Micro Examples and Usage","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"examples.md","filePath":"examples.md","lastUpdated":1736501267000}'),h={name:"examples.md"};function l(k,s,p,e,E,r){return t(),a("div",null,s[0]||(s[0]=[n(`

📚 Nuxt I18n Micro Examples and Usage

This section provides various examples demonstrating how to use Nuxt I18n Micro in your Nuxt.js application. You'll see how to switch locales, use the <i18n-link>, <i18n-switcher>, and <i18n-t> components, and dynamically handle translation keys.

🛠️ Basic Setup

Here's a basic setup to get started with Nuxt I18n Micro:

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n-micro'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr', disabled: false, displayName: 'English' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr', disabled: false, displayName: 'Français' },
+      { code: 'de', iso: 'de-DE', dir: 'ltr', disabled: false, displayName: 'Deutsch' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

🌍 Locale Switching

Switching Locales Programmatically

This example demonstrates how to switch locales programmatically using buttons:

vue
<template>
+  <div>
+    <p>Current Locale: {{ $getLocale() }}</p>
+    <div>
+      <button
+        v-for="locale in $getLocales()"
+        :key="locale.code"
+        :disabled="locale.code === $getLocale()"
+        @click="() => $switchLocale(locale.code)"
+      >
+        Switch to {{ $t(locale.code) }}
+      </button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $t } = useNuxtApp()
+</script>

Example JSON for Locale Switching

json
{
+  "en": "English",
+  "fr": "Français",
+  "de": "Deutsch"
+}

Using <i18n-switcher> Component

The <i18n-switcher> component provides a dropdown for locale switching with customizable labels:

vue
<template>
+  <div>
+    <i18n-switcher
+      :custom-labels="{ en: 'English', fr: 'Français', de: 'Deutsch' }"
+    />
+  </div>
+</template>

The <i18n-link> component automatically handles locale-specific routing:

vue
<template>
+  <div>
+    <i18n-link to="/about">{{ $t('about') }}</i18n-link>
+    <i18n-link :to="{ name: 'index' }">{{ $t('home') }}</i18n-link>
+  </div>
+</template>
+
+<script setup>
+  import { useNuxtApp } from '#imports'
+
+  const { $getLocale, $switchLocale, $getLocales, $t } = useNuxtApp()
+</script>
json
{
+  "about": "About Us",
+  "home": "Home"
+}
vue
<template>
+  <div>
+    <i18n-link to="/about" activeClass="current">About Us</i18n-link>
+  </div>
+</template>

The same JSON file can be used as in the previous example for this scenario.

📝 Rendering Dynamic Keys from Translation Files

In some scenarios, you may want to iterate over dynamic keys stored within your translation files and render their values conditionally. The example below demonstrates how to achieve this using Nuxt I18n Micro.

Example: Rendering Dynamic Keys

This example fetches an array of keys from a specific translation path (in this case, dynamic) and iterates over them. Each key is checked for its existence using $has before rendering its value with $t.

vue
<template>
+  <div>
+    <div
+      v-for="key in $t('dynamic')"
+      :key="key"
+    >
+      <p>{{ key }}: <span v-if="$has(key)">{{ $t(key) }}</span></p>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $t, $has } = useNuxtApp()
+</script>

Example Translation File (en.json)

json
{
+  "dynamic": ["key1", "key2", "key3"],
+  "key1": "This is the first key's value",
+  "key2": "This is the second key's value",
+  "key3": "This is the third key's value"
+}

Example: Rendering Dynamic Keys from an Object

In this example, we handle an object stored within your translation file. We fetch and iterate over the keys of the object, dynamically rendering both the key names and their associated values.

vue
<template>
+  <div>
+    <div v-for="(value, key) in $t('dynamicObject')" :key="key">
+      <p>{{ key }}: {{ value }}</p>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $t } = useNuxtApp()
+</script>

Example Translation File (en.json)

json
{
+  "dynamicObject": {
+    "title": "Welcome to our site",
+    "description": "This is a brief description of our services.",
+    "footerNote": "Thank you for visiting!"
+  }
+}

🌟 Using <i18n-t> for Translations with Slots and Interpolation

The <i18n-t> component is useful for rendering translations with dynamic content and HTML tags:

vue
<template>
+  <i18n-t keypath="greeting" tag="h1">
+    <template #default="{ translation }">
+      <strong>{{ translation.replace('page', 'page replace') }}</strong> <i>!!!</i>
+    </template>
+  </i18n-t>
+</template>

Example JSON for <i18n-t>

json
{
+  "greeting": "Welcome to the page"
+}

With Interpolation

vue
<template>
+  <i18n-t keypath="welcome" :params="{ username: 'Alice', unreadCount: 5 }"></i18n-t>
+</template>

Example JSON for Interpolation

json
{
+  "welcome": "Hello {username}, you have {unreadCount} unread messages."
+}

📝 Comprehensive Example with Nested Sections

Here's a complex structure demonstrating multiple translation uses within a single page:

vue
<template>
+  <div>
+    <h1>{{ $t('mainHeader') }}</h1>
+
+    <nav>
+      <ul>
+        <li><a href="#">{{ $t('nav.home') }}</a></li>
+        <li><a href="#">{{ $t('nav.about') }}</a></li>
+        <li><a href="#">{{ $t('nav.services') }}</a></li>
+        <li><a href="#">{{ $t('nav.contact') }}</a></li>
+      </ul>
+    </nav>
+
+    <section>
+      <h2>{{ $t('section1.header') }}</h2>
+      <p>{{ $t('section1.intro') }}</p>
+
+      <div>
+        <h3>{{ $t('section1.subsection1.header') }}</h3>
+        <p>{{ $t('section1.subsection1.content') }}</p>
+      </div>
+
+      <div>
+        <h3>{{ $t('section1.subsection2.header') }}</h3>
+        <ul>
+          <li>{{ $t('section1.subsection2.item1') }}</li>
+          <li>{{ $t('section1.subsection2.item2') }}</li>
+          <li>{{ $t('section1.subsection2.item3') }}</li>
+        </ul>
+      </div>
+    </section>
+
+    <footer>
+      <h4>{{ $t('footer.contact.header') }}</h4>
+      <address>
+        {{ $t('footer.contact.address') }}<br>
+        {{ $t('footer.contact.city') }}<br>
+        {{ $t('footer.contact.phone') }}
+      </address>
+    </footer>
+
+    <div>
+      <button
+        v-for="locale in $getLocales()"
+        :key="locale.code"
+        :disabled="locale.code === $getLocale()"
+        @click="() => $switchLocale(locale.code)"
+      >
+        Switch to {{ locale.code }}
+      </button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $t } = useNuxtApp()
+</script>

Example JSON for Nested Sections

json
{
+  "mainHeader": "Welcome to Our Services",
+  "nav": {
+    "home": "Home",
+    "about": "About Us",
+    "services": "Services",
+    "contact": "Contact"
+  },
+  "section1": {
+    "header": "Our Expertise",
+    "intro": "We provide a wide range of services to meet your needs.",
+    "subsection1": {
+      "header": "Consulting",
+      "content": "Our team offers expert consulting services in various domains."
+    },
+    "subsection2": {
+      "header": "Development",
+      "item1":
+
+ "Web Development",
+      "item2": "Mobile Apps",
+      "item3": "Custom Software"
+    }
+  },
+  "footer": {
+    "contact": {
+      "header": "Contact Us",
+      "address": "123 Main Street",
+      "city": "Anytown, USA",
+      "phone": "+1 (555) 123-4567"
+    }
+  }
+}

🌟 Using $tc for Pluralization

The $tc function in Nuxt I18n Micro handles pluralization based on the count and locale settings. This is useful for dynamically adjusting messages that involve counts, such as items, notifications, or other entities that can vary in number.

Example: Using $tc for Pluralization

In the following example, we display a message indicating the number of apples using $tc. The translation key handles multiple plural forms based on the count provided.

vue
<template>
+  <div>
+    <!-- Display a pluralized message about the number of apples -->
+    <p>{{ $tc('apples', 0) }}</p>  <!-- Outputs: no apples -->
+    <p>{{ $tc('apples', 1) }}</p>  <!-- Outputs: one apple -->
+    <p>{{ $tc('apples', 10) }}</p> <!-- Outputs: 10 apples -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $tc } = useNuxtApp()
+</script>

Example JSON for Pluralization

Here's how you can define the translation in your JSON file to handle different plural forms:

json
{
+  "apples": "no apples | one apple | {count} apples"
+}

Explanation

  • $tc('apples', 0): Returns the first form, used when the count is zero ("no apples").
  • $tc('apples', 1): Returns the second form, used when the count is one ("one apple").
  • $tc('apples', 10): Returns the third form with the count value, used when the count is two or more ("10 apples").

Additional Example with More Complex Pluralization

If your application needs to handle more complex pluralization rules (e.g., specific cases for zero, one, two, few, many, other), you can extend the translation strings accordingly:

json
{
+  "apples": "no apples | one apple | two apples | a few apples | many apples | {count} apples"
+}
  • $tc('apples', 2): Could be set up to return "two apples".
  • $tc('apples', 3): Could return "a few apples", depending on the rules defined for the count.

🌐 Using $tn for Number Formatting

The $tn function formats numbers according to the current locale using the Intl.NumberFormat API. This is useful for displaying numbers in a way that matches the user's regional settings, such as currency, percentages, or other number formats.

Example: Using $tn for Number Formatting

vue
<template>
+  <div>
+    <!-- Format a number as currency -->
+    <p>{{ $tn(1234567.89, { style: 'currency', currency: 'USD' }) }}</p> <!-- Outputs: $1,234,567.89 in 'en-US' locale -->
+
+    <!-- Format a number with custom options -->
+    <p>{{ $tn(0.567, { style: 'percent', minimumFractionDigits: 1 }) }}</p> <!-- Outputs: 56.7% in 'en-US' locale -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $tn } = useNuxtApp()
+</script>

🗓️ Using $td for Date and Time Formatting

The $td function formats dates and times according to the current locale using the Intl.DateTimeFormat API. This is useful for displaying dates and times in formats that are familiar to the user based on their locale settings.

Example: Using $td for Date and Time Formatting

vue
<template>
+  <div>
+    <!-- Format a date with full options -->
+    <p>{{ $td(new Date(), { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }) }}</p> <!-- Outputs: "Friday, September 1, 2023" in 'en-US' locale -->
+
+    <!-- Format a date with time -->
+    <p>{{ $td(new Date(), { hour: '2-digit', minute: '2-digit', second: '2-digit' }) }}</p> <!-- Outputs: "10:15:30 AM" in 'en-US' locale -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $td } = useNuxtApp()
+</script>

🗓️ Using $tdr for Relative Date Formatting

The $tdr function formats dates as relative times (e.g., "5 minutes ago", "2 days ago") according to the current locale using the Intl.RelativeTimeFormat API. This is useful for displaying time differences relative to the current date and time.

Example: Using $tdr for Relative Date Formatting

vue
<template>
+  <div>
+    <!-- Format a date as a relative time -->
+    <p>{{ $tdr(new Date(Date.now() - 1000 * 60 * 5)) }}</p> <!-- Outputs: "5 minutes ago" in 'en-US' locale -->
+
+    <!-- Format a date that is in the future -->
+    <p>{{ $tdr(new Date(Date.now() + 1000 * 60 * 60 * 24)) }}</p> <!-- Outputs: "in 1 day" in 'en-US' locale -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $tdr } = useNuxtApp()
+</script>
`,75)]))}const y=i(h,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/examples.md.DfpJSwPq.lean.js b/assets/examples.md.DfpJSwPq.lean.js new file mode 100644 index 00000000..e739ac33 --- /dev/null +++ b/assets/examples.md.DfpJSwPq.lean.js @@ -0,0 +1,260 @@ +import{_ as i,c as a,a2 as n,o as t}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"📚 Nuxt I18n Micro Examples and Usage","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"examples.md","filePath":"examples.md","lastUpdated":1736501267000}'),h={name:"examples.md"};function l(k,s,p,e,E,r){return t(),a("div",null,s[0]||(s[0]=[n(`

📚 Nuxt I18n Micro Examples and Usage

This section provides various examples demonstrating how to use Nuxt I18n Micro in your Nuxt.js application. You'll see how to switch locales, use the <i18n-link>, <i18n-switcher>, and <i18n-t> components, and dynamically handle translation keys.

🛠️ Basic Setup

Here's a basic setup to get started with Nuxt I18n Micro:

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n-micro'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr', disabled: false, displayName: 'English' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr', disabled: false, displayName: 'Français' },
+      { code: 'de', iso: 'de-DE', dir: 'ltr', disabled: false, displayName: 'Deutsch' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

🌍 Locale Switching

Switching Locales Programmatically

This example demonstrates how to switch locales programmatically using buttons:

vue
<template>
+  <div>
+    <p>Current Locale: {{ $getLocale() }}</p>
+    <div>
+      <button
+        v-for="locale in $getLocales()"
+        :key="locale.code"
+        :disabled="locale.code === $getLocale()"
+        @click="() => $switchLocale(locale.code)"
+      >
+        Switch to {{ $t(locale.code) }}
+      </button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $t } = useNuxtApp()
+</script>

Example JSON for Locale Switching

json
{
+  "en": "English",
+  "fr": "Français",
+  "de": "Deutsch"
+}

Using <i18n-switcher> Component

The <i18n-switcher> component provides a dropdown for locale switching with customizable labels:

vue
<template>
+  <div>
+    <i18n-switcher
+      :custom-labels="{ en: 'English', fr: 'Français', de: 'Deutsch' }"
+    />
+  </div>
+</template>

The <i18n-link> component automatically handles locale-specific routing:

vue
<template>
+  <div>
+    <i18n-link to="/about">{{ $t('about') }}</i18n-link>
+    <i18n-link :to="{ name: 'index' }">{{ $t('home') }}</i18n-link>
+  </div>
+</template>
+
+<script setup>
+  import { useNuxtApp } from '#imports'
+
+  const { $getLocale, $switchLocale, $getLocales, $t } = useNuxtApp()
+</script>
json
{
+  "about": "About Us",
+  "home": "Home"
+}
vue
<template>
+  <div>
+    <i18n-link to="/about" activeClass="current">About Us</i18n-link>
+  </div>
+</template>

The same JSON file can be used as in the previous example for this scenario.

📝 Rendering Dynamic Keys from Translation Files

In some scenarios, you may want to iterate over dynamic keys stored within your translation files and render their values conditionally. The example below demonstrates how to achieve this using Nuxt I18n Micro.

Example: Rendering Dynamic Keys

This example fetches an array of keys from a specific translation path (in this case, dynamic) and iterates over them. Each key is checked for its existence using $has before rendering its value with $t.

vue
<template>
+  <div>
+    <div
+      v-for="key in $t('dynamic')"
+      :key="key"
+    >
+      <p>{{ key }}: <span v-if="$has(key)">{{ $t(key) }}</span></p>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $t, $has } = useNuxtApp()
+</script>

Example Translation File (en.json)

json
{
+  "dynamic": ["key1", "key2", "key3"],
+  "key1": "This is the first key's value",
+  "key2": "This is the second key's value",
+  "key3": "This is the third key's value"
+}

Example: Rendering Dynamic Keys from an Object

In this example, we handle an object stored within your translation file. We fetch and iterate over the keys of the object, dynamically rendering both the key names and their associated values.

vue
<template>
+  <div>
+    <div v-for="(value, key) in $t('dynamicObject')" :key="key">
+      <p>{{ key }}: {{ value }}</p>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $t } = useNuxtApp()
+</script>

Example Translation File (en.json)

json
{
+  "dynamicObject": {
+    "title": "Welcome to our site",
+    "description": "This is a brief description of our services.",
+    "footerNote": "Thank you for visiting!"
+  }
+}

🌟 Using <i18n-t> for Translations with Slots and Interpolation

The <i18n-t> component is useful for rendering translations with dynamic content and HTML tags:

vue
<template>
+  <i18n-t keypath="greeting" tag="h1">
+    <template #default="{ translation }">
+      <strong>{{ translation.replace('page', 'page replace') }}</strong> <i>!!!</i>
+    </template>
+  </i18n-t>
+</template>

Example JSON for <i18n-t>

json
{
+  "greeting": "Welcome to the page"
+}

With Interpolation

vue
<template>
+  <i18n-t keypath="welcome" :params="{ username: 'Alice', unreadCount: 5 }"></i18n-t>
+</template>

Example JSON for Interpolation

json
{
+  "welcome": "Hello {username}, you have {unreadCount} unread messages."
+}

📝 Comprehensive Example with Nested Sections

Here's a complex structure demonstrating multiple translation uses within a single page:

vue
<template>
+  <div>
+    <h1>{{ $t('mainHeader') }}</h1>
+
+    <nav>
+      <ul>
+        <li><a href="#">{{ $t('nav.home') }}</a></li>
+        <li><a href="#">{{ $t('nav.about') }}</a></li>
+        <li><a href="#">{{ $t('nav.services') }}</a></li>
+        <li><a href="#">{{ $t('nav.contact') }}</a></li>
+      </ul>
+    </nav>
+
+    <section>
+      <h2>{{ $t('section1.header') }}</h2>
+      <p>{{ $t('section1.intro') }}</p>
+
+      <div>
+        <h3>{{ $t('section1.subsection1.header') }}</h3>
+        <p>{{ $t('section1.subsection1.content') }}</p>
+      </div>
+
+      <div>
+        <h3>{{ $t('section1.subsection2.header') }}</h3>
+        <ul>
+          <li>{{ $t('section1.subsection2.item1') }}</li>
+          <li>{{ $t('section1.subsection2.item2') }}</li>
+          <li>{{ $t('section1.subsection2.item3') }}</li>
+        </ul>
+      </div>
+    </section>
+
+    <footer>
+      <h4>{{ $t('footer.contact.header') }}</h4>
+      <address>
+        {{ $t('footer.contact.address') }}<br>
+        {{ $t('footer.contact.city') }}<br>
+        {{ $t('footer.contact.phone') }}
+      </address>
+    </footer>
+
+    <div>
+      <button
+        v-for="locale in $getLocales()"
+        :key="locale.code"
+        :disabled="locale.code === $getLocale()"
+        @click="() => $switchLocale(locale.code)"
+      >
+        Switch to {{ locale.code }}
+      </button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $t } = useNuxtApp()
+</script>

Example JSON for Nested Sections

json
{
+  "mainHeader": "Welcome to Our Services",
+  "nav": {
+    "home": "Home",
+    "about": "About Us",
+    "services": "Services",
+    "contact": "Contact"
+  },
+  "section1": {
+    "header": "Our Expertise",
+    "intro": "We provide a wide range of services to meet your needs.",
+    "subsection1": {
+      "header": "Consulting",
+      "content": "Our team offers expert consulting services in various domains."
+    },
+    "subsection2": {
+      "header": "Development",
+      "item1":
+
+ "Web Development",
+      "item2": "Mobile Apps",
+      "item3": "Custom Software"
+    }
+  },
+  "footer": {
+    "contact": {
+      "header": "Contact Us",
+      "address": "123 Main Street",
+      "city": "Anytown, USA",
+      "phone": "+1 (555) 123-4567"
+    }
+  }
+}

🌟 Using $tc for Pluralization

The $tc function in Nuxt I18n Micro handles pluralization based on the count and locale settings. This is useful for dynamically adjusting messages that involve counts, such as items, notifications, or other entities that can vary in number.

Example: Using $tc for Pluralization

In the following example, we display a message indicating the number of apples using $tc. The translation key handles multiple plural forms based on the count provided.

vue
<template>
+  <div>
+    <!-- Display a pluralized message about the number of apples -->
+    <p>{{ $tc('apples', 0) }}</p>  <!-- Outputs: no apples -->
+    <p>{{ $tc('apples', 1) }}</p>  <!-- Outputs: one apple -->
+    <p>{{ $tc('apples', 10) }}</p> <!-- Outputs: 10 apples -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $tc } = useNuxtApp()
+</script>

Example JSON for Pluralization

Here's how you can define the translation in your JSON file to handle different plural forms:

json
{
+  "apples": "no apples | one apple | {count} apples"
+}

Explanation

  • $tc('apples', 0): Returns the first form, used when the count is zero ("no apples").
  • $tc('apples', 1): Returns the second form, used when the count is one ("one apple").
  • $tc('apples', 10): Returns the third form with the count value, used when the count is two or more ("10 apples").

Additional Example with More Complex Pluralization

If your application needs to handle more complex pluralization rules (e.g., specific cases for zero, one, two, few, many, other), you can extend the translation strings accordingly:

json
{
+  "apples": "no apples | one apple | two apples | a few apples | many apples | {count} apples"
+}
  • $tc('apples', 2): Could be set up to return "two apples".
  • $tc('apples', 3): Could return "a few apples", depending on the rules defined for the count.

🌐 Using $tn for Number Formatting

The $tn function formats numbers according to the current locale using the Intl.NumberFormat API. This is useful for displaying numbers in a way that matches the user's regional settings, such as currency, percentages, or other number formats.

Example: Using $tn for Number Formatting

vue
<template>
+  <div>
+    <!-- Format a number as currency -->
+    <p>{{ $tn(1234567.89, { style: 'currency', currency: 'USD' }) }}</p> <!-- Outputs: $1,234,567.89 in 'en-US' locale -->
+
+    <!-- Format a number with custom options -->
+    <p>{{ $tn(0.567, { style: 'percent', minimumFractionDigits: 1 }) }}</p> <!-- Outputs: 56.7% in 'en-US' locale -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $tn } = useNuxtApp()
+</script>

🗓️ Using $td for Date and Time Formatting

The $td function formats dates and times according to the current locale using the Intl.DateTimeFormat API. This is useful for displaying dates and times in formats that are familiar to the user based on their locale settings.

Example: Using $td for Date and Time Formatting

vue
<template>
+  <div>
+    <!-- Format a date with full options -->
+    <p>{{ $td(new Date(), { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }) }}</p> <!-- Outputs: "Friday, September 1, 2023" in 'en-US' locale -->
+
+    <!-- Format a date with time -->
+    <p>{{ $td(new Date(), { hour: '2-digit', minute: '2-digit', second: '2-digit' }) }}</p> <!-- Outputs: "10:15:30 AM" in 'en-US' locale -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $td } = useNuxtApp()
+</script>

🗓️ Using $tdr for Relative Date Formatting

The $tdr function formats dates as relative times (e.g., "5 minutes ago", "2 days ago") according to the current locale using the Intl.RelativeTimeFormat API. This is useful for displaying time differences relative to the current date and time.

Example: Using $tdr for Relative Date Formatting

vue
<template>
+  <div>
+    <!-- Format a date as a relative time -->
+    <p>{{ $tdr(new Date(Date.now() - 1000 * 60 * 5)) }}</p> <!-- Outputs: "5 minutes ago" in 'en-US' locale -->
+
+    <!-- Format a date that is in the future -->
+    <p>{{ $tdr(new Date(Date.now() + 1000 * 60 * 60 * 24)) }}</p> <!-- Outputs: "in 1 day" in 'en-US' locale -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $tdr } = useNuxtApp()
+</script>
`,75)]))}const y=i(h,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/guide_cli.md.DbExMDtf.js b/assets/guide_cli.md.DbExMDtf.js new file mode 100644 index 00000000..a683c90f --- /dev/null +++ b/assets/guide_cli.md.DbExMDtf.js @@ -0,0 +1 @@ +import{_ as i}from"./chunks/text-to-i18n.CC9iMeyu.js";import{_ as a,c as e,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const u=JSON.parse('{"title":"🌐 nuxt-i18n-micro-cli Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/cli.md","filePath":"guide/cli.md","lastUpdated":1735022684000}'),l={name:"guide/cli.md"};function o(p,s,r,h,d,c){return n(),e("div",null,s[0]||(s[0]=[t('

🌐 nuxt-i18n-micro-cli Guide

📖 Introduction

nuxt-i18n-micro-cli is a command-line tool designed to streamline the localization and internationalization process in Nuxt.js projects using the nuxt-i18n module. It provides utilities to extract translation keys from your codebase, manage translation files, synchronize translations across locales, and automate the translation process using external translation services.

This guide will walk you through installing, configuring, and using nuxt-i18n-micro-cli to effectively manage your project's translations. Package on npmjs.com.

🔧 Installation and Setup

📦 Installing nuxt-i18n-micro-cli

Install nuxt-i18n-micro-cli globally using npm:

bash
npm install -g nuxt-i18n-micro-cli

This will make the i18n-micro command available globally on your system.

🛠 Initializing in Your Project

After installing, you can run i18n-micro commands in your Nuxt.js project directory.

Ensure that your project is set up with nuxt-i18n and has the necessary configuration in nuxt.config.js.

📄 Common Arguments

  • --cwd: Specify the current working directory (defaults to .).
  • --logLevel: Set the log level (silent, info, verbose).
  • --translationDir: Directory containing JSON translation files (default: locales).

📋 Commands

🔄 text-to-i18n Command

Version introduced: v1.1.0

DevTools

Description: The text-to-i18n command automatically scans your codebase for hardcoded text strings and replaces them with i18n translation references. It extracts text from Vue templates, JavaScript, and TypeScript files, generating translation keys and updating your translation files.

Usage:

bash
i18n-micro text-to-i18n [options]

Options:

  • --translationFile: Path to the JSON file containing translations (default: locales/en.json).
  • --context: Context prefix for translation keys. Helps organize translations by feature or section.
  • --dryRun: Show changes without modifying files (default: false).
  • --verbose: Show detailed processing information (default: false).
  • --path: Path to a specific file to process (e.g., ./pages/test-page.vue). When provided, only the specified file is processed.

Example:

bash
i18n-micro text-to-i18n --translationFile locales/en.json --context auth

How it works:

  1. File Collection:
  • Scans directories: pages, components, and plugins
  • Processes files with extensions: .vue, .js, and .ts
  1. Text Processing:
  • Extracts text from Vue templates and script files
  • Identifies translatable strings
  • Generates unique translation keys based on:
    • File path
    • Text content
    • Context prefix (if provided)
  1. Translation Management:
  • Creates new translation entries
  • Maintains nested structure in translation files
  • Preserves existing translations
  • Updates translation files with new entries

Example Transformations:

Before:

vue
<template>\n  <div>\n    <h1>Welcome to our site</h1>\n    <p>Please sign in to continue</p>\n  </div>\n</template>

After:

vue
<template>\n  <div>\n    <h1>{{ $t('pages.home.welcome_to_our_site') }}</h1>\n    <p>{{ $t('pages.home.please_sign_in') }}</p>\n  </div>\n</template>

Best Practices:

  1. Run in Dry Mode First:

    bash
    i18n-micro text-to-i18n --dryRun

    This shows what changes would be made without modifying files.

  2. Use Context for Organization:

    bash
    i18n-micro text-to-i18n --context auth

    Prefixes translation keys with auth. for better organization.

  3. Review Changes:

  • Enable verbose mode to see detailed changes
  • Check generated translation keys
  • Verify extracted text accuracy
  1. Backup Files:
  • Always backup your files before running the command
  • Use version control to track changes

Notes:

  • The command preserves existing translations and keys
  • Generated keys are based on file paths and text content
  • Supports Vue template syntax and JavaScript/TypeScript files
  • Handles both simple text and attribute translations
  • Maintains nested translation structure

📊 stats Command

Description: The stats command is used to display translation statistics for each locale in your Nuxt.js project. It helps you understand the progress of your translations by showing how many keys are translated compared to the total number of keys available.

Usage:

bash
i18n-micro stats [options]

Options:

  • --full: Display combined translations statistics only (default: false).

Example:

bash
i18n-micro stats --full

🌍 translate Command

Description: The translate command automatically translates missing keys using external translation services. This command simplifies the translation process by leveraging APIs from services like Google Translate, DeepL, and others to fill in missing translations.

Usage:

bash
i18n-micro translate [options]

Options:

  • --service: Translation service to use (e.g., google, deepl, yandex). If not specified, the command will prompt you to select one.
  • --token: API key corresponding to the chosen translation service. If not provided, you will be prompted to enter it.
  • --options: Additional options for the translation service, provided as key:value pairs, separated by commas (e.g., model:gpt-3.5-turbo,max_tokens:1000).
  • --replace: Translate all keys, replacing existing translations (default: false).

Example:

bash
i18n-micro translate --service deepl --token YOUR_DEEPL_API_KEY

🌐 Supported Translation Services

The translate command supports multiple translation services. Some of the supported services are:

  • Google Translate (google)
  • DeepL (deepl)
  • Yandex Translate (yandex)
  • OpenAI (openai)
  • Azure Translator (azure)
  • IBM Watson (ibm)
  • Baidu Translate (baidu)
  • LibreTranslate (libretranslate)
  • MyMemory (mymemory)
  • Lingva Translate (lingvatranslate)
  • Papago (papago)
  • Tencent Translate (tencent)
  • Systran Translate (systran)
  • Yandex Cloud Translate (yandexcloud)
  • ModernMT (modernmt)
  • Lilt (lilt)
  • Unbabel (unbabel)
  • Reverso Translate (reverso)

⚙️ Service Configuration

Some services require specific configurations or API keys. When using the translate command, you can specify the service and provide the required --token (API key) and additional --options if needed.

For example:

bash
i18n-micro translate --service openai --token YOUR_OPENAI_API_KEY --options openaiModel:gpt-3.5-turbo,max_tokens:1000

🛠️ extract Command

Description: Extracts translation keys from your codebase and organizes them by scope.

Usage:

bash
i18n-micro extract [options]

Options:

  • --prod, -p: Run in production mode.

Example:

bash
i18n-micro extract

🔄 sync Command

Description: Synchronizes translation files across locales, ensuring all locales have the same keys.

Usage:

bash
i18n-micro sync [options]

Example:

bash
i18n-micro sync

validate Command

Description: Validates translation files for missing or extra keys compared to the reference locale.

Usage:

bash
i18n-micro validate [options]

Example:

bash
i18n-micro validate

🧹 clean Command

Description: Removes unused translation keys from translation files.

Usage:

bash
i18n-micro clean [options]

Example:

bash
i18n-micro clean

📤 import Command

Description: Converts PO files back to JSON format and saves them in the translation directory.

Usage:

bash
i18n-micro import [options]

Options:

  • --potsDir: Directory containing PO files (default: pots).

Example:

bash
i18n-micro import --potsDir pots

📥 export Command

Description: Exports translations to PO files for external translation management.

Usage:

bash
i18n-micro export [options]

Options:

  • --potsDir: Directory to save PO files (default: pots).

Example:

bash
i18n-micro export --potsDir pots

🗂️ export-csv Command

Description: The export-csv command exports translation keys and values from JSON files, including their file paths, into a CSV format. This command is useful for teams who prefer working with translation data in spreadsheet software.

Usage:

bash
i18n-micro export-csv [options]

Options:

  • --csvDir: Directory where the exported CSV files will be saved.
  • --delimiter: Specify a delimiter for the CSV file (default: ,).

Example:

bash
i18n-micro export-csv --csvDir csv_files

📑 import-csv Command

Description: The import-csv command imports translation data from CSV files, updating the corresponding JSON files. This is useful for applying bulk translation updates from spreadsheets.

Usage:

bash
i18n-micro import-csv [options]

Options:

  • --csvDir: Directory containing the CSV files to be imported.
  • --delimiter: Specify a delimiter used in the CSV file (default: ,).

Example:

bash
i18n-micro import-csv --csvDir csv_files

🧾 diff Command

Description: Compares translation files between the default locale and other locales within the same directory (including subdirectories). The command identifies missing keys and their values in the default locale compared to other locales, making it easier to track translation progress or discrepancies.

Usage:

bash
i18n-micro diff [options]

Example:

bash
i18n-micro diff

🔍 check-duplicates Command

Description: The check-duplicates command checks for duplicate translation values within each locale across all translation files, including both global and page-specific translations. It ensures that different keys within the same language do not share identical translation values, helping maintain clarity and consistency in your translations.

Usage:

bash
i18n-micro check-duplicates [options]

Example:

bash
i18n-micro check-duplicates

How it works:

  • The command checks both global and page-specific translation files for each locale.
  • If a translation value appears in multiple locations (either within global translations or across different pages), it reports the duplicate values along with the file and key where they are found.
  • If no duplicates are found, the command confirms that the locale is free of duplicated translation values.

This command helps ensure that translation keys maintain unique values, preventing accidental repetition within the same locale.

🔄 replace-values Command

Description: The replace-values command allows you to perform bulk replacements of translation values across all locales. It supports both simple text replacements and advanced replacements using regular expressions (regex). You can also use capturing groups in regex patterns and reference them in the replacement string, making it ideal for more complex replacement scenarios.

Usage:

bash
i18n-micro replace-values [options]

Options:

  • --search: The text or regex pattern to search for in translations. This is a required option.
  • --replace: The replacement text to be used for the found translations. This is a required option.
  • --useRegex: Enable search using a regular expression pattern (default: false).

Example 1: Simple replacement

Replace the string "Hello" with "Hi" across all locales:

bash
i18n-micro replace-values --search "Hello" --replace "Hi"

Example 2: Regex replacement

Enable regex search and replace any string starting with "Hello" followed by numbers (e.g., "Hello123") with "Hi" across all locales:

bash
i18n-micro replace-values --search "Hello\\\\d+" --replace "Hi" --useRegex

Example 3: Using regex capturing groups

Use capturing groups to dynamically insert part of the matched string into the replacement. For example, replace "Hello [name]" with "Hi [name]" while keeping the name intact:

bash
i18n-micro replace-values --search "Hello (\\\\w+)" --replace "Hi $1" --useRegex

In this case, $1 refers to the first capturing group, which matches the [name] part after "Hello". The replacement will keep the name from the original string.

How it works:

  • The command scans through all translation files (both global and page-specific).
  • When a match is found based on the search string or regex pattern, it replaces the matched text with the provided replacement.
  • When using regex, capturing groups can be used in the replacement string by referencing them with $1, $2, etc.
  • All changes are logged, showing the file path, translation key, and the before/after state of the translation value.

Logging: For each replacement, the command logs details including:

  • Locale and file path
  • The translation key being modified
  • The old value and the new value after replacement
  • If using regex with capturing groups, the logs will show the group matches and how they were replaced.

This allows you to track exactly where and what changes were made during the replacement operation, providing a clear history of modifications across your translation files.

🛠 Examples

  • Extracting translations:

    bash
    i18n-micro extract
  • Translating missing keys using Google Translate:

    bash
    i18n-micro translate --service google --token YOUR_GOOGLE_API_KEY
  • Translating all keys, replacing existing translations:

    bash
    i18n-micro translate --service deepl --token YOUR_DEEPL_API_KEY --replace
  • Validating translation files:

    bash
    i18n-micro validate
  • Cleaning unused translation keys:

    bash
    i18n-micro clean
  • Synchronizing translation files:

    bash
    i18n-micro sync

⚙️ Configuration Guide

nuxt-i18n-micro-cli relies on your Nuxt.js i18n configuration in nuxt.config.js. Ensure you have the nuxt-i18n module installed and configured.

🔑 nuxt.config.js Example

js
export default {\n  modules: ['@nuxtjs/i18n'],\n  i18n: {\n    locales: [\n      { code: 'en', iso: 'en-US' },\n      { code: 'fr', iso: 'fr-FR' },\n      { code: 'es', iso: 'es-ES' },\n      // Add other locales as needed\n    ],\n    defaultLocale: 'en',\n    vueI18n: {\n      fallbackLocale: 'en',\n    },\n    // Specify the directory where your translation files are stored\n    translationDir: 'locales',\n  },\n};

Ensure that the translationDir matches the directory used by nuxt-i18n-micro-cli (default is locales).

📝 Best Practices

🔑 Consistent Key Naming

Ensure translation keys are consistent and descriptive to avoid confusion and duplication.

🧹 Regular Maintenance

Use the clean command regularly to remove unused translation keys and keep your translation files clean.

🛠 Automate Translation Workflow

Integrate nuxt-i18n-micro-cli commands into your development workflow or CI/CD pipeline to automate extraction, translation, validation, and synchronization of translation files.

🛡️ Secure API Keys

When using translation services that require API keys, ensure your keys are kept secure and not committed to version control systems. Consider using environment variables or secure key management solutions.

📞 Support and Contributions

If you encounter issues or have suggestions for improvements, feel free to contribute to the project or open an issue on the project's repository.


By following this guide, you'll be able to effectively manage translations in your Nuxt.js project using nuxt-i18n-micro-cli, streamlining your internationalization efforts and ensuring a smooth experience for users in different locales.

',181)]))}const m=a(l,[["render",o]]);export{u as __pageData,m as default}; diff --git a/assets/guide_cli.md.DbExMDtf.lean.js b/assets/guide_cli.md.DbExMDtf.lean.js new file mode 100644 index 00000000..a683c90f --- /dev/null +++ b/assets/guide_cli.md.DbExMDtf.lean.js @@ -0,0 +1 @@ +import{_ as i}from"./chunks/text-to-i18n.CC9iMeyu.js";import{_ as a,c as e,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const u=JSON.parse('{"title":"🌐 nuxt-i18n-micro-cli Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/cli.md","filePath":"guide/cli.md","lastUpdated":1735022684000}'),l={name:"guide/cli.md"};function o(p,s,r,h,d,c){return n(),e("div",null,s[0]||(s[0]=[t('

🌐 nuxt-i18n-micro-cli Guide

📖 Introduction

nuxt-i18n-micro-cli is a command-line tool designed to streamline the localization and internationalization process in Nuxt.js projects using the nuxt-i18n module. It provides utilities to extract translation keys from your codebase, manage translation files, synchronize translations across locales, and automate the translation process using external translation services.

This guide will walk you through installing, configuring, and using nuxt-i18n-micro-cli to effectively manage your project's translations. Package on npmjs.com.

🔧 Installation and Setup

📦 Installing nuxt-i18n-micro-cli

Install nuxt-i18n-micro-cli globally using npm:

bash
npm install -g nuxt-i18n-micro-cli

This will make the i18n-micro command available globally on your system.

🛠 Initializing in Your Project

After installing, you can run i18n-micro commands in your Nuxt.js project directory.

Ensure that your project is set up with nuxt-i18n and has the necessary configuration in nuxt.config.js.

📄 Common Arguments

  • --cwd: Specify the current working directory (defaults to .).
  • --logLevel: Set the log level (silent, info, verbose).
  • --translationDir: Directory containing JSON translation files (default: locales).

📋 Commands

🔄 text-to-i18n Command

Version introduced: v1.1.0

DevTools

Description: The text-to-i18n command automatically scans your codebase for hardcoded text strings and replaces them with i18n translation references. It extracts text from Vue templates, JavaScript, and TypeScript files, generating translation keys and updating your translation files.

Usage:

bash
i18n-micro text-to-i18n [options]

Options:

  • --translationFile: Path to the JSON file containing translations (default: locales/en.json).
  • --context: Context prefix for translation keys. Helps organize translations by feature or section.
  • --dryRun: Show changes without modifying files (default: false).
  • --verbose: Show detailed processing information (default: false).
  • --path: Path to a specific file to process (e.g., ./pages/test-page.vue). When provided, only the specified file is processed.

Example:

bash
i18n-micro text-to-i18n --translationFile locales/en.json --context auth

How it works:

  1. File Collection:
  • Scans directories: pages, components, and plugins
  • Processes files with extensions: .vue, .js, and .ts
  1. Text Processing:
  • Extracts text from Vue templates and script files
  • Identifies translatable strings
  • Generates unique translation keys based on:
    • File path
    • Text content
    • Context prefix (if provided)
  1. Translation Management:
  • Creates new translation entries
  • Maintains nested structure in translation files
  • Preserves existing translations
  • Updates translation files with new entries

Example Transformations:

Before:

vue
<template>\n  <div>\n    <h1>Welcome to our site</h1>\n    <p>Please sign in to continue</p>\n  </div>\n</template>

After:

vue
<template>\n  <div>\n    <h1>{{ $t('pages.home.welcome_to_our_site') }}</h1>\n    <p>{{ $t('pages.home.please_sign_in') }}</p>\n  </div>\n</template>

Best Practices:

  1. Run in Dry Mode First:

    bash
    i18n-micro text-to-i18n --dryRun

    This shows what changes would be made without modifying files.

  2. Use Context for Organization:

    bash
    i18n-micro text-to-i18n --context auth

    Prefixes translation keys with auth. for better organization.

  3. Review Changes:

  • Enable verbose mode to see detailed changes
  • Check generated translation keys
  • Verify extracted text accuracy
  1. Backup Files:
  • Always backup your files before running the command
  • Use version control to track changes

Notes:

  • The command preserves existing translations and keys
  • Generated keys are based on file paths and text content
  • Supports Vue template syntax and JavaScript/TypeScript files
  • Handles both simple text and attribute translations
  • Maintains nested translation structure

📊 stats Command

Description: The stats command is used to display translation statistics for each locale in your Nuxt.js project. It helps you understand the progress of your translations by showing how many keys are translated compared to the total number of keys available.

Usage:

bash
i18n-micro stats [options]

Options:

  • --full: Display combined translations statistics only (default: false).

Example:

bash
i18n-micro stats --full

🌍 translate Command

Description: The translate command automatically translates missing keys using external translation services. This command simplifies the translation process by leveraging APIs from services like Google Translate, DeepL, and others to fill in missing translations.

Usage:

bash
i18n-micro translate [options]

Options:

  • --service: Translation service to use (e.g., google, deepl, yandex). If not specified, the command will prompt you to select one.
  • --token: API key corresponding to the chosen translation service. If not provided, you will be prompted to enter it.
  • --options: Additional options for the translation service, provided as key:value pairs, separated by commas (e.g., model:gpt-3.5-turbo,max_tokens:1000).
  • --replace: Translate all keys, replacing existing translations (default: false).

Example:

bash
i18n-micro translate --service deepl --token YOUR_DEEPL_API_KEY

🌐 Supported Translation Services

The translate command supports multiple translation services. Some of the supported services are:

  • Google Translate (google)
  • DeepL (deepl)
  • Yandex Translate (yandex)
  • OpenAI (openai)
  • Azure Translator (azure)
  • IBM Watson (ibm)
  • Baidu Translate (baidu)
  • LibreTranslate (libretranslate)
  • MyMemory (mymemory)
  • Lingva Translate (lingvatranslate)
  • Papago (papago)
  • Tencent Translate (tencent)
  • Systran Translate (systran)
  • Yandex Cloud Translate (yandexcloud)
  • ModernMT (modernmt)
  • Lilt (lilt)
  • Unbabel (unbabel)
  • Reverso Translate (reverso)

⚙️ Service Configuration

Some services require specific configurations or API keys. When using the translate command, you can specify the service and provide the required --token (API key) and additional --options if needed.

For example:

bash
i18n-micro translate --service openai --token YOUR_OPENAI_API_KEY --options openaiModel:gpt-3.5-turbo,max_tokens:1000

🛠️ extract Command

Description: Extracts translation keys from your codebase and organizes them by scope.

Usage:

bash
i18n-micro extract [options]

Options:

  • --prod, -p: Run in production mode.

Example:

bash
i18n-micro extract

🔄 sync Command

Description: Synchronizes translation files across locales, ensuring all locales have the same keys.

Usage:

bash
i18n-micro sync [options]

Example:

bash
i18n-micro sync

validate Command

Description: Validates translation files for missing or extra keys compared to the reference locale.

Usage:

bash
i18n-micro validate [options]

Example:

bash
i18n-micro validate

🧹 clean Command

Description: Removes unused translation keys from translation files.

Usage:

bash
i18n-micro clean [options]

Example:

bash
i18n-micro clean

📤 import Command

Description: Converts PO files back to JSON format and saves them in the translation directory.

Usage:

bash
i18n-micro import [options]

Options:

  • --potsDir: Directory containing PO files (default: pots).

Example:

bash
i18n-micro import --potsDir pots

📥 export Command

Description: Exports translations to PO files for external translation management.

Usage:

bash
i18n-micro export [options]

Options:

  • --potsDir: Directory to save PO files (default: pots).

Example:

bash
i18n-micro export --potsDir pots

🗂️ export-csv Command

Description: The export-csv command exports translation keys and values from JSON files, including their file paths, into a CSV format. This command is useful for teams who prefer working with translation data in spreadsheet software.

Usage:

bash
i18n-micro export-csv [options]

Options:

  • --csvDir: Directory where the exported CSV files will be saved.
  • --delimiter: Specify a delimiter for the CSV file (default: ,).

Example:

bash
i18n-micro export-csv --csvDir csv_files

📑 import-csv Command

Description: The import-csv command imports translation data from CSV files, updating the corresponding JSON files. This is useful for applying bulk translation updates from spreadsheets.

Usage:

bash
i18n-micro import-csv [options]

Options:

  • --csvDir: Directory containing the CSV files to be imported.
  • --delimiter: Specify a delimiter used in the CSV file (default: ,).

Example:

bash
i18n-micro import-csv --csvDir csv_files

🧾 diff Command

Description: Compares translation files between the default locale and other locales within the same directory (including subdirectories). The command identifies missing keys and their values in the default locale compared to other locales, making it easier to track translation progress or discrepancies.

Usage:

bash
i18n-micro diff [options]

Example:

bash
i18n-micro diff

🔍 check-duplicates Command

Description: The check-duplicates command checks for duplicate translation values within each locale across all translation files, including both global and page-specific translations. It ensures that different keys within the same language do not share identical translation values, helping maintain clarity and consistency in your translations.

Usage:

bash
i18n-micro check-duplicates [options]

Example:

bash
i18n-micro check-duplicates

How it works:

  • The command checks both global and page-specific translation files for each locale.
  • If a translation value appears in multiple locations (either within global translations or across different pages), it reports the duplicate values along with the file and key where they are found.
  • If no duplicates are found, the command confirms that the locale is free of duplicated translation values.

This command helps ensure that translation keys maintain unique values, preventing accidental repetition within the same locale.

🔄 replace-values Command

Description: The replace-values command allows you to perform bulk replacements of translation values across all locales. It supports both simple text replacements and advanced replacements using regular expressions (regex). You can also use capturing groups in regex patterns and reference them in the replacement string, making it ideal for more complex replacement scenarios.

Usage:

bash
i18n-micro replace-values [options]

Options:

  • --search: The text or regex pattern to search for in translations. This is a required option.
  • --replace: The replacement text to be used for the found translations. This is a required option.
  • --useRegex: Enable search using a regular expression pattern (default: false).

Example 1: Simple replacement

Replace the string "Hello" with "Hi" across all locales:

bash
i18n-micro replace-values --search "Hello" --replace "Hi"

Example 2: Regex replacement

Enable regex search and replace any string starting with "Hello" followed by numbers (e.g., "Hello123") with "Hi" across all locales:

bash
i18n-micro replace-values --search "Hello\\\\d+" --replace "Hi" --useRegex

Example 3: Using regex capturing groups

Use capturing groups to dynamically insert part of the matched string into the replacement. For example, replace "Hello [name]" with "Hi [name]" while keeping the name intact:

bash
i18n-micro replace-values --search "Hello (\\\\w+)" --replace "Hi $1" --useRegex

In this case, $1 refers to the first capturing group, which matches the [name] part after "Hello". The replacement will keep the name from the original string.

How it works:

  • The command scans through all translation files (both global and page-specific).
  • When a match is found based on the search string or regex pattern, it replaces the matched text with the provided replacement.
  • When using regex, capturing groups can be used in the replacement string by referencing them with $1, $2, etc.
  • All changes are logged, showing the file path, translation key, and the before/after state of the translation value.

Logging: For each replacement, the command logs details including:

  • Locale and file path
  • The translation key being modified
  • The old value and the new value after replacement
  • If using regex with capturing groups, the logs will show the group matches and how they were replaced.

This allows you to track exactly where and what changes were made during the replacement operation, providing a clear history of modifications across your translation files.

🛠 Examples

  • Extracting translations:

    bash
    i18n-micro extract
  • Translating missing keys using Google Translate:

    bash
    i18n-micro translate --service google --token YOUR_GOOGLE_API_KEY
  • Translating all keys, replacing existing translations:

    bash
    i18n-micro translate --service deepl --token YOUR_DEEPL_API_KEY --replace
  • Validating translation files:

    bash
    i18n-micro validate
  • Cleaning unused translation keys:

    bash
    i18n-micro clean
  • Synchronizing translation files:

    bash
    i18n-micro sync

⚙️ Configuration Guide

nuxt-i18n-micro-cli relies on your Nuxt.js i18n configuration in nuxt.config.js. Ensure you have the nuxt-i18n module installed and configured.

🔑 nuxt.config.js Example

js
export default {\n  modules: ['@nuxtjs/i18n'],\n  i18n: {\n    locales: [\n      { code: 'en', iso: 'en-US' },\n      { code: 'fr', iso: 'fr-FR' },\n      { code: 'es', iso: 'es-ES' },\n      // Add other locales as needed\n    ],\n    defaultLocale: 'en',\n    vueI18n: {\n      fallbackLocale: 'en',\n    },\n    // Specify the directory where your translation files are stored\n    translationDir: 'locales',\n  },\n};

Ensure that the translationDir matches the directory used by nuxt-i18n-micro-cli (default is locales).

📝 Best Practices

🔑 Consistent Key Naming

Ensure translation keys are consistent and descriptive to avoid confusion and duplication.

🧹 Regular Maintenance

Use the clean command regularly to remove unused translation keys and keep your translation files clean.

🛠 Automate Translation Workflow

Integrate nuxt-i18n-micro-cli commands into your development workflow or CI/CD pipeline to automate extraction, translation, validation, and synchronization of translation files.

🛡️ Secure API Keys

When using translation services that require API keys, ensure your keys are kept secure and not committed to version control systems. Consider using environment variables or secure key management solutions.

📞 Support and Contributions

If you encounter issues or have suggestions for improvements, feel free to contribute to the project or open an issue on the project's repository.


By following this guide, you'll be able to effectively manage translations in your Nuxt.js project using nuxt-i18n-micro-cli, streamlining your internationalization efforts and ensuring a smooth experience for users in different locales.

',181)]))}const m=a(l,[["render",o]]);export{u as __pageData,m as default}; diff --git a/assets/guide_contribution.md.BiQbFYzX.js b/assets/guide_contribution.md.BiQbFYzX.js new file mode 100644 index 00000000..cd6a071c --- /dev/null +++ b/assets/guide_contribution.md.BiQbFYzX.js @@ -0,0 +1,10 @@ +import{_ as i,c as a,a2 as s,o as t}from"./chunks/framework.Gfs4HC1t.js";const u=JSON.parse('{"title":"🤝 Contribution Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/contribution.md","filePath":"guide/contribution.md","lastUpdated":1737055913000}'),n={name:"guide/contribution.md"};function o(l,e,r,h,p,d){return t(),a("div",null,e[0]||(e[0]=[s(`

🤝 Contribution Guide

📖 Introduction

Thank you for your interest in contributing to Nuxt I18n Micro! We welcome contributions from the community, whether it's bug fixes, new features, or improvements to the documentation. This guide outlines the steps to help you get started and ensures that your contributions can be easily integrated into the project.

🚀 Getting Started

1. 📚 Familiarize Yourself with the Project

Before making changes, it's a good idea to familiarize yourself with the project's architecture and codebase. Read through the existing documentation and take a look at open issues and pull requests to understand ongoing work and challenges.

2. 🍴 Fork the Repository

  • Navigate to the Nuxt I18n Micro repository.
  • Click the "Fork" button in the upper right corner to create a copy of the repository in your GitHub account.

3. 📥 Clone Your Fork

Clone the forked repository to your local machine:

bash
git clone https://github.com/<your-username>/nuxt-i18n-micro.git
+cd nuxt-i18n-micro

Replace <your-username> with your GitHub username.

4. 🌱 Create a Branch

Create a new branch for your work:

bash
git checkout -b feature/your-feature-name

Use descriptive branch names, such as bugfix/fix-translation-error or feature/add-new-locale-support.

🛠️ Local Development Setup

🛠 Prerequisites

Before you begin, ensure that you have the following installed on your machine:

  • Node.js: v16 or later
  • npm: v7 or later
  • pnpm: v9 or later

🚀 Getting Started

1. 📥 Clone the Repository

First, you need to clone the nuxt-i18n-micro repository to your local machine.

bash
git clone https://github.com/s00d/nuxt-i18n-micro.git
+cd nuxt-i18n-micro

2. 📦 Install Dependencies

Next, install the project dependencies using pnpm.

bash
pnpm install
+pnpm --filter "./packages/**" run build
+pnpm run prepack && cd playground && pnpm run prepare && cd ..

3. 🖥️ Run the Development Server

To start the development server and work on the module, run the following command:

bash
pnpm run dev

This command will start the Nuxt development server using the playground directory as the testing environment. You can view the app in your browser by navigating to http://localhost:3000.

4. 🏗️ Building the Module

To build the module, use the following command:

bash
pnpm run prepack

This command prepares the module by building the necessary files, stubbing certain components, and ensuring everything is ready for packaging.

5. 🧹 Linting the Code

To ensure your code adheres to the project's coding standards, run the linter:

bash
pnpm run lint

If there are any issues, you can attempt to automatically fix them using:

bash
pnpm run lint:fix

6. ✅ Running Tests

To run the test suite, use the following command:

bash
pnpm run test:workspaces
+pnpm run test

This will run all the Playwright tests to ensure everything is functioning as expected.

7. 🔍 Type Checking

For TypeScript type checking, run:

bash
pnpm run typecheck
+pnpm run test:types
+pnpm run test

This checks the type definitions to ensure there are no type errors.

8. 📚 Building and Previewing the Documentation

To build and preview the documentation locally, use the following commands:

bash
pnpm run docs:build
+pnpm run docs:serve

This will build the documentation and serve it locally, allowing you to view it in your browser.

9. 🎮 Running the Playground

If you want to test your changes in a sample Nuxt application, the playground directory serves as a sandbox environment. Run the following command to start the playground:

bash
pnpm run dev:build

You can access the playground app at http://localhost:3000.

🔧 Summary of Common Scripts

  • pnpm run dev: Start the development server using the playground.
  • pnpm run prepack: Build the module and prepare it for publishing.
  • pnpm --filter "./packages/**" run build: Build the packages.
  • pnpm run lint: Run the linter to check for code quality issues.
  • pnpm run lint:fix: Automatically fix linter issues.
  • pnpm run test: Run the test suite.
  • pnpm run test:workspaces: Run the test suite for packages.
  • pnpm run typecheck: Check TypeScript types.
  • pnpm run docs:dev: Start the documentation site in development mode.
  • pnpm run docs:build: Build the documentation site.
  • pnpm run docs:serve: Serve the built documentation site locally.
  • pnpm run dev:build: Build the playground environment.

🚧 Making Changes

1. 💻 Code

  • Make your changes in the codebase according to the project’s architecture.
  • Follow the existing code style and conventions.
  • If you’re adding a new feature, consider writing tests for it.

2. 🧹 Run Linting

Before committing your changes, ensure that your code adheres to the project's coding standards by running the linter:

bash
pnpm run lint

Fix any linting errors before proceeding.

3. 🧪 Test Your Changes

Make sure your changes work and do not break any existing functionality:

  • Run all tests to ensure there are no errors:
bash
pnpm run test:workspaces
+pnpm run test
  • If you’re fixing a bug, add tests to cover the fix.

4. 📝 Commit Your Changes

To ensure consistency across the project, we use a standardized commit message format. Please follow this format when making commits:

✅ Commit Message Format

Each commit message should be structured as follows:

<type>(<scope>): <short description>

📋 Examples:

  • fix(router): resolve issue with locale switching
  • feat(seo): add automatic og:locale meta tag generation
  • docs(contribution): update contribution guide with commit message format

🛠️ Commit Types:

  • feat: A new feature.
  • fix: A bug fix.
  • docs: Documentation changes or updates.
  • style: Code style or formatting changes (no functional impact).
  • refactor: Code changes that neither fix a bug nor add a feature.
  • test: Adding or updating tests.
  • chore: Miscellaneous tasks, such as updating build scripts or dependencies.

For more details, refer to the Conventional Commits Specification.

5. 🚀 Push to GitHub

Push your changes to your fork on GitHub:

bash
git push origin feature/your-feature-name

6. 🔄 Create a Pull Request

  • Go to your forked repository on GitHub.
  • Click the "Compare & pull request" button.
  • Ensure your PR targets the main branch of the original repository (s00d/nuxt-i18n-micro).
  • Describe your changes in the PR, and link to any relevant issues.

7. 🕵️‍♂️ Await Feedback

Once your pull request is submitted, a maintainer will review your changes. Be prepared to make adjustments based on feedback. Once approved, your PR will be merged into the main branch.

💡 Contribution Tips

  • 📝 Documentation: If you add or change a feature, ensure that you update the relevant documentation.
  • 🧼 Code Cleanliness: Keep your code clean and follow the project's coding standards.
  • 💬 Respectful Communication: Be respectful and friendly in your communications. We are all working towards the common goal of making Nuxt I18n Micro better.
`,89)]))}const g=i(n,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_contribution.md.BiQbFYzX.lean.js b/assets/guide_contribution.md.BiQbFYzX.lean.js new file mode 100644 index 00000000..cd6a071c --- /dev/null +++ b/assets/guide_contribution.md.BiQbFYzX.lean.js @@ -0,0 +1,10 @@ +import{_ as i,c as a,a2 as s,o as t}from"./chunks/framework.Gfs4HC1t.js";const u=JSON.parse('{"title":"🤝 Contribution Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/contribution.md","filePath":"guide/contribution.md","lastUpdated":1737055913000}'),n={name:"guide/contribution.md"};function o(l,e,r,h,p,d){return t(),a("div",null,e[0]||(e[0]=[s(`

🤝 Contribution Guide

📖 Introduction

Thank you for your interest in contributing to Nuxt I18n Micro! We welcome contributions from the community, whether it's bug fixes, new features, or improvements to the documentation. This guide outlines the steps to help you get started and ensures that your contributions can be easily integrated into the project.

🚀 Getting Started

1. 📚 Familiarize Yourself with the Project

Before making changes, it's a good idea to familiarize yourself with the project's architecture and codebase. Read through the existing documentation and take a look at open issues and pull requests to understand ongoing work and challenges.

2. 🍴 Fork the Repository

  • Navigate to the Nuxt I18n Micro repository.
  • Click the "Fork" button in the upper right corner to create a copy of the repository in your GitHub account.

3. 📥 Clone Your Fork

Clone the forked repository to your local machine:

bash
git clone https://github.com/<your-username>/nuxt-i18n-micro.git
+cd nuxt-i18n-micro

Replace <your-username> with your GitHub username.

4. 🌱 Create a Branch

Create a new branch for your work:

bash
git checkout -b feature/your-feature-name

Use descriptive branch names, such as bugfix/fix-translation-error or feature/add-new-locale-support.

🛠️ Local Development Setup

🛠 Prerequisites

Before you begin, ensure that you have the following installed on your machine:

  • Node.js: v16 or later
  • npm: v7 or later
  • pnpm: v9 or later

🚀 Getting Started

1. 📥 Clone the Repository

First, you need to clone the nuxt-i18n-micro repository to your local machine.

bash
git clone https://github.com/s00d/nuxt-i18n-micro.git
+cd nuxt-i18n-micro

2. 📦 Install Dependencies

Next, install the project dependencies using pnpm.

bash
pnpm install
+pnpm --filter "./packages/**" run build
+pnpm run prepack && cd playground && pnpm run prepare && cd ..

3. 🖥️ Run the Development Server

To start the development server and work on the module, run the following command:

bash
pnpm run dev

This command will start the Nuxt development server using the playground directory as the testing environment. You can view the app in your browser by navigating to http://localhost:3000.

4. 🏗️ Building the Module

To build the module, use the following command:

bash
pnpm run prepack

This command prepares the module by building the necessary files, stubbing certain components, and ensuring everything is ready for packaging.

5. 🧹 Linting the Code

To ensure your code adheres to the project's coding standards, run the linter:

bash
pnpm run lint

If there are any issues, you can attempt to automatically fix them using:

bash
pnpm run lint:fix

6. ✅ Running Tests

To run the test suite, use the following command:

bash
pnpm run test:workspaces
+pnpm run test

This will run all the Playwright tests to ensure everything is functioning as expected.

7. 🔍 Type Checking

For TypeScript type checking, run:

bash
pnpm run typecheck
+pnpm run test:types
+pnpm run test

This checks the type definitions to ensure there are no type errors.

8. 📚 Building and Previewing the Documentation

To build and preview the documentation locally, use the following commands:

bash
pnpm run docs:build
+pnpm run docs:serve

This will build the documentation and serve it locally, allowing you to view it in your browser.

9. 🎮 Running the Playground

If you want to test your changes in a sample Nuxt application, the playground directory serves as a sandbox environment. Run the following command to start the playground:

bash
pnpm run dev:build

You can access the playground app at http://localhost:3000.

🔧 Summary of Common Scripts

  • pnpm run dev: Start the development server using the playground.
  • pnpm run prepack: Build the module and prepare it for publishing.
  • pnpm --filter "./packages/**" run build: Build the packages.
  • pnpm run lint: Run the linter to check for code quality issues.
  • pnpm run lint:fix: Automatically fix linter issues.
  • pnpm run test: Run the test suite.
  • pnpm run test:workspaces: Run the test suite for packages.
  • pnpm run typecheck: Check TypeScript types.
  • pnpm run docs:dev: Start the documentation site in development mode.
  • pnpm run docs:build: Build the documentation site.
  • pnpm run docs:serve: Serve the built documentation site locally.
  • pnpm run dev:build: Build the playground environment.

🚧 Making Changes

1. 💻 Code

  • Make your changes in the codebase according to the project’s architecture.
  • Follow the existing code style and conventions.
  • If you’re adding a new feature, consider writing tests for it.

2. 🧹 Run Linting

Before committing your changes, ensure that your code adheres to the project's coding standards by running the linter:

bash
pnpm run lint

Fix any linting errors before proceeding.

3. 🧪 Test Your Changes

Make sure your changes work and do not break any existing functionality:

  • Run all tests to ensure there are no errors:
bash
pnpm run test:workspaces
+pnpm run test
  • If you’re fixing a bug, add tests to cover the fix.

4. 📝 Commit Your Changes

To ensure consistency across the project, we use a standardized commit message format. Please follow this format when making commits:

✅ Commit Message Format

Each commit message should be structured as follows:

<type>(<scope>): <short description>

📋 Examples:

  • fix(router): resolve issue with locale switching
  • feat(seo): add automatic og:locale meta tag generation
  • docs(contribution): update contribution guide with commit message format

🛠️ Commit Types:

  • feat: A new feature.
  • fix: A bug fix.
  • docs: Documentation changes or updates.
  • style: Code style or formatting changes (no functional impact).
  • refactor: Code changes that neither fix a bug nor add a feature.
  • test: Adding or updating tests.
  • chore: Miscellaneous tasks, such as updating build scripts or dependencies.

For more details, refer to the Conventional Commits Specification.

5. 🚀 Push to GitHub

Push your changes to your fork on GitHub:

bash
git push origin feature/your-feature-name

6. 🔄 Create a Pull Request

  • Go to your forked repository on GitHub.
  • Click the "Compare & pull request" button.
  • Ensure your PR targets the main branch of the original repository (s00d/nuxt-i18n-micro).
  • Describe your changes in the PR, and link to any relevant issues.

7. 🕵️‍♂️ Await Feedback

Once your pull request is submitted, a maintainer will review your changes. Be prepared to make adjustments based on feedback. Once approved, your PR will be merged into the main branch.

💡 Contribution Tips

  • 📝 Documentation: If you add or change a feature, ensure that you update the relevant documentation.
  • 🧼 Code Cleanliness: Keep your code clean and follow the project's coding standards.
  • 💬 Respectful Communication: Be respectful and friendly in your communications. We are all working towards the common goal of making Nuxt I18n Micro better.
`,89)]))}const g=i(n,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_crowdin.md.DgJWT6GK.js b/assets/guide_crowdin.md.DgJWT6GK.js new file mode 100644 index 00000000..6c29ee2f --- /dev/null +++ b/assets/guide_crowdin.md.DgJWT6GK.js @@ -0,0 +1,16 @@ +import{_ as a,c as s,a2 as n,o as e}from"./chunks/framework.Gfs4HC1t.js";const u=JSON.parse('{"title":"🌐 Crowdin Integration Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/crowdin.md","filePath":"guide/crowdin.md","lastUpdated":1726410447000}'),t={name:"guide/crowdin.md"};function o(l,i,r,d,h,p){return e(),s("div",null,i[0]||(i[0]=[n(`

🌐 Crowdin Integration Guide

📖 Introduction

Integrating Crowdin into your project streamlines the localization and translation process, making it easier to manage translations across multiple languages and platforms. This guide provides a step-by-step walkthrough on setting up Crowdin with your project, including configuration, uploading sources, and downloading translations.

🔧 Installation and Setup

To get started with Crowdin, you'll need to install the Crowdin CLI globally on your machine and initialize it within your project directory.

📦 Installing Crowdin CLI

First, install the Crowdin CLI globally using npm:

bash
npm install -g @crowdin/cli

🛠 Initializing Crowdin in Your Project

Initialize Crowdin in your project by running:

bash
crowdin init

This command will guide you through the setup process, including setting your project ID, API token, and other configuration details.

🗂️ Configuration Guide

📄 Crowdin Configuration File (crowdin.yml)

The Crowdin configuration file (crowdin.yml) defines how your source files are mapped and where translations should be placed. Below is an example configuration:

yml
"project_id": "YOUR_PROJECT_ID"
+"api_token": "YOUR_API_TOKEN"
+"base_path": "./locales"
+"base_url": "https://api.crowdin.com"
+"preserve_hierarchy": true
+
+files: [
+  {
+    "source": "/en.json",
+    "translation": "/%two_letters_code%.json",
+  },
+  {
+    "source": "/pages/**/en.json",
+    "translation": "/pages/**/%two_letters_code%.json",
+  }
+]

📂 Key Configuration Parameters

  • project_id: Your Crowdin project ID. This identifies the project within Crowdin where translations are managed.
  • api_token: The API token used for authentication. Ensure this token has the correct permissions to upload and download translations.
  • base_path: Specifies the base directory for source files. In this example, translations are stored in the ./locales directory.
  • base_url: The base URL for the Crowdin API.
  • preserve_hierarchy: When set to true, Crowdin will maintain the folder structure of your source files in the project.

📂 Files Configuration

The files section maps your source files to the paths where translations will be stored. For example:

  • Source Path: Defines the location of the original translation files.
  • Translation Path: Specifies where the translated files will be stored in Crowdin. Placeholders like %two_letters_code% are used to dynamically set the language code in the file paths.

⬆️ Uploading Source Files to Crowdin

Once your Crowdin configuration is set up, you can upload your source files using the following command:

bash
crowdin upload sources

This command uploads all specified source files in your configuration to Crowdin, making them available for translation.

⬇️ Downloading Translations from Crowdin

After translations are completed or updated in Crowdin, you can download them to your project using:

bash
crowdin download

This command fetches the latest translations from Crowdin and saves them according to the paths specified in your configuration file.

⚙️ Best Practices

🔑 Consistent Key Naming

Ensure translation keys are consistent across all files to avoid confusion and duplication.

🧹 Regular Maintenance

Periodically review and clean up unused translation keys to keep your files organized and manageable.

🛠 Automate Uploads and Downloads

Integrate the Crowdin CLI commands into your CI/CD pipeline to automate the upload of source files and download of translations, ensuring your translations are always up to date.

By following this guide, you’ll be able to seamlessly integrate Crowdin into your project, ensuring an efficient and organized approach to managing your internationalization efforts.

`,37)]))}const g=a(t,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_crowdin.md.DgJWT6GK.lean.js b/assets/guide_crowdin.md.DgJWT6GK.lean.js new file mode 100644 index 00000000..6c29ee2f --- /dev/null +++ b/assets/guide_crowdin.md.DgJWT6GK.lean.js @@ -0,0 +1,16 @@ +import{_ as a,c as s,a2 as n,o as e}from"./chunks/framework.Gfs4HC1t.js";const u=JSON.parse('{"title":"🌐 Crowdin Integration Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/crowdin.md","filePath":"guide/crowdin.md","lastUpdated":1726410447000}'),t={name:"guide/crowdin.md"};function o(l,i,r,d,h,p){return e(),s("div",null,i[0]||(i[0]=[n(`

🌐 Crowdin Integration Guide

📖 Introduction

Integrating Crowdin into your project streamlines the localization and translation process, making it easier to manage translations across multiple languages and platforms. This guide provides a step-by-step walkthrough on setting up Crowdin with your project, including configuration, uploading sources, and downloading translations.

🔧 Installation and Setup

To get started with Crowdin, you'll need to install the Crowdin CLI globally on your machine and initialize it within your project directory.

📦 Installing Crowdin CLI

First, install the Crowdin CLI globally using npm:

bash
npm install -g @crowdin/cli

🛠 Initializing Crowdin in Your Project

Initialize Crowdin in your project by running:

bash
crowdin init

This command will guide you through the setup process, including setting your project ID, API token, and other configuration details.

🗂️ Configuration Guide

📄 Crowdin Configuration File (crowdin.yml)

The Crowdin configuration file (crowdin.yml) defines how your source files are mapped and where translations should be placed. Below is an example configuration:

yml
"project_id": "YOUR_PROJECT_ID"
+"api_token": "YOUR_API_TOKEN"
+"base_path": "./locales"
+"base_url": "https://api.crowdin.com"
+"preserve_hierarchy": true
+
+files: [
+  {
+    "source": "/en.json",
+    "translation": "/%two_letters_code%.json",
+  },
+  {
+    "source": "/pages/**/en.json",
+    "translation": "/pages/**/%two_letters_code%.json",
+  }
+]

📂 Key Configuration Parameters

  • project_id: Your Crowdin project ID. This identifies the project within Crowdin where translations are managed.
  • api_token: The API token used for authentication. Ensure this token has the correct permissions to upload and download translations.
  • base_path: Specifies the base directory for source files. In this example, translations are stored in the ./locales directory.
  • base_url: The base URL for the Crowdin API.
  • preserve_hierarchy: When set to true, Crowdin will maintain the folder structure of your source files in the project.

📂 Files Configuration

The files section maps your source files to the paths where translations will be stored. For example:

  • Source Path: Defines the location of the original translation files.
  • Translation Path: Specifies where the translated files will be stored in Crowdin. Placeholders like %two_letters_code% are used to dynamically set the language code in the file paths.

⬆️ Uploading Source Files to Crowdin

Once your Crowdin configuration is set up, you can upload your source files using the following command:

bash
crowdin upload sources

This command uploads all specified source files in your configuration to Crowdin, making them available for translation.

⬇️ Downloading Translations from Crowdin

After translations are completed or updated in Crowdin, you can download them to your project using:

bash
crowdin download

This command fetches the latest translations from Crowdin and saves them according to the paths specified in your configuration file.

⚙️ Best Practices

🔑 Consistent Key Naming

Ensure translation keys are consistent across all files to avoid confusion and duplication.

🧹 Regular Maintenance

Periodically review and clean up unused translation keys to keep your files organized and manageable.

🛠 Automate Uploads and Downloads

Integrate the Crowdin CLI commands into your CI/CD pipeline to automate the upload of source files and download of translations, ensuring your translations are always up to date.

By following this guide, you’ll be able to seamlessly integrate Crowdin into your project, ensuring an efficient and organized approach to managing your internationalization efforts.

`,37)]))}const g=a(t,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_custom-locale-routes.md.65G7AEaG.js b/assets/guide_custom-locale-routes.md.65G7AEaG.js new file mode 100644 index 00000000..6677d39a --- /dev/null +++ b/assets/guide_custom-locale-routes.md.65G7AEaG.js @@ -0,0 +1,35 @@ +import{_ as i,c as a,a2 as e,o as t}from"./chunks/framework.Gfs4HC1t.js";const d=JSON.parse('{"title":"🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/custom-locale-routes.md","filePath":"guide/custom-locale-routes.md","lastUpdated":1725088182000}'),n={name:"guide/custom-locale-routes.md"};function l(o,s,h,p,r,k){return t(),a("div",null,s[0]||(s[0]=[e(`

🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro

📖 Introduction to localeRoutes

The localeRoutes feature in Nuxt I18n Micro allows you to define custom routes for specific locales, offering flexibility and control over the routing structure of your application. This feature is particularly useful when certain locales require different URL structures, tailored paths, or need to follow specific regional or linguistic conventions.

🚀 Primary Use Case of localeRoutes

The primary use case for localeRoutes is to provide distinct routes for different locales, enhancing the user experience by ensuring URLs are intuitive and relevant to the target audience. For example, you might have different paths for English and Russian versions of a page, where the Russian locale follows a localized URL format.

📄 Example: Defining localeRoutes in $defineI18nRoute

Here’s an example of how you might define custom routes for specific locales using localeRoutes in your $defineI18nRoute function:

typescript
$defineI18nRoute({
+  localeRoutes: {
+    ru: '/localesubpage', // Custom route path for the Russian locale
+    de: '/lokaleseite',   // Custom route path for the German locale
+  },
+})

🔄 How localeRoutes Work

  • Default Behavior: Without localeRoutes, all locales use a common route structure defined by the primary path.
  • Custom Behavior: With localeRoutes, specific locales can have their own routes, overriding the default path with locale-specific routes defined in the configuration.

🌱 Use Cases for localeRoutes

📄 Example: Using localeRoutes in a Page

Here’s a simple Vue component demonstrating the use of $defineI18nRoute with localeRoutes:

vue
<template>
+  <div>
+    <!-- Display greeting message based on the current locale -->
+    <p>{{ $t('greeting') }}</p>
+
+    <!-- Navigation links -->
+    <div>
+      <NuxtLink :to="$localeRoute({ name: 'index' })">
+        Go to Index
+      </NuxtLink>
+      |
+      <NuxtLink :to="$localeRoute({ name: 'about' })">
+        Go to About Page
+      </NuxtLink>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t, $defineI18nRoute } = useNuxtApp()
+
+// Define translations and custom routes for specific locales
+$defineI18nRoute({
+  localeRoutes: {
+    ru: '/localesubpage', // Custom route path for Russian locale
+  },
+})
+</script>

🛠️ Using localeRoutes in Different Contexts

  • Landing Pages: Use custom routes to localize URLs for landing pages, ensuring they align with marketing campaigns.
  • Documentation Sites: Provide distinct routes for each locale to better match the localized content structure.
  • E-commerce Sites: Tailor product or category URLs per locale for improved SEO and user experience.

📝 Best Practices for Using localeRoutes

  • 🚀 Use for Relevant Locales: Apply localeRoutes primarily where the URL structure significantly impacts the user experience or SEO. Avoid overuse for minor differences.
  • 🔧 Maintain Consistency: Keep a consistent routing pattern across locales unless there's a strong reason to deviate. This approach helps in maintaining clarity and reducing complexity.
  • 📚 Document Custom Routes: Clearly document any custom routes you define with localeRoutes, especially in modular applications, to ensure team members understand the routing logic.
`,18)]))}const E=i(n,[["render",l]]);export{d as __pageData,E as default}; diff --git a/assets/guide_custom-locale-routes.md.65G7AEaG.lean.js b/assets/guide_custom-locale-routes.md.65G7AEaG.lean.js new file mode 100644 index 00000000..6677d39a --- /dev/null +++ b/assets/guide_custom-locale-routes.md.65G7AEaG.lean.js @@ -0,0 +1,35 @@ +import{_ as i,c as a,a2 as e,o as t}from"./chunks/framework.Gfs4HC1t.js";const d=JSON.parse('{"title":"🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/custom-locale-routes.md","filePath":"guide/custom-locale-routes.md","lastUpdated":1725088182000}'),n={name:"guide/custom-locale-routes.md"};function l(o,s,h,p,r,k){return t(),a("div",null,s[0]||(s[0]=[e(`

🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro

📖 Introduction to localeRoutes

The localeRoutes feature in Nuxt I18n Micro allows you to define custom routes for specific locales, offering flexibility and control over the routing structure of your application. This feature is particularly useful when certain locales require different URL structures, tailored paths, or need to follow specific regional or linguistic conventions.

🚀 Primary Use Case of localeRoutes

The primary use case for localeRoutes is to provide distinct routes for different locales, enhancing the user experience by ensuring URLs are intuitive and relevant to the target audience. For example, you might have different paths for English and Russian versions of a page, where the Russian locale follows a localized URL format.

📄 Example: Defining localeRoutes in $defineI18nRoute

Here’s an example of how you might define custom routes for specific locales using localeRoutes in your $defineI18nRoute function:

typescript
$defineI18nRoute({
+  localeRoutes: {
+    ru: '/localesubpage', // Custom route path for the Russian locale
+    de: '/lokaleseite',   // Custom route path for the German locale
+  },
+})

🔄 How localeRoutes Work

  • Default Behavior: Without localeRoutes, all locales use a common route structure defined by the primary path.
  • Custom Behavior: With localeRoutes, specific locales can have their own routes, overriding the default path with locale-specific routes defined in the configuration.

🌱 Use Cases for localeRoutes

📄 Example: Using localeRoutes in a Page

Here’s a simple Vue component demonstrating the use of $defineI18nRoute with localeRoutes:

vue
<template>
+  <div>
+    <!-- Display greeting message based on the current locale -->
+    <p>{{ $t('greeting') }}</p>
+
+    <!-- Navigation links -->
+    <div>
+      <NuxtLink :to="$localeRoute({ name: 'index' })">
+        Go to Index
+      </NuxtLink>
+      |
+      <NuxtLink :to="$localeRoute({ name: 'about' })">
+        Go to About Page
+      </NuxtLink>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t, $defineI18nRoute } = useNuxtApp()
+
+// Define translations and custom routes for specific locales
+$defineI18nRoute({
+  localeRoutes: {
+    ru: '/localesubpage', // Custom route path for Russian locale
+  },
+})
+</script>

🛠️ Using localeRoutes in Different Contexts

  • Landing Pages: Use custom routes to localize URLs for landing pages, ensuring they align with marketing campaigns.
  • Documentation Sites: Provide distinct routes for each locale to better match the localized content structure.
  • E-commerce Sites: Tailor product or category URLs per locale for improved SEO and user experience.

📝 Best Practices for Using localeRoutes

  • 🚀 Use for Relevant Locales: Apply localeRoutes primarily where the URL structure significantly impacts the user experience or SEO. Avoid overuse for minor differences.
  • 🔧 Maintain Consistency: Keep a consistent routing pattern across locales unless there's a strong reason to deviate. This approach helps in maintaining clarity and reducing complexity.
  • 📚 Document Custom Routes: Clearly document any custom routes you define with localeRoutes, especially in modular applications, to ensure team members understand the routing logic.
`,18)]))}const E=i(n,[["render",l]]);export{d as __pageData,E as default}; diff --git a/assets/guide_devtools.md.sGmDATnc.js b/assets/guide_devtools.md.sGmDATnc.js new file mode 100644 index 00000000..779120f9 --- /dev/null +++ b/assets/guide_devtools.md.sGmDATnc.js @@ -0,0 +1 @@ +import{_ as o,c as t,a2 as a,o as i}from"./chunks/framework.Gfs4HC1t.js";const n="/nuxt-i18n-micro/devtools.png",g=JSON.parse('{"title":"🛠️ DevTools in nuxt-i18n-micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/devtools.md","filePath":"guide/devtools.md","lastUpdated":1733209855000}'),r={name:"guide/devtools.md"};function l(s,e,d,u,c,h){return i(),t("div",null,e[0]||(e[0]=[a('

🛠️ DevTools in nuxt-i18n-micro

📖 What Is Nuxt DevTools?

DevTools is a powerful development assistant seamlessly integrated into the nuxt-i18n-micro module. It provides an intuitive interface for managing localization and translation tasks, making your workflow faster and more efficient. Designed for developers who value convenience, Nuxt DevTools bridges the gap between coding and runtime management.

DevTools

🌟 Key Features of DevTools in nuxt-i18n-micro

1. Locale Management

Effortlessly browse, select, and manage locales in your application. Whether you’re working with a single language or multiple, DevTools provides a centralized hub for handling all localization settings.

2. Translation Editing

Edit translation files directly through an integrated JSON editor. This eliminates the need for external tools, allowing real-time updates and changes without interrupting your workflow.

3. File Import and Export

Simplify the process of managing translation files:

  • Export: Save translations as a JSON file for backups or external use.
  • Import: Load updated translation files into the project to keep content up-to-date.

4. Real-Time Previews

View changes immediately within the development environment. This feature ensures translations and configurations are accurate before going live.

5. Seamless Nuxt Integration

DevTools works natively with nuxt-i18n-micro, enhancing its capabilities without requiring additional setup. It adapts to your localization needs while maintaining Nuxt's modular and flexible structure.


🛠️ Why Use DevTools?

Nuxt DevTools is an indispensable addition for projects requiring localization. It helps developers by:

  • Saving Time: Automates repetitive tasks like file management and format validation.
  • Reducing Errors: Provides a safe, intuitive environment for editing translations.
  • Improving Collaboration: Enables non-developers to manage translations easily.
  • Streamlining Workflows: Consolidates multiple localization tasks into a single interface.

🚀 Take Control of Localization

With Nuxt DevTools integrated into nuxt-i18n-micro, managing multilingual applications becomes straightforward and efficient. Whether you're fine-tuning translations or adding new locales, DevTools equips you with the tools needed to deliver polished, user-friendly experiences.

',23)]))}const p=o(r,[["render",l]]);export{g as __pageData,p as default}; diff --git a/assets/guide_devtools.md.sGmDATnc.lean.js b/assets/guide_devtools.md.sGmDATnc.lean.js new file mode 100644 index 00000000..779120f9 --- /dev/null +++ b/assets/guide_devtools.md.sGmDATnc.lean.js @@ -0,0 +1 @@ +import{_ as o,c as t,a2 as a,o as i}from"./chunks/framework.Gfs4HC1t.js";const n="/nuxt-i18n-micro/devtools.png",g=JSON.parse('{"title":"🛠️ DevTools in nuxt-i18n-micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/devtools.md","filePath":"guide/devtools.md","lastUpdated":1733209855000}'),r={name:"guide/devtools.md"};function l(s,e,d,u,c,h){return i(),t("div",null,e[0]||(e[0]=[a('

🛠️ DevTools in nuxt-i18n-micro

📖 What Is Nuxt DevTools?

DevTools is a powerful development assistant seamlessly integrated into the nuxt-i18n-micro module. It provides an intuitive interface for managing localization and translation tasks, making your workflow faster and more efficient. Designed for developers who value convenience, Nuxt DevTools bridges the gap between coding and runtime management.

DevTools

🌟 Key Features of DevTools in nuxt-i18n-micro

1. Locale Management

Effortlessly browse, select, and manage locales in your application. Whether you’re working with a single language or multiple, DevTools provides a centralized hub for handling all localization settings.

2. Translation Editing

Edit translation files directly through an integrated JSON editor. This eliminates the need for external tools, allowing real-time updates and changes without interrupting your workflow.

3. File Import and Export

Simplify the process of managing translation files:

  • Export: Save translations as a JSON file for backups or external use.
  • Import: Load updated translation files into the project to keep content up-to-date.

4. Real-Time Previews

View changes immediately within the development environment. This feature ensures translations and configurations are accurate before going live.

5. Seamless Nuxt Integration

DevTools works natively with nuxt-i18n-micro, enhancing its capabilities without requiring additional setup. It adapts to your localization needs while maintaining Nuxt's modular and flexible structure.


🛠️ Why Use DevTools?

Nuxt DevTools is an indispensable addition for projects requiring localization. It helps developers by:

  • Saving Time: Automates repetitive tasks like file management and format validation.
  • Reducing Errors: Provides a safe, intuitive environment for editing translations.
  • Improving Collaboration: Enables non-developers to manage translations easily.
  • Streamlining Workflows: Consolidates multiple localization tasks into a single interface.

🚀 Take Control of Localization

With Nuxt DevTools integrated into nuxt-i18n-micro, managing multilingual applications becomes straightforward and efficient. Whether you're fine-tuning translations or adding new locales, DevTools equips you with the tools needed to deliver polished, user-friendly experiences.

',23)]))}const p=o(r,[["render",l]]);export{g as __pageData,p as default}; diff --git a/assets/guide_faq.md.dIiCo_1b.js b/assets/guide_faq.md.dIiCo_1b.js new file mode 100644 index 00000000..0c21249b --- /dev/null +++ b/assets/guide_faq.md.dIiCo_1b.js @@ -0,0 +1,31 @@ +import{_ as i,c as a,a2 as t,o as e}from"./chunks/framework.Gfs4HC1t.js";const c=JSON.parse('{"title":"FAQ: Common Issues & Solutions","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/faq.md","filePath":"guide/faq.md","lastUpdated":1734691342000}'),n={name:"guide/faq.md"};function l(h,s,p,o,r,k){return e(),a("div",null,s[0]||(s[0]=[t(`

FAQ: Common Issues & Solutions

❓ What if a route doesn't load?

When using Nuxt I18n Micro, certain routes might not load as expected, especially if the router doesn't automatically assign a name to a route in subfolders.

Solution: To address this, manually define the route name for the page by adding the following to the corresponding Vue file:

javascript
definePageMeta({ name: 'pageName' })

This ensures the route is properly registered, enabling seamless navigation within the application.


❓ Why is the assets/_locales/ folder added to the server folder?

During deployment, especially on platforms like Netlify, the build process might differ from local development. This can lead to issues where certain files or folders are missing during server-side rendering (SSR).

Explanation:

  • Build Process: Translation files are cached in the production folder during the build. However, on Netlify, server code moves to functions, sometimes isolating localization files.
  • Prerendering: Prerendering does not work with $fetch in SSR, causing middleware to miss localization files.
  • Server Assets: To resolve this, localization files are saved in the Nitro server assets during prerendering. They are then accessible in production directly from server assets.

❓ Is Nuxt I18n Micro inspired by vue-i18n? What about modifiers?

While Nuxt I18n Micro serves as a performance alternative to nuxt-i18n, it’s built independently of vue-i18n. While some method names and parameters may be similar, the underlying functionality differs significantly.

Modifiers: The maintainer initially considered modifiers, but concluded that components like <i18n-t> and <i18n-link> effectively address those needs.

For example:

vue
<template>
+  <i18n-t keypath="feedback.text">
+    <template #link>
+      <nuxt-link :to="{ name: 'index' }">
+        <i18n-t keypath="feedback.link" />
+      </nuxt-link>
+    </template>
+  </i18n-t>
+</template>

This approach is flexible, so releasing modifiers is currently unnecessary. However, modifiers may be added in future releases if there is demand.


Yes, Nuxt I18n Micro allows the use of NuxtLink or i18nLink within translations through the <i18n-t> component, which is especially helpful for handling grammar and RTL language requirements without splitting translation strings.

Example:

Translation file:

json
{
+  "example": "Share your {link} with friends",
+  "link_text": "translation link"
+}

Vue template:

vue
<template>
+  <i18n-t keypath="example">
+    <template #link>
+      <nuxt-link :to="{ name: 'referral' }">
+        <i18n-t keypath="link_text" />
+      </nuxt-link>
+    </template>
+  </i18n-t>
+</template>

This allows dynamic links within translations while preserving proper localization structure.


❓ Why are translation keys not resolving during SSR on Vercel, and how can I fix the locale path issue?

$fetch limitations on SSR

On serverless platforms like Vercel, $fetch can only fetch static files from the CDN and not from the internal Nitro server. This means static translation files may not be directly accessible unless the correct base URL is set.

Fix by setting apiBaseUrl

If translations are hosted externally, specify the full URL (e.g., https://example.com/_locales) for $fetch to access the translations correctly during SSR.

Example:

js
{
+  // ...
+  apiBaseUrl: 'https://example.com/_locales'
+  // ...
+}

❓ Why does $t or other i18n composables not work in Nuxt plugins?

Nuxt I18n composables ($t, $getLocale, $localePath, etc.) may not work as expected within Nuxt plugins or utility functions, resulting in runtime errors.

Cause and Solution: Nuxt composables require specific contexts (e.g., Nuxt hooks or Vue setup functions) to access the Nuxt instance. If used outside of these contexts (e.g., in utility functions or plugins), the following error might appear in the console:

[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables

Solution 1: Use runWithContext To call i18n composables after an asynchronous operation, use runWithContext to preserve the necessary context.

Example:

javascript
await nuxtApp.runWithContext(() => $t('test_key'))

Solution 2: Retrieve Value First Alternatively, retrieve the translation value first, then pass it to a utility function.

Example:

javascript
const val = nuxtApp.$t('common.errors.unknown.title')
+showError({
+    title: val
+})

Solution 3: Pass Translation Keys in Services In services or utility functions, pass the translation keys instead of using $t directly. Then, fetch the translation in the component.

Example:

javascript
showError({
+  title: 'common.errors.unknown.title',
+  message: 'common.errors.unknown.message',
+  i18n: true
+})

These solutions help maintain context and reduce errors, allowing for flexibility in handling translations across the application.

`,50)]))}const E=i(n,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/guide_faq.md.dIiCo_1b.lean.js b/assets/guide_faq.md.dIiCo_1b.lean.js new file mode 100644 index 00000000..0c21249b --- /dev/null +++ b/assets/guide_faq.md.dIiCo_1b.lean.js @@ -0,0 +1,31 @@ +import{_ as i,c as a,a2 as t,o as e}from"./chunks/framework.Gfs4HC1t.js";const c=JSON.parse('{"title":"FAQ: Common Issues & Solutions","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/faq.md","filePath":"guide/faq.md","lastUpdated":1734691342000}'),n={name:"guide/faq.md"};function l(h,s,p,o,r,k){return e(),a("div",null,s[0]||(s[0]=[t(`

FAQ: Common Issues & Solutions

❓ What if a route doesn't load?

When using Nuxt I18n Micro, certain routes might not load as expected, especially if the router doesn't automatically assign a name to a route in subfolders.

Solution: To address this, manually define the route name for the page by adding the following to the corresponding Vue file:

javascript
definePageMeta({ name: 'pageName' })

This ensures the route is properly registered, enabling seamless navigation within the application.


❓ Why is the assets/_locales/ folder added to the server folder?

During deployment, especially on platforms like Netlify, the build process might differ from local development. This can lead to issues where certain files or folders are missing during server-side rendering (SSR).

Explanation:

  • Build Process: Translation files are cached in the production folder during the build. However, on Netlify, server code moves to functions, sometimes isolating localization files.
  • Prerendering: Prerendering does not work with $fetch in SSR, causing middleware to miss localization files.
  • Server Assets: To resolve this, localization files are saved in the Nitro server assets during prerendering. They are then accessible in production directly from server assets.

❓ Is Nuxt I18n Micro inspired by vue-i18n? What about modifiers?

While Nuxt I18n Micro serves as a performance alternative to nuxt-i18n, it’s built independently of vue-i18n. While some method names and parameters may be similar, the underlying functionality differs significantly.

Modifiers: The maintainer initially considered modifiers, but concluded that components like <i18n-t> and <i18n-link> effectively address those needs.

For example:

vue
<template>
+  <i18n-t keypath="feedback.text">
+    <template #link>
+      <nuxt-link :to="{ name: 'index' }">
+        <i18n-t keypath="feedback.link" />
+      </nuxt-link>
+    </template>
+  </i18n-t>
+</template>

This approach is flexible, so releasing modifiers is currently unnecessary. However, modifiers may be added in future releases if there is demand.


Yes, Nuxt I18n Micro allows the use of NuxtLink or i18nLink within translations through the <i18n-t> component, which is especially helpful for handling grammar and RTL language requirements without splitting translation strings.

Example:

Translation file:

json
{
+  "example": "Share your {link} with friends",
+  "link_text": "translation link"
+}

Vue template:

vue
<template>
+  <i18n-t keypath="example">
+    <template #link>
+      <nuxt-link :to="{ name: 'referral' }">
+        <i18n-t keypath="link_text" />
+      </nuxt-link>
+    </template>
+  </i18n-t>
+</template>

This allows dynamic links within translations while preserving proper localization structure.


❓ Why are translation keys not resolving during SSR on Vercel, and how can I fix the locale path issue?

$fetch limitations on SSR

On serverless platforms like Vercel, $fetch can only fetch static files from the CDN and not from the internal Nitro server. This means static translation files may not be directly accessible unless the correct base URL is set.

Fix by setting apiBaseUrl

If translations are hosted externally, specify the full URL (e.g., https://example.com/_locales) for $fetch to access the translations correctly during SSR.

Example:

js
{
+  // ...
+  apiBaseUrl: 'https://example.com/_locales'
+  // ...
+}

❓ Why does $t or other i18n composables not work in Nuxt plugins?

Nuxt I18n composables ($t, $getLocale, $localePath, etc.) may not work as expected within Nuxt plugins or utility functions, resulting in runtime errors.

Cause and Solution: Nuxt composables require specific contexts (e.g., Nuxt hooks or Vue setup functions) to access the Nuxt instance. If used outside of these contexts (e.g., in utility functions or plugins), the following error might appear in the console:

[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables

Solution 1: Use runWithContext To call i18n composables after an asynchronous operation, use runWithContext to preserve the necessary context.

Example:

javascript
await nuxtApp.runWithContext(() => $t('test_key'))

Solution 2: Retrieve Value First Alternatively, retrieve the translation value first, then pass it to a utility function.

Example:

javascript
const val = nuxtApp.$t('common.errors.unknown.title')
+showError({
+    title: val
+})

Solution 3: Pass Translation Keys in Services In services or utility functions, pass the translation keys instead of using $t directly. Then, fetch the translation in the component.

Example:

javascript
showError({
+  title: 'common.errors.unknown.title',
+  message: 'common.errors.unknown.message',
+  i18n: true
+})

These solutions help maintain context and reduce errors, allowing for flexibility in handling translations across the application.

`,50)]))}const E=i(n,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/guide_folder-structure.md.B7ryKxoT.js b/assets/guide_folder-structure.md.B7ryKxoT.js new file mode 100644 index 00000000..24fa3ccd --- /dev/null +++ b/assets/guide_folder-structure.md.B7ryKxoT.js @@ -0,0 +1,44 @@ +import{_ as s,c as e,a2 as n,o as i}from"./chunks/framework.Gfs4HC1t.js";const u=JSON.parse('{"title":"📂 Folder Structure Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/folder-structure.md","filePath":"guide/folder-structure.md","lastUpdated":1724243643000}'),t={name:"guide/folder-structure.md"};function o(l,a,r,p,d,c){return i(),e("div",null,a[0]||(a[0]=[n(`

📂 Folder Structure Guide

📖 Introduction

Organizing your translation files effectively is essential for maintaining a scalable and efficient internationalization (i18n) system. Nuxt I18n Micro simplifies this process by offering a clear approach to managing global and page-specific translations. This guide will walk you through the recommended folder structure and explain how Nuxt I18n Micro handles these translations.

Nuxt I18n Micro organizes translations into global files and page-specific files within the pages directory. This ensures that only the necessary translation data is loaded when required, optimizing both performance and organization.

🔧 Basic Structure

Here’s a basic example of the folder structure you should follow:

plaintext
  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json

📄 Explanation of Structure

1. 🌍 Global Translation Files

  • Path: /locales/{locale}.json (e.g., /locales/en.json)

  • Purpose: These files contain translations that are shared across the entire application. This is useful for common elements like navigation menus, headers, footers, or any text that appears on multiple pages.

    Example Content (/locales/en.json):

    json
    {
    +  "menu": {
    +    "home": "Home",
    +    "about": "About Us",
    +    "contact": "Contact"
    +  },
    +  "footer": {
    +    "copyright": "© 2024 Your Company"
    +  }
    +}

2. 📄 Page-Specific Translation Files

  • Path: /locales/pages/{routeName}/{locale}.json (e.g., /locales/pages/index/en.json)

  • Purpose: These files are used for translations that are specific to individual pages. This allows you to load only the necessary translations when a user visits a particular page, which enhances performance by reducing the amount of data that needs to be loaded.

    Example Content (/locales/pages/index/en.json):

    json
    {
    +  "title": "Welcome to Our Website",
    +  "description": "We offer a wide range of products and services to meet your needs."
    +}

    Example Content (/locales/pages/about/en.json):

    json
    {
    +  "title": "About Us",
    +  "description": "Learn more about our mission, vision, and values."
    +}

📂 Handling Dynamic Routes and Nested Paths

Nuxt I18n Micro automatically transforms dynamic segments and nested paths in routes into a flat folder structure using a specific renaming convention. This ensures that all translations are stored in a consistent and easily accessible manner.

Dynamic Route Translation Folder Structure

When dealing with dynamic routes, such as /products/[id], the module converts the dynamic segment [id] into a static format within the file structure.

Example Folder Structure for Dynamic Routes:

For a route like /products/[id], the translation files would be stored in a folder named products-id:

plaintext
  /locales/pages
+  ├── /products-id
+  │   ├── en.json
+  │   ├── fr.json
+  │   └── ar.json

Example Folder Structure for Nested Dynamic Routes:

For a nested route like /products/key/[id], the translation files would be stored in a folder named products-key-id:

plaintext
  /locales/pages
+  ├── /products-key-id
+  │   ├── en.json
+  │   ├── fr.json
+  │   └── ar.json

Example Folder Structure for Multi-Level Nested Routes:

For a more complex nested route like /products/category/[id]/details, the translation files would be stored in a folder named products-category-id-details:

plaintext
  /locales/pages
+  ├── /products-category-id-details
+  │   ├── en.json
+  │   ├── fr.json
+  │   └── ar.json

🛠 Customizing the Directory Structure

If you prefer to store translations in a different directory, Nuxt I18n Micro allows you to customize the directory where translation files are stored. You can configure this in your nuxt.config.ts file.

Example: Customizing the Translation Directory

typescript
export default defineNuxtConfig({
+  i18n: {
+    translationDir: 'i18n' // Custom directory path
+  }
+})

This will instruct Nuxt I18n Micro to look for translation files in the /i18n directory instead of the default /locales directory.

⚙️ How Translations are Loaded

🌍 Dynamic Locale Routes

Nuxt I18n Micro uses dynamic locale routes to load translations efficiently. When a user visits a page, the module determines the appropriate locale and loads the corresponding translation files based on the current route and locale.

For example:

  • Visiting /en/index will load translations from /locales/pages/index/en.json.
  • Visiting /fr/about will load translations from /locales/pages/about/fr.json.

This method ensures that only the necessary translations are loaded, optimizing both server load and client-side performance.

💾 Caching and Pre-rendering

To further enhance performance, Nuxt I18n Micro supports caching and pre-rendering of translation files:

  • Caching: Once a translation file is loaded, it’s cached for subsequent requests, reducing the need to repeatedly fetch the same data.
  • Pre-rendering: During the build process, you can pre-render translation files for all configured locales and routes, allowing them to be served directly from the server without runtime delays.

📝 Best Practices

📂 Use Page-Specific Files Wisely

Leverage page-specific files to avoid bloating global translation files. This keeps each page’s translations lean and fast to load, which is especially important for pages with complex or large content.

🔑 Keep Translation Keys Consistent

Use consistent naming conventions for your translation keys across files. This helps maintain clarity and prevents issues when managing translations, especially as your application grows.

🗂️ Organize Translations by Context

Group related translations together within your files. For example, group all button labels under a buttons key and all form-related texts under a forms key. This not only improves readability but also makes it easier to manage translations across different locales.

🧹 Regularly Clean Up Unused Translations

Over time, your application might accumulate unused translation keys, especially if features are removed or restructured. Periodically review and clean up your translation files to keep them lean and maintainable.

`,49)]))}const g=s(t,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_folder-structure.md.B7ryKxoT.lean.js b/assets/guide_folder-structure.md.B7ryKxoT.lean.js new file mode 100644 index 00000000..24fa3ccd --- /dev/null +++ b/assets/guide_folder-structure.md.B7ryKxoT.lean.js @@ -0,0 +1,44 @@ +import{_ as s,c as e,a2 as n,o as i}from"./chunks/framework.Gfs4HC1t.js";const u=JSON.parse('{"title":"📂 Folder Structure Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/folder-structure.md","filePath":"guide/folder-structure.md","lastUpdated":1724243643000}'),t={name:"guide/folder-structure.md"};function o(l,a,r,p,d,c){return i(),e("div",null,a[0]||(a[0]=[n(`

📂 Folder Structure Guide

📖 Introduction

Organizing your translation files effectively is essential for maintaining a scalable and efficient internationalization (i18n) system. Nuxt I18n Micro simplifies this process by offering a clear approach to managing global and page-specific translations. This guide will walk you through the recommended folder structure and explain how Nuxt I18n Micro handles these translations.

Nuxt I18n Micro organizes translations into global files and page-specific files within the pages directory. This ensures that only the necessary translation data is loaded when required, optimizing both performance and organization.

🔧 Basic Structure

Here’s a basic example of the folder structure you should follow:

plaintext
  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json

📄 Explanation of Structure

1. 🌍 Global Translation Files

  • Path: /locales/{locale}.json (e.g., /locales/en.json)

  • Purpose: These files contain translations that are shared across the entire application. This is useful for common elements like navigation menus, headers, footers, or any text that appears on multiple pages.

    Example Content (/locales/en.json):

    json
    {
    +  "menu": {
    +    "home": "Home",
    +    "about": "About Us",
    +    "contact": "Contact"
    +  },
    +  "footer": {
    +    "copyright": "© 2024 Your Company"
    +  }
    +}

2. 📄 Page-Specific Translation Files

  • Path: /locales/pages/{routeName}/{locale}.json (e.g., /locales/pages/index/en.json)

  • Purpose: These files are used for translations that are specific to individual pages. This allows you to load only the necessary translations when a user visits a particular page, which enhances performance by reducing the amount of data that needs to be loaded.

    Example Content (/locales/pages/index/en.json):

    json
    {
    +  "title": "Welcome to Our Website",
    +  "description": "We offer a wide range of products and services to meet your needs."
    +}

    Example Content (/locales/pages/about/en.json):

    json
    {
    +  "title": "About Us",
    +  "description": "Learn more about our mission, vision, and values."
    +}

📂 Handling Dynamic Routes and Nested Paths

Nuxt I18n Micro automatically transforms dynamic segments and nested paths in routes into a flat folder structure using a specific renaming convention. This ensures that all translations are stored in a consistent and easily accessible manner.

Dynamic Route Translation Folder Structure

When dealing with dynamic routes, such as /products/[id], the module converts the dynamic segment [id] into a static format within the file structure.

Example Folder Structure for Dynamic Routes:

For a route like /products/[id], the translation files would be stored in a folder named products-id:

plaintext
  /locales/pages
+  ├── /products-id
+  │   ├── en.json
+  │   ├── fr.json
+  │   └── ar.json

Example Folder Structure for Nested Dynamic Routes:

For a nested route like /products/key/[id], the translation files would be stored in a folder named products-key-id:

plaintext
  /locales/pages
+  ├── /products-key-id
+  │   ├── en.json
+  │   ├── fr.json
+  │   └── ar.json

Example Folder Structure for Multi-Level Nested Routes:

For a more complex nested route like /products/category/[id]/details, the translation files would be stored in a folder named products-category-id-details:

plaintext
  /locales/pages
+  ├── /products-category-id-details
+  │   ├── en.json
+  │   ├── fr.json
+  │   └── ar.json

🛠 Customizing the Directory Structure

If you prefer to store translations in a different directory, Nuxt I18n Micro allows you to customize the directory where translation files are stored. You can configure this in your nuxt.config.ts file.

Example: Customizing the Translation Directory

typescript
export default defineNuxtConfig({
+  i18n: {
+    translationDir: 'i18n' // Custom directory path
+  }
+})

This will instruct Nuxt I18n Micro to look for translation files in the /i18n directory instead of the default /locales directory.

⚙️ How Translations are Loaded

🌍 Dynamic Locale Routes

Nuxt I18n Micro uses dynamic locale routes to load translations efficiently. When a user visits a page, the module determines the appropriate locale and loads the corresponding translation files based on the current route and locale.

For example:

  • Visiting /en/index will load translations from /locales/pages/index/en.json.
  • Visiting /fr/about will load translations from /locales/pages/about/fr.json.

This method ensures that only the necessary translations are loaded, optimizing both server load and client-side performance.

💾 Caching and Pre-rendering

To further enhance performance, Nuxt I18n Micro supports caching and pre-rendering of translation files:

  • Caching: Once a translation file is loaded, it’s cached for subsequent requests, reducing the need to repeatedly fetch the same data.
  • Pre-rendering: During the build process, you can pre-render translation files for all configured locales and routes, allowing them to be served directly from the server without runtime delays.

📝 Best Practices

📂 Use Page-Specific Files Wisely

Leverage page-specific files to avoid bloating global translation files. This keeps each page’s translations lean and fast to load, which is especially important for pages with complex or large content.

🔑 Keep Translation Keys Consistent

Use consistent naming conventions for your translation keys across files. This helps maintain clarity and prevents issues when managing translations, especially as your application grows.

🗂️ Organize Translations by Context

Group related translations together within your files. For example, group all button labels under a buttons key and all form-related texts under a forms key. This not only improves readability but also makes it easier to manage translations across different locales.

🧹 Regularly Clean Up Unused Translations

Over time, your application might accumulate unused translation keys, especially if features are removed or restructured. Periodically review and clean up your translation files to keep them lean and maintainable.

`,49)]))}const g=s(t,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_getting-started.md.DMTe_ufE.js b/assets/guide_getting-started.md.DMTe_ufE.js new file mode 100644 index 00000000..58004bbb --- /dev/null +++ b/assets/guide_getting-started.md.DMTe_ufE.js @@ -0,0 +1,74 @@ +import{_ as i,c as a,a2 as e,o as t}from"./chunks/framework.Gfs4HC1t.js";const c=JSON.parse('{"title":"🌐 Getting Started with Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/getting-started.md","filePath":"guide/getting-started.md","lastUpdated":1736853461000}'),n={name:"guide/getting-started.md"};function l(p,s,h,o,r,d){return t(),a("div",null,s[0]||(s[0]=[e(`

🌐 Getting Started with Nuxt I18n Micro

📖 Overview

Nuxt I18n Micro is a lightweight internationalization module for Nuxt that delivers superior performance compared to traditional solutions. It's designed to reduce build times, memory usage, and server load, making it ideal for high-traffic and large projects.

🤔 Why Choose Nuxt I18n Micro?

Here are some key benefits of using Nuxt I18n Micro:

  • 🚀 High Performance: Significantly reduces build times and memory consumption.
  • 📦 Compact Size: Has minimal impact on your app's bundle size.
  • ⚙️ Efficiency: Optimized for large-scale applications with a focus on memory consumption and server load.

🛠 Installation

To install the module in your Nuxt application, run the following command:

bash
npm install nuxt-i18n-micro

⚙️ Basic Setup

After installation, add the module to your nuxt.config.ts file:

typescript
export default defineNuxtConfig({
+  modules: [
+    'nuxt-i18n-micro',
+  ],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

📂 Folder Structure

Translation files are organized into global and page-specific directories:

  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json
  • Global Files: Contain translations shared across the entire app.
  • Page-Specific Files: Contain translations unique to specific pages.

⚙️ Module Configuration Options

The Nuxt I18n Micro module provides a range of customizable options to fine-tune your internationalization setup:

Here’s the updated documentation for locales, including the new baseUrl and baseDefault properties:

🌍 locales

Defines the locales available in your application.

Type: Locale[]

Each locale object can include the following properties:

  • code (string, required): A unique identifier for the locale, e.g., 'en' for English.
  • iso (string, optional): The ISO code for the locale, such as 'en-US'. This can be used for the lang attribute in HTML to help with accessibility and SEO.
  • dir (string, optional): Specifies the text direction for the locale, either 'ltr' (left-to-right) or 'rtl' (right-to-left).
  • disabled (boolean, optional): Disables the locale in the dropdown if set to true, preventing users from selecting it.
  • baseUrl (string, optional): Sets a base URL for the locale, which should be used to configure redirection for locale-specific domains or subdomains. The actual redirection implementation should be handled in layers outside of this configuration, as setting baseUrl alone means all links within the project will direct to the specified domain. Additionally, this parameter requires an explicit protocol, either http or https.
  • baseDefault (boolean, optional): If set to true, the locale's routes do not include the locale code in the URL path, making it the default locale.

Example:

typescript
locales: [
+  { code: 'en', iso: 'en-US', dir: 'ltr' },
+  { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+  { code: 'ar', iso: 'ar-SA', dir: 'rtl', disabled: true },
+  { code: 'de', iso: 'de-DE', dir: 'ltr', baseUrl: 'https://de.example.com', baseDefault: true },
+  { code: 'es', iso: 'es-ES', dir: 'ltr', baseUrl: 'https://es.example.com', baseDefault: true },
+  { code: 'ja', iso: 'ja-JP', dir: 'ltr', baseUrl: 'https://new.example.com' }
+]

In this example:

  • The ar locale is disabled.
  • de and es each have their own baseUrl and baseDefault, meaning routes for these locales will start with their respective URLs (https://de.example.com, https://es.example.com).
  • ja each have their own baseUrl, meaning routes for these locales will start with their respective URLs (https://new.example.com/ja).

Additional Notes:

  • If baseUrl is provided, it will override the default routing structure, adding the baseUrl prefix to all routes for that locale. However, using baseUrl is generally not recommended, as it can lead to duplication of all internal routes as external links, complicating routing and maintenance. Instead, it is often simpler and more manageable to create external links directly for specific locales.
  • When baseDefault is set to true, the specified locale's URLs will not include the locale code prefix, making it appear as the primary or default language. Note that baseDefault works only in combination with baseUrl.

🌐 defaultLocale

Sets the default locale if no specific locale is selected by the user.

Type: string

Example:

typescript
defaultLocale: 'en'

🗂 translationDir

Specifies the directory where translation files are stored.

Type: string
Default: 'locales'

Example:

typescript
translationDir: 'i18n' // Custom directory for translation files

🔍 meta

Automatically generates SEO-related meta tags, such as alternate links for different locales.

Type: boolean
Default: true

Example:

typescript
meta: true // Enable automatic SEO meta tags generation

🐛 debug

Enables logging and debugging information during the generation process to help with troubleshooting.

Type: boolean
Default: false

Example:

typescript
debug: true // Enable logging and debugging information

🐛 types

Adds types to the project during the postinstall process. If you encounter issues with types, you can disable this option.

Type: boolean
Default: true

Example:

typescript
types: true

🔗 metaBaseUrl

Sets the base URL for generating SEO-related meta tags like canonical and alternate URLs.

Type: string
Default: '/'

Example:

typescript
metaBaseUrl: 'https://example.com' // Custom base URL for meta tags

🌍 autoDetectLanguage

Automatically detects the user's preferred language based on browser settings and redirects to the appropriate locale.

Type: boolean
Default: false

Example:

typescript
autoDetectLanguage: true // Enable automatic language detection and redirection

🔍 autoDetectPath

Specifies the route path(s) on which locale auto-detection and switching should occur.

Type: string
Default: "/"

Description:
Defines the route(s) where locale detection is active. By default, locale detection happens only on the home route ("/").

Setting this to "*" enables locale detection on all routes. However, using "*" may cause unexpected issues, especially if cookies are disabled, as this can interfere with tracking the user's locale preference.

🔢 plural

Custom function for handling pluralization in translations based on count and locale.

Type: (key: string, count: number, params: Record<string, string | number | boolean>, locale: string, t: Getter) => string

Example:

typescript
export type Getter = (key: string, params?: Record<string, string | number | boolean>, defaultValue?: string) => unknown
+
+{
+  plural: (key: string, count: number, _params: Record<string, string | number | boolean>, _locale: string, t: Getter) => {
+    const translation = t(key)
+    if (!translation) {
+      return key
+    }
+    const forms = translation.toString().split('|')
+    return (count < forms.length ? forms[count].trim() : forms[forms.length - 1].trim()).replace('{count}', count.toString())
+  }
+}

🚦 includeDefaultLocaleRoute

(Deprecated)

Automatically redirects routes without a locale prefix to the default locale.

Type: boolean
Default: false

Deprecated: As of version 1.50.0, includeDefaultLocaleRoute is deprecated. Use the strategy option instead for more flexible route handling.

🚦 strategy

Version introduced: v1.50.0

Defines how locale prefixes should be handled in routes. Choose the strategy that best fits your use case.

Type: string
Default: prefix_and_default

Available Strategies:

  • no_prefix
    Routes will not have a locale prefix. The locale will be detected and changed without modifying the URL. Locale detection relies on the browser and cookies, and you need to manage locale switching through the i18n API.
    Note: This strategy does not support features like Custom paths or Ignore routes.

  • prefix_except_default
    A locale prefix will be added to all routes, except for the default language. URLs for the default language will not include a prefix.

  • prefix
    All routes will include a locale prefix, regardless of the language.

  • prefix_and_default
    Combines both previous behaviors. URLs for every language will have a locale prefix, while URLs for the default language will have a non-prefixed version. However, if detectBrowserLanguage is enabled, the prefixed version will be preferred for the default language.

🚦 customRegexMatcher

I18n-micro meticulously checks each locale via vue-router route regex. If you have a lot of locales, you can improve pattern matching performances via a custom regex matcher.

Type: string | RegExp
Default: false

Example:

typescript
customRegexMatcher: '[a-z]-[A-Z]'// This matches locales in isoCode (e.g: '/en-US', 'de-DE' etc)

Creates links between different pages' locale files to share translations, reducing duplication.

Type: Record<string, string>

Example:

typescript
{
+  routesLocaleLinks: {
+    'products-id': 'products', 
+    'about-us': 'about'
+  }
+}

🧩 define

Enables or disables the addition of a special define plugin that allows you to use Nuxt's runtime configuration for overriding settings in your translation files.

Type: boolean
Default: true

Example:

typescript
define: false // Disable the define plugin

🧩 plugin

Enables or disables a special plugin that integrates additional features or functionality into your Nuxt application.

Type: boolean
Default: true

Example:

typescript
plugin: false // Disable the plugin

🔄 disablePageLocales

Allows you to disable page-specific translations, limiting the module to only use global translation files.

Type: boolean
Default: false

Example:

typescript
disablePageLocales: true // Disable page-specific translations, using only global translations

📂 Folder Structure with disablePageLocales: true

When disablePageLocales is enabled, the module will only use the translations defined in the global files located directly under the locales directory. Page-specific translation files (located in /locales/pages) will be ignored.

  /locales
+  ├── en.json
+  ├── fr.json
+  └── ar.json

👀 disableWatcher

Disables the automatic creation of locale files during development.

Type: boolean
Default: false

Example:

typescript
disableWatcher: true // Disables the automatic creation of locale files

👀 disableUpdater

Version introduced: v1.60.0

Disables the file watcher for updating store items during development.

Type: boolean
Default: false

Example:

typescript
disableUpdater: true // Disables the file watcher for updating store items

🔗 apiBaseUrl

env: NUXT_I18N_APP_BASE_URL

Defines the base URL that the server will use to fetch cached translations. By default, this is set to _locales, but you can change it to any custom path, such as api/_locales, if you want to load translations from a different endpoint.

Type: string
Default: '_locales'

Example:

typescript
apiBaseUrl: 'api/_locales' // Custom URL for fetching cached translations

When set, the module will use the specified URL to request cached translations instead of using the default _locales.

🍪 localeCookie

Specifies the name of the cookie used to store the user's selected locale.

Type: string
Default: 'user-locale'

🌐 fallbackLocale

Specifies a fallback locale to be used when the current locale does not have a specific translation available.

Type: string | undefined
Default: undefined

Example:

typescript
{
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'es', iso: 'es-ES', dir: 'ltr' }
+    ],
+    defaultLocale: 'en',
+    // Use English as a fallback locale
+    fallbackLocale: 'en'
+  }
+}

🌐 globalLocaleRoutes

Allows you to define custom localized routes for specific pages. You can specify a custom path for each locale for a given page, or disable localization for certain pages entirely.

Type: Record<string, Record<string, string> | false>

  • Key (string): The name of the page you want to customize or disable localization for.
  • Value:
    • Record<string, string>: A set of locale codes with corresponding custom paths for the page.
    • false: Disable localization for this page entirely. The page will not be localized, and it will remain accessible only through its default path.

This option gives you the flexibility to localize certain pages differently while leaving others unaffected by localization.

Example:

typescript
{
+  globalLocaleRoutes: {
+    page2: {
+      en: '/custom-page2-en',
+        de: '/custom-page2-de',
+        ru: '/custom-page2-ru'
+    },
+    // Unlocalized page should not be localized
+    unlocalized: false
+  }
+}

Usage:

In the example above:

  • page2: Custom localized paths are defined for the page page2 in English (en), German (de), and Russian (ru). Instead of following the standard localization pattern (like /en/page2), each locale will have a completely custom URL, such as /en/custom-page2-en for English, /de/custom-page2-de for German, and /ru/custom-page2-ru for Russian.
  • unlocalized: This page will not be localized, so it remains accessible only at /unlocalized, without any locale prefixes or custom paths.

🔄 Caching Mechanism

One of the standout features of Nuxt I18n Micro is its intelligent caching system. When a translation is requested during server-side rendering (SSR), the result is stored in a cache. This means that subsequent requests for the same translation can

retrieve the data from the cache rather than searching through the translation files again. This caching mechanism drastically reduces the time needed to fetch translations and significantly lowers the server's resource consumption.

`,154)]))}const g=i(n,[["render",l]]);export{c as __pageData,g as default}; diff --git a/assets/guide_getting-started.md.DMTe_ufE.lean.js b/assets/guide_getting-started.md.DMTe_ufE.lean.js new file mode 100644 index 00000000..58004bbb --- /dev/null +++ b/assets/guide_getting-started.md.DMTe_ufE.lean.js @@ -0,0 +1,74 @@ +import{_ as i,c as a,a2 as e,o as t}from"./chunks/framework.Gfs4HC1t.js";const c=JSON.parse('{"title":"🌐 Getting Started with Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/getting-started.md","filePath":"guide/getting-started.md","lastUpdated":1736853461000}'),n={name:"guide/getting-started.md"};function l(p,s,h,o,r,d){return t(),a("div",null,s[0]||(s[0]=[e(`

🌐 Getting Started with Nuxt I18n Micro

📖 Overview

Nuxt I18n Micro is a lightweight internationalization module for Nuxt that delivers superior performance compared to traditional solutions. It's designed to reduce build times, memory usage, and server load, making it ideal for high-traffic and large projects.

🤔 Why Choose Nuxt I18n Micro?

Here are some key benefits of using Nuxt I18n Micro:

  • 🚀 High Performance: Significantly reduces build times and memory consumption.
  • 📦 Compact Size: Has minimal impact on your app's bundle size.
  • ⚙️ Efficiency: Optimized for large-scale applications with a focus on memory consumption and server load.

🛠 Installation

To install the module in your Nuxt application, run the following command:

bash
npm install nuxt-i18n-micro

⚙️ Basic Setup

After installation, add the module to your nuxt.config.ts file:

typescript
export default defineNuxtConfig({
+  modules: [
+    'nuxt-i18n-micro',
+  ],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

📂 Folder Structure

Translation files are organized into global and page-specific directories:

  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json
  • Global Files: Contain translations shared across the entire app.
  • Page-Specific Files: Contain translations unique to specific pages.

⚙️ Module Configuration Options

The Nuxt I18n Micro module provides a range of customizable options to fine-tune your internationalization setup:

Here’s the updated documentation for locales, including the new baseUrl and baseDefault properties:

🌍 locales

Defines the locales available in your application.

Type: Locale[]

Each locale object can include the following properties:

  • code (string, required): A unique identifier for the locale, e.g., 'en' for English.
  • iso (string, optional): The ISO code for the locale, such as 'en-US'. This can be used for the lang attribute in HTML to help with accessibility and SEO.
  • dir (string, optional): Specifies the text direction for the locale, either 'ltr' (left-to-right) or 'rtl' (right-to-left).
  • disabled (boolean, optional): Disables the locale in the dropdown if set to true, preventing users from selecting it.
  • baseUrl (string, optional): Sets a base URL for the locale, which should be used to configure redirection for locale-specific domains or subdomains. The actual redirection implementation should be handled in layers outside of this configuration, as setting baseUrl alone means all links within the project will direct to the specified domain. Additionally, this parameter requires an explicit protocol, either http or https.
  • baseDefault (boolean, optional): If set to true, the locale's routes do not include the locale code in the URL path, making it the default locale.

Example:

typescript
locales: [
+  { code: 'en', iso: 'en-US', dir: 'ltr' },
+  { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+  { code: 'ar', iso: 'ar-SA', dir: 'rtl', disabled: true },
+  { code: 'de', iso: 'de-DE', dir: 'ltr', baseUrl: 'https://de.example.com', baseDefault: true },
+  { code: 'es', iso: 'es-ES', dir: 'ltr', baseUrl: 'https://es.example.com', baseDefault: true },
+  { code: 'ja', iso: 'ja-JP', dir: 'ltr', baseUrl: 'https://new.example.com' }
+]

In this example:

  • The ar locale is disabled.
  • de and es each have their own baseUrl and baseDefault, meaning routes for these locales will start with their respective URLs (https://de.example.com, https://es.example.com).
  • ja each have their own baseUrl, meaning routes for these locales will start with their respective URLs (https://new.example.com/ja).

Additional Notes:

  • If baseUrl is provided, it will override the default routing structure, adding the baseUrl prefix to all routes for that locale. However, using baseUrl is generally not recommended, as it can lead to duplication of all internal routes as external links, complicating routing and maintenance. Instead, it is often simpler and more manageable to create external links directly for specific locales.
  • When baseDefault is set to true, the specified locale's URLs will not include the locale code prefix, making it appear as the primary or default language. Note that baseDefault works only in combination with baseUrl.

🌐 defaultLocale

Sets the default locale if no specific locale is selected by the user.

Type: string

Example:

typescript
defaultLocale: 'en'

🗂 translationDir

Specifies the directory where translation files are stored.

Type: string
Default: 'locales'

Example:

typescript
translationDir: 'i18n' // Custom directory for translation files

🔍 meta

Automatically generates SEO-related meta tags, such as alternate links for different locales.

Type: boolean
Default: true

Example:

typescript
meta: true // Enable automatic SEO meta tags generation

🐛 debug

Enables logging and debugging information during the generation process to help with troubleshooting.

Type: boolean
Default: false

Example:

typescript
debug: true // Enable logging and debugging information

🐛 types

Adds types to the project during the postinstall process. If you encounter issues with types, you can disable this option.

Type: boolean
Default: true

Example:

typescript
types: true

🔗 metaBaseUrl

Sets the base URL for generating SEO-related meta tags like canonical and alternate URLs.

Type: string
Default: '/'

Example:

typescript
metaBaseUrl: 'https://example.com' // Custom base URL for meta tags

🌍 autoDetectLanguage

Automatically detects the user's preferred language based on browser settings and redirects to the appropriate locale.

Type: boolean
Default: false

Example:

typescript
autoDetectLanguage: true // Enable automatic language detection and redirection

🔍 autoDetectPath

Specifies the route path(s) on which locale auto-detection and switching should occur.

Type: string
Default: "/"

Description:
Defines the route(s) where locale detection is active. By default, locale detection happens only on the home route ("/").

Setting this to "*" enables locale detection on all routes. However, using "*" may cause unexpected issues, especially if cookies are disabled, as this can interfere with tracking the user's locale preference.

🔢 plural

Custom function for handling pluralization in translations based on count and locale.

Type: (key: string, count: number, params: Record<string, string | number | boolean>, locale: string, t: Getter) => string

Example:

typescript
export type Getter = (key: string, params?: Record<string, string | number | boolean>, defaultValue?: string) => unknown
+
+{
+  plural: (key: string, count: number, _params: Record<string, string | number | boolean>, _locale: string, t: Getter) => {
+    const translation = t(key)
+    if (!translation) {
+      return key
+    }
+    const forms = translation.toString().split('|')
+    return (count < forms.length ? forms[count].trim() : forms[forms.length - 1].trim()).replace('{count}', count.toString())
+  }
+}

🚦 includeDefaultLocaleRoute

(Deprecated)

Automatically redirects routes without a locale prefix to the default locale.

Type: boolean
Default: false

Deprecated: As of version 1.50.0, includeDefaultLocaleRoute is deprecated. Use the strategy option instead for more flexible route handling.

🚦 strategy

Version introduced: v1.50.0

Defines how locale prefixes should be handled in routes. Choose the strategy that best fits your use case.

Type: string
Default: prefix_and_default

Available Strategies:

  • no_prefix
    Routes will not have a locale prefix. The locale will be detected and changed without modifying the URL. Locale detection relies on the browser and cookies, and you need to manage locale switching through the i18n API.
    Note: This strategy does not support features like Custom paths or Ignore routes.

  • prefix_except_default
    A locale prefix will be added to all routes, except for the default language. URLs for the default language will not include a prefix.

  • prefix
    All routes will include a locale prefix, regardless of the language.

  • prefix_and_default
    Combines both previous behaviors. URLs for every language will have a locale prefix, while URLs for the default language will have a non-prefixed version. However, if detectBrowserLanguage is enabled, the prefixed version will be preferred for the default language.

🚦 customRegexMatcher

I18n-micro meticulously checks each locale via vue-router route regex. If you have a lot of locales, you can improve pattern matching performances via a custom regex matcher.

Type: string | RegExp
Default: false

Example:

typescript
customRegexMatcher: '[a-z]-[A-Z]'// This matches locales in isoCode (e.g: '/en-US', 'de-DE' etc)

Creates links between different pages' locale files to share translations, reducing duplication.

Type: Record<string, string>

Example:

typescript
{
+  routesLocaleLinks: {
+    'products-id': 'products', 
+    'about-us': 'about'
+  }
+}

🧩 define

Enables or disables the addition of a special define plugin that allows you to use Nuxt's runtime configuration for overriding settings in your translation files.

Type: boolean
Default: true

Example:

typescript
define: false // Disable the define plugin

🧩 plugin

Enables or disables a special plugin that integrates additional features or functionality into your Nuxt application.

Type: boolean
Default: true

Example:

typescript
plugin: false // Disable the plugin

🔄 disablePageLocales

Allows you to disable page-specific translations, limiting the module to only use global translation files.

Type: boolean
Default: false

Example:

typescript
disablePageLocales: true // Disable page-specific translations, using only global translations

📂 Folder Structure with disablePageLocales: true

When disablePageLocales is enabled, the module will only use the translations defined in the global files located directly under the locales directory. Page-specific translation files (located in /locales/pages) will be ignored.

  /locales
+  ├── en.json
+  ├── fr.json
+  └── ar.json

👀 disableWatcher

Disables the automatic creation of locale files during development.

Type: boolean
Default: false

Example:

typescript
disableWatcher: true // Disables the automatic creation of locale files

👀 disableUpdater

Version introduced: v1.60.0

Disables the file watcher for updating store items during development.

Type: boolean
Default: false

Example:

typescript
disableUpdater: true // Disables the file watcher for updating store items

🔗 apiBaseUrl

env: NUXT_I18N_APP_BASE_URL

Defines the base URL that the server will use to fetch cached translations. By default, this is set to _locales, but you can change it to any custom path, such as api/_locales, if you want to load translations from a different endpoint.

Type: string
Default: '_locales'

Example:

typescript
apiBaseUrl: 'api/_locales' // Custom URL for fetching cached translations

When set, the module will use the specified URL to request cached translations instead of using the default _locales.

🍪 localeCookie

Specifies the name of the cookie used to store the user's selected locale.

Type: string
Default: 'user-locale'

🌐 fallbackLocale

Specifies a fallback locale to be used when the current locale does not have a specific translation available.

Type: string | undefined
Default: undefined

Example:

typescript
{
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'es', iso: 'es-ES', dir: 'ltr' }
+    ],
+    defaultLocale: 'en',
+    // Use English as a fallback locale
+    fallbackLocale: 'en'
+  }
+}

🌐 globalLocaleRoutes

Allows you to define custom localized routes for specific pages. You can specify a custom path for each locale for a given page, or disable localization for certain pages entirely.

Type: Record<string, Record<string, string> | false>

  • Key (string): The name of the page you want to customize or disable localization for.
  • Value:
    • Record<string, string>: A set of locale codes with corresponding custom paths for the page.
    • false: Disable localization for this page entirely. The page will not be localized, and it will remain accessible only through its default path.

This option gives you the flexibility to localize certain pages differently while leaving others unaffected by localization.

Example:

typescript
{
+  globalLocaleRoutes: {
+    page2: {
+      en: '/custom-page2-en',
+        de: '/custom-page2-de',
+        ru: '/custom-page2-ru'
+    },
+    // Unlocalized page should not be localized
+    unlocalized: false
+  }
+}

Usage:

In the example above:

  • page2: Custom localized paths are defined for the page page2 in English (en), German (de), and Russian (ru). Instead of following the standard localization pattern (like /en/page2), each locale will have a completely custom URL, such as /en/custom-page2-en for English, /de/custom-page2-de for German, and /ru/custom-page2-ru for Russian.
  • unlocalized: This page will not be localized, so it remains accessible only at /unlocalized, without any locale prefixes or custom paths.

🔄 Caching Mechanism

One of the standout features of Nuxt I18n Micro is its intelligent caching system. When a translation is requested during server-side rendering (SSR), the result is stored in a cache. This means that subsequent requests for the same translation can

retrieve the data from the cache rather than searching through the translation files again. This caching mechanism drastically reduces the time needed to fetch translations and significantly lowers the server's resource consumption.

`,154)]))}const g=i(n,[["render",l]]);export{c as __pageData,g as default}; diff --git a/assets/guide_layers.md.Bs1rVVV1.js b/assets/guide_layers.md.Bs1rVVV1.js new file mode 100644 index 00000000..b2c8f6de --- /dev/null +++ b/assets/guide_layers.md.Bs1rVVV1.js @@ -0,0 +1,72 @@ +import{_ as i,c as a,a2 as n,o as t}from"./chunks/framework.Gfs4HC1t.js";const o=JSON.parse('{"title":"🗂️ Layers in Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/layers.md","filePath":"guide/layers.md","lastUpdated":1724243643000}'),e={name:"guide/layers.md"};function l(h,s,p,k,r,E){return t(),a("div",null,s[0]||(s[0]=[n(`

🗂️ Layers in Nuxt I18n Micro

📖 Introduction to Layers

Layers in Nuxt I18n Micro allow you to manage and customize localization settings flexibly across different parts of your application. By defining different layers, you can adjust the configuration for various contexts, such as overriding settings for specific sections of your site or creating reusable base configurations that can be extended by other parts of your application.

🛠️ Primary Configuration Layer

The Primary Configuration Layer is where you set up the default localization settings for your entire application. This layer is essential as it defines the global configuration, including the supported locales, default language, and other critical i18n settings.

📄 Example: Defining the Primary Configuration Layer

Here’s an example of how you might define the primary configuration layer in your nuxt.config.ts file:

typescript
export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en', // The default locale for the entire app
+    translationDir: 'locales', // Directory where translations are stored
+    meta: true, // Automatically generate SEO-related meta tags like \`alternate\`
+    autoDetectLanguage: true, // Automatically detect and use the user's preferred language
+  },
+})

🌱 Child Layers

Child layers are used to extend or override the primary configuration for specific parts of your application. For instance, you might want to add additional locales or modify the default locale for a particular section of your site. Child layers are especially useful in modular applications where different parts of the application might have different localization requirements.

📄 Example: Extending the Primary Layer in a Child Layer

Suppose you have a section of your site that needs to support additional locales, or you want to disable a particular locale in a certain context. Here’s how you can achieve that by extending the primary configuration layer:

typescript
// basic/nuxt.config.ts (Primary Layer)
+export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    meta: true,
+    translationDir: 'locales',
+  },
+})
typescript
// extended/nuxt.config.ts (Child Layer)
+export default defineNuxtConfig({
+  extends: '../basic', // Inherit the base configuration from the 'basic' layer
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' }, // Inherited from the base layer
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Inherited from the base layer
+      { code: 'de', iso: 'de-DE', dir: 'ltr' }, // Added in the child layer
+    ],
+    defaultLocale: 'fr', // Override the default locale to French for this section
+    autoDetectLanguage: false, // Disable automatic language detection in this section
+  },
+})

🌐 Using Layers in a Modular Application

In a larger, modular Nuxt application, you might have multiple sections, each requiring its own i18n settings. By leveraging layers, you can maintain a clean and scalable configuration structure.

📄 Example: Layered Configuration in a Modular Application

Imagine you have an e-commerce site with distinct sections like the main website, admin panel, and customer support portal. Each section might need a different set of locales or other i18n settings.

Primary Layer (Global Configuration):

typescript
// nuxt.config.ts
+export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    meta: true,
+    translationDir: 'locales',
+    autoDetectLanguage: true,
+  },
+})

Child Layer for Admin Panel:

typescript
// admin/nuxt.config.ts
+export default defineNuxtConfig({
+  extends: '../nuxt.config', // Inherit the global settings
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' }, // Inherited
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Inherited
+      { code: 'es', iso: 'es-ES', dir: 'ltr' }, // Specific to the admin panel
+    ],
+    defaultLocale: 'en',
+    meta: false, // Disable automatic meta generation in the admin panel
+  },
+})

Child Layer for Customer Support Portal:

typescript
// support/nuxt.config.ts
+export default defineNuxtConfig({
+  extends: '../nuxt.config', // Inherit the global settings
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' }, // Inherited
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Inherited
+      { code: 'de', iso: 'de-DE', dir: 'ltr' }, // Specific to the support portal
+    ],
+    defaultLocale: 'de', // Default to German in the support portal
+    autoDetectLanguage: false, // Disable automatic language detection
+  },
+})

In this modular example:

  • Each section (admin, support) has its own i18n settings, but they all inherit the base configuration.
  • The admin panel adds Spanish (es) as a locale and disables meta tag generation.
  • The support portal adds German (de) as a locale and defaults to German for the user interface.

📝 Best Practices for Using Layers

  • 🔧 Keep the Primary Layer Simple: The primary layer should contain the most commonly used settings that apply globally across your application. Keep it straightforward to ensure consistency.
  • ⚙️ Use Child Layers for Specific Customizations: Only override or extend settings in child layers when necessary. This approach avoids unnecessary complexity in your configuration.
  • 📚 Document Your Layers: Clearly document the purpose and specifics of each layer in your project. This will help maintain clarity and make it easier for others (or future you) to understand the configuration.
`,28)]))}const y=i(e,[["render",l]]);export{o as __pageData,y as default}; diff --git a/assets/guide_layers.md.Bs1rVVV1.lean.js b/assets/guide_layers.md.Bs1rVVV1.lean.js new file mode 100644 index 00000000..b2c8f6de --- /dev/null +++ b/assets/guide_layers.md.Bs1rVVV1.lean.js @@ -0,0 +1,72 @@ +import{_ as i,c as a,a2 as n,o as t}from"./chunks/framework.Gfs4HC1t.js";const o=JSON.parse('{"title":"🗂️ Layers in Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/layers.md","filePath":"guide/layers.md","lastUpdated":1724243643000}'),e={name:"guide/layers.md"};function l(h,s,p,k,r,E){return t(),a("div",null,s[0]||(s[0]=[n(`

🗂️ Layers in Nuxt I18n Micro

📖 Introduction to Layers

Layers in Nuxt I18n Micro allow you to manage and customize localization settings flexibly across different parts of your application. By defining different layers, you can adjust the configuration for various contexts, such as overriding settings for specific sections of your site or creating reusable base configurations that can be extended by other parts of your application.

🛠️ Primary Configuration Layer

The Primary Configuration Layer is where you set up the default localization settings for your entire application. This layer is essential as it defines the global configuration, including the supported locales, default language, and other critical i18n settings.

📄 Example: Defining the Primary Configuration Layer

Here’s an example of how you might define the primary configuration layer in your nuxt.config.ts file:

typescript
export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en', // The default locale for the entire app
+    translationDir: 'locales', // Directory where translations are stored
+    meta: true, // Automatically generate SEO-related meta tags like \`alternate\`
+    autoDetectLanguage: true, // Automatically detect and use the user's preferred language
+  },
+})

🌱 Child Layers

Child layers are used to extend or override the primary configuration for specific parts of your application. For instance, you might want to add additional locales or modify the default locale for a particular section of your site. Child layers are especially useful in modular applications where different parts of the application might have different localization requirements.

📄 Example: Extending the Primary Layer in a Child Layer

Suppose you have a section of your site that needs to support additional locales, or you want to disable a particular locale in a certain context. Here’s how you can achieve that by extending the primary configuration layer:

typescript
// basic/nuxt.config.ts (Primary Layer)
+export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    meta: true,
+    translationDir: 'locales',
+  },
+})
typescript
// extended/nuxt.config.ts (Child Layer)
+export default defineNuxtConfig({
+  extends: '../basic', // Inherit the base configuration from the 'basic' layer
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' }, // Inherited from the base layer
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Inherited from the base layer
+      { code: 'de', iso: 'de-DE', dir: 'ltr' }, // Added in the child layer
+    ],
+    defaultLocale: 'fr', // Override the default locale to French for this section
+    autoDetectLanguage: false, // Disable automatic language detection in this section
+  },
+})

🌐 Using Layers in a Modular Application

In a larger, modular Nuxt application, you might have multiple sections, each requiring its own i18n settings. By leveraging layers, you can maintain a clean and scalable configuration structure.

📄 Example: Layered Configuration in a Modular Application

Imagine you have an e-commerce site with distinct sections like the main website, admin panel, and customer support portal. Each section might need a different set of locales or other i18n settings.

Primary Layer (Global Configuration):

typescript
// nuxt.config.ts
+export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    meta: true,
+    translationDir: 'locales',
+    autoDetectLanguage: true,
+  },
+})

Child Layer for Admin Panel:

typescript
// admin/nuxt.config.ts
+export default defineNuxtConfig({
+  extends: '../nuxt.config', // Inherit the global settings
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' }, // Inherited
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Inherited
+      { code: 'es', iso: 'es-ES', dir: 'ltr' }, // Specific to the admin panel
+    ],
+    defaultLocale: 'en',
+    meta: false, // Disable automatic meta generation in the admin panel
+  },
+})

Child Layer for Customer Support Portal:

typescript
// support/nuxt.config.ts
+export default defineNuxtConfig({
+  extends: '../nuxt.config', // Inherit the global settings
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' }, // Inherited
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Inherited
+      { code: 'de', iso: 'de-DE', dir: 'ltr' }, // Specific to the support portal
+    ],
+    defaultLocale: 'de', // Default to German in the support portal
+    autoDetectLanguage: false, // Disable automatic language detection
+  },
+})

In this modular example:

  • Each section (admin, support) has its own i18n settings, but they all inherit the base configuration.
  • The admin panel adds Spanish (es) as a locale and disables meta tag generation.
  • The support portal adds German (de) as a locale and defaults to German for the user interface.

📝 Best Practices for Using Layers

  • 🔧 Keep the Primary Layer Simple: The primary layer should contain the most commonly used settings that apply globally across your application. Keep it straightforward to ensure consistency.
  • ⚙️ Use Child Layers for Specific Customizations: Only override or extend settings in child layers when necessary. This approach avoids unnecessary complexity in your configuration.
  • 📚 Document Your Layers: Clearly document the purpose and specifics of each layer in your project. This will help maintain clarity and make it easier for others (or future you) to understand the configuration.
`,28)]))}const y=i(e,[["render",l]]);export{o as __pageData,y as default}; diff --git a/assets/guide_migration.md.DP2CIHWa.js b/assets/guide_migration.md.DP2CIHWa.js new file mode 100644 index 00000000..0eb2adbb --- /dev/null +++ b/assets/guide_migration.md.DP2CIHWa.js @@ -0,0 +1,36 @@ +import{_ as i,c as a,a2 as n,o as t}from"./chunks/framework.Gfs4HC1t.js";const c=JSON.parse('{"title":"🔄 Migration from nuxt-i18n to Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/migration.md","filePath":"guide/migration.md","lastUpdated":1724265480000}'),e={name:"guide/migration.md"};function l(o,s,h,p,r,d){return t(),a("div",null,s[0]||(s[0]=[n(`

🔄 Migration from nuxt-i18n to Nuxt I18n Micro

📖 Introduction

Migrating from nuxt-i18n to Nuxt I18n Micro can significantly improve the performance of your Nuxt application, especially in high-traffic environments or projects with large translation files. This guide provides a step-by-step approach to help you smoothly transition from nuxt-i18n to Nuxt I18n Micro.

🚀 Why Migrate?

The Nuxt I18n Micro module offers several advantages over the traditional nuxt-i18n:

  • ⚡ Improved Performance: Faster build times, lower memory usage, and smaller bundle sizes.
  • 🔧 Simplified Configuration: A more streamlined setup process with fewer moving parts.
  • 📉 Better Resource Management: Optimized handling of large translation files and reduced server load.

🔍 Key Differences

Before you begin the migration process, it’s essential to understand the key differences between nuxt-i18n and Nuxt I18n Micro:

  • 🌐 Route Management: Nuxt I18n Micro uses dynamic regex-based routing, generating only two routes regardless of the number of locales, unlike nuxt-i18n which creates a separate route for each locale.
  • 🗂️ Translation Files: Only JSON files are supported in Nuxt I18n Micro. The translations are split into global and page-specific files, which are auto-generated in development mode if not present.
  • 📈 SEO Integration: Nuxt I18n Micro offers built-in SEO optimization with automatic meta tag generation and support for hreflang tags.

🛠️ Step-by-Step Migration

1. 🛠️ Install Nuxt I18n Micro

First, add Nuxt I18n Micro to your Nuxt project:

bash
npm install nuxt-i18n-micro

2. 🔄 Update Configuration

Replace your existing nuxt-i18n configuration in nuxt.config.ts with the Nuxt I18n Micro configuration. Here’s an example:

Before (nuxt-i18n):

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US' },
+      { code: 'fr', iso: 'fr-FR' },
+    ],
+    defaultLocale: 'en',
+    vueI18n: './i18n.config.js',
+  },
+})

After (Nuxt I18n Micro):

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n-micro'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

3. 🗂️ Reorganize Translation Files

Move your translation files to the locales directory. Ensure they are in JSON format and organized by locale. For example:

plaintext
  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json

If you are using <nuxt-link> for navigation, replace it with <NuxtLink> to ensure compatibility with the new module.

Before:

vue
<nuxt-link :to="{ name: 'index' }">Home</nuxt-link>

After:

vue
<NuxtLink :to="$localeRoute({ name: 'index' })">Home</NuxtLink>
+<!-- or -->
+<i18n-link :to="{ name: 'index' }">Home</i18n-link>

5. 🛠️ Handle SEO Configurations

Ensure that your SEO configurations are updated to take advantage of Nuxt I18n Micro’s automatic meta tag generation. Remove any redundant SEO configurations that were specific to nuxt-i18n.

6. 🧪 Test Your Application

After completing the migration steps, thoroughly test your application to ensure that all translations are loading correctly and that navigation between locales works as expected. Pay special attention to SEO-related tags and ensure that they are generated as intended.

🛡️ Common Issues and Troubleshooting

❌ Translation Files Not Loading

Ensure that your translation files are in the correct directory and follow the JSON format. Also, confirm that the translationDir option in your configuration matches the location of your translation files.

⚠️ Route Not Found Errors

Check that the routes are correctly set up in your application and that the locales array in the configuration includes all necessary locale codes.

🏷️ Missing SEO Tags

If SEO tags are not being generated, verify that the meta option is enabled in your configuration and that each locale has a valid iso code.

`,39)]))}const E=i(e,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/guide_migration.md.DP2CIHWa.lean.js b/assets/guide_migration.md.DP2CIHWa.lean.js new file mode 100644 index 00000000..0eb2adbb --- /dev/null +++ b/assets/guide_migration.md.DP2CIHWa.lean.js @@ -0,0 +1,36 @@ +import{_ as i,c as a,a2 as n,o as t}from"./chunks/framework.Gfs4HC1t.js";const c=JSON.parse('{"title":"🔄 Migration from nuxt-i18n to Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/migration.md","filePath":"guide/migration.md","lastUpdated":1724265480000}'),e={name:"guide/migration.md"};function l(o,s,h,p,r,d){return t(),a("div",null,s[0]||(s[0]=[n(`

🔄 Migration from nuxt-i18n to Nuxt I18n Micro

📖 Introduction

Migrating from nuxt-i18n to Nuxt I18n Micro can significantly improve the performance of your Nuxt application, especially in high-traffic environments or projects with large translation files. This guide provides a step-by-step approach to help you smoothly transition from nuxt-i18n to Nuxt I18n Micro.

🚀 Why Migrate?

The Nuxt I18n Micro module offers several advantages over the traditional nuxt-i18n:

  • ⚡ Improved Performance: Faster build times, lower memory usage, and smaller bundle sizes.
  • 🔧 Simplified Configuration: A more streamlined setup process with fewer moving parts.
  • 📉 Better Resource Management: Optimized handling of large translation files and reduced server load.

🔍 Key Differences

Before you begin the migration process, it’s essential to understand the key differences between nuxt-i18n and Nuxt I18n Micro:

  • 🌐 Route Management: Nuxt I18n Micro uses dynamic regex-based routing, generating only two routes regardless of the number of locales, unlike nuxt-i18n which creates a separate route for each locale.
  • 🗂️ Translation Files: Only JSON files are supported in Nuxt I18n Micro. The translations are split into global and page-specific files, which are auto-generated in development mode if not present.
  • 📈 SEO Integration: Nuxt I18n Micro offers built-in SEO optimization with automatic meta tag generation and support for hreflang tags.

🛠️ Step-by-Step Migration

1. 🛠️ Install Nuxt I18n Micro

First, add Nuxt I18n Micro to your Nuxt project:

bash
npm install nuxt-i18n-micro

2. 🔄 Update Configuration

Replace your existing nuxt-i18n configuration in nuxt.config.ts with the Nuxt I18n Micro configuration. Here’s an example:

Before (nuxt-i18n):

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US' },
+      { code: 'fr', iso: 'fr-FR' },
+    ],
+    defaultLocale: 'en',
+    vueI18n: './i18n.config.js',
+  },
+})

After (Nuxt I18n Micro):

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n-micro'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

3. 🗂️ Reorganize Translation Files

Move your translation files to the locales directory. Ensure they are in JSON format and organized by locale. For example:

plaintext
  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json

If you are using <nuxt-link> for navigation, replace it with <NuxtLink> to ensure compatibility with the new module.

Before:

vue
<nuxt-link :to="{ name: 'index' }">Home</nuxt-link>

After:

vue
<NuxtLink :to="$localeRoute({ name: 'index' })">Home</NuxtLink>
+<!-- or -->
+<i18n-link :to="{ name: 'index' }">Home</i18n-link>

5. 🛠️ Handle SEO Configurations

Ensure that your SEO configurations are updated to take advantage of Nuxt I18n Micro’s automatic meta tag generation. Remove any redundant SEO configurations that were specific to nuxt-i18n.

6. 🧪 Test Your Application

After completing the migration steps, thoroughly test your application to ensure that all translations are loading correctly and that navigation between locales works as expected. Pay special attention to SEO-related tags and ensure that they are generated as intended.

🛡️ Common Issues and Troubleshooting

❌ Translation Files Not Loading

Ensure that your translation files are in the correct directory and follow the JSON format. Also, confirm that the translationDir option in your configuration matches the location of your translation files.

⚠️ Route Not Found Errors

Check that the routes are correctly set up in your application and that the locales array in the configuration includes all necessary locale codes.

🏷️ Missing SEO Tags

If SEO tags are not being generated, verify that the meta option is enabled in your configuration and that each locale has a valid iso code.

`,39)]))}const E=i(e,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/guide_multi-domain-locales.md.nqKQQ1PT.js b/assets/guide_multi-domain-locales.md.nqKQQ1PT.js new file mode 100644 index 00000000..ea4471d1 --- /dev/null +++ b/assets/guide_multi-domain-locales.md.nqKQQ1PT.js @@ -0,0 +1,45 @@ +import{_ as s,c as a,a2 as n,o as e}from"./chunks/framework.Gfs4HC1t.js";const E=JSON.parse('{"title":"🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/multi-domain-locales.md","filePath":"guide/multi-domain-locales.md","lastUpdated":1724309370000}'),t={name:"guide/multi-domain-locales.md"};function l(h,i,p,r,o,k){return e(),a("div",null,i[0]||(i[0]=[n(`

🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers

📝 Introduction

By leveraging layers in Nuxt I18n Micro, you can create a flexible and maintainable multi-domain localization setup. This approach not only simplifies domain management by eliminating the need for complex functionalities but also allows for efficient load distribution and reduced project complexity. By running separate projects for different locales, your application can easily scale and adapt to varying locale requirements across multiple domains, offering a robust and scalable solution for global applications.

🎯 Objective

To create a setup where different domains serve specific locales by customizing configurations in child layers. This method leverages Nuxt's layering system, allowing you to maintain a base configuration while extending or modifying it for each domain.

🛠 Steps to Implement Multi-Domain Locales

1. Create the Base Layer

Start by creating a base configuration layer that includes all the common locale settings for your application. This configuration will serve as the foundation for other domain-specific configurations.

Base Layer Configuration

Create the base configuration file base/nuxt.config.ts:

typescript
// base/nuxt.config.ts
+
+export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'de', iso: 'de-DE', dir: 'ltr' },
+      { code: 'es', iso: 'es-ES', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+    autoDetectLanguage: true,
+  },
+})

2. Create Domain-Specific Child Layers

For each domain, create a child layer that modifies the base configuration to meet the specific requirements of that domain. You can disable locales that are not needed for a specific domain.

Example: Configuration for the French Domain

Create a child layer configuration for the French domain in fr/nuxt.config.ts:

typescript
// fr/nuxt.config.ts
+
+export default defineNuxtConfig({
+  extends: '../base', // Inherit from the base configuration
+
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr', disabled: true }, // Disable English
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Add and enable the French locale
+      { code: 'de', iso: 'de-DE', dir: 'ltr', disabled: true }, // Disable German
+      { code: 'es', iso: 'es-ES', dir: 'ltr', disabled: true }, // Disable Spanish
+    ],
+    defaultLocale: 'fr', // Set French as the default locale
+    autoDetectLanguage: false, // Disable automatic language detection
+  },
+})

Example: Configuration for the German Domain

Similarly, create a child layer configuration for the German domain in de/nuxt.config.ts:

typescript
// de/nuxt.config.ts
+
+export default defineNuxtConfig({
+  extends: '../base', // Inherit from the base configuration
+
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr', disabled: true }, // Disable English
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr', disabled: true }, // Disable French
+      { code: 'de', iso: 'de-DE', dir: 'ltr' }, // Use the German locale
+      { code: 'es', iso: 'es-ES', dir: 'ltr', disabled: true }, // Disable Spanish
+    ],
+    defaultLocale: 'de', // Set German as the default locale
+    autoDetectLanguage: false, // Disable automatic language detection
+  },
+})

3. Deploy the Application for Each Domain

Deploy the application with the appropriate configuration for each domain. For example:

  • Deploy the fr layer configuration to fr.example.com.
  • Deploy the de layer configuration to de.example.com.

4. Set Up Multiple Projects for Different Locales

For each locale and domain, you'll need to run a separate instance of the application. This ensures that each domain serves the correct locale configuration, optimizing the load distribution and simplifying the project's structure. By running multiple projects tailored to each locale, you can maintain a clean separation between configurations and reduce the complexity of the overall setup.

5. Configure Routing Based on Domain

Ensure that your routing is configured to direct users to the correct project based on the domain they are accessing. This will ensure that each domain serves the appropriate locale, enhancing user experience and maintaining consistency across different regions.

6. Deploy and Verify

After configuring the layers and deploying them to their respective domains, ensure each domain is serving the correct locale. Test the application thoroughly to confirm that the correct locale is loaded depending on the domain.

📝 Best Practices

  • Keep Base Configuration Generic: The base configuration should cover general settings applicable to all domains.
  • Isolate Domain-Specific Logic: Keep domain-specific configurations in their respective layers to maintain clarity and separation of concerns.

🎉 Conclusion

By leveraging layers in Nuxt I18n Micro, you can create a flexible and maintainable multi-domain localization setup. This approach not only eliminates the need for complex domain management functionalities but also allows you to distribute the load efficiently and reduce project complexity. Running separate projects for different locales ensures that your application can scale easily and adapt to different locale requirements across various domains, providing a robust and scalable solution for global applications.

`,32)]))}const c=s(t,[["render",l]]);export{E as __pageData,c as default}; diff --git a/assets/guide_multi-domain-locales.md.nqKQQ1PT.lean.js b/assets/guide_multi-domain-locales.md.nqKQQ1PT.lean.js new file mode 100644 index 00000000..ea4471d1 --- /dev/null +++ b/assets/guide_multi-domain-locales.md.nqKQQ1PT.lean.js @@ -0,0 +1,45 @@ +import{_ as s,c as a,a2 as n,o as e}from"./chunks/framework.Gfs4HC1t.js";const E=JSON.parse('{"title":"🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/multi-domain-locales.md","filePath":"guide/multi-domain-locales.md","lastUpdated":1724309370000}'),t={name:"guide/multi-domain-locales.md"};function l(h,i,p,r,o,k){return e(),a("div",null,i[0]||(i[0]=[n(`

🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers

📝 Introduction

By leveraging layers in Nuxt I18n Micro, you can create a flexible and maintainable multi-domain localization setup. This approach not only simplifies domain management by eliminating the need for complex functionalities but also allows for efficient load distribution and reduced project complexity. By running separate projects for different locales, your application can easily scale and adapt to varying locale requirements across multiple domains, offering a robust and scalable solution for global applications.

🎯 Objective

To create a setup where different domains serve specific locales by customizing configurations in child layers. This method leverages Nuxt's layering system, allowing you to maintain a base configuration while extending or modifying it for each domain.

🛠 Steps to Implement Multi-Domain Locales

1. Create the Base Layer

Start by creating a base configuration layer that includes all the common locale settings for your application. This configuration will serve as the foundation for other domain-specific configurations.

Base Layer Configuration

Create the base configuration file base/nuxt.config.ts:

typescript
// base/nuxt.config.ts
+
+export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'de', iso: 'de-DE', dir: 'ltr' },
+      { code: 'es', iso: 'es-ES', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+    autoDetectLanguage: true,
+  },
+})

2. Create Domain-Specific Child Layers

For each domain, create a child layer that modifies the base configuration to meet the specific requirements of that domain. You can disable locales that are not needed for a specific domain.

Example: Configuration for the French Domain

Create a child layer configuration for the French domain in fr/nuxt.config.ts:

typescript
// fr/nuxt.config.ts
+
+export default defineNuxtConfig({
+  extends: '../base', // Inherit from the base configuration
+
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr', disabled: true }, // Disable English
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Add and enable the French locale
+      { code: 'de', iso: 'de-DE', dir: 'ltr', disabled: true }, // Disable German
+      { code: 'es', iso: 'es-ES', dir: 'ltr', disabled: true }, // Disable Spanish
+    ],
+    defaultLocale: 'fr', // Set French as the default locale
+    autoDetectLanguage: false, // Disable automatic language detection
+  },
+})

Example: Configuration for the German Domain

Similarly, create a child layer configuration for the German domain in de/nuxt.config.ts:

typescript
// de/nuxt.config.ts
+
+export default defineNuxtConfig({
+  extends: '../base', // Inherit from the base configuration
+
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr', disabled: true }, // Disable English
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr', disabled: true }, // Disable French
+      { code: 'de', iso: 'de-DE', dir: 'ltr' }, // Use the German locale
+      { code: 'es', iso: 'es-ES', dir: 'ltr', disabled: true }, // Disable Spanish
+    ],
+    defaultLocale: 'de', // Set German as the default locale
+    autoDetectLanguage: false, // Disable automatic language detection
+  },
+})

3. Deploy the Application for Each Domain

Deploy the application with the appropriate configuration for each domain. For example:

  • Deploy the fr layer configuration to fr.example.com.
  • Deploy the de layer configuration to de.example.com.

4. Set Up Multiple Projects for Different Locales

For each locale and domain, you'll need to run a separate instance of the application. This ensures that each domain serves the correct locale configuration, optimizing the load distribution and simplifying the project's structure. By running multiple projects tailored to each locale, you can maintain a clean separation between configurations and reduce the complexity of the overall setup.

5. Configure Routing Based on Domain

Ensure that your routing is configured to direct users to the correct project based on the domain they are accessing. This will ensure that each domain serves the appropriate locale, enhancing user experience and maintaining consistency across different regions.

6. Deploy and Verify

After configuring the layers and deploying them to their respective domains, ensure each domain is serving the correct locale. Test the application thoroughly to confirm that the correct locale is loaded depending on the domain.

📝 Best Practices

  • Keep Base Configuration Generic: The base configuration should cover general settings applicable to all domains.
  • Isolate Domain-Specific Logic: Keep domain-specific configurations in their respective layers to maintain clarity and separation of concerns.

🎉 Conclusion

By leveraging layers in Nuxt I18n Micro, you can create a flexible and maintainable multi-domain localization setup. This approach not only eliminates the need for complex domain management functionalities but also allows you to distribute the load efficiently and reduce project complexity. Running separate projects for different locales ensures that your application can scale easily and adapt to different locale requirements across various domains, providing a robust and scalable solution for global applications.

`,32)]))}const c=s(t,[["render",l]]);export{E as __pageData,c as default}; diff --git a/assets/guide_per-component-translations.md.DxQAkf1R.js b/assets/guide_per-component-translations.md.DxQAkf1R.js new file mode 100644 index 00000000..a436038c --- /dev/null +++ b/assets/guide_per-component-translations.md.DxQAkf1R.js @@ -0,0 +1,56 @@ +import{_ as i,c as a,a2 as n,o as e}from"./chunks/framework.Gfs4HC1t.js";const d=JSON.parse('{"title":"📖 Per-Component Translations in Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/per-component-translations.md","filePath":"guide/per-component-translations.md","lastUpdated":1726216827000}'),t={name:"guide/per-component-translations.md"};function l(h,s,p,r,o,k){return e(),a("div",null,s[0]||(s[0]=[n(`

📖 Per-Component Translations in Nuxt I18n Micro

Overview

Per-Component Translations in Nuxt I18n Micro allows developers to define translations directly within specific components or pages of a Nuxt application using the $defineI18nRoute function. This approach is ideal for managing localized content that is unique to individual components, providing a more modular and maintainable method for handling translations.

$defineI18nRoute Function

The $defineI18nRoute function configures route behavior based on the current locale, offering a versatile solution to:

  • Control access to specific routes based on available locales.
  • Provide translations for specific locales.
  • Set custom routes for different locales.

Method Signature

typescript
$defineI18nRoute(routeDefinition: { 
+  locales?: string[] | Record<string, Record<string, TranslationObject>>, 
+  localeRoutes?: Record<string, string> 
+})

Parameters

  • locales: Defines which locales are available for the route. This can be:

    • An array of strings, where each string is an available locale (e.g., ['en', 'fr', 'de']).
    • An object where each key is a locale code, and the value is an object containing translations or an empty object if no translations are needed.
  • localeRoutes: Allows custom routes for specific locales. Each key represents a locale code, and the value is the custom route path for that locale. This is useful for scenarios where different locales require unique routing.

Example Usage

typescript
$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    ru: { greeting: 'Привет', farewell: 'До свидания' },
+    de: { greeting: 'Hallo', farewell: 'Auf Wiedersehen' },
+  },
+  localeRoutes: {
+    ru: '/localesubpage', // Custom route path for the Russian locale
+  },
+})

Use Cases

  1. Controlling Access Based on Locales: Define which locales are allowed for specific routes to ensure users only see content relevant to their language.

    typescript
    import { useNuxtApp } from '#imports'
    +
    +const { $defineI18nRoute } = useNuxtApp()
    +
    +$defineI18nRoute({
    +  locales: ['en', 'fr', 'de'] // Only these locales are allowed for this route
    +})
  2. Providing Translations for Locales: Use the locales object to provide specific translations for each route, enhancing the user experience by delivering content in the user's preferred language.

    typescript
    import { useNuxtApp } from '#imports'
    +
    +const { $defineI18nRoute } = useNuxtApp()
    +
    +$defineI18nRoute({
    +  locales: {
    +    en: { greeting: 'Hello', farewell: 'Goodbye' },
    +    fr: { greeting: 'Bonjour', farewell: 'Au revoir' },
    +    de: { greeting: 'Hallo', farewell: { aaa: { bbb: "Auf Wiedersehen" } } },
    +    ru: {} // Russian locale is allowed but no translations are provided
    +  }
    +})
  3. Custom Routing for Locales: Define custom paths for specific locales using the localeRoutes property. This allows you to create unique navigational flows or URL structures for different languages or regions.

Best Practices

  • Keep Translations Close to Components: Define translations directly within the relevant component to keep localized content organized and maintainable.
  • Use Locale Objects for Flexibility: Utilize the object format for the locales property when specific translations or access control based on locales are required.
  • Document Custom Routes: Clearly document any custom routes set for different locales to maintain clarity and simplify development and maintenance.

Here's an example of a Vue page using defineI18nRoute for per-component translations:

Example: Vue Page with Per-Component Translations

Below is an example of how to use $defineI18nRoute within a Vue component to handle translations and custom routing based on locale.

vue
<template>
+  <div>
+    <h1>{{ t('greeting') }}</h1>
+    <p>{{ t('farewell') }}</p>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useNuxtApp } from '#imports'
+
+// Access the $defineI18nRoute function from Nuxt's context
+const { $defineI18nRoute, $t: t } = useNuxtApp()
+
+// Define i18n route with translations for specific locales
+$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    fr: { greeting: 'Bonjour', farewell: 'Au revoir' },
+    de: { greeting: 'Hallo', farewell: 'Auf Wiedersehen' },
+    ru: { greeting: 'Привет', farewell: 'До свидания' },
+  },
+  localeRoutes: {
+    ru: '/ru-specific-path', // Custom route path for the Russian locale
+    fr: '/fr-specific-path'  // Custom route path for the French locale
+  }
+})
+</script>

Explanation

  • Component-Level Translations: The translations are defined directly in the component using the locales property of $defineI18nRoute. This keeps translations closely tied to the component, making them easy to manage and update.
  • Custom Routing: The localeRoutes property is used to set specific paths for different locales. This allows for unique navigational flows based on the user's language preference.

This setup enables the component to display localized greetings and farewells based on the current locale, and it also allows for custom routes tailored to specific locales, enhancing the user experience by delivering content in the preferred language and structure.

Summary

The Per-Component Translations feature, powered by the $defineI18nRoute function, offers a powerful and flexible way to manage localization within your Nuxt application. By allowing localized content and routing to be defined at the component level, it helps create a highly customized and user-friendly experience tailored to the language and regional preferences of your audience.

`,25)]))}const c=i(t,[["render",l]]);export{d as __pageData,c as default}; diff --git a/assets/guide_per-component-translations.md.DxQAkf1R.lean.js b/assets/guide_per-component-translations.md.DxQAkf1R.lean.js new file mode 100644 index 00000000..a436038c --- /dev/null +++ b/assets/guide_per-component-translations.md.DxQAkf1R.lean.js @@ -0,0 +1,56 @@ +import{_ as i,c as a,a2 as n,o as e}from"./chunks/framework.Gfs4HC1t.js";const d=JSON.parse('{"title":"📖 Per-Component Translations in Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/per-component-translations.md","filePath":"guide/per-component-translations.md","lastUpdated":1726216827000}'),t={name:"guide/per-component-translations.md"};function l(h,s,p,r,o,k){return e(),a("div",null,s[0]||(s[0]=[n(`

📖 Per-Component Translations in Nuxt I18n Micro

Overview

Per-Component Translations in Nuxt I18n Micro allows developers to define translations directly within specific components or pages of a Nuxt application using the $defineI18nRoute function. This approach is ideal for managing localized content that is unique to individual components, providing a more modular and maintainable method for handling translations.

$defineI18nRoute Function

The $defineI18nRoute function configures route behavior based on the current locale, offering a versatile solution to:

  • Control access to specific routes based on available locales.
  • Provide translations for specific locales.
  • Set custom routes for different locales.

Method Signature

typescript
$defineI18nRoute(routeDefinition: { 
+  locales?: string[] | Record<string, Record<string, TranslationObject>>, 
+  localeRoutes?: Record<string, string> 
+})

Parameters

  • locales: Defines which locales are available for the route. This can be:

    • An array of strings, where each string is an available locale (e.g., ['en', 'fr', 'de']).
    • An object where each key is a locale code, and the value is an object containing translations or an empty object if no translations are needed.
  • localeRoutes: Allows custom routes for specific locales. Each key represents a locale code, and the value is the custom route path for that locale. This is useful for scenarios where different locales require unique routing.

Example Usage

typescript
$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    ru: { greeting: 'Привет', farewell: 'До свидания' },
+    de: { greeting: 'Hallo', farewell: 'Auf Wiedersehen' },
+  },
+  localeRoutes: {
+    ru: '/localesubpage', // Custom route path for the Russian locale
+  },
+})

Use Cases

  1. Controlling Access Based on Locales: Define which locales are allowed for specific routes to ensure users only see content relevant to their language.

    typescript
    import { useNuxtApp } from '#imports'
    +
    +const { $defineI18nRoute } = useNuxtApp()
    +
    +$defineI18nRoute({
    +  locales: ['en', 'fr', 'de'] // Only these locales are allowed for this route
    +})
  2. Providing Translations for Locales: Use the locales object to provide specific translations for each route, enhancing the user experience by delivering content in the user's preferred language.

    typescript
    import { useNuxtApp } from '#imports'
    +
    +const { $defineI18nRoute } = useNuxtApp()
    +
    +$defineI18nRoute({
    +  locales: {
    +    en: { greeting: 'Hello', farewell: 'Goodbye' },
    +    fr: { greeting: 'Bonjour', farewell: 'Au revoir' },
    +    de: { greeting: 'Hallo', farewell: { aaa: { bbb: "Auf Wiedersehen" } } },
    +    ru: {} // Russian locale is allowed but no translations are provided
    +  }
    +})
  3. Custom Routing for Locales: Define custom paths for specific locales using the localeRoutes property. This allows you to create unique navigational flows or URL structures for different languages or regions.

Best Practices

  • Keep Translations Close to Components: Define translations directly within the relevant component to keep localized content organized and maintainable.
  • Use Locale Objects for Flexibility: Utilize the object format for the locales property when specific translations or access control based on locales are required.
  • Document Custom Routes: Clearly document any custom routes set for different locales to maintain clarity and simplify development and maintenance.

Here's an example of a Vue page using defineI18nRoute for per-component translations:

Example: Vue Page with Per-Component Translations

Below is an example of how to use $defineI18nRoute within a Vue component to handle translations and custom routing based on locale.

vue
<template>
+  <div>
+    <h1>{{ t('greeting') }}</h1>
+    <p>{{ t('farewell') }}</p>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useNuxtApp } from '#imports'
+
+// Access the $defineI18nRoute function from Nuxt's context
+const { $defineI18nRoute, $t: t } = useNuxtApp()
+
+// Define i18n route with translations for specific locales
+$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    fr: { greeting: 'Bonjour', farewell: 'Au revoir' },
+    de: { greeting: 'Hallo', farewell: 'Auf Wiedersehen' },
+    ru: { greeting: 'Привет', farewell: 'До свидания' },
+  },
+  localeRoutes: {
+    ru: '/ru-specific-path', // Custom route path for the Russian locale
+    fr: '/fr-specific-path'  // Custom route path for the French locale
+  }
+})
+</script>

Explanation

  • Component-Level Translations: The translations are defined directly in the component using the locales property of $defineI18nRoute. This keeps translations closely tied to the component, making them easy to manage and update.
  • Custom Routing: The localeRoutes property is used to set specific paths for different locales. This allows for unique navigational flows based on the user's language preference.

This setup enables the component to display localized greetings and farewells based on the current locale, and it also allows for custom routes tailored to specific locales, enhancing the user experience by delivering content in the preferred language and structure.

Summary

The Per-Component Translations feature, powered by the $defineI18nRoute function, offers a powerful and flexible way to manage localization within your Nuxt application. By allowing localized content and routing to be defined at the component level, it helps create a highly customized and user-friendly experience tailored to the language and regional preferences of your audience.

`,25)]))}const c=i(t,[["render",l]]);export{d as __pageData,c as default}; diff --git a/assets/guide_performance-results.md.DEEBDFv7.js b/assets/guide_performance-results.md.DEEBDFv7.js new file mode 100644 index 00000000..6b110231 --- /dev/null +++ b/assets/guide_performance-results.md.DEEBDFv7.js @@ -0,0 +1 @@ +import{_ as r,c as t,a2 as s,o as i}from"./chunks/framework.Gfs4HC1t.js";const o="/nuxt-i18n-micro/i18n.png",n="/nuxt-i18n-micro/i18n-micro.png",f=JSON.parse('{"title":"Performance Test Results","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/performance-results.md","filePath":"guide/performance-results.md","lastUpdated":1737356756000}'),a={name:"guide/performance-results.md"};function l(g,e,c,m,d,u){return i(),t("div",null,e[0]||(e[0]=[s('

Performance Test Results

Project Information

Description:

This performance test compares two implementations of internationalization: i18n-micro and i18n. The main focus of the test is to evaluate build times, memory usage, CPU usage, and the performance of the server under stress (e.g., how many requests can be handled and how efficiently). The i18n-micro implementation shows slightly lower overall script execution times. This difference is attributed to its ability to handle more requests, which requires additional time for processing.

Important Note:

It is essential to recognize that the example used in this test is not entirely representative of the intended usage pattern for i18n-micro. The example simplifies the translation structure by consolidating all translations into a single file. However, i18n-micro is optimized for scenarios where translations are organized on a per-page basis. This approach allows for more granular control and efficiency, particularly in large-scale applications. The current setup is used merely for demonstration purposes and may not fully showcase the potential performance benefits of i18n-micro in real-world applications.


Dependency Versions

DependencyVersion
nodev20.18.0
nuxt^3.15.2
nuxt-i18n-micro1.64.0
@nuxtjs/i18n^9.1.1

Build Performance for ./test/fixtures/i18n

  • Build Time: 20.12 seconds
  • Max CPU Usage: 187.00%
  • Min CPU Usage: 20.30%
  • Average CPU Usage: 98.24%
  • Max Memory Usage: 2819.25 MB
  • Min Memory Usage: 182.17 MB
  • Average Memory Usage: 1265.44 MB

Build Performance for ./test/fixtures/i18n-micro

  • Build Time: 7.55 seconds
  • Max CPU Usage: 239.10%
  • Min CPU Usage: 95.90%
  • Average CPU Usage: 174.60%
  • Max Memory Usage: 1155.53 MB
  • Min Memory Usage: 176.36 MB
  • Average Memory Usage: 618.83 MB

⏱️ Build Time and Resource Consumption

i18n v9
  • Build Time: 20.12 seconds
  • Max CPU Usage: 187.00%
  • Max Memory Usage: 2819.25 MB
i18n-micro
  • Build Time: 7.55 seconds
  • Max CPU Usage: 239.10%
  • Max Memory Usage: 1155.53 MB

Performance Comparison

  • i18n-micro: 7.55 seconds, Max Memory: 1155.53 MB, Max CPU: 239.10%
  • i18n v9: 20.12 seconds, Max Memory: 2819.25 MB, Max CPU: 187.00%
  • Time Difference: -12.57 seconds
  • Memory Difference: -1663.72 MB
  • CPU Usage Difference: 52.10%

Stress Test with Artillery for ./test/fixtures/i18n

  • Max CPU Usage: 174.50%
  • Min CPU Usage: 0.00%
  • Average CPU Usage: 129.58%
  • Max Memory Usage: 796.69 MB
  • Min Memory Usage: 48.44 MB
  • Average Memory Usage: 387.15 MB
  • Stress Test Time: 75.72 seconds
  • Average Response Time: 1547.10 ms
  • Min Response Time: 70.00 ms
  • Max Response Time: 9965.00 ms
  • Requests per Second: 73.00
  • Error Rate: 0.00%

i18n

Stress Test with Artillery for ./test/fixtures/i18n-micro

  • Max CPU Usage: 127.00%
  • Min CPU Usage: 0.00%
  • Average CPU Usage: 89.23%
  • Max Memory Usage: 355.58 MB
  • Min Memory Usage: 48.09 MB
  • Average Memory Usage: 291.41 MB
  • Stress Test Time: 68.11 seconds
  • Average Response Time: 422.90 ms
  • Min Response Time: 1.00 ms
  • Max Response Time: 3055.00 ms
  • Requests per Second: 291.00
  • Error Rate: 0.00%

i18n-micro

Comparison between i18n v9 and i18n-micro

  • Max Memory Used Difference: -441.11 MB
  • Min Memory Used Difference: -0.34 MB
  • Avg Memory Used Difference: -95.74 MB
  • Max CPU Usage Difference: -47.50%
  • Min CPU Usage Difference: 0.00%
  • Avg CPU Usage Difference: -40.34%
  • Stress Test Time Difference: 0.00 seconds
  • Average Response Time Difference: -1124.20 ms
  • Min Response Time Difference: -69.00 ms
  • Max Response Time Difference: -6910.00 ms
  • Requests Per Second Difference: 218.00
  • Error Rate Difference: 0.00%

📊 Detailed Performance Analysis

🔍 Test Logic Explanation

The performance tests conducted for Nuxt I18n Micro and nuxt-i18n v9 are designed to simulate real-world usage scenarios. Below is an overview of the key aspects of the test methodology:

  1. Build Time: Measures the time required to build the project, focusing on how efficiently each module handles large translation files.
  2. CPU Usage: Tracks the CPU load during the build and stress tests to assess the impact on server resources.
  3. Memory Usage: Monitors memory consumption to determine how each module manages memory, especially under high load.
  4. Stress Testing: Simulates a series of requests to evaluate the server's ability to handle concurrent traffic. The test is divided into two phases:
    • Warm-up Phase: Over 6 seconds, one request per second is sent to each of the specified URLs, with a maximum of 6 users, to ensure that the server is ready for the main test.
    • Main Test Phase: For 60 seconds, the server is subjected to 60 requests per second, spread across various endpoints, to measure response times, error rates, and overall throughput under load.

🛠 Why This Approach?

The chosen testing methodology is designed to reflect the scenarios that developers are likely to encounter in production environments. By focusing on build time, CPU and memory usage, and server performance under load, the tests provide a comprehensive view of how each module will perform in a large-scale, high-traffic application.

Nuxt I18n Micro is optimized for:

  • Faster Build Times: By reducing the overhead during the build process.
  • Lower Resource Consumption: Minimizing CPU and memory usage, making it suitable for resource-constrained environments.
  • Better Handling of Large Projects: With a focus on scalability, ensuring that applications remain responsive even as they grow.
',35)]))}const p=r(a,[["render",l]]);export{f as __pageData,p as default}; diff --git a/assets/guide_performance-results.md.DEEBDFv7.lean.js b/assets/guide_performance-results.md.DEEBDFv7.lean.js new file mode 100644 index 00000000..6b110231 --- /dev/null +++ b/assets/guide_performance-results.md.DEEBDFv7.lean.js @@ -0,0 +1 @@ +import{_ as r,c as t,a2 as s,o as i}from"./chunks/framework.Gfs4HC1t.js";const o="/nuxt-i18n-micro/i18n.png",n="/nuxt-i18n-micro/i18n-micro.png",f=JSON.parse('{"title":"Performance Test Results","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/performance-results.md","filePath":"guide/performance-results.md","lastUpdated":1737356756000}'),a={name:"guide/performance-results.md"};function l(g,e,c,m,d,u){return i(),t("div",null,e[0]||(e[0]=[s('

Performance Test Results

Project Information

Description:

This performance test compares two implementations of internationalization: i18n-micro and i18n. The main focus of the test is to evaluate build times, memory usage, CPU usage, and the performance of the server under stress (e.g., how many requests can be handled and how efficiently). The i18n-micro implementation shows slightly lower overall script execution times. This difference is attributed to its ability to handle more requests, which requires additional time for processing.

Important Note:

It is essential to recognize that the example used in this test is not entirely representative of the intended usage pattern for i18n-micro. The example simplifies the translation structure by consolidating all translations into a single file. However, i18n-micro is optimized for scenarios where translations are organized on a per-page basis. This approach allows for more granular control and efficiency, particularly in large-scale applications. The current setup is used merely for demonstration purposes and may not fully showcase the potential performance benefits of i18n-micro in real-world applications.


Dependency Versions

DependencyVersion
nodev20.18.0
nuxt^3.15.2
nuxt-i18n-micro1.64.0
@nuxtjs/i18n^9.1.1

Build Performance for ./test/fixtures/i18n

  • Build Time: 20.12 seconds
  • Max CPU Usage: 187.00%
  • Min CPU Usage: 20.30%
  • Average CPU Usage: 98.24%
  • Max Memory Usage: 2819.25 MB
  • Min Memory Usage: 182.17 MB
  • Average Memory Usage: 1265.44 MB

Build Performance for ./test/fixtures/i18n-micro

  • Build Time: 7.55 seconds
  • Max CPU Usage: 239.10%
  • Min CPU Usage: 95.90%
  • Average CPU Usage: 174.60%
  • Max Memory Usage: 1155.53 MB
  • Min Memory Usage: 176.36 MB
  • Average Memory Usage: 618.83 MB

⏱️ Build Time and Resource Consumption

i18n v9
  • Build Time: 20.12 seconds
  • Max CPU Usage: 187.00%
  • Max Memory Usage: 2819.25 MB
i18n-micro
  • Build Time: 7.55 seconds
  • Max CPU Usage: 239.10%
  • Max Memory Usage: 1155.53 MB

Performance Comparison

  • i18n-micro: 7.55 seconds, Max Memory: 1155.53 MB, Max CPU: 239.10%
  • i18n v9: 20.12 seconds, Max Memory: 2819.25 MB, Max CPU: 187.00%
  • Time Difference: -12.57 seconds
  • Memory Difference: -1663.72 MB
  • CPU Usage Difference: 52.10%

Stress Test with Artillery for ./test/fixtures/i18n

  • Max CPU Usage: 174.50%
  • Min CPU Usage: 0.00%
  • Average CPU Usage: 129.58%
  • Max Memory Usage: 796.69 MB
  • Min Memory Usage: 48.44 MB
  • Average Memory Usage: 387.15 MB
  • Stress Test Time: 75.72 seconds
  • Average Response Time: 1547.10 ms
  • Min Response Time: 70.00 ms
  • Max Response Time: 9965.00 ms
  • Requests per Second: 73.00
  • Error Rate: 0.00%

i18n

Stress Test with Artillery for ./test/fixtures/i18n-micro

  • Max CPU Usage: 127.00%
  • Min CPU Usage: 0.00%
  • Average CPU Usage: 89.23%
  • Max Memory Usage: 355.58 MB
  • Min Memory Usage: 48.09 MB
  • Average Memory Usage: 291.41 MB
  • Stress Test Time: 68.11 seconds
  • Average Response Time: 422.90 ms
  • Min Response Time: 1.00 ms
  • Max Response Time: 3055.00 ms
  • Requests per Second: 291.00
  • Error Rate: 0.00%

i18n-micro

Comparison between i18n v9 and i18n-micro

  • Max Memory Used Difference: -441.11 MB
  • Min Memory Used Difference: -0.34 MB
  • Avg Memory Used Difference: -95.74 MB
  • Max CPU Usage Difference: -47.50%
  • Min CPU Usage Difference: 0.00%
  • Avg CPU Usage Difference: -40.34%
  • Stress Test Time Difference: 0.00 seconds
  • Average Response Time Difference: -1124.20 ms
  • Min Response Time Difference: -69.00 ms
  • Max Response Time Difference: -6910.00 ms
  • Requests Per Second Difference: 218.00
  • Error Rate Difference: 0.00%

📊 Detailed Performance Analysis

🔍 Test Logic Explanation

The performance tests conducted for Nuxt I18n Micro and nuxt-i18n v9 are designed to simulate real-world usage scenarios. Below is an overview of the key aspects of the test methodology:

  1. Build Time: Measures the time required to build the project, focusing on how efficiently each module handles large translation files.
  2. CPU Usage: Tracks the CPU load during the build and stress tests to assess the impact on server resources.
  3. Memory Usage: Monitors memory consumption to determine how each module manages memory, especially under high load.
  4. Stress Testing: Simulates a series of requests to evaluate the server's ability to handle concurrent traffic. The test is divided into two phases:
    • Warm-up Phase: Over 6 seconds, one request per second is sent to each of the specified URLs, with a maximum of 6 users, to ensure that the server is ready for the main test.
    • Main Test Phase: For 60 seconds, the server is subjected to 60 requests per second, spread across various endpoints, to measure response times, error rates, and overall throughput under load.

🛠 Why This Approach?

The chosen testing methodology is designed to reflect the scenarios that developers are likely to encounter in production environments. By focusing on build time, CPU and memory usage, and server performance under load, the tests provide a comprehensive view of how each module will perform in a large-scale, high-traffic application.

Nuxt I18n Micro is optimized for:

  • Faster Build Times: By reducing the overhead during the build process.
  • Lower Resource Consumption: Minimizing CPU and memory usage, making it suitable for resource-constrained environments.
  • Better Handling of Large Projects: With a focus on scalability, ensuring that applications remain responsive even as they grow.
',35)]))}const p=r(a,[["render",l]]);export{f as __pageData,p as default}; diff --git a/assets/guide_performance.md.CbRsZzqQ.js b/assets/guide_performance.md.CbRsZzqQ.js new file mode 100644 index 00000000..79d37e81 --- /dev/null +++ b/assets/guide_performance.md.CbRsZzqQ.js @@ -0,0 +1 @@ +import{_ as r,c as o,a2 as n,o as a}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🚀 Performance Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/performance.md","filePath":"guide/performance.md","lastUpdated":1724679268000}'),i={name:"guide/performance.md"};function t(s,e,l,c,d,u){return a(),o("div",null,e[0]||(e[0]=[n('

🚀 Performance Guide

📖 Introduction

Nuxt I18n Micro is designed with performance in mind, offering a significant improvement over traditional internationalization (i18n) modules like nuxt-i18n. This guide provides an in-depth look at the performance benefits of using Nuxt I18n Micro, and how it compares to other solutions.

🤔 Why Focus on Performance?

In large-scale projects and high-traffic environments, performance bottlenecks can lead to slow build times, increased memory usage, and poor server response times. These issues become more pronounced with complex i18n setups involving large translation files. Nuxt I18n Micro was built to address these challenges head-on by optimizing for speed, memory efficiency, and minimal impact on your application’s bundle size.

📊 Performance Comparison

We conducted a series of tests to demonstrate the performance improvements that Nuxt I18n Micro brings to the table. Below is a detailed comparison between Nuxt I18n Micro and the traditional nuxt-i18n module, based on identical conditions with a 10MB translation file on the same hardware.

⏱️ Build Time and Resource Consumption

Nuxt I18n
  • Total Size: 54.7 MB (3.31 MB gzip)
  • Max CPU Usage: 391.4%
  • Max Memory Usage: 8305 MB
  • Elapsed Time: 1m 31s

Nuxt I18n Micro

  • Total Size: 1.93 MB (473 kB gzip) — 96% smaller
  • Max CPU Usage: 220.1% — 44% lower
  • Max Memory Usage: 655 MB — 92% less memory
  • Elapsed Time: 0m 5s — 94% faster

🌐 Server Performance Under Load

We also tested server performance by simulating 10,000 requests to each module.

Nuxt I18n
  • Requests per Second: 49.05 [#/sec] (mean)
  • Time per Request: 611.599 ms (mean)
  • Max Memory Usage: 703.73 MB

Nuxt I18n Micro

  • Requests per Second: 61.18 [#/sec] (mean) — 25% more requests per second
  • Time per Request: 490.379 ms (mean) — 20% faster
  • Max Memory Usage: 323.00 MB — 54% less memory usage

🔍 Interpretation of Results

These tests clearly indicate that Nuxt I18n Micro offers superior performance across multiple metrics:

  • 🗜️ Smaller Bundle Size: Reduces the overall size of your application bundle, leading to faster load times and better user experience.
  • 🔋 Lower CPU Usage: Decreases the load on your server’s CPU, allowing for more efficient processing of requests.
  • 🧠 Reduced Memory Consumption: Significantly lowers memory usage, minimizing the risk of memory leaks and enabling your application to handle larger workloads.
  • 🕒 Faster Build Times: Drastically reduces build times, which is particularly beneficial during development and CI/CD processes.

⚙️ Key Optimizations

🛠️ Minimalist Design

Nuxt I18n Micro is built around a minimalist architecture, using only 5 components (1 module and 4 plugins). This reduces overhead and simplifies the internal logic, leading to improved performance.

🚦 Efficient Routing

Unlike other i18n modules that generate a separate route for each locale, Nuxt I18n Micro uses dynamic regex-based routing. This approach generates only two routes regardless of the number of locales, significantly reducing the complexity of your routing configuration and speeding up route resolution.

📂 Streamlined Translation Loading

The module supports only JSON files for translations, with a clear separation between global and page-specific files. This ensures that only the necessary translation data is loaded at any given time, further enhancing performance.

💾 Caching and Pre-rendering

To optimize performance, Nuxt I18n Micro implements caching and supports pre-rendering of translation files:

  • 🗄️ Caching: Translations are cached after the initial load, reducing the need for subsequent requests and improving response times.
  • 🏁 Pre-rendering: During the build process, translation files for all configured locales and routes can be pre-rendered. This eliminates the need for runtime requests, ensuring that translations are served quickly and efficiently.

📝 Tips for Maximizing Performance

Here are a few tips to ensure you get the best performance out of Nuxt I18n Micro:

  • 📉 Limit Locale Data: Only include the locales you need in your project to keep the bundle size small.
  • 🗂️ Use Page-Specific Translations: Organize your translation files by page to avoid loading unnecessary data.
  • 💾 Enable Caching: Make use of the caching features to reduce server load and improve response times.
  • 🏁 Leverage Pre-rendering: Pre-render your translations to speed up page loads and reduce runtime overhead.

For detailed results of the performance tests, please refer to the Performance Test Results.

',31)]))}const p=r(i,[["render",t]]);export{g as __pageData,p as default}; diff --git a/assets/guide_performance.md.CbRsZzqQ.lean.js b/assets/guide_performance.md.CbRsZzqQ.lean.js new file mode 100644 index 00000000..79d37e81 --- /dev/null +++ b/assets/guide_performance.md.CbRsZzqQ.lean.js @@ -0,0 +1 @@ +import{_ as r,c as o,a2 as n,o as a}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🚀 Performance Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/performance.md","filePath":"guide/performance.md","lastUpdated":1724679268000}'),i={name:"guide/performance.md"};function t(s,e,l,c,d,u){return a(),o("div",null,e[0]||(e[0]=[n('

🚀 Performance Guide

📖 Introduction

Nuxt I18n Micro is designed with performance in mind, offering a significant improvement over traditional internationalization (i18n) modules like nuxt-i18n. This guide provides an in-depth look at the performance benefits of using Nuxt I18n Micro, and how it compares to other solutions.

🤔 Why Focus on Performance?

In large-scale projects and high-traffic environments, performance bottlenecks can lead to slow build times, increased memory usage, and poor server response times. These issues become more pronounced with complex i18n setups involving large translation files. Nuxt I18n Micro was built to address these challenges head-on by optimizing for speed, memory efficiency, and minimal impact on your application’s bundle size.

📊 Performance Comparison

We conducted a series of tests to demonstrate the performance improvements that Nuxt I18n Micro brings to the table. Below is a detailed comparison between Nuxt I18n Micro and the traditional nuxt-i18n module, based on identical conditions with a 10MB translation file on the same hardware.

⏱️ Build Time and Resource Consumption

Nuxt I18n
  • Total Size: 54.7 MB (3.31 MB gzip)
  • Max CPU Usage: 391.4%
  • Max Memory Usage: 8305 MB
  • Elapsed Time: 1m 31s

Nuxt I18n Micro

  • Total Size: 1.93 MB (473 kB gzip) — 96% smaller
  • Max CPU Usage: 220.1% — 44% lower
  • Max Memory Usage: 655 MB — 92% less memory
  • Elapsed Time: 0m 5s — 94% faster

🌐 Server Performance Under Load

We also tested server performance by simulating 10,000 requests to each module.

Nuxt I18n
  • Requests per Second: 49.05 [#/sec] (mean)
  • Time per Request: 611.599 ms (mean)
  • Max Memory Usage: 703.73 MB

Nuxt I18n Micro

  • Requests per Second: 61.18 [#/sec] (mean) — 25% more requests per second
  • Time per Request: 490.379 ms (mean) — 20% faster
  • Max Memory Usage: 323.00 MB — 54% less memory usage

🔍 Interpretation of Results

These tests clearly indicate that Nuxt I18n Micro offers superior performance across multiple metrics:

  • 🗜️ Smaller Bundle Size: Reduces the overall size of your application bundle, leading to faster load times and better user experience.
  • 🔋 Lower CPU Usage: Decreases the load on your server’s CPU, allowing for more efficient processing of requests.
  • 🧠 Reduced Memory Consumption: Significantly lowers memory usage, minimizing the risk of memory leaks and enabling your application to handle larger workloads.
  • 🕒 Faster Build Times: Drastically reduces build times, which is particularly beneficial during development and CI/CD processes.

⚙️ Key Optimizations

🛠️ Minimalist Design

Nuxt I18n Micro is built around a minimalist architecture, using only 5 components (1 module and 4 plugins). This reduces overhead and simplifies the internal logic, leading to improved performance.

🚦 Efficient Routing

Unlike other i18n modules that generate a separate route for each locale, Nuxt I18n Micro uses dynamic regex-based routing. This approach generates only two routes regardless of the number of locales, significantly reducing the complexity of your routing configuration and speeding up route resolution.

📂 Streamlined Translation Loading

The module supports only JSON files for translations, with a clear separation between global and page-specific files. This ensures that only the necessary translation data is loaded at any given time, further enhancing performance.

💾 Caching and Pre-rendering

To optimize performance, Nuxt I18n Micro implements caching and supports pre-rendering of translation files:

  • 🗄️ Caching: Translations are cached after the initial load, reducing the need for subsequent requests and improving response times.
  • 🏁 Pre-rendering: During the build process, translation files for all configured locales and routes can be pre-rendered. This eliminates the need for runtime requests, ensuring that translations are served quickly and efficiently.

📝 Tips for Maximizing Performance

Here are a few tips to ensure you get the best performance out of Nuxt I18n Micro:

  • 📉 Limit Locale Data: Only include the locales you need in your project to keep the bundle size small.
  • 🗂️ Use Page-Specific Translations: Organize your translation files by page to avoid loading unnecessary data.
  • 💾 Enable Caching: Make use of the caching features to reduce server load and improve response times.
  • 🏁 Leverage Pre-rendering: Pre-render your translations to speed up page loads and reduce runtime overhead.

For detailed results of the performance tests, please refer to the Performance Test Results.

',31)]))}const p=r(i,[["render",t]]);export{g as __pageData,p as default}; diff --git a/assets/guide_seo.md.CjeG8qHD.js b/assets/guide_seo.md.CjeG8qHD.js new file mode 100644 index 00000000..f1d1c66e --- /dev/null +++ b/assets/guide_seo.md.CjeG8qHD.js @@ -0,0 +1,13 @@ +import{_ as e,c as s,a2 as a,o as n}from"./chunks/framework.Gfs4HC1t.js";const k=JSON.parse('{"title":"🌐 SEO Guide for Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/seo.md","filePath":"guide/seo.md","lastUpdated":1724243643000}'),t={name:"guide/seo.md"};function l(o,i,r,h,d,p){return n(),s("div",null,i[0]||(i[0]=[a(`

🌐 SEO Guide for Nuxt I18n Micro

📖 Introduction

Effective SEO (Search Engine Optimization) is essential for ensuring that your multilingual site is accessible and visible to users worldwide through search engines. Nuxt I18n Micro simplifies the process of managing SEO for multilingual sites by automatically generating essential meta tags and attributes that inform search engines about the structure and content of your site.

This guide explains how Nuxt I18n Micro handles SEO to enhance your site's visibility and user experience without requiring additional configuration.

⚙️ Automatic SEO Handling

🔑 Key SEO Features

When the meta option is enabled in Nuxt I18n Micro, the module automatically manages the following SEO aspects:

  1. 🌍 Language and Direction Attributes:

    • The module sets the lang and dir attributes on the <html> tag according to the current locale and text direction (e.g., ltr for English or rtl for Arabic).
  2. 🔗 Canonical URLs:

    • The module generates a canonical link (<link rel="canonical">) for each page, ensuring that search engines recognize the primary version of the content.
  3. 🌐 Alternate Language Links (hreflang):

    • The module automatically generates <link rel="alternate" hreflang=""> tags for all available locales. This helps search engines understand which language versions of your content are available, improving the user experience for global audiences.
  4. 🔖 Open Graph Metadata:

    • The module generates Open Graph meta tags (og:locale, og:url, etc.) for each locale, which is particularly useful for social media sharing and search engine indexing.

🛠️ Configuration

To enable these SEO features, ensure the meta option is set to true in your nuxt.config.ts file:

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n-micro'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true, // Enables automatic SEO management
+  },
+})

🎯 Benefits

By enabling the meta option, you benefit from:

  • 📈 Improved Search Engine Rankings: Search engines can better index your site, understanding the relationships between different language versions.
  • 👥 Better User Experience: Users are served the correct language version based on their preferences, leading to a more personalized experience.
  • 🔧 Reduced Manual Configuration: The module handles SEO tasks automatically, freeing you from the need to manually add SEO-related meta tags and attributes.
`,14)]))}const g=e(t,[["render",l]]);export{k as __pageData,g as default}; diff --git a/assets/guide_seo.md.CjeG8qHD.lean.js b/assets/guide_seo.md.CjeG8qHD.lean.js new file mode 100644 index 00000000..f1d1c66e --- /dev/null +++ b/assets/guide_seo.md.CjeG8qHD.lean.js @@ -0,0 +1,13 @@ +import{_ as e,c as s,a2 as a,o as n}from"./chunks/framework.Gfs4HC1t.js";const k=JSON.parse('{"title":"🌐 SEO Guide for Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/seo.md","filePath":"guide/seo.md","lastUpdated":1724243643000}'),t={name:"guide/seo.md"};function l(o,i,r,h,d,p){return n(),s("div",null,i[0]||(i[0]=[a(`

🌐 SEO Guide for Nuxt I18n Micro

📖 Introduction

Effective SEO (Search Engine Optimization) is essential for ensuring that your multilingual site is accessible and visible to users worldwide through search engines. Nuxt I18n Micro simplifies the process of managing SEO for multilingual sites by automatically generating essential meta tags and attributes that inform search engines about the structure and content of your site.

This guide explains how Nuxt I18n Micro handles SEO to enhance your site's visibility and user experience without requiring additional configuration.

⚙️ Automatic SEO Handling

🔑 Key SEO Features

When the meta option is enabled in Nuxt I18n Micro, the module automatically manages the following SEO aspects:

  1. 🌍 Language and Direction Attributes:

    • The module sets the lang and dir attributes on the <html> tag according to the current locale and text direction (e.g., ltr for English or rtl for Arabic).
  2. 🔗 Canonical URLs:

    • The module generates a canonical link (<link rel="canonical">) for each page, ensuring that search engines recognize the primary version of the content.
  3. 🌐 Alternate Language Links (hreflang):

    • The module automatically generates <link rel="alternate" hreflang=""> tags for all available locales. This helps search engines understand which language versions of your content are available, improving the user experience for global audiences.
  4. 🔖 Open Graph Metadata:

    • The module generates Open Graph meta tags (og:locale, og:url, etc.) for each locale, which is particularly useful for social media sharing and search engine indexing.

🛠️ Configuration

To enable these SEO features, ensure the meta option is set to true in your nuxt.config.ts file:

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n-micro'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true, // Enables automatic SEO management
+  },
+})

🎯 Benefits

By enabling the meta option, you benefit from:

  • 📈 Improved Search Engine Rankings: Search engines can better index your site, understanding the relationships between different language versions.
  • 👥 Better User Experience: Users are served the correct language version based on their preferences, leading to a more personalized experience.
  • 🔧 Reduced Manual Configuration: The module handles SEO tasks automatically, freeing you from the need to manually add SEO-related meta tags and attributes.
`,14)]))}const g=e(t,[["render",l]]);export{k as __pageData,g as default}; diff --git a/assets/guide_server-side-translations.md.Dqb0NeYG.js b/assets/guide_server-side-translations.md.Dqb0NeYG.js new file mode 100644 index 00000000..11aba3ef --- /dev/null +++ b/assets/guide_server-side-translations.md.Dqb0NeYG.js @@ -0,0 +1,23 @@ +import{_ as i,c as a,a2 as e,o as n}from"./chunks/framework.Gfs4HC1t.js";const c=JSON.parse('{"title":"🌍 Server-Side Translations in Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/server-side-translations.md","filePath":"guide/server-side-translations.md","lastUpdated":1733172482000}'),t={name:"guide/server-side-translations.md"};function l(h,s,r,p,k,d){return n(),a("div",null,s[0]||(s[0]=[e(`

🌍 Server-Side Translations in Nuxt I18n Micro

📖 Overview

Nuxt I18n Micro supports server-side translations, allowing you to translate content on the server and return it as part of the response. This is particularly useful for APIs or server-rendered applications where localization is needed before reaching the client.

The translations use locale messages defined in the Nuxt I18n configuration and are dynamically resolved based on the detected locale.

To clarify, the translations used by Nuxt I18n Micro in server-side handling are only sourced from the root-level translation files. Any nested translation files or subdirectories are not utilized in this context. The system will only retrieve translations from the root folder, ensuring a consistent and manageable approach to server-side translation retrieval.


🛠️ Setting Up Server-Side Translations

To enable server-side translations, use the provided middleware to handle locale detection and return translations dynamically. The useTranslationServerMiddleware function is designed for this purpose.


✨ Using Translations in Server Handlers

You can seamlessly translate content in any eventHandler by using the middleware.

Example: Basic Usage

typescript
import { defineEventHandler } from 'h3'
+
+export default defineEventHandler(async (event) => {
+  const t = await useTranslationServerMiddleware(event)
+  return {
+    message: t('greeting'), // Returns the translated value for the key "greeting"
+  }
+})

In this example:

  • The user's locale is detected automatically from query parameters, cookies, or headers.
  • The t function retrieves the appropriate translation for the detected locale.

🌐 Providing a Custom Locale

If you need to specify a locale manually (e.g., for testing or certain requests), you can pass it to the middleware:

Example: Custom Locale

typescript
import { defineEventHandler } from 'h3'
+
+function detectLocale(event): string | null {
+  const urlSearchParams = new URLSearchParams(event.node.req.url?.split('?')[1]);
+  const localeFromQuery = urlSearchParams.get('locale');
+  if (localeFromQuery) return localeFromQuery;
+
+  return 'en';
+}
+
+export default defineEventHandler(async (event) => {
+  const t = await useTranslationServerMiddleware(event, 'en', detectLocale(event)) // Force French local, en - default locale
+  return {
+    message: t('welcome'), // Returns the French translation for "welcome"
+  }
+})

📋 Detecting Locale

The middleware automatically determines the user's locale using a fallback chain:

  1. Query Parameter: ?locale=fr
  2. Cookie: user-locale
  3. HTTP Header: Accept-Language
  4. Default Locale: As defined in useTranslationServerMiddleware param.
`,24)]))}const E=i(t,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/guide_server-side-translations.md.Dqb0NeYG.lean.js b/assets/guide_server-side-translations.md.Dqb0NeYG.lean.js new file mode 100644 index 00000000..11aba3ef --- /dev/null +++ b/assets/guide_server-side-translations.md.Dqb0NeYG.lean.js @@ -0,0 +1,23 @@ +import{_ as i,c as a,a2 as e,o as n}from"./chunks/framework.Gfs4HC1t.js";const c=JSON.parse('{"title":"🌍 Server-Side Translations in Nuxt I18n Micro","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/server-side-translations.md","filePath":"guide/server-side-translations.md","lastUpdated":1733172482000}'),t={name:"guide/server-side-translations.md"};function l(h,s,r,p,k,d){return n(),a("div",null,s[0]||(s[0]=[e(`

🌍 Server-Side Translations in Nuxt I18n Micro

📖 Overview

Nuxt I18n Micro supports server-side translations, allowing you to translate content on the server and return it as part of the response. This is particularly useful for APIs or server-rendered applications where localization is needed before reaching the client.

The translations use locale messages defined in the Nuxt I18n configuration and are dynamically resolved based on the detected locale.

To clarify, the translations used by Nuxt I18n Micro in server-side handling are only sourced from the root-level translation files. Any nested translation files or subdirectories are not utilized in this context. The system will only retrieve translations from the root folder, ensuring a consistent and manageable approach to server-side translation retrieval.


🛠️ Setting Up Server-Side Translations

To enable server-side translations, use the provided middleware to handle locale detection and return translations dynamically. The useTranslationServerMiddleware function is designed for this purpose.


✨ Using Translations in Server Handlers

You can seamlessly translate content in any eventHandler by using the middleware.

Example: Basic Usage

typescript
import { defineEventHandler } from 'h3'
+
+export default defineEventHandler(async (event) => {
+  const t = await useTranslationServerMiddleware(event)
+  return {
+    message: t('greeting'), // Returns the translated value for the key "greeting"
+  }
+})

In this example:

  • The user's locale is detected automatically from query parameters, cookies, or headers.
  • The t function retrieves the appropriate translation for the detected locale.

🌐 Providing a Custom Locale

If you need to specify a locale manually (e.g., for testing or certain requests), you can pass it to the middleware:

Example: Custom Locale

typescript
import { defineEventHandler } from 'h3'
+
+function detectLocale(event): string | null {
+  const urlSearchParams = new URLSearchParams(event.node.req.url?.split('?')[1]);
+  const localeFromQuery = urlSearchParams.get('locale');
+  if (localeFromQuery) return localeFromQuery;
+
+  return 'en';
+}
+
+export default defineEventHandler(async (event) => {
+  const t = await useTranslationServerMiddleware(event, 'en', detectLocale(event)) // Force French local, en - default locale
+  return {
+    message: t('welcome'), // Returns the French translation for "welcome"
+  }
+})

📋 Detecting Locale

The middleware automatically determines the user's locale using a fallback chain:

  1. Query Parameter: ?locale=fr
  2. Cookie: user-locale
  3. HTTP Header: Accept-Language
  4. Default Locale: As defined in useTranslationServerMiddleware param.
`,24)]))}const E=i(t,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/guide_strategy.md.CUuNsgYn.js b/assets/guide_strategy.md.CUuNsgYn.js new file mode 100644 index 00000000..c263741a --- /dev/null +++ b/assets/guide_strategy.md.CUuNsgYn.js @@ -0,0 +1,26 @@ +import{_ as s,c as i,a2 as a,o as t}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","description":"","frontmatter":{},"headers":[],"relativePath":"guide/strategy.md","filePath":"guide/strategy.md","lastUpdated":1737355375000}'),n={name:"guide/strategy.md"};function l(o,e,r,h,p,d){return t(),i("div",null,e[0]||(e[0]=[a(`

🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)

📖 Introduction to Locale Prefix Strategies

Starting with version 1.50.0, Nuxt I18n introduces a more flexible way to manage how locale prefixes are handled in URLs through the strategy option. This new approach replaces the deprecated includeDefaultLocaleRoute and gives you better control over how localization is applied to different routes in your application.

The strategy option allows you to choose between different behaviors regarding locale prefixes, providing more fine-grained control over the URLs of your application and how they are structured based on the user's selected language.

🚦 strategy (New in Version 1.50.0)

The strategy option defines how locale prefixes should be managed across your routes. The available strategies give you varying levels of control over how the locale appears in the URLs.

Type: string
Default: prefix_and_default

Available Strategies:

🛑 no_prefix

This strategy ensures that no locale prefix is added to your routes. Instead of modifying the URL, the application will detect and change the locale based on the user's browser settings or cookies.

  • Behavior: Routes won't have any locale prefix.
  • Locale Detection: The locale is detected based on the user's browser language or cookies, and it is changed without altering the URL.
  • Restrictions: This strategy does not support features like Custom paths or Ignore routes.

Default Locale: You can set the default locale using an environment variable. For example:

  • DEFAULT_LOCALE=de npm run dev
  • DEFAULT_LOCALE=de npm run build

Use Case: Ideal when you want a cleaner URL structure and are relying on automatic language detection rather than explicit locale identifiers in the URL.

typescript
i18n: {
+  strategy: 'no_prefix'
+}

Example Routes:

  • /about (for any language, e.g., en, ru, fr, etc.)
  • /contact (for any language)
  • /other (for any language)
  • /other2 (for any language)

🚧 prefix_except_default

With this strategy, all of your routes will include a locale prefix, except for the default language. For the default language, the route will appear without any prefix.

  • Behavior: All routes will include a locale prefix, except for the default language.
  • Locale Handling: This ensures that only the default locale has URLs without a prefix, while all other locales will have a locale-specific prefix.

Use Case: Useful when you want all non-default languages to have a distinct URL structure with a locale prefix but prefer the default language to be accessible without the prefix.

typescript
i18n: {
+  strategy: 'prefix_except_default'
+}

Example Routes:

  • /about (for the default language, e.g., en)
  • /ru/about (for Russian)
  • /fr/about (for French)

🌍 prefix

This strategy ensures that every route in your application will include a locale prefix, regardless of the language. It standardizes the URL structure across all languages.

  • Behavior: All routes will have a locale prefix.
  • Locale Handling: Every route will follow a consistent pattern, with a locale prefix present in the URL for all languages.

Use Case: Ideal for situations where you want a consistent URL structure for all languages, ensuring every route includes the locale prefix.

typescript
i18n: {
+  strategy: 'prefix'
+}

Example Routes:

  • /en/about (for English)
  • /ru/about (for Russian)
  • /fr/about (for French)

🔄 prefix_and_default

This strategy combines both the prefix and prefix_except_default behaviors. It ensures that all languages have a locale prefix in their URLs, but the default language also has a non-prefixed URL version available. When the detectBrowserLanguage feature is enabled, the prefixed version of the default language will be preferred.

  • Behavior: Every language gets a URL with a locale prefix, but the default language also has a non-prefixed version.
  • Locale Handling: The default language has both a prefixed and non-prefixed URL, but the prefixed version takes priority when the browser language is detected.

Use Case: Best for applications that want to support both prefixed and non-prefixed URLs for the default language while maintaining a locale prefix for other languages.

typescript
i18n: {
+  strategy: 'prefix_and_default'
+}

Example Routes:

  • /about (for the default language, e.g., en)
  • /en/about (for English, with prefix)
  • /ru/about (for Russian)
  • /fr/about (for French)

⚠️ Known Issues and Best Practices

While the strategy option provides flexibility, there are some known issues and best practices to keep in mind when using these strategies.

1. Hydration Mismatch in no_prefix Strategy with Static Generation

When using the no_prefix strategy in combination with static site generation (generate mode), you may encounter a hydration mismatch error. This happens because the locale is determined dynamically (e.g., via cookies or browser settings) after the static page is rendered, leading to a mismatch between the server-rendered content and the client-side hydration.

Error Example:

Hydration completed but contains mismatches.

Workaround:

  • Avoid relying on dynamic locale changes during static generation.
  • Consider using a different strategy like prefix_except_default or prefix if static generation is a requirement.

2. Issues with localeRoute and Route Resolution

When using localeRoute to generate links, there can be issues with route resolution, especially if you rely on path-based routing. For example:

typescript
localeRoute('/page') // May cause issues with route resolution

Best Practice:

  • Always use named routes with localeRoute to avoid unnecessary redirects or route resolution problems:
typescript
localeRoute({ name: 'page' }) // Preferred approach

This ensures that the correct route is resolved regardless of the locale strategy.

3. Rendering Issues with Locale-Dependent Content in no_prefix Strategy

In the no_prefix strategy, rendering content that depends on the selected locale (e.g., buttons for switching languages) can lead to issues. For example, if you use a v-for loop to render locale buttons, Vue may incorrectly apply the disabled attribute due to hydration mismatches.

Example Problematic Code:

vue
<button
+  v-for="locale in availableLocales"
+  :key="locale.code"
+  :disabled="locale.isActive"
+  :class="{ disabled: locale.isActive }"
+  @click="() => $switchLocale(locale.code)"
+>
+  Switch to {{ locale.code }}
+</button>

Issue:

  • Vue may incorrectly apply the disabled attribute during hydration, and it may not update correctly when the locale changes.

Best Practice:

  • Use a <select> element or another approach that avoids direct DOM manipulation for locale-dependent content:
vue
<select @change="(e) => $switchLocale(e.target.value)">
+  <option
+    v-for="locale in availableLocales"
+    :key="locale.code"
+    :value="locale.code"
+    :selected="locale.isActive"
+  >
+    {{ locale.code }}
+  </option>
+</select>

This approach avoids hydration issues and ensures that the UI updates correctly when the locale changes.

📝 Conclusion

The new strategy option, introduced in version 1.50.0, provides more flexibility and control over how locale prefixes are handled in your application. Whether you need a clean, non-prefixed URL structure, or prefer to add locale prefixes for all or some languages, the available strategies allow you to customize your URL structure to fit your needs.

📚 Best Practices:

  • Simplicity for Default Language: If you don't need locale prefixes for your default language, use prefix_except_default or prefix_and_default.
  • Consistency: For a consistent URL structure with locale prefixes across all languages, use prefix.
  • User Experience: Consider using no_prefix when you want to rely on browser language detection and avoid cluttering the URL with prefixes.
  • Avoid Hydration Issues: Be cautious with no_prefix in static generation mode and use named routes with localeRoute for better route resolution.
  • Handle Locale-Dependent Content Carefully: Use <select> or other approaches to avoid hydration mismatches when rendering locale-dependent content.

By understanding and applying these strategies and best practices, you can ensure that your application's localization behavior fits your project's requirements while avoiding common pitfalls.

`,68)]))}const u=s(n,[["render",l]]);export{g as __pageData,u as default}; diff --git a/assets/guide_strategy.md.CUuNsgYn.lean.js b/assets/guide_strategy.md.CUuNsgYn.lean.js new file mode 100644 index 00000000..c263741a --- /dev/null +++ b/assets/guide_strategy.md.CUuNsgYn.lean.js @@ -0,0 +1,26 @@ +import{_ as s,c as i,a2 as a,o as t}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)","description":"","frontmatter":{},"headers":[],"relativePath":"guide/strategy.md","filePath":"guide/strategy.md","lastUpdated":1737355375000}'),n={name:"guide/strategy.md"};function l(o,e,r,h,p,d){return t(),i("div",null,e[0]||(e[0]=[a(`

🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)

📖 Introduction to Locale Prefix Strategies

Starting with version 1.50.0, Nuxt I18n introduces a more flexible way to manage how locale prefixes are handled in URLs through the strategy option. This new approach replaces the deprecated includeDefaultLocaleRoute and gives you better control over how localization is applied to different routes in your application.

The strategy option allows you to choose between different behaviors regarding locale prefixes, providing more fine-grained control over the URLs of your application and how they are structured based on the user's selected language.

🚦 strategy (New in Version 1.50.0)

The strategy option defines how locale prefixes should be managed across your routes. The available strategies give you varying levels of control over how the locale appears in the URLs.

Type: string
Default: prefix_and_default

Available Strategies:

🛑 no_prefix

This strategy ensures that no locale prefix is added to your routes. Instead of modifying the URL, the application will detect and change the locale based on the user's browser settings or cookies.

  • Behavior: Routes won't have any locale prefix.
  • Locale Detection: The locale is detected based on the user's browser language or cookies, and it is changed without altering the URL.
  • Restrictions: This strategy does not support features like Custom paths or Ignore routes.

Default Locale: You can set the default locale using an environment variable. For example:

  • DEFAULT_LOCALE=de npm run dev
  • DEFAULT_LOCALE=de npm run build

Use Case: Ideal when you want a cleaner URL structure and are relying on automatic language detection rather than explicit locale identifiers in the URL.

typescript
i18n: {
+  strategy: 'no_prefix'
+}

Example Routes:

  • /about (for any language, e.g., en, ru, fr, etc.)
  • /contact (for any language)
  • /other (for any language)
  • /other2 (for any language)

🚧 prefix_except_default

With this strategy, all of your routes will include a locale prefix, except for the default language. For the default language, the route will appear without any prefix.

  • Behavior: All routes will include a locale prefix, except for the default language.
  • Locale Handling: This ensures that only the default locale has URLs without a prefix, while all other locales will have a locale-specific prefix.

Use Case: Useful when you want all non-default languages to have a distinct URL structure with a locale prefix but prefer the default language to be accessible without the prefix.

typescript
i18n: {
+  strategy: 'prefix_except_default'
+}

Example Routes:

  • /about (for the default language, e.g., en)
  • /ru/about (for Russian)
  • /fr/about (for French)

🌍 prefix

This strategy ensures that every route in your application will include a locale prefix, regardless of the language. It standardizes the URL structure across all languages.

  • Behavior: All routes will have a locale prefix.
  • Locale Handling: Every route will follow a consistent pattern, with a locale prefix present in the URL for all languages.

Use Case: Ideal for situations where you want a consistent URL structure for all languages, ensuring every route includes the locale prefix.

typescript
i18n: {
+  strategy: 'prefix'
+}

Example Routes:

  • /en/about (for English)
  • /ru/about (for Russian)
  • /fr/about (for French)

🔄 prefix_and_default

This strategy combines both the prefix and prefix_except_default behaviors. It ensures that all languages have a locale prefix in their URLs, but the default language also has a non-prefixed URL version available. When the detectBrowserLanguage feature is enabled, the prefixed version of the default language will be preferred.

  • Behavior: Every language gets a URL with a locale prefix, but the default language also has a non-prefixed version.
  • Locale Handling: The default language has both a prefixed and non-prefixed URL, but the prefixed version takes priority when the browser language is detected.

Use Case: Best for applications that want to support both prefixed and non-prefixed URLs for the default language while maintaining a locale prefix for other languages.

typescript
i18n: {
+  strategy: 'prefix_and_default'
+}

Example Routes:

  • /about (for the default language, e.g., en)
  • /en/about (for English, with prefix)
  • /ru/about (for Russian)
  • /fr/about (for French)

⚠️ Known Issues and Best Practices

While the strategy option provides flexibility, there are some known issues and best practices to keep in mind when using these strategies.

1. Hydration Mismatch in no_prefix Strategy with Static Generation

When using the no_prefix strategy in combination with static site generation (generate mode), you may encounter a hydration mismatch error. This happens because the locale is determined dynamically (e.g., via cookies or browser settings) after the static page is rendered, leading to a mismatch between the server-rendered content and the client-side hydration.

Error Example:

Hydration completed but contains mismatches.

Workaround:

  • Avoid relying on dynamic locale changes during static generation.
  • Consider using a different strategy like prefix_except_default or prefix if static generation is a requirement.

2. Issues with localeRoute and Route Resolution

When using localeRoute to generate links, there can be issues with route resolution, especially if you rely on path-based routing. For example:

typescript
localeRoute('/page') // May cause issues with route resolution

Best Practice:

  • Always use named routes with localeRoute to avoid unnecessary redirects or route resolution problems:
typescript
localeRoute({ name: 'page' }) // Preferred approach

This ensures that the correct route is resolved regardless of the locale strategy.

3. Rendering Issues with Locale-Dependent Content in no_prefix Strategy

In the no_prefix strategy, rendering content that depends on the selected locale (e.g., buttons for switching languages) can lead to issues. For example, if you use a v-for loop to render locale buttons, Vue may incorrectly apply the disabled attribute due to hydration mismatches.

Example Problematic Code:

vue
<button
+  v-for="locale in availableLocales"
+  :key="locale.code"
+  :disabled="locale.isActive"
+  :class="{ disabled: locale.isActive }"
+  @click="() => $switchLocale(locale.code)"
+>
+  Switch to {{ locale.code }}
+</button>

Issue:

  • Vue may incorrectly apply the disabled attribute during hydration, and it may not update correctly when the locale changes.

Best Practice:

  • Use a <select> element or another approach that avoids direct DOM manipulation for locale-dependent content:
vue
<select @change="(e) => $switchLocale(e.target.value)">
+  <option
+    v-for="locale in availableLocales"
+    :key="locale.code"
+    :value="locale.code"
+    :selected="locale.isActive"
+  >
+    {{ locale.code }}
+  </option>
+</select>

This approach avoids hydration issues and ensures that the UI updates correctly when the locale changes.

📝 Conclusion

The new strategy option, introduced in version 1.50.0, provides more flexibility and control over how locale prefixes are handled in your application. Whether you need a clean, non-prefixed URL structure, or prefer to add locale prefixes for all or some languages, the available strategies allow you to customize your URL structure to fit your needs.

📚 Best Practices:

  • Simplicity for Default Language: If you don't need locale prefixes for your default language, use prefix_except_default or prefix_and_default.
  • Consistency: For a consistent URL structure with locale prefixes across all languages, use prefix.
  • User Experience: Consider using no_prefix when you want to rely on browser language detection and avoid cluttering the URL with prefixes.
  • Avoid Hydration Issues: Be cautious with no_prefix in static generation mode and use named routes with localeRoute for better route resolution.
  • Handle Locale-Dependent Content Carefully: Use <select> or other approaches to avoid hydration mismatches when rendering locale-dependent content.

By understanding and applying these strategies and best practices, you can ensure that your application's localization behavior fits your project's requirements while avoiding common pitfalls.

`,68)]))}const u=s(n,[["render",l]]);export{g as __pageData,u as default}; diff --git a/assets/guide_testing.md.BhPNxZf_.js b/assets/guide_testing.md.BhPNxZf_.js new file mode 100644 index 00000000..6330e58e --- /dev/null +++ b/assets/guide_testing.md.BhPNxZf_.js @@ -0,0 +1,104 @@ +import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const o=JSON.parse('{"title":"🧪 Testing Nuxt I18n Micro Module","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/testing.md","filePath":"guide/testing.md","lastUpdated":1733313494000}'),e={name:"guide/testing.md"};function l(h,s,p,k,r,E){return n(),a("div",null,s[0]||(s[0]=[t(`

🧪 Testing Nuxt I18n Micro Module

📖 Introduction to Testing

Testing the Nuxt I18n Micro module is crucial to ensure that your application's localization features work as expected. This documentation will guide you through setting up the testing environment, creating mock configurations for vitest, and writing tests for your components. For a practical example, you can refer to the example project on GitHub.

🛠️ Setting Up the Testing Environment

1. Install nuxt-i18n-micro-test-utils

First, you need to install the testing utilities for Nuxt I18n Micro. This package provides the necessary tools to mock and test your i18n configurations.

bash
npm install nuxt-i18n-micro-test-utils --save-dev

2. Create a Mock Configuration File

Next, create a file to set up the mock i18n configuration. This file will be used to mock the i18n functions and utilities during your tests.

typescript
// tests/unit-setup.ts
+
+import { mockNuxtImport } from '@nuxt/test-utils/runtime'
+import { vi } from 'vitest'
+import { i18nUtils } from 'nuxt-i18n-micro-test-utils'
+
+export function createFakeI18n() {
+  return {
+    $getLocale: vi.fn(i18nUtils.getLocale),
+    $t: vi.fn(i18nUtils.t),
+    $tc: vi.fn(i18nUtils.tc),
+    $setLocale: vi.fn(i18nUtils.setLocale),
+    $getLocaleName: vi.fn(i18nUtils.getLocaleName),
+    $setLocaleName: vi.fn(i18nUtils.setLocaleName),
+    $getLocales: vi.fn(i18nUtils.getLocales),
+    $setLocales: vi.fn(i18nUtils.setLocales),
+    $defaultLocale: vi.fn(i18nUtils.defaultLocale),
+    $setDefaultLocale: vi.fn(i18nUtils.setDefaultLocale),
+    $getRouteName: vi.fn(i18nUtils.getRouteName),
+    $settRouteName: vi.fn(i18nUtils.settRouteName),
+    $ts: vi.fn(i18nUtils.ts),
+    $tn: vi.fn(i18nUtils.tn),
+    $td: vi.fn(i18nUtils.td),
+    $has: vi.fn(i18nUtils.has),
+    $mergeTranslations: vi.fn(i18nUtils.mergeTranslations),
+    $switchLocaleRoute: vi.fn(i18nUtils.switchLocaleRoute),
+    $switchLocalePath: vi.fn(i18nUtils.switchLocalePath),
+    $switchLocale: vi.fn(i18nUtils.switchLocale),
+    $switchRoute: vi.fn(i18nUtils.switchRoute),
+    $localeRoute: vi.fn(i18nUtils.localeRoute),
+    $localePath: vi.fn(i18nUtils.localePath),
+    $setI18nRouteParams: vi.fn(i18nUtils.setI18nRouteParams),
+  }
+}
+
+mockNuxtImport<() => ReturnType<typeof createFakeI18n>>('useI18n', () =>
+  vi.fn(() => createFakeI18n()),
+)
+
+export const setTranslationsFromJson = i18nUtils.setTranslationsFromJson

3. Configure Vitest

Now, configure Vitest to use the mock configuration file and set up the testing environment.

typescript
// vitest.config.ts
+
+import { defineVitestConfig } from '@nuxt/test-utils/config'
+
+export default defineVitestConfig({
+  test: {
+    watch: false,
+    setupFiles: ['./tests/unit-setup.ts'],
+    include: ['./**/*.spec.ts'],
+  },
+})

🧪 Writing Tests

Example Component

Here’s an example of a simple component that uses the useI18n composable to translate messages.

vue
<script setup lang="ts">
+const { $t } = useI18n()
+
+const props = defineProps({
+  message: {
+    type: String,
+    default: null,
+  },
+})
+
+// Test to see that $t works in script setup as well as the template
+const message = props.message || $t('defaultMessage')
+</script>
+
+<template>
+  <div>
+    <p>Test from component: {{ $t('welcome') }}</p>
+    <p data-testid="message">
+      Test message from props: {{ message }}
+    </p>
+  </div>
+</template>

Test File

Now, let’s write a test for this component.

typescript
// tests/unit/example.spec.ts
+
+import { describe, it, expect, beforeEach } from 'vitest'
+import { mount } from '@vue/test-utils'
+import ExampleComponent from '@/components/ExampleComponent.vue'
+import fs from 'fs'
+import path from 'path'
+import { setTranslationsFromJson } from './unit-setup'
+
+describe('ExampleComponent', () => {
+  beforeEach(async () => {
+    const fileContent = fs.readFileSync(path.join(__dirname, '../../locales/en-GB.json')).toString()
+    await setTranslationsFromJson('en', JSON.parse(fileContent))
+  })
+
+  it('renders the welcome message correctly', () => {
+    const wrapper = mount(ExampleComponent)
+    expect(wrapper.text()).toContain('Test from component: Welcome')
+  })
+
+  it('renders the default message correctly', () => {
+    const wrapper = mount(ExampleComponent)
+    expect(wrapper.find('[data-testid="message"]').text()).toContain('Test message from props: Default Message')
+  })
+
+  it('renders the custom message correctly', () => {
+    const wrapper = mount(ExampleComponent, {
+      props: {
+        message: 'Custom Message',
+      },
+    })
+    expect(wrapper.find('[data-testid="message"]').text()).toContain('Test message from props: Custom Message')
+  })
+})

📝 Best Practices for Testing

  • 🔧 Mock i18n Functions: Always mock the i18n functions using nuxt-i18n-micro-test-utils to ensure consistent and predictable test results.
  • ⚙️ Use Vitest for Unit Tests: Vitest is a powerful testing framework for Vue applications. Use it to write unit tests for your components.
  • 📚 Document Your Tests: Clearly document the purpose and expected outcomes of each test. This will help maintain clarity and make it easier for others (or future you) to understand the tests.

📊 i18n Utility Methods

Below is a table describing all the utility methods provided by nuxt-i18n-micro-test-utils.

MethodDescription
t(key, params, defaultValue)Translates a key with optional parameters and a default value.
tc(key, params, defaultValue)Translates a key with pluralization support.
setTranslationsFromJson(locale, translations)Loads translations from a JSON object for a specific locale.
getLocale()Returns the current locale.
setLocale(val)Sets the current locale.
getLocaleName()Returns the current locale name.
setLocaleName(val)Sets the current locale name.
getLocales()Returns the list of available locales.
setLocales(val)Sets the list of available locales.
defaultLocale()Returns the default locale.
setDefaultLocale(val)Sets the default locale.
getRouteName()Returns the current route name.
settRouteName(val)Sets the current route name.
ts(key, params, defaultValue)Translates a key and returns the result as a string.
tn(value, options)Formats a number according to the current locale.
td(value, options)Formats a date according to the current locale.
has(key)Checks if a translation key exists.

By following these steps, you can effectively test the Nuxt I18n Micro module and ensure that your application's localization features work as expected.

`,26)]))}const g=i(e,[["render",l]]);export{o as __pageData,g as default}; diff --git a/assets/guide_testing.md.BhPNxZf_.lean.js b/assets/guide_testing.md.BhPNxZf_.lean.js new file mode 100644 index 00000000..6330e58e --- /dev/null +++ b/assets/guide_testing.md.BhPNxZf_.lean.js @@ -0,0 +1,104 @@ +import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const o=JSON.parse('{"title":"🧪 Testing Nuxt I18n Micro Module","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/testing.md","filePath":"guide/testing.md","lastUpdated":1733313494000}'),e={name:"guide/testing.md"};function l(h,s,p,k,r,E){return n(),a("div",null,s[0]||(s[0]=[t(`

🧪 Testing Nuxt I18n Micro Module

📖 Introduction to Testing

Testing the Nuxt I18n Micro module is crucial to ensure that your application's localization features work as expected. This documentation will guide you through setting up the testing environment, creating mock configurations for vitest, and writing tests for your components. For a practical example, you can refer to the example project on GitHub.

🛠️ Setting Up the Testing Environment

1. Install nuxt-i18n-micro-test-utils

First, you need to install the testing utilities for Nuxt I18n Micro. This package provides the necessary tools to mock and test your i18n configurations.

bash
npm install nuxt-i18n-micro-test-utils --save-dev

2. Create a Mock Configuration File

Next, create a file to set up the mock i18n configuration. This file will be used to mock the i18n functions and utilities during your tests.

typescript
// tests/unit-setup.ts
+
+import { mockNuxtImport } from '@nuxt/test-utils/runtime'
+import { vi } from 'vitest'
+import { i18nUtils } from 'nuxt-i18n-micro-test-utils'
+
+export function createFakeI18n() {
+  return {
+    $getLocale: vi.fn(i18nUtils.getLocale),
+    $t: vi.fn(i18nUtils.t),
+    $tc: vi.fn(i18nUtils.tc),
+    $setLocale: vi.fn(i18nUtils.setLocale),
+    $getLocaleName: vi.fn(i18nUtils.getLocaleName),
+    $setLocaleName: vi.fn(i18nUtils.setLocaleName),
+    $getLocales: vi.fn(i18nUtils.getLocales),
+    $setLocales: vi.fn(i18nUtils.setLocales),
+    $defaultLocale: vi.fn(i18nUtils.defaultLocale),
+    $setDefaultLocale: vi.fn(i18nUtils.setDefaultLocale),
+    $getRouteName: vi.fn(i18nUtils.getRouteName),
+    $settRouteName: vi.fn(i18nUtils.settRouteName),
+    $ts: vi.fn(i18nUtils.ts),
+    $tn: vi.fn(i18nUtils.tn),
+    $td: vi.fn(i18nUtils.td),
+    $has: vi.fn(i18nUtils.has),
+    $mergeTranslations: vi.fn(i18nUtils.mergeTranslations),
+    $switchLocaleRoute: vi.fn(i18nUtils.switchLocaleRoute),
+    $switchLocalePath: vi.fn(i18nUtils.switchLocalePath),
+    $switchLocale: vi.fn(i18nUtils.switchLocale),
+    $switchRoute: vi.fn(i18nUtils.switchRoute),
+    $localeRoute: vi.fn(i18nUtils.localeRoute),
+    $localePath: vi.fn(i18nUtils.localePath),
+    $setI18nRouteParams: vi.fn(i18nUtils.setI18nRouteParams),
+  }
+}
+
+mockNuxtImport<() => ReturnType<typeof createFakeI18n>>('useI18n', () =>
+  vi.fn(() => createFakeI18n()),
+)
+
+export const setTranslationsFromJson = i18nUtils.setTranslationsFromJson

3. Configure Vitest

Now, configure Vitest to use the mock configuration file and set up the testing environment.

typescript
// vitest.config.ts
+
+import { defineVitestConfig } from '@nuxt/test-utils/config'
+
+export default defineVitestConfig({
+  test: {
+    watch: false,
+    setupFiles: ['./tests/unit-setup.ts'],
+    include: ['./**/*.spec.ts'],
+  },
+})

🧪 Writing Tests

Example Component

Here’s an example of a simple component that uses the useI18n composable to translate messages.

vue
<script setup lang="ts">
+const { $t } = useI18n()
+
+const props = defineProps({
+  message: {
+    type: String,
+    default: null,
+  },
+})
+
+// Test to see that $t works in script setup as well as the template
+const message = props.message || $t('defaultMessage')
+</script>
+
+<template>
+  <div>
+    <p>Test from component: {{ $t('welcome') }}</p>
+    <p data-testid="message">
+      Test message from props: {{ message }}
+    </p>
+  </div>
+</template>

Test File

Now, let’s write a test for this component.

typescript
// tests/unit/example.spec.ts
+
+import { describe, it, expect, beforeEach } from 'vitest'
+import { mount } from '@vue/test-utils'
+import ExampleComponent from '@/components/ExampleComponent.vue'
+import fs from 'fs'
+import path from 'path'
+import { setTranslationsFromJson } from './unit-setup'
+
+describe('ExampleComponent', () => {
+  beforeEach(async () => {
+    const fileContent = fs.readFileSync(path.join(__dirname, '../../locales/en-GB.json')).toString()
+    await setTranslationsFromJson('en', JSON.parse(fileContent))
+  })
+
+  it('renders the welcome message correctly', () => {
+    const wrapper = mount(ExampleComponent)
+    expect(wrapper.text()).toContain('Test from component: Welcome')
+  })
+
+  it('renders the default message correctly', () => {
+    const wrapper = mount(ExampleComponent)
+    expect(wrapper.find('[data-testid="message"]').text()).toContain('Test message from props: Default Message')
+  })
+
+  it('renders the custom message correctly', () => {
+    const wrapper = mount(ExampleComponent, {
+      props: {
+        message: 'Custom Message',
+      },
+    })
+    expect(wrapper.find('[data-testid="message"]').text()).toContain('Test message from props: Custom Message')
+  })
+})

📝 Best Practices for Testing

  • 🔧 Mock i18n Functions: Always mock the i18n functions using nuxt-i18n-micro-test-utils to ensure consistent and predictable test results.
  • ⚙️ Use Vitest for Unit Tests: Vitest is a powerful testing framework for Vue applications. Use it to write unit tests for your components.
  • 📚 Document Your Tests: Clearly document the purpose and expected outcomes of each test. This will help maintain clarity and make it easier for others (or future you) to understand the tests.

📊 i18n Utility Methods

Below is a table describing all the utility methods provided by nuxt-i18n-micro-test-utils.

MethodDescription
t(key, params, defaultValue)Translates a key with optional parameters and a default value.
tc(key, params, defaultValue)Translates a key with pluralization support.
setTranslationsFromJson(locale, translations)Loads translations from a JSON object for a specific locale.
getLocale()Returns the current locale.
setLocale(val)Sets the current locale.
getLocaleName()Returns the current locale name.
setLocaleName(val)Sets the current locale name.
getLocales()Returns the list of available locales.
setLocales(val)Sets the list of available locales.
defaultLocale()Returns the default locale.
setDefaultLocale(val)Sets the default locale.
getRouteName()Returns the current route name.
settRouteName(val)Sets the current route name.
ts(key, params, defaultValue)Translates a key and returns the result as a string.
tn(value, options)Formats a number according to the current locale.
td(value, options)Formats a date according to the current locale.
has(key)Checks if a translation key exists.

By following these steps, you can effectively test the Nuxt I18n Micro module and ensure that your application's localization features work as expected.

`,26)]))}const g=i(e,[["render",l]]);export{o as __pageData,g as default}; diff --git a/assets/index.md.iT9qvt2L.js b/assets/index.md.iT9qvt2L.js new file mode 100644 index 00000000..ea44991c --- /dev/null +++ b/assets/index.md.iT9qvt2L.js @@ -0,0 +1,27 @@ +import{_ as i,c as n,a2 as e,o as a}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Nuxt I18n Micro","text":"Fast, Simple, and Lightweight Internationalization for Nuxt","tagline":"Optimize your Nuxt app with a powerful and efficient i18n solution.","actions":[{"theme":"brand","text":"🚀 Get Started","link":"/guide/getting-started"},{"theme":"alt","text":"⭐ View on GitHub","link":"https://github.com/s00d/nuxt-i18n-micro"}]},"features":[{"title":"⚡ High Performance","details":"🚀 Significant reductions in build times, memory usage, and server load, making it ideal for large-scale projects."},{"title":"🪶 Compact and Lightweight","details":"🧩 Designed for efficiency, reducing the total bundle size by up to 96% compared to traditional i18n modules."},{"title":"🎨 Minimalist Design","details":"🧱 A simple structure with just 5 components, easy to extend and maintain."},{"title":"🔄 Dynamic Routing","details":"🗺️ Efficient regex-based routing that generates only two routes regardless of the number of locales."},{"title":"📂 Streamlined Translation Loading","details":"🔧 Supports only JSON files, with auto-generated page-specific translations."},{"title":"🌐 Seamless Nuxt Integration","details":"🛠️ Seamless integration with Nuxt.js, making it easy to add powerful i18n features to your application."}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1724249388000}'),t={name:"index.md"};function r(l,s,o,p,d,h){return a(),n("div",null,s[0]||(s[0]=[e(`

✨ Introduction

Nuxt I18n Micro is a fast, simple, and lightweight internationalization (i18n) module for Nuxt. Despite its compact size, it's designed with large projects in mind, offering significant performance improvements over traditional i18n solutions like nuxt-i18n. The module was built from the ground up to be highly efficient, focusing on minimizing build times, reducing server load, and shrinking bundle sizes.

📝 Why Nuxt I18n Micro?

The Nuxt I18n Micro module was created to address critical performance issues found in the original nuxt-i18n module, particularly in high-traffic environments and projects with large translation files. Key issues with nuxt-i18n include:

  • 🚨 High Memory Consumption: Consumes significant memory during both build and runtime, leading to performance bottlenecks.
  • 🐢 Slow Performance: Especially with large translation files, it causes noticeable slowdowns in build times and server response.
  • 💼 Large Bundle Size: Generates a large bundle, negatively impacting application performance.
  • 🐛 Memory Leaks and Bugs: Known for memory leaks and unpredictable behavior under heavy load.

🏁 Performance Comparison

To showcase the efficiency of Nuxt I18n Micro, we conducted tests under identical conditions. Both modules were tested with a 10MB translation file on the same hardware.

⏱️ Build Time and Resource Consumption

Nuxt I18n
  • Total Size: 54.7 MB (3.31 MB gzip)
  • Max CPU Usage: 391.4%
  • Max Memory Usage: 8305 MB
  • Elapsed Time: 0h 1m 31s

Nuxt I18n Micro

  • Total Size: 1.93 MB (473 kB gzip) — 96% smaller
  • Max CPU Usage: 220.1% — 44% lower
  • Max Memory Usage: 655 MB — 92% less memory
  • Elapsed Time: 0h 0m 5s — 94% faster

🌐 Server Performance (10k Requests)

Nuxt I18n
  • Requests per Second: 49.05 [#/sec] (mean)
  • Time per Request: 611.599 ms (mean)
  • Max Memory Usage: 703.73 MB

Nuxt I18n Micro

  • Requests per Second: 61.18 [#/sec] (mean) — 25% more requests per second
  • Time per Request: 490.379 ms (mean) — 20% faster
  • Max Memory Usage: 323.00 MB — 54% less memory usage

These results clearly demonstrate that Nuxt I18n Micro significantly outperforms the original module in every critical area.

🔑 Key Features

  • 🌐 Compact Yet Powerful: Despite its small size, Nuxt I18n Micro is designed for large-scale projects, focusing on performance and efficiency.
  • Optimized Build and Runtime: Reduces build times, memory usage, and server load, making it ideal for high-traffic applications.
  • 🛠️ Minimalist Design: The module is structured around just 5 components (1 module and 4 plugins), making it easy to understand, extend, and maintain.
  • 📏 Efficient Routing: Generates only 2 routes regardless of the number of locales, thanks to dynamic regex-based routing, unlike other i18n modules that generate separate routes for each locale.
  • 🗂 Streamlined Translation Loading: Only JSON files are supported, with translations split between a global file for common texts (e.g., menus) and page-specific files, which are auto-generated in the dev mode if not present.

⚙️ Quick Setup

Install the module in your Nuxt application with:

bash
npm install nuxt-i18n-micro

Then, add it to your nuxt.config.ts:

typescript
export default defineNuxtConfig({
+  modules: [
+    'nuxt-i18n-micro',
+  ],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

That's it! You're now ready to use Nuxt I18n Micro in your Nuxt app.

🗂 Folder Structure

Translations are organized into global and page-specific files:

plaintext
  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json
`,26)]))}const u=i(t,[["render",r]]);export{g as __pageData,u as default}; diff --git a/assets/index.md.iT9qvt2L.lean.js b/assets/index.md.iT9qvt2L.lean.js new file mode 100644 index 00000000..ea44991c --- /dev/null +++ b/assets/index.md.iT9qvt2L.lean.js @@ -0,0 +1,27 @@ +import{_ as i,c as n,a2 as e,o as a}from"./chunks/framework.Gfs4HC1t.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Nuxt I18n Micro","text":"Fast, Simple, and Lightweight Internationalization for Nuxt","tagline":"Optimize your Nuxt app with a powerful and efficient i18n solution.","actions":[{"theme":"brand","text":"🚀 Get Started","link":"/guide/getting-started"},{"theme":"alt","text":"⭐ View on GitHub","link":"https://github.com/s00d/nuxt-i18n-micro"}]},"features":[{"title":"⚡ High Performance","details":"🚀 Significant reductions in build times, memory usage, and server load, making it ideal for large-scale projects."},{"title":"🪶 Compact and Lightweight","details":"🧩 Designed for efficiency, reducing the total bundle size by up to 96% compared to traditional i18n modules."},{"title":"🎨 Minimalist Design","details":"🧱 A simple structure with just 5 components, easy to extend and maintain."},{"title":"🔄 Dynamic Routing","details":"🗺️ Efficient regex-based routing that generates only two routes regardless of the number of locales."},{"title":"📂 Streamlined Translation Loading","details":"🔧 Supports only JSON files, with auto-generated page-specific translations."},{"title":"🌐 Seamless Nuxt Integration","details":"🛠️ Seamless integration with Nuxt.js, making it easy to add powerful i18n features to your application."}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1724249388000}'),t={name:"index.md"};function r(l,s,o,p,d,h){return a(),n("div",null,s[0]||(s[0]=[e(`

✨ Introduction

Nuxt I18n Micro is a fast, simple, and lightweight internationalization (i18n) module for Nuxt. Despite its compact size, it's designed with large projects in mind, offering significant performance improvements over traditional i18n solutions like nuxt-i18n. The module was built from the ground up to be highly efficient, focusing on minimizing build times, reducing server load, and shrinking bundle sizes.

📝 Why Nuxt I18n Micro?

The Nuxt I18n Micro module was created to address critical performance issues found in the original nuxt-i18n module, particularly in high-traffic environments and projects with large translation files. Key issues with nuxt-i18n include:

  • 🚨 High Memory Consumption: Consumes significant memory during both build and runtime, leading to performance bottlenecks.
  • 🐢 Slow Performance: Especially with large translation files, it causes noticeable slowdowns in build times and server response.
  • 💼 Large Bundle Size: Generates a large bundle, negatively impacting application performance.
  • 🐛 Memory Leaks and Bugs: Known for memory leaks and unpredictable behavior under heavy load.

🏁 Performance Comparison

To showcase the efficiency of Nuxt I18n Micro, we conducted tests under identical conditions. Both modules were tested with a 10MB translation file on the same hardware.

⏱️ Build Time and Resource Consumption

Nuxt I18n
  • Total Size: 54.7 MB (3.31 MB gzip)
  • Max CPU Usage: 391.4%
  • Max Memory Usage: 8305 MB
  • Elapsed Time: 0h 1m 31s

Nuxt I18n Micro

  • Total Size: 1.93 MB (473 kB gzip) — 96% smaller
  • Max CPU Usage: 220.1% — 44% lower
  • Max Memory Usage: 655 MB — 92% less memory
  • Elapsed Time: 0h 0m 5s — 94% faster

🌐 Server Performance (10k Requests)

Nuxt I18n
  • Requests per Second: 49.05 [#/sec] (mean)
  • Time per Request: 611.599 ms (mean)
  • Max Memory Usage: 703.73 MB

Nuxt I18n Micro

  • Requests per Second: 61.18 [#/sec] (mean) — 25% more requests per second
  • Time per Request: 490.379 ms (mean) — 20% faster
  • Max Memory Usage: 323.00 MB — 54% less memory usage

These results clearly demonstrate that Nuxt I18n Micro significantly outperforms the original module in every critical area.

🔑 Key Features

  • 🌐 Compact Yet Powerful: Despite its small size, Nuxt I18n Micro is designed for large-scale projects, focusing on performance and efficiency.
  • Optimized Build and Runtime: Reduces build times, memory usage, and server load, making it ideal for high-traffic applications.
  • 🛠️ Minimalist Design: The module is structured around just 5 components (1 module and 4 plugins), making it easy to understand, extend, and maintain.
  • 📏 Efficient Routing: Generates only 2 routes regardless of the number of locales, thanks to dynamic regex-based routing, unlike other i18n modules that generate separate routes for each locale.
  • 🗂 Streamlined Translation Loading: Only JSON files are supported, with translations split between a global file for common texts (e.g., menus) and page-specific files, which are auto-generated in the dev mode if not present.

⚙️ Quick Setup

Install the module in your Nuxt application with:

bash
npm install nuxt-i18n-micro

Then, add it to your nuxt.config.ts:

typescript
export default defineNuxtConfig({
+  modules: [
+    'nuxt-i18n-micro',
+  ],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

That's it! You're now ready to use Nuxt I18n Micro in your Nuxt app.

🗂 Folder Structure

Translations are organized into global and page-specific files:

plaintext
  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json
`,26)]))}const u=i(t,[["render",r]]);export{g as __pageData,u as default}; diff --git a/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 b/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 new file mode 100644 index 00000000..b6b603d5 Binary files /dev/null and b/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 differ diff --git a/assets/inter-italic-cyrillic.By2_1cv3.woff2 b/assets/inter-italic-cyrillic.By2_1cv3.woff2 new file mode 100644 index 00000000..def40a4f Binary files /dev/null and b/assets/inter-italic-cyrillic.By2_1cv3.woff2 differ diff --git a/assets/inter-italic-greek-ext.1u6EdAuj.woff2 b/assets/inter-italic-greek-ext.1u6EdAuj.woff2 new file mode 100644 index 00000000..e070c3d3 Binary files /dev/null and b/assets/inter-italic-greek-ext.1u6EdAuj.woff2 differ diff --git a/assets/inter-italic-greek.DJ8dCoTZ.woff2 b/assets/inter-italic-greek.DJ8dCoTZ.woff2 new file mode 100644 index 00000000..a3c16ca4 Binary files /dev/null and b/assets/inter-italic-greek.DJ8dCoTZ.woff2 differ diff --git a/assets/inter-italic-latin-ext.CN1xVJS-.woff2 b/assets/inter-italic-latin-ext.CN1xVJS-.woff2 new file mode 100644 index 00000000..2210a899 Binary files /dev/null and b/assets/inter-italic-latin-ext.CN1xVJS-.woff2 differ diff --git a/assets/inter-italic-latin.C2AdPX0b.woff2 b/assets/inter-italic-latin.C2AdPX0b.woff2 new file mode 100644 index 00000000..790d62dc Binary files /dev/null and b/assets/inter-italic-latin.C2AdPX0b.woff2 differ diff --git a/assets/inter-italic-vietnamese.BSbpV94h.woff2 b/assets/inter-italic-vietnamese.BSbpV94h.woff2 new file mode 100644 index 00000000..1eec0775 Binary files /dev/null and b/assets/inter-italic-vietnamese.BSbpV94h.woff2 differ diff --git a/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 b/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 new file mode 100644 index 00000000..2cfe6153 Binary files /dev/null and b/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 differ diff --git a/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 b/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 new file mode 100644 index 00000000..e3886dd1 Binary files /dev/null and b/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 differ diff --git a/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 b/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 new file mode 100644 index 00000000..36d67487 Binary files /dev/null and b/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 differ diff --git a/assets/inter-roman-greek.BBVDIX6e.woff2 b/assets/inter-roman-greek.BBVDIX6e.woff2 new file mode 100644 index 00000000..2bed1e85 Binary files /dev/null and b/assets/inter-roman-greek.BBVDIX6e.woff2 differ diff --git a/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 b/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 new file mode 100644 index 00000000..9a8d1e2b Binary files /dev/null and b/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 differ diff --git a/assets/inter-roman-latin.Di8DUHzh.woff2 b/assets/inter-roman-latin.Di8DUHzh.woff2 new file mode 100644 index 00000000..07d3c53a Binary files /dev/null and b/assets/inter-roman-latin.Di8DUHzh.woff2 differ diff --git a/assets/inter-roman-vietnamese.BjW4sHH5.woff2 b/assets/inter-roman-vietnamese.BjW4sHH5.woff2 new file mode 100644 index 00000000..57bdc22a Binary files /dev/null and b/assets/inter-roman-vietnamese.BjW4sHH5.woff2 differ diff --git a/assets/news_index.md.DN4b2rDE.js b/assets/news_index.md.DN4b2rDE.js new file mode 100644 index 00000000..868835d6 --- /dev/null +++ b/assets/news_index.md.DN4b2rDE.js @@ -0,0 +1,11 @@ +import{_ as s}from"./chunks/text-to-i18n.CC9iMeyu.js";import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const r="/nuxt-i18n-micro/1.65.0.jpg",o="/nuxt-i18n-micro/optimized-loading.png",E=JSON.parse('{"title":"News","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"news/index.md","filePath":"news/index.md","lastUpdated":1737360710000}'),l={name:"news/index.md"};function h(d,e,p,g,c,k){return n(),a("div",null,e[0]||(e[0]=[t('

News

Major Release: Nuxt I18n Micro v1.65.0

Date: 2025-01-20

Version: v1.65.0

1.65.0

We’re thrilled to announce v1.65.0, featuring a complete rewrite of core logic for better performance and maintainability! This release includes enhanced TypeScript support, client-side locale redirection, and streamlined translation handling. Upgrade now for a smoother, faster experience! 🚀

Learn more

Optimized Translation Loading Algorithm Released

Date: 2025-01-10

Version Introduced: v1.58.0

Optimized Loading Demo

We are thrilled to announce the release of a new algorithm for loading translations in Nuxt I18n Micro. This update introduces significant performance improvements, a cleaner architecture, and more efficient memory usage.

What’s New?

The new translation-loading algorithm focuses on:

  1. Optimized File Merging: Enhanced the deep merge functionality to handle translations more efficiently.
  2. Caching Enhancements: Leveraged server storage for pre-rendered translations, reducing redundant computations.
  3. Streamlined Code: Simplified file paths and structure for better maintainability.

Key Benefits

1. Faster Build Times

The new algorithm reduces build times by efficiently handling translation files and minimizing memory overhead.

  • Old Build Time: 7.20 seconds
  • New Build Time: 6.91 seconds
  • Improvement: 4.03% faster

2. Reduced CPU Usage

Lower maximum and average CPU usage during builds and stress tests:

  • Build Max CPU: From 257.60%198.20% (23.06% lower)
  • Stress Test Avg CPU: From 93.85%89.14% (5.01% lower)

3. Lower Memory Usage

Memory consumption has been significantly optimized across builds and runtime stress tests:

  • Build Max Memory: From 1286.00 MB885.19 MB (31.15% lower)
  • Stress Test Max Memory: From 624.22 MB429.52 MB (31.20% lower)

4. Enhanced Response Times

Stress test response times saw drastic improvement:

  • Average Response Time: From 411.50 ms9.30 ms (97.74% faster)
  • Max Response Time: From 2723.00 ms187.00 ms (93.13% faster)

5. Increased Request Throughput

The new algorithm boosts the number of handled requests per second:

  • Requests per Second: From 288.00305.00 (5.90% increase)

Why It’s Important

Localization is essential for global applications, and improving translation-loading performance can have a direct impact on:

  • User Experience: Faster response times lead to a smoother user experience.
  • Scalability: Lower resource usage allows better handling of high traffic.
  • Developer Productivity: Reduced build times and a simplified codebase streamline workflows.

How It Works

  1. Efficient Deep Merging
  • The algorithm has been rewritten to handle translation merging more intelligently, ensuring minimal memory overhead and faster operations.
  1. Smart Caching
  • Server-side storage is now used to cache translations during pre-rendering, which are then reused during runtime. This avoids repetitive reads and merges.
  1. Streamlined File Loading
  • Translation files are loaded in a more predictable and maintainable way by unifying fallback handling and caching.

New CLI Feature: text-to-i18n

Date: 2024-12-24

Cli Version Introduced: v1.1.0

text-to-i18n Command Demo

We’re excited to announce the new text-to-i18n command in the Nuxt I18n Micro CLI! This powerful feature automates the process of extracting hardcoded text strings from your codebase and converting them into i18n translation keys. It’s designed to save time, reduce errors, and streamline your localization workflow.

Key Benefits

  • Automated Text Extraction: Scans Vue templates, JavaScript, and TypeScript files.
  • Seamless Key Generation: Creates structured translation keys based on file paths and content.
  • Efficient Translation Management: Updates your translation files while preserving existing entries.

How It Works

  1. File Scanning: Processes files in key directories like pages, components, and plugins.
  2. Text Processing: Identifies and extracts translatable strings, generating unique keys.
  3. Translation Updates: Automatically inserts new keys into your translation files and maintains their nested structure.

Usage

bash
i18n-micro text-to-i18n [options]

Example:

bash
i18n-micro text-to-i18n --translationFile locales/en.json --context auth

Example Transformations

Before

vue
<template>
+  <div>
+    <h1>Welcome to our site</h1>
+    <p>Please sign in to continue</p>
+  </div>
+</template>

After

vue
<template>
+  <div>
+    <h1>{{ $t('pages.home.welcome_to_our_site') }}</h1>
+    <p>{{ $t('pages.home.please_sign_in') }}</p>
+  </div>
+</template>

For more details, check out the documentation.


`,64)]))}const f=i(l,[["render",h]]);export{E as __pageData,f as default}; diff --git a/assets/news_index.md.DN4b2rDE.lean.js b/assets/news_index.md.DN4b2rDE.lean.js new file mode 100644 index 00000000..868835d6 --- /dev/null +++ b/assets/news_index.md.DN4b2rDE.lean.js @@ -0,0 +1,11 @@ +import{_ as s}from"./chunks/text-to-i18n.CC9iMeyu.js";import{_ as i,c as a,a2 as t,o as n}from"./chunks/framework.Gfs4HC1t.js";const r="/nuxt-i18n-micro/1.65.0.jpg",o="/nuxt-i18n-micro/optimized-loading.png",E=JSON.parse('{"title":"News","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"news/index.md","filePath":"news/index.md","lastUpdated":1737360710000}'),l={name:"news/index.md"};function h(d,e,p,g,c,k){return n(),a("div",null,e[0]||(e[0]=[t('

News

Major Release: Nuxt I18n Micro v1.65.0

Date: 2025-01-20

Version: v1.65.0

1.65.0

We’re thrilled to announce v1.65.0, featuring a complete rewrite of core logic for better performance and maintainability! This release includes enhanced TypeScript support, client-side locale redirection, and streamlined translation handling. Upgrade now for a smoother, faster experience! 🚀

Learn more

Optimized Translation Loading Algorithm Released

Date: 2025-01-10

Version Introduced: v1.58.0

Optimized Loading Demo

We are thrilled to announce the release of a new algorithm for loading translations in Nuxt I18n Micro. This update introduces significant performance improvements, a cleaner architecture, and more efficient memory usage.

What’s New?

The new translation-loading algorithm focuses on:

  1. Optimized File Merging: Enhanced the deep merge functionality to handle translations more efficiently.
  2. Caching Enhancements: Leveraged server storage for pre-rendered translations, reducing redundant computations.
  3. Streamlined Code: Simplified file paths and structure for better maintainability.

Key Benefits

1. Faster Build Times

The new algorithm reduces build times by efficiently handling translation files and minimizing memory overhead.

  • Old Build Time: 7.20 seconds
  • New Build Time: 6.91 seconds
  • Improvement: 4.03% faster

2. Reduced CPU Usage

Lower maximum and average CPU usage during builds and stress tests:

  • Build Max CPU: From 257.60%198.20% (23.06% lower)
  • Stress Test Avg CPU: From 93.85%89.14% (5.01% lower)

3. Lower Memory Usage

Memory consumption has been significantly optimized across builds and runtime stress tests:

  • Build Max Memory: From 1286.00 MB885.19 MB (31.15% lower)
  • Stress Test Max Memory: From 624.22 MB429.52 MB (31.20% lower)

4. Enhanced Response Times

Stress test response times saw drastic improvement:

  • Average Response Time: From 411.50 ms9.30 ms (97.74% faster)
  • Max Response Time: From 2723.00 ms187.00 ms (93.13% faster)

5. Increased Request Throughput

The new algorithm boosts the number of handled requests per second:

  • Requests per Second: From 288.00305.00 (5.90% increase)

Why It’s Important

Localization is essential for global applications, and improving translation-loading performance can have a direct impact on:

  • User Experience: Faster response times lead to a smoother user experience.
  • Scalability: Lower resource usage allows better handling of high traffic.
  • Developer Productivity: Reduced build times and a simplified codebase streamline workflows.

How It Works

  1. Efficient Deep Merging
  • The algorithm has been rewritten to handle translation merging more intelligently, ensuring minimal memory overhead and faster operations.
  1. Smart Caching
  • Server-side storage is now used to cache translations during pre-rendering, which are then reused during runtime. This avoids repetitive reads and merges.
  1. Streamlined File Loading
  • Translation files are loaded in a more predictable and maintainable way by unifying fallback handling and caching.

New CLI Feature: text-to-i18n

Date: 2024-12-24

Cli Version Introduced: v1.1.0

text-to-i18n Command Demo

We’re excited to announce the new text-to-i18n command in the Nuxt I18n Micro CLI! This powerful feature automates the process of extracting hardcoded text strings from your codebase and converting them into i18n translation keys. It’s designed to save time, reduce errors, and streamline your localization workflow.

Key Benefits

  • Automated Text Extraction: Scans Vue templates, JavaScript, and TypeScript files.
  • Seamless Key Generation: Creates structured translation keys based on file paths and content.
  • Efficient Translation Management: Updates your translation files while preserving existing entries.

How It Works

  1. File Scanning: Processes files in key directories like pages, components, and plugins.
  2. Text Processing: Identifies and extracts translatable strings, generating unique keys.
  3. Translation Updates: Automatically inserts new keys into your translation files and maintains their nested structure.

Usage

bash
i18n-micro text-to-i18n [options]

Example:

bash
i18n-micro text-to-i18n --translationFile locales/en.json --context auth

Example Transformations

Before

vue
<template>
+  <div>
+    <h1>Welcome to our site</h1>
+    <p>Please sign in to continue</p>
+  </div>
+</template>

After

vue
<template>
+  <div>
+    <h1>{{ $t('pages.home.welcome_to_our_site') }}</h1>
+    <p>{{ $t('pages.home.please_sign_in') }}</p>
+  </div>
+</template>

For more details, check out the documentation.


`,64)]))}const f=i(l,[["render",h]]);export{E as __pageData,f as default}; diff --git a/assets/style.CvLBQ1C_.css b/assets/style.CvLBQ1C_.css new file mode 100644 index 00000000..782b7911 --- /dev/null +++ b/assets/style.CvLBQ1C_.css @@ -0,0 +1 @@ +@import"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css";@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-roman-cyrillic.C5lxZ8CY.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-roman-greek-ext.CqjqNYQ-.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-roman-greek.BBVDIX6e.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-roman-vietnamese.BjW4sHH5.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-roman-latin-ext.4ZJIpNVo.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-roman-latin.Di8DUHzh.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-italic-cyrillic-ext.r48I6akx.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-italic-cyrillic.By2_1cv3.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-italic-greek-ext.1u6EdAuj.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-italic-greek.DJ8dCoTZ.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-italic-vietnamese.BSbpV94h.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-italic-latin-ext.CN1xVJS-.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/nuxt-i18n-micro/assets/inter-italic-latin.C2AdPX0b.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Punctuation SC;font-weight:400;src:local("PingFang SC Regular"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:500;src:local("PingFang SC Medium"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:600;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:700;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-purple-1: #6f42c1;--vp-c-purple-2: #7e4cc9;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-purple-1: #c8abfa;--vp-c-purple-2: #a879e6;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: rgba(60, 60, 67);--vp-c-text-2: rgba(60, 60, 67, .78);--vp-c-text-3: rgba(60, 60, 67, .56)}.dark{--vp-c-text-1: rgba(255, 255, 245, .86);--vp-c-text-2: rgba(235, 235, 245, .6);--vp-c-text-3: rgba(235, 235, 245, .38)}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-note-1: var(--vp-c-brand-1);--vp-c-note-2: var(--vp-c-brand-2);--vp-c-note-3: var(--vp-c-brand-3);--vp-c-note-soft: var(--vp-c-brand-soft);--vp-c-success-1: var(--vp-c-green-1);--vp-c-success-2: var(--vp-c-green-2);--vp-c-success-3: var(--vp-c-green-3);--vp-c-success-soft: var(--vp-c-green-soft);--vp-c-important-1: var(--vp-c-purple-1);--vp-c-important-2: var(--vp-c-purple-2);--vp-c-important-3: var(--vp-c-purple-3);--vp-c-important-soft: var(--vp-c-purple-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft);--vp-c-caution-1: var(--vp-c-red-1);--vp-c-caution-2: var(--vp-c-red-2);--vp-c-caution-3: var(--vp-c-red-3);--vp-c-caution-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;font-optical-sizing:auto}:root:where(:lang(zh)){--vp-font-family-base: "Punctuation SC", "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}@media (min-width: 960px){:root{--vp-z-index-sidebar: 25}}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-success-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-success-1);--vp-code-line-diff-remove-color: var(--vp-c-danger-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-danger-1);--vp-code-line-warning-color: var(--vp-c-warning-soft);--vp-code-line-error-color: var(--vp-c-danger-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-note-border: transparent;--vp-custom-block-note-text: var(--vp-c-text-1);--vp-custom-block-note-bg: var(--vp-c-default-soft);--vp-custom-block-note-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-tip-soft);--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);--vp-custom-block-important-border: transparent;--vp-custom-block-important-text: var(--vp-c-text-1);--vp-custom-block-important-bg: var(--vp-c-important-soft);--vp-custom-block-important-code-bg: var(--vp-c-important-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-caution-border: transparent;--vp-custom-block-caution-text: var(--vp-c-text-1);--vp-custom-block-caution-bg: var(--vp-c-caution-soft);--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-default-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-tip-1);--vp-badge-tip-bg: var(--vp-c-tip-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{overflow-x:auto}mjx-container>svg{display:inline-block;margin:auto}[class^=vpi-],[class*=" vpi-"],.vp-icon{width:1em;height:1em}[class^=vpi-].bg,[class*=" vpi-"].bg,.vp-icon.bg{background-size:100% 100%;background-color:transparent}[class^=vpi-]:not(.bg),[class*=" vpi-"]:not(.bg),.vp-icon:not(.bg){-webkit-mask:var(--icon) no-repeat;mask:var(--icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit}.vpi-align-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M21 6H3M15 12H3M17 18H3'/%3E%3C/svg%3E")}.vpi-arrow-right,.vpi-arrow-down,.vpi-arrow-left,.vpi-arrow-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5l7 7-7 7'/%3E%3C/svg%3E")}.vpi-chevron-right,.vpi-chevron-down,.vpi-chevron-left,.vpi-chevron-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E")}.vpi-chevron-down,.vpi-arrow-down{transform:rotate(90deg)}.vpi-chevron-left,.vpi-arrow-left{transform:rotate(180deg)}.vpi-chevron-up,.vpi-arrow-up{transform:rotate(-90deg)}.vpi-square-pen{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/%3E%3Cpath d='M18.375 2.625a2.121 2.121 0 1 1 3 3L12 15l-4 1 1-4Z'/%3E%3C/svg%3E")}.vpi-plus{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5v14'/%3E%3C/svg%3E")}.vpi-sun{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E")}.vpi-moon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z'/%3E%3C/svg%3E")}.vpi-more-horizontal{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='1'/%3E%3Ccircle cx='19' cy='12' r='1'/%3E%3Ccircle cx='5' cy='12' r='1'/%3E%3C/svg%3E")}.vpi-languages{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m5 8 6 6M4 14l6-6 2-3M2 5h12M7 2h1M22 22l-5-10-5 10M14 18h6'/%3E%3C/svg%3E")}.vpi-heart{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z'/%3E%3C/svg%3E")}.vpi-search{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E")}.vpi-layout-list{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='7' height='7' x='3' y='3' rx='1'/%3E%3Crect width='7' height='7' x='3' y='14' rx='1'/%3E%3Cpath d='M14 4h7M14 9h7M14 15h7M14 20h7'/%3E%3C/svg%3E")}.vpi-delete{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M20 5H9l-7 7 7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2ZM18 9l-6 6M12 9l6 6'/%3E%3C/svg%3E")}.vpi-corner-down-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 10-5 5 5 5'/%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3C/svg%3E")}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover,.custom-block.info a:hover>code{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.note{border-color:var(--vp-custom-block-note-border);color:var(--vp-custom-block-note-text);background-color:var(--vp-custom-block-note-bg)}.custom-block.note a,.custom-block.note code{color:var(--vp-c-brand-1)}.custom-block.note a:hover,.custom-block.note a:hover>code{color:var(--vp-c-brand-2)}.custom-block.note code{background-color:var(--vp-custom-block-note-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-tip-1)}.custom-block.tip a:hover,.custom-block.tip a:hover>code{color:var(--vp-c-tip-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.important{border-color:var(--vp-custom-block-important-border);color:var(--vp-custom-block-important-text);background-color:var(--vp-custom-block-important-bg)}.custom-block.important a,.custom-block.important code{color:var(--vp-c-important-1)}.custom-block.important a:hover,.custom-block.important a:hover>code{color:var(--vp-c-important-2)}.custom-block.important code{background-color:var(--vp-custom-block-important-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover,.custom-block.warning a:hover>code{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover,.custom-block.danger a:hover>code{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.caution{border-color:var(--vp-custom-block-caution-border);color:var(--vp-custom-block-caution-text);background-color:var(--vp-custom-block-caution-bg)}.custom-block.caution a,.custom-block.caution code{color:var(--vp-c-caution-1)}.custom-block.caution a:hover,.custom-block.caution a:hover>code{color:var(--vp-c-caution-2)}.custom-block.caution code{background-color:var(--vp-custom-block-caution-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover,.custom-block.details a:hover>code{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer;-webkit-user-select:none;user-select:none}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code span{color:var(--shiki-dark, inherit)}html:not(.dark) .vp-code span{color:var(--shiki-light, inherit)}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc h4{margin:24px 0 0;letter-spacing:-.01em;line-height:24px;font-size:18px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s;color:var(--vp-c-text-2)}.vp-doc blockquote>p{margin:0;font-size:16px;transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{background-color:var(--vp-c-bg);border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code,.vp-doc h4>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;-webkit-user-select:none;user-select:none;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(.no-icon):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.external-link-icon-enabled :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):after{content:"";color:currentColor}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin:0 0 4px!important;text-align:center;letter-spacing:1px!important;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.VPBadge.small{padding:0 6px;line-height:18px;font-size:10px;transform:translateY(-8px)}.VPDocFooter .VPBadge{display:none}.vp-doc h1>.VPBadge{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge{vertical-align:middle}.vp-doc h4>.VPBadge,.vp-doc h5>.VPBadge,.vp-doc h6>.VPBadge{vertical-align:middle;line-height:18px}.VPBadge.info{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-7c66b226]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-7c66b226],.VPBackdrop.fade-leave-to[data-v-7c66b226]{opacity:0}.VPBackdrop.fade-leave-active[data-v-7c66b226]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-7c66b226]{display:none}}.NotFound[data-v-c2fb1638]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-c2fb1638]{padding:96px 32px 168px}}.code[data-v-c2fb1638]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-c2fb1638]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-c2fb1638]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-c2fb1638]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-c2fb1638]{padding-top:20px}.link[data-v-c2fb1638]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-c2fb1638]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-94e4ef81]{position:relative;z-index:1}.nested[data-v-94e4ef81]{padding-right:16px;padding-left:16px}.outline-link[data-v-94e4ef81]{display:block;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s}.outline-link[data-v-94e4ef81]:hover,.outline-link.active[data-v-94e4ef81]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-94e4ef81]{padding-left:13px}.VPDocAsideOutline[data-v-8ea6637a]{display:none}.VPDocAsideOutline.has-outline[data-v-8ea6637a]{display:block}.content[data-v-8ea6637a]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-8ea6637a]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-8ea6637a]{line-height:32px;font-size:14px;font-weight:600}.VPDocAside[data-v-c6bd40e9]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-c6bd40e9]{flex-grow:1}.VPDocAside[data-v-c6bd40e9] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-c6bd40e9] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-c6bd40e9] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-9c78c02b]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-9c78c02b]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-dd28e2e9]{margin-top:64px}.edit-info[data-v-dd28e2e9]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-dd28e2e9]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-dd28e2e9]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-dd28e2e9]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-dd28e2e9]{margin-right:8px}.prev-next[data-v-dd28e2e9]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-dd28e2e9]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-dd28e2e9]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-dd28e2e9]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-dd28e2e9]{margin-left:auto;text-align:right}.desc[data-v-dd28e2e9]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-dd28e2e9]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDoc[data-v-302c5b4b]{padding:32px 24px 96px;width:100%}@media (min-width: 768px){.VPDoc[data-v-302c5b4b]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-302c5b4b]{padding:48px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-302c5b4b]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-302c5b4b]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-302c5b4b]{display:flex;justify-content:center}.VPDoc .aside[data-v-302c5b4b]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-302c5b4b]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-302c5b4b]{max-width:1104px}}.container[data-v-302c5b4b]{margin:0 auto;width:100%}.aside[data-v-302c5b4b]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-302c5b4b]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-302c5b4b]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-302c5b4b]::-webkit-scrollbar{display:none}.aside-curtain[data-v-302c5b4b]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-302c5b4b]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));padding-bottom:32px}.content[data-v-302c5b4b]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-302c5b4b]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-302c5b4b]{order:1;margin:0;min-width:640px}}.content-container[data-v-302c5b4b]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-302c5b4b]{max-width:688px}.VPButton[data-v-45b57181]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-45b57181]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-45b57181]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-45b57181]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-45b57181]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-45b57181]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-45b57181]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-45b57181]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-45b57181]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-45b57181]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-45b57181]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-45b57181]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-45b57181]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-17bebc96]{display:none}.dark .VPImage.light[data-v-17bebc96]{display:none}.VPHero[data-v-9261d9b9]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-9261d9b9]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-9261d9b9]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-9261d9b9]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-9261d9b9]{flex-direction:row}}.main[data-v-9261d9b9]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-9261d9b9]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-9261d9b9]{text-align:left}}@media (min-width: 960px){.main[data-v-9261d9b9]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-9261d9b9]{max-width:592px}}.name[data-v-9261d9b9],.text[data-v-9261d9b9]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-9261d9b9],.VPHero.has-image .text[data-v-9261d9b9]{margin:0 auto}.name[data-v-9261d9b9]{color:var(--vp-home-hero-name-color)}.clip[data-v-9261d9b9]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-9261d9b9],.text[data-v-9261d9b9]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-9261d9b9],.text[data-v-9261d9b9]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-9261d9b9],.VPHero.has-image .text[data-v-9261d9b9]{margin:0}}.tagline[data-v-9261d9b9]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-9261d9b9]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-9261d9b9]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-9261d9b9]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-9261d9b9]{margin:0}}.actions[data-v-9261d9b9]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-9261d9b9]{justify-content:center}@media (min-width: 640px){.actions[data-v-9261d9b9]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-9261d9b9]{justify-content:flex-start}}.action[data-v-9261d9b9]{flex-shrink:0;padding:6px}.image[data-v-9261d9b9]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-9261d9b9]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-9261d9b9]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-9261d9b9]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-9261d9b9]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-9261d9b9]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-9261d9b9]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-9261d9b9]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-9261d9b9]{width:320px;height:320px}}[data-v-9261d9b9] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-9261d9b9] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-9261d9b9] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-b73852cc]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-b73852cc]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-b73852cc]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-b73852cc]>.VPImage{margin-bottom:20px}.icon[data-v-b73852cc]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-b73852cc]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-b73852cc]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-b73852cc]{padding-top:8px}.link-text-value[data-v-b73852cc]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-b73852cc]{margin-left:6px}.VPFeatures[data-v-bdcd42a1]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-bdcd42a1]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-bdcd42a1]{padding:0 64px}}.container[data-v-bdcd42a1]{margin:0 auto;max-width:1152px}.items[data-v-bdcd42a1]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-bdcd42a1]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-bdcd42a1],.item.grid-4[data-v-bdcd42a1],.item.grid-6[data-v-bdcd42a1]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-bdcd42a1],.item.grid-4[data-v-bdcd42a1]{width:50%}.item.grid-3[data-v-bdcd42a1],.item.grid-6[data-v-bdcd42a1]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-bdcd42a1]{width:25%}}.container[data-v-fef19e55]{margin:auto;width:100%;max-width:1280px;padding:0 24px}@media (min-width: 640px){.container[data-v-fef19e55]{padding:0 48px}}@media (min-width: 960px){.container[data-v-fef19e55]{width:100%;padding:0 64px}}.vp-doc[data-v-fef19e55] .VPHomeSponsors,.vp-doc[data-v-fef19e55] .VPTeamPage{margin-left:var(--vp-offset, calc(50% - 50vw) );margin-right:var(--vp-offset, calc(50% - 50vw) )}.vp-doc[data-v-fef19e55] .VPHomeSponsors h2{border-top:none;letter-spacing:normal}.vp-doc[data-v-fef19e55] .VPHomeSponsors a,.vp-doc[data-v-fef19e55] .VPTeamPage a{text-decoration:none}.VPHome[data-v-9e24ba69]{margin-bottom:96px}@media (min-width: 768px){.VPHome[data-v-9e24ba69]{margin-bottom:128px}}.VPContent[data-v-2f2922de]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-2f2922de]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-2f2922de]{margin:0}@media (min-width: 960px){.VPContent[data-v-2f2922de]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-2f2922de]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-2f2922de]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-63b8cc5c]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-63b8cc5c]{display:none}.VPFooter[data-v-63b8cc5c] a{text-decoration-line:underline;text-underline-offset:2px;transition:color .25s}.VPFooter[data-v-63b8cc5c] a:hover{color:var(--vp-c-text-1)}@media (min-width: 768px){.VPFooter[data-v-63b8cc5c]{padding:32px}}.container[data-v-63b8cc5c]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-63b8cc5c],.copyright[data-v-63b8cc5c]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-49916a3f]{padding:12px 20px 11px}@media (min-width: 960px){.VPLocalNavOutlineDropdown[data-v-49916a3f]{padding:12px 36px 11px}}.VPLocalNavOutlineDropdown button[data-v-49916a3f]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-49916a3f]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-49916a3f]{color:var(--vp-c-text-1)}.icon[data-v-49916a3f]{display:inline-block;vertical-align:middle;margin-left:2px;font-size:14px;transform:rotate(0);transition:transform .25s}@media (min-width: 960px){.VPLocalNavOutlineDropdown button[data-v-49916a3f]{font-size:14px}.icon[data-v-49916a3f]{font-size:16px}}.open>.icon[data-v-49916a3f]{transform:rotate(90deg)}.items[data-v-49916a3f]{position:absolute;top:40px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}@media (min-width: 960px){.items[data-v-49916a3f]{right:auto;left:calc(var(--vp-sidebar-width) + 32px);width:320px}}.header[data-v-49916a3f]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-49916a3f]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-49916a3f]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-49916a3f]{transition:all .2s ease-out}.flyout-leave-active[data-v-49916a3f]{transition:all .15s ease-in}.flyout-enter-from[data-v-49916a3f],.flyout-leave-to[data-v-49916a3f]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-df5e51e8]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-df5e51e8]{position:fixed}@media (min-width: 960px){.VPLocalNav[data-v-df5e51e8]{top:var(--vp-nav-height)}.VPLocalNav.has-sidebar[data-v-df5e51e8]{padding-left:var(--vp-sidebar-width)}.VPLocalNav.empty[data-v-df5e51e8]{display:none}}@media (min-width: 1280px){.VPLocalNav[data-v-df5e51e8]{display:none}}@media (min-width: 1440px){.VPLocalNav.has-sidebar[data-v-df5e51e8]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.container[data-v-df5e51e8]{display:flex;justify-content:space-between;align-items:center}.menu[data-v-df5e51e8]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-df5e51e8]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-df5e51e8]{padding:0 32px}}@media (min-width: 960px){.menu[data-v-df5e51e8]{display:none}}.menu-icon[data-v-df5e51e8]{margin-right:8px;font-size:14px}.VPOutlineDropdown[data-v-df5e51e8]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-df5e51e8]{padding:12px 32px 11px}}.VPSwitch[data-v-f77dad60]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-f77dad60]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-f77dad60]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-f77dad60]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-f77dad60] [class^=vpi-]{position:absolute;top:3px;left:3px;width:12px;height:12px;color:var(--vp-c-text-2)}.dark .icon[data-v-f77dad60] [class^=vpi-]{color:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-fa59b7d6]{opacity:1}.moon[data-v-fa59b7d6],.dark .sun[data-v-fa59b7d6]{opacity:0}.dark .moon[data-v-fa59b7d6]{opacity:1}.dark .VPSwitchAppearance[data-v-fa59b7d6] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-de868ce3]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-de868ce3]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-7a03c4cb]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-7a03c4cb]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-7a03c4cb]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-7a03c4cb]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-08910976]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-08910976]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-08910976]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-08910976]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-f3096789]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-f3096789] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-f3096789] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-f3096789] .group:last-child{padding-bottom:0}.VPMenu[data-v-f3096789] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-f3096789] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-f3096789] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-f3096789] .action{padding-left:24px}.VPFlyout[data-v-d51b3e8d]{position:relative}.VPFlyout[data-v-d51b3e8d]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-d51b3e8d]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-d51b3e8d]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-d51b3e8d]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-d51b3e8d]{color:var(--vp-c-brand-2)}.button[aria-expanded=false]+.menu[data-v-d51b3e8d]{opacity:0;visibility:hidden;transform:translateY(0)}.VPFlyout:hover .menu[data-v-d51b3e8d],.button[aria-expanded=true]+.menu[data-v-d51b3e8d]{opacity:1;visibility:visible;transform:translateY(0)}.button[data-v-d51b3e8d]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-d51b3e8d]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-d51b3e8d]{margin-right:0;font-size:16px}.text-icon[data-v-d51b3e8d]{margin-left:4px;font-size:14px}.icon[data-v-d51b3e8d]{font-size:20px;transition:fill .25s}.menu[data-v-d51b3e8d]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-0badd679]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-0badd679]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-0badd679]>svg,.VPSocialLink[data-v-0badd679]>[class^=vpi-social-]{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-127ec22b]{display:flex;justify-content:center}.VPNavBarExtra[data-v-559816d6]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-559816d6]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-559816d6]{display:none}}.trans-title[data-v-559816d6]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-559816d6],.item.social-links[data-v-559816d6]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-559816d6]{min-width:176px}.appearance-action[data-v-559816d6]{margin-right:-2px}.social-links-list[data-v-559816d6]{margin:-4px -8px}.VPNavBarHamburger[data-v-da416740]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-da416740]{display:none}}.container[data-v-da416740]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-da416740]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-da416740]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-da416740]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-da416740]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-da416740]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-da416740]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-da416740],.VPNavBarHamburger.active:hover .middle[data-v-da416740],.VPNavBarHamburger.active:hover .bottom[data-v-da416740]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-da416740],.middle[data-v-da416740],.bottom[data-v-da416740]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-da416740]{top:0;left:0;transform:translate(0)}.middle[data-v-da416740]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-da416740]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-ae7f79ce]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-ae7f79ce],.VPNavBarMenuLink[data-v-ae7f79ce]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-3ee2e2ec]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-3ee2e2ec]{display:flex}}/*! @docsearch/css 3.8.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 1px 0 rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 1px 1px 0 #0304094d;--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 2px;position:relative;top:-1px;width:20px}.DocSearch-Button-Key--pressed{box-shadow:var(--docsearch-key-pressed-shadow);transform:translate3d(0,1px,0)}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:2px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;width:20px}.DocSearch-VisuallyHiddenForAccessibility{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}[class*=DocSearch]{--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-background: transparent;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button-Key--pressed{transform:none;box-shadow:none}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand-1);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:0!important}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"Ctrl";font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"⌘"}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.DocSearch-Search-Icon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke-width='1.6' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' d='m14.386 14.386 4.088 4.088-4.088-4.088A7.533 7.533 0 1 1 3.733 3.733a7.533 7.533 0 0 1 10.653 10.653z'/%3E%3C/svg%3E")}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand-1);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-default-soft)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-2fb152af]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-2fb152af]{display:flex;align-items:center}}.title[data-v-2c4cbfa5]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-2c4cbfa5]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-2c4cbfa5]{border-bottom-color:var(--vp-c-divider)}}[data-v-2c4cbfa5] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-20271d71]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-20271d71]{display:flex;align-items:center}}.title[data-v-20271d71]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-2884efbc]{position:relative;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap;transition:background-color .25s}.VPNavBar.screen-open[data-v-2884efbc]{transition:none;background-color:var(--vp-nav-bg-color);border-bottom:1px solid var(--vp-c-divider)}.VPNavBar[data-v-2884efbc]:not(.home){background-color:var(--vp-nav-bg-color)}@media (min-width: 960px){.VPNavBar[data-v-2884efbc]:not(.home){background-color:transparent}.VPNavBar[data-v-2884efbc]:not(.has-sidebar):not(.home.top){background-color:var(--vp-nav-bg-color)}}.wrapper[data-v-2884efbc]{padding:0 8px 0 24px}@media (min-width: 768px){.wrapper[data-v-2884efbc]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar .wrapper[data-v-2884efbc]{padding:0}}.container[data-v-2884efbc]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-2884efbc],.container>.content[data-v-2884efbc]{pointer-events:none}.container[data-v-2884efbc] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-2884efbc]{max-width:100%}}.title[data-v-2884efbc]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-2884efbc]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-2884efbc]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-2884efbc]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-2884efbc]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-2884efbc]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-2884efbc]{display:flex;justify-content:flex-end;align-items:center;height:var(--vp-nav-height);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.home.top) .content-body[data-v-2884efbc]{position:relative;background-color:var(--vp-nav-bg-color)}.VPNavBar:not(.has-sidebar):not(.home.top) .content-body[data-v-2884efbc]{background-color:transparent}}@media (max-width: 767px){.content-body[data-v-2884efbc]{column-gap:.5rem}}.menu+.translations[data-v-2884efbc]:before,.menu+.appearance[data-v-2884efbc]:before,.menu+.social-links[data-v-2884efbc]:before,.translations+.appearance[data-v-2884efbc]:before,.appearance+.social-links[data-v-2884efbc]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-2884efbc]:before,.translations+.appearance[data-v-2884efbc]:before{margin-right:16px}.appearance+.social-links[data-v-2884efbc]:before{margin-left:16px}.social-links[data-v-2884efbc]{margin-right:-8px}.divider[data-v-2884efbc]{width:100%;height:1px}@media (min-width: 960px){.VPNavBar.has-sidebar .divider[data-v-2884efbc]{padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .divider[data-v-2884efbc]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.divider-line[data-v-2884efbc]{width:100%;height:1px;transition:background-color .5s}.VPNavBar:not(.home) .divider-line[data-v-2884efbc]{background-color:var(--vp-c-gutter)}@media (min-width: 960px){.VPNavBar:not(.home.top) .divider-line[data-v-2884efbc]{background-color:var(--vp-c-gutter)}.VPNavBar:not(.has-sidebar):not(.home.top) .divider[data-v-2884efbc]{background-color:var(--vp-c-gutter)}}.VPNavScreenAppearance[data-v-8c86ce32]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-8c86ce32]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-90a9e7b8]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-90a9e7b8]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-0c33cb66]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-0c33cb66]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-1ac3498f]{display:block}.title[data-v-1ac3498f]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-3c5063dd]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-3c5063dd]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-3c5063dd]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-3c5063dd]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-3c5063dd]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-3c5063dd]{transform:rotate(45deg)}.button[data-v-3c5063dd]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-3c5063dd]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-3c5063dd]{transition:transform .25s}.group[data-v-3c5063dd]:first-child{padding-top:0}.group+.group[data-v-3c5063dd],.group+.item[data-v-3c5063dd]{padding-top:4px}.VPNavScreenTranslations[data-v-62968728]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-62968728]{height:auto}.title[data-v-62968728]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-62968728]{font-size:16px}.icon.lang[data-v-62968728]{margin-right:8px}.icon.chevron[data-v-62968728]{margin-left:4px}.list[data-v-62968728]{padding:4px 0 0 24px}.link[data-v-62968728]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-abf3412b]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px));right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .25s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-abf3412b],.VPNavScreen.fade-leave-active[data-v-abf3412b]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-abf3412b],.VPNavScreen.fade-leave-active .container[data-v-abf3412b]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-abf3412b],.VPNavScreen.fade-leave-to[data-v-abf3412b]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-abf3412b],.VPNavScreen.fade-leave-to .container[data-v-abf3412b]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-abf3412b]{display:none}}.container[data-v-abf3412b]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-abf3412b],.menu+.appearance[data-v-abf3412b],.translations+.appearance[data-v-abf3412b]{margin-top:24px}.menu+.social-links[data-v-abf3412b]{margin-top:16px}.appearance+.social-links[data-v-abf3412b]{margin-top:16px}.VPNav[data-v-1c090468]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-1c090468]{position:fixed}}.VPSidebarItem.level-0[data-v-4341e9b0]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-4341e9b0]{padding-bottom:10px}.item[data-v-4341e9b0]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-4341e9b0]{cursor:pointer}.indicator[data-v-4341e9b0]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-4341e9b0],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-4341e9b0],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-4341e9b0],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-4341e9b0]{background-color:var(--vp-c-brand-1)}.link[data-v-4341e9b0]{display:flex;align-items:center;flex-grow:1}.text[data-v-4341e9b0]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-4341e9b0]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-4341e9b0],.VPSidebarItem.level-2 .text[data-v-4341e9b0],.VPSidebarItem.level-3 .text[data-v-4341e9b0],.VPSidebarItem.level-4 .text[data-v-4341e9b0],.VPSidebarItem.level-5 .text[data-v-4341e9b0]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-4341e9b0],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-4341e9b0],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-4341e9b0],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-4341e9b0],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-4341e9b0],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-4341e9b0]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-4341e9b0],.VPSidebarItem.level-1.has-active>.item>.text[data-v-4341e9b0],.VPSidebarItem.level-2.has-active>.item>.text[data-v-4341e9b0],.VPSidebarItem.level-3.has-active>.item>.text[data-v-4341e9b0],.VPSidebarItem.level-4.has-active>.item>.text[data-v-4341e9b0],.VPSidebarItem.level-5.has-active>.item>.text[data-v-4341e9b0],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-4341e9b0],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-4341e9b0],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-4341e9b0],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-4341e9b0],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-4341e9b0],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-4341e9b0]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-4341e9b0],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-4341e9b0],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-4341e9b0],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-4341e9b0],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-4341e9b0],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-4341e9b0]{color:var(--vp-c-brand-1)}.caret[data-v-4341e9b0]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-4341e9b0]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-4341e9b0]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-4341e9b0]{font-size:18px;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-4341e9b0]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-4341e9b0],.VPSidebarItem.level-2 .items[data-v-4341e9b0],.VPSidebarItem.level-3 .items[data-v-4341e9b0],.VPSidebarItem.level-4 .items[data-v-4341e9b0],.VPSidebarItem.level-5 .items[data-v-4341e9b0]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-4341e9b0]{display:none}.no-transition[data-v-c89d9511] .caret-icon{transition:none}.group+.group[data-v-c89d9511]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-c89d9511]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSidebar[data-v-d4c32bb1]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-d4c32bb1]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-d4c32bb1]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-d4c32bb1]{padding-top:var(--vp-nav-height);width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-d4c32bb1]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-d4c32bb1]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-d4c32bb1]{outline:0}.VPSkipLink[data-v-6d95233d]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-6d95233d]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-6d95233d]{top:14px;left:16px}}.Layout[data-v-20383531]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-cc55a14d]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPHomeSponsors[data-v-cc55a14d]{margin:96px 0}@media (min-width: 768px){.VPHomeSponsors[data-v-cc55a14d]{margin:128px 0}}.VPHomeSponsors[data-v-cc55a14d]{padding:0 24px}@media (min-width: 768px){.VPHomeSponsors[data-v-cc55a14d]{padding:0 48px}}@media (min-width: 960px){.VPHomeSponsors[data-v-cc55a14d]{padding:0 64px}}.container[data-v-cc55a14d]{margin:0 auto;max-width:1152px}.love[data-v-cc55a14d]{margin:0 auto;width:fit-content;font-size:28px;color:var(--vp-c-text-3)}.icon[data-v-cc55a14d]{display:inline-block}.message[data-v-cc55a14d]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-cc55a14d]{padding-top:32px}.action[data-v-cc55a14d]{padding-top:40px;text-align:center}.VPTeamPage[data-v-e24d2733]{margin:96px 0}@media (min-width: 768px){.VPTeamPage[data-v-e24d2733]{margin:128px 0}}.VPHome .VPTeamPageTitle[data-v-e24d2733-s]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPTeamPageSection+.VPTeamPageSection[data-v-e24d2733-s],.VPTeamMembers+.VPTeamPageSection[data-v-e24d2733-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-e24d2733-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-e24d2733-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-e24d2733-s],.VPTeamMembers+.VPTeamPageSection[data-v-e24d2733-s]{margin-top:96px}}.VPTeamMembers[data-v-e24d2733-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-e24d2733-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-e24d2733-s]{padding:0 64px}}.VPTeamPageTitle[data-v-fec25b5f]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-fec25b5f]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-fec25b5f]{padding:80px 64px 48px}}.title[data-v-fec25b5f]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-fec25b5f]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-fec25b5f]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-fec25b5f]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-b4d87d5a]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-b4d87d5a]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-b4d87d5a]{padding:0 64px}}.title[data-v-b4d87d5a]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-b4d87d5a]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-b4d87d5a]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-b4d87d5a]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-b4d87d5a]{padding-top:40px}.VPTeamMembersItem[data-v-fdb8f498]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-fdb8f498]{padding:32px}.VPTeamMembersItem.small .data[data-v-fdb8f498]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-fdb8f498]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-fdb8f498]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-fdb8f498]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-fdb8f498]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-fdb8f498]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-fdb8f498]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-fdb8f498]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-fdb8f498]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-fdb8f498]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-fdb8f498]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-fdb8f498]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-fdb8f498]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-fdb8f498]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-fdb8f498]{text-align:center}.avatar[data-v-fdb8f498]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-fdb8f498]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-fdb8f498]{margin:0;font-weight:600}.affiliation[data-v-fdb8f498]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-fdb8f498]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-fdb8f498]:hover{color:var(--vp-c-brand-1)}.desc[data-v-fdb8f498]{margin:0 auto}.desc[data-v-fdb8f498] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-fdb8f498]{display:flex;justify-content:center;height:56px}.sp-link[data-v-fdb8f498]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-fdb8f498]:hover,.sp .sp-link.link[data-v-fdb8f498]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-fdb8f498]{margin-right:8px;font-size:16px}.VPTeamMembers.small .container[data-v-43a34be6]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-43a34be6]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-43a34be6]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-43a34be6]{max-width:876px}.VPTeamMembers.medium .container[data-v-43a34be6]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-43a34be6]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-43a34be6]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-43a34be6]{max-width:760px}.container[data-v-43a34be6]{display:grid;gap:24px;margin:0 auto;max-width:1152px}.VPLocalSearchBox[data-v-c4217006]{position:fixed;z-index:100;top:0;right:0;bottom:0;left:0;display:flex}.backdrop[data-v-c4217006]{position:absolute;top:0;right:0;bottom:0;left:0;background:var(--vp-backdrop-bg-color);transition:opacity .5s}.shell[data-v-c4217006]{position:relative;padding:12px;margin:64px auto;display:flex;flex-direction:column;gap:16px;background:var(--vp-local-search-bg);width:min(100vw - 60px,900px);height:min-content;max-height:min(100vh - 128px,900px);border-radius:6px}@media (max-width: 767px){.shell[data-v-c4217006]{margin:0;width:100vw;height:100vh;max-height:none;border-radius:0}}.search-bar[data-v-c4217006]{border:1px solid var(--vp-c-divider);border-radius:4px;display:flex;align-items:center;padding:0 12px;cursor:text}@media (max-width: 767px){.search-bar[data-v-c4217006]{padding:0 8px}}.search-bar[data-v-c4217006]:focus-within{border-color:var(--vp-c-brand-1)}.local-search-icon[data-v-c4217006]{display:block;font-size:18px}.navigate-icon[data-v-c4217006]{display:block;font-size:14px}.search-icon[data-v-c4217006]{margin:8px}@media (max-width: 767px){.search-icon[data-v-c4217006]{display:none}}.search-input[data-v-c4217006]{padding:6px 12px;font-size:inherit;width:100%}@media (max-width: 767px){.search-input[data-v-c4217006]{padding:6px 4px}}.search-actions[data-v-c4217006]{display:flex;gap:4px}@media (any-pointer: coarse){.search-actions[data-v-c4217006]{gap:8px}}@media (min-width: 769px){.search-actions.before[data-v-c4217006]{display:none}}.search-actions button[data-v-c4217006]{padding:8px}.search-actions button[data-v-c4217006]:not([disabled]):hover,.toggle-layout-button.detailed-list[data-v-c4217006]{color:var(--vp-c-brand-1)}.search-actions button.clear-button[data-v-c4217006]:disabled{opacity:.37}.search-keyboard-shortcuts[data-v-c4217006]{font-size:.8rem;opacity:75%;display:flex;flex-wrap:wrap;gap:16px;line-height:14px}.search-keyboard-shortcuts span[data-v-c4217006]{display:flex;align-items:center;gap:4px}@media (max-width: 767px){.search-keyboard-shortcuts[data-v-c4217006]{display:none}}.search-keyboard-shortcuts kbd[data-v-c4217006]{background:#8080801a;border-radius:4px;padding:3px 6px;min-width:24px;display:inline-block;text-align:center;vertical-align:middle;border:1px solid rgba(128,128,128,.15);box-shadow:0 2px 2px #0000001a}.results[data-v-c4217006]{display:flex;flex-direction:column;gap:6px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.result[data-v-c4217006]{display:flex;align-items:center;gap:8px;border-radius:4px;transition:none;line-height:1rem;border:solid 2px var(--vp-local-search-result-border);outline:none}.result>div[data-v-c4217006]{margin:12px;width:100%;overflow:hidden}@media (max-width: 767px){.result>div[data-v-c4217006]{margin:8px}}.titles[data-v-c4217006]{display:flex;flex-wrap:wrap;gap:4px;position:relative;z-index:1001;padding:2px 0}.title[data-v-c4217006]{display:flex;align-items:center;gap:4px}.title.main[data-v-c4217006]{font-weight:500}.title-icon[data-v-c4217006]{opacity:.5;font-weight:500;color:var(--vp-c-brand-1)}.title svg[data-v-c4217006]{opacity:.5}.result.selected[data-v-c4217006]{--vp-local-search-result-bg: var(--vp-local-search-result-selected-bg);border-color:var(--vp-local-search-result-selected-border)}.excerpt-wrapper[data-v-c4217006]{position:relative}.excerpt[data-v-c4217006]{opacity:50%;pointer-events:none;max-height:140px;overflow:hidden;position:relative;margin-top:4px}.result.selected .excerpt[data-v-c4217006]{opacity:1}.excerpt[data-v-c4217006] *{font-size:.8rem!important;line-height:130%!important}.titles[data-v-c4217006] mark,.excerpt[data-v-c4217006] mark{background-color:var(--vp-local-search-highlight-bg);color:var(--vp-local-search-highlight-text);border-radius:2px;padding:0 2px}.excerpt[data-v-c4217006] .vp-code-group .tabs{display:none}.excerpt[data-v-c4217006] .vp-code-group div[class*=language-]{border-radius:8px!important}.excerpt-gradient-bottom[data-v-c4217006]{position:absolute;bottom:-1px;left:0;width:100%;height:8px;background:linear-gradient(transparent,var(--vp-local-search-result-bg));z-index:1000}.excerpt-gradient-top[data-v-c4217006]{position:absolute;top:-1px;left:0;width:100%;height:8px;background:linear-gradient(var(--vp-local-search-result-bg),transparent);z-index:1000}.result.selected .titles[data-v-c4217006],.result.selected .title-icon[data-v-c4217006]{color:var(--vp-c-brand-1)!important}.no-results[data-v-c4217006]{font-size:.9rem;text-align:center;padding:12px}svg[data-v-c4217006]{flex:none} diff --git a/components/i18n-group.html b/components/i18n-group.html new file mode 100644 index 00000000..814dc4a1 --- /dev/null +++ b/components/i18n-group.html @@ -0,0 +1,108 @@ + + + + + + 🌍 <i18n-group> Component | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🌍 <i18n-group> Component

The <i18n-group> component in Nuxt I18n Micro provides a convenient way to group translations under a common prefix, reducing repetition and improving code organization.

⚙️ Props

prefix

  • Type: String
  • Required: Yes
  • Description: The translation key prefix that will be automatically prepended to all translations within the group.
  • Example: "product.details", "user.profile"

groupClass

  • Type: String
  • Required: No
  • Default: ""
  • Description: Additional CSS class(es) to be applied to the wrapper div element.

🎯 Slots

Default Slot

The default slot provides access to two important properties:

  • prefix: The current prefix string
  • t: A translation function that automatically prepends the prefix

The slot exposes these properties through scoped slots:

vue
<template #default="{ prefix, t }">
+  <!-- Your content here -->
+</template>

🛠️ Example Usage

Basic Usage

vue
<template>
+  <i18n-group prefix="product.details">
+    <template #default="{ t }">
+      <h1>{{ t('title') }}</h1>
+      <p>{{ t('description') }}</p>
+      <div class="price">{{ t('price', { value: 99.99 }) }}</div>
+    </template>
+  </i18n-group>
+</template>

Translation file:

json
{
+  "product": {
+    "details": {
+      "title": "Premium Product",
+      "description": "This is a premium product",
+      "price": "Price: ${value}"
+    }
+  }
+}

With Custom Class

vue
<template>
+  <i18n-group 
+    prefix="user.profile" 
+    group-class="profile-section"
+  >
+    <template #default="{ t }">
+      <div class="user-info">
+        <h2>{{ t('title') }}</h2>
+        <p>{{ t('bio') }}</p>
+        <div class="stats">
+          <span>{{ t('stats.followers') }}</span>
+          <span>{{ t('stats.following') }}</span>
+        </div>
+      </div>
+    </template>
+  </i18n-group>
+</template>

Translation file:

json
{
+  "user": {
+    "profile": {
+      "title": "User Profile",
+      "bio": "User biography goes here",
+      "stats": {
+        "followers": "Followers: {count}",
+        "following": "Following: {count}"
+      }
+    }
+  }
+}

With Dynamic Content

vue
<template>
+  <i18n-group prefix="blog.post">
+    <template #default="{ t }">
+      <article>
+        <h1>{{ t('title') }}</h1>
+        <div class="meta">
+          {{ t('meta.author', { name: author }) }} |
+          {{ t('meta.date', { date: publishDate }) }}
+        </div>
+        <div v-for="(section, index) in sections" :key="index">
+          <h2>{{ t(`sections.${index}.title`) }}</h2>
+          <p>{{ t(`sections.${index}.content`) }}</p>
+        </div>
+      </article>
+    </template>
+  </i18n-group>
+</template>
+
+<script setup>
+const author = 'John Doe'
+const publishDate = '2024-01-01'
+const sections = ['intro', 'main', 'conclusion']
+</script>

🎨 Styling

The component wraps its content in a div with the class i18n-group and any additional classes specified in the groupClass prop:

css
.i18n-group {
+  /* Your base styles */
+}
+
+.profile-section {
+  /* Additional styles for profile sections */
+}

🚀 Best Practices

  1. Consistent Prefixes: Use consistent and logical prefixes that reflect your application's structure
vue
<i18n-group prefix="features.pricing">
+<i18n-group prefix="features.security">
  1. Modular Organization: Group related translations together under meaningful prefixes
vue
<i18n-group prefix="checkout.payment">
+<i18n-group prefix="checkout.shipping">
  1. Reusable Components: Create reusable components with their own translation groups
vue
<!-- UserProfile.vue -->
+<i18n-group prefix="user.profile">
+
+<!-- UserSettings.vue -->
+<i18n-group prefix="user.settings">
  1. Nested Groups: Avoid deeply nesting groups to maintain clarity
vue
<!-- Good -->
+<i18n-group prefix="shop.product">
+
+<!-- Avoid -->
+<i18n-group prefix="shop.category.product.details.specs">

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/components/i18n-link.html b/components/i18n-link.html new file mode 100644 index 00000000..c67afffb --- /dev/null +++ b/components/i18n-link.html @@ -0,0 +1,30 @@ + + + + + + 🌍 <i18n-link> Component | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/components/i18n-switcher.html b/components/i18n-switcher.html new file mode 100644 index 00000000..3c480f55 --- /dev/null +++ b/components/i18n-switcher.html @@ -0,0 +1,83 @@ + + + + + + 🌍 <i18n-switcher> Component | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🌍 <i18n-switcher> Component

The <i18n-switcher> component in Nuxt I18n Micro provides a user-friendly dropdown interface for switching between different locales in your application. This component is highly customizable, allowing seamless integration with your application's design and layout.

⚙️ Props

customLabels

  • Type: Record<string, string>
  • Default: {}
  • Description: Allows you to define custom labels for each locale, which will be displayed instead of the locale codes.
  • Example:
    vue
    <i18n-switcher :customLabels="{ en: 'English', fr: 'Français' }"></i18n-switcher>

customWrapperStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Allows you to override the default styles applied to the wrapper <div> that contains the locale switcher.
  • Example:
    vue
    <i18n-switcher :customWrapperStyle="{ backgroundColor: '#f8f9fa', padding: '10px' }"></i18n-switcher>

customButtonStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Allows you to customize the styles applied to the button element that toggles the dropdown menu.
  • Example:
    vue
    <i18n-switcher :customButtonStyle="{ backgroundColor: '#007bff', color: '#fff', borderRadius: '4px' }"></i18n-switcher>

customDropdownStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Sets the custom styles for the <ul> element that contains the list of locales.
  • Example:
    vue
    <i18n-switcher :customDropdownStyle="{ border: '1px solid #007bff', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)' }"></i18n-switcher>

customItemStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Applies custom styles to each <li> element representing a locale option.
  • Example:
    vue
    <i18n-switcher :customItemStyle="{ margin: '5px 0', padding: '5px' }"></i18n-switcher>

customLinkStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Allows you to customize the styles applied to the <NuxtLink> elements used to switch between locales.
  • Example:
    vue
    <i18n-switcher :customLinkStyle="{ padding: '8px 16px', color: '#333', textDecoration: 'none' }"></i18n-switcher>

customActiveLinkStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Sets the custom styles for the currently active locale, usually to highlight or indicate the selected option.
  • Example:
    vue
    <i18n-switcher :customActiveLinkStyle="{ color: 'green', fontWeight: 'bold', backgroundColor: '#f0f0f0' }"></i18n-switcher>

customDisabledLinkStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Applies custom styles to disable the link for the current locale, preventing users from selecting it.
  • Example:
    vue
    <i18n-switcher :customDisabledLinkStyle="{ color: 'gray', cursor: 'not-allowed' }"></i18n-switcher>

customIconStyle

  • Type: CSSProperties
  • Default: {}
  • Description: Defines custom styles for the icon that indicates the dropdown state, such as rotating the icon when the dropdown is opened or closed.
  • Example:
    vue
    <i18n-switcher :customIconStyle="{ fontSize: '20px', color: '#007bff' }"></i18n-switcher>

🛠️ Example Usages

Basic Usage

vue
<template>
+  <i18n-switcher />
+</template>

This renders a locale switcher with default styling and behavior.

Custom Labels and Inline Styles

vue
<template>
+  <i18n-switcher
+    :customLabels="{ en: 'English', fr: 'Français' }"
+    :customWrapperStyle="{ backgroundColor: '#f8f9fa', padding: '10px' }"
+    :customButtonStyle="{ backgroundColor: '#007bff', color: '#fff', borderRadius: '4px' }"
+    :customDropdownStyle="{ border: '1px solid #007bff', boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)' }"
+    :customItemStyle="{ margin: '5px 0', padding: '5px' }"
+    :customLinkStyle="{ padding: '8px 16px', color: '#333', textDecoration: 'none' }"
+    :customActiveLinkStyle="{ color: 'green', fontWeight: 'bold', backgroundColor: '#f0f0f0' }"
+    :customDisabledLinkStyle="{ color: 'gray', cursor: 'not-allowed' }"
+    :customIconStyle="{ fontSize: '20px', color: '#007bff' }"
+  />
+</template>

This example demonstrates a fully customized locale switcher with custom labels and inline styles.

🔌 Slots

The <i18n-switcher> component provides several slots that allow you to insert custom content at various points within the component. These slots enhance the flexibility and customization of the switcher, enabling you to tailor it to your application's specific needs.

before-button

  • Description: Inserts content immediately before the language switcher button.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-button>
    +    <span>🌐</span>
    +  </template>
    +</i18n-switcher>

before-selected-locale

  • Description: Inserts content before the currently selected locale label within the button.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-selected-locale>
    +    <i class="icon-flag"></i>
    +  </template>
    +</i18n-switcher>

after-selected-locale

  • Description: Inserts content after the currently selected locale label within the button.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-selected-locale>
    +    <i class="icon-caret"></i>
    +  </template>
    +</i18n-switcher>

before-dropdown

  • Description: Inserts content immediately before the dropdown menu.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-dropdown>
    +    <li class="dropdown-header">Select Language</li>
    +  </template>
    +</i18n-switcher>

after-dropdown

  • Description: Inserts content immediately after the dropdown menu.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-dropdown>
    +    <li class="dropdown-footer">Powered by Nuxt</li>
    +  </template>
    +</i18n-switcher>

before-dropdown-items

  • Description: Inserts content before the list of locale items within the dropdown.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-dropdown-items>
    +    <li class="divider"></li>
    +  </template>
    +</i18n-switcher>

after-dropdown-items

  • Description: Inserts content after the list of locale items within the dropdown.
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-dropdown-items>
    +    <li class="divider"></li>
    +  </template>
    +</i18n-switcher>

before-item

  • Description: Inserts content before each locale item. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-item="{ locale }">
    +    <i :class="`flag-${locale.code}`"></i>
    +  </template>
    +</i18n-switcher>

after-item

  • Description: Inserts content after each locale item. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-item="{ locale }">
    +    <span>{{ locale.code }}</span>
    +  </template>
    +</i18n-switcher>
  • Description: Inserts content before the locale label inside each link. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #before-link-content="{ locale }">
    +    <i :class="`icon-${locale.code}`"></i>
    +  </template>
    +</i18n-switcher>
  • Description: Inserts content after the locale label inside each link. Receives the locale as a slot prop.
  • Props: locale (Locale object)
  • Usage Example:
    vue
    <i18n-switcher>
    +  <template #after-link-content="{ locale }">
    +    <span>({{ locale.code }})</span>
    +  </template>
    +</i18n-switcher>

Summary of Slots

Slot NameDescriptionProps
before-buttonContent before the language switcher buttonNone
before-selected-localeContent before the selected locale label within the buttonNone
after-selected-localeContent after the selected locale label within the buttonNone
before-dropdownContent before the dropdown menuNone
after-dropdownContent after the dropdown menuNone
before-dropdown-itemsContent before the list of locale items within the dropdownNone
after-dropdown-itemsContent after the list of locale items within the dropdownNone
before-itemContent before each locale itemlocale
after-itemContent after each locale itemlocale
before-link-contentContent before the locale label inside each linklocale
after-link-contentContent after the locale label inside each linklocale

🎨 Styles Overview

The <i18n-switcher> component comes with basic styles defined using inline styles that can easily be overridden by passing custom styles via props. Here’s a brief overview of the default styling:

  • Wrapper: Controls the positioning of the dropdown.
  • Button: Styles the dropdown toggle button.
  • Dropdown: Styles the dropdown list.
  • Items: Styles each item in the list.
  • Links: Styles the links inside each item.
  • Icon: Styles the dropdown indicator icon.

You can customize these styles by passing custom styles through the respective props, ensuring that the locale switcher integrates seamlessly into your application's UI.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/components/i18n-t.html b/components/i18n-t.html new file mode 100644 index 00000000..d3271936 --- /dev/null +++ b/components/i18n-t.html @@ -0,0 +1,69 @@ + + + + + + 🌍 <i18n-t> Component | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🌍 <i18n-t> Component

The <i18n-t> component in Nuxt I18n Micro is a flexible translation component that supports dynamic content insertion via slots. It allows you to interpolate translations with custom Vue components or HTML content, enabling advanced localization scenarios.

⚙️ Props

keypath

  • Type: string
  • Required: Yes
  • Description: Defines the key path to the translation string in your localization files.
  • Example:
vue
<i18n-t keypath="feedback.text" />

plural

  • Type: number | string
  • Optional: Yes
  • Description: Specifies a number for pluralization rules.
  • Example:
vue
<i18n-t keypath="items" :plural="10" />
json
{
+  "items": "Nothing|You have {count} item|You have {count} items"
+}

number

  • Type: number | string
  • Optional: Yes
  • Description: This prop is used for number formatting. It can be passed as a number or string to render a localized number.
  • Example:
vue
<i18n-t keypath="data.item" :number="1234567.89" />
json
{
+  "data": {
+    "item": "The number is: {number}"
+  }
+}

date

  • Type: Date | string | number
  • Optional: Yes
  • Description: This prop is used for date formatting. It can be passed as a Date, string, or number to render a localized date.
  • Example:
vue
<i18n-t keypath="data.item" :date="'2023-12-31'" />
json
{
+  "data": {
+    "item": "The date is: {date}"
+  }
+}

relativeDate

  • Type: Date | string | number
  • Optional: Yes
  • Description: This prop is used for formatting relative dates. It can be passed as a Date, string, or number to render a localized relative date.
  • Example:
vue
<i18n-t keypath="data.item" :relative-date="'2023-12-31'" />
json
{
+  "data": {
+    "item": "The relative date is: {relativeDate}"
+  }
+}

tag

  • Type: string
  • Optional: Yes
  • Default: 'span'
  • Description: Specifies the HTML tag to wrap the translated content.
  • Example:
vue
<i18n-t keypath="feedback.text" tag="div" />

params

  • Type: Record<string, string | number | boolean>
  • Optional: Yes
  • Description: Provides parameters for interpolating dynamic values in the translation.
  • Example:
vue
<i18n-t keypath="user.greeting" :params="{ name: userName }" />

defaultValue

  • Type: string
  • Optional: Yes
  • Description: The default value to use if the translation key is not found.
  • Example:
vue
<i18n-t keypath="nonExistentKey" defaultValue="Fallback text"></i18n-t>

html

  • Type: boolean
  • Optional: Yes
  • Default: false
  • Description: Enables the rendering of the translation as raw HTML.
  • Example:
vue
<i18n-t keypath="feedback.text" html />

hideIfEmpty

  • Type: boolean
  • Optional: Yes
  • Default: false
  • Description: If true, the component will not render anything if the translation is empty.
  • Example:
vue
<i18n-t keypath="optionalMessage" :hideIfEmpty="true"></i18n-t>

customPluralRule

  • Type: (value: string, count: number, params: Record<string, string | number | boolean>, locale: string) => string
  • Optional: Yes
  • Description: A function that allows you to define custom pluralization logic. Useful if the default pluralization rules do not fit your specific needs.
  • Example:
vue
<i18n-t
+  keypath="items"
+  :plural="itemCount"
+  :customPluralRule="(key, count, params, locale, getTranslation) => {
+    const translation = getTranslation(key, params)
+    if (!translation) {
+      return null
+    }
+    return count === 1 ? 'no items' : `${count} ${translation}`;
+  }"
+></i18n-t>

🛠️ Example Usages

Basic Usage

vue
<i18n-t keypath="feedback.text" />

This renders the translation for feedback.text within a <span> tag.

Using Slots for Dynamic Content

The <i18n-t> component supports the use of slots to dynamically insert Vue components or other content into specific parts of the translation.

vue
<i18n-t keypath="feedback.text">
+  <template #link>
+    <nuxt-link :to="{ name: 'index' }">
+      <i18n-t keypath="feedback.link" />
+    </nuxt-link>
+  </template>
+</i18n-t>

In this example, the {link} placeholder in the feedback.text translation string is replaced by the <nuxt-link> component, which itself contains another translation component.

Pluralization

vue
<i18n-t keypath="items.count" :plural="itemCount" />

This automatically applies pluralization rules based on the itemCount value.

🚀 Additional Features

Default Slot

If no specific slot is provided, the translation can be customized via the default slot, which provides the entire translated string:

vue
<i18n-t keypath="welcome.message">
+  <template #default="{ translation }">
+    {{ translation.replace('Nuxt', 'Vue') }}
+  </template>
+</i18n-t>

Conditional Rendering

Render nothing if the translation string is empty by using the hideIfEmpty prop.

vue
<i18n-t keypath="optionalMessage" :hideIfEmpty="true"></i18n-t>

Custom Pluralization Rule

Use a custom function to handle pluralization.

vue
<i18n-t
+  keypath="items"
+  :plural="itemCount"
+  :customPluralRule="(key, value, count, locale) => {
+    return count === 1 ? 'One item' : `${count} items`;
+  }"
+></i18n-t>

Advanced Example with Slots

Utilize slots to customize how the translation content is rendered.

vue
<i18n-t keypath="welcomeMessage">
+  <template #default="{ translation }">
+    <strong>{{ translation }}</strong>
+  </template>
+</i18n-t>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/composables/useI18n.html b/composables/useI18n.html new file mode 100644 index 00000000..6654cc70 --- /dev/null +++ b/composables/useI18n.html @@ -0,0 +1,47 @@ + + + + + + 🛠️ useI18n Composable | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🛠️ useI18n Composable

The useI18n composable in Nuxt I18n Micro is designed to provide an easy and efficient way to access internationalization functionalities within your Nuxt application. It offers a variety of methods to handle localization, translation, and route management based on the current locale.

All methods can be accessed both with and without the $ prefix for convenience.

⚙️ Return Values

The useI18n composable returns an object containing several key methods and properties for managing internationalization:

$getLocale

  • Type: () => string
  • Description: Returns the current locale of the application.
  • Example:
    js
    const { $getLocale } = useI18n()
    +const locale = $getLocale()
    +console.log(locale) // e.g., 'en'

🌍 $getLocaleName

Version introduced: v1.28.0

  • Type: () => string | null
  • Description: Returns the current locale name from displayName config.
  • Example:
typescript
const locale = $getLocaleName()
+// Output: 'English'

$getLocales

  • Type: () => Locale[]
  • Description: Returns an array of all available locales in the application.
  • Example:
    js
    const { $getLocales } = useI18n()
    +const locales = $getLocales()
    +console.log(locales) // e.g., [{ code: 'en', iso: 'en-US' }, { code: 'fr', iso: 'fr-FR' }]

$t

  • Type: <T extends Record<string, string | number | boolean>>(key: string, params?: T, defaultValue?: string) => string | number | boolean | Translations | PluralTranslations | unknown[] | unknown | null
  • Description: Translates a given key to the corresponding localized string, optionally replacing placeholders with provided parameters and falling back to a default value if the key is not found.
  • Example:
    js
    const { $t } = useI18n()
    +const greeting = $t('hello', { name: 'John' }, 'Hello!')
    +console.log(greeting) // e.g., 'Hello, John'

$tc

  • Type: (key: string, count: number, defaultValue?: string) => string
  • Description: Translates a given key with pluralization based on the provided count, optionally falling back to a default value if the key is not found.
  • Example:
    js
    const { $tc } = useI18n()
    +const message = $tc('apples', 3, '3 apples')
    +console.log(message) // e.g., '3 apples'

$has

  • Type: (key: string) => boolean
  • Description: Checks if a translation key exists for the current locale.
  • Example:
    js
    const { $has } = useI18n()
    +const exists = $has('hello')
    +console.log(exists) // e.g., true

$mergeTranslations

  • Type: (newTranslations: Translations) => void
  • Description: Merges additional translations into the existing ones for the current locale.
  • Example:
    js
    const { $mergeTranslations } = useI18n()
    +$mergeTranslations({
    +  hello: 'Hello World',
    +})

$switchLocale

  • Type: (locale: string) => void
  • Description: Switches the application's locale to the specified locale.
  • Example:
    js
    const { $switchLocale } = useI18n()
    +$switchLocale('fr')

$localeRoute

  • Type: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw
  • Description: Generates a localized route based on the specified route and optionally the specified locale.
  • Example:
    js
    const { $localeRoute } = useI18n()
    +const route = $localeRoute('/about', 'fr')

$loadPageTranslations

  • Type: (locale: string, routeName: string) => Promise<void>
  • Description: Loads translations for the specified page and locale, enabling lazy-loading of translations.
  • Example:
    js
    const { $loadPageTranslations } = useI18n()
    +await $loadPageTranslations('fr', 'home')

🛠️ Example Usages

Basic Locale Retrieval

Retrieve the current locale of the application.

js
const { $getLocale } = useI18n()
+const locale = $getLocale()

Translation with Parameters

Translate a string with dynamic parameters, with a fallback default value.

js
const { $t } = useI18n()
+const welcomeMessage = $t('welcome', { name: 'Jane' }, 'Welcome!')

Switching Locales

Switch the application to a different locale.

js
const { $switchLocale } = useI18n()
+$switchLocale('de')

Generating a Localized Route

Generate a route localized to the current or specified locale.

js
const { $localeRoute } = useI18n()
+const route = $localeRoute('/about', 'fr')

Loading Page-Specific Translations

Lazy-load translations for a specific page and locale.

js
const { $loadPageTranslations } = useI18n()
+await $loadPageTranslations('de', 'dashboard')

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/composables/useLocaleHead.html b/composables/useLocaleHead.html new file mode 100644 index 00000000..db7b85e2 --- /dev/null +++ b/composables/useLocaleHead.html @@ -0,0 +1,45 @@ + + + + + + 🌍 useLocaleHead Composable | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🌍 useLocaleHead Composable

The useLocaleHead composable is a utility in Nuxt I18n Micro that helps you manage SEO attributes and HTML meta tags for localized routes. It dynamically generates attributes for the lang and dir of the HTML document and creates meta and link tags to improve the SEO of your localized content.

⚙️ Options

The useLocaleHead composable accepts an options object to customize its behavior:

addDirAttribute

  • Type: boolean
  • Default: true
  • Description: If true, adds the dir attribute to the HTML document based on the current locale's direction (ltr or rtl).
  • Example:
    js
    const head = useLocaleHead({ addDirAttribute: false })

identifierAttribute

  • Type: string
  • Default: 'id'
  • Description: Specifies the attribute used to identify the generated meta and link tags. This is useful for differentiating tags when inspecting the document head.
  • Example:
    js
    const head = useLocaleHead({ identifierAttribute: 'data-i18n' })

addSeoAttributes

  • Type: boolean
  • Default: true
  • Description: If true, includes SEO-related meta and link tags, such as og:locale, og:url, and hreflang attributes for alternate languages.
  • Example:
    js
    const head = useLocaleHead({ addSeoAttributes: false })

baseUrl

  • Type: string
  • Default: '/'
  • Description: The base URL of your application, used to generate canonical and alternate URLs for SEO purposes.
  • Example:
    js
    const head = useLocaleHead({ baseUrl: 'https://example.com' })

🛠️ Return Values

The useLocaleHead composable returns an object with htmlAttrs, meta, and link properties, which can be directly used in the <head> section of your Nuxt application.

htmlAttrs

  • Type: Record<string, string>
  • Description: Contains attributes to be added to the <html> tag, such as lang and dir.
  • Example:
    js
    const { htmlAttrs } = useLocaleHead()
    +console.log(htmlAttrs)
    +// Output: { lang: 'en-US', dir: 'ltr' }

meta

  • Type: Array<Record<string, string>>
  • Description: Contains meta tags for SEO, including Open Graph locale tags and alternate locales.
  • Example:
    js
    const { meta } = useLocaleHead()
    +console.log(meta)
    +// Output: [{ id: 'i18n-og', property: 'og:locale', content: 'en-US' }, ...]
  • Type: Array<Record<string, string>>
  • Description: Contains link tags for canonical URLs and alternate language versions of the page.
  • Example:
    js
    const { link } = useLocaleHead()
    +console.log(link)
    +// Output: [{ id: 'i18n-can', rel: 'canonical', href: 'https://example.com/about' }, ...]

🛠️ Example Usages

Basic Usage

Generate locale-specific head attributes with default options.

js
const head = useLocaleHead()

Customize Identifier Attribute

Use a custom identifier attribute for the generated tags.

js
const head = useLocaleHead({ identifierAttribute: 'data-i18n' })

Disable SEO Attributes

Generate head attributes without adding SEO-related meta and link tags.

js
const head = useLocaleHead({ addSeoAttributes: false })

Specify a Base URL

Set a custom base URL for canonical and alternate URLs.

js
const head = useLocaleHead({ baseUrl: 'https://mywebsite.com' })

🚀 Additional Features

When addSeoAttributes is enabled, the composable automatically generates the following tags:

  • og:locale for the current locale.
  • og:url for the canonical URL of the page.
  • og:locale:alternate for alternate language versions.
  • rel="canonical" and rel="alternate" links for SEO optimization.

Dynamic Locale and Direction

The composable dynamically determines the lang and dir attributes based on the current route's locale, ensuring that your HTML document is correctly configured for international users.

Handling Localized Routes

If your routes are prefixed with locale codes (e.g., /en/about), the composable intelligently adjusts the full path for generating URLs, ensuring that SEO attributes are accurate and relevant.

This composable simplifies the process of optimizing your Nuxt application for international audiences, ensuring that your site is well-prepared for global search engines and users.

🛠️ Example Usage

The following example demonstrates how to use the useLocaleHead composable within a Vue component with default settings:

vue
<script setup>
+const head = useLocaleHead({
+  addDirAttribute: true,
+  identifierAttribute: 'id',
+  addSeoAttributes: true,
+})
+
+useHead(head)
+</script>
+
+<template>
+  <div>
+    
+  </div>
+</template>

Explanation of the Code

  • useLocaleHead Composable: This composable is called in the <script setup> section and returns an object containing htmlAttrs, meta, and link.

  • <html> Tag: The lang and dir attributes for the HTML document are dynamically determined based on the current locale and are applied to the <html> tag.

  • <head> Section:

    • Meta Tags: SEO-related meta tags are generated, including og:locale, og:url, and rel="canonical" and rel="alternate" tags to specify alternate language versions of the page.
    • Link Tags: Canonical links and links to alternate language versions are included.
  • <body> Section: The main content of the page is displayed here. In this example, a simple header and paragraph are used.

📝 Notes

  1. Attributes: The attributes used (lang, dir, rel, href, hreflang, property, content) are extracted from the object returned by useLocaleHead.

  2. SEO Tags Generation: If the addSeoAttributes option is set to true, the composable automatically generates SEO tags for the current locale.

  3. Base URL: You can set your custom base URL using the baseUrl option to correctly generate canonical and alternate links.

This example demonstrates how easy it is to integrate useLocaleHead into your application's components to ensure correct SEO attributes and improve the search engine indexing of localized pages.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/devtools.png b/devtools.png new file mode 100644 index 00000000..3b6cf3ac Binary files /dev/null and b/devtools.png differ diff --git a/examples.html b/examples.html new file mode 100644 index 00000000..8acdc7fb --- /dev/null +++ b/examples.html @@ -0,0 +1,284 @@ + + + + + + 📚 Nuxt I18n Micro Examples and Usage | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

📚 Nuxt I18n Micro Examples and Usage

This section provides various examples demonstrating how to use Nuxt I18n Micro in your Nuxt.js application. You'll see how to switch locales, use the <i18n-link>, <i18n-switcher>, and <i18n-t> components, and dynamically handle translation keys.

🛠️ Basic Setup

Here's a basic setup to get started with Nuxt I18n Micro:

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n-micro'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr', disabled: false, displayName: 'English' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr', disabled: false, displayName: 'Français' },
+      { code: 'de', iso: 'de-DE', dir: 'ltr', disabled: false, displayName: 'Deutsch' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

🌍 Locale Switching

Switching Locales Programmatically

This example demonstrates how to switch locales programmatically using buttons:

vue
<template>
+  <div>
+    <p>Current Locale: {{ $getLocale() }}</p>
+    <div>
+      <button
+        v-for="locale in $getLocales()"
+        :key="locale.code"
+        :disabled="locale.code === $getLocale()"
+        @click="() => $switchLocale(locale.code)"
+      >
+        Switch to {{ $t(locale.code) }}
+      </button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $t } = useNuxtApp()
+</script>

Example JSON for Locale Switching

json
{
+  "en": "English",
+  "fr": "Français",
+  "de": "Deutsch"
+}

Using <i18n-switcher> Component

The <i18n-switcher> component provides a dropdown for locale switching with customizable labels:

vue
<template>
+  <div>
+    <i18n-switcher
+      :custom-labels="{ en: 'English', fr: 'Français', de: 'Deutsch' }"
+    />
+  </div>
+</template>

The <i18n-link> component automatically handles locale-specific routing:

vue
<template>
+  <div>
+    <i18n-link to="/about">{{ $t('about') }}</i18n-link>
+    <i18n-link :to="{ name: 'index' }">{{ $t('home') }}</i18n-link>
+  </div>
+</template>
+
+<script setup>
+  import { useNuxtApp } from '#imports'
+
+  const { $getLocale, $switchLocale, $getLocales, $t } = useNuxtApp()
+</script>
json
{
+  "about": "About Us",
+  "home": "Home"
+}
vue
<template>
+  <div>
+    <i18n-link to="/about" activeClass="current">About Us</i18n-link>
+  </div>
+</template>

The same JSON file can be used as in the previous example for this scenario.

📝 Rendering Dynamic Keys from Translation Files

In some scenarios, you may want to iterate over dynamic keys stored within your translation files and render their values conditionally. The example below demonstrates how to achieve this using Nuxt I18n Micro.

Example: Rendering Dynamic Keys

This example fetches an array of keys from a specific translation path (in this case, dynamic) and iterates over them. Each key is checked for its existence using $has before rendering its value with $t.

vue
<template>
+  <div>
+    <div
+      v-for="key in $t('dynamic')"
+      :key="key"
+    >
+      <p>{{ key }}: <span v-if="$has(key)">{{ $t(key) }}</span></p>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $t, $has } = useNuxtApp()
+</script>

Example Translation File (en.json)

json
{
+  "dynamic": ["key1", "key2", "key3"],
+  "key1": "This is the first key's value",
+  "key2": "This is the second key's value",
+  "key3": "This is the third key's value"
+}

Example: Rendering Dynamic Keys from an Object

In this example, we handle an object stored within your translation file. We fetch and iterate over the keys of the object, dynamically rendering both the key names and their associated values.

vue
<template>
+  <div>
+    <div v-for="(value, key) in $t('dynamicObject')" :key="key">
+      <p>{{ key }}: {{ value }}</p>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $t } = useNuxtApp()
+</script>

Example Translation File (en.json)

json
{
+  "dynamicObject": {
+    "title": "Welcome to our site",
+    "description": "This is a brief description of our services.",
+    "footerNote": "Thank you for visiting!"
+  }
+}

🌟 Using <i18n-t> for Translations with Slots and Interpolation

The <i18n-t> component is useful for rendering translations with dynamic content and HTML tags:

vue
<template>
+  <i18n-t keypath="greeting" tag="h1">
+    <template #default="{ translation }">
+      <strong>{{ translation.replace('page', 'page replace') }}</strong> <i>!!!</i>
+    </template>
+  </i18n-t>
+</template>

Example JSON for <i18n-t>

json
{
+  "greeting": "Welcome to the page"
+}

With Interpolation

vue
<template>
+  <i18n-t keypath="welcome" :params="{ username: 'Alice', unreadCount: 5 }"></i18n-t>
+</template>

Example JSON for Interpolation

json
{
+  "welcome": "Hello {username}, you have {unreadCount} unread messages."
+}

📝 Comprehensive Example with Nested Sections

Here's a complex structure demonstrating multiple translation uses within a single page:

vue
<template>
+  <div>
+    <h1>{{ $t('mainHeader') }}</h1>
+
+    <nav>
+      <ul>
+        <li><a href="#">{{ $t('nav.home') }}</a></li>
+        <li><a href="#">{{ $t('nav.about') }}</a></li>
+        <li><a href="#">{{ $t('nav.services') }}</a></li>
+        <li><a href="#">{{ $t('nav.contact') }}</a></li>
+      </ul>
+    </nav>
+
+    <section>
+      <h2>{{ $t('section1.header') }}</h2>
+      <p>{{ $t('section1.intro') }}</p>
+
+      <div>
+        <h3>{{ $t('section1.subsection1.header') }}</h3>
+        <p>{{ $t('section1.subsection1.content') }}</p>
+      </div>
+
+      <div>
+        <h3>{{ $t('section1.subsection2.header') }}</h3>
+        <ul>
+          <li>{{ $t('section1.subsection2.item1') }}</li>
+          <li>{{ $t('section1.subsection2.item2') }}</li>
+          <li>{{ $t('section1.subsection2.item3') }}</li>
+        </ul>
+      </div>
+    </section>
+
+    <footer>
+      <h4>{{ $t('footer.contact.header') }}</h4>
+      <address>
+        {{ $t('footer.contact.address') }}<br>
+        {{ $t('footer.contact.city') }}<br>
+        {{ $t('footer.contact.phone') }}
+      </address>
+    </footer>
+
+    <div>
+      <button
+        v-for="locale in $getLocales()"
+        :key="locale.code"
+        :disabled="locale.code === $getLocale()"
+        @click="() => $switchLocale(locale.code)"
+      >
+        Switch to {{ locale.code }}
+      </button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $t } = useNuxtApp()
+</script>

Example JSON for Nested Sections

json
{
+  "mainHeader": "Welcome to Our Services",
+  "nav": {
+    "home": "Home",
+    "about": "About Us",
+    "services": "Services",
+    "contact": "Contact"
+  },
+  "section1": {
+    "header": "Our Expertise",
+    "intro": "We provide a wide range of services to meet your needs.",
+    "subsection1": {
+      "header": "Consulting",
+      "content": "Our team offers expert consulting services in various domains."
+    },
+    "subsection2": {
+      "header": "Development",
+      "item1":
+
+ "Web Development",
+      "item2": "Mobile Apps",
+      "item3": "Custom Software"
+    }
+  },
+  "footer": {
+    "contact": {
+      "header": "Contact Us",
+      "address": "123 Main Street",
+      "city": "Anytown, USA",
+      "phone": "+1 (555) 123-4567"
+    }
+  }
+}

🌟 Using $tc for Pluralization

The $tc function in Nuxt I18n Micro handles pluralization based on the count and locale settings. This is useful for dynamically adjusting messages that involve counts, such as items, notifications, or other entities that can vary in number.

Example: Using $tc for Pluralization

In the following example, we display a message indicating the number of apples using $tc. The translation key handles multiple plural forms based on the count provided.

vue
<template>
+  <div>
+    <!-- Display a pluralized message about the number of apples -->
+    <p>{{ $tc('apples', 0) }}</p>  <!-- Outputs: no apples -->
+    <p>{{ $tc('apples', 1) }}</p>  <!-- Outputs: one apple -->
+    <p>{{ $tc('apples', 10) }}</p> <!-- Outputs: 10 apples -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $tc } = useNuxtApp()
+</script>

Example JSON for Pluralization

Here's how you can define the translation in your JSON file to handle different plural forms:

json
{
+  "apples": "no apples | one apple | {count} apples"
+}

Explanation

  • $tc('apples', 0): Returns the first form, used when the count is zero ("no apples").
  • $tc('apples', 1): Returns the second form, used when the count is one ("one apple").
  • $tc('apples', 10): Returns the third form with the count value, used when the count is two or more ("10 apples").

Additional Example with More Complex Pluralization

If your application needs to handle more complex pluralization rules (e.g., specific cases for zero, one, two, few, many, other), you can extend the translation strings accordingly:

json
{
+  "apples": "no apples | one apple | two apples | a few apples | many apples | {count} apples"
+}
  • $tc('apples', 2): Could be set up to return "two apples".
  • $tc('apples', 3): Could return "a few apples", depending on the rules defined for the count.

🌐 Using $tn for Number Formatting

The $tn function formats numbers according to the current locale using the Intl.NumberFormat API. This is useful for displaying numbers in a way that matches the user's regional settings, such as currency, percentages, or other number formats.

Example: Using $tn for Number Formatting

vue
<template>
+  <div>
+    <!-- Format a number as currency -->
+    <p>{{ $tn(1234567.89, { style: 'currency', currency: 'USD' }) }}</p> <!-- Outputs: $1,234,567.89 in 'en-US' locale -->
+
+    <!-- Format a number with custom options -->
+    <p>{{ $tn(0.567, { style: 'percent', minimumFractionDigits: 1 }) }}</p> <!-- Outputs: 56.7% in 'en-US' locale -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $tn } = useNuxtApp()
+</script>

🗓️ Using $td for Date and Time Formatting

The $td function formats dates and times according to the current locale using the Intl.DateTimeFormat API. This is useful for displaying dates and times in formats that are familiar to the user based on their locale settings.

Example: Using $td for Date and Time Formatting

vue
<template>
+  <div>
+    <!-- Format a date with full options -->
+    <p>{{ $td(new Date(), { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }) }}</p> <!-- Outputs: "Friday, September 1, 2023" in 'en-US' locale -->
+
+    <!-- Format a date with time -->
+    <p>{{ $td(new Date(), { hour: '2-digit', minute: '2-digit', second: '2-digit' }) }}</p> <!-- Outputs: "10:15:30 AM" in 'en-US' locale -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $td } = useNuxtApp()
+</script>

🗓️ Using $tdr for Relative Date Formatting

The $tdr function formats dates as relative times (e.g., "5 minutes ago", "2 days ago") according to the current locale using the Intl.RelativeTimeFormat API. This is useful for displaying time differences relative to the current date and time.

Example: Using $tdr for Relative Date Formatting

vue
<template>
+  <div>
+    <!-- Format a date as a relative time -->
+    <p>{{ $tdr(new Date(Date.now() - 1000 * 60 * 5)) }}</p> <!-- Outputs: "5 minutes ago" in 'en-US' locale -->
+
+    <!-- Format a date that is in the future -->
+    <p>{{ $tdr(new Date(Date.now() + 1000 * 60 * 60 * 24)) }}</p> <!-- Outputs: "in 1 day" in 'en-US' locale -->
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $tdr } = useNuxtApp()
+</script>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/cli.html b/guide/cli.html new file mode 100644 index 00000000..4100b4d9 --- /dev/null +++ b/guide/cli.html @@ -0,0 +1,52 @@ + + + + + + 🌐 nuxt-i18n-micro-cli Guide | Nuxt I18n Micro + + + + + + + + + + + + + + + +
Skip to content

🌐 nuxt-i18n-micro-cli Guide

📖 Introduction

nuxt-i18n-micro-cli is a command-line tool designed to streamline the localization and internationalization process in Nuxt.js projects using the nuxt-i18n module. It provides utilities to extract translation keys from your codebase, manage translation files, synchronize translations across locales, and automate the translation process using external translation services.

This guide will walk you through installing, configuring, and using nuxt-i18n-micro-cli to effectively manage your project's translations. Package on npmjs.com.

🔧 Installation and Setup

📦 Installing nuxt-i18n-micro-cli

Install nuxt-i18n-micro-cli globally using npm:

bash
npm install -g nuxt-i18n-micro-cli

This will make the i18n-micro command available globally on your system.

🛠 Initializing in Your Project

After installing, you can run i18n-micro commands in your Nuxt.js project directory.

Ensure that your project is set up with nuxt-i18n and has the necessary configuration in nuxt.config.js.

📄 Common Arguments

  • --cwd: Specify the current working directory (defaults to .).
  • --logLevel: Set the log level (silent, info, verbose).
  • --translationDir: Directory containing JSON translation files (default: locales).

📋 Commands

🔄 text-to-i18n Command

Version introduced: v1.1.0

DevTools

Description: The text-to-i18n command automatically scans your codebase for hardcoded text strings and replaces them with i18n translation references. It extracts text from Vue templates, JavaScript, and TypeScript files, generating translation keys and updating your translation files.

Usage:

bash
i18n-micro text-to-i18n [options]

Options:

  • --translationFile: Path to the JSON file containing translations (default: locales/en.json).
  • --context: Context prefix for translation keys. Helps organize translations by feature or section.
  • --dryRun: Show changes without modifying files (default: false).
  • --verbose: Show detailed processing information (default: false).
  • --path: Path to a specific file to process (e.g., ./pages/test-page.vue). When provided, only the specified file is processed.

Example:

bash
i18n-micro text-to-i18n --translationFile locales/en.json --context auth

How it works:

  1. File Collection:
  • Scans directories: pages, components, and plugins
  • Processes files with extensions: .vue, .js, and .ts
  1. Text Processing:
  • Extracts text from Vue templates and script files
  • Identifies translatable strings
  • Generates unique translation keys based on:
    • File path
    • Text content
    • Context prefix (if provided)
  1. Translation Management:
  • Creates new translation entries
  • Maintains nested structure in translation files
  • Preserves existing translations
  • Updates translation files with new entries

Example Transformations:

Before:

vue
<template>
+  <div>
+    <h1>Welcome to our site</h1>
+    <p>Please sign in to continue</p>
+  </div>
+</template>

After:

vue
<template>
+  <div>
+    <h1>{{ $t('pages.home.welcome_to_our_site') }}</h1>
+    <p>{{ $t('pages.home.please_sign_in') }}</p>
+  </div>
+</template>

Best Practices:

  1. Run in Dry Mode First:

    bash
    i18n-micro text-to-i18n --dryRun

    This shows what changes would be made without modifying files.

  2. Use Context for Organization:

    bash
    i18n-micro text-to-i18n --context auth

    Prefixes translation keys with auth. for better organization.

  3. Review Changes:

  • Enable verbose mode to see detailed changes
  • Check generated translation keys
  • Verify extracted text accuracy
  1. Backup Files:
  • Always backup your files before running the command
  • Use version control to track changes

Notes:

  • The command preserves existing translations and keys
  • Generated keys are based on file paths and text content
  • Supports Vue template syntax and JavaScript/TypeScript files
  • Handles both simple text and attribute translations
  • Maintains nested translation structure

📊 stats Command

Description: The stats command is used to display translation statistics for each locale in your Nuxt.js project. It helps you understand the progress of your translations by showing how many keys are translated compared to the total number of keys available.

Usage:

bash
i18n-micro stats [options]

Options:

  • --full: Display combined translations statistics only (default: false).

Example:

bash
i18n-micro stats --full

🌍 translate Command

Description: The translate command automatically translates missing keys using external translation services. This command simplifies the translation process by leveraging APIs from services like Google Translate, DeepL, and others to fill in missing translations.

Usage:

bash
i18n-micro translate [options]

Options:

  • --service: Translation service to use (e.g., google, deepl, yandex). If not specified, the command will prompt you to select one.
  • --token: API key corresponding to the chosen translation service. If not provided, you will be prompted to enter it.
  • --options: Additional options for the translation service, provided as key:value pairs, separated by commas (e.g., model:gpt-3.5-turbo,max_tokens:1000).
  • --replace: Translate all keys, replacing existing translations (default: false).

Example:

bash
i18n-micro translate --service deepl --token YOUR_DEEPL_API_KEY

🌐 Supported Translation Services

The translate command supports multiple translation services. Some of the supported services are:

  • Google Translate (google)
  • DeepL (deepl)
  • Yandex Translate (yandex)
  • OpenAI (openai)
  • Azure Translator (azure)
  • IBM Watson (ibm)
  • Baidu Translate (baidu)
  • LibreTranslate (libretranslate)
  • MyMemory (mymemory)
  • Lingva Translate (lingvatranslate)
  • Papago (papago)
  • Tencent Translate (tencent)
  • Systran Translate (systran)
  • Yandex Cloud Translate (yandexcloud)
  • ModernMT (modernmt)
  • Lilt (lilt)
  • Unbabel (unbabel)
  • Reverso Translate (reverso)

⚙️ Service Configuration

Some services require specific configurations or API keys. When using the translate command, you can specify the service and provide the required --token (API key) and additional --options if needed.

For example:

bash
i18n-micro translate --service openai --token YOUR_OPENAI_API_KEY --options openaiModel:gpt-3.5-turbo,max_tokens:1000

🛠️ extract Command

Description: Extracts translation keys from your codebase and organizes them by scope.

Usage:

bash
i18n-micro extract [options]

Options:

  • --prod, -p: Run in production mode.

Example:

bash
i18n-micro extract

🔄 sync Command

Description: Synchronizes translation files across locales, ensuring all locales have the same keys.

Usage:

bash
i18n-micro sync [options]

Example:

bash
i18n-micro sync

validate Command

Description: Validates translation files for missing or extra keys compared to the reference locale.

Usage:

bash
i18n-micro validate [options]

Example:

bash
i18n-micro validate

🧹 clean Command

Description: Removes unused translation keys from translation files.

Usage:

bash
i18n-micro clean [options]

Example:

bash
i18n-micro clean

📤 import Command

Description: Converts PO files back to JSON format and saves them in the translation directory.

Usage:

bash
i18n-micro import [options]

Options:

  • --potsDir: Directory containing PO files (default: pots).

Example:

bash
i18n-micro import --potsDir pots

📥 export Command

Description: Exports translations to PO files for external translation management.

Usage:

bash
i18n-micro export [options]

Options:

  • --potsDir: Directory to save PO files (default: pots).

Example:

bash
i18n-micro export --potsDir pots

🗂️ export-csv Command

Description: The export-csv command exports translation keys and values from JSON files, including their file paths, into a CSV format. This command is useful for teams who prefer working with translation data in spreadsheet software.

Usage:

bash
i18n-micro export-csv [options]

Options:

  • --csvDir: Directory where the exported CSV files will be saved.
  • --delimiter: Specify a delimiter for the CSV file (default: ,).

Example:

bash
i18n-micro export-csv --csvDir csv_files

📑 import-csv Command

Description: The import-csv command imports translation data from CSV files, updating the corresponding JSON files. This is useful for applying bulk translation updates from spreadsheets.

Usage:

bash
i18n-micro import-csv [options]

Options:

  • --csvDir: Directory containing the CSV files to be imported.
  • --delimiter: Specify a delimiter used in the CSV file (default: ,).

Example:

bash
i18n-micro import-csv --csvDir csv_files

🧾 diff Command

Description: Compares translation files between the default locale and other locales within the same directory (including subdirectories). The command identifies missing keys and their values in the default locale compared to other locales, making it easier to track translation progress or discrepancies.

Usage:

bash
i18n-micro diff [options]

Example:

bash
i18n-micro diff

🔍 check-duplicates Command

Description: The check-duplicates command checks for duplicate translation values within each locale across all translation files, including both global and page-specific translations. It ensures that different keys within the same language do not share identical translation values, helping maintain clarity and consistency in your translations.

Usage:

bash
i18n-micro check-duplicates [options]

Example:

bash
i18n-micro check-duplicates

How it works:

  • The command checks both global and page-specific translation files for each locale.
  • If a translation value appears in multiple locations (either within global translations or across different pages), it reports the duplicate values along with the file and key where they are found.
  • If no duplicates are found, the command confirms that the locale is free of duplicated translation values.

This command helps ensure that translation keys maintain unique values, preventing accidental repetition within the same locale.

🔄 replace-values Command

Description: The replace-values command allows you to perform bulk replacements of translation values across all locales. It supports both simple text replacements and advanced replacements using regular expressions (regex). You can also use capturing groups in regex patterns and reference them in the replacement string, making it ideal for more complex replacement scenarios.

Usage:

bash
i18n-micro replace-values [options]

Options:

  • --search: The text or regex pattern to search for in translations. This is a required option.
  • --replace: The replacement text to be used for the found translations. This is a required option.
  • --useRegex: Enable search using a regular expression pattern (default: false).

Example 1: Simple replacement

Replace the string "Hello" with "Hi" across all locales:

bash
i18n-micro replace-values --search "Hello" --replace "Hi"

Example 2: Regex replacement

Enable regex search and replace any string starting with "Hello" followed by numbers (e.g., "Hello123") with "Hi" across all locales:

bash
i18n-micro replace-values --search "Hello\\d+" --replace "Hi" --useRegex

Example 3: Using regex capturing groups

Use capturing groups to dynamically insert part of the matched string into the replacement. For example, replace "Hello [name]" with "Hi [name]" while keeping the name intact:

bash
i18n-micro replace-values --search "Hello (\\w+)" --replace "Hi $1" --useRegex

In this case, $1 refers to the first capturing group, which matches the [name] part after "Hello". The replacement will keep the name from the original string.

How it works:

  • The command scans through all translation files (both global and page-specific).
  • When a match is found based on the search string or regex pattern, it replaces the matched text with the provided replacement.
  • When using regex, capturing groups can be used in the replacement string by referencing them with $1, $2, etc.
  • All changes are logged, showing the file path, translation key, and the before/after state of the translation value.

Logging: For each replacement, the command logs details including:

  • Locale and file path
  • The translation key being modified
  • The old value and the new value after replacement
  • If using regex with capturing groups, the logs will show the group matches and how they were replaced.

This allows you to track exactly where and what changes were made during the replacement operation, providing a clear history of modifications across your translation files.

🛠 Examples

  • Extracting translations:

    bash
    i18n-micro extract
  • Translating missing keys using Google Translate:

    bash
    i18n-micro translate --service google --token YOUR_GOOGLE_API_KEY
  • Translating all keys, replacing existing translations:

    bash
    i18n-micro translate --service deepl --token YOUR_DEEPL_API_KEY --replace
  • Validating translation files:

    bash
    i18n-micro validate
  • Cleaning unused translation keys:

    bash
    i18n-micro clean
  • Synchronizing translation files:

    bash
    i18n-micro sync

⚙️ Configuration Guide

nuxt-i18n-micro-cli relies on your Nuxt.js i18n configuration in nuxt.config.js. Ensure you have the nuxt-i18n module installed and configured.

🔑 nuxt.config.js Example

js
export default {
+  modules: ['@nuxtjs/i18n'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US' },
+      { code: 'fr', iso: 'fr-FR' },
+      { code: 'es', iso: 'es-ES' },
+      // Add other locales as needed
+    ],
+    defaultLocale: 'en',
+    vueI18n: {
+      fallbackLocale: 'en',
+    },
+    // Specify the directory where your translation files are stored
+    translationDir: 'locales',
+  },
+};

Ensure that the translationDir matches the directory used by nuxt-i18n-micro-cli (default is locales).

📝 Best Practices

🔑 Consistent Key Naming

Ensure translation keys are consistent and descriptive to avoid confusion and duplication.

🧹 Regular Maintenance

Use the clean command regularly to remove unused translation keys and keep your translation files clean.

🛠 Automate Translation Workflow

Integrate nuxt-i18n-micro-cli commands into your development workflow or CI/CD pipeline to automate extraction, translation, validation, and synchronization of translation files.

🛡️ Secure API Keys

When using translation services that require API keys, ensure your keys are kept secure and not committed to version control systems. Consider using environment variables or secure key management solutions.

📞 Support and Contributions

If you encounter issues or have suggestions for improvements, feel free to contribute to the project or open an issue on the project's repository.


By following this guide, you'll be able to effectively manage translations in your Nuxt.js project using nuxt-i18n-micro-cli, streamlining your internationalization efforts and ensuring a smooth experience for users in different locales.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/contribution.html b/guide/contribution.html new file mode 100644 index 00000000..0f062342 --- /dev/null +++ b/guide/contribution.html @@ -0,0 +1,34 @@ + + + + + + 🤝 Contribution Guide | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🤝 Contribution Guide

📖 Introduction

Thank you for your interest in contributing to Nuxt I18n Micro! We welcome contributions from the community, whether it's bug fixes, new features, or improvements to the documentation. This guide outlines the steps to help you get started and ensures that your contributions can be easily integrated into the project.

🚀 Getting Started

1. 📚 Familiarize Yourself with the Project

Before making changes, it's a good idea to familiarize yourself with the project's architecture and codebase. Read through the existing documentation and take a look at open issues and pull requests to understand ongoing work and challenges.

2. 🍴 Fork the Repository

  • Navigate to the Nuxt I18n Micro repository.
  • Click the "Fork" button in the upper right corner to create a copy of the repository in your GitHub account.

3. 📥 Clone Your Fork

Clone the forked repository to your local machine:

bash
git clone https://github.com/<your-username>/nuxt-i18n-micro.git
+cd nuxt-i18n-micro

Replace <your-username> with your GitHub username.

4. 🌱 Create a Branch

Create a new branch for your work:

bash
git checkout -b feature/your-feature-name

Use descriptive branch names, such as bugfix/fix-translation-error or feature/add-new-locale-support.

🛠️ Local Development Setup

🛠 Prerequisites

Before you begin, ensure that you have the following installed on your machine:

  • Node.js: v16 or later
  • npm: v7 or later
  • pnpm: v9 or later

🚀 Getting Started

1. 📥 Clone the Repository

First, you need to clone the nuxt-i18n-micro repository to your local machine.

bash
git clone https://github.com/s00d/nuxt-i18n-micro.git
+cd nuxt-i18n-micro

2. 📦 Install Dependencies

Next, install the project dependencies using pnpm.

bash
pnpm install
+pnpm --filter "./packages/**" run build
+pnpm run prepack && cd playground && pnpm run prepare && cd ..

3. 🖥️ Run the Development Server

To start the development server and work on the module, run the following command:

bash
pnpm run dev

This command will start the Nuxt development server using the playground directory as the testing environment. You can view the app in your browser by navigating to http://localhost:3000.

4. 🏗️ Building the Module

To build the module, use the following command:

bash
pnpm run prepack

This command prepares the module by building the necessary files, stubbing certain components, and ensuring everything is ready for packaging.

5. 🧹 Linting the Code

To ensure your code adheres to the project's coding standards, run the linter:

bash
pnpm run lint

If there are any issues, you can attempt to automatically fix them using:

bash
pnpm run lint:fix

6. ✅ Running Tests

To run the test suite, use the following command:

bash
pnpm run test:workspaces
+pnpm run test

This will run all the Playwright tests to ensure everything is functioning as expected.

7. 🔍 Type Checking

For TypeScript type checking, run:

bash
pnpm run typecheck
+pnpm run test:types
+pnpm run test

This checks the type definitions to ensure there are no type errors.

8. 📚 Building and Previewing the Documentation

To build and preview the documentation locally, use the following commands:

bash
pnpm run docs:build
+pnpm run docs:serve

This will build the documentation and serve it locally, allowing you to view it in your browser.

9. 🎮 Running the Playground

If you want to test your changes in a sample Nuxt application, the playground directory serves as a sandbox environment. Run the following command to start the playground:

bash
pnpm run dev:build

You can access the playground app at http://localhost:3000.

🔧 Summary of Common Scripts

  • pnpm run dev: Start the development server using the playground.
  • pnpm run prepack: Build the module and prepare it for publishing.
  • pnpm --filter "./packages/**" run build: Build the packages.
  • pnpm run lint: Run the linter to check for code quality issues.
  • pnpm run lint:fix: Automatically fix linter issues.
  • pnpm run test: Run the test suite.
  • pnpm run test:workspaces: Run the test suite for packages.
  • pnpm run typecheck: Check TypeScript types.
  • pnpm run docs:dev: Start the documentation site in development mode.
  • pnpm run docs:build: Build the documentation site.
  • pnpm run docs:serve: Serve the built documentation site locally.
  • pnpm run dev:build: Build the playground environment.

🚧 Making Changes

1. 💻 Code

  • Make your changes in the codebase according to the project’s architecture.
  • Follow the existing code style and conventions.
  • If you’re adding a new feature, consider writing tests for it.

2. 🧹 Run Linting

Before committing your changes, ensure that your code adheres to the project's coding standards by running the linter:

bash
pnpm run lint

Fix any linting errors before proceeding.

3. 🧪 Test Your Changes

Make sure your changes work and do not break any existing functionality:

  • Run all tests to ensure there are no errors:
bash
pnpm run test:workspaces
+pnpm run test
  • If you’re fixing a bug, add tests to cover the fix.

4. 📝 Commit Your Changes

To ensure consistency across the project, we use a standardized commit message format. Please follow this format when making commits:

✅ Commit Message Format

Each commit message should be structured as follows:

<type>(<scope>): <short description>

📋 Examples:

  • fix(router): resolve issue with locale switching
  • feat(seo): add automatic og:locale meta tag generation
  • docs(contribution): update contribution guide with commit message format

🛠️ Commit Types:

  • feat: A new feature.
  • fix: A bug fix.
  • docs: Documentation changes or updates.
  • style: Code style or formatting changes (no functional impact).
  • refactor: Code changes that neither fix a bug nor add a feature.
  • test: Adding or updating tests.
  • chore: Miscellaneous tasks, such as updating build scripts or dependencies.

For more details, refer to the Conventional Commits Specification.

5. 🚀 Push to GitHub

Push your changes to your fork on GitHub:

bash
git push origin feature/your-feature-name

6. 🔄 Create a Pull Request

  • Go to your forked repository on GitHub.
  • Click the "Compare & pull request" button.
  • Ensure your PR targets the main branch of the original repository (s00d/nuxt-i18n-micro).
  • Describe your changes in the PR, and link to any relevant issues.

7. 🕵️‍♂️ Await Feedback

Once your pull request is submitted, a maintainer will review your changes. Be prepared to make adjustments based on feedback. Once approved, your PR will be merged into the main branch.

💡 Contribution Tips

  • 📝 Documentation: If you add or change a feature, ensure that you update the relevant documentation.
  • 🧼 Code Cleanliness: Keep your code clean and follow the project's coding standards.
  • 💬 Respectful Communication: Be respectful and friendly in your communications. We are all working towards the common goal of making Nuxt I18n Micro better.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/crowdin.html b/guide/crowdin.html new file mode 100644 index 00000000..299e652f --- /dev/null +++ b/guide/crowdin.html @@ -0,0 +1,40 @@ + + + + + + 🌐 Crowdin Integration Guide | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🌐 Crowdin Integration Guide

📖 Introduction

Integrating Crowdin into your project streamlines the localization and translation process, making it easier to manage translations across multiple languages and platforms. This guide provides a step-by-step walkthrough on setting up Crowdin with your project, including configuration, uploading sources, and downloading translations.

🔧 Installation and Setup

To get started with Crowdin, you'll need to install the Crowdin CLI globally on your machine and initialize it within your project directory.

📦 Installing Crowdin CLI

First, install the Crowdin CLI globally using npm:

bash
npm install -g @crowdin/cli

🛠 Initializing Crowdin in Your Project

Initialize Crowdin in your project by running:

bash
crowdin init

This command will guide you through the setup process, including setting your project ID, API token, and other configuration details.

🗂️ Configuration Guide

📄 Crowdin Configuration File (crowdin.yml)

The Crowdin configuration file (crowdin.yml) defines how your source files are mapped and where translations should be placed. Below is an example configuration:

yml
"project_id": "YOUR_PROJECT_ID"
+"api_token": "YOUR_API_TOKEN"
+"base_path": "./locales"
+"base_url": "https://api.crowdin.com"
+"preserve_hierarchy": true
+
+files: [
+  {
+    "source": "/en.json",
+    "translation": "/%two_letters_code%.json",
+  },
+  {
+    "source": "/pages/**/en.json",
+    "translation": "/pages/**/%two_letters_code%.json",
+  }
+]

📂 Key Configuration Parameters

  • project_id: Your Crowdin project ID. This identifies the project within Crowdin where translations are managed.
  • api_token: The API token used for authentication. Ensure this token has the correct permissions to upload and download translations.
  • base_path: Specifies the base directory for source files. In this example, translations are stored in the ./locales directory.
  • base_url: The base URL for the Crowdin API.
  • preserve_hierarchy: When set to true, Crowdin will maintain the folder structure of your source files in the project.

📂 Files Configuration

The files section maps your source files to the paths where translations will be stored. For example:

  • Source Path: Defines the location of the original translation files.
  • Translation Path: Specifies where the translated files will be stored in Crowdin. Placeholders like %two_letters_code% are used to dynamically set the language code in the file paths.

⬆️ Uploading Source Files to Crowdin

Once your Crowdin configuration is set up, you can upload your source files using the following command:

bash
crowdin upload sources

This command uploads all specified source files in your configuration to Crowdin, making them available for translation.

⬇️ Downloading Translations from Crowdin

After translations are completed or updated in Crowdin, you can download them to your project using:

bash
crowdin download

This command fetches the latest translations from Crowdin and saves them according to the paths specified in your configuration file.

⚙️ Best Practices

🔑 Consistent Key Naming

Ensure translation keys are consistent across all files to avoid confusion and duplication.

🧹 Regular Maintenance

Periodically review and clean up unused translation keys to keep your files organized and manageable.

🛠 Automate Uploads and Downloads

Integrate the Crowdin CLI commands into your CI/CD pipeline to automate the upload of source files and download of translations, ensuring your translations are always up to date.

By following this guide, you’ll be able to seamlessly integrate Crowdin into your project, ensuring an efficient and organized approach to managing your internationalization efforts.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/custom-locale-routes.html b/guide/custom-locale-routes.html new file mode 100644 index 00000000..c5a2e548 --- /dev/null +++ b/guide/custom-locale-routes.html @@ -0,0 +1,59 @@ + + + + + + 🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🔗 Custom Localized Routes with localeRoutes in Nuxt I18n Micro

📖 Introduction to localeRoutes

The localeRoutes feature in Nuxt I18n Micro allows you to define custom routes for specific locales, offering flexibility and control over the routing structure of your application. This feature is particularly useful when certain locales require different URL structures, tailored paths, or need to follow specific regional or linguistic conventions.

🚀 Primary Use Case of localeRoutes

The primary use case for localeRoutes is to provide distinct routes for different locales, enhancing the user experience by ensuring URLs are intuitive and relevant to the target audience. For example, you might have different paths for English and Russian versions of a page, where the Russian locale follows a localized URL format.

📄 Example: Defining localeRoutes in $defineI18nRoute

Here’s an example of how you might define custom routes for specific locales using localeRoutes in your $defineI18nRoute function:

typescript
$defineI18nRoute({
+  localeRoutes: {
+    ru: '/localesubpage', // Custom route path for the Russian locale
+    de: '/lokaleseite',   // Custom route path for the German locale
+  },
+})

🔄 How localeRoutes Work

  • Default Behavior: Without localeRoutes, all locales use a common route structure defined by the primary path.
  • Custom Behavior: With localeRoutes, specific locales can have their own routes, overriding the default path with locale-specific routes defined in the configuration.

🌱 Use Cases for localeRoutes

📄 Example: Using localeRoutes in a Page

Here’s a simple Vue component demonstrating the use of $defineI18nRoute with localeRoutes:

vue
<template>
+  <div>
+    <!-- Display greeting message based on the current locale -->
+    <p>{{ $t('greeting') }}</p>
+
+    <!-- Navigation links -->
+    <div>
+      <NuxtLink :to="$localeRoute({ name: 'index' })">
+        Go to Index
+      </NuxtLink>
+      |
+      <NuxtLink :to="$localeRoute({ name: 'about' })">
+        Go to About Page
+      </NuxtLink>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useNuxtApp } from '#imports'
+
+const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t, $defineI18nRoute } = useNuxtApp()
+
+// Define translations and custom routes for specific locales
+$defineI18nRoute({
+  localeRoutes: {
+    ru: '/localesubpage', // Custom route path for Russian locale
+  },
+})
+</script>

🛠️ Using localeRoutes in Different Contexts

  • Landing Pages: Use custom routes to localize URLs for landing pages, ensuring they align with marketing campaigns.
  • Documentation Sites: Provide distinct routes for each locale to better match the localized content structure.
  • E-commerce Sites: Tailor product or category URLs per locale for improved SEO and user experience.

📝 Best Practices for Using localeRoutes

  • 🚀 Use for Relevant Locales: Apply localeRoutes primarily where the URL structure significantly impacts the user experience or SEO. Avoid overuse for minor differences.
  • 🔧 Maintain Consistency: Keep a consistent routing pattern across locales unless there's a strong reason to deviate. This approach helps in maintaining clarity and reducing complexity.
  • 📚 Document Custom Routes: Clearly document any custom routes you define with localeRoutes, especially in modular applications, to ensure team members understand the routing logic.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/devtools.html b/guide/devtools.html new file mode 100644 index 00000000..c84015e1 --- /dev/null +++ b/guide/devtools.html @@ -0,0 +1,25 @@ + + + + + + 🛠️ DevTools in nuxt-i18n-micro | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🛠️ DevTools in nuxt-i18n-micro

📖 What Is Nuxt DevTools?

DevTools is a powerful development assistant seamlessly integrated into the nuxt-i18n-micro module. It provides an intuitive interface for managing localization and translation tasks, making your workflow faster and more efficient. Designed for developers who value convenience, Nuxt DevTools bridges the gap between coding and runtime management.

DevTools

🌟 Key Features of DevTools in nuxt-i18n-micro

1. Locale Management

Effortlessly browse, select, and manage locales in your application. Whether you’re working with a single language or multiple, DevTools provides a centralized hub for handling all localization settings.

2. Translation Editing

Edit translation files directly through an integrated JSON editor. This eliminates the need for external tools, allowing real-time updates and changes without interrupting your workflow.

3. File Import and Export

Simplify the process of managing translation files:

  • Export: Save translations as a JSON file for backups or external use.
  • Import: Load updated translation files into the project to keep content up-to-date.

4. Real-Time Previews

View changes immediately within the development environment. This feature ensures translations and configurations are accurate before going live.

5. Seamless Nuxt Integration

DevTools works natively with nuxt-i18n-micro, enhancing its capabilities without requiring additional setup. It adapts to your localization needs while maintaining Nuxt's modular and flexible structure.


🛠️ Why Use DevTools?

Nuxt DevTools is an indispensable addition for projects requiring localization. It helps developers by:

  • Saving Time: Automates repetitive tasks like file management and format validation.
  • Reducing Errors: Provides a safe, intuitive environment for editing translations.
  • Improving Collaboration: Enables non-developers to manage translations easily.
  • Streamlining Workflows: Consolidates multiple localization tasks into a single interface.

🚀 Take Control of Localization

With Nuxt DevTools integrated into nuxt-i18n-micro, managing multilingual applications becomes straightforward and efficient. Whether you're fine-tuning translations or adding new locales, DevTools equips you with the tools needed to deliver polished, user-friendly experiences.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/faq.html b/guide/faq.html new file mode 100644 index 00000000..4aaaaf90 --- /dev/null +++ b/guide/faq.html @@ -0,0 +1,55 @@ + + + + + + FAQ: Common Issues & Solutions | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

FAQ: Common Issues & Solutions

❓ What if a route doesn't load?

When using Nuxt I18n Micro, certain routes might not load as expected, especially if the router doesn't automatically assign a name to a route in subfolders.

Solution: To address this, manually define the route name for the page by adding the following to the corresponding Vue file:

javascript
definePageMeta({ name: 'pageName' })

This ensures the route is properly registered, enabling seamless navigation within the application.


❓ Why is the assets/_locales/ folder added to the server folder?

During deployment, especially on platforms like Netlify, the build process might differ from local development. This can lead to issues where certain files or folders are missing during server-side rendering (SSR).

Explanation:

  • Build Process: Translation files are cached in the production folder during the build. However, on Netlify, server code moves to functions, sometimes isolating localization files.
  • Prerendering: Prerendering does not work with $fetch in SSR, causing middleware to miss localization files.
  • Server Assets: To resolve this, localization files are saved in the Nitro server assets during prerendering. They are then accessible in production directly from server assets.

❓ Is Nuxt I18n Micro inspired by vue-i18n? What about modifiers?

While Nuxt I18n Micro serves as a performance alternative to nuxt-i18n, it’s built independently of vue-i18n. While some method names and parameters may be similar, the underlying functionality differs significantly.

Modifiers: The maintainer initially considered modifiers, but concluded that components like <i18n-t> and <i18n-link> effectively address those needs.

For example:

vue
<template>
+  <i18n-t keypath="feedback.text">
+    <template #link>
+      <nuxt-link :to="{ name: 'index' }">
+        <i18n-t keypath="feedback.link" />
+      </nuxt-link>
+    </template>
+  </i18n-t>
+</template>

This approach is flexible, so releasing modifiers is currently unnecessary. However, modifiers may be added in future releases if there is demand.


Yes, Nuxt I18n Micro allows the use of NuxtLink or i18nLink within translations through the <i18n-t> component, which is especially helpful for handling grammar and RTL language requirements without splitting translation strings.

Example:

Translation file:

json
{
+  "example": "Share your {link} with friends",
+  "link_text": "translation link"
+}

Vue template:

vue
<template>
+  <i18n-t keypath="example">
+    <template #link>
+      <nuxt-link :to="{ name: 'referral' }">
+        <i18n-t keypath="link_text" />
+      </nuxt-link>
+    </template>
+  </i18n-t>
+</template>

This allows dynamic links within translations while preserving proper localization structure.


❓ Why are translation keys not resolving during SSR on Vercel, and how can I fix the locale path issue?

$fetch limitations on SSR

On serverless platforms like Vercel, $fetch can only fetch static files from the CDN and not from the internal Nitro server. This means static translation files may not be directly accessible unless the correct base URL is set.

Fix by setting apiBaseUrl

If translations are hosted externally, specify the full URL (e.g., https://example.com/_locales) for $fetch to access the translations correctly during SSR.

Example:

js
{
+  // ...
+  apiBaseUrl: 'https://example.com/_locales'
+  // ...
+}

❓ Why does $t or other i18n composables not work in Nuxt plugins?

Nuxt I18n composables ($t, $getLocale, $localePath, etc.) may not work as expected within Nuxt plugins or utility functions, resulting in runtime errors.

Cause and Solution: Nuxt composables require specific contexts (e.g., Nuxt hooks or Vue setup functions) to access the Nuxt instance. If used outside of these contexts (e.g., in utility functions or plugins), the following error might appear in the console:

[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables

Solution 1: Use runWithContext To call i18n composables after an asynchronous operation, use runWithContext to preserve the necessary context.

Example:

javascript
await nuxtApp.runWithContext(() => $t('test_key'))

Solution 2: Retrieve Value First Alternatively, retrieve the translation value first, then pass it to a utility function.

Example:

javascript
const val = nuxtApp.$t('common.errors.unknown.title')
+showError({
+    title: val
+})

Solution 3: Pass Translation Keys in Services In services or utility functions, pass the translation keys instead of using $t directly. Then, fetch the translation in the component.

Example:

javascript
showError({
+  title: 'common.errors.unknown.title',
+  message: 'common.errors.unknown.message',
+  i18n: true
+})

These solutions help maintain context and reduce errors, allowing for flexibility in handling translations across the application.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/folder-structure.html b/guide/folder-structure.html new file mode 100644 index 00000000..151d3803 --- /dev/null +++ b/guide/folder-structure.html @@ -0,0 +1,68 @@ + + + + + + 📂 Folder Structure Guide | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

📂 Folder Structure Guide

📖 Introduction

Organizing your translation files effectively is essential for maintaining a scalable and efficient internationalization (i18n) system. Nuxt I18n Micro simplifies this process by offering a clear approach to managing global and page-specific translations. This guide will walk you through the recommended folder structure and explain how Nuxt I18n Micro handles these translations.

Nuxt I18n Micro organizes translations into global files and page-specific files within the pages directory. This ensures that only the necessary translation data is loaded when required, optimizing both performance and organization.

🔧 Basic Structure

Here’s a basic example of the folder structure you should follow:

plaintext
  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json

📄 Explanation of Structure

1. 🌍 Global Translation Files

  • Path: /locales/{locale}.json (e.g., /locales/en.json)

  • Purpose: These files contain translations that are shared across the entire application. This is useful for common elements like navigation menus, headers, footers, or any text that appears on multiple pages.

    Example Content (/locales/en.json):

    json
    {
    +  "menu": {
    +    "home": "Home",
    +    "about": "About Us",
    +    "contact": "Contact"
    +  },
    +  "footer": {
    +    "copyright": "© 2024 Your Company"
    +  }
    +}

2. 📄 Page-Specific Translation Files

  • Path: /locales/pages/{routeName}/{locale}.json (e.g., /locales/pages/index/en.json)

  • Purpose: These files are used for translations that are specific to individual pages. This allows you to load only the necessary translations when a user visits a particular page, which enhances performance by reducing the amount of data that needs to be loaded.

    Example Content (/locales/pages/index/en.json):

    json
    {
    +  "title": "Welcome to Our Website",
    +  "description": "We offer a wide range of products and services to meet your needs."
    +}

    Example Content (/locales/pages/about/en.json):

    json
    {
    +  "title": "About Us",
    +  "description": "Learn more about our mission, vision, and values."
    +}

📂 Handling Dynamic Routes and Nested Paths

Nuxt I18n Micro automatically transforms dynamic segments and nested paths in routes into a flat folder structure using a specific renaming convention. This ensures that all translations are stored in a consistent and easily accessible manner.

Dynamic Route Translation Folder Structure

When dealing with dynamic routes, such as /products/[id], the module converts the dynamic segment [id] into a static format within the file structure.

Example Folder Structure for Dynamic Routes:

For a route like /products/[id], the translation files would be stored in a folder named products-id:

plaintext
  /locales/pages
+  ├── /products-id
+  │   ├── en.json
+  │   ├── fr.json
+  │   └── ar.json

Example Folder Structure for Nested Dynamic Routes:

For a nested route like /products/key/[id], the translation files would be stored in a folder named products-key-id:

plaintext
  /locales/pages
+  ├── /products-key-id
+  │   ├── en.json
+  │   ├── fr.json
+  │   └── ar.json

Example Folder Structure for Multi-Level Nested Routes:

For a more complex nested route like /products/category/[id]/details, the translation files would be stored in a folder named products-category-id-details:

plaintext
  /locales/pages
+  ├── /products-category-id-details
+  │   ├── en.json
+  │   ├── fr.json
+  │   └── ar.json

🛠 Customizing the Directory Structure

If you prefer to store translations in a different directory, Nuxt I18n Micro allows you to customize the directory where translation files are stored. You can configure this in your nuxt.config.ts file.

Example: Customizing the Translation Directory

typescript
export default defineNuxtConfig({
+  i18n: {
+    translationDir: 'i18n' // Custom directory path
+  }
+})

This will instruct Nuxt I18n Micro to look for translation files in the /i18n directory instead of the default /locales directory.

⚙️ How Translations are Loaded

🌍 Dynamic Locale Routes

Nuxt I18n Micro uses dynamic locale routes to load translations efficiently. When a user visits a page, the module determines the appropriate locale and loads the corresponding translation files based on the current route and locale.

For example:

  • Visiting /en/index will load translations from /locales/pages/index/en.json.
  • Visiting /fr/about will load translations from /locales/pages/about/fr.json.

This method ensures that only the necessary translations are loaded, optimizing both server load and client-side performance.

💾 Caching and Pre-rendering

To further enhance performance, Nuxt I18n Micro supports caching and pre-rendering of translation files:

  • Caching: Once a translation file is loaded, it’s cached for subsequent requests, reducing the need to repeatedly fetch the same data.
  • Pre-rendering: During the build process, you can pre-render translation files for all configured locales and routes, allowing them to be served directly from the server without runtime delays.

📝 Best Practices

📂 Use Page-Specific Files Wisely

Leverage page-specific files to avoid bloating global translation files. This keeps each page’s translations lean and fast to load, which is especially important for pages with complex or large content.

🔑 Keep Translation Keys Consistent

Use consistent naming conventions for your translation keys across files. This helps maintain clarity and prevents issues when managing translations, especially as your application grows.

🗂️ Organize Translations by Context

Group related translations together within your files. For example, group all button labels under a buttons key and all form-related texts under a forms key. This not only improves readability but also makes it easier to manage translations across different locales.

🧹 Regularly Clean Up Unused Translations

Over time, your application might accumulate unused translation keys, especially if features are removed or restructured. Periodically review and clean up your translation files to keep them lean and maintainable.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/getting-started.html b/guide/getting-started.html new file mode 100644 index 00000000..e31ea568 --- /dev/null +++ b/guide/getting-started.html @@ -0,0 +1,98 @@ + + + + + + 🌐 Getting Started with Nuxt I18n Micro | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🌐 Getting Started with Nuxt I18n Micro

📖 Overview

Nuxt I18n Micro is a lightweight internationalization module for Nuxt that delivers superior performance compared to traditional solutions. It's designed to reduce build times, memory usage, and server load, making it ideal for high-traffic and large projects.

🤔 Why Choose Nuxt I18n Micro?

Here are some key benefits of using Nuxt I18n Micro:

  • 🚀 High Performance: Significantly reduces build times and memory consumption.
  • 📦 Compact Size: Has minimal impact on your app's bundle size.
  • ⚙️ Efficiency: Optimized for large-scale applications with a focus on memory consumption and server load.

🛠 Installation

To install the module in your Nuxt application, run the following command:

bash
npm install nuxt-i18n-micro

⚙️ Basic Setup

After installation, add the module to your nuxt.config.ts file:

typescript
export default defineNuxtConfig({
+  modules: [
+    'nuxt-i18n-micro',
+  ],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

📂 Folder Structure

Translation files are organized into global and page-specific directories:

  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json
  • Global Files: Contain translations shared across the entire app.
  • Page-Specific Files: Contain translations unique to specific pages.

⚙️ Module Configuration Options

The Nuxt I18n Micro module provides a range of customizable options to fine-tune your internationalization setup:

Here’s the updated documentation for locales, including the new baseUrl and baseDefault properties:

🌍 locales

Defines the locales available in your application.

Type: Locale[]

Each locale object can include the following properties:

  • code (string, required): A unique identifier for the locale, e.g., 'en' for English.
  • iso (string, optional): The ISO code for the locale, such as 'en-US'. This can be used for the lang attribute in HTML to help with accessibility and SEO.
  • dir (string, optional): Specifies the text direction for the locale, either 'ltr' (left-to-right) or 'rtl' (right-to-left).
  • disabled (boolean, optional): Disables the locale in the dropdown if set to true, preventing users from selecting it.
  • baseUrl (string, optional): Sets a base URL for the locale, which should be used to configure redirection for locale-specific domains or subdomains. The actual redirection implementation should be handled in layers outside of this configuration, as setting baseUrl alone means all links within the project will direct to the specified domain. Additionally, this parameter requires an explicit protocol, either http or https.
  • baseDefault (boolean, optional): If set to true, the locale's routes do not include the locale code in the URL path, making it the default locale.

Example:

typescript
locales: [
+  { code: 'en', iso: 'en-US', dir: 'ltr' },
+  { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+  { code: 'ar', iso: 'ar-SA', dir: 'rtl', disabled: true },
+  { code: 'de', iso: 'de-DE', dir: 'ltr', baseUrl: 'https://de.example.com', baseDefault: true },
+  { code: 'es', iso: 'es-ES', dir: 'ltr', baseUrl: 'https://es.example.com', baseDefault: true },
+  { code: 'ja', iso: 'ja-JP', dir: 'ltr', baseUrl: 'https://new.example.com' }
+]

In this example:

  • The ar locale is disabled.
  • de and es each have their own baseUrl and baseDefault, meaning routes for these locales will start with their respective URLs (https://de.example.com, https://es.example.com).
  • ja each have their own baseUrl, meaning routes for these locales will start with their respective URLs (https://new.example.com/ja).

Additional Notes:

  • If baseUrl is provided, it will override the default routing structure, adding the baseUrl prefix to all routes for that locale. However, using baseUrl is generally not recommended, as it can lead to duplication of all internal routes as external links, complicating routing and maintenance. Instead, it is often simpler and more manageable to create external links directly for specific locales.
  • When baseDefault is set to true, the specified locale's URLs will not include the locale code prefix, making it appear as the primary or default language. Note that baseDefault works only in combination with baseUrl.

🌐 defaultLocale

Sets the default locale if no specific locale is selected by the user.

Type: string

Example:

typescript
defaultLocale: 'en'

🗂 translationDir

Specifies the directory where translation files are stored.

Type: string
Default: 'locales'

Example:

typescript
translationDir: 'i18n' // Custom directory for translation files

🔍 meta

Automatically generates SEO-related meta tags, such as alternate links for different locales.

Type: boolean
Default: true

Example:

typescript
meta: true // Enable automatic SEO meta tags generation

🐛 debug

Enables logging and debugging information during the generation process to help with troubleshooting.

Type: boolean
Default: false

Example:

typescript
debug: true // Enable logging and debugging information

🐛 types

Adds types to the project during the postinstall process. If you encounter issues with types, you can disable this option.

Type: boolean
Default: true

Example:

typescript
types: true

🔗 metaBaseUrl

Sets the base URL for generating SEO-related meta tags like canonical and alternate URLs.

Type: string
Default: '/'

Example:

typescript
metaBaseUrl: 'https://example.com' // Custom base URL for meta tags

🌍 autoDetectLanguage

Automatically detects the user's preferred language based on browser settings and redirects to the appropriate locale.

Type: boolean
Default: false

Example:

typescript
autoDetectLanguage: true // Enable automatic language detection and redirection

🔍 autoDetectPath

Specifies the route path(s) on which locale auto-detection and switching should occur.

Type: string
Default: "/"

Description:
Defines the route(s) where locale detection is active. By default, locale detection happens only on the home route ("/").

Setting this to "*" enables locale detection on all routes. However, using "*" may cause unexpected issues, especially if cookies are disabled, as this can interfere with tracking the user's locale preference.

🔢 plural

Custom function for handling pluralization in translations based on count and locale.

Type: (key: string, count: number, params: Record<string, string | number | boolean>, locale: string, t: Getter) => string

Example:

typescript
export type Getter = (key: string, params?: Record<string, string | number | boolean>, defaultValue?: string) => unknown
+
+{
+  plural: (key: string, count: number, _params: Record<string, string | number | boolean>, _locale: string, t: Getter) => {
+    const translation = t(key)
+    if (!translation) {
+      return key
+    }
+    const forms = translation.toString().split('|')
+    return (count < forms.length ? forms[count].trim() : forms[forms.length - 1].trim()).replace('{count}', count.toString())
+  }
+}

🚦 includeDefaultLocaleRoute

(Deprecated)

Automatically redirects routes without a locale prefix to the default locale.

Type: boolean
Default: false

Deprecated: As of version 1.50.0, includeDefaultLocaleRoute is deprecated. Use the strategy option instead for more flexible route handling.

🚦 strategy

Version introduced: v1.50.0

Defines how locale prefixes should be handled in routes. Choose the strategy that best fits your use case.

Type: string
Default: prefix_and_default

Available Strategies:

  • no_prefix
    Routes will not have a locale prefix. The locale will be detected and changed without modifying the URL. Locale detection relies on the browser and cookies, and you need to manage locale switching through the i18n API.
    Note: This strategy does not support features like Custom paths or Ignore routes.

  • prefix_except_default
    A locale prefix will be added to all routes, except for the default language. URLs for the default language will not include a prefix.

  • prefix
    All routes will include a locale prefix, regardless of the language.

  • prefix_and_default
    Combines both previous behaviors. URLs for every language will have a locale prefix, while URLs for the default language will have a non-prefixed version. However, if detectBrowserLanguage is enabled, the prefixed version will be preferred for the default language.

🚦 customRegexMatcher

I18n-micro meticulously checks each locale via vue-router route regex. If you have a lot of locales, you can improve pattern matching performances via a custom regex matcher.

Type: string | RegExp
Default: false

Example:

typescript
customRegexMatcher: '[a-z]-[A-Z]'// This matches locales in isoCode (e.g: '/en-US', 'de-DE' etc)

Creates links between different pages' locale files to share translations, reducing duplication.

Type: Record<string, string>

Example:

typescript
{
+  routesLocaleLinks: {
+    'products-id': 'products', 
+    'about-us': 'about'
+  }
+}

🧩 define

Enables or disables the addition of a special define plugin that allows you to use Nuxt's runtime configuration for overriding settings in your translation files.

Type: boolean
Default: true

Example:

typescript
define: false // Disable the define plugin

🧩 plugin

Enables or disables a special plugin that integrates additional features or functionality into your Nuxt application.

Type: boolean
Default: true

Example:

typescript
plugin: false // Disable the plugin

🔄 disablePageLocales

Allows you to disable page-specific translations, limiting the module to only use global translation files.

Type: boolean
Default: false

Example:

typescript
disablePageLocales: true // Disable page-specific translations, using only global translations

📂 Folder Structure with disablePageLocales: true

When disablePageLocales is enabled, the module will only use the translations defined in the global files located directly under the locales directory. Page-specific translation files (located in /locales/pages) will be ignored.

  /locales
+  ├── en.json
+  ├── fr.json
+  └── ar.json

👀 disableWatcher

Disables the automatic creation of locale files during development.

Type: boolean
Default: false

Example:

typescript
disableWatcher: true // Disables the automatic creation of locale files

👀 disableUpdater

Version introduced: v1.60.0

Disables the file watcher for updating store items during development.

Type: boolean
Default: false

Example:

typescript
disableUpdater: true // Disables the file watcher for updating store items

🔗 apiBaseUrl

env: NUXT_I18N_APP_BASE_URL

Defines the base URL that the server will use to fetch cached translations. By default, this is set to _locales, but you can change it to any custom path, such as api/_locales, if you want to load translations from a different endpoint.

Type: string
Default: '_locales'

Example:

typescript
apiBaseUrl: 'api/_locales' // Custom URL for fetching cached translations

When set, the module will use the specified URL to request cached translations instead of using the default _locales.

🍪 localeCookie

Specifies the name of the cookie used to store the user's selected locale.

Type: string
Default: 'user-locale'

🌐 fallbackLocale

Specifies a fallback locale to be used when the current locale does not have a specific translation available.

Type: string | undefined
Default: undefined

Example:

typescript
{
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'es', iso: 'es-ES', dir: 'ltr' }
+    ],
+    defaultLocale: 'en',
+    // Use English as a fallback locale
+    fallbackLocale: 'en'
+  }
+}

🌐 globalLocaleRoutes

Allows you to define custom localized routes for specific pages. You can specify a custom path for each locale for a given page, or disable localization for certain pages entirely.

Type: Record<string, Record<string, string> | false>

  • Key (string): The name of the page you want to customize or disable localization for.
  • Value:
    • Record<string, string>: A set of locale codes with corresponding custom paths for the page.
    • false: Disable localization for this page entirely. The page will not be localized, and it will remain accessible only through its default path.

This option gives you the flexibility to localize certain pages differently while leaving others unaffected by localization.

Example:

typescript
{
+  globalLocaleRoutes: {
+    page2: {
+      en: '/custom-page2-en',
+        de: '/custom-page2-de',
+        ru: '/custom-page2-ru'
+    },
+    // Unlocalized page should not be localized
+    unlocalized: false
+  }
+}

Usage:

In the example above:

  • page2: Custom localized paths are defined for the page page2 in English (en), German (de), and Russian (ru). Instead of following the standard localization pattern (like /en/page2), each locale will have a completely custom URL, such as /en/custom-page2-en for English, /de/custom-page2-de for German, and /ru/custom-page2-ru for Russian.
  • unlocalized: This page will not be localized, so it remains accessible only at /unlocalized, without any locale prefixes or custom paths.

🔄 Caching Mechanism

One of the standout features of Nuxt I18n Micro is its intelligent caching system. When a translation is requested during server-side rendering (SSR), the result is stored in a cache. This means that subsequent requests for the same translation can

retrieve the data from the cache rather than searching through the translation files again. This caching mechanism drastically reduces the time needed to fetch translations and significantly lowers the server's resource consumption.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/layers.html b/guide/layers.html new file mode 100644 index 00000000..2fc304d6 --- /dev/null +++ b/guide/layers.html @@ -0,0 +1,96 @@ + + + + + + 🗂️ Layers in Nuxt I18n Micro | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🗂️ Layers in Nuxt I18n Micro

📖 Introduction to Layers

Layers in Nuxt I18n Micro allow you to manage and customize localization settings flexibly across different parts of your application. By defining different layers, you can adjust the configuration for various contexts, such as overriding settings for specific sections of your site or creating reusable base configurations that can be extended by other parts of your application.

🛠️ Primary Configuration Layer

The Primary Configuration Layer is where you set up the default localization settings for your entire application. This layer is essential as it defines the global configuration, including the supported locales, default language, and other critical i18n settings.

📄 Example: Defining the Primary Configuration Layer

Here’s an example of how you might define the primary configuration layer in your nuxt.config.ts file:

typescript
export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en', // The default locale for the entire app
+    translationDir: 'locales', // Directory where translations are stored
+    meta: true, // Automatically generate SEO-related meta tags like `alternate`
+    autoDetectLanguage: true, // Automatically detect and use the user's preferred language
+  },
+})

🌱 Child Layers

Child layers are used to extend or override the primary configuration for specific parts of your application. For instance, you might want to add additional locales or modify the default locale for a particular section of your site. Child layers are especially useful in modular applications where different parts of the application might have different localization requirements.

📄 Example: Extending the Primary Layer in a Child Layer

Suppose you have a section of your site that needs to support additional locales, or you want to disable a particular locale in a certain context. Here’s how you can achieve that by extending the primary configuration layer:

typescript
// basic/nuxt.config.ts (Primary Layer)
+export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    meta: true,
+    translationDir: 'locales',
+  },
+})
typescript
// extended/nuxt.config.ts (Child Layer)
+export default defineNuxtConfig({
+  extends: '../basic', // Inherit the base configuration from the 'basic' layer
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' }, // Inherited from the base layer
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Inherited from the base layer
+      { code: 'de', iso: 'de-DE', dir: 'ltr' }, // Added in the child layer
+    ],
+    defaultLocale: 'fr', // Override the default locale to French for this section
+    autoDetectLanguage: false, // Disable automatic language detection in this section
+  },
+})

🌐 Using Layers in a Modular Application

In a larger, modular Nuxt application, you might have multiple sections, each requiring its own i18n settings. By leveraging layers, you can maintain a clean and scalable configuration structure.

📄 Example: Layered Configuration in a Modular Application

Imagine you have an e-commerce site with distinct sections like the main website, admin panel, and customer support portal. Each section might need a different set of locales or other i18n settings.

Primary Layer (Global Configuration):

typescript
// nuxt.config.ts
+export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    meta: true,
+    translationDir: 'locales',
+    autoDetectLanguage: true,
+  },
+})

Child Layer for Admin Panel:

typescript
// admin/nuxt.config.ts
+export default defineNuxtConfig({
+  extends: '../nuxt.config', // Inherit the global settings
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' }, // Inherited
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Inherited
+      { code: 'es', iso: 'es-ES', dir: 'ltr' }, // Specific to the admin panel
+    ],
+    defaultLocale: 'en',
+    meta: false, // Disable automatic meta generation in the admin panel
+  },
+})

Child Layer for Customer Support Portal:

typescript
// support/nuxt.config.ts
+export default defineNuxtConfig({
+  extends: '../nuxt.config', // Inherit the global settings
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-EN', dir: 'ltr' }, // Inherited
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Inherited
+      { code: 'de', iso: 'de-DE', dir: 'ltr' }, // Specific to the support portal
+    ],
+    defaultLocale: 'de', // Default to German in the support portal
+    autoDetectLanguage: false, // Disable automatic language detection
+  },
+})

In this modular example:

  • Each section (admin, support) has its own i18n settings, but they all inherit the base configuration.
  • The admin panel adds Spanish (es) as a locale and disables meta tag generation.
  • The support portal adds German (de) as a locale and defaults to German for the user interface.

📝 Best Practices for Using Layers

  • 🔧 Keep the Primary Layer Simple: The primary layer should contain the most commonly used settings that apply globally across your application. Keep it straightforward to ensure consistency.
  • ⚙️ Use Child Layers for Specific Customizations: Only override or extend settings in child layers when necessary. This approach avoids unnecessary complexity in your configuration.
  • 📚 Document Your Layers: Clearly document the purpose and specifics of each layer in your project. This will help maintain clarity and make it easier for others (or future you) to understand the configuration.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/migration.html b/guide/migration.html new file mode 100644 index 00000000..c00d0a07 --- /dev/null +++ b/guide/migration.html @@ -0,0 +1,60 @@ + + + + + + 🔄 Migration from nuxt-i18n to Nuxt I18n Micro | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🔄 Migration from nuxt-i18n to Nuxt I18n Micro

📖 Introduction

Migrating from nuxt-i18n to Nuxt I18n Micro can significantly improve the performance of your Nuxt application, especially in high-traffic environments or projects with large translation files. This guide provides a step-by-step approach to help you smoothly transition from nuxt-i18n to Nuxt I18n Micro.

🚀 Why Migrate?

The Nuxt I18n Micro module offers several advantages over the traditional nuxt-i18n:

  • ⚡ Improved Performance: Faster build times, lower memory usage, and smaller bundle sizes.
  • 🔧 Simplified Configuration: A more streamlined setup process with fewer moving parts.
  • 📉 Better Resource Management: Optimized handling of large translation files and reduced server load.

🔍 Key Differences

Before you begin the migration process, it’s essential to understand the key differences between nuxt-i18n and Nuxt I18n Micro:

  • 🌐 Route Management: Nuxt I18n Micro uses dynamic regex-based routing, generating only two routes regardless of the number of locales, unlike nuxt-i18n which creates a separate route for each locale.
  • 🗂️ Translation Files: Only JSON files are supported in Nuxt I18n Micro. The translations are split into global and page-specific files, which are auto-generated in development mode if not present.
  • 📈 SEO Integration: Nuxt I18n Micro offers built-in SEO optimization with automatic meta tag generation and support for hreflang tags.

🛠️ Step-by-Step Migration

1. 🛠️ Install Nuxt I18n Micro

First, add Nuxt I18n Micro to your Nuxt project:

bash
npm install nuxt-i18n-micro

2. 🔄 Update Configuration

Replace your existing nuxt-i18n configuration in nuxt.config.ts with the Nuxt I18n Micro configuration. Here’s an example:

Before (nuxt-i18n):

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US' },
+      { code: 'fr', iso: 'fr-FR' },
+    ],
+    defaultLocale: 'en',
+    vueI18n: './i18n.config.js',
+  },
+})

After (Nuxt I18n Micro):

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n-micro'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

3. 🗂️ Reorganize Translation Files

Move your translation files to the locales directory. Ensure they are in JSON format and organized by locale. For example:

plaintext
  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json

If you are using <nuxt-link> for navigation, replace it with <NuxtLink> to ensure compatibility with the new module.

Before:

vue
<nuxt-link :to="{ name: 'index' }">Home</nuxt-link>

After:

vue
<NuxtLink :to="$localeRoute({ name: 'index' })">Home</NuxtLink>
+<!-- or -->
+<i18n-link :to="{ name: 'index' }">Home</i18n-link>

5. 🛠️ Handle SEO Configurations

Ensure that your SEO configurations are updated to take advantage of Nuxt I18n Micro’s automatic meta tag generation. Remove any redundant SEO configurations that were specific to nuxt-i18n.

6. 🧪 Test Your Application

After completing the migration steps, thoroughly test your application to ensure that all translations are loading correctly and that navigation between locales works as expected. Pay special attention to SEO-related tags and ensure that they are generated as intended.

🛡️ Common Issues and Troubleshooting

❌ Translation Files Not Loading

Ensure that your translation files are in the correct directory and follow the JSON format. Also, confirm that the translationDir option in your configuration matches the location of your translation files.

⚠️ Route Not Found Errors

Check that the routes are correctly set up in your application and that the locales array in the configuration includes all necessary locale codes.

🏷️ Missing SEO Tags

If SEO tags are not being generated, verify that the meta option is enabled in your configuration and that each locale has a valid iso code.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/multi-domain-locales.html b/guide/multi-domain-locales.html new file mode 100644 index 00000000..a6afbc41 --- /dev/null +++ b/guide/multi-domain-locales.html @@ -0,0 +1,69 @@ + + + + + + 🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🌍 Setting Up Multi-Domain Locales with Nuxt I18n Micro Using Layers

📝 Introduction

By leveraging layers in Nuxt I18n Micro, you can create a flexible and maintainable multi-domain localization setup. This approach not only simplifies domain management by eliminating the need for complex functionalities but also allows for efficient load distribution and reduced project complexity. By running separate projects for different locales, your application can easily scale and adapt to varying locale requirements across multiple domains, offering a robust and scalable solution for global applications.

🎯 Objective

To create a setup where different domains serve specific locales by customizing configurations in child layers. This method leverages Nuxt's layering system, allowing you to maintain a base configuration while extending or modifying it for each domain.

🛠 Steps to Implement Multi-Domain Locales

1. Create the Base Layer

Start by creating a base configuration layer that includes all the common locale settings for your application. This configuration will serve as the foundation for other domain-specific configurations.

Base Layer Configuration

Create the base configuration file base/nuxt.config.ts:

typescript
// base/nuxt.config.ts
+
+export default defineNuxtConfig({
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'de', iso: 'de-DE', dir: 'ltr' },
+      { code: 'es', iso: 'es-ES', dir: 'ltr' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+    autoDetectLanguage: true,
+  },
+})

2. Create Domain-Specific Child Layers

For each domain, create a child layer that modifies the base configuration to meet the specific requirements of that domain. You can disable locales that are not needed for a specific domain.

Example: Configuration for the French Domain

Create a child layer configuration for the French domain in fr/nuxt.config.ts:

typescript
// fr/nuxt.config.ts
+
+export default defineNuxtConfig({
+  extends: '../base', // Inherit from the base configuration
+
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr', disabled: true }, // Disable English
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' }, // Add and enable the French locale
+      { code: 'de', iso: 'de-DE', dir: 'ltr', disabled: true }, // Disable German
+      { code: 'es', iso: 'es-ES', dir: 'ltr', disabled: true }, // Disable Spanish
+    ],
+    defaultLocale: 'fr', // Set French as the default locale
+    autoDetectLanguage: false, // Disable automatic language detection
+  },
+})

Example: Configuration for the German Domain

Similarly, create a child layer configuration for the German domain in de/nuxt.config.ts:

typescript
// de/nuxt.config.ts
+
+export default defineNuxtConfig({
+  extends: '../base', // Inherit from the base configuration
+
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr', disabled: true }, // Disable English
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr', disabled: true }, // Disable French
+      { code: 'de', iso: 'de-DE', dir: 'ltr' }, // Use the German locale
+      { code: 'es', iso: 'es-ES', dir: 'ltr', disabled: true }, // Disable Spanish
+    ],
+    defaultLocale: 'de', // Set German as the default locale
+    autoDetectLanguage: false, // Disable automatic language detection
+  },
+})

3. Deploy the Application for Each Domain

Deploy the application with the appropriate configuration for each domain. For example:

  • Deploy the fr layer configuration to fr.example.com.
  • Deploy the de layer configuration to de.example.com.

4. Set Up Multiple Projects for Different Locales

For each locale and domain, you'll need to run a separate instance of the application. This ensures that each domain serves the correct locale configuration, optimizing the load distribution and simplifying the project's structure. By running multiple projects tailored to each locale, you can maintain a clean separation between configurations and reduce the complexity of the overall setup.

5. Configure Routing Based on Domain

Ensure that your routing is configured to direct users to the correct project based on the domain they are accessing. This will ensure that each domain serves the appropriate locale, enhancing user experience and maintaining consistency across different regions.

6. Deploy and Verify

After configuring the layers and deploying them to their respective domains, ensure each domain is serving the correct locale. Test the application thoroughly to confirm that the correct locale is loaded depending on the domain.

📝 Best Practices

  • Keep Base Configuration Generic: The base configuration should cover general settings applicable to all domains.
  • Isolate Domain-Specific Logic: Keep domain-specific configurations in their respective layers to maintain clarity and separation of concerns.

🎉 Conclusion

By leveraging layers in Nuxt I18n Micro, you can create a flexible and maintainable multi-domain localization setup. This approach not only eliminates the need for complex domain management functionalities but also allows you to distribute the load efficiently and reduce project complexity. Running separate projects for different locales ensures that your application can scale easily and adapt to different locale requirements across various domains, providing a robust and scalable solution for global applications.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/per-component-translations.html b/guide/per-component-translations.html new file mode 100644 index 00000000..a214c769 --- /dev/null +++ b/guide/per-component-translations.html @@ -0,0 +1,80 @@ + + + + + + 📖 Per-Component Translations in Nuxt I18n Micro | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

📖 Per-Component Translations in Nuxt I18n Micro

Overview

Per-Component Translations in Nuxt I18n Micro allows developers to define translations directly within specific components or pages of a Nuxt application using the $defineI18nRoute function. This approach is ideal for managing localized content that is unique to individual components, providing a more modular and maintainable method for handling translations.

$defineI18nRoute Function

The $defineI18nRoute function configures route behavior based on the current locale, offering a versatile solution to:

  • Control access to specific routes based on available locales.
  • Provide translations for specific locales.
  • Set custom routes for different locales.

Method Signature

typescript
$defineI18nRoute(routeDefinition: { 
+  locales?: string[] | Record<string, Record<string, TranslationObject>>, 
+  localeRoutes?: Record<string, string> 
+})

Parameters

  • locales: Defines which locales are available for the route. This can be:

    • An array of strings, where each string is an available locale (e.g., ['en', 'fr', 'de']).
    • An object where each key is a locale code, and the value is an object containing translations or an empty object if no translations are needed.
  • localeRoutes: Allows custom routes for specific locales. Each key represents a locale code, and the value is the custom route path for that locale. This is useful for scenarios where different locales require unique routing.

Example Usage

typescript
$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    ru: { greeting: 'Привет', farewell: 'До свидания' },
+    de: { greeting: 'Hallo', farewell: 'Auf Wiedersehen' },
+  },
+  localeRoutes: {
+    ru: '/localesubpage', // Custom route path for the Russian locale
+  },
+})

Use Cases

  1. Controlling Access Based on Locales: Define which locales are allowed for specific routes to ensure users only see content relevant to their language.

    typescript
    import { useNuxtApp } from '#imports'
    +
    +const { $defineI18nRoute } = useNuxtApp()
    +
    +$defineI18nRoute({
    +  locales: ['en', 'fr', 'de'] // Only these locales are allowed for this route
    +})
  2. Providing Translations for Locales: Use the locales object to provide specific translations for each route, enhancing the user experience by delivering content in the user's preferred language.

    typescript
    import { useNuxtApp } from '#imports'
    +
    +const { $defineI18nRoute } = useNuxtApp()
    +
    +$defineI18nRoute({
    +  locales: {
    +    en: { greeting: 'Hello', farewell: 'Goodbye' },
    +    fr: { greeting: 'Bonjour', farewell: 'Au revoir' },
    +    de: { greeting: 'Hallo', farewell: { aaa: { bbb: "Auf Wiedersehen" } } },
    +    ru: {} // Russian locale is allowed but no translations are provided
    +  }
    +})
  3. Custom Routing for Locales: Define custom paths for specific locales using the localeRoutes property. This allows you to create unique navigational flows or URL structures for different languages or regions.

Best Practices

  • Keep Translations Close to Components: Define translations directly within the relevant component to keep localized content organized and maintainable.
  • Use Locale Objects for Flexibility: Utilize the object format for the locales property when specific translations or access control based on locales are required.
  • Document Custom Routes: Clearly document any custom routes set for different locales to maintain clarity and simplify development and maintenance.

Here's an example of a Vue page using defineI18nRoute for per-component translations:

Example: Vue Page with Per-Component Translations

Below is an example of how to use $defineI18nRoute within a Vue component to handle translations and custom routing based on locale.

vue
<template>
+  <div>
+    <h1>{{ t('greeting') }}</h1>
+    <p>{{ t('farewell') }}</p>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useNuxtApp } from '#imports'
+
+// Access the $defineI18nRoute function from Nuxt's context
+const { $defineI18nRoute, $t: t } = useNuxtApp()
+
+// Define i18n route with translations for specific locales
+$defineI18nRoute({
+  locales: {
+    en: { greeting: 'Hello', farewell: 'Goodbye' },
+    fr: { greeting: 'Bonjour', farewell: 'Au revoir' },
+    de: { greeting: 'Hallo', farewell: 'Auf Wiedersehen' },
+    ru: { greeting: 'Привет', farewell: 'До свидания' },
+  },
+  localeRoutes: {
+    ru: '/ru-specific-path', // Custom route path for the Russian locale
+    fr: '/fr-specific-path'  // Custom route path for the French locale
+  }
+})
+</script>

Explanation

  • Component-Level Translations: The translations are defined directly in the component using the locales property of $defineI18nRoute. This keeps translations closely tied to the component, making them easy to manage and update.
  • Custom Routing: The localeRoutes property is used to set specific paths for different locales. This allows for unique navigational flows based on the user's language preference.

This setup enables the component to display localized greetings and farewells based on the current locale, and it also allows for custom routes tailored to specific locales, enhancing the user experience by delivering content in the preferred language and structure.

Summary

The Per-Component Translations feature, powered by the $defineI18nRoute function, offers a powerful and flexible way to manage localization within your Nuxt application. By allowing localized content and routing to be defined at the component level, it helps create a highly customized and user-friendly experience tailored to the language and regional preferences of your audience.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/performance-results.html b/guide/performance-results.html new file mode 100644 index 00000000..748911cc --- /dev/null +++ b/guide/performance-results.html @@ -0,0 +1,25 @@ + + + + + + Performance Test Results | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

Performance Test Results

Project Information

Description:

This performance test compares two implementations of internationalization: i18n-micro and i18n. The main focus of the test is to evaluate build times, memory usage, CPU usage, and the performance of the server under stress (e.g., how many requests can be handled and how efficiently). The i18n-micro implementation shows slightly lower overall script execution times. This difference is attributed to its ability to handle more requests, which requires additional time for processing.

Important Note:

It is essential to recognize that the example used in this test is not entirely representative of the intended usage pattern for i18n-micro. The example simplifies the translation structure by consolidating all translations into a single file. However, i18n-micro is optimized for scenarios where translations are organized on a per-page basis. This approach allows for more granular control and efficiency, particularly in large-scale applications. The current setup is used merely for demonstration purposes and may not fully showcase the potential performance benefits of i18n-micro in real-world applications.


Dependency Versions

DependencyVersion
nodev20.18.0
nuxt^3.15.2
nuxt-i18n-micro1.64.0
@nuxtjs/i18n^9.1.1

Build Performance for ./test/fixtures/i18n

  • Build Time: 20.12 seconds
  • Max CPU Usage: 187.00%
  • Min CPU Usage: 20.30%
  • Average CPU Usage: 98.24%
  • Max Memory Usage: 2819.25 MB
  • Min Memory Usage: 182.17 MB
  • Average Memory Usage: 1265.44 MB

Build Performance for ./test/fixtures/i18n-micro

  • Build Time: 7.55 seconds
  • Max CPU Usage: 239.10%
  • Min CPU Usage: 95.90%
  • Average CPU Usage: 174.60%
  • Max Memory Usage: 1155.53 MB
  • Min Memory Usage: 176.36 MB
  • Average Memory Usage: 618.83 MB

⏱️ Build Time and Resource Consumption

i18n v9
  • Build Time: 20.12 seconds
  • Max CPU Usage: 187.00%
  • Max Memory Usage: 2819.25 MB
i18n-micro
  • Build Time: 7.55 seconds
  • Max CPU Usage: 239.10%
  • Max Memory Usage: 1155.53 MB

Performance Comparison

  • i18n-micro: 7.55 seconds, Max Memory: 1155.53 MB, Max CPU: 239.10%
  • i18n v9: 20.12 seconds, Max Memory: 2819.25 MB, Max CPU: 187.00%
  • Time Difference: -12.57 seconds
  • Memory Difference: -1663.72 MB
  • CPU Usage Difference: 52.10%

Stress Test with Artillery for ./test/fixtures/i18n

  • Max CPU Usage: 174.50%
  • Min CPU Usage: 0.00%
  • Average CPU Usage: 129.58%
  • Max Memory Usage: 796.69 MB
  • Min Memory Usage: 48.44 MB
  • Average Memory Usage: 387.15 MB
  • Stress Test Time: 75.72 seconds
  • Average Response Time: 1547.10 ms
  • Min Response Time: 70.00 ms
  • Max Response Time: 9965.00 ms
  • Requests per Second: 73.00
  • Error Rate: 0.00%

i18n

Stress Test with Artillery for ./test/fixtures/i18n-micro

  • Max CPU Usage: 127.00%
  • Min CPU Usage: 0.00%
  • Average CPU Usage: 89.23%
  • Max Memory Usage: 355.58 MB
  • Min Memory Usage: 48.09 MB
  • Average Memory Usage: 291.41 MB
  • Stress Test Time: 68.11 seconds
  • Average Response Time: 422.90 ms
  • Min Response Time: 1.00 ms
  • Max Response Time: 3055.00 ms
  • Requests per Second: 291.00
  • Error Rate: 0.00%

i18n-micro

Comparison between i18n v9 and i18n-micro

  • Max Memory Used Difference: -441.11 MB
  • Min Memory Used Difference: -0.34 MB
  • Avg Memory Used Difference: -95.74 MB
  • Max CPU Usage Difference: -47.50%
  • Min CPU Usage Difference: 0.00%
  • Avg CPU Usage Difference: -40.34%
  • Stress Test Time Difference: 0.00 seconds
  • Average Response Time Difference: -1124.20 ms
  • Min Response Time Difference: -69.00 ms
  • Max Response Time Difference: -6910.00 ms
  • Requests Per Second Difference: 218.00
  • Error Rate Difference: 0.00%

📊 Detailed Performance Analysis

🔍 Test Logic Explanation

The performance tests conducted for Nuxt I18n Micro and nuxt-i18n v9 are designed to simulate real-world usage scenarios. Below is an overview of the key aspects of the test methodology:

  1. Build Time: Measures the time required to build the project, focusing on how efficiently each module handles large translation files.
  2. CPU Usage: Tracks the CPU load during the build and stress tests to assess the impact on server resources.
  3. Memory Usage: Monitors memory consumption to determine how each module manages memory, especially under high load.
  4. Stress Testing: Simulates a series of requests to evaluate the server's ability to handle concurrent traffic. The test is divided into two phases:
    • Warm-up Phase: Over 6 seconds, one request per second is sent to each of the specified URLs, with a maximum of 6 users, to ensure that the server is ready for the main test.
    • Main Test Phase: For 60 seconds, the server is subjected to 60 requests per second, spread across various endpoints, to measure response times, error rates, and overall throughput under load.

🛠 Why This Approach?

The chosen testing methodology is designed to reflect the scenarios that developers are likely to encounter in production environments. By focusing on build time, CPU and memory usage, and server performance under load, the tests provide a comprehensive view of how each module will perform in a large-scale, high-traffic application.

Nuxt I18n Micro is optimized for:

  • Faster Build Times: By reducing the overhead during the build process.
  • Lower Resource Consumption: Minimizing CPU and memory usage, making it suitable for resource-constrained environments.
  • Better Handling of Large Projects: With a focus on scalability, ensuring that applications remain responsive even as they grow.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/performance.html b/guide/performance.html new file mode 100644 index 00000000..739dd9de --- /dev/null +++ b/guide/performance.html @@ -0,0 +1,25 @@ + + + + + + 🚀 Performance Guide | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🚀 Performance Guide

📖 Introduction

Nuxt I18n Micro is designed with performance in mind, offering a significant improvement over traditional internationalization (i18n) modules like nuxt-i18n. This guide provides an in-depth look at the performance benefits of using Nuxt I18n Micro, and how it compares to other solutions.

🤔 Why Focus on Performance?

In large-scale projects and high-traffic environments, performance bottlenecks can lead to slow build times, increased memory usage, and poor server response times. These issues become more pronounced with complex i18n setups involving large translation files. Nuxt I18n Micro was built to address these challenges head-on by optimizing for speed, memory efficiency, and minimal impact on your application’s bundle size.

📊 Performance Comparison

We conducted a series of tests to demonstrate the performance improvements that Nuxt I18n Micro brings to the table. Below is a detailed comparison between Nuxt I18n Micro and the traditional nuxt-i18n module, based on identical conditions with a 10MB translation file on the same hardware.

⏱️ Build Time and Resource Consumption

Nuxt I18n
  • Total Size: 54.7 MB (3.31 MB gzip)
  • Max CPU Usage: 391.4%
  • Max Memory Usage: 8305 MB
  • Elapsed Time: 1m 31s

Nuxt I18n Micro

  • Total Size: 1.93 MB (473 kB gzip) — 96% smaller
  • Max CPU Usage: 220.1% — 44% lower
  • Max Memory Usage: 655 MB — 92% less memory
  • Elapsed Time: 0m 5s — 94% faster

🌐 Server Performance Under Load

We also tested server performance by simulating 10,000 requests to each module.

Nuxt I18n
  • Requests per Second: 49.05 [#/sec] (mean)
  • Time per Request: 611.599 ms (mean)
  • Max Memory Usage: 703.73 MB

Nuxt I18n Micro

  • Requests per Second: 61.18 [#/sec] (mean) — 25% more requests per second
  • Time per Request: 490.379 ms (mean) — 20% faster
  • Max Memory Usage: 323.00 MB — 54% less memory usage

🔍 Interpretation of Results

These tests clearly indicate that Nuxt I18n Micro offers superior performance across multiple metrics:

  • 🗜️ Smaller Bundle Size: Reduces the overall size of your application bundle, leading to faster load times and better user experience.
  • 🔋 Lower CPU Usage: Decreases the load on your server’s CPU, allowing for more efficient processing of requests.
  • 🧠 Reduced Memory Consumption: Significantly lowers memory usage, minimizing the risk of memory leaks and enabling your application to handle larger workloads.
  • 🕒 Faster Build Times: Drastically reduces build times, which is particularly beneficial during development and CI/CD processes.

⚙️ Key Optimizations

🛠️ Minimalist Design

Nuxt I18n Micro is built around a minimalist architecture, using only 5 components (1 module and 4 plugins). This reduces overhead and simplifies the internal logic, leading to improved performance.

🚦 Efficient Routing

Unlike other i18n modules that generate a separate route for each locale, Nuxt I18n Micro uses dynamic regex-based routing. This approach generates only two routes regardless of the number of locales, significantly reducing the complexity of your routing configuration and speeding up route resolution.

📂 Streamlined Translation Loading

The module supports only JSON files for translations, with a clear separation between global and page-specific files. This ensures that only the necessary translation data is loaded at any given time, further enhancing performance.

💾 Caching and Pre-rendering

To optimize performance, Nuxt I18n Micro implements caching and supports pre-rendering of translation files:

  • 🗄️ Caching: Translations are cached after the initial load, reducing the need for subsequent requests and improving response times.
  • 🏁 Pre-rendering: During the build process, translation files for all configured locales and routes can be pre-rendered. This eliminates the need for runtime requests, ensuring that translations are served quickly and efficiently.

📝 Tips for Maximizing Performance

Here are a few tips to ensure you get the best performance out of Nuxt I18n Micro:

  • 📉 Limit Locale Data: Only include the locales you need in your project to keep the bundle size small.
  • 🗂️ Use Page-Specific Translations: Organize your translation files by page to avoid loading unnecessary data.
  • 💾 Enable Caching: Make use of the caching features to reduce server load and improve response times.
  • 🏁 Leverage Pre-rendering: Pre-render your translations to speed up page loads and reduce runtime overhead.

For detailed results of the performance tests, please refer to the Performance Test Results.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/seo.html b/guide/seo.html new file mode 100644 index 00000000..dceb4831 --- /dev/null +++ b/guide/seo.html @@ -0,0 +1,37 @@ + + + + + + 🌐 SEO Guide for Nuxt I18n Micro | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🌐 SEO Guide for Nuxt I18n Micro

📖 Introduction

Effective SEO (Search Engine Optimization) is essential for ensuring that your multilingual site is accessible and visible to users worldwide through search engines. Nuxt I18n Micro simplifies the process of managing SEO for multilingual sites by automatically generating essential meta tags and attributes that inform search engines about the structure and content of your site.

This guide explains how Nuxt I18n Micro handles SEO to enhance your site's visibility and user experience without requiring additional configuration.

⚙️ Automatic SEO Handling

🔑 Key SEO Features

When the meta option is enabled in Nuxt I18n Micro, the module automatically manages the following SEO aspects:

  1. 🌍 Language and Direction Attributes:

    • The module sets the lang and dir attributes on the <html> tag according to the current locale and text direction (e.g., ltr for English or rtl for Arabic).
  2. 🔗 Canonical URLs:

    • The module generates a canonical link (<link rel="canonical">) for each page, ensuring that search engines recognize the primary version of the content.
  3. 🌐 Alternate Language Links (hreflang):

    • The module automatically generates <link rel="alternate" hreflang=""> tags for all available locales. This helps search engines understand which language versions of your content are available, improving the user experience for global audiences.
  4. 🔖 Open Graph Metadata:

    • The module generates Open Graph meta tags (og:locale, og:url, etc.) for each locale, which is particularly useful for social media sharing and search engine indexing.

🛠️ Configuration

To enable these SEO features, ensure the meta option is set to true in your nuxt.config.ts file:

typescript
export default defineNuxtConfig({
+  modules: ['nuxt-i18n-micro'],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true, // Enables automatic SEO management
+  },
+})

🎯 Benefits

By enabling the meta option, you benefit from:

  • 📈 Improved Search Engine Rankings: Search engines can better index your site, understanding the relationships between different language versions.
  • 👥 Better User Experience: Users are served the correct language version based on their preferences, leading to a more personalized experience.
  • 🔧 Reduced Manual Configuration: The module handles SEO tasks automatically, freeing you from the need to manually add SEO-related meta tags and attributes.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/server-side-translations.html b/guide/server-side-translations.html new file mode 100644 index 00000000..b13845b9 --- /dev/null +++ b/guide/server-side-translations.html @@ -0,0 +1,47 @@ + + + + + + 🌍 Server-Side Translations in Nuxt I18n Micro | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🌍 Server-Side Translations in Nuxt I18n Micro

📖 Overview

Nuxt I18n Micro supports server-side translations, allowing you to translate content on the server and return it as part of the response. This is particularly useful for APIs or server-rendered applications where localization is needed before reaching the client.

The translations use locale messages defined in the Nuxt I18n configuration and are dynamically resolved based on the detected locale.

To clarify, the translations used by Nuxt I18n Micro in server-side handling are only sourced from the root-level translation files. Any nested translation files or subdirectories are not utilized in this context. The system will only retrieve translations from the root folder, ensuring a consistent and manageable approach to server-side translation retrieval.


🛠️ Setting Up Server-Side Translations

To enable server-side translations, use the provided middleware to handle locale detection and return translations dynamically. The useTranslationServerMiddleware function is designed for this purpose.


✨ Using Translations in Server Handlers

You can seamlessly translate content in any eventHandler by using the middleware.

Example: Basic Usage

typescript
import { defineEventHandler } from 'h3'
+
+export default defineEventHandler(async (event) => {
+  const t = await useTranslationServerMiddleware(event)
+  return {
+    message: t('greeting'), // Returns the translated value for the key "greeting"
+  }
+})

In this example:

  • The user's locale is detected automatically from query parameters, cookies, or headers.
  • The t function retrieves the appropriate translation for the detected locale.

🌐 Providing a Custom Locale

If you need to specify a locale manually (e.g., for testing or certain requests), you can pass it to the middleware:

Example: Custom Locale

typescript
import { defineEventHandler } from 'h3'
+
+function detectLocale(event): string | null {
+  const urlSearchParams = new URLSearchParams(event.node.req.url?.split('?')[1]);
+  const localeFromQuery = urlSearchParams.get('locale');
+  if (localeFromQuery) return localeFromQuery;
+
+  return 'en';
+}
+
+export default defineEventHandler(async (event) => {
+  const t = await useTranslationServerMiddleware(event, 'en', detectLocale(event)) // Force French local, en - default locale
+  return {
+    message: t('welcome'), // Returns the French translation for "welcome"
+  }
+})

📋 Detecting Locale

The middleware automatically determines the user's locale using a fallback chain:

  1. Query Parameter: ?locale=fr
  2. Cookie: user-locale
  3. HTTP Header: Accept-Language
  4. Default Locale: As defined in useTranslationServerMiddleware param.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/strategy.html b/guide/strategy.html new file mode 100644 index 00000000..c750d66f --- /dev/null +++ b/guide/strategy.html @@ -0,0 +1,50 @@ + + + + + + 🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+) | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🗂️ Strategies for Locale Prefix Handling in Nuxt I18n (Version 1.50.0+)

📖 Introduction to Locale Prefix Strategies

Starting with version 1.50.0, Nuxt I18n introduces a more flexible way to manage how locale prefixes are handled in URLs through the strategy option. This new approach replaces the deprecated includeDefaultLocaleRoute and gives you better control over how localization is applied to different routes in your application.

The strategy option allows you to choose between different behaviors regarding locale prefixes, providing more fine-grained control over the URLs of your application and how they are structured based on the user's selected language.

🚦 strategy (New in Version 1.50.0)

The strategy option defines how locale prefixes should be managed across your routes. The available strategies give you varying levels of control over how the locale appears in the URLs.

Type: string
Default: prefix_and_default

Available Strategies:

🛑 no_prefix

This strategy ensures that no locale prefix is added to your routes. Instead of modifying the URL, the application will detect and change the locale based on the user's browser settings or cookies.

  • Behavior: Routes won't have any locale prefix.
  • Locale Detection: The locale is detected based on the user's browser language or cookies, and it is changed without altering the URL.
  • Restrictions: This strategy does not support features like Custom paths or Ignore routes.

Default Locale: You can set the default locale using an environment variable. For example:

  • DEFAULT_LOCALE=de npm run dev
  • DEFAULT_LOCALE=de npm run build

Use Case: Ideal when you want a cleaner URL structure and are relying on automatic language detection rather than explicit locale identifiers in the URL.

typescript
i18n: {
+  strategy: 'no_prefix'
+}

Example Routes:

  • /about (for any language, e.g., en, ru, fr, etc.)
  • /contact (for any language)
  • /other (for any language)
  • /other2 (for any language)

🚧 prefix_except_default

With this strategy, all of your routes will include a locale prefix, except for the default language. For the default language, the route will appear without any prefix.

  • Behavior: All routes will include a locale prefix, except for the default language.
  • Locale Handling: This ensures that only the default locale has URLs without a prefix, while all other locales will have a locale-specific prefix.

Use Case: Useful when you want all non-default languages to have a distinct URL structure with a locale prefix but prefer the default language to be accessible without the prefix.

typescript
i18n: {
+  strategy: 'prefix_except_default'
+}

Example Routes:

  • /about (for the default language, e.g., en)
  • /ru/about (for Russian)
  • /fr/about (for French)

🌍 prefix

This strategy ensures that every route in your application will include a locale prefix, regardless of the language. It standardizes the URL structure across all languages.

  • Behavior: All routes will have a locale prefix.
  • Locale Handling: Every route will follow a consistent pattern, with a locale prefix present in the URL for all languages.

Use Case: Ideal for situations where you want a consistent URL structure for all languages, ensuring every route includes the locale prefix.

typescript
i18n: {
+  strategy: 'prefix'
+}

Example Routes:

  • /en/about (for English)
  • /ru/about (for Russian)
  • /fr/about (for French)

🔄 prefix_and_default

This strategy combines both the prefix and prefix_except_default behaviors. It ensures that all languages have a locale prefix in their URLs, but the default language also has a non-prefixed URL version available. When the detectBrowserLanguage feature is enabled, the prefixed version of the default language will be preferred.

  • Behavior: Every language gets a URL with a locale prefix, but the default language also has a non-prefixed version.
  • Locale Handling: The default language has both a prefixed and non-prefixed URL, but the prefixed version takes priority when the browser language is detected.

Use Case: Best for applications that want to support both prefixed and non-prefixed URLs for the default language while maintaining a locale prefix for other languages.

typescript
i18n: {
+  strategy: 'prefix_and_default'
+}

Example Routes:

  • /about (for the default language, e.g., en)
  • /en/about (for English, with prefix)
  • /ru/about (for Russian)
  • /fr/about (for French)

⚠️ Known Issues and Best Practices

While the strategy option provides flexibility, there are some known issues and best practices to keep in mind when using these strategies.

1. Hydration Mismatch in no_prefix Strategy with Static Generation

When using the no_prefix strategy in combination with static site generation (generate mode), you may encounter a hydration mismatch error. This happens because the locale is determined dynamically (e.g., via cookies or browser settings) after the static page is rendered, leading to a mismatch between the server-rendered content and the client-side hydration.

Error Example:

Hydration completed but contains mismatches.

Workaround:

  • Avoid relying on dynamic locale changes during static generation.
  • Consider using a different strategy like prefix_except_default or prefix if static generation is a requirement.

2. Issues with localeRoute and Route Resolution

When using localeRoute to generate links, there can be issues with route resolution, especially if you rely on path-based routing. For example:

typescript
localeRoute('/page') // May cause issues with route resolution

Best Practice:

  • Always use named routes with localeRoute to avoid unnecessary redirects or route resolution problems:
typescript
localeRoute({ name: 'page' }) // Preferred approach

This ensures that the correct route is resolved regardless of the locale strategy.

3. Rendering Issues with Locale-Dependent Content in no_prefix Strategy

In the no_prefix strategy, rendering content that depends on the selected locale (e.g., buttons for switching languages) can lead to issues. For example, if you use a v-for loop to render locale buttons, Vue may incorrectly apply the disabled attribute due to hydration mismatches.

Example Problematic Code:

vue
<button
+  v-for="locale in availableLocales"
+  :key="locale.code"
+  :disabled="locale.isActive"
+  :class="{ disabled: locale.isActive }"
+  @click="() => $switchLocale(locale.code)"
+>
+  Switch to {{ locale.code }}
+</button>

Issue:

  • Vue may incorrectly apply the disabled attribute during hydration, and it may not update correctly when the locale changes.

Best Practice:

  • Use a <select> element or another approach that avoids direct DOM manipulation for locale-dependent content:
vue
<select @change="(e) => $switchLocale(e.target.value)">
+  <option
+    v-for="locale in availableLocales"
+    :key="locale.code"
+    :value="locale.code"
+    :selected="locale.isActive"
+  >
+    {{ locale.code }}
+  </option>
+</select>

This approach avoids hydration issues and ensures that the UI updates correctly when the locale changes.

📝 Conclusion

The new strategy option, introduced in version 1.50.0, provides more flexibility and control over how locale prefixes are handled in your application. Whether you need a clean, non-prefixed URL structure, or prefer to add locale prefixes for all or some languages, the available strategies allow you to customize your URL structure to fit your needs.

📚 Best Practices:

  • Simplicity for Default Language: If you don't need locale prefixes for your default language, use prefix_except_default or prefix_and_default.
  • Consistency: For a consistent URL structure with locale prefixes across all languages, use prefix.
  • User Experience: Consider using no_prefix when you want to rely on browser language detection and avoid cluttering the URL with prefixes.
  • Avoid Hydration Issues: Be cautious with no_prefix in static generation mode and use named routes with localeRoute for better route resolution.
  • Handle Locale-Dependent Content Carefully: Use <select> or other approaches to avoid hydration mismatches when rendering locale-dependent content.

By understanding and applying these strategies and best practices, you can ensure that your application's localization behavior fits your project's requirements while avoiding common pitfalls.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/guide/testing.html b/guide/testing.html new file mode 100644 index 00000000..7aefd48c --- /dev/null +++ b/guide/testing.html @@ -0,0 +1,128 @@ + + + + + + 🧪 Testing Nuxt I18n Micro Module | Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

🧪 Testing Nuxt I18n Micro Module

📖 Introduction to Testing

Testing the Nuxt I18n Micro module is crucial to ensure that your application's localization features work as expected. This documentation will guide you through setting up the testing environment, creating mock configurations for vitest, and writing tests for your components. For a practical example, you can refer to the example project on GitHub.

🛠️ Setting Up the Testing Environment

1. Install nuxt-i18n-micro-test-utils

First, you need to install the testing utilities for Nuxt I18n Micro. This package provides the necessary tools to mock and test your i18n configurations.

bash
npm install nuxt-i18n-micro-test-utils --save-dev

2. Create a Mock Configuration File

Next, create a file to set up the mock i18n configuration. This file will be used to mock the i18n functions and utilities during your tests.

typescript
// tests/unit-setup.ts
+
+import { mockNuxtImport } from '@nuxt/test-utils/runtime'
+import { vi } from 'vitest'
+import { i18nUtils } from 'nuxt-i18n-micro-test-utils'
+
+export function createFakeI18n() {
+  return {
+    $getLocale: vi.fn(i18nUtils.getLocale),
+    $t: vi.fn(i18nUtils.t),
+    $tc: vi.fn(i18nUtils.tc),
+    $setLocale: vi.fn(i18nUtils.setLocale),
+    $getLocaleName: vi.fn(i18nUtils.getLocaleName),
+    $setLocaleName: vi.fn(i18nUtils.setLocaleName),
+    $getLocales: vi.fn(i18nUtils.getLocales),
+    $setLocales: vi.fn(i18nUtils.setLocales),
+    $defaultLocale: vi.fn(i18nUtils.defaultLocale),
+    $setDefaultLocale: vi.fn(i18nUtils.setDefaultLocale),
+    $getRouteName: vi.fn(i18nUtils.getRouteName),
+    $settRouteName: vi.fn(i18nUtils.settRouteName),
+    $ts: vi.fn(i18nUtils.ts),
+    $tn: vi.fn(i18nUtils.tn),
+    $td: vi.fn(i18nUtils.td),
+    $has: vi.fn(i18nUtils.has),
+    $mergeTranslations: vi.fn(i18nUtils.mergeTranslations),
+    $switchLocaleRoute: vi.fn(i18nUtils.switchLocaleRoute),
+    $switchLocalePath: vi.fn(i18nUtils.switchLocalePath),
+    $switchLocale: vi.fn(i18nUtils.switchLocale),
+    $switchRoute: vi.fn(i18nUtils.switchRoute),
+    $localeRoute: vi.fn(i18nUtils.localeRoute),
+    $localePath: vi.fn(i18nUtils.localePath),
+    $setI18nRouteParams: vi.fn(i18nUtils.setI18nRouteParams),
+  }
+}
+
+mockNuxtImport<() => ReturnType<typeof createFakeI18n>>('useI18n', () =>
+  vi.fn(() => createFakeI18n()),
+)
+
+export const setTranslationsFromJson = i18nUtils.setTranslationsFromJson

3. Configure Vitest

Now, configure Vitest to use the mock configuration file and set up the testing environment.

typescript
// vitest.config.ts
+
+import { defineVitestConfig } from '@nuxt/test-utils/config'
+
+export default defineVitestConfig({
+  test: {
+    watch: false,
+    setupFiles: ['./tests/unit-setup.ts'],
+    include: ['./**/*.spec.ts'],
+  },
+})

🧪 Writing Tests

Example Component

Here’s an example of a simple component that uses the useI18n composable to translate messages.

vue
<script setup lang="ts">
+const { $t } = useI18n()
+
+const props = defineProps({
+  message: {
+    type: String,
+    default: null,
+  },
+})
+
+// Test to see that $t works in script setup as well as the template
+const message = props.message || $t('defaultMessage')
+</script>
+
+<template>
+  <div>
+    <p>Test from component: {{ $t('welcome') }}</p>
+    <p data-testid="message">
+      Test message from props: {{ message }}
+    </p>
+  </div>
+</template>

Test File

Now, let’s write a test for this component.

typescript
// tests/unit/example.spec.ts
+
+import { describe, it, expect, beforeEach } from 'vitest'
+import { mount } from '@vue/test-utils'
+import ExampleComponent from '@/components/ExampleComponent.vue'
+import fs from 'fs'
+import path from 'path'
+import { setTranslationsFromJson } from './unit-setup'
+
+describe('ExampleComponent', () => {
+  beforeEach(async () => {
+    const fileContent = fs.readFileSync(path.join(__dirname, '../../locales/en-GB.json')).toString()
+    await setTranslationsFromJson('en', JSON.parse(fileContent))
+  })
+
+  it('renders the welcome message correctly', () => {
+    const wrapper = mount(ExampleComponent)
+    expect(wrapper.text()).toContain('Test from component: Welcome')
+  })
+
+  it('renders the default message correctly', () => {
+    const wrapper = mount(ExampleComponent)
+    expect(wrapper.find('[data-testid="message"]').text()).toContain('Test message from props: Default Message')
+  })
+
+  it('renders the custom message correctly', () => {
+    const wrapper = mount(ExampleComponent, {
+      props: {
+        message: 'Custom Message',
+      },
+    })
+    expect(wrapper.find('[data-testid="message"]').text()).toContain('Test message from props: Custom Message')
+  })
+})

📝 Best Practices for Testing

  • 🔧 Mock i18n Functions: Always mock the i18n functions using nuxt-i18n-micro-test-utils to ensure consistent and predictable test results.
  • ⚙️ Use Vitest for Unit Tests: Vitest is a powerful testing framework for Vue applications. Use it to write unit tests for your components.
  • 📚 Document Your Tests: Clearly document the purpose and expected outcomes of each test. This will help maintain clarity and make it easier for others (or future you) to understand the tests.

📊 i18n Utility Methods

Below is a table describing all the utility methods provided by nuxt-i18n-micro-test-utils.

MethodDescription
t(key, params, defaultValue)Translates a key with optional parameters and a default value.
tc(key, params, defaultValue)Translates a key with pluralization support.
setTranslationsFromJson(locale, translations)Loads translations from a JSON object for a specific locale.
getLocale()Returns the current locale.
setLocale(val)Sets the current locale.
getLocaleName()Returns the current locale name.
setLocaleName(val)Sets the current locale name.
getLocales()Returns the list of available locales.
setLocales(val)Sets the list of available locales.
defaultLocale()Returns the default locale.
setDefaultLocale(val)Sets the default locale.
getRouteName()Returns the current route name.
settRouteName(val)Sets the current route name.
ts(key, params, defaultValue)Translates a key and returns the result as a string.
tn(value, options)Formats a number according to the current locale.
td(value, options)Formats a date according to the current locale.
has(key)Checks if a translation key exists.

By following these steps, you can effectively test the Nuxt I18n Micro module and ensure that your application's localization features work as expected.

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/hashmap.json b/hashmap.json new file mode 100644 index 00000000..ee99fd53 --- /dev/null +++ b/hashmap.json @@ -0,0 +1 @@ +{"api_events.md":"bHhRa_Pw","api_methods.md":"VL5OYeZ9","components_i18n-group.md":"D_KGhnfJ","components_i18n-link.md":"BWN41WEE","components_i18n-switcher.md":"BVMz2Cf5","components_i18n-t.md":"C61xRTdL","composables_usei18n.md":"CtJaYII6","composables_uselocalehead.md":"Cw60RGsA","examples.md":"DfpJSwPq","guide_cli.md":"DbExMDtf","guide_contribution.md":"BiQbFYzX","guide_crowdin.md":"DgJWT6GK","guide_custom-locale-routes.md":"65G7AEaG","guide_devtools.md":"sGmDATnc","guide_faq.md":"dIiCo_1b","guide_folder-structure.md":"B7ryKxoT","guide_getting-started.md":"DMTe_ufE","guide_layers.md":"Bs1rVVV1","guide_migration.md":"DP2CIHWa","guide_multi-domain-locales.md":"nqKQQ1PT","guide_per-component-translations.md":"DxQAkf1R","guide_performance-results.md":"DEEBDFv7","guide_performance.md":"CbRsZzqQ","guide_seo.md":"CjeG8qHD","guide_server-side-translations.md":"Dqb0NeYG","guide_strategy.md":"CUuNsgYn","guide_testing.md":"BhPNxZf_","index.md":"iT9qvt2L","news_index.md":"DN4b2rDE"} diff --git a/i18n-micro.png b/i18n-micro.png new file mode 100644 index 00000000..bc635a3e Binary files /dev/null and b/i18n-micro.png differ diff --git a/i18n.png b/i18n.png new file mode 100644 index 00000000..9521cefd Binary files /dev/null and b/i18n.png differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..3de653f8 --- /dev/null +++ b/index.html @@ -0,0 +1,51 @@ + + + + + + Nuxt I18n Micro + + + + + + + + + + + + + + +
Skip to content

Nuxt I18n Micro

Fast, Simple, and Lightweight Internationalization for Nuxt

Optimize your Nuxt app with a powerful and efficient i18n solution.


✨ Introduction

Nuxt I18n Micro is a fast, simple, and lightweight internationalization (i18n) module for Nuxt. Despite its compact size, it's designed with large projects in mind, offering significant performance improvements over traditional i18n solutions like nuxt-i18n. The module was built from the ground up to be highly efficient, focusing on minimizing build times, reducing server load, and shrinking bundle sizes.

📝 Why Nuxt I18n Micro?

The Nuxt I18n Micro module was created to address critical performance issues found in the original nuxt-i18n module, particularly in high-traffic environments and projects with large translation files. Key issues with nuxt-i18n include:

  • 🚨 High Memory Consumption: Consumes significant memory during both build and runtime, leading to performance bottlenecks.
  • 🐢 Slow Performance: Especially with large translation files, it causes noticeable slowdowns in build times and server response.
  • 💼 Large Bundle Size: Generates a large bundle, negatively impacting application performance.
  • 🐛 Memory Leaks and Bugs: Known for memory leaks and unpredictable behavior under heavy load.

🏁 Performance Comparison

To showcase the efficiency of Nuxt I18n Micro, we conducted tests under identical conditions. Both modules were tested with a 10MB translation file on the same hardware.

⏱️ Build Time and Resource Consumption

Nuxt I18n
  • Total Size: 54.7 MB (3.31 MB gzip)
  • Max CPU Usage: 391.4%
  • Max Memory Usage: 8305 MB
  • Elapsed Time: 0h 1m 31s

Nuxt I18n Micro

  • Total Size: 1.93 MB (473 kB gzip) — 96% smaller
  • Max CPU Usage: 220.1% — 44% lower
  • Max Memory Usage: 655 MB — 92% less memory
  • Elapsed Time: 0h 0m 5s — 94% faster

🌐 Server Performance (10k Requests)

Nuxt I18n
  • Requests per Second: 49.05 [#/sec] (mean)
  • Time per Request: 611.599 ms (mean)
  • Max Memory Usage: 703.73 MB

Nuxt I18n Micro

  • Requests per Second: 61.18 [#/sec] (mean) — 25% more requests per second
  • Time per Request: 490.379 ms (mean) — 20% faster
  • Max Memory Usage: 323.00 MB — 54% less memory usage

These results clearly demonstrate that Nuxt I18n Micro significantly outperforms the original module in every critical area.

🔑 Key Features

  • 🌐 Compact Yet Powerful: Despite its small size, Nuxt I18n Micro is designed for large-scale projects, focusing on performance and efficiency.
  • Optimized Build and Runtime: Reduces build times, memory usage, and server load, making it ideal for high-traffic applications.
  • 🛠️ Minimalist Design: The module is structured around just 5 components (1 module and 4 plugins), making it easy to understand, extend, and maintain.
  • 📏 Efficient Routing: Generates only 2 routes regardless of the number of locales, thanks to dynamic regex-based routing, unlike other i18n modules that generate separate routes for each locale.
  • 🗂 Streamlined Translation Loading: Only JSON files are supported, with translations split between a global file for common texts (e.g., menus) and page-specific files, which are auto-generated in the dev mode if not present.

⚙️ Quick Setup

Install the module in your Nuxt application with:

bash
npm install nuxt-i18n-micro

Then, add it to your nuxt.config.ts:

typescript
export default defineNuxtConfig({
+  modules: [
+    'nuxt-i18n-micro',
+  ],
+  i18n: {
+    locales: [
+      { code: 'en', iso: 'en-US', dir: 'ltr' },
+      { code: 'fr', iso: 'fr-FR', dir: 'ltr' },
+      { code: 'ar', iso: 'ar-SA', dir: 'rtl' },
+    ],
+    defaultLocale: 'en',
+    translationDir: 'locales',
+    meta: true,
+  },
+})

That's it! You're now ready to use Nuxt I18n Micro in your Nuxt app.

🗂 Folder Structure

Translations are organized into global and page-specific files:

plaintext
  /locales
+  ├── /pages
+  │   ├── /index
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  │   ├── /about
+  │   │   ├── en.json
+  │   │   ├── fr.json
+  │   │   └── ar.json
+  ├── en.json
+  ├── fr.json
+  └── ar.json

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/news/index.html b/news/index.html new file mode 100644 index 00000000..aaf20ca7 --- /dev/null +++ b/news/index.html @@ -0,0 +1,36 @@ + + + + + + News | Nuxt I18n Micro + + + + + + + + + + + + + + + +
Skip to content

News

Major Release: Nuxt I18n Micro v1.65.0

Date: 2025-01-20

Version: v1.65.0

1.65.0

We’re thrilled to announce v1.65.0, featuring a complete rewrite of core logic for better performance and maintainability! This release includes enhanced TypeScript support, client-side locale redirection, and streamlined translation handling. Upgrade now for a smoother, faster experience! 🚀

Learn more

Optimized Translation Loading Algorithm Released

Date: 2025-01-10

Version Introduced: v1.58.0

Optimized Loading Demo

We are thrilled to announce the release of a new algorithm for loading translations in Nuxt I18n Micro. This update introduces significant performance improvements, a cleaner architecture, and more efficient memory usage.

What’s New?

The new translation-loading algorithm focuses on:

  1. Optimized File Merging: Enhanced the deep merge functionality to handle translations more efficiently.
  2. Caching Enhancements: Leveraged server storage for pre-rendered translations, reducing redundant computations.
  3. Streamlined Code: Simplified file paths and structure for better maintainability.

Key Benefits

1. Faster Build Times

The new algorithm reduces build times by efficiently handling translation files and minimizing memory overhead.

  • Old Build Time: 7.20 seconds
  • New Build Time: 6.91 seconds
  • Improvement: 4.03% faster

2. Reduced CPU Usage

Lower maximum and average CPU usage during builds and stress tests:

  • Build Max CPU: From 257.60%198.20% (23.06% lower)
  • Stress Test Avg CPU: From 93.85%89.14% (5.01% lower)

3. Lower Memory Usage

Memory consumption has been significantly optimized across builds and runtime stress tests:

  • Build Max Memory: From 1286.00 MB885.19 MB (31.15% lower)
  • Stress Test Max Memory: From 624.22 MB429.52 MB (31.20% lower)

4. Enhanced Response Times

Stress test response times saw drastic improvement:

  • Average Response Time: From 411.50 ms9.30 ms (97.74% faster)
  • Max Response Time: From 2723.00 ms187.00 ms (93.13% faster)

5. Increased Request Throughput

The new algorithm boosts the number of handled requests per second:

  • Requests per Second: From 288.00305.00 (5.90% increase)

Why It’s Important

Localization is essential for global applications, and improving translation-loading performance can have a direct impact on:

  • User Experience: Faster response times lead to a smoother user experience.
  • Scalability: Lower resource usage allows better handling of high traffic.
  • Developer Productivity: Reduced build times and a simplified codebase streamline workflows.

How It Works

  1. Efficient Deep Merging
  • The algorithm has been rewritten to handle translation merging more intelligently, ensuring minimal memory overhead and faster operations.
  1. Smart Caching
  • Server-side storage is now used to cache translations during pre-rendering, which are then reused during runtime. This avoids repetitive reads and merges.
  1. Streamlined File Loading
  • Translation files are loaded in a more predictable and maintainable way by unifying fallback handling and caching.

New CLI Feature: text-to-i18n

Date: 2024-12-24

Cli Version Introduced: v1.1.0

text-to-i18n Command Demo

We’re excited to announce the new text-to-i18n command in the Nuxt I18n Micro CLI! This powerful feature automates the process of extracting hardcoded text strings from your codebase and converting them into i18n translation keys. It’s designed to save time, reduce errors, and streamline your localization workflow.

Key Benefits

  • Automated Text Extraction: Scans Vue templates, JavaScript, and TypeScript files.
  • Seamless Key Generation: Creates structured translation keys based on file paths and content.
  • Efficient Translation Management: Updates your translation files while preserving existing entries.

How It Works

  1. File Scanning: Processes files in key directories like pages, components, and plugins.
  2. Text Processing: Identifies and extracts translatable strings, generating unique keys.
  3. Translation Updates: Automatically inserts new keys into your translation files and maintains their nested structure.

Usage

bash
i18n-micro text-to-i18n [options]

Example:

bash
i18n-micro text-to-i18n --translationFile locales/en.json --context auth

Example Transformations

Before

vue
<template>
+  <div>
+    <h1>Welcome to our site</h1>
+    <p>Please sign in to continue</p>
+  </div>
+</template>

After

vue
<template>
+  <div>
+    <h1>{{ $t('pages.home.welcome_to_our_site') }}</h1>
+    <p>{{ $t('pages.home.please_sign_in') }}</p>
+  </div>
+</template>

For more details, check out the documentation.


Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/optimized-loading.png b/optimized-loading.png new file mode 100644 index 00000000..be40c033 Binary files /dev/null and b/optimized-loading.png differ diff --git a/text-to-i18n.gif b/text-to-i18n.gif new file mode 100644 index 00000000..1ccf4ab6 Binary files /dev/null and b/text-to-i18n.gif differ diff --git a/vp-icons.css b/vp-icons.css new file mode 100644 index 00000000..ddc5bd8e --- /dev/null +++ b/vp-icons.css @@ -0,0 +1 @@ +.vpi-social-github{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")} \ No newline at end of file