Nenhuma descrição

AppLocalization.swift 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. //
  2. // AppLocalization.swift
  3. // App for Indeed
  4. //
  5. // English-first localization using Localizable.strings (same pattern as the LinkedIn app).
  6. // Add more locales by creating `<locale>.lproj/Localizable.strings` and extending AppLanguage.
  7. //
  8. import Foundation
  9. enum AppLanguage: String, CaseIterable {
  10. case english = "English"
  11. case arabic = "Arabic"
  12. var localeIdentifier: String {
  13. switch self {
  14. case .english:
  15. return "en"
  16. case .arabic:
  17. return "ar"
  18. }
  19. }
  20. static var systemLanguage: AppLanguage {
  21. let preferred = Locale.preferredLanguages.first ?? "en"
  22. for language in AppLanguage.allCases where preferred.hasPrefix(language.localeIdentifier) {
  23. return language
  24. }
  25. return .english
  26. }
  27. var localizedDisplayName: String {
  28. switch self {
  29. case .english:
  30. return "English"
  31. case .arabic:
  32. return "العربية"
  33. }
  34. }
  35. }
  36. func appLocalized(_ key: String, language: AppLanguage) -> String {
  37. guard let path = Bundle.main.path(forResource: language.localeIdentifier, ofType: "lproj"),
  38. let bundle = Bundle(path: path) else {
  39. return key
  40. }
  41. return bundle.localizedString(forKey: key, value: key, table: nil)
  42. }
  43. func currentAppLanguage() -> AppLanguage {
  44. let code = UserDefaults.standard.string(forKey: "com.appforindeed.preferredLanguage") ?? "en"
  45. return AppLanguage.allCases.first(where: { $0.localeIdentifier == code }) ?? .english
  46. }
  47. /// Resolves copy for the user’s currently selected language.
  48. func L(_ key: String) -> String {
  49. appLocalized(key, language: currentAppLanguage())
  50. }
  51. /// Localized CV template title; `name` is always the English localization key.
  52. func localizedTemplateName(_ nameKey: String) -> String {
  53. L(nameKey)
  54. }
  55. @MainActor
  56. final class AppLanguageManager {
  57. static let shared = AppLanguageManager()
  58. static let didChangeNotification = Notification.Name("AppLanguageManager.didChange")
  59. private enum UserDefaultsKey {
  60. static let preferredLanguage = "com.appforindeed.preferredLanguage"
  61. }
  62. var current: AppLanguage {
  63. currentAppLanguage()
  64. }
  65. func applyStoredPreferenceOnLaunch() {
  66. if UserDefaults.standard.string(forKey: UserDefaultsKey.preferredLanguage) == nil {
  67. setLanguage(AppLanguage.systemLanguage, notify: false)
  68. }
  69. }
  70. func setLanguage(_ language: AppLanguage, notify: Bool = true) {
  71. let code = language.localeIdentifier
  72. UserDefaults.standard.set(code, forKey: UserDefaultsKey.preferredLanguage)
  73. UserDefaults.standard.set([code], forKey: "AppleLanguages")
  74. if notify {
  75. NotificationCenter.default.post(name: Self.didChangeNotification, object: self)
  76. }
  77. }
  78. func setLanguage(code: String, notify: Bool = true) {
  79. guard let language = AppLanguage.allCases.first(where: { $0.localeIdentifier == code }) else { return }
  80. setLanguage(language, notify: notify)
  81. }
  82. }