Длина и расстояние

Библиотека Globalize строит форматирование единиц измерения на основе данных CLDR (Unicode Common Locale Data Repository). Это означает, что работа с длиной и расстоянием не сводится к простому конкатенированию строк — используются локализованные правила, учитывающие язык, множественное число и региональные особенности записи величин.

Для корректного форматирования требуется подключение соответствующих данных CLDR:

import Globalize from "globalize";

// числовые данные
import likelySubtags from "cldr-core/supplemental/likelySubtags.json";
import numberingSystems from "cldr-core/supplemental/numberingSystems.json";
import timeData from "cldr-core/supplemental/timeData.json";

// локаль
import en from "cldr-dates-full/main/en/units.json";
import ru from "cldr-dates-full/main/ru/units.json";

// загрузка данных
Globalize.load(
  likelySubtags,
  numberingSystems,
  timeData,
  en,
  ru
);

После загрузки CLDR можно переключать локали:

Globalize.locale("en");

Форматирование единиц длины

Globalize использует единый механизм для всех измеримых величин. Длина входит в категорию length, которая включает метры, километры, мили, футы и дюймы.

Создание форматтера выполняется через unitFormatter:

const formatMeter = Globalize.unitFormatter("meter");
console.log(formatMeter(5));
// "5 meters"

Форматтер учитывает правила множественного числа. Например, в английском:

formatMeter(1);  // "1 meter"
formatMeter(2);  // "2 meters"

В других языках поведение отличается. Например, в русском:

Globalize.locale("ru");

const formatKm = Globalize.unitFormatter("kilometer");

formatKm(1); // "1 километр"
formatKm(2); // "2 километра"
formatKm(5); // "5 километров"

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

Расстояние в Globalize не является отдельной сущностью — оно реализуется через те же единицы длины. На практике используются километры и мили как основные единицы для отображения расстояний.

Globalize.locale("en");

const formatKm = Globalize.unitFormatter("kilometer");
const formatMile = Globalize.unitFormatter("mile");

formatKm(12);   // "12 kilometers"
formatMile(12); // "12 miles"

Для компактного отображения расстояний применяется параметр стиля.

Стили форматирования: long, short, narrow

Globalize поддерживает три основных стиля представления единиц:

  • long — полные слова
  • short — сокращения
  • narrow — максимально компактный вид
const longFormat = Globalize.unitFormatter("kilometer", { style: "long" });
const shortFormat = Globalize.unitFormatter("kilometer", { style: "short" });
const narrowFormat = Globalize.unitFormatter("kilometer", { style: "narrow" });

longFormat(10);   // "10 kilometers"
shortFormat(10);  // "10 km"
narrowFormat(10); // "10km"

Различия особенно заметны в интерфейсах с ограниченным пространством, где narrow позволяет минимизировать визуальный объем данных.

Комбинация чисел и единиц

Globalize разделяет ответственность: числовое форматирование выполняется отдельно от единиц измерения. Это позволяет учитывать локальные правила записи чисел (разделители, группировка разрядов, десятичные символы).

const numberFormatter = Globalize.numberFormatter();
const distanceFormatter = Globalize.unitFormatter("kilometer");

const value = 12345.67;

console.log(`${numberFormatter(value)} ${distanceFormatter.unit}`);
// некорректный подход

Корректное использование заключается в том, что unitFormatter сам управляет числом:

const formatDistance = Globalize.unitFormatter("kilometer");

formatDistance(12345.67);
// "12,345.67 kilometers" (en)

В русской локали:

Globalize.locale("ru");

const formatDistanceRu = Globalize.unitFormatter("kilometer");

formatDistanceRu(12345.67);
// "12 345,67 километра"

Метрическая и имперская система

CLDR содержит поддержку различных систем измерений. Globalize автоматически использует локализованные предпочтения.

Globalize.locale("en-US");

const formatMiles = Globalize.unitFormatter("mile");
const formatFeet = Globalize.unitFormatter("foot");

formatMiles(3); // "3 miles"
formatFeet(10); // "10 feet"

Для стран с метрической системой предпочтение отдается километрам и метрам:

Globalize.locale("ru");

const formatMeters = Globalize.unitFormatter("meter");
const formatKilometers = Globalize.unitFormatter("kilometer");

formatMeters(500);
formatKilometers(2);

Точность представления расстояний

При работе с длиной и расстоянием часто требуется управлять точностью отображения. Globalize позволяет комбинировать форматирование чисел с округлением перед передачей значения в unitFormatter.

const formatKm = Globalize.unitFormatter("kilometer");

const distance = 12.3456;

formatKm(Math.round(distance * 10) / 10);
// "12.3 kilometers"

В реальных сценариях округление обычно выполняется на уровне бизнес-логики, а форматтер отвечает только за локализацию.

Конвертация единиц перед форматированием

Globalize не выполняет автоматическую конвертацию единиц. Все преобразования выполняются вручную до передачи значения в форматтер.

Пример перевода метров в километры:

const formatKm = Globalize.unitFormatter("kilometer");

function metersToKilometers(m) {
  return m / 1000;
}

const distanceMeters = 2500;

formatKm(metersToKilometers(distanceMeters));
// "2.5 kilometers"

Аналогично для миль и футов:

const formatMiles = Globalize.unitFormatter("mile");

function kmToMiles(km) {
  return km * 0.621371;
}

formatMiles(kmToMiles(10));
// "6.21371 miles"

Локализация дробных значений

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

Английская локаль:

Globalize.locale("en");

Globalize.unitFormatter("kilometer")(3.5);
// "3.5 kilometers"

Русская локаль:

Globalize.locale("ru");

Globalize.unitFormatter("kilometer")(3.5);
// "3,5 километра"

Разделитель десятичной части берётся из CLDR и автоматически применяется ко всем числам внутри единиц измерения.

Использование фабрики форматтеров

При массовом форматировании расстояний выгодно создавать форматтер один раз и переиспользовать его.

const formatKm = Globalize.unitFormatter("kilometer");

const distances = [1, 2, 5, 10, 21];

const formatted = distances.map(formatKm);

Такой подход снижает накладные расходы на создание объектов форматирования и упрощает обработку больших массивов данных.

Множественные единицы и контекст

CLDR содержит контекстные формы единиц измерения, которые могут различаться в зависимости от числа. Globalize скрывает эти различия, автоматически выбирая нужную форму:

Globalize.locale("en");

const formatFoot = Globalize.unitFormatter("foot");

formatFoot(1); // "1 foot"
formatFoot(2); // "2 feet"

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

Практическое применение в интерфейсах

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

Типичные сценарии:

  • отображение длины маршрута
  • расстояние до точки интереса
  • длина объектов в технических спецификациях
  • масштабирование картографических данных

Во всех случаях Globalize обеспечивает единообразное отображение без ручного управления языковыми правилами.