How to translate a Blender Addon

The Grove is available in several languages. This is a documentation of how this was made possible, as a reference to fellow addon developers who want to translate their own addons.

I first wasted some time with Blender’s translation system, but soon gave up on it. It seems impossible to override words that have already been translated in other contexts of Blender. And it’s a general pain to work with. Took me several attempts to get to a good system of my own, but in the end it is extremely simple. It works like a charm and more addons could be using it. So I’d love to share it with you.

Here’s why I couldn’t work with Blender’s system:

  • There are already many of the same words translated, and it seems impossible to overrule ones that are incorrect in the specific context of the Grove. Although Blender’s translation system does allow for contexts, it seems impossible to use in addons.
  • Blender’s existing translations are inconsistent in use of caps and generally incomplete.
  • Blender’s included translations can change without you knowing.
  • Its dictionary format is very hard to work with, especially for translators.
  • Doesn’t allow translation of more strings than just those used in the interface, like interface messages and terminal console messages.

For each language, I have a file with a simple Python dictionary with keys and values. Every language is treated equal, so English has its own dictionary, which looks something like this:

[code] # coding=utf-8

dictionary = {
‘wind_force’: ‘Wind Force’,
‘wind_force_tt’: ‘Strength of the wind effect.’,
}
[/code]

The way it works is I have a file Translations.py that imports the right dictionary based on the selected language. Other than that, there’s just a simple function called “t” that takes a string ( variable name in my case ) and returns the translation from the dictionary.

[code language=”css”]

from bpy.app.translations import locale

if locale in [‘ja_JP’]:
from .Languages.ja_JP import dictionary
elif locale in [‘zh_CN’]:
from .Languages.zh_CN import dictionary
elif locale in [‘es’, ‘es_ES’]:
from .Languages.es import dictionary
else:
from .Languages.en_US import dictionary

def t(phrase: str):
""" Translate the give phrase into Blender’s current language. """

try:
return dictionary[phrase]

except KeyError:
print(‘Warning – Text missing for: ‘ + phrase)
return phrase

[/code]

Missing keys are printed to the terminal – a handy tool to see which translations are missing.

Then to make it all work, I define each property using this translation function, so for instance:

[code] wind_force: FloatProperty(
name=t(‘wind_force’), description=t(‘wind_force_tt’),
default=1.0, soft_min=0.0, soft_max=2.0, step=10)
[/code]

The _tt suffix denotes that this is a tooltip. Here you can see why I called the function “t”, it’s as short as can be and won’t distract from the rest of the code.

This translation is only done once, when the addon is loaded, so it has almost no impact. A downside of this system is that you will have to reload scripts to see the newly selected language.

As you see, the system is extremely simple. Let me know if you found this useful or if you have trouble implementing this code.

Have fun coding!