Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode Localizable.string multiple targets issue

I have a project with multiple targets, which represent the same app just with different styling and translations.

Since almost whole project looks the same for each target, I need to have just few strings in Localizable.strings file, that I need to be different. And I don't want to copy whole huge Localizable.strings file to each project just because of the fact it has few lines different.

It is required for me to have just 1 strings file because of third-party libraries/SDK that are included in project. So I cannot use tableName for localizedString.

The problem is - I need to have a flexible possibility to override just few lines from Localizable.strings for each target separately. And I don't like the idea just to copy whole file to each target, cause it will lead to annoying flow in the future, in case I will have 10 targets and I need to add 1 string to all of them.

The goal is to have 1 huge Localizable.strings file with all strings included, that would be common for all targets, and have small configuration for each target for the strings that should tell different. So target's file should kinda merge and override the one that is common.

AFAIK it is not natively supported by Xcode, so I'm probably looking for a script that would make it works.

So, script should look into common and target's Localizable files, merge them, and in case some keys are defined in both, then it should use the one from target's file.

Can anyone help me with such script?


P.S. Similar issue exists with .xcassets, and CocoaPods solves it by merging multiple assets into 1, and it works as expected - if some targets has an asset containing the image with the same name that is already included into a common asset, then the one from target will replace it.

P.S.2. Similar feature is natively supported for Android devs - each image, each translations can be overridden by "child" flawor, or whatever it is called :)

like image 644
Stas Ivanov Avatar asked Jul 24 '17 11:07

Stas Ivanov


1 Answers

TL;DR:

Example project: https://github.com/JakubMazur/SO45279964


OK, the easier thing to do would be shell/python script, because it will work for every build server. I assume that you have a different scheme for each target (otherwise it will make no sense). So what you can do is:

Let's say your target is named:

  • target1
  • target2
  • target3

1) Create separate files contains all the strings that should be different (i will put it under Localizable directory.

Your Localizable.strings file may look like this:

"someGeneralString" = "General string 1";
"AppName" = "This is a string that you probably need to change";
"someOtherGeneralString" = "General string 2";

And any of your targetX.strings file may look like this:

"AppName" = "target[x]"

And here is how it should look like in your project:

enter image description here

Note that your target localizable files should has target membership set only to one target, but your Localizable.strings should be for all targets!

That's all for project configuration. Let's go to scripting (I will use python for that):

#!/usr/bin/python

import sys

supportedLanguages = ["en","pl"]
commonPath = ".lproj/Localizable.strings"
keys = ["AppName"]

    class CopyLocalizable():

        target = ""

        def __init__(self,arg):
            self.target = arg
            self.perform()

        def perform(self):
            for lang in supportedLanguages:
                pathToLocalizable = lang+commonPath
                textToFile = ""
                with open(pathToLocalizable,"r") as languageFile:          
                    for line in languageFile.readlines():
                        for key in keys:
                            if key in line:
                                textToFile += self.foundAndReplace(key,lang)
                            else:
                                textToFile += line
                self.saveInFile(pathToLocalizable,textToFile)


        def foundAndReplace(self,key,lang):
            pathToTargetFile = "Localizable/"+lang+".lproj/"+self.target+".strings"
            with open(pathToTargetFile,"r") as targetFile:
                for targetLine in targetFile.readlines():
                    if key in targetLine:
                        return targetLine

        def saveInFile(self,file,stringToSave):
            with open(file,"w+") as languageFile:
                languageFile.write(stringToSave)

You can optimize it yourself. It's easier script i can think about to get a job done.

And in the end let's automate it a bit: - Go to your target - add a new build phase - Add a new script:

export PATH="/usr/local/bin:$PATH"
cd SO45279964/
python localize.py target[x]

and watch a magic happen ;)

http://www.giphy.com/gifs/26n6NKgiwYvuQk7WU

Here you can find example project that I've created to run this example: https://github.com/JakubMazur/SO45279964

like image 139
Jakub Avatar answered Sep 28 '22 06:09

Jakub