Video hosted by Apple at devstreaming-cdn.apple.com

Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2017-410
$eventId
ID of event: wwdc2017
$eventContentId
ID of session without event part: 410
$eventShortId
Shortened ID of event: wwdc17
$year
Year of session: 2017
$extension
Extension of original filename: mp4
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2017] [Session 410] Localizing ...

WWDC17 • Session 410

Localizing Content for Swift Playgrounds

Developer Tools • iOS • 35:29

Localizing a playground book is more than just translation. Explore best practices, potential problem areas, and the unique challenges of localizing educational content. Understand how a localized playground book is structured and hear about the lessons learned by the people who made it happen.

Speakers: Alex Kuhn, Aaltan Ahmad

Unlisted on Apple Developer site

Transcript

This transcript has potential transcription errors. We are working on an improved version.

Good afternoon and welcome to Localizing Content for Swift Playgrounds. I am Alex Kuhn. I'm an engineer on the Content team, developing content for Swift Playgrounds, and I'll be joined later by Aaltan Ahmad from the Internationalization Team. Now it's a big world out there full of many different diverse people that would love to use the amazing content that you build in Swift Playgrounds. However, at Swift Playgrounds, right now we have over a million users. Except nearly two-thirds of them are outside the US. So for them to be able to use your amazing content you need to localize it to hit this whole world, is what we'll talk about today.

So a little bit of history on Swift Playgrounds. This is an iPad app that enables you to write Swift code and see the results of it executed live. And along with Swift Playgrounds we've released a curriculum teaching a beginner the basics of learning the code. And also, there is different coding challenges such as writing the logic for the game of Battleship.

Now this was initially released in English, but we have since translated that into five additional languages. Spanish. French. German. Simplified Chinese and Japanese. And we have more coming soon. And in localizing the content, we had a number of different challenges and issues that we had to encounter and work through in order to have a great experience for our users.

And so this is what we want to talk about some of the lessons learned for you, when you make your own content. So today we'll give an overview of what is content and Swift Playgrounds and some of the challenges around it. And we'll talk through some of the localization considerations when you are making your own content and localizing it. And lastly, we'll go through what is the structure of a localized Playground book so that you can make your books localizable today.

Now before we begin talking about localization, it's something that's really critical is to define your content goals. And this is important because when you build the content initially, when it goes to localization, you need to be able to tell someone else what exactly your goals were, and what do you want the experience for that user to be like in any language, since it's not going to be you necessarily doing all of the translations. So to give an example of the content goals we had and learned at code.

For one, it was instructional. We're trying to teach the beginner the basics of coding in Swift, assuming no prior knowledge. However, we also want it to be fun and engaging. It shouldn't be like a dry textbook, but rather something the user wants to use and is engaged with coding and learning more.

And we chose to target the ages of 12 and up. So whether you're 12 or 112, we'd love for you to have a great experience using our content. Now just to get an overview of what this translates to and learn the code, here you see this page is about learning about debugging and finding and fixing bugs. Something I'm sure many of you are quite familiar with. However, to a learner this is the first time they're being introduced to the concept.

Now on the right here we have a live view. In this case it's a 3D animated puzzle world where you're trying to write code to solve different puzzles and collect gems. There's also a prose area that provides instructional content and the goals on a page and the tasks a learner needs to perform.

And then, of course, the coding area where they can write and edit Swift code to solve the puzzle. So going back to those goals, one of ours is to be instructional. So we are actually defining what the term "bug" and "debugging" means to a learner who might never have experienced this before. And this is something that needs to be kept into mind with localization which I'll tie back to later.

And throughout the course of the curriculum, there are many such definitions that occur gradually. And in the end, there's a whole glossary of terms that the learner gets exposed to when they go through the curriculum that has gradually built up to, and this needs to be taken into account when you localize it.

Now one other feature in the system is that when the learner runs their code, the system is analyzing what the learner has done and is trying to help provide corrective feedback. Trying to give him instruction of how to improve or fix what they did. So here you'll see that animated character, Byte, failed to collect the gem.

And the learner tapped on the hint saying, "Did you notice that bug? Byte tried to collect a gem that wasn't there." So here we're taking a conversational tone trying to be a little bit more fun and engaging, while at the same time giving instructional feedback saying that they need to use collect gem, the function, when they're under a particular gem.

So when this page is put into Chinese, you'll notice that while the code is in English everything else is localized. And we're still teaching these exact same concepts, but in a way that is appropriate to the language. So they're still learning about bugs and debugging, but they need to be able to relate it back to the code that they're seeing on the page.

And similarly, those hints -- we want to maintain that similar style, but you'll notice that we're referencing to the collect gem command in English. So this is one of the things that challenges around localization of dealing with these various different technical terms as well as code in English that we'll talk more about later.

Now one other feature in Swift Playgrounds is we use animated cut scenes to introduce a concept at high level before the learner dives into coding. So in this case, learner is learning about what an "if statement" is before they proceed to use it. And when this is localized, the localization has to take into account how helping the learner to actually do the task. So we're still mentioning if statement -- the if command in English, even though everything else is in Chinese because that's how they're going to need to solve the puzzles later when they write Swift Code.

So that's a little overview of the content. But I'm just going to step back a moment and talk about the process of building localized content. And a common approach that many people might take is that you define your goals and you build up the content in one language; testing and iterating it. Testing it with your users and making sure you have a great experience. Then you decide you want to localize it. So then you send it off to your translators and localize it and then you get it back and ship it.

You're done, right? Unfortunately, this has many problems. You may find when you send it off to be translated that your content isn't localizable. Or that there are different issues in the translation, and it's not actually hitting the goals you're seeking at the same level as when you first developed it in one language.

So what is the better approach? Well, for one, localization is part of the design process. You should be thinking about localization when you are designing out your content goals and the initial design of the product in order to avoid costly mistakes later that prevent content from being localized. And this is no different than what you should do with accessibility. Thinking about it during the design process instead of afterwards. Which is what enables you to make it a really amazing product.

So a better way to think about this diagram, is -- the process is to define your goals and design out the content thinking about localization. And then when you send it off to be localized, you make sure that your translators really understand your goals and what your content is, so that they can translate it appropriately for each language to consistently hit those goals.

And this may take several rounds of iteration when you translate it. So during this time it's really critical to test with actual users, as they're the ones who you're trying to serve and they can tell you if you're doing it right or wrong or if it's actually meeting their needs and understandable.

And of course, during this process you may find you need to go back and adapt your original content due to some issues you found that prevent it from being localized fully. But hopefully because you've considered this in the beginning, these changes are relatively minor. So this is a much better approach to taking and thinking about building localized content. Now I'll hand it over to Aaltan to talk about localization considerations.

Thank you Alex. So today I'm going to talk to you about the process that we went through when we localized Swift Playgrounds, and some of the key areas that you should be thinking about when you are localizing your own Swift Playgrounds. So let's go back to that diagram that Alex introduced to you and let's talk first about the process of actually adapting our own content and goals while thinking about localization to begin with before we even start the actual process of translation.

and the important thing to remember here is that your content choices affect your localizability of your playground. So, for example, if you have a storyline running through your prose, or a particular style of writing that involves wordplay or puns, this is something that is really important to communicate to the people who are actually translating your playground, so that they can maintain that feeling in their own languages. Additionally, there may -- the concepts that you are trying to teach may be tied to a particular language in the first place. And so you're going to need to think about adapting these for localization.

And we can take the example of Cipher, which is a playground that we developed where we try to teach the learner about coded messages and encryption through a very story-like setting where their place is a detective and follow clues to solve the mystery. So here their adding style is actually kind of unique where we really place the reader in the setting of the storyline. So here we say, "The library is warm and quiet. A welcome relief from the howling snowstorm outside." And this will be something that you want to communicate to translators so that they can maintain that same narrative feel, otherwise that friendly, playful feeling might get lost.

Another part about Cipher is the clues. So we have a clue where often you can bring one of the coded messages, the learner is told to look to N for the answer to the next challenges. And we actually call this out in the prose as well, where we say the message says, "look to N." Who or what is N? And right here you can see that there's an interesting challenge with the letter N itself.

Different languages have different alphabets, and some languages may not even have the letter N in their alphabet. And so this is something you'll want to consider. If the letter N is particularly tied to your challenge or finding clues or investigating certain things in the puzzle, that might be a problem down the road for localizability. So you want to give translators the freedom to take this letter N and actually adapt it to what feels most comfortable and natural for their language.

So in Cipher we actually try to teach the learner about encryption. And we do this through a simple substitution cipher. And in a substitution cipher you take your alphabet and you shift it by a certain number of letters to create a new mapping. And using that mapping you can take a plain text word like Cipher and encrypt it so it can't be deciphered without the right key.

And This works great in English. But when you translate your playground and hand it to someone who's a Spanish speaker, probably they're going to end up typing a letter enye, which was not in your original alphabet. And if you hadn't thought about this beforehand, you're going to be in a situation where maybe a learner can't solve the next step of the puzzle, or decrypt the particular message because it doesn't work in their language. So really, these are the kinds of things you want to look out for when you're planning your content and your puzzles.

Another strategy you can take when planning out your content is to actually make it language agnostic to begin with. So if you plan it out in a way that doesn't -- is not particularly tied to any particular language or culture, you can avoid that problem to begin with. And that's exactly what we did with Learn to Code.

We have a made up character, Byte, in a made up world, that is free from any kind of cultural or linguistic ties. So the translation and localization process becomes a lot easier because this puzzle is pretty much the same, no matter what language it's running in. Collecting a gem is collecting a gem. Whether it's in English or in Spanish. So that's another strategy you can use.

Once you've actually planned out your goals and your content, and you feel like you're in a good place with localization and you're ready to actually translate, there are a few key areas that you should keep in mind when doing this. So let's talk about the actual translation process.

The first important thing to consider is your audience. So different languages have different levels of formality. In English you are you, no matter what the context. We don't make any distinction between addressing someone using the word, "you". However, most languages other than English actually do make a distinction here such as German and French. You can see in German, in an informal context you would refer to someone as du. And in informal context, you would refer to someone as Sie. and same for French.

And an important thing to note about these languages is that children's texts here are actually written in the informal voice. And this goes a long way to creating a kind of informal, comfortable feeling for the children. And if you're targeting your Swift Playground to a younger audience as we were, using the informal voice is going to be a key piece in making this feel comfortable to them, and like something they're already used to reading with from school.

There's an important distinction here to be made between the formal and informal voice. Because in iOS, for alerts or other messages we actually use the formal tone. This is because it's more appropriate when your phone or computer is delivering you a message in a matter-of-fact way, to have a formal tone of voice. And of course this contrasts with Swift Playgrounds.

So this is an important factor to consider, depending on the age you're targeting. Another part of your audience is going to be how old they are. And Japanese gives us a good example to understand this distinction between older and younger readers. So Japanese uses three different writing systems, and one of those writing systems is called Kan ji. And Kan ji is a pictographical alphabet that has thousands of characters.

And the point here is that children learn these characters as they grow older, and a younger person is going to be familiar with less Kan ji than an older person. And they're going to be familiar with simpler Kan ji rather than more complex ones. So how does this factor into sort of playgrounds? let's take the example of the term, "Code area" which we use to refer to the code editor where you can input your Swift. If you handed this off to a translator without any prior explanation, or instructions about what age you're trying to target, they might choose a standard Japanese translation of this, which sort of roughly sounds like code sphere or territory.

However, when you inform them about these goals and the younger audience that you're targeting, a better translation comes out, which is a place to write code. And there's a couple of important points that I want to highlight between these two translations. The first is the usage of the word "place" versus "fear" or "territory".

Place is a very common Kan ji, and so a younger reader is much more likely to be able to -- to be familiar with this -- with these words. Additionally, we also chose to include the verb for, "to write". To really make it explicit what the purpose of this area or place is. So that can go a long way in making your Playgrounds easy to understand.

Technical terms are another area where you should pay a lot of attention when writing and translating your Swift Playgrounds. So these can include computer science terms, math terms, and of course, the Swift language keyword, enums, functions and other code that you include in your prose. And to understand this, let's look at the example that Alex mentioned earlier about introducing debugging.

And in order to introduce debugging, we have to introduce the concept of a bug. And in English, we have a simple phrase here that says, "A mistake that keeps your program from running correctly is called a bug." And the highlight here is on the term bug, because that's what we're going to take and translate into our various languages.

So in French we discovered that while learning programming in French, the word bug is actually left untranslated. And that is the standard for learning how to program. So this is, you know, what feels most natural and comfortable to a speaker of French, and what's most appropriate for the context. And so in this case, actually not translating that word and leaving it in English was the most appropriate choice.

However, for a language like Spanish, using a native term, "error" was through our research and understanding, a more appropriate choice here. And an interesting fact about the Spanish translation is that in parentheses, we actually point out that in English, the word "error" is called, "bug". And this allows the learner to sort of see that term -- see the term bug outside a Swift Playground, perhaps, and actually be able to relate it back to what they learned in Swift Playgrounds. So that's terms that you actually have a freedom to translate.

But what about terms that you can't translate like code? Here we have the example of the function moveForward in the Japanese version of Swift Playgrounds. And we needed to mention this function in the prose to sort of explain certain concepts. And Japanese is an interesting language because it has a relatively low tolerance for English words being introduced into the language.

So it's important that we call out the simple explanation for this function moveForward, or susumo or move in Japanese, in parentheses following the occurrence of the function name. And this really helps the learner draw a parallel between the English term and the Japanese term so that they can sort of internalize the meaning of it.

And another interesting thing about Japanese is because of this familiarity with English, or lack of familiarity with English, we make it a point to mention these parenthesized explanations for function names and other variables throughout the entire prose instead of mentioning them when the term is introduced and then phasing them out. And that's a strategy that varies per language because different language are familiar differently with English. So it's another important thing to consider.

Your translators will also have a lot of editorial freedom when translating Swift Playgrounds. So here we are introducing and learn to code three, the concept of a quadrant and the fact that the learner can place different objects at a different coordinate in the space. And to do this, of course we need to talk about the term quadrant.

So in English, we introduce the term quadrant by relating it to quarters. And there is a nice alliteration here, and that makes it a little bit easier for the term to get introduced. However, in Japanese we don't have the advantage of having this alliteration. And so the translator here adopted a different strategy to use a simple word for area or [inaudible] outside parentheses. And then inside parentheses, use the more technical; complicated term or shogan for quadrant. The English translations there are for your reference below.

So the translator -- an important thing to note here is that the translator didn't stick verbatim to what was in English. Which might be the default case if you didn't give them any instructions. They might try to stick very closely to the English text. So it's important to let them know that they have the freedom to do what is most appropriate and most comfortable for their own language. Additionally, because Swift Playgrounds prose is written in a variant of Markdown, they actually have the freedom to add extra formatting, bold or italic, or even extra glossary links to their particular language if they deem that to be appropriate.

So when thinking about technical terms, it's important to keep in mind that unfamiliar terms are confusing, and you should be aware of that when using them in your prose. Different languages have different levels of comfort with English. So what works for one language will not always work for another. And lastly, consistency is really, really important here. Especially because we're dealing with terms that might be from a foreign language or might be highly technical. It's important to maintain a consistent usage of those terms throughout your prose so that a person can get more familiar with them.

So we looked at a lot of examples of different localization strategies and different localization pitfalls and Swift Playgrounds, and there's a few things that I want you to take away from this. Firstly, your content goals and your audience are really going to influence your localization here, perhaps even more so than a standard iOS application. So it's really important to plan those out with localization in mind beforehand. Different languages have different language features, and your translators are going to need to have the freedom to do what's most appropriate for their particular language.

Maintaining a style guide or some kind of document for your translation process is going to be really helpful for you here. Both in, you know, explaining to your translators how -- what your goals are; what your content goals are and how you want the translations to sound and feel, as well as any language-specific issues that they may encounter and strategies they want to -- may want to develop to maintain consistency throughout your translations.

And user testing is really your friend here. It might be resource intensive and difficult to find people that you are targeting with your playgrounds, but the effort really, really pays off here. Because your users of your target are the audience are the only people who can really tell you how effective your playground is being at teaching them these concepts.

So lastly, I'd like to bring you back to this picture of localization and kind of the holistic idea here where your goals -- your original goals and the localized content are not really separate entities that feedback into each other and really influence each others development. It's really important to keep this in mind when you're taking your content from English or whatever you're -- the language that you wrote it in is into translated Playgrounds.

Because localization is so often overlooked as a part of software development, you have no idea how much users really appreciate a well-localized, well-thought out product. And I'm confident that if you try to follow these guidelines and stick to what we talked about here, you'll really be able to give people an amazing experience in their native language. So with that I'll hand it back to Alex, and he'll take you through the process of actually localizing your Playground book. Thank you.

[ Applause ]

Thank you Aaltan. So now we're going to dive into some of the technical details to make your book localizable. And along with this talk there's also sample code which you can explore in detail all of the things we're talking about today. Now, this is a page in "Learn to Code" that's expanded out to show off all the different areas that you have to worry about when you localize. So on the right you'll see the live view, but you can have strings presented to the user. In this case the audio controls. There's also prose providing instructional text.

The editable code area which is a text that is displayed to the user before they begin writing codes to provide a prompt. Each page can have a title. Then also different glossary terms which have definitions for the learner to learn more about if they forgot a term. And a page can have one or more hints if you want to provide help for your learner as they're going through and learning a concept.

So these are all the different parts we'll talk about showing how to localize and what you need to do for each of them. And these come in a few different types of files for Playgrounds. You might use a string in a stringsdict file as well as an xml plist. And the cut scenes are written in html. And you may also have localized assets. So just do a change in each image for each language to adapt it.

Now one other detail before we begin diving into the details is understanding the overall structure of a playground book. So at a base level here, you see you have a sources directory and a private resources directory. And the thing to note here is that in the private resources directory, you'll have an lproj for each language you're supporting. In this example we're doing English and Spanish, with English being our development language. Then there is one or more chapters in each book.

And each chapter has one or more pages. And this is an example in one of the pages in a book. And again, the thing to note here is that the private resource directory has those same lproj's for each language you are supporting. So what does this look like for each of the things? Well, the strings that you have in the live view, these you should use in this localized string for any time you are using a string that will be presented to the user.

And a thing to note here is that it's not just things that visually appear in the Live View, but this also is important for accessibility. All of your accessibility labels should use NSLocalizedString, so that when someone is using the accessibility features in another language, they can get the proper voiceover in their language and have a great experience with your content.

Now once you use NSLocalizedString you would extract this into the strings file with a tool we made called genstrings. And there's more information on the developers site of how to use this tool and extract it. And there was also a talk earlier this week on localizing with Xcode 9 that goes through a lot of general best practices with localizing in Xcode.

Now one key thing to note that you might do in your playground is using an image with text. And it's really critical here to not hardcode the text into the image, as this will make it very difficult to localize, requiring you to remake the image for each language.

Instead, you can layer the text on top of it to enable the translator just to translate the strings and take advantage of all of iOS's layout capabilities to have a great experience for the learner. Now once you have these files, the string file will get extracted into the base level private resources folder in the project. And optionally for using a stringsdict file to dynamically reference a number, such as how many lines of code the learner has written, you would create a stringsdict file for that as well in the same directory.

So the next piece is the prose. And this is rendered in markups to the form of markdown. And this enables page level formatting. You can do bolding, italics, you can create glossary terms or link to another page in the book. And because of this, you have this different markup format that your translators will need to be aware of to take advantage of.

So as Aaltan said, you want to tell all of your translators to have editorial freedom to adjust maybe the bolding or the style per language. And so they really need to understand the format in order to be able to do so. And it's also important that they be aware of what terms cannot be translated that are actually part of the format so that they don't accidentally introduce errors in the code when they go to localize it.

now how do you make your prose localizable? Well, you start a prose block by this little opening comment here, and then you add a localized key. In this case we're calling it firstproseblock as a name for this key. This will enable it to be localized. And then in your lproj you'll create a prose.strings file and put that same key there and then set the value for whatever the markup that should be substituted in for that language. And the contents.swift resides at the base directory for each page. But the prose.strings file will be in the private resources for each language that you're supporting.

Next is the editable text field placeholders. So these are another strings file. And you see here the tap to tenter code. So how this is defined in the initial language is just in a code comment. Where you see in the contents.swift tap to enter code. And for this to be localizable, you'll create an editable field.strings file using the key being the initial phrase you created in your contents.swift. So again, tap to enter code, but you put in the appropriate translation for each other language you're supporting. And this is done at the base directory of the Playground book in the private resources for the associated languages.

Next up is a page and chapter titles. And so here there is a manifest plist.strings file that you'll need to create for each page or chapter, and in this the app is looking for the key name to substitute in the new name for the localized title for your book.

And this is put in, again, the private resources for that particular page for each language project. So next up is the glossary. And this is changing the format as it's using XML. And you'll need to make a copy for this for each language you're supporting. But here is an example of the English glossary.

And we're looking at what the command definition is in English. So one thing to note here is that the top level key command is going to be the same across every language. This will be how the [applause] looks up the glossary definition and will not change. Similarly, the page reference should use a -- be by file reference and not be page referencing the title, which can cause it to break in localization if you were to change the title.

And then there are several different strings that you will send off to your translator to localize that you see here. So if this is put into Spanish, you then see the -- that overall everything is the same, except for those three strings get localized and will be displayed appropriately when the user runs the app in Spanish. And this glossary is stored at the base-level private resources in the project. So you'd have one in your English lproj, and then also a copy that's been translated for your Spanish project.

Hints follow a similar format as the glossary in that they are using XML as well. But these are done on a per page level. And each page can have one or more hints if desired. And this is an example of what a hint file looks like. And in it are several different strings that your translators will need to translate.

And so to -- you would make a copy of this file and have them localize these strings, and then you would get this output. And this new hintplist, this goes in the private resources directory for that page, as they only apply to that particular page. And you'd have both the English version and the Spanish version.

And so last up are the animated cut scenes, which are html files. And these, your translators will need to make a copy for each language and appropriately localize the strings, as well as potentially change any of the concepts or images as needed per each language. And when they do this, you will need to put it in the cut scene pages private resources directory. So here we see the English version is called conditionalcode.html. And the initial html file for each other language needs to follow that exact same name. So for Spanish, even though it'll have all the localized terms, the file name should be conditionalcode.html.

So in summary today, we covered a lot about localization. And one thing that's really key to remember is to define who your audience is, and be sure to understand them when you're going into each different language and trying to adapt the content. Localization is really nuance and complex. It requires a lot of research and testing with actual users, and understanding what are the standards for each country or language or region that you want to go into.

And one thing to keep in mind of all this is that localization is really part of the design process. And so you should be thinking about localization up front if you want to have an amazing experience for your users. And I encourage you all to do so, and make amazing content that everyone in the world can experience. There's more information on the developer website, as well as the sample code that goes along with this. And there's some fantastic related sessions on both localization as well as using Swift Playgrounds and teaching with it. Thank you.

[ Applause and Cheers ]