Reputation: 265
My app is available in German, There are around 30 Xcode generated Localizable.strings files (means app is available in 30 more languages) i'm slowly converting to swift structs
, personal opinion.
struct German {
let contacting_app_services: String = "Kontaktiere App Service.."
let validating_user: String = "Validiere Nutzer"
let email_in_use: String = "Diese e-mail wird bereits von einem andern Konto genutzt"
let account_not_found: String = "Nutzerkonto nicht gefunden. Bitte prüfen und nochmals versuchen"
let valid_email: String = "Bitte geben Sie eine gültige e-mail Adresse ein"
}
Now, I check if the device is in German:
extension Locale {
func isGerman() -> Bool {
return Locale.preferredLanguages[0].range(of:"de") != nil
}
}
And update my UI with:
if Locale.current.isGerman() {
self.errorLabel.text = German().valid_email
}
What i'm trying to do:
if statement
and use a cleaner way.Upvotes: 0
Views: 93
Reputation: 63264
Don't do this. Even if you have some inexplicable repulsion to the localization tools already built into the system, don't do this.
Just imagine what I night mare you would run into if you had to support multiple languages. Imagine you wanted to add support for the 6 official languages of the UN.
if Locale.current.isArabic {
self.errorLabel.text = Arabic().valid_email
}
else if Locale.current.isChinese {
self.errorLabel.text = Chinese().valid_email
}
else if Locale.current.isEnglish {
self.errorLabel.text = English().valid_email
}
else if Locale.current.isFrench {
self.errorLabel.text = French().valid_email
}
else if Locale.current.isGerman {
self.errorLabel.text = German().valid_email
}
else if Locale.current.isRussian {
self.errorLabel.text = Russian().valid_email
}
else if Locale.current.isSpanish {
self.errorLabel.text = Spanish().valid_email
} else {
// What would you even put here?
}
What an absolute disaster. There are so many issues with it:
if
/else if
/else
ladder at every place where you want a localized string!else
case? A default language?else
case? Are you going to go back and change it every where?That's obviously a complete non-starter.
Instead, use polymorphism to pick the right string for you:
protocol LocalizedStrings {
var contactingAppServices: String { get }
var validatingUser: String { get }
var emailInUse: String { get }
var accountNotFound: String { get }
var validEmail: String { get }
}
struct EnglishLocalizedStrings: LocalizedStrings {
let contactingAppServices = "Contacting App Services, please wait."
let validatingUser = "Validating user, please wait."
let emailInUse = "This e-mail is already in use."
let accountNotFound = "Account not found."
let invalidEmail = "This e-mail is not valid"
}
struct ArabicLocalizedStrings: LocalizedStrings {
// ...
}
// Somewhere in the initalization of your app
let localizedStrings: LocalizedString = PickTheRightLocalizationStringsObjectForTheUser()
// somewhere where you need localized strings:
self.errorLabel.text = localizedStrings.validEmail
And then you can just rely on the dynamic dispatch mechanism to do the branching for you to pick the right string for the job, rather than manually enumerating each possible case yourself, everytime.
Upvotes: 2
Reputation: 265
I'd go with:
protocol Translations {
var valid_email: String { get }
}
struct German: Translations {
var valid_email: String = "Bitte geben Sie eine gültige e-mail Adresse ein"
}
struct English: Translations {
var valid_email: String = ""
}
extension Locale {
static func isGerman() -> Bool {
return Locale.preferredLanguages[0].range(of:"de") != nil
}
static func language() -> Translations {
if isGerman() {
return German()
}
return English()
}
}
Usage:
let errorLabel = UILabel()
errorLabel.text = Locale.language().valid_email
Upvotes: 0