Как заставить NSLocalizedString использовать определенный язык

На iPhone NSLocalizedString возвращает строку на языке iPhone. Можно ли заставить NSLocalizedString использовать определенный язык для приложения? на другом языке, чем устройство?

Ответ 1

NSLocalizedString() (и их варианты) получают доступ к ключу AppleLanguages ​​в NSUserDefaults, чтобы определить, какие пользовательские настройки для предпочтительных языков. Это возвращает массив кодов языков, первый из которых задан пользователем для своего телефона, а последующие - резервными, если ресурс недоступен на предпочтительном языке. (на рабочем столе пользователь может указать несколько языков с пользовательским заказом в Системных настройках)

Вы можете переопределить глобальные настройки для своего собственного приложения, если хотите, используя метод setObject: forKey:, чтобы установить свой собственный список языков. Это будет иметь приоритет над глобально заданным значением и будет возвращено в любой код вашего приложения, выполняющего локализацию. Код для этого будет выглядеть примерно так:

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate

Это сделает немецкий язык предпочтительным для вашего приложения, а английский и французский - в качестве резервных копий. Вы бы хотели называть это когда-нибудь на ранней стадии запуска вашего приложения. Подробнее о языковых настройках и языковых настройках вы можете узнать здесь: Темы программирования интернационализации: получение текущего языка и локали

Ответ 2

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

Мое решение состояло в том, чтобы динамически изменить класс основного пакета и загрузить соответствующий пакет:

Заголовочный файл

@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end

Реализация

#import <objc/runtime.h>

static const char _bundle=0;

@interface BundleEx : NSBundle
@end

@implementation BundleEx
-(NSString*)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
    NSBundle* bundle=objc_getAssociatedObject(self, &_bundle);
    return bundle ? [bundle localizedStringForKey:key value:value table:tableName] : [super localizedStringForKey:key value:value table:tableName];
}
@end

@implementation NSBundle (Language)
+(void)setLanguage:(NSString*)language
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^
    {
        object_setClass([NSBundle mainBundle],[BundleEx class]);
    });
    objc_setAssociatedObject([NSBundle mainBundle], &_bundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

Итак, в основном, когда ваше приложение запускается и перед загрузкой вашего первого контроллера просто звоните:

[NSBundle setLanguage:@"en"];

Когда ваш пользователь изменит свой предпочтительный язык на экране настроек, просто вызовите его еще раз:

[NSBundle setLanguage:@"fr"];

В reset вернитесь к системным значениям по умолчанию, просто передайте nil:

[NSBundle setLanguage:nil];

Enjoy...

Для тех, кому нужна версия Swift:

var bundleKey: UInt8 = 0

class AnyLanguageBundle: Bundle {

    override func localizedString(forKey key: String,
                                  value: String?,
                                  table tableName: String?) -> String {

        guard let path = objc_getAssociatedObject(self, &bundleKey) as? String,
              let bundle = Bundle(path: path) else {

            return super.localizedString(forKey: key, value: value, table: tableName)
            }

        return bundle.localizedString(forKey: key, value: value, table: tableName)
    }
}

extension Bundle {

    class func setLanguage(_ language: String) {

        defer {

            object_setClass(Bundle.main, AnyLanguageBundle.self)
        }

        objc_setAssociatedObject(Bundle.main, &bundleKey,    Bundle.main.path(forResource: language, ofType: "lproj"), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
}

Ответ 3

Я обычно делаю это таким образом, но вы должны иметь все файлы локализации в вашем проекте.

@implementation Language

static NSBundle *bundle = nil;

+(void)initialize 
{
    NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
    NSArray* languages = [defs objectForKey:@"AppleLanguages"];
    NSString *current = [[languages objectAtIndex:0] retain];
    [self setLanguage:current];
}

/*
  example calls:
    [Language setLanguage:@"it"];
    [Language setLanguage:@"de"];
*/
+(void)setLanguage:(NSString *)l
{
    NSLog(@"preferredLang: %@", l);
    NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];
    bundle = [[NSBundle bundleWithPath:path] retain];
}

+(NSString *)get:(NSString *)key alter:(NSString *)alternate 
{
    return [bundle localizedStringForKey:key value:alternate table:nil];
}

@end

Ответ 4

Не использовать на iOS 9. Это возвращает nil для всех строк, прошедших через него.

Я нашел другое решение, которое позволяет вам обновлять языковые строки, без перезапуска приложения и совместимого с genstrings:

Поместите этот макрос в Prefix.pch:

#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]

и где вам понадобится локализованная строка:

NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")

Чтобы установить язык, используйте:

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];

Работает даже с последовательным переходом на язык, например:

NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"fr"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"it"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));

Ответ 5

Как говорилось ранее, просто выполните:

[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];

Но чтобы не перезапускать приложение, поместите строку в основной метод main.m, перед UIApplicationMain (...).

Ответ 6

Трюк использовать определенный язык, выбрав его из приложения, - заставить NSLocalizedString использовать конкретный пакет в зависимости от выбранного языка,

вот пост, который я написал для этого обучение продвижению локализации в приложениях ios

и вот код одного примера приложения продвигать локализацию в приложениях ios

Ответ 7

Как отмечает Брайан Вебстер, язык должен быть установлен "когда-нибудь в начале запуска приложения". Я думал, что applicationDidFinishLaunching: для AppDelegate должно быть подходящим местом для этого, потому что это я делаю всю другую инициализацию.

Но, как упоминает Уильям Деннисс, это похоже на эффект только после перезапуска приложения, что бесполезно.

Кажется, что это нормально, если я помещаю код в основную функцию:

int main(int argc, char *argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Force language to Swedish.
    [[NSUserDefaults standardUserDefaults]
     setObject:[NSArray arrayWithObject:@"sv"]
     forKey:@"AppleLanguages"];

    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

Буду признателен за любые комментарии по этому поводу.

Ответ 8

Что вы думаете об этом решении для Swift 3?

extension String {

    func localized(forLanguage language: String = Locale.preferredLanguages.first!.components(separatedBy: "-").first!) -> String {

        guard let path = Bundle.main.path(forResource: language == "en" ? "Base" : language, ofType: "lproj") else {

            let basePath = Bundle.main.path(forResource: "Base", ofType: "lproj")!

            return Bundle(path: basePath)!.localizedString(forKey: self, value: "", table: nil)
        }

        return Bundle(path: path)!.localizedString(forKey: self, value: "", table: nil)
    }
}

Простое использование:

"report".localized(forLanguage: "pl") //forced language
"report".localized() //default language selected by user in settings, in case when your app doesnt support selected lanaguage, the default one is selected, here is an english.

Ответ 9

Мне нравится лучший метод Мауро Дельрио. Я также добавил следующее в свой Project_Prefix.pch

#import "Language.h"    
#define MyLocalizedString(key, alt) [Language get:key alter:alt]

Итак, если вы когда-нибудь захотите использовать стандартный метод (который использует NSLocalizedString), вы можете сделать быструю подстановку синтаксиса во всех файлах.

Ответ 10

NSLocalizedString() считывает значение для ключа AppleLanguages из стандартных значений по умолчанию пользователя ([NSUserDefaults standardUserDefaults]). Он использует это значение для выбора подходящей локализации среди всех существующих локализаций во время выполнения. Когда Apple строит словарь по умолчанию для пользователей при запуске приложения, они ищут предпочтительный язык в системных настройках и копируют значение оттуда. Это также объясняет, например, почему изменение языковых настроек в OS X не влияет на запуск приложений, только после запуска приложений. После копирования значение не обновляется только потому, что настройки меняются. Поэтому iOS перезапускает все приложения, если вы измените язык.

Однако все значения словаря по умолчанию пользователя могут быть перезаписаны аргументами командной строки. См. Документацию NSUserDefaults на NSArgumentDomain. Это даже включает те значения, которые загружаются из файла настроек приложения (.plist). Это действительно хорошо, если вы хотите изменить значение только один раз для тестирования.

Итак, если вы хотите изменить язык только для тестирования, вы, вероятно, не захотите изменить свой код (если вы забыли удалить этот код позже...), вместо этого скажите Xcode запустить приложение с помощью команды (например, используйте испанскую локализацию):

enter image description here

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

Ответ 11

Я придумал решение, которое позволяет использовать NSLocalizedString. Я создаю категорию вызова NSBundle NSBundle+RunTimeLanguage. Интерфейс подобен этому.

// NSBundle+RunTimeLanguage.h
#import <Foundation/Foundation.h>
@interface NSBundle (RunTimeLanguage)
#define NSLocalizedString(key, comment) [[NSBundle mainBundle] runTimeLocalizedStringForKey:(key) value:@"" table:nil]
- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName;
@end

Реализация такая.

// NSBundle+RunTimeLanguage.m
#import "NSBundle+RunTimeLanguage.h"
#import "AppDelegate.h"

@implementation NSBundle (RunTimeLanguage)

- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
    AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    NSString *path= [[NSBundle mainBundle] pathForResource:[appDelegate languageCode] ofType:@"lproj"];
    NSBundle *languageBundle = [NSBundle bundleWithPath:path];
    NSString *localizedString=[languageBundle localizedStringForKey:key value:key table:nil];
    return localizedString;
}
@end

Вместо добавления import NSBundle+RunTimeLanguage.h в файлы, которые используют NSLocalizedString.

Как вы можете видеть, я сохраняю свой код языка в свойстве AppDelegate. Это можно сохранить в любом месте.

Это единственное, что мне не нравится в этом: Предупреждение, что NSLocalizedString marco переопределено. Возможно, кто-то может помочь мне исправить эту часть.

Ответ 12

Быстрая версия:

NSUserDefaults.standardUserDefaults().setObject(["fr"], forKey: "AppleLanguages")
NSUserDefaults.standardUserDefaults().synchronize()

Ответ 13

В двух словах:

Локализовать ваше приложение

Это первое, что вам нужно сделать, это локализовать ваше приложение с минимум двумя языками (английский и французский в этом примере).

Переопределить NSLocalizedString

В вашем коде вместо NSLocalizedString(key, comment) используйте макрос MYLocalizedString(key, comment), определенный следующим образом: #define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];

Этот MYLocalizationSystem singleton будет:

  • Установите langage, установив правильный локализованный пользователь NSBundle, запрашивающий
  • Возвращает локализованный NSString в соответствии с этим ранее установленным языком

Установить язык пользователя

Когда пользователь изменил язык приложения на французском языке, вызовите [[MYLocalizationSystem sharedInstance] setLanguage:@"fr"];

- (void)setLanguage:(NSString *)lang
{
    NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj"];
    if (!path)
    {
        _bundle = [NSBundle mainBundle];
        NSLog(@"Warning: No lproj for %@, system default set instead !", lang);
        return;
    }

    _bundle = [NSBundle bundleWithPath:path];
}

В этом примере этот метод устанавливает локализованное расслоение на fr.lproj

Возвращает локализованную строку

После того, как вы установили локализованный пакет, вы сможете получить из него подходящую локализованную строку:

- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value
{
    // bundle was initialized with [NSBundle mainBundle] as default and modified in setLanguage method
    return [self.bundle localizedStringForKey:key value:value table:nil];
}

Надеюсь, это поможет вам.

Подробнее об этой статье вы найдете в NSWinery.io

Ответ 14

Расширения Swift 3:

extension Locale {
    static var preferredLanguage: String {
        get {
            return self.preferredLanguages.first ?? "en"
        }
        set {
            UserDefaults.standard.set([newValue], forKey: "AppleLanguages")
            UserDefaults.standard.synchronize()
        }
    }
}

extension String {
    var localized: String {

    var result: String

    let languageCode = Locale.preferredLanguage //en-US

    var path = Bundle.main.path(forResource: languageCode, ofType: "lproj")

    if path == nil, let hyphenRange = languageCode.range(of: "-") {
        let languageCodeShort = languageCode.substring(to: hyphenRange.lowerBound) // en
        path = Bundle.main.path(forResource: languageCodeShort, ofType: "lproj")
    }

    if let path = path, let locBundle = Bundle(path: path) {
        result = locBundle.localizedString(forKey: self, value: nil, table: nil)
    } else {
        result = NSLocalizedString(self, comment: "")
    }
        return result
    }
}

Применение:

Locale.preferredLanguage = "uk"

label.text = "localizedKey".localized

Ответ 15

Может быть, вам следует дополнить это (в .pch файле после #import):

extern NSBundle* bundle; // Declared on Language.m

#ifdef NSLocalizedString
    #undef NSLocalizedString
    // Delete this line to avoid warning
    #warning "Undefining NSLocalizedString"
#endif

#define NSLocalizedString(key, comment) \
    [bundle localizedStringForKey:(key) value:@"" table:nil]

Ответ 16

В файле .pch, чтобы определить:

#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]


#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")

Ответ 17

Вы можете создать подкомплекс с набором локализованных строк, с которым вы хотите это сделать, а затем использовать NSLocalizedStringFromTableInBundle() для их загрузки. (Я предполагаю, что это контент отдельно от обычной локализации пользовательского интерфейса, которую вы можете использовать в приложении.)

Ответ 18

для моего случая у меня есть два локализованных файла, ja и en

и я хотел бы заставить его указать, если предпочтительный язык в системе не является en или ja

Я собираюсь отредактировать файл main.m

i проверить, является ли первым предпочтительным значение en или ja, если не тогда, то я изменю второй предпочтительный язык на en.

int main(int argc, char *argv[])
{

    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"AppleLanguages"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    NSString *lang = [[NSLocale preferredLanguages] objectAtIndex:0];

    if (![lang isEqualToString:@"en"]  &&  ![lang isEqualToString:@"ja"]){

        NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[NSLocale preferredLanguages]];
        [array replaceObjectAtIndex:1 withObject:@"en"];

        [[NSUserDefaults standardUserDefaults] setObject:array forKey:@"AppleLanguages"];
        [[NSUserDefaults standardUserDefaults] synchronize];


    }

    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));


    }


}

Ответ 19

Решение Swift 3:

let languages = ["bs", "zh-Hant", "en", "fi", "ko", "lv", "ms", "pl", "pt-BR", "ru", "sr-Latn", "sk", "es", "tr"]
UserDefaults.standard.set([languages[0]], forKey: "AppleLanguages")

Дайте несколько примеров кодов языков, которые можно использовать. Надеюсь, что это поможет

Ответ 20

Вы можете сделать что-то вроде этого:

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];


NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];

NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):

Ответ 21

На основе Tudorizer ответ на изменение языка без ухода или перезапуска приложения.

Вместо макроса используйте класс для доступа к предпочтительному языку, чтобы проверить, присутствует ли конкретный код языка.

Ниже приведен класс, используемый для получения текущего языкового пакета, который работает для iOS 9:

@implementation OSLocalization

+ (NSBundle *)currentLanguageBundle
{
    // Default language incase an unsupported language is found
    NSString *language = @"en";

    if ([NSLocale preferredLanguages].count) {
        // Check first object to be of type "en","es" etc
        // Codes seen by my eyes: "en-US","en","es-US","es" etc

        NSString *letterCode = [[NSLocale preferredLanguages] objectAtIndex:0];

        if ([letterCode rangeOfString:@"en"].location != NSNotFound) {
            // English
            language = @"en";
        } else if ([letterCode rangeOfString:@"es"].location != NSNotFound) {
            // Spanish
            language = @"es";
        } else if ([letterCode rangeOfString:@"fr"].location != NSNotFound) {
            // French
            language = @"fr";
        } // Add more if needed
    }

    return [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]];
}

/// Check if preferred language is English
+ (BOOL)isCurrentLanguageEnglish
{
    if (![NSLocale preferredLanguages].count) {
        // Just incase check for no items in array
        return YES;
    }

    if ([[[NSLocale preferredLanguages] objectAtIndex:0] rangeOfString:@"en"].location == NSNotFound) {
        // No letter code for english found
        return NO;
    } else {
        // Tis English
        return YES;
    }
}

/*  Swap language between English & Spanish
 *  Could send a string argument to directly pass the new language
 */
+ (void)changeCurrentLanguage
{
    if ([self isCurrentLanguageEnglish]) {
        [[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
    } else {
        [[NSUserDefaults standardUserDefaults] setObject:@[@"en"] forKey:@"AppleLanguages"];
    }
}
@end

Используйте вышеприведенный класс для ссылки на строковый файл/изображение/видео/etc:

// Access a localized image
[[OSLocalization currentLanguageBundle] pathForResource:@"my_image_name.png" ofType:nil]
// Access  a localized string from Localizable.strings file
NSLocalizedStringFromTableInBundle(@"StringKey", nil, [OSLocalization currentLanguageBundle], @"comment")

Измените язык в строке, как показано ниже, или обновите метод changeCurrentLanguage в указанном выше классе, чтобы взять строковый параметр, ссылающийся на новый язык.

[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];

Ответ 22

Эта функция попытается получить локализованную строку для текущего языка, и если она не будет найдена, она получит ее с использованием английского языка.

- (NSString*)L:(NSString*)key
{
    static NSString* valueNotFound = @"VALUE_NOT_FOUND";
    static NSBundle* enBundle = nil;

    NSString* pl = [NSLocale preferredLanguages][0];
    NSString* bp = [[NSBundle mainBundle] pathForResource:pl ofType:@"lproj"];
    NSBundle* b = [NSBundle bundleWithPath:bp];

    NSString* s = [b localizedStringForKey:key value:valueNotFound table:nil];
    if ( [s isEqualToString:valueNotFound] ) {
        if ( !enBundle ) {
            bp = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
            enBundle = [NSBundle bundleWithPath:bp];
        }
        s = [enBundle localizedStringForKey:key value:key table:nil];
    }

    return s;
}

Ответ 23

Я хотел добавить поддержку языка, который официально не поддерживается iOS (не указан в разделе "Язык" в разделе "Системные настройки" ). Следуя учебному пособию по интернационализации Apple, и несколько советов здесь Брайана Вебстера и геолога, я придумал этот фрагмент кода (поместите его в main.m ):

int main(int argc, char * argv[]) {
    @autoreleasepool {
        // Grab regional settings locale, for Slovenian this is either sl_SI or en_SI
        NSLocale *locale = [NSLocale currentLocale];
        NSString *ll = [locale localeIdentifier]; // sl_SI

        // Grab the first part of language identifier
        NSArray *comp = [ll componentsSeparatedByString:@"_"];
        NSString *ll1 = @"en";
        if (comp.count > 0) {
            ll1 = comp[0]; // sl, en, ...
        }
        // Check if we already saved language (user can manually change it inside app for example)
        if (![[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"]) {
            //   Slovenian (Slovenia),            Slovenia
            if ([ll isEqualToString:@"sl_SI"] || [ll isEqualToString:@"en_SI"]) {
                ll1 = @"sl-SI"; // This is the part of localized path for Slovenian language that Xcode generates
            }
            // Add more unsupported languages here...

            [[NSUserDefaults standardUserDefaults] setObject:ll1 forKey:@"SelectedLanguage"]; // Save language
        }
        else {
            // Restore language as we have previously saved it
            ll1 = [[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"];
        }
        // Overwrite NSLocalizedString and StoryBoard language preference
        [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:ll1, @"en", @"fr", nil] forKey:@"AppleLanguages"];
        // Make sure settings are stored to disk
        [[NSUserDefaults standardUserDefaults] synchronize];

        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

Это хорошо работает для кода Storyboard и NSLocalizedString. Код предполагает, что пользователь будет иметь возможность вручную изменить язык внутри приложения позже.

Конечно, не забудьте добавить правильные переводы раскадровки и переводы Localizable.strings(см. ссылку на страницу Apple выше, как это сделать).

Ответ 24

Вот достойное решение этой проблемы и не требует перезапуска приложения.

https://github.com/cmaftuleac/BundleLocalization

Эта реализация работает путем настройки внутри NSBundle. Идея заключается в том, что вы переопределяете метод localizedStringForKey в экземпляре объекта NSBundle, а затем вызываете этот метод в другом комплекте с другим языком. Простая и элегантная, полностью совместимая со всеми типами ресурсов.

Ответ 25

В Swift 4 я решил это без необходимости перезапуска или использования библиотек.

Перепробовав много вариантов, я нашел эту функцию, где вы передаете stringToLocalize (из Localizable.String, файл строк), который вы хотите перевести, и язык, на который вы хотите перевести его, и что он возвращает, это значение для та строка, которая у вас есть в файле строк:

    func localizeString (stringToLocalize: String, language: String) -> String
    {
        let path = Bundle.main.path (forResource: language, ofType: "lproj")
        let languageBundle = Bundle (path: path!)
        return languageBundle! .localizedString (forKey: stringToLocalize, value: "", table: nil)
    }

Учитывая эту функцию, я создал эту функцию в файле Swift:

struct CustomLanguage {

    func createBundlePath () -> Bundle {
        let selectedLanguage = //recover the language chosen by the user (in my case, from UserDefaults)
        let path = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj")
        return Bundle(path: path!)!
    }
}

Для доступа ко всему приложению и в каждой строке остальных ViewControllers вместо:

NSLocalizedString ("StringToLocalize", comment: "")

Я заменил его

let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()

NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: "") //use in each String

Я не знаю, будет ли это лучшим способом, но я нашел это очень простым, и это работает для меня, я надеюсь, что это поможет вам!

Ответ 26

что бы вы ни делали, лучший способ - взять short_name для указанного языка, например: fr, en, nl, de, it и т.д.... и присвоить его глобальному значению.

сделайте вид подборщика всплывающим меню, как выпадающее меню (комбинация кнопки, по щелчку которой вид снизу отображается со списком языков) и выберите желаемый язык. пусть короткое имя будет храниться внутри. создайте файл .h +.m с именем LocalizedString.

Установите глобальное значение short_name равным полученному значению в LocalizedString.m Когда выбран нужный язык, назначьте NSBundlePath для создания подкаталогов проекта для нужного языка. например, nl.proj, en.proj.

Когда выбрана конкретная папка proj, вызовите локализованную строку для соответствующего языка и динамически измените язык.

не нарушены правила.

Ответ 27

Для Swift вы можете переопределить файл main.swift и установить туда строку UserDefaults перед запуском приложения. Таким образом, вам не нужно перезапускать приложение, чтобы увидеть желаемый эффект.

import Foundation
import UIKit

// Your initialisation code here
let langCultureCode: String = "LANGUAGE_CODE"

UserDefaults.standard.set([langCultureCode], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()

UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))

в сочетании с удалением @UIApplicationMain в файле AppDelegate.swift.