Строгий и нестрогий режимы

Библиотека Globalize активно использует механизмы обработки локализации, чисел, дат, валют и сообщений. Одним из ключевых аспектов работы становится поведение при ошибках, отсутствии данных CLDR и некорректных параметрах. Для этого применяются строгий и нестрогий режимы обработки.

Понимание различий между ними критически важно при разработке интернационализированных приложений, поскольку ошибки локализации могут приводить как к падению приложения, так и к скрытым логическим дефектам.


Понятие строгого режима

Строгий режим предполагает максимально жёсткую проверку входных данных, локалей и параметров форматирования. При любой ошибке библиотека генерирует исключение.

Подобное поведение особенно полезно:

  • при разработке;
  • при тестировании;
  • в CI/CD;
  • во время поиска ошибок локализации;
  • при валидации переводов.

Пример строгой проверки локали

const Globalize = require("globalize");

Globalize.locale("ru");

const formatter = Globalize.numberFormatter();

console.log(formatter(12345.67));

Если CLDR-данные для ru не были загружены:

Error: E_MISSING_CLDR

В строгом режиме ошибка возникает немедленно.


Поведение при отсутствии CLDR-данных

Библиотека требует предварительной загрузки данных Unicode CLDR.

Например:

const Globalize = require("globalize");

Globalize.locale("fr");

const dateFormatter = Globalize.dateFormatter({
    datetime: "medium"
});

Без подключения:

cldr-data/main/fr/ca-gregorian.json
cldr-data/main/fr/timeZoneNames.json

будет выброшено исключение.

Такой подход предотвращает:

  • тихое повреждение данных;
  • неверное форматирование;
  • отображение дат в неправильной культуре;
  • смешивание локалей.

Ошибки как часть архитектуры

В строгом режиме исключения рассматриваются как механизм контроля качества.

Типичные категории ошибок:

Код ошибки Описание
E_MISSING_CLDR отсутствуют CLDR-данные
E_INVALID_PAR_TYPE неверный тип параметра
E_DEFAULT_LOCALE_NOT_DEFINED локаль по умолчанию не установлена
E_UNSUPPORTED операция не поддерживается

Проверка параметров форматирования

Строгий режим валидирует параметры форматтера.

Корректный пример

const formatter = Globalize.numberFormatter({
    minimumFractionDigits: 2
});

Некорректный пример

const formatter = Globalize.numberFormatter({
    minimumFractionDigits: "2"
});

Результат:

Error: E_INVALID_PAR_TYPE

Библиотека требует именно число, а не строку.


Проверка типов данных

Строгая обработка распространяется и на входные значения.

Пример

const formatter = Globalize.currencyFormatter("USD");

formatter("100");

Ошибка:

Error: E_INVALID_PAR_TYPE

Строковое значение недопустимо.

Правильный вариант:

formatter(100);

Нестрогий режим

Нестрогий режим предполагает более мягкое поведение системы. Ошибки либо игнорируются, либо обрабатываются через fallback-механизмы.

В самой библиотеке Globalize отсутствует отдельный глобальный переключатель strict/sloppy, однако разработчик может реализовать нестрогую модель самостоятельно.

Обычно используются:

  • try/catch;
  • fallback-локали;
  • значения по умолчанию;
  • резервные форматтеры;
  • безопасные обёртки.

Реализация нестрогого поведения

Пример безопасного форматирования

function safeNumberFormat(value) {
    try {
        return Globalize.numberFormatter()(value);
    } catch (e) {
        return String(value);
    }
}

Если форматирование невозможно:

  • приложение не падает;
  • значение отображается как обычная строка.

Использование fallback-локалей

Нестрогий режим часто строится на резервных локалях.

Пример

function setLocale(locale) {
    try {
        Globalize.locale(locale);
    } catch (e) {
        Globalize.locale("en");
    }
}

Если нужная локаль отсутствует:

  • используется английская;
  • приложение продолжает работу.

Сравнение подходов

Особенность Строгий режим Нестрогий режим
Ошибки вызывают исключение могут игнорироваться
Надёжность высокая средняя
Удобство пользователя ниже при ошибках выше
Контроль качества максимальный ограниченный
Поведение в production риск падения устойчивость выше

Строгий режим при работе с сообщениями

Модуль сообщений особенно чувствителен к отсутствующим переводам.

Пример

const messageFormatter = Globalize.messageFormatter("welcome");

Если ключ welcome отсутствует:

Error: E_MISSING_MESSAGE_BUNDLE

Нестрогая обработка переводов

Часто реализуется собственный fallback.

Пример

function translate(key) {
    try {
        return Globalize.messageFormatter(key)();
    } catch (e) {
        return key;
    }
}

При отсутствии перевода:

translate("menu.profile");

результатом станет:

menu.profile

Влияние на UX

Строгий режим полезен разработчикам, но может ухудшать пользовательский опыт.

Например:

  • одна ошибка локализации способна сломать интерфейс;
  • отсутствующий перевод приводит к исключению;
  • неправильный формат даты блокирует рендеринг.

Нестрогий подход обеспечивает:

  • устойчивость интерфейса;
  • постепенную деградацию;
  • отображение резервных значений.

Комбинированная стратегия

На практике обычно комбинируются оба подхода.

Во время разработки

Используется строгая модель:

Globalize.locale("de");

Ошибки не скрываются.

В production

Используются безопасные обёртки:

function safeCurrency(value) {
    try {
        return Globalize.currencyFormatter("EUR")(value);
    } catch {
        return value + " EUR";
    }
}

Обработка ошибок через middleware

В крупных приложениях форматирование часто инкапсулируется.

Пример сервиса локализации

class I18nService {

    formatNumber(value) {
        try {
            return Globalize.numberFormatter()(value);
        } catch (e) {
            console.error(e);
            return value;
        }
    }

}

Преимущества:

  • централизованный контроль;
  • единая политика ошибок;
  • упрощённая диагностика.

Проверка загрузки CLDR

Строгий режим особенно полезен при инициализации.

Пример

const likelySubtags = require(
    "cldr-data/supplemental/likelySubtags.json"
);

Globalize.load(likelySubtags);

Если файл повреждён:

Error: E_MISSING_CLDR

Проблема выявляется сразу после запуска приложения.


Валидация валют

Пример корректного кода

Globalize.currencyFormatter("USD")(100);

Некорректный код

Globalize.currencyFormatter("UNKNOWN")(100);

Ошибка:

Error: E_UNSUPPORTED

В строгом режиме это предотвращает использование несуществующих валют.


Безопасные фабрики форматтеров

Нестрогий подход часто реализуется через фабрики.

Пример

function createSafeDateFormatter(options) {

    try {
        return Globalize.dateFormatter(options);

    } catch (e) {

        return function(value) {
            return String(value);
        };

    }

}

Работа с пользовательскими локалями

Пользователь может передать:

ru-RU
ru
RU
russian

Строгий режим отвергнет некорректные значения.

Пример проверки

try {

    Globalize.locale("russian");

} catch (e) {

    console.error("Некорректная локаль");

}

Нормализация локалей

Перед использованием локаль часто нормализуют.

Пример

function normalizeLocale(locale) {

    const supported = ["en", "ru", "de"];

    if (supported.includes(locale)) {
        return locale;
    }

    return "en";
}

Это типичная реализация нестрогой обработки.


Строгий режим и тестирование

При unit-тестировании строгая модель помогает выявлять:

  • отсутствующие переводы;
  • неверные параметры;
  • пропущенные CLDR-файлы;
  • ошибки интеграции.

Пример теста

test("formatter should exist", () => {

    expect(() => {
        Globalize.numberFormatter();
    }).not.toThrow();

});

Диагностика ошибок

Исключения библиотеки содержат диагностическую информацию.

Пример

try {

    Globalize.currencyFormatter("BAD");

} catch (e) {

    console.log(e.code);
    console.log(e.message);

}

Результат:

E_UNSUPPORTED
Unsupported currency code

Поведение в SSR-приложениях

В серверном рендеринге строгий режим особенно опасен:

  • ошибка может прервать рендер страницы;
  • исключение способно завершить HTTP-запрос;
  • проблема локализации становится причиной 500 ошибки.

Поэтому в SSR часто применяется гибридный подход:

try {

    html = renderPage();

} catch (e) {

    html = renderFallbackPage();

}

Стратегия graceful degradation

Graceful degradation — постепенное ухудшение функциональности без полного отказа системы.

Для локализации это означает:

  • отображение ISO-дат;
  • вывод чисел без локализации;
  • использование английского языка;
  • показ ключей переводов вместо текста.

Пример

function safeDate(value) {

    try {

        return Globalize.dateFormatter({
            datetime: "short"
        })(value);

    } catch {

        return value.toISOString();

    }

}

Антипаттерны

Полное подавление ошибок

try {

    return formatter(value);

} catch {}

Проблема:

  • ошибка теряется;
  • диагностика невозможна;
  • дефект остаётся незамеченным.

Игнорирование отсутствующих переводов

return "";

Подобный подход создаёт:

  • пустые элементы интерфейса;
  • непредсказуемый UX;
  • сложность отладки.

Практическая стратегия использования

Наиболее распространённая архитектура выглядит следующим образом:

Этап Подход
Разработка строгий режим
Unit-тесты строгий режим
CI/CD строгий режим
Production UI нестрогий режим
Логирование строгое
Fallback обязательный

Рекомендации по проектированию

Для strict-подхода

Подход подходит:

  • финансовым системам;
  • банковским приложениям;
  • системам отчётности;
  • enterprise-проектам.

Главная цель — абсолютная корректность локализации.


Для non-strict-подхода

Подход используется:

  • в SPA;
  • пользовательских интерфейсах;
  • публичных сайтах;
  • high-load frontend-приложениях.

Главная цель — непрерывность работы интерфейса.


Инкапсуляция режимов

Хорошей практикой считается сокрытие библиотеки за abstraction layer.

Пример

class LocalizationAdapter {

    constructor(strict = false) {
        this.strict = strict;
    }

    format(value) {

        try {

            return Globalize.numberFormatter()(value);

        } catch (e) {

            if (this.strict) {
                throw e;
            }

            return value;
        }

    }

}

Такой подход позволяет:

  • переключать режимы;
  • централизовать обработку;
  • упрощать поддержку проекта.