Translating interfaces into almost fifty languages: Sketch
By: Alexey Timin
Tags: Open Source, Nodejs, JavaScript, Sketchapp

Main characters from the ‘Sherlock’ TV series (https://en.wikipedia.org/wiki/Sherlock_(TV_series))

Hi! I am Alexey Timin, an engineer on the localisation team at Badoo. In this post I will be telling you about how we help translators do their difficult job, and about the new Open Source solution which allows screenshots of designs produced in Sketch to be generated for various languages.

If you produce designs for multi-language projects or if you work on a team which develops projects of this nature, then you should find this information helpful.

There are only two developers on the Badoo localisation team, but we are hanging in there and creating some very interesting tools:

● Translation Memory

● Collaborative Translation Platform, which can be accessed at the URL https://translate.badoo.com/,

● Functionality for providing a given user with the correct translation (depending on language, gender, preferences and date),

● A system for preparing translations for A/B testing (yes, we run tests for versions of a translation in order to determine which wording is best),

● Ten or so interfaces for translators’ work,

● Collection of statistics relating to translators’ work and their use of tools.

The tools listed above are intended to help with the process of localising the Badoo site and two Badoo mobile apps (for Android and iOS) for 47 languages. This is a huge to-do list.

Our translators work with lexemes (this is what we call the indivisible unit of translation: a word or a sentence). For each lexeme the optimal wording is chosen with a view to the app displaying it correctly on users’ screens. Sometimes the translation doesn’t just need to be correct; it also needs to be appealing (for example, for marketing purposes).

This is what the translation process looks like:

1. Designers draw.

2. Programmers program.

3. Translators translate.

4. Release.

As you can see, translators have to wait for the prototype of the app from the programmers. Or, if there have been changes to the translation, they have to ask developers to build a new test version in order to test how it will be displayed. But we had the idea of keeping the programmers’ involvement in the translation process to a minimum and of speeding up the process of preparing for a release.

In line with what we were thinking, this is what the process might look like:

1. Designers draw.

2. Programmers program, and translators translate and are able somehow to see the result of their translation.

3. Release.

To make it easier for you to visualise the problem, here are some diagrams of the process before and after. The section to be optimised is highlighted in red on the first diagram:

Our designers work in the graphics editor, Sketch. We made sure that the accompanying sketch-tool utility is able to generate screenshots and this means that when a translation is added it is possible to show the translator the screenshot! However, a question arose. How can you replace the source texts in the design in order to obtain a localised screenshot?

In breaks between partying we discussed possible options for implementing our idea. And we found a way forward.

Right, what is the internal structure of a .sketch-file?

Presentation of data inside a .sketch-file

In the 43rd version of Sketch developers started to use a new format for the .sketch-file “to allow better integration with third-party services”(http://sketchplugins.com/d/87-new-file-format-in-sketch-43).

Logically the design produced in Sketch may be broken down into the following entities: pages, artboards and graphic elements. Each entity – a page, artboard or graphic element – is assigned a unique identifier (UUID) once (at the moment it is created); this does not change.

The relations between the entities may be visualised as follows:

Look at the image below to understand what is what in the Sketch interface: iPhone SE and iPhone 7 – two possible artboards, and Page 1 is one of the possible pages.

The design saved in .sketch-file is a ZIP archive which contains directories with PNG and JSON files. Looks simple, right?

If we unarchive the .sketch-file, we will get a directories tree looking something like this:

The information relating to each page and related artboard objects is saved in pages/*.json. The UUID for the page object serves as the file name; for each page object there is one file.

We can easily open any pages/*.json and edit, for example, the name of one of the artboards. To determine the specific file for editing, we run the following:

$ grep -l ‘iPhone 7’ pages/*

Changing the name might not be a problem, but changing, say, the text “Click here” is more complicated. We trailed through various forums and did various searches for suitable libraries (with no success) and realised that lots of other people are also looking for a solution to this.

It is all rather like the Russian fairy tale character, Koschei the Deathless , who can only be killed by finding his soul which is hidden inside a needle, which is in an egg, which is in a duck, which is in a hare, which is in a chest which is buried under a tall oak tree. 🙃

The text on the button “Click here” is packed in a binary plist, coded in a Base64 string, which is an attribute value of a serialised JS object which is located in one of the files compressed as a ZIP.

We are not going to touch on the issues of unarchiving and reading JSON from files, but it is worth saying something about the Property Lists format (bplist on the diagram above). In order to amend the text, “Click here,” you can use the utility, plutil. This allows you to enter a new value and delete the old one for a given property, and you can also use it to convert plist from binary form to XML and vice versa. XML is a convenient format and there are lots of tools available for working with it. It is also possible to export to JSON, however, first of all, doing so means you lose the data types, and, secondly, plist cannot always be converted into JSON. For example, using plist to export from a sketch-file to JSON did not work.

Right, we’ve dealt with the internal structure of the data, and now we can finally move on to options for implementing our idea.

Choosing suitable realisation

Option 1. The lazy solution

We tried to tell translators about JSON, Base64 and bplist, to train them to replace texts with translations by themselves and then to do screenshots. However, when we showed them the console command for export preview:

$ sketchtool export artboards --items='42C53146-F9BF-4EEE-A4F8-BB489F0A3CDA,BF38A95A-F0CD-452E-BE26-E346EBD349CE' --formats=png --save-for-web example_design.sketch

We realised that this option was not going to work out (I’m joking! We didn’t tell them anything; we just went straight to the second option☺).

Option 2. The best way

Translators shouldn’t have to think about technical issues. All that they need is to be given a screenshot when they save their translation.

For this purpose, we decided to develop a service where minimum functionality would be:

1. Determine in the .sketch-file the UUID of graphic elements containing text.

2. Generate screenshots with localised text.

The project was given the name Sketch Modifier and was published on GitHub.

Working with Sketch Modifier

To start using Sketch Modifier, you have to install Sketch and Node.js on macOS. Yes, Sketch only exists for macOS. But if your designer works in Sketch, then you should have at least one Mac.

Let’s examine the process for working with Sketch Modifier step-by-step.

Step 1. Installation

Find a computer operating with macOS. Download and install Sketch and Node.js on it – this is easy to do.

Then download the archive or clone the repository from GitHub with the command:

$ git clone https://github.com/AlexTimin/sketch-modifier.git

Go to the project directory:

$ cd sketch-modifier

Install dependencies using npm:

$ npm install

And, finally, launch the server:

$ ./bin/www

That’s it. Now your server should respond if you visit the URL http://localhost:3000. You can go to this URL and check.

Step 2. Load the sketch-file and determine source texts

As an example let’s take example_design.sketch and let’s load it into the system. Send a request from the directory where you’ve saved example_design.sketch:

$ curl -F 'data=@example_design.sketch' http://localhost:3000/add-sketch/

The .sketch-file will be assigned an UUID. In response you will receive a JSON in the following form:

{ "8a2009c5-36ca-4328-87d6-16aa0c2e2800": { // UUID assigned to example design.sketch. Yours will be different "5A0F429A-C974-460A-9482-93AED7456850": { // Page 1 "C1C29749-B967-494D-8D7E-A484EAB37534": {// iPhone SE



"E335D359-9DF3-4DCC-8B79-E77E38824714": "Click here" // UUID for the text on the button

}

...// information relating to other Artboards

}

... // information relating to other pages

}

}

You can save this data to your database, send it to /dev/null or do something else that’s interesting with it. But we save it to the database.

Step 3. Generating a preview of what has been translated

To replace the text you need to send a request to the URL http://localhost:3000/generate-preview/ specifying the parameters of both the screens and the textReplaces. The list of necessary commands will be given below, but for now let’s deal with the structure of the request parameters.

In the screens parameter we give the list of UUID of the artboards for which screenshots should be generated. The value of the parameter has the following structure:

{

Example Design UUID: [ // example_design.sketch

Artboard UUID, // iPhone SE

...

]

}

In textReplaces we specify the UUID of the text elements and the new text for replacement. The parameter value has the following structure:

{

Text UUID: “new text, translation”,

...

}

So, we are formulating a request to generate a screenshot. Let’s replace the text “Click here” with “Start the party!” , for example. For this we need a generate-preview-request-data file, in which we specify the values of the request parameters.

The content of the generate-preview-request-data file:

textReplaces={

"E335D359-9DF3-4DCC-8B79-E77E38824714": "Start the party!"

}&screens={

"8a2009c5-36ca-4328-87d6-16aa0c2e2800" : [

"C1C29749-B967-494D-8D7E-A484EAB37534"

]

}

Execute the command from the directory where the file "generate-preview-request-data" was saved

$ curl -X POST -d "@generate-preview-request-data" http://localhost:3000/generate-preview/

The response will be structured as follows:

{

"C1C29749-B967-494D-8D7E-A484EAB37534":“data:image/sSeY+...;base64”,

...

}

You have probably guessed that the UUID of the requested screenshot is the key in the response structure and the relevant value is the Base64-representation of the screenshot.

If, say, you save the following code into the example.html (don't forget to replace the src-value)

<img src=”screenshot Base64”>,

and then open example.html in a browser, you will see the following screenshot:

Using Sketch Modifier, you can do screenshots before, during and after localisation– which is very important. You will see how the design behaves when using real texts, and understand what needs to be tweaked.

Conclusion

We're setting up working with Sketch Modifier in such a way that the design is uploaded once and the screenshots are generated at the very moment the translations have been saved. Translators will be able to see straightaway whether or not the wordings they have chosen fit into the spaces provided. This means that problems can be flagged up at an earlier stage.

The source code of Sketch Modifier is available on GitHub: https://github.com/AlexTimin/sketch-modifier .

Feel free to use it, suggest improvements and write reviews.