Locale — este o clasă Foundation în iOS și macOS care încapsulează convențiile lingvistice și culturale ale utilizatorului: formatul datelor, numerelor, valutelor și unităților de măsură. Conform Apple Developer Documentation, 2024, Locale determină cum DateFormatter afișează luna (ianuarie sau January), separatorul zecimal al unui număr (virgulă sau punct) și simbolul valutei (leu, dolar sau euro). Fiecare instanță Locale este legată de un identificator de tipul ru_RU sau en_US, unde prima parte este codul limbii (ISO 639-1), iar a doua — codul regiunii (ISO 3166-1). Spre deosebire de TimeZone, Locale nu afectează valoarea absolută a timpului, ci doar reprezentarea sa sub formă de șir.
Principalele puncte
Locale — este un value-type în Swift (NSLocale în Objective-C) care reprezintă un set de reguli de formatare caracteristice unei anumite limbi și regiuni. Spre deosebire de TimeZone, care determină deplasarea absolută a timpului, Locale determină cum arată timpul, numerele și valuta în reprezentarea sub formă de șir. Aceeași dată 2024-07-21 va fi afișată ca „21 iulie 2024„ pentru ru_RU și „July 21, 2024„ pentru en_US.
Fiecare instanță Locale este formată din două componente: Language (limbă — determină numele lunilor, zilelor săptămânii, ordinea cuvintelor) și Region (regiune — determină formatul numerelor, valuta, calendarul). Combinația acestor componente este codificată în identificator conform standardului BCP 47: ru_RU (limba rusă, Rusia), en_US (engleză, SUA), de_DE (germană, Germania).
Conform Unicode CLDR (2024), lista localizărilor suportate în iOS depășește 700 de combinații limbă-regiune. Foundation utilizează datele din CLDR (Common Locale Data Repository) — cel mai complet depozit de date de localizare, susținut de Unicode Consortium. Aceasta garantează uniformitatea formatării pe toate dispozitivele Apple.
DateFormatter folosește Locale pentru selectarea numelor corecte ale lunilor și zilelor săptămânii, determinarea ordinii componentelor datei (zi/lună/an sau lună/zi/an) și a separatorilor. Fără specificarea explicită a Locale, DateFormatter utilizează localizarea dispozitivului — acest lucru este corect pentru UI, dar periculos pentru datele de pe server unde formatul trebuie să fie fix.
| Componentă | ru_RU | en_US | de_DE |
|---|---|---|---|
| Data (medium) | 21 iulie 2024 | Jul 21, 2024 | 21.07.2024 |
| Număr (1000.5) | 1 000,5 | 1,000.5 | 1.000,5 |
| Valută (100) | 100,00 ₽ | $100.00 | 100,00 € |
| Calendar | Gregorian | Gregorian | Gregorian |
| Separator listă | ; | , | ; |
NumberFormatter folosește Locale pentru determinarea separatorului zecimal (virgulă sau punct), separatorului de grupare (spațiu, virgulă, punct) și simbolului valutei. Ignorarea Locale la parsarea numerelor este una dintre cauzele frecvente ale erorilor în aplicațiile internaționale: numărul „1,5„ înseamnă „unu și jumătate„ pentru ru_RU, dar pentru en_US analizorul numeric îl va citi ca „cinci„ după virgulă.
Important: Calendar creat prin Calendar.current moștenește localizarea dispozitivului. Calendar(identifier: .gregorian) cu locale specificată explicit — metoda recomandată pentru formatarea previzibilă. La lucrul cu datele ISO 8601 utilizați întotdeauna Locale(identifier: "en_US_POSIX") — o localizare specială pentru formatarea tehnică care nu este supusă influenței setărilor regionale.
Identificatorul Locale este format din codul limbii (ISO 639-1, două caractere) și codul regiunii (ISO 3166-1, două caractere), separate prin underscore. Exemple: ru_RU, en_US, fr_FR, zh_Hans_CN (chineză, scriere simplificată, China). Foundation suportă și identificatori în format BCP 47: ru-RU, en-US, utilizați în standardele web.
Pe lângă identificatorii complecți, Locale poate fi creat doar pe baza limbii: Locale(identifier: "ru") returnează o localizare cu limba rusă și regiunea implicită pentru această limbă (de obicei Rusia). Similar pentru engleză: Locale(identifier: "en") utilizează regiunea SUA. Această abordare este utilă pentru setarea limbii de formatare fără legare la o regiune specifică.
Localizări speciale includ en_US_POSIX — o localizare tehnică pentru formatarea mașină a datelor și numerelor, care garantează un format stabil indiferent de setările utilizatorului. Această localizare este obligatorie pentru parsarea datelor din API-urile server, în special pentru formatul ISO 8601. Utilizează calendarul gregorian, formatul de 24 de ore și punctul ca separator zecimal.
import Foundation
// Identificatorii de localizare disponibili
let available: [String] = Locale.availableIdentifiers
print("Total localizări: \(available.count)")
// Filtrează localizările rusești
let russianLocales = available.filter { $0.hasPrefix("ru") }
print("Localizări rusești: \(russianLocales)")
// Componentele localizării
let locale = Locale(identifier: "de_DE")
print("Limba: \(locale.languageCode ?? "nil")")
print("Regiunea: \(locale.regionCode ?? "nil")")
print("Valuta: \(locale.currencyCode ?? "nil")")
print("Calendar: \(locale.calendar.identifier)")
Verificarea localizărilor disponibile prin Locale.availableIdentifiers returnează un tablou cu toți identificatorii suportați de versiunea curentă a iOS. Pentru filtrarea după regiune utilizați Locale.availableIdentifiers.filter cu verificarea regionCode. Acest lucru este util pentru construirea UI de selectare a regiunii fără o listă codificată fix.
Locale.current — modul principal de obținere a localizării curente a dispozitivului, stabilită de utilizator în setările iOS (Settings > General > Language & Region). Această proprietate se actualizează automat la modificarea limbii sau regiunii în setări fără repornirea aplicației. Cu toate acestea, este posibil să nu coincidă cu localizarea preferată pentru afișarea conținutului: utilizatorul poate seta limba interfeței la engleză, dar să vizualizeze datele în format rusesc.
Pentru o determinare mai precisă a preferințelor utilizatorului utilizați Locale.preferredLanguages — un tablou de limbi ordonate după prioritățile utilizatorului. Primul element este limba principală a interfeței. Această listă corespunde setărilor din Language & Region, inclusiv tragerea și plasarea limbilor în ordinea preferințelor. Aplicațiile de comunicare (mesagerii, clienții de email) trebuie să țină cont de această ordine la selectarea limbii de afișare a conținutului.
import Foundation
// Localizarea curentă de sistem
let current = Locale.current
print("Localizare curentă: \(current.identifier)")
print("Limba: \(current.language?.disjointName ?? "nil")")
// Limbile preferate ale utilizatorului
let preferred = Locale.preferredLanguages
print("Limbile preferate: \(preferred)")
// Obține regiunea din localizarea curentă
if let region = current.regionCode {
let regionLocale = Locale(identifier: "en_\(region)")
let countryName = regionLocale.localizedString(
forRegionCode: region
)
print("Țara: \(countryName ?? region)")
}
// Verifică formatul 24h
let uses24h = current.uses24hClock(
for: .dateAndTime
)
print("Folosește 24h: \(uses24h)")
Localizarea în UI: pentru afișarea numelor lunilor și zilelor săptămânii în limba interfeței utilizați Calendar cu locale setată. Calendar.current.symbols(for: .month) returnează numele lunilor în limba localizării curente. Pentru afișarea numelor țărilor în limba utilizatorului utilizați Locale.current.localizedString(forRegionCode:).
Formatarea datei cu luarea în considerare a localizării — o sarcină cheie la afișarea datelor utilizatorului. DateFormatter cu locale setată selectează automat formatul corect al datei și orei pentru regiunea utilizatorului. Pentru dateStyle și timeStyle cu valorile .short, .medium, .long, .full, formatterul utilizează regulile localizării pentru compunerea componentelor datei.
import Foundation
let date = Date()
// Formatarea cu diferite localizări
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.locale = Locale(identifier: "ru_RU")
print("Rusă: \(formatter.string(from: date))")
formatter.locale = Locale(identifier: "en_US")
print("Engleză: \(formatter.string(from: date))")
formatter.locale = Locale(identifier: "ja_JP")
print("Japoneză: \(formatter.string(from: date))")
// Formatarea valutei cu localizare
let numFormatter = NumberFormatter()
numFormatter.numberStyle = .currency
numFormatter.locale = Locale(identifier: "de_DE")
print("Valuta germană: \(numFormatter.string(from: 1234.56) ?? "nil")")
numFormatter.locale = Locale(identifier: "en_US")
print("Valuta americană: \(numFormatter.string(from: 1234.56) ?? "nil")")
Parsarea datelor din API-urile server trebuie să utilizeze întotdeauna Locale(identifier: "en_US_POSIX") pentru un format fix. Servere trimit de obicei datele în format ISO 8601 cu nume de luni în engleză, iar utilizarea localizării curente a dispozitivului poate duce la erori de parsare dacă utilizatorul se află într-o regiune cu o limbă non-engleză. en_US_POSIX garantează că parsarea nu depinde de setările dispozitivului.
import Foundation
// Parsarea corectă a datelor de pe server
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("Data parsată: \(parsed)")
}
// Denumirea localizată a valutei
let usLocale = Locale(identifier: "en_US")
let currencyName = usLocale.localizedString(
forCurrencyCode: "RUB"
)
print("Rublă rusească în localizarea americană: \(currencyName ?? "nil")")
Capabilități suplimentare: Locale oferă descrieri localizate ale componentelor sale prin metodele localizedString(forRegionCode:), localizedString(forLanguageCode:), localizedString(forCurrencyCode:) și localizedString(forCalendarIdentifier:). Aceste metode returnează numele în limba localizării în care au fost apelate. De exemplu, Locale(identifier: "ru_RU").localizedString(forCountryCode: "DE") va returna „Germania„.
Ignorarea Locale la parsarea numerelor — o eroare critică în aplicațiile internaționale. NumberFormatter fără localizare explicită utilizează localizarea curentă a dispozitivului. Dacă un utilizator din Rusia introduce „1,5„, NumberFormatter.number(from: "1,5") returnează corect 1.5. Dar dacă același cod este executat pe un dispozitiv cu localizarea en_US, parsarea returnează nil, deoarece pentru en_US separatorul zecimal este punctul.
Lipsa en_US_POSIX pentru datele de pe server duce la erori greu de depistat. DateFormatter cu dateFormat și locale = Locale.current se poate strica la utilizatorii din regiuni unde formatul datei diferă de cel american. De exemplu, în Germania DateFormatter poate aștepta „21.07.2024„, iar serverul trimite „07/21/2024„. en_US_POSIX garantează un format fix pentru parsarea mașină indiferent de regiunea utilizatorului.
Compararea șirurilor de date în loc de utilizarea Date — o altă eroare frecventă. Dezvoltatorii compară uneori reprezentările sub formă de șir ale datelor din diferite localizări, obținând rezultate incorecte. Locale modifică doar afișarea, dar nu și valoarea absolută a datei. Comparați întotdeauna obiectele Date, nu reprezentările lor sub formă de șir. Pentru compararea componentelor datei utilizați Calendar cu locale specificată explicit.
Conform WWDC 2023, aproximativ 30% din problemele de internaționalizare în aplicații sunt legate de configurarea incorectă a Locale. Apple recomandă să specificați întotdeauna explicit locale pentru DateFormatter și NumberFormatter la lucrul cu datele de pe server și să utilizați Locale.current doar la afișarea în UI. Această practică simplă elimină majoritatea erorilor legate de setările regionale.
Întrebări frecvente
Locale — clasa Foundation care reprezintă regulile culturale și lingvistice de formatare: formatul datei, numerelor, valutei și unităților de măsură. Utilizată împreună cu DateFormatter, NumberFormatter și Calendar pentru afișarea localizată a datelor.
Locale determină formatul de afișare (limbă, convenții regionale), iar TimeZone — deplasarea absolută a timpului față de UTC. Locale influențează reprezentarea sub formă de șir, TimeZone — valoarea numerică a timpului. Ambele sunt utilizate împreună pentru formatarea completă a datei.
en_US_POSIX — o localizare specială pentru formatarea tehnică, care garantează un format stabil indiferent de setările utilizatorului. Obligatorie pentru parsarea datelor de pe server (ISO 8601) și lucrul cu API-uri unde formatul trebuie să fie previzibil.
Locale.availableIdentifiers returnează un tablou de șiruri cu identificatorii tuturor localizărilor suportate. Pentru filtrarea după limbă utilizați filter cu hasPrefix, pentru obținerea regiunii — Locale(identifier:).regionCode.
NumberFormatter utilizează Locale pentru determinarea separatorului zecimal (virgulă sau punct), simbolului valutei și separatorului de grupare. Pentru un format fix setați locale la en_US_POSIX sau specificați explicit proprietățile formatterului.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și