IMHO Xcode has one among the worst localization features available around...
I really don't like developing for Android but I must admit Android Studio has a better localization system.
That said, because I really cannot stand anymore to recreate Storyboard.strings after each mod (you know, Xcode won't update them for you...), this is how I do :
I have a couple of extensions to loop subviews (and subviews of subviews) and I deal with each of the main objects (labels, textfield, buttons...) by localizing their main properties (text, placeholde...) through a simple helper (AltoUtil.ls) which is a "short" version for NSLocalizedString.
Then I insert texts and placeholders with underscores (for example "_first_name", "_email_address") in my storyboard/xibs and I add those strings to each Localizable.strings file.
Now I just need to call the localize() function in viewDidLoad (or whereber I need it) so that I can have the whole view controller localized. For cells I just call the localize() inside the awakeFromNib() method for example.
I'm sure this is not the fastest method (due to subviews loop) but I don't get any slowdown compared to other methods I used to use and it's pretty productive.
import UIKit
extension UIView {
func localize()
{
for view in self.allSubviews()
{
if let label = view as? UILabel
{
label.text = AltoUtil.ls(label.text)
}
else if let textField = view as? UITextField
{
textField.text = AltoUtil.ls(textField.text)
textField.placeholder = AltoUtil.ls(textField.placeholder)
}
else if let button = view as? UIButton
{
button.setTitle(AltoUtil.ls(button.title(for: UIControl.State.normal)), for: UIControl.State.normal)
}
else if let searchBar = view as? UISearchBar
{
searchBar.placeholder = AltoUtil.ls(searchBar.placeholder)
}
}
}
func allSubviews() -> [UIView]
{
return subviews + subviews.flatMap { $0.allSubviews() }
}
}
The second extension is needed to localize view controllers title and tab bar items in view controllers. You can add any item you need to localize.
import UIKit
extension UIViewController {
func localize()
{
self.title = AltoUtil.ls(self.navigationItem.title)
self.tabBarItem?.title = AltoUtil.ls(self.tabBarItem?.title)
self.view.localize()
}
}