Introducting LThemeManager.localization
I’m always not happy with the default localization solution iOS provides, and while what Android offers is much better, it’s still not the best it could be. Here are the features LThemeManager.localization provides, and I’ll be discussing the disadvantages of the current solutions as well:
To Define
In iOS or Android you’ll have to put languages into different text / xml files. In LThemeManager however, we use class LFLocalizable / LFParseLocalizable to define the languages.
class TestLocalizable: LFParseLocalizable {
var new = Item()
var old = Item()
required init(dict: LTDictStrObj?) {
super.init(dict: dict)
new += "new"
new += "新"
new += "nuevo"
old += "old"
old += "旧"
old += "viejo"
}
}This allows you to:
- Put everything together if your language file is going to be very small.
- Split languages into different classes / files by module etc.
- Organize different localizable by language types (same as
iOSandAndroid). - Organize different localizable by keys (easier for translator who knows multiple languages).
Basically it’s more flexiable since it’s implemented programmatically. The done side is that you’ll have to write an additional key = Item() to define a LFLocalization.Item, but it comes easier when it gets to:
To Use
Instead of some unwrapping functions, you’ll be able to use the localized strings as native data structure:
struct Test {
static var common = TestLocalizable(publish:false)
}
// ...
let common = Test.common
LF.log("test", common.new.str)Normally you’d define the localizable keys as consts to avoid spelling mistakes, but with native data structure, this problem is solved automatically. Besides, you can use the localized strings in 3 ways:
- common.new.str: an “as is” way that retuns the localized string.
- common.new.STR: returns uppercase version of the string.
- common.new.Str: the first character is in uppercase; useful when it’s used with
Storyboard.
Storyboard Integration
In Storyboard, various controls including UILabel, UITextView… have 2 text_localized and text_auto_localized fields. Once text_localized is set, LThemeManager.localization uses it as the key and replace the text with the localized version; and if text_auto_localized is set, the current text will be used as the key. It may have some variant, e.g. for UIButton there are things like normal_title_localized and highlighted_title_localized, but they work in a very similar way.
To enable this though, localization needs to be initialized before UIApplicationMain is started. To do this, you need to:
- Remove the line with
@UIApplicationMaininAppDelegate.swift. - Create a new
main.swiftfile with contents like:
// init Parse here if it's based on ParseSDK
LTheme.localization.strings_append(Test.common.dictionary)
UIApplicationMain(Process.argc, Process.unsafeArgv, nil, NSStringFromClass(AppDelegate))Basically before the main app is started, LTheme.localization and Test.common will be initialized before Storyboard. Although with this extra step, I believe it’s still easier to use than the default localization solution of Storybard. (Android on the other hand, is easier enough as is - you just use “@string/key” to set the key directly in the layout files.)
Setting Support Languages
Besides common.new.str, you can also call LTheme.localization.str("new") (or Str and STR). Both of them are used to get the localized strings which is based on the current locale setting. However, it is much more flexible than the default solution of iOS so that you can:
- Set current language:
LTheme.localization.language = .SpanishMexico - If the current language is not supported,
default_languagewill be used which can be set programmatically:LTheme.localization.default_language = .English - You can also reset the supported languages and languages alias list:
struct LTheme {
struct localization {
static var languages = [
Language.English,
Language.ChineseSimplified,
Language.SpanishMexico,
]
static var languages_alias = [
Language.EnglishAustralia.rawValue: Language.English,
Language.EnglishUnitedStates.rawValue: Language.English,
Language.EnglishUnitedKingdom.rawValue: Language.English,
Language.ChineseTraditional.rawValue: Language.ChineseSimplified,
Language.Spanish.rawValue: Language.SpanishMexico,
]
}
}In this example, tranditional Chinese users see simplified Chinese instead of English. All these makes LTheme.localization more flexible and powerful.
How It Actually Works
There’s a LTheme.localization.strings dictionary that contains all the localized version of the strings.LTheme.localization.strings_append(dictionary) appends a set of strings into it, and LFLocalizable can work with it easily as shown in the example above.
Future Plans
Different language packs can be released as source code. I’ll make some of them as demo into LConst and see if it helps things get my life easier first.
Tags: