Different app-name depending on configuration when app-name is localized in InfoPlist.strings
Asked Answered
S

3

14

We use a setup with different plists for each configuration. Like this: Target-Info-Dev.plist, Target-Info-Beta.plist...

This way our configurations could have their own CFBundleDisplayName, and we can differentiate builds by app-name on device. Like this: "DEV Appname", "BETA Appname"...

However, now we are required to localize the app-name. We have done this by creating a localized InfoPlist.strings for each target:

"CFBundleDisplayName" = "<localized-appname>";
"CFBundleName" = "<localized-appname>";

But since the CFBundleDisplayName is no longer derived from Target-Info-[Configuration].plist, we cannot differentiate the app-name for different configurations.

It should be noted that we have several Targets as well, for different brands of the same app, but we already got that working by haveing a separate InfoPlist.strings for each target.

Anybody have an idea of how to accomplish both localized and configuration-based app-name?

Severalty answered 27/8, 2014 at 13:22 Comment(1)
Did you ever solve this, have exactly the same issueLibel
B
13

Better Solution

  1. Edit Info.plist, set CFBundleDisplayName's value to a variable named something like $(MY_DISPLAY_NAME)

enter image description here

  1. Open 'Build Settings' tab of the project or target, add a key named MY_DISPLAY_NAME under User-Defined section(you need scroll to the bottom to find this section), then just expand the newly-added key, and set any name for each configuration as you wish.

enter image description here

When building your project, every variable in the Info.plist will be replaced to its value.

The solution is much simpler than the original one.

Original Solution

I had the same requirement in my project, and then I found your question, and at last I solved it. Edit your projects' scheme, add pre-action and post-action script to execute your change. Like this,

Step 1. change app name in Build's Pre-actions

str=""
if [ "${CONFIGURATION}" == "Debug" ];then
    str="dev"
elif [ "${CONFIGURATION}" == "AdhocDevelopment" ];then
    str="dev"
elif [ "${CONFIGURATION}" == "AdhocDistribution" ];then
    str="adhoc"
elif [ "${CONFIGURATION}" == "DailyBuild" ];then
    str="rdm"
fi
perl -pi -e "s/appName[^<]*/appName${str}/g" ${PROJECT_DIR}/smd/Info.plist

enter image description here

Step 2. Restore app name in Build's Post-actions

perl -pi -e "s/appName[^<]*/appName/g" ${PROJECT_DIR}/smd/Info.plist
echo ${PROJECT_DIR}/${INFOPLIST_FILE} > ~/tmp.txt; rm -f ~/tmp.txt

Something to explain: Debug/AdhocDevelopment/AdhocDistribution/DailyBuild are your projects' configuration names; ${CONFIGURATION} is predefined by Xcode; perl is preferable to awk and sed, which are all pre-installed on every mac OS X.

By the way, what I have done is changing appName in Info.plist, you can change your infoPlist.strings. In this way, you just need a single Info.plist file.

Bronchial answered 6/5, 2016 at 8:36 Comment(3)
It took me a lot of elbow grease and trial-and-error to get this to work on our end for an InfoPlist.strings file, but I got it sorted out. perl -pi -e "s/NameInStringsFile[^\"]*/NameInStringsFile (Extra)/g" "${PROJECT_DIR}/path/to/InfoPlist.strings"Dilantin
How do you localize MY_DISPLAY_NAME?Music
AFAIK you can't localize MY_DISPLAY_NAME using this method. See my answer below for a way you can: https://mcmap.net/q/816551/-different-app-name-depending-on-configuration-when-app-name-is-localized-in-infoplist-stringsWandie
W
2

Since the file InfoPlist.strings is not just 1 single file, but is spread across multiple folders and files like so: en.lproj/InfoPlist.strings, de.lproj/InfoPlist.strings. It is a bit trickier to use it for different schemes. Here is how I localized the name of the Today Widget shared by 2 flavors / schemes of the same target. For demonstration purposes, I used 2 "flavors": TA and EC. I will refer to them in this answer.

Step 1:

  • Create folders for each "flavor" or scheme in the target directory. Name each folder exactly as they are named in your user-defined scheme. Copy there the InfoPlist.strings file.

This step might be tricky. What I did: I created a new folder in XCode and named it TA. I dragged & dropped there my InfoPlist.strings file, then browsed to that folder in Finder, duplicated that folder, and renamed it to EC. Then, I drag & dropped it into XCode. Don't add it to any target. It is not needed.

Step 2:

  • Remove the InfoPlist.strings from the target's Copy Bundle Resources build phase:

Click on your project name -> Select the widget's target (ex. Today Widget) -> go to Build Phases -> open the Copy Bundle Resources -> find the file InfoPlist.strings, select it and press Delete button

Step 3:

  • Add a new Run Script to copy the correct InfoPlist.strings file

Here is the script I came up with which will copy the correct file, based on the current flavor/scheme your app is running now:

for lng in en de es fr it nl pt-PT tr
do
  INFO_PLIST_FILE="${PROJECT_DIR}/TodayMatchesWidget/${APP_FLAVOR}/${lng}.lproj/InfoPlist.strings" 
  BUILD_APP_DIR="${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}" 
  FILE_LOCATION="${BUILD_APP_DIR}/${lng}.lproj/InfoPlist.strings" 
  cp "${INFO_PLIST_FILE}" "${FILE_LOCATION}"
done

This is a for loop, which iterates through all my localization languages. You need to put there only the languages that you support. Each language abbreviation should be separated by a space, nothing else.

The only variable which you need to take care of is APP_FLAVOR, which in my case is a user-defined setting inside the project's Build Settings, and in my case will be either TA or EC.

Here is the final folder structure in Today Widget's folder:

enter image description here

P.S: I assume you already have a InfoPlist.strings file in the target's directory. If not, just add a new Strings File and call it InfoPlist.strings and add this value inside:

CFBundleDisplayName = "My Localized Widget";

I hope it helps anyone out there!

Wooster answered 23/4, 2021 at 13:54 Comment(3)
I think it should be "CFBundleDisplayName"="My Localized Widget"; in strings fileCretic
@MostafaAlazhariy that is not necessary actually. Try it without the quotation marks and you'll see that it works just fine.Wooster
I tried it and it works. I voted your comment as a useful comment.Cretic
W
1

Here's how you can have different InfoPlist.strings for different build configurations in the same target, using only Build Settings and a few duplicate Info.plist files.

  1. In your Build Settings:
    • Specify a different Info.plist File (INFOPLIST_FILE) for each configuration.
    • Set Adjust Strings File Names for Info.plist (STRINGS_FILE_INFOPLIST_RENAME) to Yes. On Xcode 14, it was set to Yes by default.
  2. Create .strings files with the base name of your Info.plist filename + Plist.strings.
    • For example, if your Info.plist filename is Beta-Info.plist, your strings file should have the name Beta-InfoPlist.strings. Make sure you include all of these strings file to your build.
  3. Do not include an InfoPlist.strings file in your target.

The key to making this work is Adjust Strings File Names for Info.plist in the Build Settings Reference.

Adjust Strings File Names for Info.plist.
Setting name: STRINGS_FILE_INFOPLIST_RENAME

If enabled, renames .strings files whose basename matches that of the target’s Info.plist file, to InfoPlist.strings in the built product.

Example

Here's an example in my app which has 3 different variants (AdSupported, AdSupported-Dev, Pro) that require different app names.

  1. Build settings.

Build settings

  1. Strings files. They are all included in my target.

InfoPlist strings files

  1. Info plist files. As usual, they are specified in the Build Settings and NOT included in my target.

InfoPlist files

Wandie answered 5/10, 2022 at 1:8 Comment(3)
while doing this, what did you do to the target Info.plist entry? did you change that as well?Veal
Each target needs to have their own unique Info plist file, since that's how the .strings file with the actual name of the app is found. For the example in this answer, I have a specific info plist for each target.Wandie
Thanks, it worked for me after some tries. but it worked with me when I created the second scheme, but when I created the third one it did not work anymore and I got an error.Cretic

© 2022 - 2024 — McMap. All rights reserved.