¿Cómo mostrar nombres de países en diferentes idiomas?

Utiliza Intl.DisplayNames para convertir códigos de países en nombres de países localizados para usuarios internacionales.

Introducción

Cuando construyes un formulario de envío, una página de perfil de usuario o un selector de direcciones, necesitas mostrar nombres de países. Los usuarios ven "France" en inglés, "Francia" en español, "Frankreich" en alemán y "フランス" en japonés. Cada usuario espera ver los nombres de los países escritos en su propio idioma.

Tu aplicación almacena códigos de países como FR, US o JP en bases de datos y APIs. Estos códigos estandarizados funcionan en todos los sistemas, pero los usuarios necesitan nombres legibles. La API Intl.DisplayNames convierte códigos de países en nombres de países localizados en cualquier idioma sin necesidad de mantener tablas de traducción o depender de bibliotecas externas.

Entendiendo los códigos de países

Los países se identifican mediante códigos de dos letras definidos en el estándar ISO 3166-1 alpha-2. Cada país recibe un código único que permanece constante en todos los idiomas y sistemas.

// Códigos de países comunes
// US = United States
// GB = Great Britain (United Kingdom)
// FR = France
// DE = Germany (Deutschland)
// JP = Japan
// CN = China
// BR = Brazil
// IN = India

Estos códigos aparecen en formularios, URLs, bases de datos y APIs. El código US siempre significa Estados Unidos, independientemente de si tu aplicación se ejecuta en inglés, español, japonés o cualquier otro idioma. El código proporciona un identificador estable mientras que el nombre mostrado cambia según el idioma del usuario.

Usando Intl.DisplayNames para obtener nombres de países

El constructor Intl.DisplayNames crea un formateador que convierte códigos de países en nombres de países. Especificas un locale y estableces el tipo a "region" para obtener nombres de países.

const countryNames = new Intl.DisplayNames(["en"], { type: "region" });

console.log(countryNames.of("US"));
// "United States"

console.log(countryNames.of("FR"));
// "France"

console.log(countryNames.of("JP"));
// "Japan"

El primer argumento es un array de identificadores de locale. La opción type: "region" le indica al formateador que quieres nombres de países o regiones. El método of() toma un código de país y devuelve su nombre localizado.

El término "región" abarca países, territorios y áreas geográficas. Esto incluye países independientes como Francia, territorios como Puerto Rico y regiones especiales como la Unión Europea.

Mostrar nombres de países en diferentes idiomas

El mismo código de país produce diferentes nombres en diferentes idiomas. Crea formateadores para diferentes locales para ver cómo cambian los nombres de los países.

const englishNames = new Intl.DisplayNames(["en"], { type: "region" });
const spanishNames = new Intl.DisplayNames(["es"], { type: "region" });
const germanNames = new Intl.DisplayNames(["de"], { type: "region" });
const japaneseNames = new Intl.DisplayNames(["ja"], { type: "region" });

console.log(englishNames.of("FR"));
// "France"

console.log(spanishNames.of("FR"));
// "Francia"

console.log(germanNames.of("FR"));
// "Frankreich"

console.log(japaneseNames.of("FR"));
// "フランス"

Cada formateador devuelve el nombre del país en su locale de visualización. Esto maneja toda la complejidad de mantener traducciones de nombres de países en diferentes idiomas.

Puedes crear una función que obtenga nombres de países en cualquier idioma.

function getCountryName(countryCode, locale) {
  const names = new Intl.DisplayNames([locale], { type: "region" });
  return names.of(countryCode);
}

console.log(getCountryName("US", "en"));
// "United States"

console.log(getCountryName("US", "fr"));
// "États-Unis"

console.log(getCountryName("US", "ar"));
// "الولايات المتحدة"

console.log(getCountryName("DE", "en"));
// "Germany"

console.log(getCountryName("DE", "de"));
// "Deutschland"

console.log(getCountryName("DE", "es"));
// "Alemania"

Esta función funciona para cualquier combinación de código de país y locale. El navegador proporciona las traducciones automáticamente.

Construir un selector de países

Un caso de uso común es construir un menú desplegable donde los usuarios seleccionan su país. Los nombres de los países deben aparecer en el idioma del usuario.

function createCountrySelector(locale) {
  const countryNames = new Intl.DisplayNames([locale], { type: "region" });

  const countries = [
    "US", "GB", "CA", "AU", "FR", "DE", "ES", "IT",
    "JP", "CN", "KR", "IN", "BR", "MX", "AR", "RU"
  ];

  const select = document.createElement("select");
  select.id = "country";
  select.name = "country";

  const placeholder = document.createElement("option");
  placeholder.value = "";
  placeholder.textContent = "Selecciona un país";
  select.appendChild(placeholder);

  countries.forEach((code) => {
    const option = document.createElement("option");
    option.value = code;
    option.textContent = countryNames.of(code);
    select.appendChild(option);
  });

  return select;
}

const selector = createCountrySelector("en");
document.body.appendChild(selector);

Esto crea un menú desplegable con nombres de países en inglés. Cambia el locale a "es" y la misma función produce un menú desplegable con nombres de países en español. Cámbialo a "ja" y los nombres aparecen en japonés.

Puedes hacer que el selector responda al idioma del navegador del usuario.

function createLocalizedCountrySelector() {
  const userLocale = navigator.language;
  return createCountrySelector(userLocale);
}

const selector = createLocalizedCountrySelector();
document.body.appendChild(selector);

El selector muestra automáticamente los nombres de los países en el idioma preferido del usuario según la configuración de su navegador.

Obtener todos los países disponibles

El método Intl.supportedValuesOf() devuelve un array con todos los códigos de país compatibles. Esto elimina la necesidad de mantener una lista codificada manualmente.

const allCountries = Intl.supportedValuesOf("region");

console.log(allCountries.length);
// 249 (cantidad aproximada a partir de 2025)

console.log(allCountries.slice(0, 10));
// ["AC", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ"]

El método devuelve los códigos en orden alfabético por código, no por nombre de país. Necesitas ordenarlos por nombres localizados si quieres un orden alfabético en un idioma específico.

function getSortedCountries(locale) {
  const countryNames = new Intl.DisplayNames([locale], { type: "region" });
  const allCountries = Intl.supportedValuesOf("region");

  return allCountries
    .map((code) => ({
      code,
      name: countryNames.of(code)
    }))
    .sort((a, b) => a.name.localeCompare(b.name, locale));
}

const sortedEnglish = getSortedCountries("en");
console.log(sortedEnglish.slice(0, 5));
// [
//   { code: "AF", name: "Afghanistan" },
//   { code: "AX", name: "Åland Islands" },
//   { code: "AL", name: "Albania" },
//   { code: "DZ", name: "Algeria" },
//   { code: "AS", name: "American Samoa" }
// ]

const sortedSpanish = getSortedCountries("es");
console.log(sortedSpanish.slice(0, 5));
// [
//   { code: "AF", name: "Afganistán" },
//   { code: "AL", name: "Albania" },
//   { code: "DE", name: "Alemania" },
//   { code: "AD", name: "Andorra" },
//   { code: "AO", name: "Angola" }
// ]

El orden de clasificación difiere entre idiomas porque los nombres de países se ordenan de manera diferente según los alfabetos y las reglas de cotejo.

Construir un selector de países completo

Combina Intl.supportedValuesOf() con Intl.DisplayNames para crear un selector con todos los países disponibles.

function createComprehensiveCountrySelector(locale) {
  const countryNames = new Intl.DisplayNames([locale], { type: "region" });
  const allCountries = Intl.supportedValuesOf("region");

  const sortedCountries = allCountries
    .map((code) => ({
      code,
      name: countryNames.of(code)
    }))
    .sort((a, b) => a.name.localeCompare(b.name, locale));

  const select = document.createElement("select");
  select.id = "country";
  select.name = "country";

  const placeholder = document.createElement("option");
  placeholder.value = "";
  placeholder.textContent = "Selecciona un país";
  select.appendChild(placeholder);

  sortedCountries.forEach(({ code, name }) => {
    const option = document.createElement("option");
    option.value = code;
    option.textContent = name;
    select.appendChild(option);
  });

  return select;
}

const selector = createComprehensiveCountrySelector("en");
document.body.appendChild(selector);

Este selector incluye los 249 países y territorios compatibles con el navegador, ordenados alfabéticamente en el idioma del usuario.

Manejo de códigos de país inválidos

No todas las cadenas de dos letras son códigos de país válidos. El método of() maneja códigos inválidos según la opción fallback.

const withCodeFallback = new Intl.DisplayNames(["en"], {
  type: "region",
  fallback: "code"
});

const withNoneFallback = new Intl.DisplayNames(["en"], {
  type: "region",
  fallback: "none"
});

console.log(withCodeFallback.of("US"));
// "United States"

console.log(withCodeFallback.of("XX"));
// "XX"

console.log(withNoneFallback.of("US"));
// "United States"

console.log(withNoneFallback.of("XX"));
// undefined

La opción fallback: "code" devuelve el código de entrada cuando no existe un país. La opción fallback: "none" devuelve undefined para códigos inválidos.

Utiliza fallback: "none" cuando necesites detectar códigos inválidos y manejarlos explícitamente.

function getValidatedCountryName(code, locale) {
  const names = new Intl.DisplayNames([locale], {
    type: "region",
    fallback: "none"
  });

  const name = names.of(code);

  if (name === undefined) {
    return "Unknown country";
  }

  return name;
}

console.log(getValidatedCountryName("US", "en"));
// "United States"

console.log(getValidatedCountryName("INVALID", "en"));
// "Unknown country"

Este patrón te ayuda a validar la entrada del usuario o datos de fuentes externas.

Control de la longitud del nombre del país con style

La opción style controla cómo aparecen los nombres de los países. Tres valores producen diferentes longitudes de salida.

const longNames = new Intl.DisplayNames(["en"], {
  type: "region",
  style: "long"
});

const shortNames = new Intl.DisplayNames(["en"], {
  type: "region",
  style: "short"
});

const narrowNames = new Intl.DisplayNames(["en"], {
  type: "region",
  style: "narrow"
});

console.log(longNames.of("US"));
// "United States"

console.log(shortNames.of("US"));
// "US"

console.log(narrowNames.of("US"));
// "US"

El estilo long es el predeterminado y produce nombres completos de países. Los estilos short y narrow devuelven formas abreviadas cuando están disponibles. Para la mayoría de los países, los estilos corto y estrecho devuelven el código del país mismo.

Algunos países tienen formas cortas distintas.

const longNames = new Intl.DisplayNames(["en"], {
  type: "region",
  style: "long"
});

const shortNames = new Intl.DisplayNames(["en"], {
  type: "region",
  style: "short"
});

console.log(longNames.of("GB"));
// "United Kingdom"

console.log(shortNames.of("GB"));
// "UK"

console.log(longNames.of("BO"));
// "Bolivia"

console.log(shortNames.of("BO"));
// "Bolivia"

Utiliza el estilo predeterminado long para la mayoría de las interfaces. Usa short o narrow cuando el espacio es limitado, como en navegación móvil o tablas compactas.

Mostrando nombres de regiones para territorios

El estándar ISO 3166-1 incluye territorios, dependencias y áreas especiales más allá de los países independientes. La API Intl.DisplayNames también maneja estos casos.

const regionNames = new Intl.DisplayNames(["en"], { type: "region" });

console.log(regionNames.of("PR"));
// "Puerto Rico"

console.log(regionNames.of("GU"));
// "Guam"

console.log(regionNames.of("HK"));
// "Hong Kong"

console.log(regionNames.of("MQ"));
// "Martinique"

console.log(regionNames.of("GF"));
// "French Guiana"

Estos códigos funcionan de la misma manera que los códigos de país. Su aplicación puede tratarlos uniformemente mientras que el navegador proporciona nombres localizados apropiados.

Usando códigos numéricos de región

El estándar ISO 3166-1 también define códigos numéricos. La API Intl.DisplayNames acepta códigos numéricos de región UN M.49 además de códigos de dos letras.

const regionNames = new Intl.DisplayNames(["en"], { type: "region" });

console.log(regionNames.of("840"));
// "United States"

console.log(regionNames.of("250"));
// "France"

console.log(regionNames.of("392"));
// "Japan"

Los códigos numéricos también representan regiones geográficas más amplias.

const regionNames = new Intl.DisplayNames(["en"], { type: "region" });

console.log(regionNames.of("150"));
// "Europe"

console.log(regionNames.of("019"));
// "Americas"

console.log(regionNames.of("142"));
// "Asia"

console.log(regionNames.of("002"));
// "Africa"

console.log(regionNames.of("009"));
// "Oceania"

Estos códigos funcionan en todos los idiomas.

const englishRegions = new Intl.DisplayNames(["en"], { type: "region" });
const spanishRegions = new Intl.DisplayNames(["es"], { type: "region" });

console.log(englishRegions.of("150"));
// "Europe"

console.log(spanishRegions.of("150"));
// "Europa"

Utilice códigos numéricos cuando necesite evitar problemas de codificación de caracteres o trabajar con sistemas que utilizan códigos UN M.49.

Almacenamiento en caché de instancias DisplayNames para mejorar el rendimiento

La creación de instancias de Intl.DisplayNames tiene una sobrecarga mínima, pero las aplicaciones que convierten muchos códigos de país pueden beneficiarse del almacenamiento en caché de formateadores.

const displayNamesCache = new Map();

function getDisplayNames(locale, type) {
  const key = `${locale}-${type}`;

  if (!displayNamesCache.has(key)) {
    displayNamesCache.set(
      key,
      new Intl.DisplayNames([locale], { type })
    );
  }

  return displayNamesCache.get(key);
}

function getCountryName(code, locale) {
  const formatter = getDisplayNames(locale, "region");
  return formatter.of(code);
}

console.log(getCountryName("US", "en"));
// "United States"

console.log(getCountryName("FR", "en"));
// "France"

console.log(getCountryName("US", "es"));
// "Estados Unidos"

La caché almacena formateadores indexados por locale y tipo. Las llamadas subsiguientes reutilizan los formateadores existentes en lugar de crear nuevos.

Esta optimización es más importante cuando se renderizan grandes listas de países o se procesan cientos de códigos de país en tablas o cuadrículas de datos.

Manejo de alternativas de configuración regional

El constructor Intl.DisplayNames acepta un array de configuraciones regionales. Si la primera configuración regional no es compatible, el navegador recurre a la siguiente configuración regional en el array.

const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "region" });

console.log(names.of("US"));
// "United States"

El navegador intenta primero con "xx-XX", que no existe, y luego recurre a "en". Esto asegura que tu código funcione incluso cuando la configuración regional solicitada no está disponible.

Puedes comprobar qué configuración regional utiliza realmente el formateador.

const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "region" });

console.log(names.resolvedOptions().locale);
// "en"

El método resolvedOptions() devuelve la configuración regional a la que se resolvió el formateador después del procesamiento de alternativas.

Comparación de nombres de países en diferentes idiomas

Los diferentes idiomas formatean los nombres de países de manera distinta. Algunos idiomas ponen en mayúscula los nombres de países, otros no. Algunos idiomas incluyen artículos, otros no.

const english = new Intl.DisplayNames(["en"], { type: "region" });
const french = new Intl.DisplayNames(["fr"], { type: "region" });
const german = new Intl.DisplayNames(["de"], { type: "region" });

console.log(english.of("US"));
// "United States"

console.log(french.of("US"));
// "États-Unis"

console.log(german.of("US"));
// "Vereinigte Staaten"

console.log(english.of("NL"));
// "Netherlands"

console.log(french.of("NL"));
// "Pays-Bas"

console.log(german.of("NL"));
// "Niederlande"

El formateador maneja automáticamente todas estas convenciones lingüísticas. No necesitas conocer las reglas gramaticales de cada idioma.

Compatibilidad con navegadores

La API Intl.DisplayNames con type: "region" está disponible en todos los navegadores modernos. Ha sido compatible desde 2021 en los principales navegadores, incluyendo Chrome, Firefox, Safari y Edge.

Las aplicaciones modernas pueden usar esta API sin polyfills o alternativas. El navegador mantiene los datos de nombres de países y los mantiene actualizados a medida que cambian los países y territorios.

Puedes verificar si la API está disponible antes de usarla.

if (typeof Intl.DisplayNames !== "undefined") {
  const names = new Intl.DisplayNames(["en"], { type: "region" });
  console.log(names.of("US"));
} else {
  console.log("Intl.DisplayNames is not supported");
}

Para aplicaciones que soportan navegadores más antiguos, proporciona una alternativa utilizando una tabla de búsqueda estática de nombres de países.

function getCountryName(code, locale) {
  if (typeof Intl.DisplayNames !== "undefined") {
    const names = new Intl.DisplayNames([locale], { type: "region" });
    return names.of(code);
  }

  const fallbackNames = {
    US: "United States",
    GB: "United Kingdom",
    FR: "France",
    DE: "Germany",
    JP: "Japan"
  };

  return fallbackNames[code] || code;
}

console.log(getCountryName("US", "en"));
// "United States"

Esto asegura que tu aplicación funcione en todos los navegadores, aunque los navegadores más antiguos pierdan la función de localización automática.