Implementing Multilingual Support in Applications with Empress Translation System

Introduction

Welcome to this comprehensive guide on how to effectively utilize the Empress Translation System in Empress. As developers, you’ll find this feature to be a vital tool in internationalizing your applications, enabling you to cater to a broader audience by supporting multiple languages.

Empress Translation System Overview

The Empress Translation System is an in-built feature in the Empress framework that allows you to mark strings in your code as translatable and then extract these strings into Comma Separated Values (CSV) files for different languages.

Workflow of Empress Translation System

The translation process in Empress is executed in three main steps:

1. Extracting Translatable Strings

Empress automatically identifies translatable strings in your code such as field label and description in JSON files of DocTypes. However, you can also explicitly mark strings as translatable in your source code files (.json, .js, .py) using the _() or __() methods.

message = _("You don't have permissions to access this file")

2. Translating Extracted Strings

The extracted strings are then listed in CSV files according to the language. Translations are primarily contributed by Empress and ERPNext users on the translator portal. The submitted translations are verified by a bot, converted into a Pull Request, and merged into the core weekly.

3. Applying Translations in the App

The translated strings are essentially key-value pairs of the original string and its translation in a particular language.

{
    "1 hour ago": "एक घंटे पहले",
    "1 minute ago": "1 मिनट पहले",
    "1 month": "1 महीना",
    "1 week": "1 सप्ताह",
    "1 year": "1 साल",
    "3 months": "3 महीने",
    "6 months": "6 महीने",
    "About": "के बारे में",
    "About Us Settings": "हमारे बारे में सेटिंग्स",
    "About Us Team Member": "हमारे बारे में टीम के सदस्य",
    "Academic Term": "शैक्षणिक शब्द",
    "Academic Year": "शैक्षणिक वर्ष",
    "Academics User": "अकादमिक उपयोगकर्ता",
    ...
}

When a string is written as __('1 hour ago') in the code, the __ method searches the dictionary for a translation for that string. If a translation exists, the translated string is returned.

Guidelines for Writing Valid Translatable Strings

There are a few rules that you need to follow to ensure that the translation parser can correctly identify the strings from your code:

1. Literal Strings

The string to be translated must always be a literal string, not a variable or expression.

# This will work
message = _('Document submitted successfully')
frappe.msgprint(message)

# This won't work
message = 'Document submitted successfully'
frappe.msgprint(_(message))

2. Variables

When using variables in your string, you must use the positional formatter {0}. Any other type of formatter will not work.

# This is fine
_('Welcome {0}, get started with ERPNext in just a few clicks.').format(full_name)

3. Blocks

Avoid splitting your string into separate blocks or writing multiline strings. Always write your string in a single line, even if the string is very large.

# This is fine
_('You have {0} subscribers in your mailing list.').format(len(subscribers))

4. Plural

Do not attempt to pluralize words using logic. Every language has different plural forms.

# Write separate strings for different plural forms
if invoice_count > 1:
  msg = _("You have {0} pending invoices").format(invoice_count)
else:
  msg = _("You have {0} pending invoice").format(invoice_count)

5. No Trailing Spaces

Avoid starting or ending the sentence with spaces. Trailing spaces get trimmed for other languages when passed through the translation engine.

# Do this
msg = ' ' + _("You have {0} pending invoices") + ' '

6. Adding Context for a String

A translatable string can have different meanings in different contexts. You can use the context variable to set the context for a string so that it can be translated differently in different languages.

_("Change", context="Switch")

Adding a New Language

Adding a new language to your Empress application involves the following steps:

Step 1: Export untranslated strings to a file

$ bench --site sitename get-untranslated [lang] [path-to-file]

Step 2: Translate the strings

Create a file with updated translations (in the same order as the source file).

Step 3: Import your translations

$ bench update-translations [lang] [source-path] [translated-path]

Step 4: Update languages.json

Add your language in frappe/geo/languages.json.

Step 5: Commit each app and push

Commit your changes with the .csv files in each app and push them to their repositories.

In conclusion, the Empress Translation System is a powerful tool that allows developers to cater to a global audience by providing multilingual support. By following these guidelines, you can ensure that your Empress applications are accessible to users around the world, regardless of their preferred language.