Вопрос

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

Это было полезно?

Решение

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

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

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

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

Другие советы

Недавно у меня была такая же проблема, и я не хотел запускать и исправлять всю свою 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"];

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

[NSBundle setLanguage:nil];

Наслаждайся...

Для тех, кому нужна версия 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)
    }
}

Обычно я делаю это таким образом, но у вас ДОЛЖНЫ быть все файлы локализации в вашем проекте.

@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

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

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

Поместите этот макрос в префикс.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, @""));

Как было сказано ранее, просто сделайте:

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

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

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

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

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

Как упоминает Брайан Вебстер, язык необходимо установить "когда-нибудь на ранней стадии запуска вашего приложения".Я думал 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;
}

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

Что вы думаете об этом решении для 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.

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

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

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

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

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

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

enter image description here

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

Я придумал решение, которое позволяет вам использовать 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

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

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

Единственное, что мне в этом не нравится, так это Предупреждение о том, что NSLocalizedString марко переосмыслил.Возможно, кто-нибудь мог бы помочь мне исправить эту часть.

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

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

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

Локализуйте свое приложение

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

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

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

Это MYLocalizationSystem синглтон будет :

  • Установите язык, установив правильный локализованный 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

Расширения 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

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

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


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

Возможно, вам следует дополнить это (в файле .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]

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

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

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

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

я проверю, является ли первый предпочтительный язык 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]));


    }


}

Решение 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")

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

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

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


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

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

Основанный на Тюдоризатора ответ на изменение языка без выход или перезапуск приложение.

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

Ниже приведен класс, используемый для получения текущего языкового пакета, который работает для 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"];

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

- (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;
}

Я хотел добавить поддержку языка, который официально не поддерживается 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]));
    }
}

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

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

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

https://github.com/cmaftuleac/BundleLocalization

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

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

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

    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

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

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

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

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

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

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

Для 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 файл.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top