Skip to content

How to write translations for futurecoder

Alex Hall edited this page Mar 25, 2024 · 3 revisions

A great and relatively straightforward way to contribute to futurecoder is to add translations from English to other languages. For example, there is a fully translated French version of futurecoder. Translations to other languages are in progress, and new ones can be added.

Translation don't require deep knowledge of programming, in fact you don't even have to touch the codebase! It's all done online in POEditor: click here to join and start now! Then join the #translation channel on Discord to discuss translation in general or even join/start a language-specific channel.

Markdown

The text and the translations are written in markdown, a language with a simple syntax for writing formatted text. You don't need to know much, and even if you don't know anything it's usually fine to just make sure that the same special symbols are there in both languages. POEditor helps with this by warning you of mismatches and by sometimes offering a button with an 'eye' icon to see a preview with the text formatted as described by the markdown. Here's the most relevant parts of markdown for futurecoder:

  • Blank lines separate paragraphs.
  • Text surrounded by `backticks` is inline code: text formatted as code inside a line of other normal text.
  • A paragraph indented by four spaces is a code block.
  • *Asterisks* make text italic.
  • **Double asterisks** make text bold.
  • Lines starting with a dash (-) make a bulleted list like this one.
  • Hyperlinks use square and round brackets like this: [human friendly label](https://example.com/address/url).

Other special syntax

  • futurecoder has some special strings starting and ending with __ that must be left exactly as is, including whatever indentation or backticks they do or don't have. This includes __copyable__, __program__, __program_indented__, __no_auto_translate__, and __codeN__.
  • Some strings represent templates (a.k.a format strings) into which variables are substituted/interpolated, e.g. more than {max_count} {label} can become more than 1 loop when max_count=1 and label='loop'. Translate the more than which is for humans, but not the parts inside {} which are for code to process. Some terms have just {} with nothing inside, and some have a preceding $ like Shown ${numHints} of ${totalHints} hints which should also be left as is.
  • Sometimes there are links to other pages in the futurecoder course such as [Introducing Lists page](#IntroducingLists). The label inside square brackets should be translated, and there will even be specific terms representing page and chapter titles to translate. The address #IntroducingLists shouldn't be translated.

Translating code

A lot of the course text in futurecoder is Python code, much of which the user has to type in almost exactly, or at least details like function names have to match. The variable names and string literals are written in English, and while students don't have to understand what all of it means to complete the course, it adds mental overhead. It's great if the code (not counting Python keywords and builtins) is in the same language as the rest of the course text so that users can easily make sense of examples and not be distracted by another language barrier.

On the other hand, you may choose not to translate code for a particular language. For example, a Chinese translator thought it best to leave the code in English so that students wouldn't have to switch back and forth between two alphabets while writing code. In that case, you can just copy the terms containing English terms directly into the translations unchanged.

Translating all the code consistently is a lot of work, so futurecoder helps automate most of it. By default, all code blocks (not inline code) containing valid Python code are replaced with __codeN__ (e.g. __code0__, __code1__, etc.) which is translated automatically behind the scenes. This works by translating each variable name and string literal based on the corresponding term starting with code_bits.. So you only have to translate each little code bit once, and the full blocks of code are taken care of for you.

That still leaves some kinds of code that you have to manually translate:

  • Inline code, i.e. text surrounded by `backticks`.
  • Code blocks that aren't valid Python syntax.
  • Code blocks preceded by __no_auto_translate__.
  • Programs for steps that have been marked with auto_translate_program = False in the futurecoder source code. These have a term identifier ending in .program.

Some examples of code that's marked for manual translation and the reasons why:

  • Many of the steps in GettingElementsAtPosition because translating each word of words = ['This', 'is', 'a', 'list'] separately may not work well. Even the program words[4] needs manual translation because the translated version of words may have more than 4 elements.
  • The final_text of IntroducingForLoops which expands the example loop over name = 'World' into character = 'W', character = 'o' etc. because the translation system doesn't know about the individual characters.
  • Places where the number of characters in a word matters.

When you translate code, make sure you don't translate names that are part of Python itself, like len and range. This gets a bit trickier with method names: a variable called index should be translated, but not the builtin list method .index(...).

Tips

Comments

Most terms have some extra information in the comments, such as:

  • A link to the relevant page on futurecoder. Unfortunately the link doesn't behave quite the way I want it to - futurecoder overrides it with the last page you visited. When it does that, press the browser back button.
  • The original contents of the substituted __codeN__ blocks.
  • Links to related terms, particularly for code bits.

Unfortunately it seems that these comments can't be updated on poeditor by subsequent uploads, so they may go out of date after a while.

Single and double qoutes

On the page "Single and Double Quotes in Strings" are a few terms where the presence of specific types of quotes is important:

  • pages.SingleAndDoubleQuotesInStrings.steps.single_quotes_apostrophe.program: print('Alice's Diner')
  • code_bits."Alice's Diner": "Alice's Diner"
  • pages.SingleAndDoubleQuotesInStrings.steps.double_quotes.text (talking about the apostrophe in Alice's)
  • pages.SingleAndDoubleQuotesInStrings.steps.double_quote_exercise.text: requires printing Special cases aren't special enough to break the rules. The user is expected to define the string using double quotes to handle the apostrophe (single quote) in aren't.
  • pages.SingleAndDoubleQuotesInStrings.steps.single_quote_exercise.text requires printing "Talk is cheap. Show me the code." - Linus Torvalds which contains double quotes.

Make sure that the translations also have single and double quotes in the right places so that the user gets the appropriate syntax error or obstacle to overcome.