Установите язык iOS без перезагрузкиIOS

Программируем под IOS
Ответить
Anonymous
 Установите язык iOS без перезагрузки

Сообщение Anonymous »

Мне известно немало сообщений, в которых говорится, что этого делать не следует или это невозможно. Я повозился с несколькими идеями и теперь задаю этот вопрос, потому что хочу быть абсолютно уверен, что других вариантов нет.

Вариант 1:

Самое популярное решение — изменить AppleLanguages, как в этом посте. Я не возражаю против необходимости перезагрузки, поэтому для меня это было бы приемлемым решением, за исключением того, что вы не можете перезапустить свое приложение программно (не можете найти метод или будет отклонено Apple). Просить пользователя перезапустить приложение вручную было бы не лучшим решением.

Вариант 2:

Следующее решение — получить соответствующий пакет и выполнить поиск localizedStringForKey для каждого UILabel, UIButton и т. д. Это может быть немного утомительно, но меня это устраивает, поскольку я уже добавил localizationProperties (аналогично этому) к этим представлениям, чтобы у меня был централизованный файл строк.

AppDelegate.swift:

Код: Выделить всё

static var userLanguage: String?
{
set
{
let defaults = NSUserDefaults.standardUserDefaults();
defaults.setObject(newValue, forKey: LanguageKey);
defaults.synchronize();

let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle());
instance.window?.rootViewController = storyboard.instantiateInitialViewController();
}

get
{
let defaults = NSUserDefaults.standardUserDefaults();
return defaults.stringForKey(LanguageKey);
}
}
Localization.swift:

Код: Выделить всё

private var bundle: NSBundle
{
get
{
let bundle: NSBundle;
#if TARGET_INTERFACE_BUILDER
bundle = NSBundle(forClass: self.dynamicType);
#else
bundle = NSBundle.mainBundle();
#endif

let lang: String;
if(AppDelegate.userLanguage == nil || AppDelegate.userLanguage == "en")
{
lang = "Base";
}
else
{
lang = AppDelegate.userLanguage!;
}

let path = bundle.pathForResource(lang, ofType: "lproj");
if(path != nil)
{
let toreturn = NSBundle(path: path!);
if(toreturn != nil)
{
return toreturn!;
}
}

return bundle;
}
}

extension UILabel
{
@IBInspectable var localizedText: String?
{
get { return "" }

set
{
if(newValue != nil)
{
text = bundle.localizedStringForKey(newValue!, value:"", table: nil);
}
}
}
}
Проблема варианта 2 заключается в том, что он устанавливает язык только для этих полей. Направление макета останется неизменным, и такие файлы, как макеты для конкретного языка, не будут использоваться.

Расширяя UIApplication, я могу указать собственный userInterfaceLayoutDirection, который успешно меняет все макеты между LTR и RTL.

DemoApplication.swift:

Код: Выделить всё

class DemoApplication: UIApplication
{
override internal var userInterfaceLayoutDirection: UIUserInterfaceLayoutDirection
{
get
{
if(AppDelegate.userLanguage == "ar")
{
return UIUserInterfaceLayoutDirection.RightToLeft;
}

return UIUserInterfaceLayoutDirection.LeftToRight;
}
}
}
Теперь, когда я устанавливаю AppDelegate.userLanguage, приложение возвращается к исходному контроллеру представления, отображая новый язык, переключая макет между LTR и RTL. Это не решает проблему языковых файлов, и я также заметил, что текст остается выровненным по левому или правому краю в пределах своих границ.

Поскольку я не могу найти исходный код для собственных классов iOS, я не могу видеть, какие языковые переменные устанавливаются при запуске, поэтому я предположил, что он связан с NSBundle.mainBundle. Я попытался переопределить это, используя метод swizzling.

Код: Выделить всё

extension NSBundle
{
override public class func initialize()
{
struct Static
{
static var token: dispatch_once_t = 0;
}

// make sure this isn't a subclass
if (self !== NSBundle.self)
{
return;
}

dispatch_once(&Static.token)
{
do
{
try jr_swizzleClassMethod("mainBundle", withClassMethod: "mainBundleExt");
}
catch
{
print("\(error)");
}
}

super.initialize();
}

public class func mainBundleExt() -> NSBundle
{
let bundle = self.mainBundleExt();  // Due to swizzling, this is the "super" method

let lang: String;
if(AppDelegate.userLanguage == nil || AppDelegate.userLanguage == "en")
{
lang = "Base";
}
else
{
lang = AppDelegate.userLanguage!;
}

let path = bundle.pathForResource(lang, ofType: "lproj");
if(path != nil)
{
let toreturn = NSBundle(path: path!);
if(toreturn != nil)
{
return toreturn!;
}
}
}
}
Однако это не работает, похоже, что mainBundle по умолчанию все еще используется.

Поэтому у меня вопрос: как mainBundle присваивается значение? Какие другие переменные, специфичные для языка, устанавливаются при запуске, например userInterfaceLayoutDirection.
Я предполагаю, что таких переменных 2 или 3. Наконец, возможно ли, чтобы это сработало или я просто зря трачу время?

Спасибо.

Подробнее здесь: https://stackoverflow.com/questions/333 ... restarting
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»