Instantly share code, notes, and snippets.

What would you like to do?
Detect ISO 681 Language Code from String and Convert to BCP 47 Language Code
static NSString * BCP47LanguageCodeFromISO681LanguageCode(NSString *ISO681LanguageCode) {
if ([ISO681LanguageCode isEqualToString:@"ar"]) {
return @"ar-SA";
} else if ([ISO681LanguageCode hasPrefix:@"cs"]) {
return @"cs-CZ";
} else if ([ISO681LanguageCode hasPrefix:@"da"]) {
return @"da-DK";
} else if ([ISO681LanguageCode hasPrefix:@"de"]) {
return @"de-DE";
} else if ([ISO681LanguageCode hasPrefix:@"el"]) {
return @"el-GR";
} else if ([ISO681LanguageCode hasPrefix:@"en"]) {
return @"en-US"; // en-AU, en-GB, en-IE, en-ZA
} else if ([ISO681LanguageCode hasPrefix:@"es"]) {
return @"es-ES"; // es-MX
} else if ([ISO681LanguageCode hasPrefix:@"fi"]) {
return @"fi-FI";
} else if ([ISO681LanguageCode hasPrefix:@"fr"]) {
return @"fr-FR"; // fr-CA
} else if ([ISO681LanguageCode hasPrefix:@"hi"]) {
return @"hi-IN";
} else if ([ISO681LanguageCode hasPrefix:@"hu"]) {
return @"hu-HU";
} else if ([ISO681LanguageCode hasPrefix:@"id"]) {
return @"id-ID";
} else if ([ISO681LanguageCode hasPrefix:@"it"]) {
return @"it-IT";
} else if ([ISO681LanguageCode hasPrefix:@"ja"]) {
return @"ja-JP";
} else if ([ISO681LanguageCode hasPrefix:@"ko"]) {
return @"ko-KR";
} else if ([ISO681LanguageCode hasPrefix:@"nl"]) {
return @"nl-NL"; // nl-BE
} else if ([ISO681LanguageCode hasPrefix:@"no"]) {
return @"no-NO";
} else if ([ISO681LanguageCode hasPrefix:@"pl"]) {
return @"pl-PL";
} else if ([ISO681LanguageCode hasPrefix:@"pt"]) {
return @"pt-BR"; // pt-PT
} else if ([ISO681LanguageCode hasPrefix:@"ro"]) {
return @"ro-RO";
} else if ([ISO681LanguageCode hasPrefix:@"ru"]) {
return @"ru-RU";
} else if ([ISO681LanguageCode hasPrefix:@"sk"]) {
return @"sk-SK";
} else if ([ISO681LanguageCode hasPrefix:@"sv"]) {
return @"sv-SE";
} else if ([ISO681LanguageCode hasPrefix:@"th"]) {
return @"th-TH";
} else if ([ISO681LanguageCode hasPrefix:@"tr"]) {
return @"tr-TR";
} else if ([ISO681LanguageCode hasPrefix:@"zh"]) {
return @"zh-CN"; // zh-HK, zh-TW
} else {
return nil;
static NSString * BCP47LanguageCodeForString(NSString *string) {
NSString *ISO681LanguageCode = (__bridge NSString *)CFStringTokenizerCopyBestStringLanguage((__bridge CFStringRef)string, CFRangeMake(0, [string length]));
return BCP47LanguageCodeFromISO681LanguageCode(ISO681LanguageCode);

This comment has been minimized.

Copy link

loretoparisi commented Nov 11, 2015

First, thanks for this piece of code. That's great.
It seems that in iOS9.1 can cause the issue

2015-11-12 00:04:32.701 Speech Synthesizer[72300:1113005] BCP-47 Language Code: ja-JP Speech rate:[0.000000, 1.000000]
2015-11-12 00:04:32.707 Speech Synthesizer[72300:1113005] |AXSpeechAssetDownloader|error| ASAssetQuery error fetching results (for Error Domain=ASError Code=21 "Unable to copy asset information" UserInfo={NSDescription=Unable to copy asset information}

when getting the voice from a language that is not the device language. See here:

This seems to be addressed in the Apple's Forums as well:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment