Skip to content

Instantly share code, notes, and snippets.

@ole
Last active March 12, 2020 04:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ole/8f38c29746fefa21bb9e53aee21c36ef to your computer and use it in GitHub Desktop.
Save ole/8f38c29746fefa21bb9e53aee21c36ef to your computer and use it in GitHub Desktop.
Paste into a playground.
import Foundation
// Playing around with MeasurementFormatter.string(from: Unit)
let f = MeasurementFormatter()
f.locale = Locale(identifier: "de_DE")
f.unitOptions = .naturalScale
f.unitStyle = .long
f.string(from: UnitSpeed.milesPerHour)
f.string(from: UnitTemperature.celsius)
// NSLocale exposes measurement system (Locale doesn't)
Locale(identifier: "de_DE").usesMetricSystem
NSLocale(localeIdentifier: "de_DE").object(forKey: .measurementSystem)
NSLocale(localeIdentifier: "en_GB").object(forKey: .measurementSystem)
NSLocale(localeIdentifier: "en_US").object(forKey: .measurementSystem)
enum MeasurementSystem: String {
case metric = "Metric"
case us = "U.S."
case uk = "U.K."
}
extension Locale {
/// Type-safe variant of NSLocale.object(forKey: .measurementSystem)
/// Returns .metric by default if an unknown measurement system is returned.
var measurementSystem: MeasurementSystem {
let ns = (self as NSLocale).object(forKey: .measurementSystem)
guard let s = ns as? String, let m = MeasurementSystem(rawValue: s) else {
assertionFailure("Locale \(self) has unknown measurement system: \(ns as Any)")
return .metric
}
return m
}
}
extension UnitTemperature {
static func preferredUnits(for locale: Locale) -> [UnitTemperature] {
switch locale.measurementSystem {
case .metric, .uk:
return [.celsius]
case .us:
return [.fahrenheit]
}
}
}
UnitTemperature.preferredUnits(for: Locale(identifier: "de_DE")).first?.symbol
UnitTemperature.preferredUnits(for: Locale(identifier: "en_US")).first?.symbol
// I'd like to have a protocol-based version of the method, e.g.:
//
// protocol LocalizableUnit where Self: Unit {
// static func preferredUnits(for locale: Locale) -> [Self]
// }
//
// But that isn't compatible with Foundation's non-final unit classes. Pity.
extension UnitLength {
static func preferredUnits(for locale: Locale) -> [UnitLength] {
switch locale.measurementSystem {
case .metric:
return [.meters, .kilometers, .centimeters, .millimeters]
case .us, .uk:
return [.feet, .yards, .miles, .inches]
}
}
}
let locales = [
Locale(identifier: "de_DE"),
Locale(identifier: "dk_DK"),
Locale(identifier: "fr_FR"),
Locale(identifier: "en_US")
]
let unitsPerLocale = locales.map { locale -> [String] in
let units = UnitLength.preferredUnits(for: locale)
let formatter = MeasurementFormatter()
formatter.locale = locale
formatter.unitStyle = .long
return units.map(formatter.string(from:))
}
print(unitsPerLocale)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment