I have a project with 3 targets. Each target needs to suppport only one language, but the language is not the same for each target.
Currently I have
Target 1 (es)
Target 2 (es)
Target 3 (pt)
Most of my strings are in a Localizable.strings file, and I simply target a different file for each target. However, a number of strings are in my storyboards. My problem is that it does not seem possible to create different storyboard localization files for each target. If I change the targeting of the portuguese file, the targeting of the spanish file changes automatically.
A possible solution is to duplicate each Storyboard for each target, but this won't scale well as the number of tagets grow. I could also modify all the text with NSLocalizedString in each ViewController, but this seems tedious and error prone.
Is there a better solution?
Shared Storyboard across targets
While this answer is the preferred approach, you can assign different Storyboard localizations to different targets, while sharing the same Storyboard across all targets.
Prerequisites:
Follow this instructions in this answer.
Concept:
You want to have the Main.storyboard in each target, but a different Main.strings in each target. Additionally, you do not want all localizations to be available in each target.
To achieve this, you must manipulate the .lproj directly, a process which is hidden when merely using the File Inspector.
Step by step:
Create all the pieces by following the steps in this answer.
From any target, remove the Main.storyboard. Of course, select Remove Reference to keep the storyboard around.
In the Finder, locate Base.lproj. Drag and drop Main.storyboard back to your project, and select every target.
In the File Inspector, ensure that the languages are not selected, and that you are still using Localizable Strings.
In the Finder again, locate en.lproj, es.lproj, fr.lproj, etc. Notice that they each contain a version of Main.strings. Drag these .lproj (the entire directories) back into your project. This time, do not select any target
One last time, in File inspector, associate each Main.strings to the desired target. Repeat for each .strings.
Conclusion
By decoupling the .lproj from the .storyboard in the Project Navigator, you can associate files and targets freely.
Demo:
See it at work using a French target, on a device with language set to Français in the Settings:
► Find this solution on GitHub and additional details on Swift Recipes.
Shared localizations across targets
Assuming you already have multiple languages in your project, in the Project Navigator, select your storyboard (say Main.storyboard)
In the File Inspector, under Localization, add English. Pick Localizable Strings which is the default. This will create a Main.string for each language, and share your Storyboard across all languages.
Merely clicking that checkbox in step 2. will add a Main.string (English) for that language, specifically for that Main.Storyboard. Pay special attention to the new hierarchy, these are not Localizable.strings but Main.strings, derived from Main.storyboard:
Localize in each language file to your heart content.
For example, starting with a UILabel which message was in Esperanto, it will appear in English when the device runs in English:
/* Class = "UILabel"; text = "Tiu mesaĝo estas en Esperanto"; ObjectID = "acC-pA-eMt"; */
"acC-pA-eMt.text" = "This message is in English";
Start here to add multiple languages to your project:
In the event you need to add more languages, follow these steps:
In the Project Navigator, select your Project
In the Project and Target List, select, once again, the Project
Select the Info tab
Under Localizations, keep Use Base Internationalization (unless your UI itself must change across languages)
Click +, pick a new language. In the dialog presented to you, select every Storyboard you want to have multiple localizations for.
If you missed Storyboards at Step 5. you can simply add a new language to that a storyboard by following the steps in Assuming you already have multiple languages.
All you need: to make common xcode workspace for your app, then to create a duplicates of main xcodeproj file for your set of languages and make different targets for all of them, also then you can set language for individual project settings in new xcodeproj's. Also you easy can tune build phase 'Copy Bundle Resourses' and others. I use this method. If you have a Xcode's crash during adding project in workspace - open project with Xcode, rename it and rename or duplicate targets (I think same names cause this issue).
Related
Usually adding a new language in a project is easy. I'm in the project tab, I press on "+" in the Localizations area, and then I choose the language that I need to add. It asks me which files I want to translate, I choose them, I press finish and then nothing. The new language won't appear. The project that I'm working on is full of frameworks and sub-projects. I didn't create it, so I don't know its full history.
In the end I fixed it by manually creating an "el.lproj" folder (for adding Greek) and copying the Localizable.strings from another language. Then I moved it into my project and it magically appeared in the localizations tab. I think it's kinda of a bug.
My Xcode is v10 and I'm developing a custom intent for SiriKit, targeting iOS 12.
In Xcode 10, custom intents are designed in .intentdefinition files, where you can define your own parameters for intent phrases as well as the title of the intent and Siri shortcut for that intent. Building a project with a .intentdefinition file makes Xcode automatically generate an INIntent derived class for that intent.
My issue is that in order to support other languages than English so that the intent's title is show in the system's language in General > Siri & Search when the user is able to manipulate shortcuts for custom intents, I need to provide localized intent title for my .intentdefinition file.
When I try to add another language for my .intentdefinition file in the File Inspector and then build the project I get:
duplicate output file '/Users/.../IntentDefinitionGenerated/Intents/MyCustomIntent.swift' on task: IntentDefinitionCodegen /Users/.../ru.lproj/Intents.intentdefinition
This is likely happening because Xcode sees multiple .intentdefinition files in .lproj folders and tries to generate a same named class for each of them.
How do I localize my .intentdefinition file for iOS 12?
Go to intentdefinition file -> File Inspector -> Select Localize -> Now select current language for your intentdefinition file.
This will convert your existing intentdefinition file for current language.
Now again select the same intentdefinitionfile, add other language -> it will create a new Intents.strings file where you can customize the text for other locales.
I had the same issue as #desmond-hume. In my case, I have an old xcode project that already contained some localizations before "Base" was available. The initial .intentdefinition file must be added as the Base localization. From there, further localization can be added and Xcode will add only a .strings file for each localization.
Without a base localization, Xcode adds a new .intentdefinition for each localization which causes the "multiple commands produce...." error.
You can add a Base localization under the main project settings via a checkbox.
Some old projects (like mine) may also run into this issue:
iOS - Using Base localization pane is always empty
It looks like you've already localized your Intent Definition file (since Xcode has put it into a ru.lproj folder) so the problem might be that you've two copies of the file in the "Compile Sources" build phase.
Go here:
Project -> App target -> Build Phases -> Compile Sources
and look for duplicate entries. If you find a duplicate, delete one of the copies
You can also try Editor > Validate Settings… to find duplicates
You can also try cleaning the build
I've recently Localised the intents for my App, however after the original localisation, I added another Intent.
In Xcode 10.2.1 at least that I've checked, there is an "Export for Localization" option when you select the top level of your project.
It will ask you to save the output.
When you investigate your output, you should see an .xcloc folder for EACH of the languages you support.
Dig down to the .xliff under "Localized Contents" and open it.
There you will find your treasure trove of the items and you're looking for and you're looking for items that don't have a 'target'
The engineers at Apple at dub dub showed me this, however I personally wasn't happy of this process, as you have to edit it, and then re-import it (assuming you send off your files to a translator and get an .xliff back.
The annoyance though with Intents is the fact that it uses arbitrary IDs and not something legible
I haven't found an easier way (yet) to locate the missing translations.
Hope this helps!
you must be Project->info checked "Use Base Internationalization"
Next use the top answer method to create
How can I use container apps localized strings from shared extension in Swift. I have already added containers strings files into extension -> build phase -> compile sources but its still not working. Should I set anything in configuration? From main container app strings are translated but from shared extension it shows only the string keys/ids for texts.
You need to change target membership of the Localizable.strings file. Select Localizable.strings in the Project Navigator on the left, then open File Inspector on the right and add checkmark next to your extension target in the "Target Membership" field.
There are a couple things to check:
One is the solution offered here by #ovejka - click on your string
localization file and ensure, in the rightside settings pane, that
the file applies to your widget as well as your main app (target
membership).
Another is to ensure that your storyboard strings file, which should
have been created automatically when you added a second language to
your app, has the proper translations.
If neither of those work, given that a widget is quite small and
likely only has few labels, you could add a switch statement to 'viewWillAppear' to translate each label based on the detected language
Finally, none of those seemed to be working for me in the simulator or even by switching the schema language and running it on my actual phone.
It turns out, it was working all along and the simulated language wasn't applying to the widget. I turned my actual phone's language to Spanish, run the new version of my app, and the widget was translated.
I have 2 Apps : Free & Full
I have 2 Languages : English & German
This results in 4 different App-Names
How can I achieve this.
Actually all my targets have the name "Free" in it, even it the the Full Version.
I know:
I have 1 InfoPlist.strings File, which is multiplied by Localization and I can assign them to targets. So for 1 App I can localize the BundleDisplayName.
But how can I assign the specific names for the second app ?
PlistBuddy is your friend here. What you need to do is update your plist in a build time.
You have to create custom scheme for every target you have (I assume you are already has that)
In your xcode go to scheme and add post action like that to custom scheme target:
Here is the code:
infoplist="$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH"
/usr/libexec/PlistBuddy -c "Set CFBundleName some_new_name_here" "$infoplist"
Important thing with this approach is that you're not change nothing in your plist file but with post-actions you already changing the packet prepared for device, so you keep your code repository nice and clean.
Associate InfoPlist.strings to targets
From the Apple Developer Technical Notes:
If your app supports localization, be sure to localize CFBundleDisplayName by adding it to all your language-specific InfoPlist.strings files. Furthermore, be sure to use a name that complies with the App Review Guidelines for your app.
Prerequisites
I am assuming you already have multiple targets.
I am also assuming you already have an InfoPlist.strings file. If your do not, code > File > File... > Resource > Strings File > Next > Save As: InfoPlist > Base.lproj > Target: the english target > Create
Ensure you have enabled this in your Info.plist:
<key>LSHasLocalizedDisplayName</key>
<true/>
Step by step
In Project Navigator, select InfoPlist.strings.
In File Inspector > Localization, select all the languages. This will create and/or copy said InfoPlist.strings into their respective locations.
Would you want to add languages, you achieve this in Project Navigator > project > Project & Target List > Project > Info > Localizations > +. Again, keep Use Base Internationalization.
Unfortunately, when you execute step 2., Xcode does all the magic for you. It is worth noting that in versions of Xcode where that magic did not happen, you had to do the associations by hand. Step 5. is about reverting the magic.
Remove InfoPlist.strings from the Project Navigator. Of course, only Remove References when prompted.
In the Finder, locate en.lproj, drag it onto your Project Navigator, pick Create Groups, add to target your English, or Base target, Finish
Repeat step 6 with de.lproj, fr.lproj, each time dragging the entire .lproj from the Finder, and associating with the appropriate target.
Some .lproj may contain other localized files for which you want to enjoy the magic of step 3. Simply remove their references.
You are done.
The final setup, for say the German language, will look like this in the File Inspector:
References:
Share localization across targets:
This is the general method to achieving localization. See https://stackoverflow.com/a/33749062/218152.
Specific localization to specific targets:
This is only useful if you want to explicitly control which languages go into which target. See https://stackoverflow.com/a/33791181/218152.
I deleted the Localizations of the project from the project's info by mistake. Both the storyboard and the related language were removed.
I got back the storyboard from previous file but when I want to add a new Localization, a window popped out and asked me to "Choose files and reference language to create English localization" and there is no resource file at all.
How can I add back the localizations?
Adding back a localization
When you delete your localizations sometimes you can get that situation where you can't add back any localizations in Xcode. Go to the command-line and create a ISO 639-1 two-letter language abbreviation folder with the lproj extension somewhere within your project.
Create an empty language folder
For example:
${SRCROOT}/Resources/Translations/nb.lproj
or
${SRCROOT}/Resources/Translations/en.lproj
Re-add language files to project
In the folder create an empty file called Localizable.strings and add this file to your project. Don't add the .lproj folder, just the contents. Then when you go back into the project file you will see the language under localizations. Now when you have added this, you should see the localization in your project.
No checkbox
If the added file, like a storyboard, doesn't have a checkbox next to it indicating that is part of that language localization you might need to round trip them through another language. To do this add a new language in the project. It should prompt you to copy the existing localized files over to the new language. Then delete the broken localization and re-add it.
My Example
As a specific example, I added the storyboard in the nb.lproj directory to the project. The Norwegian Bokmål appears in the project, but the checkbox for the language in the storyboard inspector won't let me add it. I created nb_NO in the project and it prompted me to copy over the storyboard. Then the storyboard had that checkbox checked. I deleted the 'nb' localization and re-added it. Now everything was the way I wanted it.
I had to solve same problem, and found one solution:
You need to find in finder your *.xcodeproj file and open it as container (ctrl+click on it and you will see it in context menu)
Here you can see project.pbxproj file, open it in Xcode. Its large (but still readable file).
(it will be better to make some copy on save spot, before you start)
Now its the task to add the missing language to this file, and its done.(U can try it on other project with localizations).
There is paragraph you need to add. Search in this file for this /* End PBXSourcesBuildPhase section */(its paragraph right before localization paragraph which is missing) and add something like this after:
/* Begin PBXVariantGroup section */
27548D921611B0BE008EA1CD /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
27548D941611B0BE008EA1CD /* en */,
);
name = Localizable.strings;
path = ../Code;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
You have to do some changes first. Look at the long number 27548D921611B0BE008EA1CD, its ID of the localization file (or some xib file, or other localizable file...), if you dont have any in the procject, just add some Localizable.string file to the project, reopen(or refresh) this project.pbxpro, and find this Localizable.string you should find something like this:
275490591611B0BE008EA1CD /* Localizable.strings in Resources */
and this is it what you need to replace in localization paragraph
also you need to do right settings on path parametr and sourceTree. This twos are readable in fileinspector in xcode.
The "sourceTree" param is Location - mostly its relative to group so sourceTree = "<group>";
The path is path relative from the group to the file (if you dont know, try to make some localization files in different project and look at project.pbxpro, what all this works)
After this you can save project.pbxpro, and you should see in xcode info section "en" localization and you can add more localizations and all other localization stuff.
In xcode 6, do the following:
With the command line, create the following directory/file structure somewhere outside your project directory:
/en.lproj/InfoPlist.strings
/en.lproj/Localizable.strings
In Xcode, open your project and choose File>Add Files to ProjectName to add the recently created en.lproj directory.
After that, you will see English in the Localizations list.
This is an old topic, but after having this issue, and then trying the solution (and having it not work exactly), I thought I'd give details on what DID work.
Like the original poster, I accidentally deleted all of my localizations and was given no obvious recourse in Xcode-- in the project settings under Info it simply said 'this project has not been localized', and when I clicked on the plus button beneath, a blank list of resource files was presented.
I followed #Cameron's guide but found that language folders with Localizable.strings files were already present in Finder, but weren't being acknowledged by Xcode. I couldn't decide how to proceed, but I happened to see an unrelated comment about adding files to Xcode, so I tried adding the existing en.lproj folder and its Localizable.strings file.
This worked, and the listing for English as the development language appeared under Info as well.
Hopefully this will help anyone who experiences the same problem!
Simply create a Folder "Base.lproj" in finder and paste the Xib you want to localize inside it, and add this folder to your project. Now you can able to add other languages without issue.
I've followed a similar approach of #user2070775 reply.
Firstyl when you delete Storyboard and Launchscreen to use your own creation or code programmatically, on Localization you might get similar following empty screen.
Then firstly you should know the language code for example to use French localization its fr etc
With project folder in the Project Navigator you must add New Group -> {LANGUAGE_CODE}.lproj. And then you should add New File -> Strings File -> Localizable.strings. In the #user2070775 answer, also InfoPlist.strings file has added so I added too for now.
In the Localizable.strings file you can add <KEY> = <VALUE> pairs for string to localizated.
Our pair is "this-is-key" = "and-this-is-value-for-spesific-language-on-localizable-string"; for now.
HINT: In key-value pair, when I did not put the semicolon, the XCode
gives error for this situation.
Until now, the following project scheme, must the result of you have.
Additionally, when you looked at the Project -> Info -> Localizations the French or etc. language must be added like in the following image.
TESTING
Basically you can get the results of the what've you done
The remaining part can be set from the Simulator. You must change the simulator language, for this answer the correct one is French.
Go to Settings -> General -> Language & Region -> French and run the project again.