Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support Nuxt 4 #3105

Merged
merged 2 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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