Подтвердить что ты не робот

Почему приложение iOS только правильно определяет текущий язык при первом запуске?

Я локализую свое приложение iOS, и в Симуляторе он работает правильно на моем выбранном языке каждый раз.

При тестировании на моем iPhone 5 он только правильно определяет язык при первом запуске приложения. Каждый раз, когда я перекомпилирую и запускаю свое приложение на устройстве, он обнаруживает "en" в качестве языка, хотя я тестирую с выбранным вами "Español".

Я определяю язык, используя:

[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]

Я также использовал:

[[NSLocale preferredLanguages] objectAtIndex:0]

Тот же результат.

Если я убил приложение после первого запуска и перезапустил его на устройстве, он продолжает правильно распознавать язык.

Но если я убью приложение, а затем перекомпилирую/перезапустим через Xcode после первого запуска, он будет загружаться с помощью "en" (англ.), обнаруженного вместо этого.

После этого убийство и повторное начало приложения постоянно обнаруживаются как английский, если я полностью не удалю приложение и не перекомпилирую/не переустановить/запустить приложение с помощью Xcode. Затем цикл повторяется... последующая перестройка/перезапуск без предварительного удаления приложения из устройства приводит к неправильному определению.

Все остальные приложения на моем устройстве отображаются на испанском языке все время. Весь пользовательский интерфейс отображается на испанском языке.

ОБНОВЛЕНИЕ: Я тестировал на своем iPad (3rd gen), также работающем на iOS 6, и испытываю то же поведение.

ОБНОВЛЕНИЕ 2:

В didFinishLaunchingWithOptions у меня есть этот код для обнаружения языка: (язык - это NSString *):

language = [[NSLocale preferredLanguages] objectAtIndex:0];

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

NSLog(@"Detected language: %@ / %@", language, [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]);

Результат отображается как "Обнаруженный язык: es/es", когда приложение работает правильно в испанском режиме, а затем отображается как "Обнаруженный язык: en/en", когда он этого не делает. По-прежнему не знаю, почему он решает загрузить как английский иногда...

ОБНОВЛЕНИЕ 4: Я ценю все ответы, и я пробовал различные предложения. К сожалению, я не смог наградить +100 баунти, поскольку ни одна из предложений, похоже, не решила проблему. Если кто-то окончательно найдет решение, которое будет работать для меня, я в это время награжу еще +50 баунти.

ОБНОВЛЕНИЕ 5: Я обновил с Xcode 4.5 до 4.5.2 и столкнулся с этой же проблемой.

ОБНОВЛЕНИЕ 6: Я создал новый тестовый проект с нуля, и он отлично работает! Очевидно, что-то должно быть неправильно в том, как мой проект выложен или, возможно, в одном из файлов данных. Я предполагаю, что следующее путешествие будет состоять в том, чтобы воссоздать проект с нуля, скопировав данные файла по одному...

ОБНОВЛЕНИЕ 7 (МЕСЯЦЫ ПОЗЖЕ): К сожалению, я снова столкнулся с этой проблемой после временного ее разрешения (по-видимому) путем тщательного воссоздания моего проекта. При первой загрузке язык правильно отображается, но при последующих нагрузках он возвращается на английский.

SOLVED Посмотрите мое окончательное решение ниже. Спасибо всем за помощь. Я могу получить часть щедрости, так как она все равно пропадет.

4b9b3361

Ответ 1

Я НАСТОЯЩИМ решил эту проблему через много месяцев! Спасибо всем за помощь (у меня также было неплохо взад и вперед с разработчиком Apple через dev-каналы).

TL; DR: Я случайно менял языковые предпочтения (среди многих других неожиданных вещей) между устройствами, используя мое хранилище ключей iCloud моего приложения (через MKiCloudSync)! Читайте дальше...

Я использую сторонний класс под названием MKiCloudSync, который помогает синхронизировать [NSUserDefaults standardUserDefaults] с моим хранилищем значений ключа iCloud. Мое намерение, когда я начал использовать его, было позволить ему обрабатывать некоторые пользовательские фавориты, синхронизирующиеся в фоновом режиме.

Однако, не понимая, как работает standardUserDefaults, я не понял, что в standardUserDefaults есть еще много других вещей, кроме только моих собственных настроек приложения!

Итак, что произошло, это:

  • Запустите приложение в первый раз. Свежий standardUserDefaults на месте, а внутренний ключ "AppleLanguages", который хранит упорядоченный список языковых настроек, корректен на основе текущих вариантов устройства.

  • Приложение отображается правильно на указанном языке.

  • В фоновом режиме MKiCloudSync синхронизирует ALL standardUserDefaults с iCloud. И наоборот, если вы запустили это приложение в другом месте, скажем, с помощью английского набора устройств, это устройство также синхронизировало бы его настройки языка до iCloud. Итак, теперь это текущее приложение на самом деле переписывает языковые настройки.

  • BOOM... в следующий раз, когда приложение будет запущено, независимо от того, что вы выбрали на устройстве, все, что было снято с iCloud, которое будет использоваться в качестве языка по умолчанию!

Что я планирую сделать для решения проблемы с моим следующим обновлением приложения:

  • Используйте разветвленную версию MKiCloudSync, которая позволяет синхронизировать только имена белых списков.

  • Добавьте код, который будет выполнять одноразовую очистку, сначала очистив хранилище iCloud для моего приложения, затем (на основе этого SO-ответа) вызывая этот код до reset по умолчанию пользователя:

    NSString * appDomain = [[NSBundle mainBundle] bundleIdentifier]; [[NSUserDefaults standardUserDefaults] removePersistentDomainForName: appDomain];

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

Ответ 2

В настройках- > general- > international есть возможность указать язык местоположения и т.д., если вы установите его на язык, который вы пытаетесь проверить, он будет работать, если ваш код верен.

Ответ 3

Я протестировал ваши шаги на своем iPhone 5 без проблем. Это заставляет меня думать, что здесь есть что-то другое: скорее всего, там что-то мешает тому, как вы читаете значение локали.

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

  • Вывести полный код метода, в котором вы получаете предпочтительное значение языка. Убедитесь, что метод выполняется каждый раз, когда приложение запускается.
  • Убедитесь, что введенный вами код содержит расположение директивы NSLog, которое вы используете, для проверки языка.
  • Сохраняете ли вы предпочтительный язык где-то еще после первого запуска?

Ответ 4

Попробуйте со следующим кодом:

LocalizationSystem.h ===

#import <Foundation/Foundation.h>

#define AMLocalizedString(key, comment) \
[[LocalizationSystem sharedLocalSystem] localizedStringForKey:(key) value:(comment)]

#define LocalizationSetLanguage(language) \
[[LocalizationSystem sharedLocalSystem] setLanguage:(language)]

#define LocalizationGetLanguage \
[[LocalizationSystem sharedLocalSystem] getLanguage]

#define LocalizationReset \
[[LocalizationSystem sharedLocalSystem] resetLocalization]

@interface LocalizationSystem : NSObject {
    NSString *language;
}


+ (LocalizationSystem *)sharedLocalSystem;

//gets the string localized
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)comment;

//sets the language
- (void) setLanguage:(NSString*) language;

//gets the current language
- (NSString*) getLanguage;

//resets this system.
- (void) resetLocalization;

@end

LocalizationSystem.m ===

#import "LocalizationSystem.h"

@implementation LocalizationSystem

//Singleton instance
static LocalizationSystem *_sharedLocalSystem = nil;

//Current application bundle to get the languages.
static NSBundle *bundle = nil;

+ (LocalizationSystem *)sharedLocalSystem{
    @synchronized([LocalizationSystem class])
    {
        if (!_sharedLocalSystem){
            [[self alloc] init];
        }
        return _sharedLocalSystem;
    }
    // to avoid compiler warning
    return nil;
}

+(id)alloc{
    @synchronized([LocalizationSystem class])
    {
        NSAssert(_sharedLocalSystem == nil, @"Attempted to allocate a second instance of a singleton.");
        _sharedLocalSystem = [super alloc];
        return _sharedLocalSystem;
    }
    // to avoid compiler warning
    return nil;
}

- (id)init{
    if ((self = [super init])) 
    {
        //empty.
        bundle = [NSBundle mainBundle];
    }
    return self;
}

// Gets the current localized string as in NSLocalizedString.

- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)comment{
    return [bundle localizedStringForKey:key value:comment table:nil];
}

// If this function is not called it will use the default OS language.
// If the language does not exists y returns the default OS language.
- (void) setLanguage:(NSString*) l{
    NSLog(@"preferredLang: %@", l);

    NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];


    if (path == nil)
        //in case the language does not exists
        [self resetLocalization];
    else
        bundle = [[NSBundle bundleWithPath:path] retain];

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

// Just gets the current setted up language.
// returns "es","fr",...
//
// example call:
// NSString * currentL = LocalizationGetLanguage;
- (NSString*) getLanguage{

    NSArray* languages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"];

    NSString *preferredLang = [languages objectAtIndex:0];

    return preferredLang;
}

// Resets the localization system, so it uses the OS default language.
//
// example call:
// LocalizationReset;
- (void) resetLocalization{
    bundle = [NSBundle mainBundle];
}


@end

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

Ответ 5

Вы случайно используете NSUserDefaults для сохранения связанного языка?

Посмотрите на каталог своего приложения Simulator → Library → Настройки → <YourAppBundleName>.plist

Смотрите: Как заставить NSLocalizedString использовать определенный язык для описания метода NSUserDefaults для установки языка.

Возможно, вы просто сохранили свой язык, и поэтому обнаружение просто возвращает сохраненное значение.