summaryrefslogtreecommitdiffhomepage
path: root/ios/Shared/ApplicationLanguage.swift
blob: c460f921232fc92be0b3c7e3972fd7e0e8da1dae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//
//  ApplicationLanguage.swift
//  MullvadVPN
//
//  Created by Mojgan on 2025-07-16.
//  Copyright © 2025 Mullvad VPN AB. All rights reserved.
//

import Foundation

/**
 * TODO:
 * Edit the "Localization Cleanup (Release Build)" build script phase after
 * multi-language support is completed and released.
 *
 * Note:
 * - Localization is not available for the Staging configuration, which is used by `UITest`.
 * - When the functionality is finished, the script should:
 *    • Remove bilingual content only for Staging.
 *    • Eliminate the Debug configuration check.
 */
enum ApplicationLanguage: String, CaseIterable, Identifiable {
    case english = "en"
    case danish = "da"
    case german = "de"
    case spanish = "es"
    case finnish = "fi"
    case french = "fr"
    case italian = "it"
    case japanese = "ja"
    case korean = "ko"
    case burmese = "my"
    case norwegianBokmal = "nb"
    case dutch = "nl"
    case polish = "pl"
    case portuguese = "pt"
    case russian = "ru"
    case swedish = "sv"
    case thai = "th"
    case turkish = "tr"
    case chineseSimplified = "zh-Hans"  // Maps to zh-CN
    case chineseTraditional = "zh-Hant"  // Maps to zh-TW

    var id: String { rawValue }

    var displayName: String {
        switch self {
        case .english: "English"
        case .danish: "Dansk"
        case .german: "Deutsch"
        case .spanish: "Español"
        case .finnish: "Suomi"
        case .french: "Français"
        case .italian: "Italiano"
        case .japanese: "日本語"
        case .korean: "한국어"
        case .burmese: "မြန်မာ"
        case .norwegianBokmal: "Norsk Bokmål"
        case .dutch: "Nederlands"
        case .polish: "Polski"
        case .portuguese: "Português"
        case .russian: "Русский"
        case .swedish: "Svenska"
        case .thai: "ไทย"
        case .turkish: "Türkçe"
        case .chineseSimplified: "简体中文"
        case .chineseTraditional: "繁體中文"
        }
    }

    var countryCodeForFlag: String {
        switch self {
        case .english: "us"  // English → US flag (or "gb" for UK)
        case .danish: "dk"
        case .german: "de"
        case .spanish: "es"
        case .finnish: "fi"
        case .french: "fr"
        case .italian: "it"
        case .japanese: "jp"
        case .korean: "kr"
        case .burmese: "mm"
        case .norwegianBokmal: "no"
        case .dutch: "nl"
        case .polish: "pl"
        case .portuguese: "pt"
        case .russian: "ru"
        case .swedish: "se"
        case .thai: "th"
        case .turkish: "tr"
        case .chineseSimplified: "cn"
        case .chineseTraditional: "tw"
        }
    }

    var flagEmoji: String {
        let base: UInt32 = 127397
        var flagString = ""
        for scalar in countryCodeForFlag.uppercased().unicodeScalars {
            guard let scalarValue = UnicodeScalar(base + scalar.value) else { return "" }
            flagString.unicodeScalars.append(scalarValue)
        }
        return flagString
    }

    static var currentLanguage: ApplicationLanguage {
        let defaultCode = ApplicationLanguage.english.rawValue
        let fullCode = Locale.preferredLanguages.first ?? defaultCode

        if #available(iOS 16, *) {
            let locale = Locale(identifier: fullCode)
            if let script = locale.language.script?.identifier {
                switch script {
                case "Hans":
                    return .chineseSimplified
                case "Hant":
                    return .chineseTraditional
                default:
                    break
                }
            }
        } else {
            if fullCode.contains("Hans") {
                return .chineseSimplified
            } else if fullCode.contains("Hant") {
                return .chineseTraditional
            }
        }

        // Otherwise, try to get languageCode (e.g., "en", "fr")
        let locale = Locale(identifier: fullCode)
        let langCode = locale.languageCode ?? defaultCode

        return ApplicationLanguage(rawValue: langCode) ?? .english
    }
}