Wednesday, March 8, 2017

Drupal & Ubercart: Translating the Seemingly Un-Translatable (D6U2)

Drupal handles internationalization in many ways - maybe too many!

Lately I have been working with Drupal a lot.  It is a powerful CMS, a System designed to Manage and present Content (text and data) on the Internet.  One of the more valuable features of Drupal is that it can switch languages, catering to the linguistic preferences of the visitor and presumably making the website more alluring and "sticky".  One of the websites that I have developed features a language selector in the form of a country flag and the name of the language in question.  Clicking on either takes the  visitor to the indicated language:

For the visitor, languages are easy.  Just click on the language you want and the Drupal system makes it happen.  If only it were that easy on the back end!

Unfortunately, Drupal has no less than four (4) ways to accomplish internationalization.

  1. Via translation files, which have the extension .po
  2. Via the Translation Interface, which is used to translate things missed by the .po files
  3. Via Translate Strings, which requires that they be registered with Drupal
  4. Via changes to the Drupal source code (PHP)
There does not appear to be a great deal of consensus between Drupal developers when it comes to internationalization, at least not with respect to Drupal 6.  Admittedly, this version is quite old now, but the frustrations of internationalization were highlighted to me while dealing with the multilingual capabilities of uc_coupon, a Drupal module that helps website administrators to issue and manage coupons.  When it was first developed, it didn't consider internationalization.  Then, after some complaints, it was updated to incorporate the t() function, which is the internal I18N function call in Drupal that checks for a matching string in the current language context against some "root" language (for me, that's English).

In this example, we are working with code extracted from uc_coupon-6.x-1.7.tar.gz., which the maintainer (who I know and who is a nice, hard working guy) avows has been internationalized:

Confirming this is easy, simply crack open modules/uc_coupon/uc_coupon.module and take a look.  The proof of his word appears on or around line 998:

$form['uc_coupon_pane_description'] = array(
    '#type' => 'textarea',
    '#title' => t('Checkout pane message'),
  '#default_value' => variable_get('uc_coupon_pane_description', t('Enter a coupon code for this order.')),

...and also on or around line 949:

$description = variable_get('uc_coupon_pane_description', t('Enter a coupon code for this order.'));

Furthermore, these are the only places in the code base where the phrase 'Enter a coupon code for this order.' appears.:

# grep "Enter a coupon" * -R
uc_coupon.module: $description = variable_get('uc_coupon_pane_description', t('Enter a coupon code for this order.'));
uc_coupon.module: '#default_value' => variable_get('uc_coupon_pane_description', t('Enter a coupon code for this order.')),

Now, the presence of the t function bounding the phrase should make the phrase in question translatable.  All one has to do is go to the Translate Interface... for the string in question ('Enter a coupon code for this order.') 

...Choose the translation to edit with...

...and supply its translation in the target language context...

But sometimes doing all of this still doesn't work:

The English string is still there, even though the Translation Interface has managed to convert everything else to Chinese, which means that it is doing its job, just not with respect to the string 'Enter a coupon code for this order.'  

Thankfully, I have seen this before.  Just recently, I found out that the t() function was being ignored for certain values in Drupal.  In my case, it happened when I was dealing with the Submit Order button on the checkout screen for PayPal,  I wanted to change the text to Go Pay in both English and Chinese.  As I (eventually) found out, multilingual variable management in Drupal out-ranks the Translate Interface function, and works in a completely different way.

When working with multilingual variables, you do this:

Navigate to the place where the multilingual variable is, enter the string you want the field to hold and click on Save:

...then switch to the target language context using the language selector...

...Then enter the desired translation and click on Save.

So the challenge with multilingual variables is rooting out where they are registered

Sometimes, like with the PayPal checkout button, they appear in the menu system.  This devolves into a fishing expedition where you click around in the Drupal administration menu system looking for the appearance of a field holding 'Enter a coupon code for this order.'  This can be a very lengthy and frustrating exercise, because of the way Drupal module developers insert functions.  It can sometimes be a little willy-nilly.  

In this case, I was lucky.  I found the multilingual variable in the following area:

Home » Dashboard » Store administration » Configuration » Checkout settings » Coupon discount settings

Treating this situation exactly like that of the PayPal button resolved the issue.  I switched language contexts, entered the Chinese translation and clicked on Save:

Once I was done, the website displayed the message in the correct language:

No comments:

Post a Comment