Continuous integration in multilingual mobile application
Have you ever developed multilanguage iOS app? How did you handle translations? Did you work with the client on translations? I hope you didn’t have any problem with things mentioned about, but we had ;) We used to struggle with them in every next project. That leaded us to the idea to improve that process. We share our solution with you just below.
How it looked in the past vs how it looks now
Process looked like that:
- We had shared google docs, for example https://drive.google.com/a/valueadd.pl/file/d/0B62idhNgYYfoT3FpNzROV1JNZ28/view?usp=drivesdk
- Client or person responsible for the translations had to fill it in Google Docs
- Developer needed to update the translations by hand (copying and pasting each line)
- Xcode release was being done manually (the endless and monotonous clicking)
- Doing manual release in Testflight. Need to click publish in the portal etc.
- Done! After about an hour the work was finished.
As you see it wasn’t really automatic.
That’s how it looks now
- Write fastlane testflight in console. Process is being done in the background
- Whole process takes 1 min of Developer’s time.
How it works
We have developed new flow using fastlane.tools, localise.biz and Jenkins (it’s not about our Hedgehog). It requires only one command to start deployment.
For the start we need to install fastlane `gem install fastlane` and `fastlane init` in the project directory. More about fastlane itself you can read on https://docs.fastlane.tools/
Then we synchronise translations thanks to loco and it’s api.
Few lines of code and our Ruby class does the job. To initialize Loco you need api key and path to directory where *.lproj directories are. Example:
LOCO_API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" LOCO_DESTINATION_DIR = "#{__dir__}/../acme_ios/" LOCO = IOSLoco.new(LOCO_API_KEY, LOCO_DESTINATION_DIR)
Let’s imagine that our application has English and Danish translations, so sync_languages method takes array with two languages.
Loco api key can be found on the right of the project preview in developer tools tab.
before_all do Encoding.default_internal = Encoding::UTF_8 Encoding.default_external = Encoding::UTF_8 LOCO_API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" LOCO_DESTINATION_DIR = "#{__dir__}/../acme_ios/" LOCO = IOSLoco.new(LOCO_API_KEY, LOCO_DESTINATION_DIR) end desc "Sync translations" lane :translations do LOCO.sync_languages(["en","da"]) end
the result of `fastlane translations` command will be:

If we want to synchronise translations just before publishing to the testlight/appstore we can move the code just before `gym` execution in our lane.
desc "Submit a new develop build to Testflight" lane :develop do cert sigh increment_build_number LOCO.syncLanguages(["da"]) LOCO.syncMainLanguage("en") gym(scheme: "Develop") pilot end
Whole Fastfile should looks like:
fastlane_require 'json' require __dir__+'/libs/IOSLoco.rb' fastlane_version "2.55.0" default_platform :ios platform :ios do before_all do Encoding.default_internal = Encoding::UTF_8 Encoding.default_external = Encoding::UTF_8 LOCO_API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" LOCO_DESTINATION_DIR = "#{__dir__}/../acme_ios/" LOCO = IOSLoco.new(LOCO_API_KEY, LOCO_DESTINATION_DIR) end desc "Sync translations" lane :translations do LOCO.sync_languages(["da","en"]) end desc "Submit a new develop build to Testflight" lane :develop do cert sigh increment_build_number LOCO.sync_languages(["da","en"]) LOCO.sync_main_language("en") gym(scheme: "Develop") pilot end [...] end
I hope you found that article helpful. If you have better ideas for solving that challenge let me me know at blog@valueadd.pl. If you have any questions do the same and I will help you out.