Оптимизация раскадровки /XIB и локализации
Официально рекомендуемый метод для локализации XIB/Storyboard заключается в создании файлов .xib и .storyboard внутри xx.lproj(где xx - это два идентификатор языка письма) для каждой локализации, которую вы хотите поддерживать.
Это создает проблему, потому что у вас есть несколько файлов, которые во многих случаях используют один и тот же пользовательский интерфейс, которые подвержены изменениям. Если вы хотите перепроектировать пользовательский интерфейс для одного вида, вам придется делать это несколько раз (хуже, если вы ввели локализованные строковые значения в самом xib). Это противоречит принципу DRY.
Кажется более эффективным вызвать NSLocalizedString()
там, где он вам нужен, и просто использовать один XIB или Storyboard для одной базовой локализации.
Итак, почему (не) я создаю локализованные файлы XIB/Storyboard?
Ответы
Ответ 1
Для простого изменения текстовых меток я сделал что-то вроде этого
+(void) replaceTextWithLocalizedTextInSubviewsForView:(UIView*)view
{
for (UIView* v in view.subviews)
{
if (v.subviews.count > 0)
{
[self replaceTextWithLocalizedTextInSubviewsForView:v];
}
if ([v isKindOfClass:[UILabel class]])
{
UILabel* l = (UILabel*)v;
l.text = NSLocalizedString(l.text, nil);
[l sizeToFit];
}
if ([v isKindOfClass:[UIButton class]])
{
UIButton* b = (UIButton*)v;
[b setTitle:NSLocalizedString(b.titleLabel.text, nil) forState:UIControlStateNormal];
}
}
}
вызовите эту функцию в viewDidLoad:
следующим образом:
[[self class] replaceTextWithLocalizedTextInSubviewsForView:self.view];
Это сэкономило мне много работы, объявив и соединив IBOutlets, когда все, что вам нужно, - это локализованные метки.
Ответ 2
Вы можете создать категорию на UILabel, UIButton и т.д., например:
#import "UILabel+Localization.h"
@implementation UILabel (Localization)
- (void)setLocalizeKey:(NSString*)key
{
self.text = NSLocalizedString(key, nil);
}
@end
а после этого в вашем файле xib используйте атрибуты Runtime, определенные пользователем, чтобы связать UILabel (или UIButton и т.д.) с ключом, сохраненным в файле Localizable.strings
![user defined runtime attributes]()
Таким образом, вы можете иметь все свои строки в одном файле, и вам не нужно создавать отдельный xib для каждого языка.
Ответ 3
Решение Flax работает хорошо, нужно отметить, что если у вас есть UILabels
или UIButtons
, которые содержатся в UICollectionViewCells
в UICollectionViews
(или аналогичном), и эти коллекции часто меняются в текущем представлении, например, из-за действия пользователя или заполняется асинхронным запросом, чтобы обновить метки с помощью правильных строк локализации, вы можете вызвать функцию локализации в viewDidLayoutSubviews
вместо viewDidLoad
(которая вызывается только один раз):
- (void)viewDidLayoutSubviews
{
[LocalizationHelper replaceTextWithLocalizedTextInSubviewsForView:self.view];
}
Как видно из этого кода, я сохраняю метод локализации в статическом вспомогательном классе (как предложил другой глава):
@implementation LocalizationHelper
+(void) replaceTextWithLocalizedTextInSubviewsForView:(UIView*)view
{
for (UIView* v in view.subviews)
... <code from above> ...
}
@end
Добавил бы это как комментарий к вышеуказанному решению, но у меня нет 'rep!
Ответ 4
вы можете автоматизировать его много с помощью ibtool
. это достойное введение: http://www.bdunagan.com/2009/03/15/ibtool-localization-made-easy/
Ответ 5
Полезный пост, намного проще, чем несколько XIB. Я расширил код для обработки UISegmentedControl
:
if ([v isKindOfClass:[UISegmentedControl class]]) {
UISegmentedControl* s = (UISegmentedControl*)v;
for (int i = 0; i < s.numberOfSegments; i++) {
[s setTitle:NSLocalizedString([s titleForSegmentAtIndex:i],nil) forSegmentAtIndex:i];
}
}
Ответ 6
Я искал точно ответ, который дал Лен, отмеченный как правый, но мне это нужно в Свифте. Поэтому я перевел на это. Спасибо, Лен.
func replaceTextWithLocalizedTextInSubviewsForView(view: UIView) {
for v in view.subviews {
if v.subviews.count > 0 {
self.replaceTextWithLocalizedTextInSubviewsForView(v)
}
if (v.isKindOfClass(UILabel)) {
let myLabel: UILabel = v as! UILabel
myLabel.text = NSLocalizedString(myLabel.text!, comment: "Text to translate.")
myLabel.sizeToFit()
}
if (v.isKindOfClass(UIButton)) {
let myButton: UIButton = v as! UIButton
myButton.setTitle(NSLocalizedString((myButton.titleLabel?.text)!, comment: "Text to translate.") as String, forState: .Normal)
myButton.sizeToFit()
}
}
}
Это работает для Swift 2.1
Ответ 7
Как объясняется Leszek S, вы можете создать категорию.
Здесь я приведу вам пример в swift 3 с расширением для UILabel и UIButton:
- Прежде всего создайте файл StringExtension.swift
-
Добавьте в него этот код:
extension String {
func localized() -> String {
let bundle = Bundle.main
return NSLocalizedString(self, tableName: nil, bundle: bundle, value: "", comment: "")
}
}
-
Затем создайте еще один новый файл с нужным именем (например) " LocalizableObjectsExtensions.swift"
-
Добавьте в него расширение для UIButton и одно для UILabel, подобное этому (конечно, вы можете создать расширение для того, что вы хотите, UITextField...):
extension UIButton {
var localizedText: String {
set (key) { setTitle(key.localized(), for: .normal) }
get { return titleLabel!.text! }
}
}
extension UILabel {
var localizedText: String {
set (key) { text = key.localized() }
get { return text! }
}
}
-
Теперь идите в свою раскадровку, а для вашей кнопки и/или вы наклейте, что хотите локализовать, просто добавьте в инспектор по идентификации объекта:
![введите описание изображения здесь]()
FYI: здесь Key Путь - это имя функции, которую вы добавили в своих расширениях (UIlabel и UIButton), а Value - это имя ключа, который вы хотите перевести автоматически, который находится в вашем Localizable.strings файл. Например, в Localizable.strings(французский) у вас есть ключ/значение "ourOffers" = "NOS OFFRES";
Теперь создадим и запустим. Ваш объект будет переведен на язык вашего устройства, если у вас есть ключ/значение в вашей Localizable.string. Наслаждайтесь:)
Ответ 8
Каждое место, которое я смотрю, говорит, что вам нужно реплицировать весь xib файл для каждого экземпляра локализации, даже если вы действительно хотели только разорвать текст и реплицировать текст на другом языке для каждого экземпляра локализации.
Если кто-нибудь знает о методе репликации только видимого пользователем текста xib (на другом языке) без репликации всего xib файла для каждого языка, сообщите нам.
Ответ 9
Я столкнулся с этим сообщением и несколькими другими, пытаясь упростить локализацию xib. Я отправил свой метод включения IBOutles для меток/кнопок по этому вопросу, отлично поработал у меня, сохраняет все изменения, ограниченные файлами Localization.strings.
fooobar.com/info/435672/...