Cuando lanzamos MarketNow hace 2 semanas, todo estaba en inglés. Hoy soportamos 5 idiomas: English, Español, Português, 中文, Français. Este artículo explica cómo lo hicimos sin react-i18next ni librerías pesadas.
El problema
MarketNow es un marketplace de 8,560 MCP skills. Nuestros usuarios son:
- Desarrolladores en EE.UU. y Europa (inglés)
- Agentes IA que consumen JSON (language-agnostic)
- Comunidades dev en Latinoamérica (español/portugués)
- Mercado AI en China (chino — el segundo más grande del mundo)
- Comunidades en Francia, Quebec, África francófona
Un sitio solo en inglés pierde ~60% del tráfico potencial.
La solución: Context + CONTENT objects
1. LanguageContext
Creamos un context simple que persiste el idioma en localStorage:
const LanguageContext = createContext(null);
export function LanguageProvider({ children }) {
const [lang, setLang] = useState(detectInitialLang);
const t = useCallback((key, vars) => {
const dict = TRANSLATIONS[lang] || TRANSLATIONS[DEFAULT_LANG];
let str = dict[key] ?? TRANSLATIONS[DEFAULT_LANG][key] ?? key;
// Interpolate {count} → params.count
if (vars) {
for (const [k, v] of Object.entries(vars)) {
str = str.replace(new RegExp(`\{${k}\}`, 'g'), String(v));
}
}
return str;
}, [lang]);
return (
<LanguageContext.Provider value={{ lang, setLang, t }}>
{children}
</LanguageContext.Provider>
);
}
2. Translation dictionary
Un solo archivo translations.js con ~400 keys × 5 idiomas:
export const TRANSLATIONS = {
en: {
'nav.marketplace': 'MARKETPLACE',
'hero.title1': 'The trust layer for',
'hero.title2': 'agent commerce.',
'home.freeTitle': '⚡ {count} Free Skills — Install Now',
// ... 400+ keys
},
es: { /* ... */ },
pt: { /* ... */ },
zh: { /* ... */ },
fr: { /* ... */ },
};
3. CONTENT objects para páginas complejas
Las páginas con mucho contenido (Trust, Security, About) usan un patrón CONTENT:
const CONTENT = {
en: {
title: 'Trust Roadmap',
points: [
{ title: 'Human-in-the-loop by default', claudeSaid: '...', whatWeDid: [...] },
// ... 7 points
],
},
es: { /* ... */ },
// ... 5 languages
};
export default function Trust() {
const { lang } = useLang();
const c = CONTENT[lang] || CONTENT.en;
return <h1>{c.title}</h1>;
}
Lo que aprendimos
1. NO uses display:none para SEO content
Primero usamos <div class="sr-only"> con CSS para esconder contenido SEO. Resultado: Google lo indexaba, pero los usuarios con screen readers lo veían duplicado. Mezclaba idiomas.
Solución: <noscript> tag. Google lo indexa inmediatamente, los usuarios con JS ven React.
2. Las categorías técnicas se mantienen en inglés
"AI/ML", "DevOps", "Security" — son términos universales. Los tradujimos pero mantuvimos los originales como fallback.
3. El selector de idioma debe ser visible
Pusimos un dropdown con banderas (🇺🇸🇪🇸🇧🇷🇨🇳🇫🇷). Click → cambia todo al instante, sin reload.
Resultado
- 5 idiomas completos (no parciales)
- 400+ strings traducidos por idioma
- 23 páginas con contenido traducido
- 0 librerías externas (solo React Context)
- Persistencia en localStorage
- Detección automática del idioma del navegador
Links
- MarketNow — cambia el idioma en el navbar
- Código fuente
- Trust roadmap
¿Qué idioma deberíamos añadir next? Estamos considerando japonés (ja) y alemán (de).
MarketNow es la capa de confianza para el comercio de agentes. 8,560 MCP skills, Sentinel L2 security, x402 + USDC on Base. Maintained by AliceLabs LLC (Wyoming, USA).
Top comments (0)