(I resolved this issue but I still consider it a bug in Xcode. Hopefully any other poor soul that encounters it will find this post.)
Summary
When
- App default localization is e.g. Japanese
- Secondary localization is e.g. English
- InfoPlist.xcstrings is added to the target
NSLocationWhenInUseUsageDescriptionis added in Japanese to Info.plist (within target build settings).NSLocationWhenInUseUsageDescriptionis localized to EnglishCLLocationManager().requestWhenInUseAuthorization()is called
Then
- If device language is English:
NSLocationWhenInUseUsageDescriptionis displayed in English on the location permission system dialog (correct behavior).
- If device language is Japanese:
NSLocationWhenInUseUsageDescriptionis displayed in English on the location permission system dialog (incorrect behavior).
Expected behavior
- If device language is Japanese:
NSLocationWhenInUseUsageDescriptionshould be displayed in Japanese on the location permission system dialog.
Root cause
The json representation of InfoPlist.xcstrings is the following after following the above procedure:
{
"sourceLanguage" : "ja",
"strings" : {
"NSLocationWhenInUseUsageDescription" : {
"comment" : "Privacy - Location When In Use Usage Description",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "test"
}
},
"ja" : {
"stringUnit" : {
"state" : "new",
"value" : "テスト"
}
}
}
}
},
"version" : "1.0"
}
After building, Xcode creates the key NSLocationWhenInUseUsageDescription.ja.stringUnit.state with the value new, and the value as テスト (the automatically extracted value from Info.plist).
At runtime, iOS ignores ja.stringUnit.value and falls back to en.stringUnit.value when:
NSLocationWhenInUseUsageDescription.localizations.ja.stringUnit.state == "new"NSLocationWhenInUseUsageDescription.extractionState == "extracted_with_value"
Additionally, Xcode's "String Catalog" interface for xcstrings files does not show the new state value in the interface and does not allow ja.stringUnit.value to be modified.
Fixes/Workarounds
Option 1
- Open
InfoPlist.xcstringsin string catalog mode. - Right click the entry in the source language.
- Click "Mark as Reviewed".
Option 2
- Open
InfoPlist.xcstringsin source mode. - Change all
{sourceLanguage}.stringUnit.statevalues fromnewtotranslated.
Option 3
- Remove
NSLocationWhenInUseUsageDescriptionkey fromInfo.plistor build settings. - Add
NSLocationWhenInUseUsageDescriptionkey manually toInfoPlist.xcstrings. - Fill in values for source language and other languages.
- Note:
{key}.extractionStatefor this case will bemanualinstead ofextracted_with_value.
Option 4
- Use older/deprecated
InfoPlist.stringsfiles instead of.xcstrings.
InfoPlist.xcstrings after fix
{
"sourceLanguage" : "ja",
"strings" : {
"NSLocationWhenInUseUsageDescription" : {
"comment" : "Privacy - Location When In Use Usage Description",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "test"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "テスト"
}
}
}
}
},
"version" : "1.0"
}
Reproduceable Environment
- Xcode 15.4 / iOS 17.5
- Xcode 16 beta 5 / iOS 18
- Simulator
- Device
Screenshot of bug
"test" should be "テスト".