Software localization

Automating iOS Storyboard Localization

This guide will guide you through an automated approach to storyboard localization for iOS in Xcode If your iOS app has several storyboards.
Software localization blog category featured image | Phrase

It’s easy to integrate automated translation into your app using our translation workflow or – if you’re okay with a manual step in your workflow – by using XLIFF – as explained in this tutorial.

Our Setup

We use this folder structure for our apps:

  • Application/
  • Controllers/
    • Controller1/
      • Controller1.storyboard
    • Controller2/
      • Controller2.storyboard
    • Controller3/
      • Controller3.storyboard
  • Library/
  • Models/
  • Ressources/
    • Scripts/
    • Localizations/
      • Localizable.strings
      • InfoPlist.strings
  • Vendors/

Our languages are en, es, fr and de.

The Script

The task is to automate the extraction of strings and the push & pull of all .strings files to/from the Phrase translation center. So we created the UpdateTranslations.shscript that takes care of it. You can run this script at any point in your deployment process (e.g. during your build phase).

In the first part of the script we are going to push the storyboard .strings files with a tag to Phrase. This way we can easily pull back only the needed translation keys afterwards. Part 2 of the script is basically the push of new translation keys to Phrase and the pull of translations. (See [our workflow] for details)

phraseapp_push_pull flowchart | Phrase

Script Config

 # The path to your standard Localizations.strings file


 # The path to your controllers folders (assuming you follow these naming conventions:


 # The languages that you want to translate

 languages=(de en es fr)

 # Your controllers that contain storyboards

 storyboards=(Controller1 Controller2 Controller3)

Part 1: Storyboard Translation

 # For each storyboard

 for storyboard in ${storyboards[@]} ; do

   # Push english translation file

   phrase push ${controllersPath}/${storyboard}/en.lproj/${storyboard}.strings --locale=en --tags=${storyboard}

   # Pull language translations and clean and rename folders for each language

   for language in ${languages[@]} ; do

     # Pull translation files into storyboard folder

     phrase pull ${language} --target=${controllersPath}/${storyboard}/ --format=strings --tag=${storyboard}

    # Clean and rename

    if [ -f ${controllersPath}/${storyboard}/${language}.lproj/Localizable.strings ] ; then

      rm -f ${controllersPath}/${storyboard}/${language}.lproj/${storyboard}.strings

      mv ${controllersPath}/${storyboard}/${language}.lproj/Localizable.strings ${controllersPath}/${storyboard}/${language}.lproj/${storyboard}.strings




Part 2: Push And Pull The Standard Translation Files

# Generate new entries in Base locale for new translation keys

find ./ -name "*.m" -print0 | xargs -0 genstrings -o ${localizationsPath}/Base.lproj

# Push to PhraseApp

phrase push ${localizationsPath}/Base.lproj/Localizable.strings --locale=Base --tags=Localizable

phrase push ${localizationsPath}/Base.lproj/InfoPlist.strings --locale=Base --tags=InfoPlist

# Pull from PhraseApp

phrase pull --target=${localizationsPath} --format=strings


It’s a little bit laborious to achieve this fully automated solution. But since a manual solution with XLIFF files was not an option for our processes, we needed this. The Phrase API documentation helped us to create a custom workflow that fits our needs.

You can find the complete script here.