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

Usa 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 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 mantener tablas de traducción ni depender de bibliotecas externas.

Comprender 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.

// Common country codes
// 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, ya sea que tu aplicación se ejecute 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.

Usar 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 una configuración regional y estableces el tipo en "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 configuración regional. La opción type: "region" indica al formateador que deseas 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 nombres diferentes en distintos 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 gestiona toda la complejidad de mantener las traducciones de nombres de países en todos los 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 = "Select a country";
  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 de todos los códigos de país admitidos. Esto elimina la necesidad de mantener una lista codificada.

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

console.log(allCountries.length);
// 249 (approximate count as of 2025)

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

El método devuelve códigos en orden alfabético por código, no por nombre de país. Necesitas ordenar por nombres localizados si quieres 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 en distintos alfabetos y reglas de intercalación.

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 = "Select a country";
  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.

Gestionar códigos de país no válidos

No todas las cadenas de dos letras son códigos de país válidos. El método of() gestiona códigos no vá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 ningún país. La opción fallback: "none" devuelve undefined para códigos no válidos.

Usa fallback: "none" cuando necesites detectar códigos no válidos y gestionarlos 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.

Controlar la longitud del nombre del país con style

La opción style controla cómo aparecen los nombres de 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 de países completos. Los estilos short y narrow devuelven formas abreviadas cuando están disponibles. Para la mayoría de los países, los estilos short y narrow devuelven el código del país en sí.

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"

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

Mostrar nombres de regiones para territorios

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

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. Tu aplicación puede tratarlos de manera uniforme mientras el navegador proporciona nombres localizados apropiados.

Uso de códigos de región numéricos

El estándar ISO 3166-1 también define códigos numéricos. La API Intl.DisplayNames acepta códigos de región numéricos 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"

Utiliza códigos numéricos cuando necesites evitar problemas de codificación de caracteres o trabajar con sistemas que usan códigos UN M.49.

Almacenamiento en caché de instancias DisplayNames para mejorar el rendimiento

Crear 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 configuración regional y tipo. Las llamadas posteriores reutilizan los formateadores existentes en lugar de crear nuevos.

Esta optimización es más importante al renderizar listas grandes de países o procesar cientos de códigos de país en tablas o cuadrículas de datos.

Manejo de respaldos de configuración regional

El constructor de 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 del 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 garantiza que tu código funcione incluso cuando la configuración regional solicitada no esté disponible.

Puedes verificar 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 el formateador se resolvió después del procesamiento de respaldo.

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

Los diferentes idiomas formatean los nombres de países de manera diferente. Algunos idiomas escriben los nombres de países con mayúscula inicial, 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 todas estas convenciones lingüísticas automáticamente. 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 ni 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 usando 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.