Saltar al contenido principal
La internacionalización (i18n) es el proceso de diseñar software o contenido para que funcione en distintos idiomas y configuraciones regionales. Esta guía explica cómo estructurar archivos, configurar la navegación y mantener las traducciones de forma eficiente, para que puedas ayudar a los usuarios a acceder a tu documentación en su idioma preferido y mejorar tu alcance global.

Estructura de archivos

Organiza el contenido traducido en directorios específicos por idioma para mantener tu documentación manejable y estructurar tu navegación por idioma. Crea un directorio separado para cada idioma usando los códigos de idioma ISO 639-1. Coloca los archivos traducidos en estos directorios con la misma estructura que tu idioma predeterminado.
Example file structure
docs/
├── index.mdx                    # English (default)
├── quickstart.mdx
├── fr/
│   ├── index.mdx               # French
│   ├── quickstart.mdx
├── es/
│   ├── index.mdx               # Spanish
│   ├── quickstart.mdx
└── zh/
    ├── index.mdx               # Chinese
    └── quickstart.mdx
Mantén los mismos nombres de archivo y la misma estructura de directorios en todos los idiomas. Esto facilita el mantenimiento de las traducciones y la identificación del contenido faltante.

Configurar el selector de idioma

Para añadir un selector de idioma a tu documentación, configura el array languages en la propiedad navigation de tu docs.json.
docs.json
{
  "navigation": {
    "languages": [
      {
        "language": "en",
        "groups": [
          {
            "group": "Primeros pasos",
            "pages": ["index", "quickstart"]
          }
        ]
      },
      {
        "language": "es",
        "groups": [
          {
            "group": "Comenzando",
            "pages": ["es/index", "es/quickstart"]
          }
        ]
      }
    ]
  }
}
Cada entrada de idioma en el array languages requiere:
  • language: código de idioma ISO 639-1
  • Estructura completa de navigation
  • Rutas de los archivos traducidos
La estructura de navigation puede diferir entre idiomas para adaptarse a las necesidades de contenido específicas de cada idioma.

Establecer el idioma predeterminado

El primer idioma del arreglo languages se usa automáticamente como idioma predeterminado. Para establecer otro idioma como predeterminado, reordena el arreglo o agrega la propiedad default:
docs.json
{
  "navigation": {
    "languages": [
      {
        "language": "es",
        "groups": [...]
      },
      {
        "language": "en",
        "groups": [...]
      }
    ]
  }
}
Alternativamente, usa la propiedad default para modificar el orden:
docs.json
{
  "navigation": {
    "languages": [
      {
        "language": "en",
        "groups": [...]
      },
      {
        "language": "es",
        "default": true,
        "groups": [...]
      }
    ]
  }
}

Documentación en un solo idioma

Si solo quieres tener un único idioma disponible sin un selector de idioma, elimina el campo languages de tu configuración de navigation. En su lugar, define directamente tu estructura de navigation:
docs.json
{
  "navigation": {
    "tabs": [
      {
        "tab": "Documentación",
        "groups": [
          {
            "group": "Primeros pasos",
            "pages": ["index", "quickstart"]
          }
        ]
      }
    ]
  }
}
Esto muestra la documentación en un solo idioma sin la interfaz de usuario del selector de idioma.
Traduce las etiquetas de navegación, como los nombres de grupos o Tabs, para que coincidan con el idioma del contenido. Esto crea una experiencia completamente localizada para tus usuarios.
Para añadir elementos de navegación global que aparezcan en todos los idiomas, configura el objeto global dentro de la navigation de tu docs.json.
docs.json
{
  "navigation": {
    "global": {
      "anchors": [
        {
          "anchor": "Documentación",
          "href": "https://example.com/docs"
        },
        {
          "anchor": "Blog",
          "href": "https://example.com/blog"
        }
      ]
    },
    "languages": [
      // Language-specific navigation
    ]
  }
}

Mantén las traducciones

Mantén las traducciones precisas y sincronizadas con tu contenido original.

Flujo de trabajo de traducción

  1. Actualiza el contenido original en tu idioma principal.
  2. Identifica el contenido modificado.
  3. Traduce el contenido modificado.
  4. Revisa las traducciones para comprobar su precisión.
  5. Actualiza los archivos traducidos.
  6. Verifica que la navegación y los enlaces funcionen.

Traducciones automatizadas

Para soluciones de traducción automática, ponte en contacto con el equipo de ventas de Mintlify.

Proveedores de traducción externos

Si trabajas con tus propios proveedores de traducción o traductores regionales, puedes integrar su flujo de trabajo con tu documentación de Mintlify mediante GitHub Actions o herramientas de CI/CD similares.
  1. Exportar el contenido fuente: Extrae los archivos MDX que necesiten traducción.
  2. Enviar a los traductores: Proporciona los archivos a tu proveedor de traducción.
  3. Recibir las traducciones: Recibe de vuelta los archivos MDX traducidos.
  4. Importar y desplegar: Añade los archivos traducidos a los directorios de idioma y actualiza la navegación.
Este flujo de trabajo de GitHub Actions exporta automáticamente el contenido en inglés modificado para su traducción cuando los PR se fusionan en main.
.github/workflows/export-for-translation.yml
name: Export content for translation

on:
  push:
    branches: [main]
    paths:
      - '*.mdx'
      - '!es/**'
      - '!fr/**'
      - '!zh/**'

# Evitar ejecuciones simultáneas del flujo de trabajo para prevenir condiciones de carrera
concurrency:
  group: translation-export-${{ github.ref }}
  cancel-in-progress: false

jobs:
  export:
    runs-on: ubuntu-latest
    
    # Salida anticipada si no se detectan cambios (opcional: actúa como seguridad adicional)
    outputs:
      files-changed: ${{ steps.changed.outputs.has-files }}
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 2

      - name: Get changed MDX files
        id: changed
        run: |
          # Verificar si existe el commit padre (gestiona el push inicial)
          if ! git rev-parse HEAD~1 >/dev/null 2>&1; then
            echo "has-files=false" >> $GITHUB_OUTPUT
            echo "files=" >> $GITHUB_OUTPUT
            echo "No parent commit found - skipping export"
            exit 0
          fi
          
          # Obtener la lista de archivos MDX modificados (excluyendo los directorios de traducción)
          files=$(git diff --name-only HEAD~1 HEAD -- '*.mdx' ':!es/' ':!fr/' ':!zh/' | tr '\n' ' ')
          
          if [ -z "$files" ]; then
            echo "has-files=false" >> $GITHUB_OUTPUT
            echo "files=" >> $GITHUB_OUTPUT
            echo "No MDX files changed - skipping export"
          else
            echo "has-files=true" >> $GITHUB_OUTPUT
            echo "files=$files" >> $GITHUB_OUTPUT
            echo "Found changed files: $files"
          fi
        shell: bash

      - name: Create translation package directory
        if: steps.changed.outputs.has-files == 'true'
        run: |
          mkdir -p translation-export
          echo "Created translation-export directory"

      - name: Copy changed files to export directory
        if: steps.changed.outputs.has-files == 'true'
        run: |
          failed_count=0
          for file in ${{ steps.changed.outputs.files }}; do
            if [ -f "$file" ]; then
              target_dir="translation-export/$(dirname "$file")"
              mkdir -p "$target_dir"
              cp "$file" "$target_dir/"
              echo "✓ Copied: $file"
            else
              echo "✗ File not found: $file"
              ((failed_count++))
            fi
          done
          
          if [ $failed_count -gt 0 ]; then
            echo "Warning: $failed_count file(s) could not be copied"
          fi
        shell: bash

      - name: Validate translation package
        if: steps.changed.outputs.has-files == 'true'
        run: |
          echo "Translation package contents:"
          find translation-export -type f -name "*.mdx" | sort
          echo ""
          file_count=$(find translation-export -type f -name "*.mdx" | wc -l)
          echo "Total MDX files: $file_count"

      - name: Upload translation package
        if: steps.changed.outputs.has-files == 'true'
        uses: actions/upload-artifact@v4
        with:
          name: translation-export-${{ github.sha }}
          path: translation-export/
          retention-days: 30
          if-no-files-found: error
          compression-level: 9

      - name: Print job summary
        if: steps.changed.outputs.has-files == 'true'
        run: |
          echo "## Translation Export Complete" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Artifact:** \`translation-export-${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Changed Files:**" >> $GITHUB_STEP_SUMMARY
          echo "${{ steps.changed.outputs.files }}" | tr ' ' '\n' | sed 's/^/- /' >> $GITHUB_STEP_SUMMARY
Este flujo de trabajo de GitHub Actions valida e importa el contenido traducido cuando se añade en una PR.
.github/workflows/import-translations.yml
name: Importar traducciones

on:
  pull_request:
    paths:
      - 'es/**'
      - 'fr/**'
      - 'zh/**'

# Definir permisos explícitos
permissions:
  contents: read
  pull-requests: write

jobs:
  validate:
    runs-on: ubuntu-latest
    
    outputs:
      validation-status: ${{ steps.final-check.outputs.status }}
    
    steps:
      - name: Obtener repositorio
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Historial completo para garantizar que origin/main esté disponible

      - name: Obtener referencia de origin/main
        run: |
          git fetch origin main:origin/main 2>/dev/null || echo "origin/main no disponible, usando el más reciente"
        continue-on-error: true

      - name: Obtener archivos de traducción modificados
        id: changed-files
        run: |
          # Obtener todos los archivos MDX modificados en los directorios de traducción
          files=$(git diff --name-only origin/main..HEAD -- 'es/**/*.mdx' 'fr/**/*.mdx' 'zh/**/*.mdx' | sort)
          
          if [ -z "$files" ]; then
            echo "No se detectaron archivos MDX de traducción en este PR"
            echo "files=" >> $GITHUB_OUTPUT
            echo "count=0" >> $GITHUB_OUTPUT
          else
            echo "Se encontraron $(echo "$files" | wc -l) archivos de traducción"
            echo "$files"
            echo "files=$files" >> $GITHUB_OUTPUT
            echo "count=$(echo "$files" | wc -l)" >> $GITHUB_OUTPUT
          fi
        shell: bash

      - name: Validar frontmatter
        id: frontmatter
        if: steps.changed-files.outputs.count > 0
        run: |
          failed_files=()
          success_count=0
          total=${{ steps.changed-files.outputs.count }}
          
          while IFS= read -r file; do
            if [ ! -f "$file" ]; then
              echo "✗ Archivo no encontrado: $file"
              failed_files+=("$file")
              continue
            fi
            
            # Verificar frontmatter válido (las líneas 1-2 deben ser ---)
            first_line=$(sed -n '1p' "$file")
            second_line=$(sed -n '2p' "$file")
            last_line=$(awk 'NF' "$file" | tail -1)
            
            if [ "$first_line" = "---" ] && grep -q "^---$" "$file"; then
              echo "✓ Frontmatter válido: $file"
              ((success_count++))
            else
              echo "✗ Frontmatter inválido en $file"
              echo "  Línea 1: '$first_line'"
              failed_files+=("$file")
            fi
          done <<< "${{ steps.changed-files.outputs.files }}"
          
          echo ""
          echo "Verificación de frontmatter: $success_count/$total aprobados"
          
          if [ ${#failed_files[@]} -gt 0 ]; then
            echo "frontmatter_valid=false" >> $GITHUB_OUTPUT
            printf 'failed_files=%s\n' "${failed_files[@]}" >> $GITHUB_OUTPUT
          else
            echo "frontmatter_valid=true" >> $GITHUB_OUTPUT
          fi
        shell: bash

      - name: Verificar estructura de archivos
        id: structure
        if: steps.changed-files.outputs.count > 0
        run: |
          missing_sources=()
          orphaned_count=0
          
          while IFS= read -r translated_file; do
            # Extraer idioma y ruta relativa
            # p. ej., "es/docs/guide.mdx" -> lang="es", relative_path="docs/guide.mdx"
            lang=$(echo "$translated_file" | cut -d'/' -f1)
            relative_path=$(echo "$translated_file" | cut -d'/' -f2-)
            source_file="$relative_path"
            
            if [ ! -f "$source_file" ]; then
              echo "Fuente faltante: $translated_file -> $source_file"
              missing_sources+=("$translated_file")
              ((orphaned_count++))
            else
              echo "✓ Fuente encontrada: $translated_file -> $source_file"
            fi
          done <<< "${{ steps.changed-files.outputs.files }}"
          
          echo ""
          echo "Verificación de estructura: $orphaned_count archivo(s) huérfano(s)"
          
          if [ $orphaned_count -gt 0 ]; then
            echo "structure_valid=false" >> $GITHUB_OUTPUT
            printf 'missing_sources=%s\n' "${missing_sources[@]}" >> $GITHUB_OUTPUT
          else
            echo "structure_valid=true" >> $GITHUB_OUTPUT
          fi
        shell: bash

      - name: Validar integridad de archivos
        id: integrity
        if: steps.changed-files.outputs.count > 0
        run: |
          integrity_passed=true
          
          while IFS= read -r file; do
            # Verificar que el archivo sea legible y no esté vacío
            if [ ! -r "$file" ] || [ ! -s "$file" ]; then
              echo "✗ Problema de integridad del archivo: $file (no legible o vacío)"
              integrity_passed=false
            fi
            
            # Verificación básica: el archivo debe tener contenido después del frontmatter
            line_count=$(wc -l < "$file")
            if [ "$line_count" -lt 5 ]; then
              echo "El archivo es sospechosamente corto: $file ($line_count líneas)"
            fi
          done <<< "${{ steps.changed-files.outputs.files }}"
          
          if [ "$integrity_passed" = true ]; then
            echo "integrity_valid=true" >> $GITHUB_OUTPUT
          else
            echo "integrity_valid=false" >> $GITHUB_OUTPUT
          fi
        shell: bash

      - name: Generar informe de validación
        if: always()
        run: |
          echo "## Informe de validación de traducciones" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "**Archivos modificados:** ${{ steps.changed-files.outputs.count }}" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          
          if [ "${{ steps.changed-files.outputs.count }}" = "0" ]; then
            echo "No se encontraron archivos MDX de traducción en este PR" >> $GITHUB_STEP_SUMMARY
            echo "" >> $GITHUB_STEP_SUMMARY
            echo "> Esto podría significar:" >> $GITHUB_STEP_SUMMARY
            echo "- Solo se modificaron archivos que no son MDX en los directorios es/, fr/ o zh/" >> $GITHUB_STEP_SUMMARY
            echo "- El flujo de trabajo se activó pero no hay contenido de traducción para validar" >> $GITHUB_STEP_SUMMARY
          else
            echo "### Resultados de validación" >> $GITHUB_STEP_SUMMARY
            echo "- Frontmatter: ${{ steps.frontmatter.outputs.frontmatter_valid }}" >> $GITHUB_STEP_SUMMARY
            echo "- Estructura de archivos: ${{ steps.structure.outputs.structure_valid }}" >> $GITHUB_STEP_SUMMARY
            echo "- Integridad de archivos: ${{ steps.integrity.outputs.integrity_valid }}" >> $GITHUB_STEP_SUMMARY
            echo "" >> $GITHUB_STEP_SUMMARY
          fi
        shell: bash

      - name: Verificación final de validación
        id: final-check
        # Solo ejecutar esta verificación si realmente había archivos MDX para validar
        if: steps.changed-files.outputs.count > 0
        run: |
          validation_failed=false
          
          if [ "${{ steps.frontmatter.outputs.frontmatter_valid }}" != "true" ]; then
            echo "La validación del frontmatter falló"
            validation_failed=true
          fi
          
          if [ "${{ steps.structure.outputs.structure_valid }}" != "true" ]; then
            echo "La validación de la estructura de archivos falló"
            validation_failed=true
          fi
          
          if [ "${{ steps.integrity.outputs.integrity_valid }}" != "true" ]; then
            echo "La validación de integridad de archivos falló"
            validation_failed=true
          fi
          
          if [ "$validation_failed" = true ]; then
            echo "status=failed" >> $GITHUB_OUTPUT
            exit 1
          else
            echo "status=passed" >> $GITHUB_OUTPUT
            echo "Todas las validaciones aprobadas"
          fi
        shell: bash

      - name: Gestionar el caso sin archivos para validar
        # Ejecutar solo cuando no hay archivos MDX para validar
        if: steps.changed-files.outputs.count == 0
        run: |
          echo "No hay archivos MDX de traducción para validar - el PR es válido"
          echo "status=no-changes" >> ${{ steps.final-check.outputs }}
        shell: bash
Mejores prácticas para flujos de trabajo de traducción externos
  • Conserva el frontmatter: Asegúrate de que los traductores mantengan intacto el frontmatter en YAML y traduzcan solo los valores de title y description.
  • Protege los bloques de código: Marca los bloques de código como “no traducir” para tus proveedores de traducción.
  • Usa memoria de traducción: Proporciona glosarios con términos técnicos que deban mantenerse en inglés o tener traducciones específicas.
  • Automatiza la validación: Usa comprobaciones de CI para verificar la sintaxis de MDX y el frontmatter antes de integrar las traducciones.
  • Control de versiones: Lleva un seguimiento de la versión de origen de cada traducción para identificar contenido desactualizado.

Imágenes y recursos multimedia

Guarda las imágenes traducidas en directorios específicos para cada idioma.
images/
├── dashboard.png          # Versión en inglés
├── fr/
│   └── dashboard.png     # Versión en francés
└── es/
    └── dashboard.png     # Versión en español
Referencia las imágenes usando rutas relativas en tu contenido traducido.
es/index.mdx
![Captura de pantalla del dashboard](/images/es/dashboard.png)

SEO para sitios multilingües

Optimiza cada versión en cada idioma para los motores de búsqueda.

Metadata de la página

Incluye la metadata traducida en el frontmatter de cada archivo:
fr/index.mdx
---
title: "Comenzar"
description: "Aprenda a comenzar con nuestro producto."
keywords: ["inicio", "tutorial", "guía"]
---

Mejores prácticas

Formatos de fecha y número

Ten en cuenta los formatos específicos de cada región para fechas y números.
  • Formatos de fecha: MM/DD/YYYY vs DD/MM/YYYY
  • Formatos numéricos: 1,000.00 vs 1.000,00
  • Símbolos de moneda: $100.00 vs 100,00€
Incluye ejemplos en el formato apropiado para cada idioma o utiliza formatos universalmente comprensibles.

Mantén la consistencia

  • Mantén el mismo contenido en todos los idiomas para garantizar que cada usuario reciba la misma calidad de información.
  • Crea un glosario de traducción para los términos técnicos.
  • Conserva la misma estructura de contenido en todos los idiomas.
  • Haz que el tono y el estilo coincidan con los de tu contenido original.
  • Usa branches de Git para gestionar el trabajo de traducción por separado de las actualizaciones del contenido principal.

Diferencias de diseño

Algunos idiomas requieren más o menos espacio que el inglés. Prueba tu contenido traducido en diferentes tamaños de pantalla para asegurarte de que:
  • La navegación quepa correctamente.
  • Los bloques de código no se desborden.
  • Las tablas y otros textos con formato sigan siendo legibles.
  • Las imágenes se escalen adecuadamente.

Codificación de caracteres

Asegúrate de que tanto tu entorno de desarrollo como tu pipeline de implementación sean compatibles con la codificación UTF-8 para mostrar correctamente todos los caracteres de idiomas con alfabetos distintos y caracteres especiales.