Add Spanish (Latin American) activities translations

Full activities i18n for Spanish: categories, detail page, tickets,
filters. Uses Latin American terminology (boleto instead of entrada,
charla instead of ponencia). Added Spanish to the standalone app
Settings language picker alongside French and English.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-04-20 13:08:37 +02:00
commit 36c8cb8c7a
2 changed files with 72 additions and 5 deletions

View file

@ -11,6 +11,12 @@ import { Sun, Moon, LogIn, LogOut } from 'lucide-vue-next'
const { theme, setTheme } = useTheme() const { theme, setTheme } = useTheme()
const { locale } = useI18n() const { locale } = useI18n()
const languages: { code: AvailableLocale; label: string }[] = [
{ code: 'fr', label: 'Français' },
{ code: 'en', label: 'English' },
{ code: 'es', label: 'Español' },
]
const isAuthenticated = computed(() => auth.isAuthenticated.value) const isAuthenticated = computed(() => auth.isAuthenticated.value)
const userPubkey = computed(() => auth.currentUser.value?.pubkey) const userPubkey = computed(() => auth.currentUser.value?.pubkey)
@ -75,13 +81,13 @@ async function handleLogout() {
<h2 class="text-sm font-medium text-muted-foreground uppercase tracking-wide">Language</h2> <h2 class="text-sm font-medium text-muted-foreground uppercase tracking-wide">Language</h2>
<div class="flex gap-2"> <div class="flex gap-2">
<Button <Button
v-for="lang in (['fr', 'en'] as const)" v-for="lang in languages"
:key="lang" :key="lang.code"
:variant="locale === lang ? 'default' : 'outline'" :variant="locale === lang.code ? 'default' : 'outline'"
size="sm" size="sm"
@click="setLanguage(lang)" @click="setLanguage(lang.code)"
> >
{{ lang === 'fr' ? 'Français' : 'English' }} {{ lang.label }}
</Button> </Button>
</div> </div>
</div> </div>

View file

@ -30,6 +30,67 @@ const messages: LocaleMessages = {
de: 'Alemán', de: 'Alemán',
zh: 'Chino' zh: 'Chino'
}, },
activities: {
title: 'Actividades',
createNew: 'Crear actividad',
noActivities: 'No se encontraron actividades',
filters: {
all: 'Todas',
today: 'Hoy',
tomorrow: 'Mañana',
thisWeek: 'Esta semana',
thisMonth: 'Este mes',
},
categories: {
concert: 'Concierto',
workshop: 'Taller',
market: 'Mercado',
festival: 'Festival',
exhibition: 'Exposición',
sport: 'Deporte',
theater: 'Teatro',
cinema: 'Cine',
party: 'Fiesta',
talk: 'Charla',
conference: 'Conferencia',
meetup: 'Encuentro',
food: 'Gastronomía',
outdoor: 'Al aire libre',
kids: 'Niños',
wellness: 'Bienestar',
technology: 'Tecnología',
art: 'Arte',
music: 'Música',
dance: 'Danza',
literature: 'Literatura',
comedy: 'Comedia',
charity: 'Solidario',
tradition: 'Tradición',
other: 'Otro',
},
detail: {
getTicket: 'Obtener boleto',
going: 'Voy',
maybe: 'Tal vez',
notGoing: 'No voy',
contactOrganizer: 'Contactar organizador',
organizer: 'Organizador',
location: 'Ubicación',
when: 'Cuándo',
tickets: 'Boletos',
ticketsAvailable: '{count} boletos disponibles',
soldOut: 'Agotado',
free: 'Gratis',
},
tickets: {
myTickets: 'Mis boletos',
scanTicket: 'Escanear boleto',
noTickets: 'Aún no tienes boletos',
paid: 'Pagado',
pending: 'Pendiente',
registered: 'Registrado',
},
},
dateTimeFormats: { dateTimeFormats: {
short: { short: {
year: 'numeric', year: 'numeric',