Cómo verificar si un identificador de configuración regional es válido

Valida identificadores de configuración regional antes de usarlos para formatear fechas, números y monedas

Introducción

Cuando tu aplicación acepta identificadores de configuración regional desde la entrada del usuario, respuestas de API o archivos de configuración, necesitas verificar que sean válidos antes de usarlos. Un identificador de configuración regional inválido hará que las funciones de formateo lancen errores o produzcan resultados inesperados.

La validación asegura que cadenas como en-US sean estructuralmente correctas según los estándares internacionales. Esto previene errores en tiempo de ejecución al pasar identificadores de configuración regional a la API Intl u otras bibliotecas de internacionalización.

JavaScript proporciona dos métodos integrados para validar identificadores de configuración regional. Ambos métodos verifican la estructura del identificador contra el estándar BCP 47, que define el formato para etiquetas de idioma.

Qué hace válido a un identificador de configuración regional

Un identificador de configuración regional sigue el estándar BCP 47 para etiquetas de idioma. Este estándar define la estructura y reglas para combinar componentes de idioma, escritura, región y extensión.

Los identificadores de configuración regional válidos usan guiones para separar componentes, no guiones bajos u otros caracteres. El código de idioma debe ser un código ISO 639 reconocido, y los códigos de región deben ser códigos ISO 3166-1 reconocidos.

Ejemplos de identificadores de configuración regional válidos:

  • en (inglés)
  • en-US (inglés americano)
  • zh-Hans (chino simplificado)
  • zh-Hans-CN (chino simplificado usado en China)
  • en-US-u-ca-gregory (inglés americano con calendario gregoriano)

Ejemplos de identificadores de configuración regional inválidos:

  • en_US (usa guion bajo en lugar de guion)
  • english (no es un código de idioma reconocido)
  • en-USA (el código de región debe tener dos letras, no tres)
  • EN-us (el código de idioma debe estar en minúsculas)
  • abc-XY (el código de idioma no existe)

Los métodos de validación verifican estas reglas estructurales y confirman que los códigos son estándares reconocidos.

Uso de Intl.getCanonicalLocales para validar

El método Intl.getCanonicalLocales() valida identificadores de configuración regional y los devuelve en su forma canónica. Este método acepta un único identificador de configuración regional o un array de identificadores.

const result = Intl.getCanonicalLocales("en-US");
console.log(result);
// Output: ["en-US"]

El método normaliza la entrada convirtiéndola al formato estándar. Incluso si pasas un identificador de configuración regional con mayúsculas incorrectas, devuelve la forma canónica correcta:

const result = Intl.getCanonicalLocales("EN-us");
console.log(result);
// Output: ["en-US"]

Cuando pasas un identificador de configuración regional no válido, el método lanza un RangeError:

try {
  Intl.getCanonicalLocales("en_US");
} catch (error) {
  console.error(error.name);
  // Output: "RangeError"
  console.error(error.message);
  // Output: "en_US is not a structurally valid language tag"
}

Este error indica que el identificador no sigue la estructura BCP 47. Puedes capturar este error para manejar entradas no válidas de forma elegante.

Validación de múltiples identificadores de configuración regional

El método Intl.getCanonicalLocales() acepta un array para validar múltiples identificadores de configuración regional a la vez. El método devuelve un array de formas canónicas para todos los identificadores válidos.

const locales = ["en-US", "fr-FR", "es-MX"];
const result = Intl.getCanonicalLocales(locales);
console.log(result);
// Output: ["en-US", "fr-FR", "es-MX"]

El método también elimina identificadores de configuración regional duplicados del resultado:

const locales = ["en-US", "EN-us", "en-US"];
const result = Intl.getCanonicalLocales(locales);
console.log(result);
// Output: ["en-US"]

Los tres valores de entrada representan la misma configuración regional, por lo que el método devuelve solo una forma canónica.

Si alguna configuración regional en el array no es válida, el método completo lanza un error:

try {
  Intl.getCanonicalLocales(["en-US", "invalid", "fr-FR"]);
} catch (error) {
  console.error(error.message);
  // Output: "invalid is not a structurally valid language tag"
}

Al validar listas proporcionadas por el usuario, valida cada configuración regional individualmente para identificar qué identificadores específicos no son válidos.

Uso del constructor Intl.Locale para validar

El constructor Intl.Locale proporciona otra forma de validar identificadores de configuración regional. Cuando creas un objeto de configuración regional con un identificador no válido, el constructor lanza un RangeError.

try {
  const locale = new Intl.Locale("en-US");
  console.log("Valid locale");
} catch (error) {
  console.error("Invalid locale");
}
// Output: "Valid locale"

El constructor lanza un error para identificadores no válidos:

try {
  const locale = new Intl.Locale("en_US");
  console.log("Valid locale");
} catch (error) {
  console.error("Invalid locale");
  console.error(error.message);
}
// Output: "Invalid locale"
// Output: "invalid language subtag: en_US"

A diferencia de Intl.getCanonicalLocales(), el constructor Intl.Locale no normaliza las mayúsculas. Requiere que el identificador use las mayúsculas correctas:

const locale1 = new Intl.Locale("en-US");
console.log(locale1.baseName);
// Output: "en-US"

const locale2 = new Intl.Locale("EN-US");
console.log(locale2.baseName);
// Output: "en-US"

Se aceptan códigos de idioma tanto en mayúsculas como en minúsculas, y el constructor los normaliza a la forma canónica.

Elegir un método de validación

Ambos métodos de validación sirven para diferentes propósitos y proporcionan diferentes características.

Usa Intl.getCanonicalLocales() cuando necesites:

  • Normalizar identificadores de configuración regional a su forma canónica
  • Validar y eliminar duplicados de una lista de identificadores de configuración regional
  • Convertir el uso inconsistente de mayúsculas al formato estándar
  • Validar identificadores de configuración regional sin crear objetos

Usa el constructor Intl.Locale cuando necesites:

  • Validar un identificador de configuración regional y trabajar inmediatamente con sus propiedades
  • Extraer componentes como idioma, región o escritura del identificador
  • Crear un objeto de configuración regional para usar con otras APIs de Intl
  • Validar y manipular identificadores de configuración regional juntos

El constructor Intl.Locale es más potente porque crea un objeto que puedes consultar y modificar. Sin embargo, si solo necesitas validación y normalización, Intl.getCanonicalLocales() es más simple.

Validar entrada del usuario

Al aceptar identificadores de configuración regional desde la entrada del usuario, valídalos antes de usarlos en tu aplicación. Esto previene errores y proporciona retroalimentación clara cuando los usuarios introducen valores inválidos.

function validateUserLocale(input) {
  try {
    const canonicalLocales = Intl.getCanonicalLocales(input);
    return {
      valid: true,
      locale: canonicalLocales[0]
    };
  } catch (error) {
    return {
      valid: false,
      error: "Please enter a valid locale identifier like en-US or fr-FR"
    };
  }
}

const result1 = validateUserLocale("en-US");
console.log(result1);
// Output: { valid: true, locale: "en-US" }

const result2 = validateUserLocale("english");
console.log(result2);
// Output: { valid: false, error: "Please enter a valid locale..." }

Esta función valida la entrada y devuelve la configuración regional canónica o un mensaje de error fácil de entender.

Validar datos de configuración

Las aplicaciones a menudo cargan identificadores de configuración regional desde archivos de configuración o variables de entorno. Valida estos valores cuando tu aplicación se inicie para detectar errores de configuración temprano.

function loadLocaleConfig(configLocales) {
  const validLocales = [];
  const invalidLocales = [];

  for (const locale of configLocales) {
    try {
      const canonical = Intl.getCanonicalLocales(locale);
      validLocales.push(canonical[0]);
    } catch (error) {
      invalidLocales.push(locale);
    }
  }

  if (invalidLocales.length > 0) {
    console.warn("Invalid locale identifiers found:", invalidLocales);
  }

  return validLocales;
}

const config = ["en-US", "fr-FR", "invalid", "es_MX", "de-DE"];
const locales = loadLocaleConfig(config);
console.log(locales);
// Output: ["en-US", "fr-FR", "de-DE"]
// Warning: Invalid locale identifiers found: ["invalid", "es_MX"]

Esta función filtra los identificadores de configuración regional inválidos y registra una advertencia, permitiendo que la aplicación continúe con las configuraciones regionales válidas.

Validar respuestas de API

Al recibir identificadores de configuración regional desde APIs externas, valídalos antes de usarlos en tu aplicación. Las APIs pueden devolver identificadores de configuración regional en formatos no estándar o con errores.

function processApiLocale(apiResponse) {
  const locale = apiResponse.preferredLocale;

  try {
    const validated = new Intl.Locale(locale);
    return {
      success: true,
      language: validated.language,
      region: validated.region,
      baseName: validated.baseName
    };
  } catch (error) {
    console.error("API returned invalid locale:", locale);
    return {
      success: false,
      fallback: "en-US"
    };
  }
}

const response1 = { preferredLocale: "fr-CA" };
console.log(processApiLocale(response1));
// Output: { success: true, language: "fr", region: "CA", baseName: "fr-CA" }

const response2 = { preferredLocale: "invalid_locale" };
console.log(processApiLocale(response2));
// Output: { success: false, fallback: "en-US" }

Esta función valida la respuesta de la API y extrae información estructurada sobre la configuración regional, o proporciona un valor de respaldo si la configuración regional no es válida.