Translation strings from JS files are not imported if the JavaScript file is transpiled by Babel from TS or JSX

Created on 11 December 2024, 11 days ago

Problem/Motivation

Translation of the frontend components in JavaScript in Drupal is pretty easy: just wrap the text by the Drupal.t() function in any place of your JS and it will work.

So, if you write JavaScript code in pure JS, and attach those JS files using Drupal API, The Drupal Locale module automatically parses these files and extracts all translateable string, and adds the translated strings to the frontend JS automatically too.

But, if you use TS or JSX, each line of your code will be transpiled to pure JS by Babel. And that Babel breaks the whole idea!

So, if we have something like Drupal.t('Hello world') in any TS or JSX file, it will be represented as something like this:

var a=require('Drupal');var myString=a.t('Hello world');

that is already not parseable.

Therefore, any attempts to parse the transpiled JS files tend to fail.

Steps to reproduce

1. Write a bit of JavaScript code like this:

const myString = Drupal.t('Hello world');
console.log(myString);

and attach this file to a page.
2. Translate this string by the Drupal translation interface to another language.
3. See that the translation works automatically!
4. Convert this JS file to TypeScript and transpile it back to JS using Webpack and Babel or something else.
5. See that the automatic translation stops working.

Proposed resolution

I see several ways to fix this issue:

1. Add the source files (TS and JSX) to the parser, to make them able to extract the strings before the files get transpiled.

2. Configure Babel or something else to keep the Drupal.t() calls untouched in the transpiled JS.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

🐛 Bug report
Status

Active

Version

11.0 🔥

Component

locale.module

Created by

🇦🇲Armenia murz Yerevan, Armenia

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @murz
  • 🇦🇲Armenia murz Yerevan, Armenia

    Another alternative to this issue is to not use any transpilers, but use pure JS. But with this approach, we will get a problem with missing translations in files, included from the JS side (by import, require). And a workaround for this is to include them from the Drupal side instead, something like this - components/my-component/my-component.component.yml:

    name: My Component
    status: experimental
    group: My Components
    props:
      type: object
      properties: {}
    
    libraryOverrides:
      js:
        js/CatalogPage.js: { attributes: { type: 'module', defer: true } }
        # We have to include here all dependencies of the components used in the
        # template to extract translation strings from them by Drupal.
        # @see https://www.drupal.org/project/drupal/issues/3493106
        ../../../js/templates/ProductCatalog.js: { attributes: { type: module } }
        ../../../js/organisms/ProductList.js: { attributes: { type: module } }
        ../../../js/organisms/FacetsForm.js: { attributes: { type: module } }
        ../../../js/molecules/Pager.js: { attributes: { type: module } }
        ../../../js/molecules/ProductCard.js: { attributes: { type: module } }
    
  • 🇫🇷France nod_ Lille

    I don't see what to change in Drupal core, hence setting this as a support request.

    The easiest way to go about this is exclude Drupal.t from being replaced. Using a library with attribute type: module shouldn't aggregate them so you won't get aggregation or minification for theses

Production build 0.71.5 2024