2012-11-27 16 views
24

Lokalizuję aplikację na iOS, aw Symulatorze działa ona poprawnie w wybranym języku za każdym razem.Dlaczego moja aplikacja iOS wykrywa tylko bieżący język poprawnie przy pierwszym uruchomieniu?

Podczas testowania na moim iPhone 5, wykrywa język poprawnie tylko przy pierwszym uruchomieniu aplikacji. Co drugi raz przekompilowuję i uruchamiam moją aplikację na urządzeniu, wykrywa ona "en" jako język, mimo że testuję z wybranym językiem ("es").

wykryć przy użyciu języka:

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

Ja również używany:

[[NSLocale preferredLanguages] objectAtIndex:0]

sam rezultat.

Jeśli zabiję aplikację po pierwszym uruchomieniu i uruchomię ją ponownie na urządzeniu, nadal będzie poprawnie wykrywać język.

Ale jeśli zabiję aplikację, a następnie ponownie skompiluję/zrestartuję przez Xcode po pierwszym uruchomieniu, załaduje się ona z wykrytym "en" (angielski).

Po tym, zabijanie i ponowne uruchamianie aplikacji stale wykrywa, jak angielski, chyba że całkowicie usunę aplikację, i ponownie skompilować/ponownie zainstalować/uruchomić aplikację za pośrednictwem Xcode. Cykl następnie powtarza ... późniejsze przebudowanie/ponowne uruchomienie bez wcześniejszego usunięcia aplikacji z urządzenia powoduje błędne wykrycie.

Wszystkie inne aplikacje na moim urządzeniu są wyświetlane przez cały czas w języku hiszpańskim. Cały interfejs użytkownika wyświetla się po hiszpańsku.

AKTUALIZACJA: Testowałem na moim iPadzie (3rd gen), również z systemem iOS 6, i doświadczam tego samego zachowania.

UPDATE 2:

W didFinishLaunchingWithOptions, mam ten kod do wykrywania języka (język jest NSString *):

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

Obserwowani przez tego oświadczenia debugowania, aby porównywać wartość, którą otrzymuję, a także nieco inny sposób wykrywania, tylko do debugowania:

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

Dane wyjściowe są wyświetlane jako "Wykryty język: es/es", gdy aplikacja działa poprawnie w trybie hiszpańskim, a następnie wyświetla się jako "Wykryty język: en/en", gdy nie jest. Wciąż nie mam pojęcia, dlaczego czasami ładuje się jako angielski ...

AKTUALIZACJA 4: Doceniam odpowiedzi wszystkich osób i próbowałem różnych sugestii. Niestety nie udało mi się przyznać +100 bounty, ponieważ żadna z propozycji nie rozwiązała problemu. Jeśli ktoś w końcu znajdzie rozwiązanie, które będzie dla mnie skuteczne, w tym czasie nagrodzę go kolejnym +50 nagrodami.

AKTUALIZACJA 5: Mam zaktualizowane z Xcode 4.5 do 4.5.2 i doświadczam tego samego problemu.

AKTUALIZACJA 6: Zrobiłem nowy projekt testowy od podstaw, i działa idealnie dobrze! Oczywiście coś musi być nie tak w sposobie, w jaki mój projekt został opracowany, lub może w jednym z plików danych. Chyba moja następna podróż będzie ponownie utworzyć projekt od zera, kopiowania danych plików przez jeden po drugim ...

UPDATE (7 miesięcy później): Niestety, jestem znowu w obliczu tego problemu po tymczasowo rozwiązać to (pozornie) przez staranne odtworzenie mojego projektu. Przy pierwszym załadowaniu język jest poprawnie renderowany, ale po kolejnych ładowaniach wraca z powrotem do angielskiego.

SOLVED Zobacz moje ostateczne rozwiązanie below. Dzięki za pomoc dla wszystkich. Mogę odłożyć trochę nagród, ponieważ i tak pójdzie na marne.

+2

Nie mam zbyt wiele do podzielenia się z tobą, ale czy grałeś z parametrem "Uruchomiony język angielski" (angielski)? (Zobacz http://dl.dropbox.com/u/15994997/Screenshots/2h.png, który znajduje się w sekcji Zarządzaj Schematy). Wątpię, że to jest problem, ale to jedyna rzecz, która przychodzi do głowy zakładając, że twój kod jest w porządku. Założę się, że to zrobiłeś, ale spróbuj po prostu wydrukować język za pomocą NSLog zaraz po pobraniu go z ustawień narodowych i sprawdź, czy to nie jest reszta twojego kodu. – Mayjak

+0

Testowałeś to na iOS 5? Może to błąd systemu iOS 6? – Lefteris

+0

@Estarriol Dam twoją -AppleLanguage rzecz strzał po południu. Drukuję z NSLog zaraz po tym, jak otrzymam wartości, i zgłasza je jako "es" za pierwszym razem, gdy działa, a następnie "en", kiedy się nie udaje. Jeśli wyjdę z aplikacji, wszystko inne w iOS będzie nadal w języku hiszpańskim zgodnie z oczekiwaniami. –

Odpowiedz

7

W KOŃCU rozwiązałem ten problem po wielu miesiącach! Dziękuję wszystkim za pomoc (miałem też dobre relacje z deweloperem Apple za pośrednictwem kanałów programistycznych).

TL; DR: byłem przypadkowo synchronizowania preferencje językowe (wśród wielu innych niespodziewanych rzeczy) między urządzeniami za pomocą iCloud sklep wartość klucza mojej aplikacji (poprzez MKiCloudSync)! Czytaj dalej ...

Używam trzeciej klasy o nazwie MKiCloudSync, która pomaga zsynchronizować [NSUserDefaults standardUserDefaults] ze składnią wartości klucza iCloud mojej aplikacji. Moją intencją, kiedy zacząłem go używać, było umożliwienie obsługi niektórych ulubionych synchronizujących użytkownika w tle.

Nie rozumiem jednak, jak działa standardUserDefaults, ale nie zdawałem sobie sprawy, że istnieje wiele innych rzeczy zapisanych w standardUserDefaults innych niż moje własne niestandardowe ustawienia aplikacji!

Więc co się dzieje, było to:

  1. uruchomić aplikację po raz pierwszy. Świeży standardUserDefaults w miejscu, a wewnętrzny klucz "AppleLanguages", który przechowuje uporządkowaną listę preferencji językowych, jest poprawny w zależności od bieżących wyborów urządzeń.

  2. Aplikacja wyświetla się prawidłowo w wybranym języku.

  3. W tle MKiCloudSync synchronizuje WSZYSTKIE standardUserDefaults z usługą iCloud. I odwrotnie, gdybyś uruchomił tę aplikację w innym miejscu, powiedzmy przy użyciu urządzenia z ustawionym angielskim, urządzenie to zsynchronizowałoby ustawienia językowe z usługą iCloud. Teraz ta bieżąca aplikacja faktycznie ma nadpisane preferencje językowe.

  4. BOOM ... następnym razem, gdy aplikacja zostanie uruchomiona, niezależnie od tego, co wybrałeś na urządzeniu, jest to wszystko, co zostało ściągnięte z iCloud, które będzie używane jako domyślny język!

Co mam zamiar zrobić, aby rozwiązać problem z moim następnym app aktualizacji:

  1. Użyj forked version of MKiCloudSync który pozwala na synchronizację tylko białej liście kluczowych nazwisk.

  2. dodać kod, który zrobi porządki jednorazową, najpierw czyszczenie magazynu kluczy iCloud dla mojej aplikacji, a następnie (based on this SO answer), nazywając ten kod, aby przywrócić ustawienia domyślne użytkowniczki:

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

W moich testów do tej pory, tego typu rozwiązuje problem ... niestety, użytkownik będzie musiał ponownie uruchomić aplikację dla poprawki językowej kopać w. Jednak wydaje mi się, większość użytkowników nie występują ten problem, ponieważ jest mało prawdopodobne, aby używało wielu urządzeń z różnymi domyślnymi językami.

+0

Czy próbowałeś wyczyścić swój folder budowy? Cmd + opcja + shift + k – Danra

+0

To właśnie uratowało mi życie.W każdym razie są to klucze, które powinny zostać zignorowane: [[NSMutableSet setWithObjects: @ "AppleICUForce24HourTime", @ "AppleITunesStoreItemKinds", @ "AppleKeyboards", @ "AppleKeyboardsExpanded", @ "AppleLanguages", @ "AppleLocale", @ "NSInterfaceStyle" , @ "NSLanguages", @ "OpenUDID", @ "StatsDone", @ "UIDisableLegacyTextView", nil] zachowaj]; –

+0

@AndreiRadulescu Prawdopodobnie lepiej będzie dodać do białej listy klawisze, które chcesz zsynchronizować, ponieważ Apple może wprowadzić nowe klucze w przyszłości, co może spowodować inne nieoczekiwane problemy ... –

2

Testowałem twoje kroki na moim iPhone 5 bez problemów. Prowadzi mnie to do wniosku, że jest tu jeszcze coś innego: prawdopodobnie coś przeszkadza w sposobie, w jaki czytasz wartość locale.

Kroki polecam wziąć pomóc debugowania tego problemu są:

  1. post kompletny kod metody, w której jesteś uzyskanie wartości język preferowany. Upewnij się, że metoda jest wykonywana przy każdym uruchomieniu aplikacji.
  2. Upewnij się, że wpisywany kod zawiera lokalizację dyrektywy NSLog, której używasz do testowania ustawień języka.
  3. Czy po pierwszym uruchomieniu przechowujesz preferowany język w innym miejscu?
+0

Nawet rzeczy w moim kodzie, które nie używają jawnie wartości, którą wykrywam jako preferowany język, powracają do języka angielskiego. Na przykład mam zlokalizowane pliki Storyboard i pliki Localizable.strings, które działają w języku hiszpańskim przy pierwszym ładowaniu. Potem, gdy przejdzie na angielski, nawet te rzeczy się odwrócą. –

0

Czy przez przypadek używasz NSUserDefaults, aby zapisać coś związanego z językiem?

Look w katalogu App Simulator -> Biblioteka -> Preferencje -><YourAppBundleName>.plist

Patrz: How to force NSLocalizedString to use a specific language do opisu metody NSUserDefaults ustawiania języka.

Być może po prostu zapiszesz swój język, dzięki czemu funkcja wykrywania po prostu zwróci zapisaną wartość.

+0

Dzięki za odpowiedź. Nie używam NSUserDefaults do zapisywania czegokolwiek związanego z językiem. –

2

Spróbuj z następującego kodu:

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 

Ten kod działa doskonale, jak wspomniano. To zadziałało dla mnie, a ta gra to sklep z aplikacjami na żywo, jeśli chcesz sprawdzić (HueShapes).

+0

Doceniam twoją odpowiedź, ale jeśli czegoś nie brakuje, ostatecznie nazywasz '[[NSUserDefaults standardUserDefaults] objectForKey: @" AppleLanguages ​​"]', aby uzyskać język, który jest jednym z kilku połączeń, które już wypróbowałem, i wciąż doświadczam tego samego problemu ... działa po raz pierwszy (wraca z "es"), a następnie w kolejnych uruchomieniach się nie powiedzie (zwraca "en" zamiast, mimo że nigdy nie zmieniłem języka z powrotem na telefonie). –

+0

zmieniasz język w aplikacji lub w ustawieniach urządzenia, jeśli z aplikacji możesz udostępnić kod lokalizacji. –

+0

Z ustawień urządzenia. –

3

W ustawieniach-> ogólne-> międzynarodowe istnieje możliwość ustawienia języka lokalizacji itp. Jeśli ustawisz język, który próbujesz przetestować, zadziała, jeśli Twój kod jest poprawny.

+0

Tak, próbowałem to przetestować. Tak wybieram język, który testuję (w tym przypadku hiszpański). Jak opisano w moim pytaniu, działa to tylko za pierwszym razem. Kiedy raz uruchomię swój kod po raz drugi, to tak, jakby resetował język, mimo że reszta interfejsu telefonu pokazuje, że wciąż jestem ustawiony poprawnie na hiszpański. –

+1

To musi być spowodowane błędem Xcode, a następnie (spróbuj zaktualizować Xcode) – OnkaPlonka

+0

Spróbuję to i złożyć raport. Wygląda na to, że byłem w Xcode 4.5, a najnowsze wydanie to 4.5.2. –

Powiązane problemy