Как проверить, является ли идентификатор локали допустимым
Проверяйте идентификаторы локалей перед их использованием для форматирования дат, чисел и валют
Введение
Когда ваше приложение принимает идентификаторы локалей из пользовательского ввода, ответов API или конфигурационных файлов, необходимо проверять их на корректность перед использованием. Неверный идентификатор локали приведет к тому, что функции форматирования вызовут ошибки или дадут неожиданные результаты.
Проверка гарантирует, что строки, такие как en-US, структурно корректны в соответствии с международными стандартами. Это предотвращает ошибки во время выполнения при передаче идентификаторов локалей в API Intl или другие библиотеки интернационализации.
JavaScript предоставляет два встроенных метода для проверки идентификаторов локалей. Оба метода проверяют структуру идентификатора на соответствие стандарту BCP 47, который определяет формат языковых тегов.
Что делает идентификатор локали корректным
Идентификатор локали следует стандарту BCP 47 для языковых тегов. Этот стандарт определяет структуру и правила для комбинирования компонентов языка, письменности, региона и расширений.
Корректные идентификаторы локалей используют дефисы для разделения компонентов, а не подчеркивания или другие символы. Код языка должен быть признанным кодом ISO 639, а коды регионов — признанными кодами ISO 3166-1.
Примеры корректных идентификаторов локалей:
en(английский)en-US(американский английский)zh-Hans(упрощенный китайский)zh-Hans-CN(упрощенный китайский, используемый в Китае)en-US-u-ca-gregory(американский английский с григорианским календарем)
Примеры некорректных идентификаторов локалей:
en_US(используется подчеркивание вместо дефиса)english(не является признанным кодом языка)en-USA(код региона должен состоять из двух букв, а не трех)EN-us(код языка должен быть в нижнем регистре)abc-XY(код языка не существует)
Методы проверки проверяют эти структурные правила и подтверждают, что коды соответствуют признанным стандартам.
Использование Intl.getCanonicalLocales для проверки
Метод Intl.getCanonicalLocales() проверяет идентификаторы локалей и возвращает их в канонической форме. Этот метод принимает один идентификатор локали или массив идентификаторов.
const result = Intl.getCanonicalLocales("en-US");
console.log(result);
// Вывод: ["en-US"]
Метод нормализует ввод, преобразуя его в стандартный формат. Даже если вы передадите идентификатор локали с неправильным регистром, он вернет правильную каноническую форму:
const result = Intl.getCanonicalLocales("EN-us");
console.log(result);
// Вывод: ["en-US"]
Если вы передадите недопустимый идентификатор локали, метод выбросит ошибку RangeError:
try {
Intl.getCanonicalLocales("en_US");
} catch (error) {
console.error(error.name);
// Вывод: "RangeError"
console.error(error.message);
// Вывод: "en_US не является структурно допустимым языковым тегом"
}
Эта ошибка указывает, что идентификатор не соответствует структуре BCP 47. Вы можете обработать эту ошибку, чтобы корректно работать с недопустимым вводом.
Проверка нескольких идентификаторов локалей
Метод Intl.getCanonicalLocales() принимает массив для проверки нескольких идентификаторов локалей одновременно. Метод возвращает массив канонических форм для всех допустимых идентификаторов.
const locales = ["en-US", "fr-FR", "es-MX"];
const result = Intl.getCanonicalLocales(locales);
console.log(result);
// Вывод: ["en-US", "fr-FR", "es-MX"]
Метод также удаляет дублирующиеся идентификаторы локалей из результата:
const locales = ["en-US", "EN-us", "en-US"];
const result = Intl.getCanonicalLocales(locales);
console.log(result);
// Вывод: ["en-US"]
Все три входных значения представляют одну и ту же локаль, поэтому метод возвращает только одну каноническую форму.
Если любая локаль в массиве недопустима, метод выбрасывает ошибку:
try {
Intl.getCanonicalLocales(["en-US", "invalid", "fr-FR"]);
} catch (error) {
console.error(error.message);
// Вывод: "invalid не является структурно допустимым языковым тегом"
}
При проверке списков, предоставленных пользователем, проверяйте каждую локаль отдельно, чтобы определить, какие конкретные идентификаторы недопустимы.
Использование конструктора Intl.Locale для проверки
Конструктор Intl.Locale предоставляет еще один способ проверки идентификаторов локали. Если вы создаете объект локали с недопустимым идентификатором, конструктор выбрасывает исключение RangeError.
try {
const locale = new Intl.Locale("en-US");
console.log("Допустимая локаль");
} catch (error) {
console.error("Недопустимая локаль");
}
// Вывод: "Допустимая локаль"
Конструктор выбрасывает ошибку для недопустимых идентификаторов:
try {
const locale = new Intl.Locale("en_US");
console.log("Допустимая локаль");
} catch (error) {
console.error("Недопустимая локаль");
console.error(error.message);
}
// Вывод: "Недопустимая локаль"
// Вывод: "недопустимый языковой подтег: en_US"
В отличие от Intl.getCanonicalLocales(), конструктор Intl.Locale не нормализует регистр. Он требует, чтобы идентификатор использовал правильный регистр:
const locale1 = new Intl.Locale("en-US");
console.log(locale1.baseName);
// Вывод: "en-US"
const locale2 = new Intl.Locale("EN-US");
console.log(locale2.baseName);
// Вывод: "en-US"
Допускаются как прописные, так и строчные коды языков, и конструктор нормализует их до канонической формы.
Выбор метода проверки
Оба метода проверки служат разным целям и предоставляют разные возможности.
Используйте Intl.getCanonicalLocales(), если вам нужно:
- Нормализовать идентификаторы локалей до их канонической формы
- Проверить и устранить дублирование списка идентификаторов локалей
- Преобразовать несоответствующий регистр в стандартный формат
- Проверить идентификаторы локалей без создания объектов
Используйте конструктор Intl.Locale, если вам нужно:
- Проверить идентификатор локали и сразу работать с его свойствами
- Извлечь компоненты, такие как язык, регион или скрипт, из идентификатора
- Создать объект локали для использования с другими API Intl
- Проверить и манипулировать идентификаторами локалей вместе
Конструктор Intl.Locale более мощный, так как создает объект, который можно запрашивать и изменять. Однако, если вам нужна только проверка и нормализация, Intl.getCanonicalLocales() проще.
Проверка пользовательского ввода
При приёме идентификаторов локалей от пользователя проверяйте их перед использованием в вашем приложении. Это предотвращает ошибки и предоставляет понятную обратную связь, если пользователь вводит недопустимые значения.
function validateUserLocale(input) {
try {
const canonicalLocales = Intl.getCanonicalLocales(input);
return {
valid: true,
locale: canonicalLocales[0]
};
} catch (error) {
return {
valid: false,
error: "Введите корректный идентификатор локали, например en-US или fr-FR"
};
}
}
const result1 = validateUserLocale("en-US");
console.log(result1);
// Вывод: { valid: true, locale: "en-US" }
const result2 = validateUserLocale("english");
console.log(result2);
// Вывод: { valid: false, error: "Введите корректный идентификатор локали..." }
Эта функция проверяет ввод и возвращает либо каноническую локаль, либо понятное сообщение об ошибке.
Проверка данных конфигурации
Приложения часто загружают идентификаторы локалей из конфигурационных файлов или переменных окружения. Проверяйте эти значения при запуске приложения, чтобы заранее выявить ошибки конфигурации.
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("Обнаружены недопустимые идентификаторы локалей:", invalidLocales);
}
return validLocales;
}
const config = ["en-US", "fr-FR", "invalid", "es_MX", "de-DE"];
const locales = loadLocaleConfig(config);
console.log(locales);
// Вывод: ["en-US", "fr-FR", "de-DE"]
// Предупреждение: Обнаружены недопустимые идентификаторы локалей: ["invalid", "es_MX"]
Эта функция отфильтровывает недопустимые идентификаторы локалей и выводит предупреждение, позволяя приложению продолжить работу с допустимыми локалями.
Проверка ответов API
При получении идентификаторов локалей от внешних API проверяйте их перед использованием в вашем приложении. API могут возвращать идентификаторы локалей в нестандартных форматах или с ошибками.
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 вернул недопустимую локаль:", locale);
return {
success: false,
fallback: "en-US"
};
}
}
const response1 = { preferredLocale: "fr-CA" };
console.log(processApiLocale(response1));
// Вывод: { success: true, language: "fr", region: "CA", baseName: "fr-CA" }
const response2 = { preferredLocale: "invalid_locale" };
console.log(processApiLocale(response2));
// Вывод: { success: false, fallback: "en-US" }
Эта функция проверяет ответ API и извлекает структурированную информацию о локали или предоставляет значение по умолчанию, если локаль недопустима.