Guía detallada

Language Declaration Guide

Ver contenido

Guía Técnica Completa de Declaración de Idioma: BCP 47, WCAG y SEO Internacional

Introducción

Si ya conoces los fundamentos de la declaración de idioma desde nuestra guía introductoria, esta guía técnica avanzada te equipará con conocimientos profundos sobre BCP 47, cumplimiento WCAG completo, y estrategias de implementación para sitios multilingües complejos.

La declaración de idioma correcta no es solo una etiqueta HTML—es la base de la accesibilidad internacional, el SEO multilingüe efectivo, y la experiencia de usuario para audiencias globales.

Anatomía de BCP 47: El Estándar Detrás de lang

¿Qué es BCP 47?

BCP 47 (Best Current Practice 47) es el estándar IETF que define la estructura de etiquetas de idioma¹. Es el formato que usa el atributo lang de HTML y es mucho más que códigos de dos letras.

Estructura Completa de una Etiqueta BCP 47

language-extlang-script-region-variant-extension-privateuse
Componente Ejemplo Descripción
language es Código ISO 639-1 (obligatorio)
extlang cmn (mandarín) Sub-idioma (raro)
script Latn, Hans Sistema de escritura
region ES, MX, 419 País o región
variant valencia Variante dialectal
extension u-nu-thai Extensiones Unicode
privateuse x-custom Uso privado

Ejemplos Prácticos de BCP 47

<!-- Español genérico -->
<html lang="es">

<!-- Español de España -->
<html lang="es-ES">

<!-- Español de México -->
<html lang="es-MX">

<!-- Español de América Latina (código regional 419) -->
<html lang="es-419">

<!-- Chino simplificado (Mainland China) -->
<html lang="zh-Hans-CN">

<!-- Chino tradicional (Taiwan) -->
<html lang="zh-Hant-TW">

<!-- Portugués de Brasil -->
<html lang="pt-BR">

<!-- Serbio en escritura cirílica -->
<html lang="sr-Cyrl">

<!-- Serbio en escritura latina -->
<html lang="sr-Latn">

<!-- Azerbaiyano en escritura árabe -->
<html lang="az-Arab">

<!-- Inglés con extensión Unicode para números Thai -->
<html lang="en-u-nu-thai">

Cuándo Usar Cada Nivel de Especificidad

Solo Idioma (es, en, fr)

Usar cuando:

  • El contenido es comprensible para todos los hablantes del idioma
  • No hay diferencias regionales significativas
  • Quieres máxima compatibilidad
<!-- Artículo técnico sobre programación - universal -->
<html lang="en">

Idioma + Región (es-ES, en-US, pt-BR)

Usar cuando:

  • El contenido tiene vocabulario específico regional
  • Diferencias ortográficas importantes (color vs colour)
  • Targeting geográfico para SEO
  • Contenido legal o regulatorio específico de un país
<!-- Tienda online con precios en euros -->
<html lang="es-ES">

<!-- Documentación legal para Estados Unidos -->
<html lang="en-US">

Idioma + Script (zh-Hans, sr-Cyrl)

Usar cuando:

  • El idioma usa múltiples sistemas de escritura
  • Quieres especificar la escritura sin vincular a una región
<!-- Chino simplificado (sin especificar país) -->
<html lang="zh-Hans">

Cumplimiento WCAG 2.2: Requisitos Completos

Criterio 3.1.1: Idioma de la Página (Nivel A)²

Requisito: El idioma humano predeterminado de cada página web puede ser determinado programáticamente.

Técnicas suficientes:

<!-- H57: Usar el atributo lang en el elemento html -->
<!DOCTYPE html>
<html lang="es">
<head>
  <title>Mi Sitio Web</title>
</head>
<body>
  <!-- Todo el contenido en español -->
</body>
</html>

Errores comunes que causan incumplimiento:

  1. Ausencia total del atributo lang:
<!-- ❌ FALLA WCAG 3.1.1 -->
<html>
  1. Código de idioma inválido:
<!-- ❌ FALLA WCAG 3.1.1 - "spanish" no es un código válido -->
<html lang="spanish">
  1. Idioma incorrecto para el contenido:
<!-- ❌ FALLA WCAG 3.1.1 - Contenido en español, declarado en inglés -->
<html lang="en">
<body>
  <h1>Bienvenido a nuestro sitio</h1>
</body>
</html>

Criterio 3.1.2: Idioma de las Partes (Nivel AA)³

Requisito: El idioma humano de cada pasaje o frase del contenido puede ser determinado programáticamente, excepto para nombres propios, términos técnicos, palabras de idioma indeterminado, y palabras/frases que son parte del dialecto del texto circundante.

Técnicas suficientes:

<html lang="es">
<body>
  <p>Este artículo es sobre desarrollo web.</p>

  <!-- Cita en inglés - REQUIERE lang -->
  <blockquote lang="en">
    <p>"The best code is no code at all."</p>
    <cite>— Jeff Atwood</cite>
  </blockquote>

  <p>Como dice la cita anterior, la simplicidad es clave.</p>

  <!-- Término técnico en inglés - NO requiere lang (término técnico) -->
  <p>Usamos <code>localStorage</code> para almacenar datos.</p>

  <!-- Nombre propio - NO requiere lang -->
  <p>La empresa Google fue fundada en 1998.</p>

  <!-- Palabra extranjera adoptada al español - NO requiere lang -->
  <p>El software incluye muchas features nuevas.</p>
</body>
</html>

Cuándo SÍ declarar idioma en secciones:

Contenido ¿Requiere lang? Razón
Citas textuales ✅ Sí Contenido significativo en otro idioma
Poemas/letras ✅ Sí Contenido creativo en idioma original
Testimonios ✅ Sí Voz del usuario en su idioma
Código fuente ⚠️ Opcional Generalmente lang="en"
Términos técnicos ❌ No Excepción explícita en WCAG
Nombres propios ❌ No Excepción explícita en WCAG
Extranjerismos adoptados ❌ No Parte del dialecto local

Impacto en Tecnologías de Asistencia

Lectores de pantalla y declaración de idioma:

<!-- Sin lang: NVDA/JAWS pronuncian "BIEN-veh-NEE-doh" con fonética inglesa -->
<html>
<body><h1>Bienvenido</h1></body>
</html>

<!-- Con lang="es": Pronunciación correcta en español -->
<html lang="es">
<body><h1>Bienvenido</h1></body>
</html>

Comportamiento de lectores de pantalla populares:

Lector Sin lang Con lang incorrecto Con lang correcto
NVDA Usa idioma del sistema Pronunciación incorrecta ✅ Correcto
JAWS Usa idioma por defecto Cambio de voz incorrecto ✅ Correcto
VoiceOver Inferencia automática Puede cambiar de voz ✅ Correcto
TalkBack Usa idioma del dispositivo Pronunciación forzada ✅ Correcto

SEO Internacional: hreflang y Declaración de Idioma

Relación entre lang y hreflang

El atributo lang y las etiquetas hreflang trabajan juntos pero tienen propósitos diferentes⁴:

Atributo Propósito Audiencia
lang Declarar idioma del contenido Navegadores, lectores de pantalla
hreflang Indicar versiones alternativas Motores de búsqueda

Implementación correcta:

<!-- Versión en español -->
<!DOCTYPE html>
<html lang="es">
<head>
  <title>Mi Sitio Web</title>
  <link rel="canonical" href="https://ejemplo.com/es/">

  <!-- hreflang para SEO internacional -->
  <link rel="alternate" hreflang="es" href="https://ejemplo.com/es/">
  <link rel="alternate" hreflang="en" href="https://ejemplo.com/en/">
  <link rel="alternate" hreflang="pt-BR" href="https://ejemplo.com/pt-br/">
  <link rel="alternate" hreflang="x-default" href="https://ejemplo.com/en/">
</head>
<body>
  <h1>Bienvenido</h1>
</body>
</html>

Estrategias para Sitios Multilingües

Estructura de URLs

# Por subdirectorio (recomendado)
ejemplo.com/es/           → lang="es"
ejemplo.com/en/           → lang="en"
ejemplo.com/pt-br/        → lang="pt-BR"

# Por subdominio
es.ejemplo.com/           → lang="es"
en.ejemplo.com/           → lang="en"

# Por dominio de país
ejemplo.es/               → lang="es"
ejemplo.com/              → lang="en"
ejemplo.com.br/           → lang="pt-BR"

Implementación en Frameworks Modernos

Vue 3 con Vue Router:

// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/:lang(es|en|pt-br)',
    children: [
      { path: '', component: Home },
      { path: 'about', component: About }
    ]
  }
]

// composables/useLanguage.ts
import { useHead } from '@vueuse/head'
import { useRoute } from 'vue-router'
import { computed } from 'vue'

export function useLanguage() {
  const route = useRoute()

  const currentLang = computed(() => {
    const lang = route.params.lang as string
    const langMap: Record<string, string> = {
      'es': 'es',
      'en': 'en',
      'pt-br': 'pt-BR'
    }
    return langMap[lang] || 'es'
  })

  useHead({
    htmlAttrs: {
      lang: currentLang
    }
  })

  return { currentLang }
}

Next.js con i18n:

// next.config.js
module.exports = {
  i18n: {
    locales: ['es', 'en', 'pt-BR'],
    defaultLocale: 'es',
    localeDetection: true
  }
}

// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html> {/* Next.js inyecta lang automáticamente */}
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

Nuxt 3 con @nuxtjs/i18n:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/i18n'],
  i18n: {
    locales: [
      { code: 'es', iso: 'es-ES', name: 'Español' },
      { code: 'en', iso: 'en-US', name: 'English' },
      { code: 'pt-br', iso: 'pt-BR', name: 'Português' }
    ],
    defaultLocale: 'es',
    strategy: 'prefix'
  }
})
// El módulo maneja lang automáticamente

Content-Language vs lang: Diferencias Críticas

HTTP Header Content-Language

HTTP/1.1 200 OK
Content-Language: es
Content-Type: text/html; charset=UTF-8

HTML lang Attribute

<html lang="es">

Comparación Detallada

Aspecto Content-Language HTTP HTML lang
Propósito Audiencia objetivo del recurso Idioma del contenido
Lectura Antes de parsear HTML Al parsear HTML
Accesibilidad ❌ No usado ✅ Usado por lectores de pantalla
SEO Señal débil Señal más fuerte
Granularidad Solo a nivel de documento Elemento por elemento
Recomendación Opcional Obligatorio (WCAG Nivel A)

Recomendación: Siempre usa lang en HTML. El header Content-Language es opcional y menos útil.

Casos Especiales y Soluciones

Contenido Mixto

<html lang="es">
<body>
  <article>
    <h1>Reseña: "The Pragmatic Programmer"</h1>
    <p>Este libro clásico de programación incluye consejos valiosos.</p>

    <!-- Cita del libro en inglés -->
    <blockquote lang="en">
      <p>"Care about your craft. Why spend your life developing software unless you care about doing it well?"</p>
    </blockquote>

    <p>Como vemos, los autores enfatizan la importancia de la calidad.</p>
  </article>
</body>
</html>

Idiomas RTL (Derecha a Izquierda)

<!-- Árabe -->
<html lang="ar" dir="rtl">

<!-- Hebreo -->
<html lang="he" dir="rtl">

<!-- Persa/Farsi -->
<html lang="fa" dir="rtl">

Secciones RTL en documento LTR:

<html lang="en">
<body>
  <p>This article discusses Middle Eastern cuisine.</p>

  <blockquote lang="ar" dir="rtl">
    <p>الطعام العربي لذيذ جدا</p>
  </blockquote>
</body>
</html>

Idiomas Sin Código ISO 639-1

Algunos idiomas solo tienen códigos ISO 639-2 (3 letras) o ISO 639-3:

<!-- Náhuatl (azteca) - Solo ISO 639-2/3 -->
<html lang="nah">

<!-- Mapudungun (mapuche) - Solo ISO 639-3 -->
<span lang="arn">Mari mari</span>

<!-- Lenguas de señas -->
<video lang="ase"> <!-- American Sign Language -->

Verificación y Testing

Herramientas de Validación

  1. W3C Validator: Verifica sintaxis HTML incluyendo lang
  2. axe DevTools: Auditoría de accesibilidad WCAG
  3. WAVE: Detecta errores de declaración de idioma
  4. UXR SEO Analyzer: Verificación específica de lang y SEO

Checklist de Verificación

Nivel A (Obligatorio)

  • [ ] <html lang="xx"> presente en todas las páginas
  • [ ] Código de idioma válido según BCP 47
  • [ ] Idioma declarado coincide con contenido principal

Nivel AA (Recomendado)

  • [ ] Secciones en otros idiomas tienen lang específico
  • [ ] Citas textuales tienen idioma declarado
  • [ ] Cambios de idioma significativos marcados

SEO Internacional

  • [ ] hreflang implementado para todas las versiones
  • [ ] x-default definido para fallback
  • [ ] Consistencia entre lang y hreflang
  • [ ] URLs canónicas por idioma

Cómo Verificarlo con UXR SEO Analyzer

Verifica tu configuración de idioma con nuestra extensión:

  1. Instala la extensión UXR SEO Analyzer
  2. Navega a tu sitio web
  3. Abre la extensión → pestaña “Basic SEO”
  4. Revisa “Language Declaration”

La extensión detecta:

  • ✅ Presencia del atributo lang
  • ✅ Validez del código BCP 47
  • ⚠️ Inconsistencias entre idioma declarado y contenido
  • ⚠️ Secciones sin declaración de idioma
  • ❌ Códigos inválidos o mal formados

Próximos Pasos

Continúa mejorando tu implementación multilingüe:

Artículos relacionados:

Referencias

Este artículo fue creado utilizando fuentes autorizadas oficiales:

[1] W3C: Language tags in HTML and XML https://www.w3.org/International/articles/language-tags/ Especificación W3C completa sobre etiquetas de idioma BCP 47, incluyendo estructura, sintaxis, y casos de uso. Referencia autoritativa para la construcción correcta de códigos de idioma.

[2] WCAG 2.2: Success Criterion 3.1.1 Language of Page https://www.w3.org/WAI/WCAG22/Understanding/language-of-page.html Criterio de conformidad WCAG Nivel A que requiere declaración programática del idioma de la página. Incluye técnicas suficientes y errores comunes.

[3] WCAG 2.2: Success Criterion 3.1.2 Language of Parts https://www.w3.org/WAI/WCAG22/Understanding/language-of-parts.html Criterio de conformidad WCAG Nivel AA para declaración de idioma en secciones específicas. Define excepciones para términos técnicos y nombres propios.

[4] Google Search Central: Tell Google about localized versions https://developers.google.com/search/docs/specialty/international/localized-versions Documentación oficial de Google sobre implementación de hreflang y señales de idioma para SEO internacional.

[5] IANA Language Subtag Registry https://www.iana.org/assignments/language-subtag-registry/ Registro oficial de IANA con todos los códigos de idioma, región, script y variantes válidos para uso en etiquetas BCP 47.

Cobertura de fuentes: ALTA - Fuentes W3C, WCAG, Google Search Central e IANA proporcionan cobertura autoritativa completa.

Recursos Adicionales


Nota: Este artículo es parte de nuestra serie avanzada sobre SEO técnico e internacionalización. Explora todos los artículos en el Hub de SEO Básico.

Autor: Equipo UXR Chile Última actualización: Diciembre 2025 Tiempo de lectura: 14 minutos

Artículos relacionados

Versión relacionada

Introducción

Language Declaration Explained

La declaración de idioma (el atributo ) es un elemento HTML fundamental que indica a navegadores, buscadores y tecnologías de asistencia el idioma principal...