0

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, I am using this 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.

With the following code, I can see the translations.

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

Is there any possible way or workaround to use Drupal.t() with variables?

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.

(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>
        `)
      });
    });
  }
})

With the following data, object.field_supplier_products returns "product1".

{
    "title": "Supplier 1",
    "nid": "1",
    "market_id": "2",
    "product_id": "15",
    "field_supplier_products": product1,
}
5
  • You're doing this on a site that isn't Drupal? The API needs to pass the translation in its response.
    – Kevin
    Jan 18, 2022 at 17:34
  • The site is Drupal, I'm just using the Drupal REST API to generate my markup instead of a view
    – jfc
    Jan 18, 2022 at 17:39
  • 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.
    – Jaypan
    Jan 18, 2022 at 17:51
  • I edited my post with some more details @Jaypan
    – jfc
    Jan 18, 2022 at 18:07
  • I still don't get your architecture, but I think I can see the problem now, and will add a solution below.
    – Jaypan
    Jan 18, 2022 at 18:10

1 Answer 1

1

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));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.