Locale — що це таке, клас Foundation та локалізація

Автор: IT Sectr Опубліковано: 2026-07-12 Час читання: 9 хв

Locale — це клас Foundation в iOS і macOS, що інкапсулює лінгвістичні та культурні угоди користувача: формат дат, чисел, валют і одиниць вимірювання. За даними Apple Developer Documentation, 2024, Locale визначає, як DateFormatter відображає місяць (січень або January), роздільник десятих у числі (кома або крапка) та символ валюти (рубль, долар або євро). Кожен екземпляр Locale прив'язаний до ідентифікатора виду ru_RU або en_US, де перша частина — код мови (ISO 639-1), друга — код регіону (ISO 3166-1). На відміну від TimeZone, Locale не впливає на абсолютне значення часу, тільки на його рядкове представлення.

Головне

  • Locale — клас Foundation для культурних і лінгвістичних налаштувань форматування в iOS і macOS
  • Ідентифікатор ru_RU — поєднання коду мови (ISO 639-1) та коду регіону (ISO 3166-1)
  • DateFormatter і NumberFormatter автоматично використовують Locale для локалізації виводу
  • Locale.current — системна локаль користувача, може бути перевизначена для окремих операцій
  • Фікс vs автооновлення — Locale(identifier:) створює фіксовану локаль, Locale.current відстежує зміни в налаштуваннях

Що таке Locale в Foundation?

Locale — це value-тип в Swift (NSLocale в Objective-C), що представляє набір правил форматування, характерних для конкретної мови та регіону. На відміну від TimeZone, який визначає абсолютне зміщення часу, Locale визначає, як час, числа та валюта виглядають у рядковому представленні. Одна й та сама дата 2024-07-21 буде відображена як «21 липня 2024 р.» для ru_RU і «July 21, 2024» для en_US.

Кожен екземпляр Locale складається з двох компонентів: Language (мова — визначає назви місяців, днів тижня, порядок слів) і Region (регіон — визначає формат чисел, валюту, календар). Комбінація цих компонентів кодується в ідентифікаторі за стандартом BCP 47: ru_RU (російська мова, Росія), en_US (англійська, США), de_DE (німецька, Німеччина).

За даними Unicode CLDR (2024), список підтримуваних локалей в iOS перевищує 700 комбінацій мова-регіон. Foundation використовує дані з CLDR (Common Locale Data Repository) — найповнішого репозиторію локалізаційних даних, що підтримується Unicode Consortium. Це гарантує єдність форматування на всіх пристроях Apple.

Як Locale впливає на форматування дат і чисел?

DateFormatter використовує Locale для вибору правильних назв місяців і днів тижня, визначення порядку компонентів дати (день/місяць/рік або місяць/день/рік) та роздільників. Без явного зазначення Locale DateFormatter використовує локаль пристрою — це коректно для UI, але небезпечно для серверних даних, де формат має бути фіксованим.

Компонентru_RUen_USde_DE
Дата (medium)21 липня 2024 р.Jul 21, 202421.07.2024
Число (1000.5)1 000,51,000.51.000,5
Валюта (100)100,00 ₽$100.00100,00 €
КалендарГригоріанськийГригоріанськийГригоріанський
Роздільник списку;,;

NumberFormatter використовує Locale для визначення десяткового роздільника (кома або крапка), групуючого роздільника (пробіл, кома, крапка) та символу валюти. Ігнорування Locale при парсингу чисел — одна з частих причин багів в інтернаціональних застосунках: число «1,5» означає «один з половиною» для ru_RU, але для en_US його цифровий аналізатор прочитає як «п'ять» після коми.

Важливо: Calendar, створений через Calendar.current, успадковує локаль пристрою. Calendar(identifier: .gregorian) з явно заданою locale — рекомендований спосіб для передбачуваного форматування. При роботі з ISO 8601 датами завжди використовуйте Locale(identifier: «en_US_POSIX») — спеціальну локаль для технічного форматування, що не піддається впливу регіональних налаштувань.

Locale-ідентифікатори: основні формати

Ідентифікатор Locale складається з коду мови (ISO 639-1, два символи) та коду регіону (ISO 3166-1, два символи), розділених підкресленням. Приклади: ru_RU, en_US, fr_FR, zh_Hans_CN (китайська, спрощене письмо, Китай). Foundation також підтримує ідентифікатори у форматі BCP 47: ru-RU, en-US, що використовуються у веб-стандартах.

Крім повних ідентифікаторів, Locale можна створити тільки за мовою: Locale(identifier: «ru») поверне локаль з російською мовою та регіоном за замовчуванням для цієї мови (зазвичай Росія). Аналогічно для англійської: Locale(identifier: «en») використовує регіон США. Такий підхід корисний для встановлення мови форматування без прив'язки до конкретного регіону.

Спеціальні локалі включають en_US_POSIX — технічну локаль для машинного форматування дат і чисел, що гарантує стабільний формат незалежно від користувацьких налаштувань. Ця локаль обов'язкова для парсингу дат із серверних API, особливо для формату ISO 8601. Вона використовує григоріанський календар, 24-годинний формат часу та крапку як десятковий роздільник.

swift
import Foundation

// Доступні ідентифікатори локалей
let available: [String] = Locale.availableIdentifiers
print("Всього локалей: \(available.count)")

// Фільтрувати російські локалі
let russianLocales = available.filter { $0.hasPrefix("ru") }
print("Російських локалей: \(russianLocales)")

// Компоненти локалі
let locale = Locale(identifier: "de_DE")
print("Мова: \(locale.languageCode ?? "nil")")
print("Регіон: \(locale.regionCode ?? "nil")")
print("Валюта: \(locale.currencyCode ?? "nil")")
print("Календар: \(locale.calendar.identifier)")

Перевірка доступних локалей через Locale.availableIdentifiers повертає масив усіх ідентифікаторів, підтримуваних поточною версією iOS. Для фільтрації за регіоном використовуйте Locale.availableIdentifiers.filter з перевіркою regionCode. Це корисно для побудови UI вибору регіону без жорстко закодованого списку.

Визначення поточної локалі користувача в Swift

Locale.current — основний спосіб отримання поточної локалі пристрою, встановленої користувачем у налаштуваннях iOS (Settings > General > Language & Region). Ця властивість автоматично оновлюється при зміні мови або регіону в налаштуваннях без перезапуску застосунку. Однак вона може не збігатися з локалью, бажаною для відображення контенту: користувач може встановити мову інтерфейсу англійською, але переглядати дати в українському форматі.

Для більш точного визначення вподобань користувача використовуйте Locale.preferredLanguages — масив мов, упорядкованих за пріоритетом користувача. Перший елемент — основна мова інтерфейсу. Цей список відповідає налаштуванням у Language & Region, включаючи перетягування мов у порядку вподобання. Застосунки для спілкування (месенджери, email-клієнти) повинні враховувати цей порядок при виборі мови відображення контенту.

swift
import Foundation

// Поточна системна локаль
let current = Locale.current
print("Поточна локаль: \(current.identifier)")
print("Мова: \(current.language?.disjointName ?? "nil")")

// Бажані мови користувача
let preferred = Locale.preferredLanguages
print("Бажані мови: \(preferred)")

// Отримати регіон з поточної локалі
if let region = current.regionCode {
    let regionLocale = Locale(identifier: "en_\(region)")
    let countryName = regionLocale.localizedString(
        forRegionCode: region
    )
    print("Країна: \(countryName ?? region)")
}

// Перевірити 24-годинний формат
let uses24h = current.uses24hClock(
    for: .dateAndTime
)
print("Використовує 24 год: \(uses24h)")

Локалізація в UI: для відображення назв місяців і днів тижня мовою інтерфейсу використовуйте Calendar з встановленою locale. Calendar.current.symbols(for: .month) поверне назви місяців мовою поточної локалі. Для відображення назв країн мовою користувача використовуйте Locale.current.localizedString(forRegionCode:).

Locale в Swift: приклади використання

Форматування дати з урахуванням локалі — ключове завдання при відображенні дат користувачеві. DateFormatter з встановленим locale автоматично вибирає правильний формат дати та часу для регіону користувача. Для dateStyle та timeStyle зі значеннями .short, .medium, .long, .full форматер використовує правила локалі для компонування компонентів дати.

swift
import Foundation

let date = Date()

// Форматування з різними локалями
let formatter = DateFormatter()
formatter.dateStyle = .medium

formatter.locale = Locale(identifier: "ru_RU")
print("Російська: \(formatter.string(from: date))")

formatter.locale = Locale(identifier: "en_US")
print("Англійська: \(formatter.string(from: date))")

formatter.locale = Locale(identifier: "ja_JP")
print("Японська: \(formatter.string(from: date))")

// Форматування валюти з локаллю
let numFormatter = NumberFormatter()
numFormatter.numberStyle = .currency

numFormatter.locale = Locale(identifier: "de_DE")
print("Німецька валюта: \(numFormatter.string(from: 1234.56) ?? "nil")")

numFormatter.locale = Locale(identifier: "en_US")
print("Американська валюта: \(numFormatter.string(from: 1234.56) ?? "nil")")

Парсинг дат із серверних API завжди повинен використовувати Locale(identifier: «en_US_POSIX») для фіксованого формату. Сервери зазвичай надсилають дати у форматі ISO 8601 з англійськими назвами місяців, і використання поточної локалі пристрою може призвести до помилки парсингу, якщо користувач знаходиться в регіоні з неанглійською мовою. en_US_POSIX гарантує, що парсинг не залежить від налаштувань пристрою.

swift
import Foundation

// Правильний парсинг серверної дати
let isoFormatter = DateFormatter()
isoFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
isoFormatter.locale = Locale(identifier: "en_US_POSIX")
isoFormatter.timeZone = TimeZone(secondsFromGMT: 0)

let serverDate = "2024-07-21T14:30:00+0000"
if let parsed = isoFormatter.date(from: serverDate) {
    print("Розпарсена дата: \(parsed)")
}

// Локалізована назва валюти
let usLocale = Locale(identifier: "en_US")
let currencyName = usLocale.localizedString(
    forCurrencyCode: "RUB"
)
print("Російський рубль в американській локалі: \(currencyName ?? "nil")")

Додаткові можливості: Locale надає локалізований опис своїх компонентів через методи localizedString(forRegionCode:), localizedString(forLanguageCode:), localizedString(forCurrencyCode:) та localizedString(forCalendarIdentifier:). Ці методи повертають назви мовою тієї локалі, у якої вони викликані. Наприклад, Locale(identifier: «ru_RU»).localizedString(forCountryCode: «DE») поверне «Німеччина».

Типові помилки при роботі з Locale

Ігнорування Locale при парсингу чисел — критична помилка в інтернаціональних застосунках. NumberFormatter без явної локалі використовує поточну локаль пристрою. Якщо користувач в Україні вводить «1,5», NumberFormatter.number(from: «1,5») коректно поверне 1.5. Але якщо цей же код виконується на пристрої з en_US локалью, парсинг поверне nil, тому що для en_US десятковий роздільник — крапка.

Відсутність en_US_POSIX для серверних дат веде до невловимих багів. DateFormatter з dateFormat та locale = Locale.current може зламатися у користувачів із регіонів, де формат дати відрізняється від американського. Наприклад, у Німеччині DateFormatter може очікувати «21.07.2024», а сервер надсилає «07/21/2024». en_US_POSIX гарантує фіксований формат для машинного парсингу незалежно від регіону користувача.

Порівняння рядків дат замість використання Date — ще одна поширена помилка. Розробники іноді порівнюють рядкові представлення дат із різних локалей, отримуючи невірні результати. Locale змінює тільки відображення, але не абсолютне значення дати. Завжди порівнюйте об'єкти Date, а не їх рядкові представлення. Для порівняння компонентів дати використовуйте Calendar з явно заданою locale.

За даними WWDC 2023, близько 30% проблем з інтернаціоналізацією в застосунках пов'язані з неправильним налаштуванням Locale. Apple рекомендує завжди явно задавати locale для DateFormatter та NumberFormatter при роботі з серверними даними та використовувати Locale.current тільки при відображенні в UI. Ця проста практика усуває більшість багів, пов'язаних із регіональними налаштуваннями.

Часті запитання

Що таке Locale в Foundation?

Locale — клас Foundation, що представляє культурні та лінгвістичні правила форматування: формат дати, чисел, валюти та одиниць вимірювання. Використовується спільно з DateFormatter, NumberFormatter та Calendar для локалізованого відображення даних.

У чому різниця між Locale та TimeZone?

Locale визначає формат відображення (мова, регіональні угоди), а TimeZone — абсолютне зміщення часу відносно UTC. Locale впливає на рядкове представлення, TimeZone — на числове значення часу. Обидва використовуються разом для повного форматування дати.

Що таке en_US_POSIX і для чого він потрібен?

en_US_POSIX — спеціальна локаль для технічного форматування, що гарантує стабільний формат незалежно від користувацьких налаштувань. Обов'язкова для парсингу серверних дат (ISO 8601) та роботи з API, де формат має бути передбачуваним.

Як отримати список усіх доступних локалей?

Locale.availableIdentifiers повертає масив рядків з ідентифікаторами всіх підтримуваних локалей. Для фільтрації за мовою використовуйте filter з hasPrefix, для отримання регіону — Locale(identifier:).regionCode.

Як Locale впливає на NumberFormatter?

NumberFormatter використовує Locale для визначення десяткового роздільника (кома або крапка), символу валюти та групуючого роздільника. Для фіксованого формату встановлюйте locale в en_US_POSIX або явно задавайте властивості formatter.

Підсумки

  • Locale — фундаментальний клас для локалізації форматування дат, чисел та валют в iOS і macOS
  • Ідентифікатор ru_RU кодує мову (ISO 639-1) та регіон (ISO 3166-1) для точного налаштування форматування
  • DateFormatter та NumberFormatter автоматично використовують Locale.current для локалізованого виводу
  • en_US_POSIX — обов'язкова локаль для парсингу серверних дат та фіксованого машинного форматування
  • Locale.current відстежує зміни в налаштуваннях, Locale(identifier:) створює фіксовану локаль
  • Парсинг чисел вимагає явної установки locale — десятковий роздільник залежить від регіону користувача
  • Calendar.current успадковує локаль пристрою; для передбачуваних розрахунків задавайте locale явно

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також