feat(i18n): French and German localization (phase 5)
- Add full message catalogs and content for French (fr) and German (de) - Implement ASCII canonical slugs for French and German routes - Add language-specific search endpoints (/api/busca/fr, /api/busca/de) - Configure strict 404 responses for /fr/livro and /de/livro - Localize SEO, OpenGraph (fr_FR, de_DE), Twitter and JSON-LD schemas - Add localized code example comments across 14 examples for fr and de - Enable 'fr' and 'de' in ENABLED_LOCALES with root negotiation and redirect - Extend test suite in check-i18n, smoke-imagem and verifica-vazamentos Co-Authored-By: Antigravity <noreply@google.com>
This commit is contained in:
1 parent
7b673aeb4b
commit
7fce46b9e1
104 files changed
+33369
-686
No files matched your search
@@ -63,8 +63,26 @@ export default function LanguageSelector() {
|
||||
className="flex h-11 min-w-[44px] items-center gap-1.5 rounded-full border border-line bg-surface px-3 text-sm font-semibold text-ink transition-colors hover:bg-surface-2 focus-visible:outline-2 focus-visible:outline-accent"
|
||||
aria-haspopup="listbox"
|
||||
aria-expanded={open}
|
||||
aria-label={currentLocaleCode === "en" ? `Current language: ${currentLocale.label}. Click to switch language.` : currentLocaleCode === "es" ? `Idioma actual: ${currentLocale.label}. Haga clic para cambiar de idioma.` : `Idioma atual: ${currentLocale.label}. Clique para trocar de idioma.`}
|
||||
title={currentLocaleCode === "en" ? `Language: ${currentLocale.label}` : `Idioma: ${currentLocale.label}`}
|
||||
aria-label={
|
||||
currentLocaleCode === "en"
|
||||
? `Current language: ${currentLocale.label}. Click to switch language.`
|
||||
: currentLocaleCode === "es"
|
||||
? `Idioma actual: ${currentLocale.label}. Haga clic para cambiar de idioma.`
|
||||
: currentLocaleCode === "fr"
|
||||
? `Langue actuelle : ${currentLocale.label}. Cliquez pour changer de langue.`
|
||||
: currentLocaleCode === "de"
|
||||
? `Aktuelle Sprache: ${currentLocale.label}. Klicken Sie, um die Sprache zu wechseln.`
|
||||
: `Idioma atual: ${currentLocale.label}. Clique para trocar de idioma.`
|
||||
}
|
||||
title={
|
||||
currentLocaleCode === "en"
|
||||
? `Language: ${currentLocale.label}`
|
||||
: currentLocaleCode === "fr"
|
||||
? `Langue : ${currentLocale.label}`
|
||||
: currentLocaleCode === "de"
|
||||
? `Sprache: ${currentLocale.label}`
|
||||
: `Idioma: ${currentLocale.label}`
|
||||
}
|
||||
>
|
||||
<Globe className="h-4 w-4 text-muted" aria-hidden="true" />
|
||||
<span className="font-semibold">{currentLocale.short}</span>
|
||||
@@ -77,7 +95,17 @@ export default function LanguageSelector() {
|
||||
{open && (
|
||||
<div
|
||||
role="listbox"
|
||||
aria-label={currentLocaleCode === "en" ? "Available languages" : currentLocaleCode === "es" ? "Idiomas disponibles" : "Idiomas disponíveis"}
|
||||
aria-label={
|
||||
currentLocaleCode === "en"
|
||||
? "Available languages"
|
||||
: currentLocaleCode === "es"
|
||||
? "Idiomas disponibles"
|
||||
: currentLocaleCode === "fr"
|
||||
? "Langues disponibles"
|
||||
: currentLocaleCode === "de"
|
||||
? "Verfügbare Sprachen"
|
||||
: "Idiomas disponíveis"
|
||||
}
|
||||
className="absolute right-0 top-full mt-2 w-48 rounded-2xl border border-line bg-surface p-1.5 shadow-[0_24px_60px_-20px_rgba(15,23,42,0.35)] dark:shadow-[0_24px_60px_-20px_rgba(0,0,0,0.8)] z-50"
|
||||
>
|
||||
{LOCALES.map((loc) => {
|
||||
|
||||
Reference in new issue
Block a user