[Dos and Don’ts #2] Translation in JavaScript

In an effort to increase the code quality of contributions to ERPNext and other frappe apps, I started to post some examples of code I found and how it could be done better. The previous post was on the advantages of frappe.db.get_value over frappe.db.sql. Today we’re looking at how to translate strings in JavaScript.

My code is of course not perfect. You’re welcome to comment suggestions on how it could be improved.

Don’t

const empty_state_message = __(`No featured items yet. Got to your
    <a href="#marketplace/published-items">
    Published Items</a>
    and feature upto 8 items that you want to highlight to your customers.`)
const views_message = __(`${this.item.view_count} Views`);
  • Translators should’t need to know HTML and shouldn’t be able to mess it up accidentally.
  • The translation setup doesn’t support template strings; views_message would not get translated. For the same reason you shouldn’t do this in python:
views_message = _('{} Views'.format(view_count))

Source: frappe/erpnext

Do

const empty_state_message = __('No featured items yet. Got to your {0} and feature up to eight items that you want to highlight to your customers.',
    [`<a href="#marketplace/published-items">${__("Published Items")}</a>`])
const views_message = __('{0} Views', [this.item.view_count]);

The translation function takes a second parameter, a list of variables that will be substituted into the translated string at runtime. We can pull out the HTML and the view count.

Strings within the HTML, “Published Items” in this case, also need to get translated. This can be achieved by calling the translation function from within a template string (not the other way round).

In python, the solution is to format the translated string, not the source string:

views_message = _('{} Views').format(view_count)

That’s it, have a nice day!

5 Likes

Agree.
I see many variables, url, fieldnames, and icon names are included in the translation tags.
And because Frappe and ERPNext are translated by sending script to Google, most of them also got translated word by word.
This causes problems because when changing language the string/variable/fieldname/etc can’t be found.

Hello rmeyer,

Thank you very much for your tips.

I have a question, I can’t translate any external custom apps for some reason.

I’m trying to translate some Webshop Modals / Popups and It just won’t work.

Already did the following:

  • Moved the file from templates/generators/item to public/js
  • Added the Translation Tags __(‘Example’),
  • Added import ‘./js/item_configure’ to web.bundle.js
  • Confirmed that web_include_js = “web.bundle.js” is present in hooks.py
  • Ran bench build and bench build-message-files
  • Also tried bench get-untranslated, but the JS strings and variables are still not there.
  • Checked the pt.csv for the translations and they’re not there.
  • Translations are not working when visiting the page.

Any tips?

Web pages are harder to translate than desk pages, because we try to publish only the specific translations that are needed for a page. E.g. for a web form, only the translations for the field labels are pushed to the user. So when you define a custom modal, you won’t be able to use other translations there, out of the box.

1 Like