Locale è una classe Foundation in iOS e macOS che incapsula le convenzioni linguistiche e culturali dell'utente: formato di date, numeri, valute e unità di misura. Secondo Apple Developer Documentation, 2024, Locale determina come DateFormatter visualizza un mese (gennaio o January), il separatore decimale in un numero (virgola o punto) e il simbolo di valuta (rublo, dollaro o euro). Ogni istanza di Locale è legata a un identificatore come ru_RU o en_US, dove la prima parte è il codice della lingua (ISO 639-1) e la seconda è il codice della regione (ISO 3166-1). A differenza di TimeZone, Locale non influisce sul valore assoluto del tempo, ma solo sulla sua rappresentazione in stringa.
Punti chiave
Locale è un tipo valore in Swift (NSLocale in Objective-C) che rappresenta un insieme di regole di formattazione specifiche per una particolare lingua e regione. A differenza di TimeZone, che determina l'offset assoluto del tempo, Locale determina come tempo, numeri e valuta appaiono nella rappresentazione in stringa. La stessa data 2024-07-21 verrà visualizzata come “21 luglio 2024” per ru_RU e “July 21, 2024” per en_US.
Ogni istanza di Locale è composta da due componenti: Lingua (determina i nomi dei mesi, i giorni della settimana, l'ordine delle parole) e Regione (determina il formato numerico, la valuta, il calendario). La combinazione di questi componenti è codificata in un identificatore secondo lo standard BCP 47: ru_RU (russo, Russia), en_US (inglese, USA), de_DE (tedesco, Germania).
Secondo Unicode CLDR (2024), il numero di impostazioni internazionali supportate in iOS supera le 700 combinazioni lingua-regione. Foundation utilizza i dati del CLDR (Common Locale Data Repository) — il repository più completo di dati di localizzazione gestito dal Unicode Consortium. Ciò garantisce una formattazione coerente su tutti i dispositivi Apple.
DateFormatter usa Locale per selezionare i nomi corretti di mesi e giorni, determinare l'ordine dei componenti della data (giorno/mese/anno o mese/giorno/anno) e i separatori. Senza specificare esplicitamente Locale, DateFormatter usa le impostazioni internazionali del dispositivo — questo è corretto per l'interfaccia utente ma pericoloso per i dati del server dove il formato deve essere fisso.
| Componente | ru_RU | en_US | de_DE |
|---|---|---|---|
| Data (medium) | 21 luglio 2024 | Jul 21, 2024 | 21.07.2024 |
| Numero (1000.5) | 1 000,5 | 1,000.5 | 1.000,5 |
| Valuta (100) | 100,00 ₽ | $100.00 | 100,00 € |
| Calendario | Gregoriano | Gregoriano | Gregoriano |
| Separatore di elenco | ; | , | ; |
NumberFormatter usa Locale per determinare il separatore decimale (virgola o punto), il separatore di raggruppamento (spazio, virgola, punto) e il simbolo di valuta. Ignorare Locale durante l'analisi dei numeri è una delle cause comuni di bug nelle applicazioni internazionali: il numero “1,5” significa “uno e mezzo” per ru_RU, ma per en_US il parser digitale lo leggerà come “cinque” dopo la virgola.
Importante: Calendar creato tramite Calendar.current eredita le impostazioni internazionali del dispositivo. Calendar(identifier: .gregorian) con impostazioni internazionali impostate esplicitamente è l'approccio raccomandato per una formattazione prevedibile. Quando si lavora con date ISO 8601, usa sempre Locale(identifier: “en_US_POSIX”) — impostazioni internazionali speciali per la formattazione tecnica che non vengono influenzate dalle impostazioni regionali.
L'identificatore Locale è composto da un codice lingua (ISO 639-1, due caratteri) e un codice regione (ISO 3166-1, due caratteri), separati da un trattino basso. Esempi: ru_RU, en_US, fr_FR, zh_Hans_CN (cinese, scrittura semplificata, Cina). Foundation supporta anche identificatori in formato BCP 47: ru-RU, en-US, utilizzati negli standard web.
Oltre agli identificatori completi, Locale può essere creato solo per lingua: Locale(identifier: “ru”) restituisce impostazioni internazionali con la lingua russa e la regione predefinita per quella lingua (di solito Russia). Analogamente per l'inglese: Locale(identifier: “en”) usa la regione USA. Questo approccio è utile per impostare la lingua di formattazione senza essere legati a una regione specifica.
Impostazioni internazionali speciali includono en_US_POSIX — impostazioni internazionali tecniche per la formattazione automatica di date e numeri, che garantiscono un formato stabile indipendentemente dalle impostazioni dell'utente. Queste impostazioni sono obbligatorie per analizzare le date dalle API del server, specialmente per il formato ISO 8601. Usano il calendario gregoriano, il formato 24 ore e il punto come separatore decimale.
import Foundation
// Identificatori di impostazioni internazionali disponibili
let available: [String] = Locale.availableIdentifiers
print("Totale impostazioni internazionali: \(available.count)")
// Filtra impostazioni internazionali russe
let russianLocales = available.filter { $0.hasPrefix("ru") }
print("Impostazioni internazionali russe: \(russianLocales)")
// Componenti delle impostazioni internazionali
let locale = Locale(identifier: "de_DE")
print("Lingua: \(locale.languageCode ?? "nil")")
print("Regione: \(locale.regionCode ?? "nil")")
print("Valuta: \(locale.currencyCode ?? "nil")")
print("Calendario: \(locale.calendar.identifier)")
Controllare le impostazioni internazionali disponibili tramite Locale.availableIdentifiers restituisce un array di tutti gli identificatori supportati dalla versione corrente di iOS. Per filtrare per regione, usa Locale.availableIdentifiers.filter con il controllo di regionCode. Questo è utile per creare un'interfaccia di selezione della regione senza un elenco codificato.
Locale.current è il modo principale per ottenere le impostazioni internazionali correnti del dispositivo impostate dall'utente nelle impostazioni iOS (Settings > General > Language & Region). Questa proprietà si aggiorna automaticamente quando si modifica la lingua o la regione nelle impostazioni senza riavviare l'applicazione. Tuttavia, potrebbe non corrispondere alle impostazioni preferite per la visualizzazione dei contenuti: un utente può impostare la lingua dell'interfaccia su inglese ma visualizzare le date in formato russo.
Per una determinazione più precisa delle preferenze dell'utente, usa Locale.preferredLanguages — un array di lingue ordinate per priorità dell'utente. Il primo elemento è la lingua principale dell'interfaccia. Questo elenco corrisponde alle impostazioni in Language & Region, inclusa la possibilità di trascinare le lingue in ordine di preferenza. Le applicazioni di comunicazione (messenger, client email) dovrebbero considerare questo ordine quando selezionano la lingua di visualizzazione dei contenuti.
import Foundation
// Impostazioni internazionali di sistema correnti
let current = Locale.current
print("Impostazioni correnti: \(current.identifier)")
print("Lingua: \(current.language?.disjointName ?? "nil")")
// Lingue preferite dall'utente
let preferred = Locale.preferredLanguages
print("Lingue preferite: \(preferred)")
// Ottieni regione dalle impostazioni correnti
if let region = current.regionCode {
let regionLocale = Locale(identifier: "en_\(region)")
let countryName = regionLocale.localizedString(
forRegionCode: region
)
print("Paese: \(countryName ?? region)")
}
// Controlla formato 24h
let uses24h = current.uses24hClock(
for: .dateAndTime
)
print("Usa 24h: \(uses24h)")
Localizzazione nell'interfaccia utente: per visualizzare i nomi dei mesi e dei giorni nella lingua dell'interfaccia, usa Calendar con impostazioni internazionali impostate. Calendar.current.symbols(for: .month) restituisce i nomi dei mesi nella lingua delle impostazioni internazionali correnti. Per visualizzare i nomi dei paesi nella lingua dell'utente, usa Locale.current.localizedString(forRegionCode:).
Formattazione della data con consapevolezza delle impostazioni internazionali è un compito chiave quando si visualizzano le date all'utente. DateFormatter con impostazioni internazionali impostate seleziona automaticamente il formato corretto di data e ora per la regione dell'utente. Per dateStyle e timeStyle con valori .short, .medium, .long, .full, il formattatore usa le regole delle impostazioni internazionali per comporre i componenti della data.
import Foundation
let date = Date()
// Formato con diverse impostazioni internazionali
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.locale = Locale(identifier: "ru_RU")
print("Russo: \(formatter.string(from: date))")
formatter.locale = Locale(identifier: "en_US")
print("Inglese: \(formatter.string(from: date))")
formatter.locale = Locale(identifier: "ja_JP")
print("Giapponese: \(formatter.string(from: date))")
// Formattazione valuta con impostazioni internazionali
let numFormatter = NumberFormatter()
numFormatter.numberStyle = .currency
numFormatter.locale = Locale(identifier: "de_DE")
print("Valuta tedesca: \(numFormatter.string(from: 1234.56) ?? "nil")")
numFormatter.locale = Locale(identifier: "en_US")
print("Valuta americana: \(numFormatter.string(from: 1234.56) ?? "nil")")
Analisi delle date dalle API del server dovrebbe sempre usare Locale(identifier: “en_US_POSIX”) per un formato fisso. I server inviano solitamente le date in formato ISO 8601 con nomi dei mesi in inglese e l'uso delle impostazioni internazionali correnti del dispositivo può causare errori di analisi se l'utente si trova in una regione non anglofona. en_US_POSIX garantisce che l'analisi non dipenda dalle impostazioni del dispositivo.
import Foundation
// Analisi corretta della data del 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 analizzata: \(parsed)")
}
// Nome valuta localizzato
let usLocale = Locale(identifier: "en_US")
let currencyName = usLocale.localizedString(
forCurrencyCode: "RUB"
)
print("Rublo russo nelle impostazioni americane: \(currencyName ?? "nil")")
Capacità aggiuntive: Locale fornisce descrizioni localizzate dei suoi componenti attraverso i metodi localizedString(forRegionCode:), localizedString(forLanguageCode:), localizedString(forCurrencyCode:) e localizedString(forCalendarIdentifier:). Questi metodi restituiscono i nomi nella lingua delle impostazioni internazionali su cui vengono chiamati. Ad esempio, Locale(identifier: “ru_RU”).localizedString(forCountryCode: “DE”) restituisce “Germania”.
Ignorare Locale durante l'analisi dei numeri è un errore critico nelle applicazioni internazionali. NumberFormatter senza impostazioni internazionali esplicite usa le impostazioni internazionali correnti del dispositivo. Se un utente in Russia inserisce “1,5”, NumberFormatter.number(from: “1,5”) restituisce correttamente 1.5. Ma se lo stesso codice viene eseguito su un dispositivo con impostazioni en_US, l'analisi restituisce nil perché per en_US il separatore decimale è un punto.
Mancanza di en_US_POSIX per le date del server porta a bug sottili. DateFormatter con dateFormat e locale = Locale.current può rompersi per utenti di regioni in cui il formato della data differisce da quello americano. Ad esempio, in Germania DateFormatter potrebbe aspettarsi “21.07.2024” mentre il server invia “07/21/2024”. en_US_POSIX garantisce un formato fisso per l'analisi automatica indipendentemente dalla regione dell'utente.
Confrontare stringhe di date invece di usare Date è un altro errore comune. Gli sviluppatori a volte confrontano rappresentazioni in stringa di date da diverse impostazioni internazionali, ottenendo risultati errati. Locale cambia solo la visualizzazione, non il valore assoluto della data. Confronta sempre oggetti Date, non le loro rappresentazioni in stringa. Per confrontare componenti di data, usa Calendar con impostazioni internazionali impostate esplicitamente.
Secondo WWDC 2023, circa il 30% dei problemi di internazionalizzazione nelle applicazioni sono correlati a una configurazione errata di Locale. Apple raccomanda di impostare sempre esplicitamente le impostazioni internazionali per DateFormatter e NumberFormatter quando si lavora con dati del server e di usare Locale.current solo per la visualizzazione nell'interfaccia utente. Questa semplice pratica elimina la maggior parte dei bug relativi alle impostazioni regionali.
Domande frequenti
Locale è una classe Foundation che rappresenta le regole culturali e linguistiche di formattazione: formato di data, numero, valuta e unità di misura. Viene utilizzata insieme a DateFormatter, NumberFormatter e Calendar per la visualizzazione localizzata dei dati.
Locale determina il formato di visualizzazione (lingua, convenzioni regionali), mentre TimeZone determina l'offset assoluto del tempo rispetto a UTC. Locale influisce sulla rappresentazione in stringa, TimeZone influisce sul valore numerico del tempo. Entrambi vengono utilizzati insieme per la formattazione completa della data.
en_US_POSIX è un'impostazione internazionale speciale per la formattazione tecnica che garantisce un formato stabile indipendentemente dalle impostazioni dell'utente. È obbligatoria per analizzare le date del server (ISO 8601) e lavorare con API dove il formato deve essere prevedibile.
Locale.availableIdentifiers restituisce un array di stringhe con gli identificatori di tutte le impostazioni internazionali supportate. Per filtrare per lingua, usa filter con hasPrefix; per ottenere la regione, usa Locale(identifier:).regionCode.
NumberFormatter usa Locale per determinare il separatore decimale (virgola o punto), il simbolo di valuta e il separatore di raggruppamento. Per un formato fisso, imposta le impostazioni internazionali su en_US_POSIX o imposta esplicitamente le proprietà del formattatore.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche