API Intl.Locale

Analiza, manipula y consulta identificadores de localización con objetos JavaScript estructurados

Introducción

Al construir aplicaciones para múltiples idiomas y regiones, te encontrarás con identificadores de configuración regional como en-US, fr-FR o zh-Hans-CN. Estas cadenas aparecen en las API del navegador, encabezados HTTP y preferencias de usuario. Codifican información sobre el idioma, la región, el sistema de escritura y las preferencias de formato.

La API Intl.Locale transforma estas cadenas opacas en objetos estructurados que puedes inspeccionar y manipular. En lugar de analizar cadenas manualmente o adivinar qué significa zh-Hans-CN, puedes crear un objeto de configuración regional y leer sus propiedades directamente.

Esta guía explica cómo funcionan los identificadores de configuración regional, cómo usar la API Intl.Locale para trabajar con ellos y cuándo los objetos de configuración regional estructurados ayudan a resolver problemas reales.

Entendiendo los identificadores de configuración regional

Un identificador de configuración regional es una cadena que especifica preferencias culturales para formatear fechas, números, monedas y texto. El identificador contiene múltiples componentes separados por guiones.

La estructura más común sigue el estándar BCP 47:

idioma-escritura-región-variante-extensiones

Cada componente es opcional excepto el código de idioma.

Códigos de idioma

Los códigos de idioma utilizan dos o tres letras del ISO 639. Ejemplos comunes:

  • en para inglés
  • es para español
  • fr para francés
  • de para alemán
  • ja para japonés
  • zh para chino
  • ar para árabe

El código de idioma siempre está en minúsculas y aparece primero en el identificador.

Códigos de región

Los códigos de región especifican áreas geográficas utilizando dos letras mayúsculas del ISO 3166-1. Indican qué variante de un idioma usar:

  • en-US para inglés americano
  • en-GB para inglés británico
  • es-ES para español de España
  • es-MX para español mexicano
  • fr-FR para francés hablado en Francia
  • fr-CA para francés canadiense

Los códigos de región cambian las convenciones de formato. El inglés americano usa fechas en formato MM/DD/YYYY, mientras que el inglés británico usa DD/MM/YYYY.

Códigos de escritura

Los códigos de escritura especifican el sistema de escritura utilizando cuatro letras con la primera letra en mayúscula. Son importantes para idiomas que se escriben en múltiples sistemas de escritura:

  • zh-Hans para caracteres chinos simplificados
  • zh-Hant para caracteres chinos tradicionales
  • sr-Cyrl para serbio en escritura cirílica
  • sr-Latn para serbio en escritura latina

La mayoría de las configuraciones regionales omiten el código de escritura porque el idioma implica un sistema de escritura predeterminado. El inglés utiliza el alfabeto latino por defecto, por lo que se escribe en en lugar de en-Latn.

Etiquetas de extensión

Las etiquetas de extensión añaden preferencias de formato a los identificadores de configuración regional. Comienzan con -u- seguido de pares clave-valor:

en-US-u-ca-gregory-nu-latn-hc-h12

Claves de extensión comunes:

  • ca para sistema de calendario (gregory, buddhist, islamic)
  • nu para sistema de numeración (latn, arab, hanidec)
  • hc para ciclo horario (h12, h23, h11, h24)

Las extensiones personalizan cómo los formateadores muestran los datos sin cambiar el idioma o la región.

Creación de objetos de configuración regional

El constructor Intl.Locale acepta una cadena identificadora de configuración regional y devuelve un objeto estructurado:

const locale = new Intl.Locale("en-US");

console.log(locale.language); // "en"
console.log(locale.region); // "US"

También puedes pasar un objeto de opciones para sobrescribir o añadir propiedades:

const locale = new Intl.Locale("en", {
  region: "GB",
  hourCycle: "h23"
});

console.log(locale.baseName); // "en-GB"
console.log(locale.hourCycle); // "h23"

El constructor lanza un RangeError si el identificador no es válido:

try {
  const invalid = new Intl.Locale("invalid-locale-code");
} catch (error) {
  console.error(error.message); // "invalid language subtag: invalid"
}

Esta validación asegura que detectes identificadores de configuración regional mal formados antes de pasarlos a los formateadores.

Lectura de propiedades de configuración regional

Los objetos de configuración regional exponen propiedades que corresponden a los componentes de la cadena identificadora. Todas las propiedades son de solo lectura.

Propiedades principales

La propiedad language devuelve el código de idioma:

const locale = new Intl.Locale("fr-CA");
console.log(locale.language); // "fr"

La propiedad region devuelve el código de región:

const locale = new Intl.Locale("fr-CA");
console.log(locale.region); // "CA"

La propiedad script devuelve el código de escritura si está presente:

const locale = new Intl.Locale("zh-Hans-CN");
console.log(locale.script); // "Hans"

La propiedad baseName devuelve el identificador principal completo sin extensiones:

const locale = new Intl.Locale("en-US-u-ca-gregory-nu-latn");
console.log(locale.baseName); // "en-US"

Utilice baseName cuando necesite el idioma y la región pero quiera ignorar las preferencias de formato.

Propiedades de extensión

Las propiedades de extensión devuelven valores de la etiqueta de extensión -u- o undefined si no se especifica.

La propiedad calendar devuelve el sistema de calendario:

const locale = new Intl.Locale("ar-SA-u-ca-islamic");
console.log(locale.calendar); // "islamic"

La propiedad numberingSystem devuelve el sistema de numeración:

const locale = new Intl.Locale("ar-EG-u-nu-arab");
console.log(locale.numberingSystem); // "arab"

La propiedad hourCycle devuelve la preferencia del ciclo horario:

const locale = new Intl.Locale("en-US-u-hc-h23");
console.log(locale.hourCycle); // "h23"

La propiedad caseFirst devuelve la preferencia de mayúsculas y minúsculas en la ordenación:

const locale = new Intl.Locale("en-US-u-kf-upper");
console.log(locale.caseFirst); // "upper"

La propiedad numeric indica si la ordenación numérica está habilitada:

const locale = new Intl.Locale("en-US-u-kn-true");
console.log(locale.numeric); // true

Estas propiedades le permiten inspeccionar las preferencias de formato sin tener que analizar manualmente la cadena de extensión.

Consulta de información de configuración regional

La API Intl.Locale proporciona métodos que devuelven matrices de opciones disponibles para una configuración regional. Estos métodos ayudan a construir interfaces de usuario y validar opciones de formato.

Calendarios disponibles

El método getCalendars() devuelve los sistemas de calendario comúnmente utilizados para la configuración regional:

const locale = new Intl.Locale("th-TH");
const calendars = locale.getCalendars();
console.log(calendars); // ["buddhist", "gregory"]

El primer elemento es el calendario predeterminado. Las configuraciones regionales tailandesas utilizan por defecto el calendario budista, pero también utilizan el calendario gregoriano.

Colaciones disponibles

El método getCollations() devuelve tipos de colación para ordenar cadenas:

const locale = new Intl.Locale("de-DE");
const collations = locale.getCollations();
console.log(collations); // ["phonebk", "emoji", "eor"]

El alemán tiene una colación de guía telefónica que ordena las cadenas de manera diferente a la colación estándar de Unicode.

Ciclos horarios disponibles

El método getHourCycles() devuelve formatos de ciclo horario:

const locale = new Intl.Locale("en-US");
const hourCycles = locale.getHourCycles();
console.log(hourCycles); // ["h12"]

El inglés americano utiliza el formato de 12 horas por defecto. Muchas otras configuraciones regionales devuelven ["h23"] para el formato de 24 horas.

Sistemas de numeración disponibles

El método getNumberingSystems() devuelve los sistemas de numeración comúnmente utilizados para la configuración regional:

const locale = new Intl.Locale("ar-EG");
const numberingSystems = locale.getNumberingSystems();
console.log(numberingSystems); // ["arab", "latn"]

Las configuraciones regionales árabes a menudo admiten tanto numerales arábigo-índicos como numerales latinos.

Dirección del texto

El método getTextInfo() devuelve información sobre el ordenamiento del texto:

const locale = new Intl.Locale("ar-SA");
const textInfo = locale.getTextInfo();
console.log(textInfo.direction); // "rtl"

Los idiomas de derecha a izquierda como el árabe y el hebreo devuelven "rtl". Los idiomas de izquierda a derecha devuelven "ltr".

Convenciones de semana

El método getWeekInfo() devuelve la estructura de la semana para la configuración regional:

const locale = new Intl.Locale("en-US");
const weekInfo = locale.getWeekInfo();
console.log(weekInfo.firstDay); // 7 (domingo)
console.log(weekInfo.weekend); // [6, 7] (sábado, domingo)
console.log(weekInfo.minimalDays); // 1

Las convenciones de semana varían según la región. Las semanas estadounidenses comienzan el domingo, mientras que la mayoría de las semanas europeas comienzan el lunes.

Zonas horarias

El método getTimeZones() devuelve las zonas horarias para la región de la configuración regional:

const locale = new Intl.Locale("en-US");
const timeZones = locale.getTimeZones();
console.log(timeZones); // ["America/New_York", "America/Chicago", ...]

Este método devuelve identificadores de zona horaria IANA para el código de región.

Maximizando identificadores de configuración regional

El método maximize() agrega subtags probables para crear un identificador completo. Infiere códigos de script y región faltantes basándose en los datos del idioma.

Cuando especificas solo un código de idioma, maximize() agrega el script y la región más comunes:

const locale = new Intl.Locale("en");
const maximized = locale.maximize();
console.log(maximized.baseName); // "en-Latn-US"

El inglés por defecto utiliza el script latino y la región de Estados Unidos porque son las asociaciones más comunes.

La maximización del chino depende del script:

const simplified = new Intl.Locale("zh-Hans");
const maximized = simplified.maximize();
console.log(maximized.baseName); // "zh-Hans-CN"

const traditional = new Intl.Locale("zh-Hant");
const maximizedTrad = traditional.maximize();
console.log(maximizedTrad.baseName); // "zh-Hant-TW"

El chino simplificado se asocia con China, mientras que el chino tradicional se asocia con Taiwán.

Utiliza maximize() cuando normalices entradas de usuario o compares identificadores de locale. Hace que la información implícita sea explícita.

Minimizando identificadores de locale

El método minimize() elimina subtags redundantes para crear el identificador equivalente más corto. Elimina códigos de script y región cuando coinciden con los valores predeterminados probables.

Cuando un locale utiliza el script y la región predeterminados, minimize() los elimina:

const locale = new Intl.Locale("en-Latn-US");
const minimized = locale.minimize();
console.log(minimized.baseName); // "en"

El script latino y la región de Estados Unidos son valores predeterminados para el inglés, por lo que pueden eliminarse sin perder información.

Para locales con regiones no predeterminadas, minimize() mantiene la región:

const locale = new Intl.Locale("en-Latn-GB");
const minimized = locale.minimize();
console.log(minimized.baseName); // "en-GB"

El inglés británico necesita el código de región porque difiere del predeterminado.

Utiliza minimize() para crear identificadores compactos para almacenamiento o URLs mientras preservas el significado.

Conversión a cadenas de texto

El método toString() devuelve el identificador de locale completo incluyendo extensiones:

const locale = new Intl.Locale("en-US", {
  calendar: "gregory",
  numberingSystem: "latn",
  hourCycle: "h12"
});

console.log(locale.toString()); // "en-US-u-ca-gregory-hc-h12-nu-latn"

La representación en cadena es válida para pasarla a otras APIs de Intl o almacenarla como datos de configuración.

También puedes convertir objetos locale a cadenas implícitamente:

const locale = new Intl.Locale("fr-FR");
const formatter = new Intl.DateTimeFormat(locale);

El constructor DateTimeFormat acepta objetos locale directamente y llama a toString() internamente.

Casos de uso prácticos

La API Intl.Locale resuelve varios problemas comunes al construir aplicaciones internacionalizadas.

Construcción de selectores de localización

Los selectores de localización permiten a los usuarios elegir su idioma y región. La API Intl.Locale ayuda a analizar y validar las selecciones de los usuarios:

function createLocaleSelector(locales) {
  const options = locales.map(identifier => {
    const locale = new Intl.Locale(identifier);
    const displayName = new Intl.DisplayNames([identifier], { type: "language" });

    return {
      value: locale.toString(),
      label: displayName.of(locale.language),
      region: locale.region
    };
  });

  return options;
}

const options = createLocaleSelector(["en-US", "en-GB", "fr-FR", "es-MX"]);
console.log(options);
// [
//   { value: "en-US", label: "English", region: "US" },
//   { value: "en-GB", label: "English", region: "GB" },
//   { value: "fr-FR", label: "French", region: "FR" },
//   { value: "es-MX", label: "Spanish", region: "MX" }
// ]

Validación de entrada de localización

Al aceptar identificadores de localización desde la entrada del usuario o archivos de configuración, valídalos antes de usarlos:

function validateLocale(identifier) {
  try {
    const locale = new Intl.Locale(identifier);
    return {
      valid: true,
      locale: locale.toString(),
      language: locale.language,
      region: locale.region
    };
  } catch (error) {
    return {
      valid: false,
      error: error.message
    };
  }
}

console.log(validateLocale("en-US")); // { valid: true, locale: "en-US", ... }
console.log(validateLocale("invalid")); // { valid: false, error: "..." }

Extracción de idioma para alternativas

Al implementar cadenas de alternativas de idioma, extrae el código de idioma sin la región:

function getLanguageFallback(identifier) {
  const locale = new Intl.Locale(identifier);
  const fallbacks = [locale.toString()];

  if (locale.region) {
    const languageOnly = new Intl.Locale(locale.language);
    fallbacks.push(languageOnly.toString());
  }

  fallbacks.push("en");

  return fallbacks;
}

console.log(getLanguageFallback("fr-CA"));
// ["fr-CA", "fr", "en"]

Esto crea una cadena de alternativas que intenta usar la localización específica, luego el idioma sin región, y finalmente el idioma predeterminado.

Configuración de formateadores

Utiliza objetos locale para configurar formateadores Intl con preferencias específicas:

function createFormatter(baseLocale, options = {}) {
  const locale = new Intl.Locale(baseLocale, {
    calendar: options.calendar || "gregory",
    numberingSystem: options.numberingSystem || "latn",
    hourCycle: options.hourCycle || "h23"
  });

  return {
    date: new Intl.DateTimeFormat(locale),
    number: new Intl.NumberFormat(locale),
    locale: locale.toString()
  };
}

const formatter = createFormatter("ar-SA", {
  calendar: "islamic",
  numberingSystem: "arab"
});

console.log(formatter.locale); // "ar-SA-u-ca-islamic-nu-arab"

Detección de preferencias del usuario

Las APIs del navegador proporcionan cadenas de texto locale que puedes analizar para entender las preferencias del usuario:

function getUserPreferences() {
  const userLocale = new Intl.Locale(navigator.language);
  const hourCycles = userLocale.getHourCycles();
  const calendars = userLocale.getCalendars();
  const textInfo = userLocale.getTextInfo();

  return {
    language: userLocale.language,
    region: userLocale.region,
    preferredHourCycle: hourCycles[0],
    preferredCalendar: calendars[0],
    textDirection: textInfo.direction
  };
}

const preferences = getUserPreferences();
console.log(preferences);
// { language: "en", region: "US", preferredHourCycle: "h12", ... }

Esto crea un perfil de preferencias del usuario basado en la configuración de su navegador.

Compatibilidad con navegadores

La API Intl.Locale funciona en todos los navegadores modernos. Chrome, Firefox, Safari y Edge proporcionan soporte completo para el constructor, propiedades y métodos descritos en esta guía.

Los métodos más recientes como getCalendars(), getCollations(), getHourCycles(), getNumberingSystems(), getTextInfo(), getTimeZones() y getWeekInfo() requieren versiones recientes de navegadores. Verifica las tablas de compatibilidad de navegadores antes de usar estos métodos si das soporte a navegadores antiguos.

Node.js soporta la API Intl.Locale a partir de la versión 12, con soporte completo de métodos en la versión 18 y posteriores.

Resumen

La API Intl.Locale transforma cadenas identificadoras de locale en objetos estructurados que puedes inspeccionar y manipular. En lugar de analizar cadenas manualmente, creas objetos locale y lees sus propiedades.

Conceptos fundamentales:

  • Los identificadores de locale contienen componentes de idioma, escritura, región y extensión
  • El constructor Intl.Locale valida identificadores y crea objetos
  • Propiedades como language, region y calendar proporcionan acceso estructurado
  • Métodos como getCalendars() y getHourCycles() devuelven opciones disponibles
  • Los métodos maximize() y minimize() normalizan identificadores
  • Los objetos locale funcionan directamente con otras APIs de Intl

Utiliza la API Intl.Locale cuando construyas selectores de locale, valides entradas de usuario, implementes cadenas de respaldo o configures formateadores. Proporciona una forma estándar de trabajar con identificadores de locale en aplicaciones JavaScript.