Here’s more detail about how I use awk and Vim to create translation files for my iOS apps.

In a previous blog post I described how I used awk and Vim to populate the part of my Localizable.strings file that dealt with Pickers for the Dutch translation of my first app, Museum Shuffle. Now that I’m working on localizing my second app, Snack Plan, I realized that I could also explain how I use the same tools in general when dealing with translating my apps.

The goal

Instead of sending a file with just English strings to my translator I like to send a file that has an attempt at translation that they can clean up. So I need to take the English strings, feed them to a tranlsation tool, and then create the output that contains English and another language in the format that Xcode expects.

The base translation file

Remove comments

When you run the genstrings command to start populating your Localizable.strings file it attaches the following to every single string:

/* No comment provided by engineer. */

I prefer the default to be no comment and then adding them when I feel they are needed. We’re going to strip these comments out.

I copy the contents of the Localizable.strings file into a text editor. I personally use Vim. I save that as a file named “before.txt” and then remove those comments with grep.

grep -v 'No comment provided by engineer.' before.txt > clean.txt

Extract each English string

Then you’ll have a file that has contents that look like this:

"The first line." = "The first line.";

We want to extract just the left string. There are obviously many ways we could do this. You could use cut and specify that the equal sign is the delimeter. Since we’re using awk a lot in this blog post I’ll use that. Note: if you have a string that contains an equal sign then these methods won’t work for that line. I like to retain the double quotes.

awk works by specifying an optional pattern and an action to perform. This command specifies that equal sign is the delimeter. The pattern is not provided so the action is always performed. The action is to print the first field, which is the left string. If a line is blank then a blank line will be printed.

awk 'BEGIN{FS="="}{print $1}' clean.txt > english.txt       

Paste into a translation app

Now we’re going to copy the contents of english.txt into a translation app. I used Google Translate because it can translate to Dutch. The amount of strings you can paste into it is not unlimited. I’ve had good success pasting around 75 lines into it. That will produce output like this:

"Vergeet de derde regel niet."

"Tweede lijnen zijn geweldig."

"De eerste regel."  

There’s a button that lets you copy the translation. Paste that into another text file.

Combine the translations

Now we’re able to use another awk command to combine the two files. My previous blog post about awk and Vim explains the full details of how this particular awk command works. However, in my previous blog post I was describing transforming an array of strings for a Picker and there were no blank lines to deal with. That is no longer the case. I want to preserve blank lines in the files. To do this I’ve added some “NF” patterns to the command. “NF” means the number of fields. The pattern that is just “NF” will only be true if the value is non-zero. If a line is blank the number of fields is zero. The pattern’s action is to print an English string on the left and the corresponding Dutch string on the right. The pattern “0==NF” matches for lines with no fields (empty lines). For that pattern the action is to just print a blank line. That preserves our blank lines in the output file.

awk 'NR==FNR{a[FNR]=$0;next}NF{print a[FNR]" = "$0";"}0==NF{print}' english.txt dutch.txt > after.txt

To test this I added another blank link in the English and Dutch files above the last line. Sure enough, the final result that combines both files preserves that.

"Don't forget the third line."  = "Vergeet de derde regel niet.";

"Second lines are great."  = "Tweede lijnen zijn geweldig.";

"The first line."  = "De eerste regel.";

Now you can paste these lines into your translation file (Dutch in my case) and remove the versions of them that were only one language.

Big Warning

Be absolutely sure that your comment lines are correct. My awk commands caused a line like this to be generated and it caused some interesting problems with Xcode.

/* fish */ = /* fish */

A line like this will stop Xcode from performing some translations. Lines below it in the Localizable.string file are not used but ones above it are! The project will compile and “plutil -lint” says the file is OK. I filed feedback FB9968157 about this problem.

Why are you doing this?

I already know what several of you are thinking. “Why are you doing this? Isn’t it the job of the person translating the file to another langauge to create the translated strings?” In most cases that would absolutely be true. However, in my case I’m asking friends to help me with translating and they’re doing it for free. I feel guilty about making them spend a lot of time on this effort.

If you’ve used online translation tools then you know that sometimes they can be laughably inaccurate. However, some of the time they are going to be exactly correct. For the strings where they’re correct the person helping me doesn’t have to do anything with those lines and can just skip past them. When you’re talking about hundreds of lines to translate that can become a significant number of lines that can be ignored. I remember Jordi Bruin asking me how I did this when I gave him my attempt at a translated Dutch file for Museum Shuffle. 😃

Zsh is great!

If you couldn’t tell I love using command line tools. I knew that macOS had changed its default shell from Bash to Zsh a while ago, but investigating the differences had always been low on my to-do list. I just stuck with Bash. Josh Holtz and Adam Rush recently talked me into switching to Zsh and I love it! I can keep using all of the commands I’m used to (including Vim commands) and continue seeing the current git status in my prompt while at the same have many exciting new tools that make development easier. Thanks Josh and Adam!


With these tips you can give your translators a head start with the translation files for your app.

If this post was helpful to you I’d love to hear about it! Find me on Twitter.