122 lines
4.2 KiB
Swift
Executable File
122 lines
4.2 KiB
Swift
Executable File
import Foundation
|
||
import SwiftUI
|
||
|
||
/// Schlüssel wie Android `strings.xml` – Auflösung über `Localizable.strings` (de/en).
|
||
enum L10n {
|
||
static func tr(_ key: String) -> String {
|
||
String(localized: String.LocalizationValue(key))
|
||
}
|
||
|
||
static func timeoutIn(_ time: String) -> String {
|
||
String(format: tr("timeout_in"), time)
|
||
}
|
||
|
||
static func inboxNew(_ count: Int) -> String {
|
||
String(format: tr("inbox_new_count"), locale: .current, count)
|
||
}
|
||
|
||
static func feedbackCreatedAt(_ date: String) -> String {
|
||
String(format: tr("feedback_created_at"), locale: .current, date)
|
||
}
|
||
|
||
static func countriesLoadError(_ detail: String) -> String {
|
||
String(format: tr("countries_load_error"), locale: .current, detail)
|
||
}
|
||
|
||
static func userBlocked(_ name: String) -> String {
|
||
String(format: tr("user_blocked"), locale: .current, name)
|
||
}
|
||
|
||
static func userUnblocked(_ name: String) -> String {
|
||
String(format: tr("user_unblocked"), locale: .current, name)
|
||
}
|
||
}
|
||
|
||
func formatTimeout(totalSeconds: Int) -> String {
|
||
let minutes = totalSeconds / 60
|
||
let seconds = totalSeconds % 60
|
||
return String(format: "%d:%02d", minutes, seconds)
|
||
}
|
||
|
||
func localizeRuntimeMessage(_ message: String) -> String {
|
||
if message.hasPrefix("Country list could not be loaded:") {
|
||
let detail = String(message.dropFirst("Country list could not be loaded:".count)).trimmingCharacters(in: .whitespacesAndNewlines)
|
||
return L10n.countriesLoadError(detail)
|
||
}
|
||
switch message {
|
||
case "Image uploaded": return L10n.tr("image_upload_success")
|
||
case "Image upload failed": return L10n.tr("image_upload_failed")
|
||
case "Image exceeds 5 MB": return L10n.tr("image_upload_too_large")
|
||
case "Image could not be opened": return L10n.tr("image_upload_open_failed")
|
||
case "Feedback saved": return L10n.tr("feedback_saved")
|
||
default:
|
||
break
|
||
}
|
||
if message.hasSuffix(" blocked") {
|
||
let name = String(message.dropLast(" blocked".count))
|
||
return L10n.userBlocked(name)
|
||
}
|
||
if message.hasSuffix(" unblocked") {
|
||
let name = String(message.dropLast(" unblocked".count))
|
||
return L10n.userUnblocked(name)
|
||
}
|
||
return message
|
||
}
|
||
|
||
func formatFeedbackTimestamp(_ createdAt: String) -> String? {
|
||
guard !createdAt.isEmpty else { return nil }
|
||
return ISO8601DateFormatter().date(from: createdAt).map {
|
||
DateFormatter.localizedString(from: $0, dateStyle: .medium, timeStyle: .short)
|
||
}
|
||
}
|
||
|
||
func smileyEmoji(hexCode: String) -> String {
|
||
guard let v = UInt32(hexCode, radix: 16), let scalar = UnicodeScalar(v) else { return "" }
|
||
return String(Character(scalar))
|
||
}
|
||
|
||
struct SmileyItem: Identifiable {
|
||
var id: String { token }
|
||
let token: String
|
||
let hexCode: String
|
||
}
|
||
|
||
let ypChatSmileys: [SmileyItem] = [
|
||
SmileyItem(token: ":)", hexCode: "1F642"),
|
||
SmileyItem(token: ":D", hexCode: "1F600"),
|
||
SmileyItem(token: ":(", hexCode: "1F641"),
|
||
SmileyItem(token: ";)", hexCode: "1F609"),
|
||
SmileyItem(token: ":p", hexCode: "1F60B"),
|
||
SmileyItem(token: ";p", hexCode: "1F61C"),
|
||
SmileyItem(token: "O)", hexCode: "1F607"),
|
||
SmileyItem(token: ":*", hexCode: "1F617"),
|
||
SmileyItem(token: "(h)", hexCode: "1FA77"),
|
||
SmileyItem(token: "xD", hexCode: "1F602"),
|
||
SmileyItem(token: ":@", hexCode: "1F635"),
|
||
SmileyItem(token: ":O", hexCode: "1F632"),
|
||
SmileyItem(token: ":3", hexCode: "1F63A"),
|
||
SmileyItem(token: ":|", hexCode: "1F610"),
|
||
SmileyItem(token: ":/", hexCode: "1FAE4"),
|
||
SmileyItem(token: ":#", hexCode: "1F912"),
|
||
SmileyItem(token: "#)", hexCode: "1F973"),
|
||
SmileyItem(token: "%)", hexCode: "1F974"),
|
||
SmileyItem(token: "(t)", hexCode: "1F44D"),
|
||
SmileyItem(token: ":'(", hexCode: "1F622"),
|
||
]
|
||
|
||
struct GenderOptionRow: Identifiable {
|
||
var id: String { value }
|
||
let value: String
|
||
let label: String
|
||
}
|
||
|
||
func displayCountryName(user: UserDto, countries: [CountryOption]) -> String {
|
||
if let byEnglish = countries.first(where: { $0.englishName == user.country }) {
|
||
return byEnglish.displayName
|
||
}
|
||
if let byIso = countries.first(where: { $0.isoCode.caseInsensitiveCompare(user.isoCountryCode) == .orderedSame }) {
|
||
return byIso.displayName
|
||
}
|
||
return user.country
|
||
}
|