Translations in Your Custom Frappe App

How to Add and Manage Translations in Your Custom Frappe App: A Step-by-Step Guide


1. Create the translations Folder

Step:
In your custom app directory, create a folder named translations at:

apps/your-app/your-app/translations/

Why? Frappe automatically detects this folder. It follows a convention-over-configuration approach, so placing your translation files here ensures they're recognized without extra setup.


2. Add Translation CSV Files

Step:
Create a CSV file for each language in the translations folder. For example:

  • ar.csv (Arabic)
  • es.csv (Spanish)

CSV Structure:

"source_string","translated_string","context"
"agent","توكيل",""
"continue","إستكمال",""

Why?

  • Column 1 (source_string): The original string used in your code (e.g., _("continue")).
  • Column 2 (translated_string): The translated version of the string.
  • Column 3 (context): Optional. Use it to clarify the translation context.

The third column is optional and may be left empty.


3. Use Translatable Strings in Your Code

Step:
Wrap strings in your Python, HTML, or JavaScript code using _():

from frappe import _

def my_function():
    message = _("continue")  # Will be replaced with "إستكمال" for Arabic users

Why?
The _() function marks strings as translatable. During runtime, Frappe replaces them based on the user's language preference.


4. Build the Site

Only needed if you're using __() in custom frontend JS and changed the JS files

Step:
Run the build command:

bench --site your-site build

5. Verify Translations

Step:

  • Switch your user’s language to Arabic (or target language) in Frappe.
  • Check if _("continue") now shows as "إستكمال".

Why?
This confirms that Frappe correctly maps the source string to its translated counterpart.


Key Notes

Language Codes

  • CSV filenames must match Frappe’s language code (e.g., ar for Arabic).
  • You can find these codes in Frappe > Language settings.

Folder Location

  • The translations folder must be at the root of your app’s package directory (not inside a submodule).

Performance

  • Translations are cached during build.
  • Always restart bench after editing translation files.

Fallback Behavior

  • If a string isn’t translated, Frappe will use the original (source) string.

Do i need to build or migrate the site?

NO, frappe loads translations dynamically at runtime from your translations/lang.csv file, based on the logged-in user’s language preference. you just need to refresh your browser or clear-cashe if necessary.

bench build only needed if you’re using __() in custom frontend JS and changed the JS files


Example Workflow

  1. Create:

    apps/my_app/my_app/translations/ar.csv
    
  2. Add entries:

    "welcome_message","مرحبا بك!",""
    
  3. Use in code:

    _("welcome_message")
    
  4. Clear Cashe:

  • use it if translations don't reflect immediately
    bench --site my-site clear-cache
    
  1. Build:
    • only needed if you're using __() in custom frontend JS and changed the JS files
      bench --site my-site build
      
  2. Test in Arabic interface.

Explain Context?

context is nothing but a meta-data, to explain to the one who will use this translation when and where to use it. because sometimes you have the same word with different meaning

as example:

"charge","شحن",""
"charge","رسوم",""

here we have same word but different meaning (different context to use) so, to filter it we have to give it a context

"charge","شحن","mobile phone charge"
"charge","رسوم","invoice line"

in code:

_("charge") # here we don't know which meaning (context to use)
_("charge", context="mobile phone charge") # here we mean شحن
_("charge", context="invoice line") # here we mean رسوم
Discard
Save
This page has been updated since your last edit. Your draft may contain outdated content. Load Latest Version
Was this article helpful?

On this page

Review Changes ← Back to Content
Message Status Space Raised By Last update on