Skip to content

Commit

Permalink
feat: support Nuxt 4 (#3105)
Browse files Browse the repository at this point in the history
* test: add test and fixture using `compatibilityVersion: 4`

* fix: remove nuxt version checks
  • Loading branch information
BobbieGoede authored Sep 17, 2024
1 parent df79f54 commit 73f6b99
Show file tree
Hide file tree
Showing 46 changed files with 2,925 additions and 150 deletions.
1,296 changes: 1,167 additions & 129 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

647 changes: 647 additions & 0 deletions specs/basic_usage_compat_4.spec.ts

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions specs/fixtures/basic_usage_compat_4/app/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script setup lang="ts">
import { useI18n } from '#i18n'
import { useRuntimeConfig } from '#imports'
const { finalizePendingLocaleChange } = useI18n()
const skipSettingLocale = useRuntimeConfig().public.i18n.skipSettingLocaleOnNavigate
const pageTransition = {
name: 'my',
mode: 'out-in',
onBeforeEnter: async () => {
await finalizePendingLocaleChange()
}
}
</script>

<template>
<NuxtLayout>
<NuxtPage id="nuxt-page" :transition="skipSettingLocale ? pageTransition : undefined" />
</NuxtLayout>
</template>

<style>
section {
margin: 1rem 0;
}
.my-enter-active,
.my-leave-active {
transition: opacity 0.3s;
}
.my-enter,
.my-leave-active {
opacity: 0;
}
</style>
15 changes: 15 additions & 0 deletions specs/fixtures/basic_usage_compat_4/app/app/router.options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useNuxtApp } from '#imports'

import type { RouterConfig } from '@nuxt/schema'

export default <RouterConfig>{
async scrollBehavior(to, from, savedPosition) {
const nuxtApp = useNuxtApp()

if (nuxtApp.$config.public.i18n.skipSettingLocaleOnNavigate && nuxtApp.$18n && to.name !== from.name) {
await nuxtApp.$i18n.waitForPendingLocaleChange()
}

return savedPosition || { top: 0 }
}
}
76 changes: 76 additions & 0 deletions specs/fixtures/basic_usage_compat_4/app/components/BasicUsage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<script setup lang="ts">
import { navigateTo } from '#imports'
import { useLocalePath, useSwitchLocalePath, useLocaleRoute, useI18n } from '#i18n'
const { locale, locales } = 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 id="welcome-message">{{ $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 v-for="l in locales" :key="l" :class="`switch-to-${l}`">
<NuxtLink :to="switchLocalePath(l)">l</NuxtLink>
</li>
</ul>
</section>
<section id="locale-route-usages">
<h3>localeRoute</h3>
<button @click="onClick">Show profile</button>
</section>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script setup lang="ts">
import { useI18n, useSwitchLocalePath } from '#i18n'
import { useRoute } from '#imports'
const { locales, locale, setLocale } = useI18n()
const route = useRoute()
const switchLocalePath = useSwitchLocalePath()
const localesExcludingCurrent = computed(() => {
return locales.value.filter(i => i.code !== locale.value)
})
</script>

<template>
<div>
<section id="lang-switcher-with-nuxt-link">
<strong>Using <code>NuxtLink</code></strong
>:
<NuxtLink
v-for="(locale, index) in localesExcludingCurrent"
:id="`nuxt-locale-link-${locale.code}`"
:key="index"
:exact="true"
:to="switchLocalePath(locale.code)"
>{{ locale.name }}</NuxtLink
>
</section>
<section id="lang-switcher-with-switch-locale-path-link">
<strong>Using <code>SwitchLocalePathLink</code></strong
>:
<SwitchLocalePathLink
v-for="(locale, index) in localesExcludingCurrent"
:id="`switch-locale-path-link-${locale.code}`"
:key="index"
:exact="true"
:locale="locale.code"
>{{ locale.name }}</SwitchLocalePathLink
>
</section>
<section id="lang-switcher-with-set-locale">
<strong>Using <code>setLocale()</code></strong
>:
<a
v-for="(locale, index) in localesExcludingCurrent"
: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>
<section>
<code id="route-path">route: {{ route.path }}</code>
</section>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<code id="local-scope-properties">{{ localeProperties }}</code>
</template>

<script setup lang="ts">
const { localeProperties } = useI18n({
useScope: 'local'
})
</script>
30 changes: 30 additions & 0 deletions specs/fixtures/basic_usage_compat_4/app/layouts/default.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from '#imports'
import { useI18n, useLocaleHead } from '#i18n'
const route = useRoute()
const { t } = useI18n()
const head = useLocaleHead({ key: 'id', seo: { canonicalQueries: ['page'] } })
const title = computed(() => `Page - ${t(route.meta?.title ?? '')}`)
</script>

<template>
<Html :lang="head.htmlAttrs.lang" :dir="head.htmlAttrs.dir">
<Head>
<Title>{{ title }}</Title>
<template v-for="link in head.link" :key="link.id">
<Link :id="link.id" :rel="link.rel" :href="link.href" :hreflang="link.hreflang" />
</template>
<template v-for="meta in head.meta" :key="meta.id">
<Meta :id="meta.id" :property="meta.property" :content="meta.content" />
</template>
</Head>
<Body>
<slot />
<section>
<code id="layout-use-locale-head">{{ head }}</code>
</section>
</Body>
</Html>
</template>
3 changes: 3 additions & 0 deletions specs/fixtures/basic_usage_compat_4/app/locales/en.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
'server-key': 'Hello!'
}
1 change: 1 addition & 0 deletions specs/fixtures/basic_usage_compat_4/app/locales/ja.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
server-key: 'こんにちは!'
18 changes: 18 additions & 0 deletions specs/fixtures/basic_usage_compat_4/app/pages/[...pathMatch].vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script setup lang="ts">
import LangSwitcher from '../components/LangSwitcher.vue'
const route = useRoute()
const setI18nParams = useSetI18nParams()
setI18nParams({
en: { pathMatch: ['my-post', 'abc'] },
fr: { pathMatch: ['mon-article', 'xyz'] }
})
</script>

<template>
<div>
<code id="catch-all-id">{{ route.params.pathMatch.join('/') }}</code>
<LangSwitcher />
</div>
</template>
40 changes: 40 additions & 0 deletions specs/fixtures/basic_usage_compat_4/app/pages/about/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n, useLocalePath } from '#i18n'
import LangSwitcher from '../../components/LangSwitcher.vue'
const { localeProperties } = useI18n()
const localePath = useLocalePath()
const code = computed(() => {
return localeProperties.value.code
})
// @ts-ignore
definePageMeta({
title: 'about'
})
/*
// TODO: defineNuxtI18n macro
defineNuxtI18n({
paths: {
en: '/about-us',
fr: '/a-propos'
}
})
*/
</script>

<template>
<div>
<h1 id="about-header">{{ $t('about') }}</h1>
<LangSwitcher />
<!-- div id="store-path-fr">{{ $store.state.routePathFr }}</div -->
<section>
<strong
>code: <code id="locale-properties-code">{{ code }}</code></strong
>
</section>
<NuxtLink id="link-home" exact :to="localePath('index')">{{ $t('home') }}</NuxtLink>
</div>
</template>
35 changes: 35 additions & 0 deletions specs/fixtures/basic_usage_compat_4/app/pages/api/products-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export default [
{
id: 1,
name: {
en: 'Red mug',
nl: 'Rode mok'
},
slugs: {
en: 'red-mug',
nl: 'rode-mok'
}
},
{
id: 2,
name: {
en: 'Big chair',
nl: 'Grote stoel'
},
slugs: {
en: 'big-chair',
nl: 'grote-stoel'
}
},
{
id: 3,
name: {
en: 'Standing desk',
nl: 'Sta bureau'
},
slugs: {
en: 'standing-desk',
nl: 'sta-bureau'
}
}
]
19 changes: 19 additions & 0 deletions specs/fixtures/basic_usage_compat_4/app/pages/api/products.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { LocaleMessages, DefineLocaleMessage } from 'vue-i18n'
import productsData from './products-data'
/**
* NOTE:
* locale resources is managed on backend examples
*/

const locales: LocaleMessages<DefineLocaleMessage> = {
'en-GB': {
settings: {
profile: 'Profile'
}
},
ja: {}
}

export default defineEventHandler(event => {
return productsData
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { LocaleMessages, DefineLocaleMessage } from 'vue-i18n'
import productsData from '../products-data'

/**
* NOTE:
* locale resources is managed on backend examples
*/

const locales: LocaleMessages<DefineLocaleMessage> = {
'en-GB': {
settings: {
profile: 'Profile'
}
},
ja: {}
}

export default defineEventHandler(event => {
const slug = event.context.params?.product
const found = productsData.find(x => Object.values(x.slugs).includes(slug))

if (found == null) {
return {}
}

return found
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<p>This is cateory page on '{{ $route.params.slug }}'</p>
</template>
Loading

0 comments on commit 73f6b99

Please sign in to comment.