Skip to main content

Translations

Frappe includes a built-in translation system that makes applications
multilingual. It automatically extracts translatable text from your
application, stores translations for different languages, and displays
the appropriate translation based on the user’s selected language.

Note: Strings that should be translated must be wrapped
inside the _() function in Python or __() in
JavaScript.

How the Translation System Works

The translation workflow consists of three stages: extracting
translatable strings, translating them into different languages, and
displaying the translated text within the application.

Step 1: Extracting Translatable Strings

Many strings, such as DocType field labels and descriptions, are
automatically detected from JSON files. Strings written directly in
Python or JavaScript files must be explicitly marked for translation.

Example in Python:

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

During extraction, Frappe scans supported files such as
.py, .js, and .json and collects
every string wrapped in translation functions.

Step 2: Translating Extracted Strings

After extraction, all strings are exported into language-specific CSV
files. Community contributors translate these strings through the
Frappe translation portal, and verified translations are merged into
the framework.

Community Contribution:

Translation updates are regularly reviewed and merged into the Frappe
codebase, making improvements available to all users.

Step 3: Displaying Translated Strings

Translations are stored as key-value pairs where the original text acts
as the key and the translated version becomes the value.

{
    "About": "के बारे में",
    "Academic Year": "शैक्षणिक वर्ष",
    "1 week": "1 सप्ताह"
}

When the application encounters a translated string wrapped in
__() or _(), it searches the translation
dictionary and returns the appropriate language if available.

Best Practices for Writing Translatable Strings

Following these guidelines ensures the translation parser correctly
identifies every string and produces accurate translations.

1. Always Use Literal Strings

Only literal strings can be extracted. Variables or expressions cannot
be parsed by the translation engine.

Correct

message = _("Document submitted successfully")

frappe.msgprint(message)

Incorrect

message = "Document submitted successfully"

frappe.msgprint(_(message))

2. Use Positional Placeholders for Variables

Variables should always be inserted using positional placeholders such
as {0}. Avoid formatting the string before passing it to
the translation function.

Python

_("Welcome {0}, get started with ERPNext.")
.format(full_name)

JavaScript

__("Welcome {0}, get started with ERPNext.",
[full_name])

3. Don’t Split Strings

Keep complete sentences together. Avoid concatenating translated
strings or writing multiline text.

Correct

_("You have {0} subscribers.")
.format(count)

Incorrect

_("You have ")
+ count +
_(" subscribers.")

4. Handle Singular and Plural Separately

Languages have different pluralization rules, so singular and plural
messages should be translated independently.

if invoice_count > 1:
    msg = _("You have {0} pending invoices").format(invoice_count)
else:
    msg = _("You have {0} pending invoice").format(invoice_count)

5. Avoid Leading or Trailing Spaces

Spaces surrounding translated strings may be removed during the
translation process. Add spaces outside the translation function if
needed.

Correct

msg = " " + _("You have pending invoices") + " "

6. Provide Context When Needed

Some words have multiple meanings depending on where they are used.
Context helps translators provide accurate translations.

JavaScript

__("Change", null, "Coins")

Python

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

Adding a New Language

Frappe allows developers to add support for additional languages by
exporting untranslated strings, translating them, and importing the
translated files back into the application.

Step 1: Export Untranslated Strings

bench --site [sitename] get-untranslated [language] [output-file]

This command exports all untranslated strings into a file that can be
translated.

Step 2: Translate the File

Translate every string while preserving the original order of entries.
The translated file should match the exported file line by line.

Step 3: Import the Translations

bench update-translations
[language]
[source-file]
[translated-file]

Bench generates a new [language].csv file inside the
translations directory of each application.

Step 4: Register the Language

Add the new language entry to the
frappe/geo/languages.json file so it becomes available in
the application.

Step 5: Commit Your Changes

Commit the generated translation CSV files together with the updated
language configuration and push the changes to your repository.

Best Practice:

Test your application after importing translations to verify that all
strings appear correctly and that placeholders remain intact.

Rating: 0 / 5 (0 votes)