+
+ {/* min-w reserves the longest translation ("Iniciar sesión" /
+ "Registrarse"), so language switches never resize these */}
{t('nav.login')}
{t('nav.signUp')}
diff --git a/client/src/i18n/index.ts b/client/src/i18n/index.ts
index cabc612..f789727 100644
--- a/client/src/i18n/index.ts
+++ b/client/src/i18n/index.ts
@@ -14,4 +14,19 @@ i18n.use(initReactI18next).init({
interpolation: { escapeValue: false },
});
+/** Full BCP 47 tags for the html lang attribute. */
+const HTML_LANG: Record = { en: 'en', pt: 'pt-BR', es: 'es' };
+
+/** Keeps tab title, meta description, and html lang in the active language. */
+function syncDocumentLanguage(language: string): void {
+ document.title = i18n.t('meta.title');
+ document
+ .querySelector('meta[name="description"]')
+ ?.setAttribute('content', i18n.t('meta.description'));
+ document.documentElement.lang = HTML_LANG[language] ?? language;
+}
+
+syncDocumentLanguage(lng);
+i18n.on('languageChanged', syncDocumentLanguage);
+
export default i18n;
diff --git a/client/src/i18n/locales/en.json b/client/src/i18n/locales/en.json
index 2d0554e..7c50762 100644
--- a/client/src/i18n/locales/en.json
+++ b/client/src/i18n/locales/en.json
@@ -4,7 +4,9 @@
"leaderboard": "Leaderboard",
"login": "Log In",
"signUp": "Sign Up",
- "logout": "Log Out"
+ "logout": "Log Out",
+ "language": "Change language",
+ "theme": "Toggle theme"
},
"home": {
"tagline": "Open Source · Free Forever",
@@ -15,11 +17,26 @@
"featuresTitle": "Everything you need to play chess",
"featuresSubtitle": "A full chess experience with no subscriptions, no ads, no tracking.",
"features": {
- "realtime": { "title": "Real-time Play", "desc": "Live games with instant moves. No delays, no lag." },
- "bots": { "title": "Play vs Stockfish", "desc": "Challenge the world's strongest engine at any difficulty." },
- "analysis": { "title": "Move Analysis", "desc": "Automatic post-game review with move classifications." },
- "ladder": { "title": "Leaderboards", "desc": "Separate ratings for bullet, blitz, rapid, and classical." },
- "multilang": { "title": "Multilingual", "desc": "Full support for English, Portuguese, and Spanish." }
+ "realtime": {
+ "title": "Real-time Play",
+ "desc": "Live games with instant moves. No delays, no lag."
+ },
+ "bots": {
+ "title": "Play vs Stockfish",
+ "desc": "Challenge the world's strongest engine at any difficulty."
+ },
+ "analysis": {
+ "title": "Move Analysis",
+ "desc": "Automatic post-game review with move classifications."
+ },
+ "ladder": {
+ "title": "Leaderboards",
+ "desc": "Separate ratings for bullet, blitz, rapid, and classical."
+ },
+ "multilang": {
+ "title": "Multilingual",
+ "desc": "Full support for English, Portuguese, and Spanish."
+ }
}
},
"play": {
@@ -129,5 +146,9 @@
"theme": {
"light": "Light",
"dark": "Dark"
+ },
+ "meta": {
+ "title": "ChessKernel: free, open-source chess platform",
+ "description": "Play chess online on your own terms: real-time multiplayer, Stockfish analysis, and Glicko-2 ratings. Free, open source, self-hostable, no ads or subscriptions."
}
}
diff --git a/client/src/i18n/locales/es.json b/client/src/i18n/locales/es.json
index 3ec49ae..ec2bdd2 100644
--- a/client/src/i18n/locales/es.json
+++ b/client/src/i18n/locales/es.json
@@ -4,7 +4,9 @@
"leaderboard": "Clasificación",
"login": "Iniciar sesión",
"signUp": "Registrarse",
- "logout": "Cerrar sesión"
+ "logout": "Cerrar sesión",
+ "language": "Cambiar idioma",
+ "theme": "Cambiar tema"
},
"home": {
"tagline": "Código Abierto · Gratuito Para Siempre",
@@ -15,11 +17,26 @@
"featuresTitle": "Todo lo que necesitas para jugar ajedrez",
"featuresSubtitle": "Una experiencia completa sin suscripciones, sin anuncios, sin rastreo.",
"features": {
- "realtime": { "title": "Juego en Vivo", "desc": "Partidas en directo con movimientos instantáneos." },
- "bots": { "title": "vs Stockfish", "desc": "Desafía al mejor motor de ajedrez en cualquier nivel." },
- "analysis": { "title": "Análisis de Jugadas", "desc": "Revisión automática con clasificación de jugadas." },
- "ladder": { "title": "Clasificación", "desc": "Ratings separados para bullet, blitz, rapid y clásico." },
- "multilang": { "title": "Multilingüe", "desc": "Soporte completo para inglés, portugués y español." }
+ "realtime": {
+ "title": "Juego en Vivo",
+ "desc": "Partidas en directo con movimientos instantáneos."
+ },
+ "bots": {
+ "title": "vs Stockfish",
+ "desc": "Desafía al mejor motor de ajedrez en cualquier nivel."
+ },
+ "analysis": {
+ "title": "Análisis de Jugadas",
+ "desc": "Revisión automática con clasificación de jugadas."
+ },
+ "ladder": {
+ "title": "Clasificación",
+ "desc": "Ratings separados para bullet, blitz, rapid y clásico."
+ },
+ "multilang": {
+ "title": "Multilingüe",
+ "desc": "Soporte completo para inglés, portugués y español."
+ }
}
},
"play": {
@@ -129,5 +146,9 @@
"theme": {
"light": "Claro",
"dark": "Oscuro"
+ },
+ "meta": {
+ "title": "ChessKernel: plataforma de ajedrez gratuita y de código abierto",
+ "description": "Juega al ajedrez online a tu manera: multijugador en tiempo real, análisis con Stockfish y puntuaciones Glicko-2. Gratis, de código abierto y autoalojable, sin anuncios ni suscripciones."
}
}
diff --git a/client/src/i18n/locales/pt.json b/client/src/i18n/locales/pt.json
index 53d45e8..b4d154e 100644
--- a/client/src/i18n/locales/pt.json
+++ b/client/src/i18n/locales/pt.json
@@ -4,7 +4,9 @@
"leaderboard": "Placar",
"login": "Entrar",
"signUp": "Cadastrar",
- "logout": "Sair"
+ "logout": "Sair",
+ "language": "Mudar idioma",
+ "theme": "Alternar tema"
},
"home": {
"tagline": "Código Aberto · Gratuito Para Sempre",
@@ -15,11 +17,26 @@
"featuresTitle": "Tudo que você precisa para jogar xadrez",
"featuresSubtitle": "Uma experiência completa sem assinaturas, sem anúncios, sem rastreamento.",
"features": {
- "realtime": { "title": "Jogo em Tempo Real", "desc": "Partidas ao vivo com lances instantâneos." },
- "bots": { "title": "vs Stockfish", "desc": "Desafie o melhor motor de xadrez em qualquer nível." },
- "analysis": { "title": "Análise de Lances", "desc": "Revisão automática com classificação de lances." },
- "ladder": { "title": "Classificação", "desc": "Ratings separados para bullet, blitz, rapid e clássico." },
- "multilang": { "title": "Multilíngue", "desc": "Suporte completo para inglês, português e espanhol." }
+ "realtime": {
+ "title": "Jogo em Tempo Real",
+ "desc": "Partidas ao vivo com lances instantâneos."
+ },
+ "bots": {
+ "title": "vs Stockfish",
+ "desc": "Desafie o melhor motor de xadrez em qualquer nível."
+ },
+ "analysis": {
+ "title": "Análise de Lances",
+ "desc": "Revisão automática com classificação de lances."
+ },
+ "ladder": {
+ "title": "Classificação",
+ "desc": "Ratings separados para bullet, blitz, rapid e clássico."
+ },
+ "multilang": {
+ "title": "Multilíngue",
+ "desc": "Suporte completo para inglês, português e espanhol."
+ }
}
},
"play": {
@@ -129,5 +146,9 @@
"theme": {
"light": "Claro",
"dark": "Escuro"
+ },
+ "meta": {
+ "title": "ChessKernel: plataforma de xadrez gratuita e open source",
+ "description": "Jogue xadrez online do seu jeito: multiplayer em tempo real, análise com Stockfish e ratings Glicko-2. Gratuito, open source e auto-hospedável, sem anúncios ou assinaturas."
}
}