Ingeniería 9 min de lectura

【Soporte total para 5 idiomas】Crónica de 3 horas intensas expandiendo un blog que solo estaba en japonés e inglés al chino, coreano y español

La impactante verdad de que solo había 2 idiomas cuando se creía que eran 5. El registro completo de la implementación ultrarrápida de chino, coreano y español junto a Claude Code

Terisuke
Share this article:
Página 404 del blog en coreano

【Soporte total para 5 idiomas】Crónica de 3 horas intensas expandiendo un blog que solo estaba en japonés e inglés al chino, coreano y español

“¡Pero si pone que está disponible en 5 idiomas!”

Ocurrió un jueves a primera hora de la tarde, mientras revisaba casualmente la implementación en la rama Develop del sitio web. Tal como le había pedido a Cursor Agent, en el selector de idiomas aparecían, en efecto, cinco banderas alineadas. Sin embargo, probé a abrir la página del blog en chino.

Página del blog en chino mostrando un error 404

404 Not Found.

Al investigar, descubrí una verdad impactante.

Soporte para 2 idiomas disfrazado de 5 idiomas

// utils/i18n.ts には確かに5言語の翻訳が...
export type Locale = 'ja' | 'en' | 'zh' | 'ko' | 'es';

A juzgar por la configuración de i18n, efectivamente admitía 5 idiomas. Tanto la página principal como el perfil de la empresa estaban correctamente traducidos por completo. Sin embargo, eché un vistazo al directorio de páginas del blog.

$ ls src/pages/*/blog/
src/pages/en/blog/:
[...page].astro  [...slug].astro

src/pages/zh/blog/:
ls: src/pages/zh/blog/: No such file or directory

src/pages/ko/blog/:
ls: src/pages/ko/blog/: No such file or directory

src/pages/es/blog/:
ls: src/pages/es/blog/: No such file or directory

Solo el blog estaba disponible únicamente en japonés e inglés.

Comprobación de la estructura de directorios

Inicio de la implementación rápida con Claude Code

Llegados a este punto, no quedaba más remedio que implementar los 3 idiomas restantes. Por suerte, contaba con Claude Code. Sin perder tiempo, comencé con la implementación.

Paso 1: Duplicación y modificación de las páginas del blog

En primer lugar, copié las páginas del blog de la versión en inglés y las modifiqué para cada idioma.

# 中国語、韓国語、スペイン語のディレクトリを作成
for lang in zh ko es; do
  mkdir -p src/pages/$lang/blog/
  cp -r src/pages/en/blog/* src/pages/$lang/blog/
done

Sin embargo, esto por sí solo no funcionaba. Era necesario corregir el filtro de idioma dentro de cada archivo.

// 修正前(全ファイル共通)
const allPosts = await getCollection('blog', ({ data }) => {
  return data.lang === 'en' && !data.isDraft;
});

// 修正後(例:中国語版)
const allPosts = await getCollection('blog', ({ data }) => {
  return data.lang === 'zh' && !data.isDraft;
});

Paso 2: Creación del script de traducción

Traducir 8 artículos en japonés manualmente no era nada realista. Por lo tanto, creé un script de traducción automática utilizando la API de Gemini.

// scripts/translate-blog-all-languages.js
const LANGUAGES = {
  en: { name: 'English', author: 'Terisuke' },
  zh: { name: 'Chinese', author: 'Terisuke' },
  ko: { name: 'Korean', author: 'Terisuke' },
  es: { name: 'Spanish', author: 'Terisuke' }
};

async function translateToLanguage(inputFile, targetLang, body, frontmatter) {
  console.log(`📝 Translating to ${LANGUAGES[targetLang].name}...`);

  // タイトルとdescriptionを翻訳
  const titleAndDescription = `Title: ${frontmatter.title}\nDescription: ${frontmatter.description}`;
  const translatedTitleDesc = await translateWithGemini(titleAndDescription, targetLang);

  // 本文を翻訳
  const translatedBody = await translateWithGemini(body, targetLang);

  // ファイルを保存
  saveTranslatedFile(targetLang, translatedContent);
}

Paso 3: Una lucha a muerte contra los errores

Ejecuté el script de traducción y, lleno de optimismo, me dispuse a comprobar el sitio.

$ npm run build
✘ [ERROR] Expected "}" but found "."
  script:/ProductsTable.astro:3:33:
    3 │   buttonTexts: {t.buttonTexts},
      ╵                ^

Una tormenta de errores de compilación.

Pila de registros de errores

Una serie continua de correcciones de errores

Problema 1: Misterioso código de depuración en ProductsTable.astro

// なぜか入っていた謎のデバッグコード
<script>
  console.log('Button text debug:', {
    buttonTexts: {t.buttonTexts},  // ← これが構文エラー
    goTo: {t.buttonTexts?.goTo},
    itemName: {item.name}
  });
</script>

Se solucionó eliminando este código de depuración.

Problema 2: Omisión del soporte de idiomas en CategoryBadge

// 修正前
const categoryLabels = {
  ja: { 'ai': 'AI', 'engineering': 'エンジニアリング', ... },
  en: { 'ai': 'AI', 'engineering': 'Engineering', ... },
  // zh, ko, es が存在しない!
};

// 修正後
const categoryLabels = {
  ja: { ... },
  en: { ... },
  zh: { 'ai': '人工智能', 'engineering': '工程', ... },
  ko: { 'ai': 'AI', 'engineering': '엔지니어링', ... },
  es: { 'ai': 'IA', 'engineering': 'Ingeniería', ... },
};

Problema 3: Todos los enlaces de PostCard redirigen al inglés

// 修正前
const postUrl = currentLocale === 'ja'
  ? `/blog/${cleanSlug}`
  : `/en/blog/${cleanSlug}`;  // 他の言語でも/en/に飛んでしまう!

// 修正後
const postUrl = currentLocale === 'ja'
  ? `/blog/${cleanSlug}`
  : `/${currentLocale}/blog/${cleanSlug}`;

Problema 4: A pesar de haberse traducido, el título seguía en japonés

Este fue el problema más engorroso. Aunque el script de traducción supuestamente funcionaba con normalidad, el title y la description del frontmatter permanecían en japonés.

# 中国語の記事なのに...
---
title: "【爆速15分】MCPサーバーでMCPサーバーを作る!"  # 日本語!
description: "LT中止の絶望から生まれた奇跡..."  # 日本語!
lang: "zh"
---

# 【闪电15分钟】用MCP服务器构建MCP服务器!  # 本文は中国語

Al investigar la causa, descubrí un error en el procesamiento de análisis sintáctico (parsing) del script de traducción. Lo solucioné creando un script de corrección por separado.

// scripts/fix-translated-frontmatter.cjs
function extractTitleFromBody(body) {
  const lines = body.split('\n');
  for (const line of lines) {
    if (line.startsWith('# ')) {
      return line.substring(2).trim();  // 本文の最初の見出しから抽出
    }
  }
  return null;
}

Resultados de 3 horas frenéticas

Aproximadamente 3 horas después de descubrir el primer error, finalmente resolví todos los problemas.

Lista de funciones implementadas

  • Creación de páginas de blog en chino, coreano y español
  • Soporte para 5 idiomas en las páginas de categorías
  • Soporte para 5 idiomas en las páginas de etiquetas
  • Soporte para 5 idiomas en los feeds RSS
  • Soporte para 5 idiomas en las páginas de pago exitoso/cancelado
  • Traducción automática de 8 artículos existentes × 3 idiomas = 24 artículos
  • Resolución de todos los errores de TypeScript
  • Compilación exitosa (317 páginas)

Blog en chino terminado Blog en coreano terminado Blog en español terminado

Calidad de la traducción

La traducción mediante la API de Gemini superó con creces mis expectativas en cuanto a calidad.

日本語: 「いい感じにアレしとくアプリ」開発秘話
中国語: "随心所欲处理应用"开发秘辛
韓国語: '적당히 알아서 해주는 앱' 개발 비화
スペイン語: La historia detrás de la aplicación 'Hazlo bien y ya'

Se obtuvieron traducciones naturales que capturan adecuadamente los matices de cada idioma.

Lecciones aprendidas

1. La definición de “soportado” es ambigua

Aunque se hable de “soporte para 5 idiomas”, no se sabe realmente hasta qué punto está cubierto hasta que se examina a fondo. Casos como este, donde la página principal sí tiene soporte pero el blog no, probablemente sean más comunes de lo que parece.

2. El poder del trabajo conjunto con Claude Code

Poder completar la implementación de 5 idiomas × 8 artículos en 3 horas se debió en gran medida a la presencia de Claude Code. Resultó de gran ayuda especialmente en los siguientes puntos:

  • Identificación inmediata de la causa a partir de los mensajes de error
  • Aprendizaje de los patrones de corrección para aplicar modificaciones similares en lote
  • Implementación eficiente de la lógica del script de traducción

3. Los scripts de automatización son el camino a seguir

Haber traducido manualmente 24 artículos probablemente me habría tomado mucho más tiempo. Aunque tome 1 hora crear un script de automatización, la rentabilidad es mucho mayor.

4. Los errores son una mina de oro

Los numerosos errores que encontré en esta ocasión supusieron una excelente oportunidad para descubrir problemas latentes en el sistema. En particular, la omisión del soporte de idiomas en CategoryBadge habría terminado siendo un problema tarde o temprano.

Conclusión: Hacia una verdadera compatibilidad multilingüe

La impactante verdad fue que un sitio que al principio consideraba “con soporte para 5 idiomas” era en realidad “un simulacro de soporte para 5 idiomas”. Sin embargo, durante las 3 horas de batalla junto a Claude Code, logré hacer realidad un auténtico soporte para 5 idiomas.

Ahora, los artículos del blog se muestran adecuadamente tanto en chino como en coreano y español. El error 404 ya no vuelve a aparecer.

Esto sí es verdadera compatibilidad multilingüe.


El código implementado está publicado en GitHub. El script de traducción también debería ser utilizable en otros proyectos de Astro.

Las 3 horas de batalla junto a Claude Code fueron una experiencia frenética pero sumamente enriquecedora.

¿Quiere aplicar esto en su empresa?

Nuestra recepción con IA «Cloudia» atiende solicitudes de desarrollo de IA por encargo.

Más información: Plataforma de IA y desarrollo por contrato

Support this article

If this article was helpful, please support us with a tip. You can choose any amount.

Secure payment via Stripe
Última actualización: 23 de octubre de 2026

Artículos Relacionados

Leer artículo
Ingeniería

Qué se ve y qué no se ve en el historial de Git: comprobamos cuatro OSS con Grift

Separamos qué se puede contar en un historial de git con reglas explícitas y qué no. Comprobamos cuatro OSS reales por repositorio. No garantiza la capacidad de una persona ni que el registro esté completo.

#Grift #OSS +3
Leer artículo
Ingeniería

Cómo mantener en la implementación el principio de «no asignar puntuaciones ni clasificaciones»: las 5 condiciones que Grift CLI ha establecido para la próxima versión

Grift CLI promete no emitir puntuaciones ni clasificaciones. En la verificación cruzada de octubre de 2026, se descubrió que, si bien una nota indicaba que no se trataba de una clasificación, la tabla estaba ordenada de forma descendente por número de commits. Explicamos de forma sencilla las 5 condiciones de aceptación impuestas para la versión 0.8, dirigidas a clientes, comerciales de SES e ingenieros.

#Grift #OSS +3
Leer artículo
Ingeniería

Por qué las estimaciones en desarrollo de IA y por encargo dependen de cada persona: cómo convertir los fundamentos en activos de la empresa

Explicamos por qué las estimaciones en el desarrollo por encargo varían según la persona y cómo crear fundamentos explicables utilizando el historial de GitHub, los precios de mercado y el desglose de horas de trabajo. También presentamos el enfoque para utilizar Grift.

#見積もり #受託開発 +2