Files
hermes/mobile/ios-app/Core/Localization/LocalizationStore.swift
T

76 lines
2.2 KiB
Swift

import Combine
import Foundation
@MainActor
final class LocalizationStore: ObservableObject {
@Published private(set) var localeCode: String
private let bundle: Bundle
private static let supportedLocaleCodes = ["en", "sv"]
private static let fallbackLocaleCode = "en"
init(bundle: Bundle? = nil, localeCode: String = Locale.preferredLanguages.first.map { String($0.prefix(2)) } ?? "en") {
self.bundle = bundle ?? Self.defaultBundle
self.localeCode = Self.normalize(localeCode)
}
func setLocale(_ localeCode: String) {
self.localeCode = Self.normalize(localeCode)
}
func string(for key: String) -> String {
string(for: key, localeCode: localeCode)
}
func string(for key: String, localeCode: String) -> String {
guard let localizedBundle = localizedBundle(for: localeCode) else {
return fallbackString(for: key, localeCode: localeCode)
}
let value = localizedBundle.localizedString(forKey: key, value: nil, table: nil)
if value == key {
return fallbackString(for: key, localeCode: localeCode)
}
return value
}
func localeName(for targetLocaleCode: String, displayLocaleCode: String? = nil) -> String {
let key = Self.normalize(targetLocaleCode) == "sv" ? "locale_swedish" : "locale_english"
return string(for: key, localeCode: displayLocaleCode ?? localeCode)
}
private func fallbackString(for key: String, localeCode: String) -> String {
guard localeCode != Self.fallbackLocaleCode else {
return key
}
return string(for: key, localeCode: Self.fallbackLocaleCode)
}
private func localizedBundle(for localeCode: String) -> Bundle? {
guard let path = bundle.path(forResource: localeCode, ofType: "lproj") else {
return nil
}
return Bundle(path: path)
}
private static func normalize(_ localeCode: String) -> String {
guard supportedLocaleCodes.contains(localeCode) else {
return fallbackLocaleCode
}
return localeCode
}
private static var defaultBundle: Bundle {
#if SWIFT_PACKAGE
.module
#else
.main
#endif
}
}