Add hand-rolled English support (/en/*) alongside the Italian site
PocketBase gains optional, manually-authored English fields on articles and categories (same record, same slug), and the frontend serves an /en counterpart of every dynamic route via thin page wrappers around shared view components — no i18n library, consistent with the project's existing minimalism stance for a two-locale site with ~20 UI strings. An article/category with no translation 404s cleanly on its own /en detail page and is filtered out of /en listings, and the header's language-switch link falls back to the English blog index rather than a dead link; resolving that requires a global route middleware, since the layout's header renders before the page content in document order and so can't react to state a page component sets during its own async setup.
This commit is contained in:
@@ -1,26 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import { STRINGS } from '#shared/utils/i18n'
|
||||
import { localePath } from '#shared/utils/locale'
|
||||
|
||||
const locale = useLocale()
|
||||
const strings = computed(() => STRINGS[locale.value])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page">
|
||||
<a class="skip-link" href="#main">Vai al contenuto</a>
|
||||
<a class="skip-link" href="#main">{{ strings.skipLink }}</a>
|
||||
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
<p class="wordmark">
|
||||
<NuxtLink to="/">
|
||||
<NuxtLink :to="localePath(locale, '/')">
|
||||
<img src="/logo.png" :alt="SITE_NAME" width="400" height="400">
|
||||
</NuxtLink>
|
||||
</p>
|
||||
<p class="tagline kicker">Articoli, guide e analisi.</p>
|
||||
<p class="tagline kicker">{{ strings.tagline }}</p>
|
||||
<p class="lang-switch-header">
|
||||
<LanguageSwitch />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<nav class="site-nav" aria-label="Navigazione principale">
|
||||
<nav class="site-nav" :aria-label="strings.navAriaLabel">
|
||||
<div class="container nav-inner">
|
||||
<ul>
|
||||
<li><NuxtLink to="/">Home</NuxtLink></li>
|
||||
<li><NuxtLink to="/blog">Tutti gli articoli</NuxtLink></li>
|
||||
<li><NuxtLink to="/come-difendersi-dal-corralito">Come difendersi dal corralito</NuxtLink></li>
|
||||
<li><NuxtLink :to="localePath(locale, '/')">{{ strings.navHome }}</NuxtLink></li>
|
||||
<li><NuxtLink :to="localePath(locale, '/blog')">{{ strings.navBlog }}</NuxtLink></li>
|
||||
<li v-if="locale === 'it'">
|
||||
<NuxtLink to="/come-difendersi-dal-corralito">{{ strings.navCorralito }}</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -34,24 +44,26 @@
|
||||
<div class="container footer-inner">
|
||||
<div class="footer-block">
|
||||
<img class="footer-logo" src="/logo.png" :alt="SITE_NAME" width="400" height="400">
|
||||
<p class="muted">Articoli, guide e analisi.</p>
|
||||
<p class="muted">{{ strings.tagline }}</p>
|
||||
<address class="contact">
|
||||
Contatti:
|
||||
{{ strings.contactLabel }}
|
||||
<a :href="`mailto:${SITE_EMAIL}`">{{ SITE_EMAIL }}</a>
|
||||
</address>
|
||||
</div>
|
||||
|
||||
<nav class="footer-block" aria-label="Naviga">
|
||||
<p class="kicker">Naviga</p>
|
||||
<nav class="footer-block" :aria-label="strings.footerNavAriaLabel">
|
||||
<p class="kicker">{{ strings.footerNavigaKicker }}</p>
|
||||
<ul>
|
||||
<li><NuxtLink to="/">Home</NuxtLink></li>
|
||||
<li><NuxtLink to="/blog">Tutti gli articoli</NuxtLink></li>
|
||||
<li><NuxtLink to="/come-difendersi-dal-corralito">Come difendersi dal corralito</NuxtLink></li>
|
||||
<li><NuxtLink :to="localePath(locale, '/')">{{ strings.navHome }}</NuxtLink></li>
|
||||
<li><NuxtLink :to="localePath(locale, '/blog')">{{ strings.navBlog }}</NuxtLink></li>
|
||||
<li v-if="locale === 'it'">
|
||||
<NuxtLink to="/come-difendersi-dal-corralito">{{ strings.navCorralito }}</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<nav class="footer-block" aria-label="Seguici">
|
||||
<p class="kicker">Seguici</p>
|
||||
<nav class="footer-block" :aria-label="strings.footerFollowAriaLabel">
|
||||
<p class="kicker">{{ strings.footerSeguiciKicker }}</p>
|
||||
<ul>
|
||||
<li v-for="social in SOCIAL_LINKS" :key="social.name">
|
||||
<a class="social" :href="social.url" target="_blank" rel="noopener me">
|
||||
@@ -64,7 +76,7 @@
|
||||
</div>
|
||||
|
||||
<p class="container copyright kicker">
|
||||
© {{ new Date().getFullYear() }} {{ SITE_NAME }}. Tutti i diritti riservati.
|
||||
© {{ new Date().getFullYear() }} {{ SITE_NAME }}. {{ strings.copyright }}
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
@@ -109,6 +121,10 @@
|
||||
margin-top: 0.6rem;
|
||||
}
|
||||
|
||||
.lang-switch-header {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
margin-top: 1.25rem;
|
||||
border-top: 1px solid var(--color-border);
|
||||
|
||||
Reference in New Issue
Block a user