(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 EnglishCLLocationManager().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 fromnew
totranslated
.
Option 3
- Remove
NSLocationWhenInUseUsageDescription
key fromInfo.plist
or build settings. - Add
NSLocationWhenInUseUsageDescription
key manually toInfoPlist.xcstrings
. - Fill in values for source language and other languages.
- Note:
{key}.extractionState
for this case will bemanual
instead ofextracted_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 "テスト".