@4verburga/alpine-spanishplus 2.0.0-dev.7ab3971 → 2.0.0-dev.838f140
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/AppFooter.vue +3 -0
- package/components/AppHeader.vue +1 -1
- package/components/ColorModeSwitch.vue +4 -4
- package/components/DocumentDrivenNotFound.vue +3 -3
- package/components/LanguageSwitcher.vue +40 -0
- package/components/MainNav.vue +11 -1
- package/components/content/ArticlesIndex.vue +5 -1
- package/components/content/ArticlesList.vue +5 -3
- package/components/content/ContactForm.vue +41 -37
- package/composables/date.ts +2 -1
- package/i18n/locales/en.json +55 -0
- package/i18n/locales/es.json +55 -0
- package/layouts/article.vue +3 -3
- package/nuxt.config.ts +16 -7
- package/package.json +3 -1
package/components/AppFooter.vue
CHANGED
|
@@ -24,6 +24,9 @@ const alpine = useAppConfig().alpine
|
|
|
24
24
|
<div v-if="alpine.socials && Object.entries(alpine.socials)" class="social">
|
|
25
25
|
<SocialIcons :socials="alpine.socials" />
|
|
26
26
|
</div>
|
|
27
|
+
<div class="language-switch">
|
|
28
|
+
<LanguageSwitcher />
|
|
29
|
+
</div>
|
|
27
30
|
<div class="color-mode-switch">
|
|
28
31
|
<ColorModeSwitch />
|
|
29
32
|
</div>
|
package/components/AppHeader.vue
CHANGED
|
@@ -7,7 +7,7 @@ const show = ref(false)
|
|
|
7
7
|
<template>
|
|
8
8
|
<header :class="alpine.header.position || 'left'">
|
|
9
9
|
<div class="menu">
|
|
10
|
-
<button @click="(show = !show)" aria-label="
|
|
10
|
+
<button @click="(show = !show)" :aria-label="$t('nav.menu')">
|
|
11
11
|
<svg width="24" height="24" viewBox="0 0 68 68" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
12
12
|
<path d="M8 34C8 32.1362 8 31.2044 8.30448 30.4693C8.71046 29.4892 9.48915 28.7105 10.4693 28.3045C11.2044 28 12.1362 28 14 28C15.8638 28 16.7956 28 17.5307 28.3045C18.5108 28.7105 19.2895 29.4892 19.6955 30.4693C20 31.2044 20 32.1362 20 34C20 35.8638 20 36.7956 19.6955 37.5307C19.2895 38.5108 18.5108 39.2895 17.5307 39.6955C16.7956 40 15.8638 40 14 40C12.1362 40 11.2044 40 10.4693 39.6955C9.48915 39.2895 8.71046 38.5108 8.30448 37.5307C8 36.7956 8 35.8638 8 34Z" />
|
|
13
13
|
<path d="M28 34C28 32.1362 28 31.2044 28.3045 30.4693C28.7105 29.4892 29.4892 28.7105 30.4693 28.3045C31.2044 28 32.1362 28 34 28C35.8638 28 36.7956 28 37.5307 28.3045C38.5108 28.7105 39.2895 29.4892 39.6955 30.4693C40 31.2044 40 32.1362 40 34C40 35.8638 40 36.7956 39.6955 37.5307C39.2895 38.5108 38.5108 39.2895 37.5307 39.6955C36.7956 40 35.8638 40 34 40C32.1362 40 31.2044 40 30.4693 39.6955C29.4892 39.2895 28.7105 38.5108 28.3045 37.5307C28 36.7956 28 35.8638 28 34Z" />
|
|
@@ -10,19 +10,19 @@ const onClick = () => {
|
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
12
|
<template>
|
|
13
|
-
<button aria-label="
|
|
13
|
+
<button :aria-label="$t('colorMode.label')" @click="onClick">
|
|
14
14
|
<ColorScheme>
|
|
15
15
|
<template v-if="colorMode.preference === 'dark'">
|
|
16
16
|
<Icon name="uil:moon" />
|
|
17
|
-
<span class="sr-only">
|
|
17
|
+
<span class="sr-only">{{ $t('colorMode.dark') }}</span>
|
|
18
18
|
</template>
|
|
19
19
|
<template v-else-if="colorMode.preference === 'light'">
|
|
20
20
|
<Icon name="uil:sun" />
|
|
21
|
-
<span class="sr-only">
|
|
21
|
+
<span class="sr-only">{{ $t('colorMode.light') }}</span>
|
|
22
22
|
</template>
|
|
23
23
|
<template v-else>
|
|
24
24
|
<Icon name="uil:desktop" />
|
|
25
|
-
<span class="sr-only">
|
|
25
|
+
<span class="sr-only">{{ $t('colorMode.system') }}</span>
|
|
26
26
|
</template>
|
|
27
27
|
</ColorScheme>
|
|
28
28
|
</button>
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<section>
|
|
3
3
|
<p class="message">
|
|
4
|
-
|
|
4
|
+
{{ $t('notFound.message') }}
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
<p class="status">
|
|
8
|
-
|
|
8
|
+
{{ $t('notFound.code') }}
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<NuxtLink to="/">
|
|
12
|
-
|
|
12
|
+
{{ $t('notFound.backHome') }}
|
|
13
13
|
<Icon name="ph:arrow-right" />
|
|
14
14
|
</NuxtLink>
|
|
15
15
|
</section>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const { locale, locales, setLocale } = useI18n()
|
|
3
|
+
const switchLocalePath = useSwitchLocalePath()
|
|
4
|
+
|
|
5
|
+
const availableLocales = computed(() =>
|
|
6
|
+
locales.value.filter((l: any) => l.code !== locale.value)
|
|
7
|
+
)
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<div class="language-switcher">
|
|
12
|
+
<NuxtLink
|
|
13
|
+
v-for="loc in availableLocales"
|
|
14
|
+
:key="loc.code"
|
|
15
|
+
:to="switchLocalePath(loc.code)"
|
|
16
|
+
class="locale-link"
|
|
17
|
+
>
|
|
18
|
+
{{ loc.code.toUpperCase() }}
|
|
19
|
+
</NuxtLink>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<style scoped lang="ts">
|
|
24
|
+
css({
|
|
25
|
+
'.language-switcher': {
|
|
26
|
+
display: 'flex',
|
|
27
|
+
alignItems: 'center',
|
|
28
|
+
gap: '{space.2}',
|
|
29
|
+
'.locale-link': {
|
|
30
|
+
fontSize: '{text.sm.fontSize}',
|
|
31
|
+
fontWeight: '{fontWeight.medium}',
|
|
32
|
+
padding: '{space.1} {space.2}',
|
|
33
|
+
borderRadius: '{radii.md}',
|
|
34
|
+
'&:hover': {
|
|
35
|
+
color: '{color.primary.500}',
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
</style>
|
package/components/MainNav.vue
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
const { navigation } = useContent()
|
|
3
|
+
const { locale } = useI18n()
|
|
3
4
|
|
|
4
5
|
const emits = defineEmits(['linkClick'])
|
|
5
6
|
|
|
6
7
|
function handleClick() {
|
|
7
8
|
emits('linkClick')
|
|
8
9
|
}
|
|
10
|
+
|
|
11
|
+
const localizedNavigation = computed(() => {
|
|
12
|
+
if (!navigation.value) return []
|
|
13
|
+
// Find the locale subtree in navigation (e.g. /es or /en)
|
|
14
|
+
const localeRoot = navigation.value.find(
|
|
15
|
+
(item: any) => item._path === `/${locale.value}`
|
|
16
|
+
)
|
|
17
|
+
return localeRoot?.children || navigation.value
|
|
18
|
+
})
|
|
9
19
|
</script>
|
|
10
20
|
|
|
11
21
|
<template>
|
|
12
22
|
<nav>
|
|
13
23
|
<ul>
|
|
14
24
|
<li
|
|
15
|
-
v-for="link of
|
|
25
|
+
v-for="link of localizedNavigation"
|
|
16
26
|
:key="link._path"
|
|
17
27
|
>
|
|
18
28
|
<NuxtLink
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { withTrailingSlash } from 'ufo'
|
|
3
3
|
import ArticleIndexEntry from './ArticleIndexEntry.vue';
|
|
4
4
|
|
|
5
|
+
const { locale } = useI18n()
|
|
6
|
+
|
|
5
7
|
const props = defineProps({
|
|
6
8
|
path: {
|
|
7
9
|
type: String,
|
|
@@ -9,8 +11,10 @@ const props = defineProps({
|
|
|
9
11
|
}
|
|
10
12
|
})
|
|
11
13
|
|
|
14
|
+
const contentPath = computed(() => `${locale.value}/${props.path}`)
|
|
15
|
+
|
|
12
16
|
// @ts-ignore
|
|
13
|
-
const { data: _articles } = await useAsyncData(
|
|
17
|
+
const { data: _articles } = await useAsyncData(contentPath.value, async () => await queryContent(withTrailingSlash(contentPath.value)).sort({ date: -1 }).find())
|
|
14
18
|
|
|
15
19
|
// create new fields year and month
|
|
16
20
|
// const articles = computed(() => _articles.value || [])
|
|
@@ -5,6 +5,7 @@ import { useRouter, useRoute } from 'vue-router'
|
|
|
5
5
|
|
|
6
6
|
const router = useRouter()
|
|
7
7
|
const route = useRoute()
|
|
8
|
+
const { locale } = useI18n()
|
|
8
9
|
|
|
9
10
|
const props = defineProps({
|
|
10
11
|
path: {
|
|
@@ -14,10 +15,11 @@ const props = defineProps({
|
|
|
14
15
|
})
|
|
15
16
|
|
|
16
17
|
const currentYear = ref(parseInt(route.query.year as string) || new Date().getFullYear())
|
|
17
|
-
const
|
|
18
|
+
const startYear = 2023
|
|
19
|
+
const years = ref(Array.from({ length: new Date().getFullYear() - startYear + 1 }, (_, i) => new Date().getFullYear() - i))
|
|
18
20
|
|
|
19
21
|
const fetchArticles = async (year: number) => {
|
|
20
|
-
const path = `${props.path}/${year}`
|
|
22
|
+
const path = `${locale.value}/${props.path}/${year}`
|
|
21
23
|
const { data } = await useAsyncData(path, async () => await queryContent(withTrailingSlash(path)).sort({ date: -1 }).find())
|
|
22
24
|
return data
|
|
23
25
|
}
|
|
@@ -70,7 +72,7 @@ const yearButtons = computed(() => {
|
|
|
70
72
|
</div>
|
|
71
73
|
</div>
|
|
72
74
|
<div v-else class="tour">
|
|
73
|
-
<p>
|
|
75
|
+
<p>{{ $t('articles.empty', { year: currentYear }) }}</p>
|
|
74
76
|
</div>
|
|
75
77
|
<div class="spacing"> </div>
|
|
76
78
|
<div class="navigation-buttons">
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { PropType } from 'vue'
|
|
3
3
|
import type { Field } from '../../types/contact'
|
|
4
4
|
const alpine = useAppConfig().alpine
|
|
5
|
+
const { t } = useI18n()
|
|
5
6
|
|
|
6
7
|
const { FORMSPREE_URL } = useRuntimeConfig().public
|
|
7
8
|
|
|
@@ -11,56 +12,59 @@ if (!FORMSPREE_URL) {
|
|
|
11
12
|
|
|
12
13
|
const status = ref()
|
|
13
14
|
|
|
15
|
+
const defaultFields = computed<Field[]>(() => [
|
|
16
|
+
{
|
|
17
|
+
type: 'text',
|
|
18
|
+
model: 'name',
|
|
19
|
+
name: t('form.fields.name.label'),
|
|
20
|
+
placeholder: t('form.fields.name.placeholder'),
|
|
21
|
+
required: true,
|
|
22
|
+
layout: 'default'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
type: 'email',
|
|
26
|
+
model: 'email',
|
|
27
|
+
name: t('form.fields.email.label'),
|
|
28
|
+
placeholder: t('form.fields.email.placeholder'),
|
|
29
|
+
required: true,
|
|
30
|
+
layout: 'default'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
type: 'text',
|
|
34
|
+
model: 'text',
|
|
35
|
+
name: t('form.fields.subject.label'),
|
|
36
|
+
required: false,
|
|
37
|
+
layout: 'default'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
type: 'textarea',
|
|
41
|
+
model: 'message',
|
|
42
|
+
name: t('form.fields.message.label'),
|
|
43
|
+
placeholder: t('form.fields.message.placeholder'),
|
|
44
|
+
required: true,
|
|
45
|
+
layout: 'big'
|
|
46
|
+
}
|
|
47
|
+
])
|
|
48
|
+
|
|
14
49
|
const props = defineProps({
|
|
15
50
|
submitButtonText: {
|
|
16
51
|
type: String,
|
|
17
|
-
default: '
|
|
52
|
+
default: ''
|
|
18
53
|
},
|
|
19
54
|
fields: {
|
|
20
55
|
type: Array as PropType<Field[]>,
|
|
21
|
-
default:
|
|
22
|
-
{
|
|
23
|
-
type: 'text',
|
|
24
|
-
model: 'name',
|
|
25
|
-
name: 'Name',
|
|
26
|
-
placeholder: 'Your name',
|
|
27
|
-
required: true,
|
|
28
|
-
layout: 'default'
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
type: 'email',
|
|
32
|
-
model: 'email',
|
|
33
|
-
name: 'Email',
|
|
34
|
-
placeholder: 'Your email',
|
|
35
|
-
required: true,
|
|
36
|
-
layout: 'default'
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
type: 'text',
|
|
40
|
-
model: 'text',
|
|
41
|
-
name: 'Subject',
|
|
42
|
-
required: false,
|
|
43
|
-
layout: 'default'
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
type: 'textarea',
|
|
47
|
-
model: 'message',
|
|
48
|
-
name: 'Message',
|
|
49
|
-
placeholder: 'Your message',
|
|
50
|
-
required: true,
|
|
51
|
-
layout: 'big'
|
|
52
|
-
}
|
|
53
|
-
]
|
|
56
|
+
default: null
|
|
54
57
|
}
|
|
55
58
|
})
|
|
56
59
|
|
|
57
|
-
const
|
|
60
|
+
const activeFields = computed(() => props.fields || defaultFields.value)
|
|
61
|
+
const form = reactive(activeFields.value.map(v => ({ ...v, data: '' })))
|
|
58
62
|
|
|
59
63
|
const onSend = async (e: any) => {
|
|
60
64
|
e.preventDefault()
|
|
61
65
|
const data = new FormData(e.target)
|
|
62
66
|
|
|
63
|
-
status.value = '
|
|
67
|
+
status.value = t('form.sending')
|
|
64
68
|
|
|
65
69
|
fetch(e.target.action, {
|
|
66
70
|
method: e.target.method,
|
|
@@ -101,7 +105,7 @@ const onSend = async (e: any) => {
|
|
|
101
105
|
</div>
|
|
102
106
|
<div>
|
|
103
107
|
<Button type="submit" :disabled="!FORMSPREE_URL">
|
|
104
|
-
{{ status ? status : submitButtonText }}
|
|
108
|
+
{{ status ? status : (submitButtonText || $t('form.submitButton')) }}
|
|
105
109
|
</Button>
|
|
106
110
|
</div>
|
|
107
111
|
</form>
|
package/composables/date.ts
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"colorMode": {
|
|
3
|
+
"label": "Color Mode",
|
|
4
|
+
"dark": "Dark mode",
|
|
5
|
+
"light": "Light mode",
|
|
6
|
+
"system": "System mode"
|
|
7
|
+
},
|
|
8
|
+
"nav": {
|
|
9
|
+
"menu": "Navigation Menu"
|
|
10
|
+
},
|
|
11
|
+
"notFound": {
|
|
12
|
+
"message": "This page could not be found",
|
|
13
|
+
"code": "404",
|
|
14
|
+
"backHome": "Back to homepage"
|
|
15
|
+
},
|
|
16
|
+
"article": {
|
|
17
|
+
"back": "Back",
|
|
18
|
+
"byAuthor": "By",
|
|
19
|
+
"backToTop": "Back to top"
|
|
20
|
+
},
|
|
21
|
+
"articles": {
|
|
22
|
+
"empty": "Seems like there are no articles for {year}."
|
|
23
|
+
},
|
|
24
|
+
"hero": {
|
|
25
|
+
"title": "Hero title",
|
|
26
|
+
"description": "Hero description"
|
|
27
|
+
},
|
|
28
|
+
"form": {
|
|
29
|
+
"submitButton": "Send message",
|
|
30
|
+
"sending": "Sending...",
|
|
31
|
+
"fields": {
|
|
32
|
+
"name": {
|
|
33
|
+
"label": "Name",
|
|
34
|
+
"placeholder": "Your name"
|
|
35
|
+
},
|
|
36
|
+
"email": {
|
|
37
|
+
"label": "Email",
|
|
38
|
+
"placeholder": "Your email"
|
|
39
|
+
},
|
|
40
|
+
"subject": {
|
|
41
|
+
"label": "Subject"
|
|
42
|
+
},
|
|
43
|
+
"message": {
|
|
44
|
+
"label": "Message",
|
|
45
|
+
"placeholder": "Your message"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"footer": {
|
|
50
|
+
"message": "Follow me on"
|
|
51
|
+
},
|
|
52
|
+
"app": {
|
|
53
|
+
"description": "The minimalist blog theme"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"colorMode": {
|
|
3
|
+
"label": "Modo de Color",
|
|
4
|
+
"dark": "Modo oscuro",
|
|
5
|
+
"light": "Modo claro",
|
|
6
|
+
"system": "Modo del sistema"
|
|
7
|
+
},
|
|
8
|
+
"nav": {
|
|
9
|
+
"menu": "Menú de Navegación"
|
|
10
|
+
},
|
|
11
|
+
"notFound": {
|
|
12
|
+
"message": "Esta página no pudo ser encontrada",
|
|
13
|
+
"code": "404",
|
|
14
|
+
"backHome": "Volver al inicio"
|
|
15
|
+
},
|
|
16
|
+
"article": {
|
|
17
|
+
"back": "Volver",
|
|
18
|
+
"byAuthor": "Por",
|
|
19
|
+
"backToTop": "Volver arriba"
|
|
20
|
+
},
|
|
21
|
+
"articles": {
|
|
22
|
+
"empty": "Parece que no hay artículos para {year}."
|
|
23
|
+
},
|
|
24
|
+
"hero": {
|
|
25
|
+
"title": "Título del héroe",
|
|
26
|
+
"description": "Descripción del héroe"
|
|
27
|
+
},
|
|
28
|
+
"form": {
|
|
29
|
+
"submitButton": "Enviar mensaje",
|
|
30
|
+
"sending": "Enviando...",
|
|
31
|
+
"fields": {
|
|
32
|
+
"name": {
|
|
33
|
+
"label": "Nombre",
|
|
34
|
+
"placeholder": "Tu nombre"
|
|
35
|
+
},
|
|
36
|
+
"email": {
|
|
37
|
+
"label": "Correo",
|
|
38
|
+
"placeholder": "Tu correo"
|
|
39
|
+
},
|
|
40
|
+
"subject": {
|
|
41
|
+
"label": "Asunto"
|
|
42
|
+
},
|
|
43
|
+
"message": {
|
|
44
|
+
"label": "Mensaje",
|
|
45
|
+
"placeholder": "Tu mensaje"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"footer": {
|
|
50
|
+
"message": "Sígueme en"
|
|
51
|
+
},
|
|
52
|
+
"app": {
|
|
53
|
+
"description": "El tema minimalista para blogs"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/layouts/article.vue
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
>
|
|
8
8
|
<Icon name="ph:arrow-left" />
|
|
9
9
|
<span>
|
|
10
|
-
|
|
10
|
+
{{ $t('article.back') }}
|
|
11
11
|
</span>
|
|
12
12
|
</NuxtLink>
|
|
13
13
|
<header>
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
{{ formatDate(page.date) }}
|
|
25
25
|
</time>
|
|
26
26
|
<span v-if="page?.author?.name" class="author">
|
|
27
|
-
•
|
|
27
|
+
• {{ $t('article.byAuthor') }} <strong>{{ page.author.name }}</strong>
|
|
28
28
|
</span>
|
|
29
29
|
</header>
|
|
30
30
|
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
class="back-to-top"
|
|
36
36
|
>
|
|
37
37
|
<ProseA @click.prevent.stop="onBackToTop">
|
|
38
|
-
{{ alpine?.backToTop?.text || '
|
|
38
|
+
{{ alpine?.backToTop?.text || $t('article.backToTop') }}
|
|
39
39
|
<Icon :name="alpine?.backToTop?.icon || 'material-symbols:arrow-upward'" />
|
|
40
40
|
</ProseA>
|
|
41
41
|
</div>
|
package/nuxt.config.ts
CHANGED
|
@@ -29,13 +29,7 @@ const updateModule = defineNuxtModule({
|
|
|
29
29
|
|
|
30
30
|
// https://v3.nuxtjs.org/api/configuration/nuxt.config
|
|
31
31
|
export default defineNuxtConfig({
|
|
32
|
-
app: {
|
|
33
|
-
head: {
|
|
34
|
-
htmlAttrs: {
|
|
35
|
-
lang: 'en'
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
},
|
|
32
|
+
app: {},
|
|
39
33
|
extends: [envModules.typography, envModules.elements],
|
|
40
34
|
runtimeConfig: {
|
|
41
35
|
public: {
|
|
@@ -47,8 +41,23 @@ export default defineNuxtConfig({
|
|
|
47
41
|
envModules.tokens,
|
|
48
42
|
envModules.studio,
|
|
49
43
|
'@nuxt/content',
|
|
44
|
+
'@nuxtjs/i18n',
|
|
50
45
|
updateModule as any
|
|
51
46
|
],
|
|
47
|
+
i18n: {
|
|
48
|
+
locales: [
|
|
49
|
+
{ code: 'es', language: 'es-PE', name: 'Español', file: 'es.json' },
|
|
50
|
+
{ code: 'en', language: 'en-US', name: 'English', file: 'en.json' }
|
|
51
|
+
],
|
|
52
|
+
defaultLocale: 'es',
|
|
53
|
+
strategy: 'prefix',
|
|
54
|
+
langDir: 'i18n/locales',
|
|
55
|
+
detectBrowserLanguage: {
|
|
56
|
+
useCookie: true,
|
|
57
|
+
cookieKey: 'i18n_locale',
|
|
58
|
+
redirectOn: 'root'
|
|
59
|
+
}
|
|
60
|
+
},
|
|
52
61
|
components: [
|
|
53
62
|
{ path: resolve('./components'), global: true },
|
|
54
63
|
{ path: resolve('./components/content'), global: true },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@4verburga/alpine-spanishplus",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.838f140",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"assets",
|
|
13
13
|
"components",
|
|
14
14
|
"composables",
|
|
15
|
+
"i18n",
|
|
15
16
|
"layouts",
|
|
16
17
|
"types",
|
|
17
18
|
"app.config.ts",
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
"@nuxt-themes/typography": "^0.11.0",
|
|
36
37
|
"@nuxt/content": "^2.13.0",
|
|
37
38
|
"@nuxthq/studio": "^0.14.1",
|
|
39
|
+
"@nuxtjs/i18n": "^8.5.5",
|
|
38
40
|
"@vueuse/core": "^10.7.2",
|
|
39
41
|
"ufo": "^1.5.4"
|
|
40
42
|
},
|