Skip to content

Commit

Permalink
fix: layer inline module options not used in generation (#2618)
Browse files Browse the repository at this point in the history
* fix: layer inline module options not used in generation

* test: add regression test for #2617
  • Loading branch information
BobbieGoede committed Dec 14, 2023
1 parent 64fa2f6 commit 2a7ee97
Show file tree
Hide file tree
Showing 11 changed files with 268 additions and 5 deletions.
5 changes: 5 additions & 0 deletions specs/fixtures/issues/2617/app.vue
@@ -0,0 +1,5 @@
<template>
<div>
<NuxtPage />
</div>
</template>
79 changes: 79 additions & 0 deletions specs/fixtures/issues/2617/components/BasicUsage.vue
@@ -0,0 +1,79 @@
<script setup lang="ts">
import { navigateTo } from '#imports'
import { useLocalePath, useSwitchLocalePath, useLocaleRoute, useI18n } from '#i18n'
const { locale } = useI18n()
const localePath = useLocalePath()
const switchLocalePath = useSwitchLocalePath()
const localeRoute = useLocaleRoute()
const category = ref({
title: 'Kirby',
slug: 'nintendo'
})
function onClick() {
const route = localeRoute({ name: 'user-profile', query: { foo: '1' } })
if (route) {
return navigateTo(route.fullPath)
}
}
</script>

<template>
<div id="basic-usage-section">
<h2>Docs Basic usages</h2>
<section id="vue-i18n-usage">
<h3>vue-i18n</h3>
<div class="vue-i18n">
<form>
<select v-model="locale">
<option value="en">en</option>
<option value="fr">fr</option>
</select>
<p>{{ $t('welcome') }}</p>
</form>
</div>
</section>
<section id="locale-path-usages">
<h3>localePath</h3>
<ul>
<li class="name">
<NuxtLink :to="localePath('index')">{{ $t('home') }}</NuxtLink>
</li>
<li class="path">
<NuxtLink :to="localePath('/')">{{ $t('home') }}</NuxtLink>
</li>
<li class="named-with-locale">
<NuxtLink :to="localePath('index', 'en')">Homepage in English</NuxtLink>
</li>
<li class="nest-path">
<NuxtLink :to="localePath('/user/profile')">Route by path to: {{ $t('profile') }}</NuxtLink>
</li>
<li class="nest-named">
<NuxtLink :to="localePath('user-profile')">Route by name to: {{ $t('profile') }}</NuxtLink>
</li>
<li class="object-with-named">
<NuxtLink :to="localePath({ name: 'category-slug', params: { slug: category.slug } })">
{{ category.title }}
</NuxtLink>
</li>
</ul>
</section>
<section id="switch-locale-path-usages">
<h3>switchLocalePath</h3>
<ul>
<li class="switch-to-en">
<NuxtLink :to="switchLocalePath('en')">English</NuxtLink>
</li>
<li class="switch-to-fr">
<NuxtLink :to="switchLocalePath('fr')">Français</NuxtLink>
</li>
</ul>
</section>
<section id="locale-route-usages">
<h3>localeRoute</h3>
<button @click="onClick">Show profile</button>
</section>
</div>
</template>
40 changes: 40 additions & 0 deletions specs/fixtures/issues/2617/components/LangSwitcher.vue
@@ -0,0 +1,40 @@
<script setup lang="ts">
import { useI18n, useSwitchLocalePath } from '#i18n'
const { locales, locale, setLocale } = useI18n()
const switchLocalePath = useSwitchLocalePath()
</script>

<template>
<div>
<section id="lang-switcher-with-nuxt-link">
<strong>Using <code>NuxtLink</code></strong
>:
<NuxtLink
v-for="(locale, index) in locales"
:key="index"
:exact="true"
:class="`switch-to-${locale.code}`"
:to="switchLocalePath(locale.code)"
>{{ locale.name }}</NuxtLink
>
</section>
<section id="lang-switcher-with-set-locale">
<strong>Using <code>setLocale()</code></strong
>:
<a
v-for="(locale, index) in locales"
:id="`set-locale-link-${locale.code}`"
:key="`b-${index}`"
href="javascript:void(0)"
@click.prevent="setLocale(locale.code)"
>{{ locale.name }}</a
>
</section>
<section id="lang-switcher-current-locale">
<strong
>Current Locale: <code>{{ locale }}</code></strong
>:
</section>
</div>
</template>
6 changes: 6 additions & 0 deletions specs/fixtures/issues/2617/lang/locale-file-en.json
@@ -0,0 +1,6 @@
{
"home": "Homepage",
"about": "About us",
"posts": "Posts",
"dynamic": "Dynamic"
}
23 changes: 23 additions & 0 deletions specs/fixtures/issues/2617/nuxt.config.ts
@@ -0,0 +1,23 @@
// https://nuxt.com/docs/guide/directory-structure/nuxt.config
export default defineNuxtConfig({
modules: [
[
'@nuxtjs/i18n',
{
debug: false,
lazy: false,
langDir: 'lang',
defaultLocale: 'en',
detectBrowserLanguage: false,
locales: [
{
code: 'en',
iso: 'en-US',
file: 'locale-file-en.json'
}
]
}
]
],
debug: false
})
14 changes: 14 additions & 0 deletions specs/fixtures/issues/2617/package.json
@@ -0,0 +1,14 @@
{
"name": "nuxt3-test-basic-usage-layers",
"private": true,
"type": "module",
"scripts": {
"dev": "nuxi dev",
"build": "nuxt build",
"start": "node .output/server/index.mjs"
},
"devDependencies": {
"@nuxtjs/i18n": "latest",
"nuxt": "latest"
}
}
3 changes: 3 additions & 0 deletions specs/fixtures/issues/2617/pages/category/[slug].vue
@@ -0,0 +1,3 @@
<template>
<p>This is cateory page on '{{ $route.params.slug }}'</p>
</template>
65 changes: 65 additions & 0 deletions specs/fixtures/issues/2617/pages/index.vue
@@ -0,0 +1,65 @@
<script setup lang="ts">
import { watchEffect } from 'vue'
import { useAsyncData, useHead, useRouter } from '#imports'
import { useI18n, useLocalePath, useLocaleHead } from '#i18n'
import BasicUsage from '../components/BasicUsage.vue'
import LangSwitcher from '../components/LangSwitcher.vue'
const { t } = useI18n()
const localePath = useLocalePath()
const i18nHead = useLocaleHead({
addDirAttribute: true,
identifierAttribute: 'id',
addSeoAttributes: { canonicalQueries: ['page'] },
router: useRouter()
})
const { data, refresh } = useAsyncData('home', () =>
Promise.resolve({
aboutPath: localePath('about'),
aboutTranslation: t('about')
})
)
watchEffect(() => {
refresh()
})
useHead({
title: t('home'),
htmlAttrs: {
lang: i18nHead.value.htmlAttrs!.lang,
dir: i18nHead.value.htmlAttrs!.dir
},
link: [...(i18nHead.value.link || [])],
meta: [...(i18nHead.value.meta || [])]
})
</script>

<template>
<div>
<h1 id="home-header">{{ $t('home') }}</h1>
<!-- <BasicUsage /> -->
<LangSwitcher />
<section>
<strong>resolve with <code>useAsyncData</code></strong
>:
<code id="home-use-async-data">{{ data }}</code>
</section>
<section>
<strong><code>useHead</code> with <code>useLocaleHead</code></strong
>:
<code id="home-use-locale-head">{{ i18nHead }}</code>
</section>
<section>
<code id="extend-message">{{ t('my-module-exemple.hello') }}</code>
</section>
<NuxtLink id="link-about" exact :to="localePath('about')">{{ $t('about') }}</NuxtLink>
<NuxtLink id="link-blog" :to="localePath('blog')">{{ $t('blog') }}</NuxtLink>
<NuxtLink id="link-ignore-disable" :to="localePath('/ignore-routes/disable')"
>go to ignoring localized disable route</NuxtLink
>
<NuxtLink id="link-ignore-pick" :to="localePath('/ignore-routes/pick')"
>go to ignoring localized pick route</NuxtLink
>
</div>
</template>
3 changes: 3 additions & 0 deletions specs/fixtures/issues/2617/pages/user/profile.vue
@@ -0,0 +1,3 @@
<template>
<p id="profile-page">This is profile page</p>
</template>
23 changes: 23 additions & 0 deletions specs/issues/2617.spec.ts
@@ -0,0 +1,23 @@
import { test, expect, describe } from 'vitest'
import { fileURLToPath } from 'node:url'
import { setup } from '../utils'
import { renderPage } from '../helper'

describe('#2617', async () => {
await setup({
rootDir: fileURLToPath(new URL(`../fixtures/issues/2617`, import.meta.url)),
browser: true
})

test('should use inline locale objects', async () => {
const { consoleLogs } = await renderPage('/')

expect(
consoleLogs.some(
log =>
log.type === 'warning' &&
log.text.includes('[vue-i18n-routing] Locale ISO code is required to generate alternate link')
)
).toBe(false)
})
})
12 changes: 7 additions & 5 deletions src/gen.ts
Expand Up @@ -4,7 +4,7 @@ import createDebug from 'debug'
import { EXECUTABLE_EXTENSIONS } from './constants'
import { genImport, genDynamicImport } from 'knitwork'
import { withQuery } from 'ufo'
import { getLocalePaths, toCode } from './utils'
import { getLayerI18n, getLocalePaths, toCode } from './utils'

import type { Nuxt } from '@nuxt/schema'
import type { PrerenderTarget } from './utils'
Expand Down Expand Up @@ -32,14 +32,16 @@ const generateVueI18nConfiguration = (config: Required<VueI18nConfigPathInfo>, i
}

function simplifyLocaleOptions(nuxt: Nuxt, options: NuxtI18nOptions) {
const hasObjectLocales =
nuxt.options._layers.some(layer => layer?.config?.i18n?.locales?.some(x => typeof x !== 'string')) ||
options?.i18nModules?.some(module => module?.locales?.some(x => typeof x !== 'string'))
const isLocaleObjectsArray = (locales?: string[] | LocaleObject[]) => locales?.some(x => typeof x !== 'string')

const hasLocaleObjects =
nuxt.options._layers.some(layer => isLocaleObjectsArray(getLayerI18n(layer)?.locales)) ||
options?.i18nModules?.some(module => isLocaleObjectsArray(module?.locales))

const locales = (options.locales ?? []) as LocaleObject[]
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return locales.map(({ meta, ...locale }) => {
if (!hasObjectLocales) {
if (!hasLocaleObjects) {
return locale.code
}

Expand Down

0 comments on commit 2a7ee97

Please sign in to comment.