Speech Synthezis API: какая локаль используется NSLocalizedString?

Я хочу использовать новый API синтезатора речи iOS 7, и мое приложение локализовано на французском и английском языках.

Чтобы это сработало, необходимо локализовать 2 вещи:

  • текст речи: я помещаю его в обычный localizable.string файл и получаю его в коде с помощью макроса NSLocalizedString.

  • язык речи: AVSpeechSynthesisVoice должен быть выбран для соответствующего языка.

Метод создания класса AVSpeechSynthesisVoice voiceWithLanguage:(NSString *)lang. В настоящее время я использую [NSLocale currentLocale].localeIdentifier в качестве параметра для этого метода.

Проблема: если язык устройства пользователя - португальский, [NSLocale currentLocale] выберите португальское произношение, а текст, разрешенный NSLocalizedString, - английский.

Как я могу узнать, какой языковой стандарт в настоящее время читает NSLocalizedString?


person Vinzzz    schedule 21.02.2014    source источник


Ответы (2)


Хорошо, мне наконец удалось разобраться в API Apple:

  • [NSLocale currentLocale]: НЕ возвращает текущий язык, выбранный пользователем в меню «Настройки»> «Основные»> «международный», но возвращает код региона, выбранный пользователем на том же экране.

  • [NSLocale preferredLanguages]: В этом списке ДЕЙСТВИТЕЛЬНО указывается язык устройства, это первая строка в этом списке

  • [[NSBundle mainBundle] preferredLocalizations] возврат языкового пакета разрешен приложением. Думаю, это то, что использует NSLocalizedString. В моем случае у него только 1 объект, но мне интересно, в каких случаях у него может быть больше одного.

  • [AVSpeechSynthesisVoice currentLanguageCode] возвращает предопределенный системой код языка.

  • Метод создания класса [AVSpeechSynthesisVoice voiceWithLanguage:] требует полного языкового кода: с языком И регионом. (например: передача ему @ "en" вернет объект nil, ему требуется @ "en-US" или @ "en-GB" ...)

  • [AVSpeechSynthesisVoice currentLanguageCode] дает голос по умолчанию, определяемый ОС.

Вот как выглядит мой окончательный код

 // current user locale (language & region)
    NSString *voiceLangCode = [AVSpeechSynthesisVoice currentLanguageCode];
    NSString *defaultAppLang = [[[NSBundle mainBundle] preferredLocalizations] firstObject];

    // nil voice will use default system voice
    AVSpeechSynthesisVoice *voice = nil;

    // is default voice language compatible with our application language ?
    if ([voiceLangCode rangeOfString:defaultAppLang].location == NSNotFound) {
        // if not, select voice from application language
        NSString *pickedVoiceLang = nil;
        if ([defaultAppLang isEqualToString:@"en"]) {
            pickedVoiceLang = @"en-US";
        } else {
            pickedVoiceLang = @"fr-FR";
        }
        voice = [AVSpeechSynthesisVoice voiceWithLanguage:pickedVoiceLang];
    }


    AVSpeechUtterance *mySpeech = [[AVSpeechUtterance alloc] initWithString:NSLocalizedString(@"MY_SPEECH_LOCALIZED_KEY", nil)];
    frontPicUtterance.voice = voice;

Таким образом, пользователь из Новой Зеландии, Австралии, Великобритании или Канады получит голос, наиболее соответствующий его обычным настройкам.

person Vinzzz    schedule 21.02.2014
comment
Я думаю, что [NSLocale preferredLanguages] лучше, потому что приложение может быть не локализовано на экзотический язык, но TTS доступен на устройстве - person djdance; 02.12.2014

Ответ Винзца был отличным началом - я обобщил его для работы с любым языком:

NSString *language = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];
NSString *voiceLangCode = [AVSpeechSynthesisVoice currentLanguageCode];
if (![voiceLangCode hasPrefix:language]) {
    // the default voice can't speak the language the text is localized to;
    // switch to a compatible voice:
    NSArray *speechVoices = [AVSpeechSynthesisVoice speechVoices];
    for (AVSpeechSynthesisVoice *speechVoice in speechVoices) {
        if ([speechVoice.language hasPrefix:language]) {
            self.voice = speechVoice;
            break;
        }
    }
}
person Nestor    schedule 23.05.2014