Skip to content

Commit 56d5f25

Browse files
devsart95claude
andcommitted
fix(i18n): cubrir todos los strings visibles sin traducir
- Hero: subtítulo 'Fullstack developer · AI enthusiast · Agro worker.' → t() - About: 'identity record' → t('about.hud.title'), con versión JA 'プロフィール' - Skills: titleKey de AI/Web/Cloud usan claves i18n; badge FAST BUILDER → t() - Connect: label email hardcodeado → t('connect.form.email') - ThemeToggle: LIGHT/DARK y aria-label → t() - LangSelector: aria-labels → t('lang.aria') / t('lang.switch') - Translations: agrega hero.subtitle, about.hud.title, skills.*.title, connect.form.email, theme.*, lang.* en ES/EN/JA Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 45f010b commit 56d5f25

File tree

7 files changed

+76
-30
lines changed

7 files changed

+76
-30
lines changed

src/components/LangSelector.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ const LANGS: { code: Lang; label: string }[] = [
88
]
99

1010
export function LangSelector() {
11-
const { lang, setLang } = useLang()
11+
const { lang, setLang, t } = useLang()
1212

1313
return (
14-
<div className="lang-selector" role="group" aria-label="Language selector">
14+
<div className="lang-selector" role="group" aria-label={t('lang.aria')}>
1515
{LANGS.map(({ code, label }) => (
1616
<button
1717
key={code}
1818
onClick={() => setLang(code)}
1919
aria-pressed={lang === code}
20-
aria-label={`Switch to ${label}`}
20+
aria-label={`${t('lang.switch')} ${label}`}
2121
className={`lang-btn${lang === code ? ' lang-btn-active' : ''}`}
2222
>
2323
{label}

src/components/ThemeToggle.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
import { useEffect, useState } from 'react'
2+
import { useLang } from '../context/LangContext'
23

34
export function ThemeToggle() {
45
const [theme, setTheme] = useState<'dark'|'light'>(
56
() => (localStorage.getItem('theme') as 'dark'|'light') || 'dark'
67
)
8+
const { t } = useLang()
79

810
useEffect(() => {
911
document.documentElement.setAttribute('data-theme', theme)
1012
localStorage.setItem('theme', theme)
1113
}, [theme])
1214

13-
const toggle = () => setTheme(t => t === 'dark' ? 'light' : 'dark')
15+
const toggle = () => setTheme(prev => prev === 'dark' ? 'light' : 'dark')
1416

1517
return (
1618
<button
1719
onClick={toggle}
18-
aria-label="Toggle theme"
20+
aria-label={t('theme.aria')}
1921
aria-pressed={theme === 'light'}
2022
style={{
2123
position: 'fixed',
@@ -37,7 +39,7 @@ export function ThemeToggle() {
3739
}}
3840
>
3941
<span style={{ fontSize: 14 }}>{theme === 'dark' ? '◐' : '◑'}</span>
40-
{theme === 'dark' ? 'LIGHT' : 'DARK'}
42+
{theme === 'dark' ? t('theme.light') : t('theme.dark')}
4143
</button>
4244
)
4345
}

src/components/sections/About.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export function About() {
5050
</svg>
5151

5252
<div className="hud-header">
53-
<span className="hud-title-text">identity record</span>
53+
<span className="hud-title-text">{t('about.hud.title')}</span>
5454
<div className="hud-title-line" />
5555
<span className="hud-badge">v2.026</span>
5656
</div>

src/components/sections/Connect.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ export function Connect() {
138138
</div>
139139

140140
<div className="cf-field">
141-
<label className="cf-label" htmlFor="cf-email">email</label>
141+
<label className="cf-label" htmlFor="cf-email">{t('connect.form.email')}</label>
142142
<input
143143
id="cf-email"
144144
className="cf-input"

src/components/sections/Hero.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function Hero() {
2222
</h1>
2323

2424
<p className="hero-tagline">
25-
<strong>Fullstack developer</strong> · AI enthusiast · Agro worker.<br />
25+
{t('hero.subtitle')}<br />
2626
{t('hero.tagline')}
2727
</p>
2828

src/components/sections/Skills.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface Domain {
1111
id: string
1212
color: string
1313
badge?: string
14+
badgeKey?: Parameters<ReturnType<typeof useLang>['t']>[0]
1415
titleKey: string
1516
subKey: string
1617
icon: ReactNode
@@ -20,7 +21,7 @@ interface Domain {
2021
const DOMAINS: Domain[] = [
2122
{
2223
id: 'ai', color: '#a78bfa', badge: 'SPECIALIST',
23-
titleKey: 'AI & LLMs', subKey: 'skills.ai.sub',
24+
titleKey: 'skills.ai.title', subKey: 'skills.ai.sub',
2425
icon: (
2526
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
2627
<path d="M12 2a10 10 0 0 1 10 10c0 5.52-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2z" opacity=".3"/>
@@ -64,8 +65,8 @@ const DOMAINS: Domain[] = [
6465
],
6566
},
6667
{
67-
id: 'dev', color: '#34d399', badge: 'FAST BUILDER',
68-
titleKey: 'Web & Apps', subKey: 'skills.dev.sub',
68+
id: 'dev', color: '#34d399', badgeKey: 'skills.badge.fast' as const,
69+
titleKey: 'skills.dev.title', subKey: 'skills.dev.sub',
6970
icon: (
7071
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
7172
<polyline points="16 18 22 12 16 6"/>
@@ -128,7 +129,7 @@ const DOMAINS: Domain[] = [
128129
},
129130
{
130131
id: 'cloud', color: '#38bdf8',
131-
titleKey: 'Cloud & DevOps', subKey: 'skills.cloud.sub',
132+
titleKey: 'skills.cloud.title', subKey: 'skills.cloud.sub',
132133
icon: (
133134
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
134135
<path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z"/>
@@ -165,8 +166,9 @@ export function Skills() {
165166

166167
<div className="skills-map">
167168
{DOMAINS.map((d, i) => {
168-
const title = d.titleKey.startsWith('skills.') ? t(d.titleKey as Parameters<typeof t>[0]) : d.titleKey
169+
const title = t(d.titleKey as Parameters<typeof t>[0])
169170
const sub = t(d.subKey as Parameters<typeof t>[0])
171+
const badge = d.badgeKey ? t(d.badgeKey) : d.badge
170172
return (
171173
<div
172174
key={d.id}
@@ -181,7 +183,7 @@ export function Skills() {
181183
<span className="sd-title">{title}</span>
182184
<span className="sd-sub">{sub}</span>
183185
</div>
184-
{d.badge && <span className="sd-badge">{d.badge}</span>}
186+
{badge && <span className="sd-badge">{badge}</span>}
185187
</div>
186188
<div className="sd-tools">
187189
{d.tools.map(tool => (

src/i18n/translations.ts

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ export const translations = {
99
'nav.contact': 'contacto',
1010
'nav.aria': 'Navegación principal',
1111
// Hero
12-
'hero.available': 'disponible · San Pedro, Paraguay 🇵🇾',
13-
'hero.tagline': 'Construyendo herramientas que importan desde San Pedro, Paraguay.',
12+
'hero.available': 'disponible · San Pedro, Paraguay 🇵🇾',
13+
'hero.subtitle': 'Fullstack developer · AI enthusiast · Agro worker.',
14+
'hero.tagline': 'Construyendo herramientas que importan desde San Pedro, Paraguay.',
1415
'hero.cta.connect': 'conectar',
1516
'hero.cta.about': 'sobre mí',
1617
// Typewriter
@@ -22,6 +23,7 @@ export const translations = {
2223
// About
2324
'about.tag': '// whoami',
2425
'about.h2': 'Sobre mí',
26+
'about.hud.title': 'identity record',
2527
'about.key.name': 'nombre',
2628
'about.key.alias': 'alias',
2729
'about.key.location': 'ubicación',
@@ -38,23 +40,28 @@ export const translations = {
3840
'stack.tag': '// stack',
3941
'stack.h2': 'Tecnologías',
4042
// Skills
41-
'skills.tag': '// skills',
42-
'skills.h2': 'Skills Map',
43-
'skills.ai.sub': 'Modelos de lenguaje e integración de IA',
44-
'skills.cloud.sub': 'Infraestructura en la nube y servidores',
45-
'skills.bots.title': 'Bots & Mensajería',
46-
'skills.bots.sub': 'Canales conversacionales y automatización inteligente',
47-
'skills.dev.sub': 'TypeScript, React, Next.js y APIs modernas',
43+
'skills.tag': '// skills',
44+
'skills.h2': 'Skills Map',
45+
'skills.ai.title': 'AI & LLMs',
46+
'skills.ai.sub': 'Modelos de lenguaje e integración de IA',
47+
'skills.cloud.title': 'Cloud & DevOps',
48+
'skills.cloud.sub': 'Infraestructura en la nube y servidores',
49+
'skills.bots.title': 'Bots & Mensajería',
50+
'skills.bots.sub': 'Canales conversacionales y automatización inteligente',
51+
'skills.dev.title': 'Web & Apps',
52+
'skills.dev.sub': 'TypeScript, React, Next.js y APIs modernas',
4853
'skills.python.title': 'Python & Data',
4954
'skills.python.sub': 'Backend, procesamiento de datos y scripts avanzados',
50-
'skills.saas.title': 'SaaS & ERP Builder',
51-
'skills.saas.sub': 'Productos verticales, ERP y SaaS para LATAM',
55+
'skills.saas.title': 'SaaS & ERP Builder',
56+
'skills.saas.sub': 'Productos verticales, ERP y SaaS para LATAM',
57+
'skills.badge.fast': 'FAST BUILDER',
5258
// Connect
5359
'connect.tag': '// social',
5460
'connect.h2': 'Conectar',
5561
'connect.form.title': '// mensaje directo',
5662
'connect.form.name': 'nombre',
5763
'connect.form.name.ph': 'Tu nombre',
64+
'connect.form.email': 'email',
5865
'connect.form.email.ph': 'tu@email.com',
5966
'connect.form.message': 'mensaje',
6067
'connect.form.message.ph': '¿En qué puedo ayudarte?',
@@ -64,6 +71,13 @@ export const translations = {
6471
'connect.form.ok.sub': 'Recibí tu mensaje y te respondo a la brevedad.',
6572
'connect.form.err.fields': 'Completá todos los campos',
6673
'connect.form.err.send': 'Error al enviar, intentá de nuevo',
74+
// Theme toggle
75+
'theme.light': 'LIGHT',
76+
'theme.dark': 'DARK',
77+
'theme.aria': 'Cambiar tema',
78+
// Lang selector
79+
'lang.aria': 'Selector de idioma',
80+
'lang.switch': 'Cambiar a',
6781
// Footer
6882
'footer.built': 'built with ♥ caffeine & late nights',
6983
},
@@ -76,8 +90,9 @@ export const translations = {
7690
'nav.contact': 'contact',
7791
'nav.aria': 'Main navigation',
7892
// Hero
79-
'hero.available': 'available · San Pedro, Paraguay 🇵🇾',
80-
'hero.tagline': 'Building tools that matter from San Pedro, Paraguay.',
93+
'hero.available': 'available · San Pedro, Paraguay 🇵🇾',
94+
'hero.subtitle': 'Fullstack developer · AI enthusiast · Agro worker.',
95+
'hero.tagline': 'Building tools that matter from San Pedro, Paraguay.',
8196
'hero.cta.connect': 'connect',
8297
'hero.cta.about': 'about me',
8398
// Typewriter
@@ -89,6 +104,7 @@ export const translations = {
89104
// About
90105
'about.tag': '// whoami',
91106
'about.h2': 'About me',
107+
'about.hud.title': 'identity record',
92108
'about.key.name': 'name',
93109
'about.key.alias': 'alias',
94110
'about.key.location': 'location',
@@ -107,21 +123,26 @@ export const translations = {
107123
// Skills
108124
'skills.tag': '// skills',
109125
'skills.h2': 'Skills Map',
126+
'skills.ai.title': 'AI & LLMs',
110127
'skills.ai.sub': 'Language models & AI integration',
128+
'skills.cloud.title': 'Cloud & DevOps',
111129
'skills.cloud.sub': 'Cloud infrastructure & servers',
112130
'skills.bots.title': 'Bots & Messaging',
113131
'skills.bots.sub': 'Conversational channels & smart automation',
132+
'skills.dev.title': 'Web & Apps',
114133
'skills.dev.sub': 'TypeScript, React, Next.js & modern APIs',
115134
'skills.python.title': 'Python & Data',
116135
'skills.python.sub': 'Backend, data processing & advanced scripts',
117136
'skills.saas.title': 'SaaS & ERP Builder',
118137
'skills.saas.sub': 'Vertical products, ERP & SaaS for LATAM',
138+
'skills.badge.fast': 'FAST BUILDER',
119139
// Connect
120140
'connect.tag': '// social',
121141
'connect.h2': 'Connect',
122142
'connect.form.title': '// direct message',
123143
'connect.form.name': 'name',
124144
'connect.form.name.ph': 'Your name',
145+
'connect.form.email': 'email',
125146
'connect.form.email.ph': 'you@email.com',
126147
'connect.form.message': 'message',
127148
'connect.form.message.ph': 'How can I help you?',
@@ -131,6 +152,13 @@ export const translations = {
131152
'connect.form.ok.sub': 'Got your message — I\'ll get back to you shortly.',
132153
'connect.form.err.fields': 'Please fill in all fields',
133154
'connect.form.err.send': 'Send error, please try again',
155+
// Theme toggle
156+
'theme.light': 'LIGHT',
157+
'theme.dark': 'DARK',
158+
'theme.aria': 'Toggle theme',
159+
// Lang selector
160+
'lang.aria': 'Language selector',
161+
'lang.switch': 'Switch to',
134162
// Footer
135163
'footer.built': 'built with ♥ caffeine & late nights',
136164
},
@@ -143,8 +171,9 @@ export const translations = {
143171
'nav.contact': '連絡',
144172
'nav.aria': 'メインナビゲーション',
145173
// Hero
146-
'hero.available': 'オンライン · サン・ペドロ, パラグアイ 🇵🇾',
147-
'hero.tagline': 'パラグアイのサン・ペドロから、重要なツールを作っています。',
174+
'hero.available': 'オンライン · サン・ペドロ, パラグアイ 🇵🇾',
175+
'hero.subtitle': 'Fullstack developer · AI enthusiast · Agro worker.',
176+
'hero.tagline': 'パラグアイのサン・ペドロから、重要なツールを作っています。',
148177
'hero.cta.connect': 'コンタクト',
149178
'hero.cta.about': '自己紹介',
150179
// Typewriter
@@ -156,6 +185,7 @@ export const translations = {
156185
// About
157186
'about.tag': '// whoami',
158187
'about.h2': '自己紹介',
188+
'about.hud.title': 'プロフィール',
159189
'about.key.name': '名前',
160190
'about.key.alias': '別名',
161191
'about.key.location': '所在地',
@@ -174,21 +204,26 @@ export const translations = {
174204
// Skills
175205
'skills.tag': '// skills',
176206
'skills.h2': 'スキルマップ',
207+
'skills.ai.title': 'AI & LLMs',
177208
'skills.ai.sub': '言語モデルとAI統合',
209+
'skills.cloud.title': 'Cloud & DevOps',
178210
'skills.cloud.sub': 'クラウドインフラとサーバー',
179211
'skills.bots.title': 'ボット & メッセージング',
180212
'skills.bots.sub': '会話チャネルとスマート自動化',
213+
'skills.dev.title': 'Web & アプリ',
181214
'skills.dev.sub': 'TypeScript、React、Next.js とモダンAPI',
182215
'skills.python.title': 'Python & データ',
183216
'skills.python.sub': 'バックエンド、データ処理、スクリプト',
184217
'skills.saas.title': 'SaaS & ERPビルダー',
185218
'skills.saas.sub': 'LATAMのバーティカルプロダクト・ERP・SaaS',
219+
'skills.badge.fast': 'FAST BUILDER',
186220
// Connect
187221
'connect.tag': '// social',
188222
'connect.h2': 'コンタクト',
189223
'connect.form.title': '// ダイレクトメッセージ',
190224
'connect.form.name': '名前',
191225
'connect.form.name.ph': 'お名前',
226+
'connect.form.email': 'メール',
192227
'connect.form.email.ph': 'メールアドレス',
193228
'connect.form.message': 'メッセージ',
194229
'connect.form.message.ph': 'どのようにお手伝いできますか?',
@@ -198,6 +233,13 @@ export const translations = {
198233
'connect.form.ok.sub': 'メッセージを受け取りました。すぐに返信します。',
199234
'connect.form.err.fields': 'すべての項目を入力してください',
200235
'connect.form.err.send': '送信エラー。もう一度お試しください',
236+
// Theme toggle
237+
'theme.light': 'LIGHT',
238+
'theme.dark': 'DARK',
239+
'theme.aria': 'テーマ切替',
240+
// Lang selector
241+
'lang.aria': '言語選択',
242+
'lang.switch': '言語を変更:',
201243
// Footer
202244
'footer.built': 'built with ♥ caffeine & late nights',
203245
},

0 commit comments

Comments
 (0)