Score:0

Can I translate a variable using jQuery Drupal.t function in Drupal 9?

us flag
jfc

I am using the REST API in Drupal 9 and am using JavaScript template literals to generate some of the data.

For example, to generate a list of products that are pulled from the API this is my code -

<span class="products">${Drupal.t(object.field_supplier_products)}</span>

This returns what I have under field_supplier_products, so for example "Product 1, Product 1, Product 3", but I cannot find the string translations.

This is a multilingual site and these product names need to be translated.

If I do -

<span class="products">${Drupal.t('Product One')}</span>
<span class="products">${Drupal.t('Product Two')}</span>
<span class="products">${Drupal.t('Product Three')}</span>

Then I see the product names in the string translation

Is there any possible way or work around to be able to use Drupal.t with variables?

*Edit - an example outside of the API -

Drupal.t("something to translate")

I can find the "something to translate" string

translateVariable = 'translation in variable'

Drupal.t(translateVariable)

There are no results for "translation in variable" when I searched for the string

*Edit 2 -

Some more context - I am using the Drupal RESTful Web Services Module to have a REST API for a view. I created a view that has all my products.

I have a JavaScript file product.js that is used to generate markup on my products.html.twig file. In that file there is this code -

(function ($, Drupal) {
    if ( document.querySelector('#products-page') ) {
        $.ajax({
            method: 'GET',
            url: '/api/products/'
        }).done(function (data, status, xhr) {
            $.each(data, function (index, object) {
                $('#products .wrapper').append(`
                <div class="col-12 product">
                    <span class="products">${Drupal.t(object.field_supplier_products)}</span>
                </div>
                
                `)
            });
        });
    }
})

An example of some of the json returned from object -


    {
        "title": "Supplier 1",
        "nid": "1",
        "market_id": "2",
        "product_id": "15",
        "field_supplier_products": product1,
    },

So object.field_supplier_products returns "product1"

Kevin avatar
in flag
You're doing this on a site that isn't Drupal? The API needs to pass the translation in its response.
jfc avatar
us flag
jfc
The site is Drupal, I'm just using the Drupal REST API to generate my markup instead of a view
Jaypan avatar
de flag
So you're using a JS script in Drupal, to make a REST API call to the same Drupal instance (aka itself)? Is the call to `Drupal.t()` in the JS file making the call to the API? It's a little difficult to sort out your architecture to give a proper reply, so if you could explain the architecture, and where the call to `Drupal.t()` is located, it would be easier to provide assistance.
jfc avatar
us flag
jfc
I edited my post with some more details @Jaypan
Jaypan avatar
de flag
I still don't get your architecture, but I think I can see the problem now, and will add a solution below.
Score:0
de flag

Th problem is due to the fact that you are attempting to translate a variable, rather than a literal string:

Drupal.t(object.field_supplier_products)

In Drupal, variables should not be translated, for both security reasons, and to keep the translations table clean. Now, on the server side in PHP if you were to use the t() function around a variable, for example t($color) it would throw a warning, but the value should still be translatable (I haven't tried/checked in a few years). But if I recall correctly, with JS and the Drupal.t() function, it is not possible to translate variables at all. This is because the script Drupal actually parsed for the values by Drupal and re-generated with the translated values, cached with the translated values and this new file is sent to the browser. So no translation actually happens on the browser, the translation is actually enacted by PHP on the server, and a new file is generated before ever sending the file to the browser.

The solution is to ensure that your values are translated in the REST API so that they are already translated when your JS receives them, and will not require use of the Drupal.t() function. From your post it appears that the REST endpoint is also a Drupal instance, so to do this on the REST server you would:

  1. Set up the REST API server to be a multilingual site, with language detection by URL.
  2. Make your request to the API using the multilingual URL for the language to be retrieved.

For example, if your multilingual site differs by path prefix, you will have:

  • http://www.example.com/path/to/restserver [primary langauge]
  • http://www.example.com/[LANGUAGE_PREFIX]/path/to/restserver (LANGUAGE_PREFIX language)

Then, your JS would request the REST API from the relevant language path.

I often find it's beneficial to generate the URL on the server side, and pass this PHP generated URL, which will contain the language prefix for the current language, to the JS which then calls URL dynamically.

This is first done by creating a library that adds your JS file, and has a dependency on Drupal settings:

example_library:
  js:
    path/to/file.js: {}
  dependencies:
    - core/drupalSettings

Then, your render element would attach the library, and pass the URL to the JS file in the library:

use Drupal\Core\Url;
$page[
  'some_element' => [
    '#prefix' => '<div id="example_placeholder">',
    '#suffix' => '</div>',
    '#markup' => $this->t('Placeholder'),
    '#attached' => [
      'library' => ['[MODULE]/example_library'],
      'drupalSettings' => [
        'exampleModule' => [
          'ajaxCallbackUrl' => Url::fromRoute('[RESTAPI ROUTE]', [], ['absolute' => TRUE])->toString(),
        ],
      ],
    ],
  ],
];

Now, the script file.js will have access to the REST API URL with the language prefix, in the drupalSettings.exampleModule.ajaxCallbackUrl variable.

file.js:

function(drupalSettings) {

  function doSomething() {
    console.log(drupalSettings.exampleModule.ajaxCallbackUrl);
  }
}(drupalSettings));
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.