en.lproj/InfoPlist.strings
ja.lproj/InfoPlist.strings
(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
NSLocationWhenInUseUsageDescription is added in Japanese to Info.plist (within target build settings).
NSLocationWhenInUseUsageDescription is localized to English
CLLocationManager().requestWhenInUseAuthorization() is called
Then
If device language is English:
NSLocationWhenInUseUsageDescription is displayed in English on the location permission system dialog (correct behavior).
If device language is Japanese:
NSLocationWhenInUseUsageDescription is displayed in English on the location permission system dialog (incorrect behavior).
Expected behavior
If device language is Japanese:
NSLocationWhenInUseUsageDescription should 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.xcstrings in string catalog mode.
Right click the entry in the source language.
Click "Mark as Reviewed".
Option 2
Open InfoPlist.xcstrings in source mode.
Change all {sourceLanguage}.stringUnit.state values from new to translated.
Option 3
Remove NSLocationWhenInUseUsageDescription key from Info.plist or build settings.
Add NSLocationWhenInUseUsageDescription key manually to InfoPlist.xcstrings.
Fill in values for source language and other languages.
Note: {key}.extractionState for this case will be manual instead of extracted_with_value.
Option 4
Use older/deprecated InfoPlist.strings files 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 "テスト".