Make product fields multi-language in PrestaShop and ThirtyBees

In this tutorial we will learn how to make product fields translatable in PrestaShop 1.6, and see how to apply the method to the “price per…” field.

Introduction

You might have come across the need to translate the price per unit field in your PrestaShop or Thirtybees, but crashed against the software’s limitation, as that’s a single language property. Any product field can be made multi-language with a simple modification, so let’s see how to do it using the Unity one as example in this tutorial!

Step 1 – Adding the new database column

In order to make the field translatable, we have to add it to the product_lang table in the database. Not only, but we also have to erase the same column in both the product and product_shop tables, to avoid conflicts when retrieving values from the database. Let’s add it first!

Using phpMyAdmin or Adminer, locate the *prefix*product_lang table in your database, and add a new column as VARCHAR, 24 characters long. Once done, it will look like this:

multilang_field_db

Next, let’s get rid of the leftovers: open the *prefix*product table and drop the unity column first, and then on the product_shop table.
We are done! We just broke the Product class though, and have to compensate by letting it know where to grab the new values from.

Step 2 – Editing the product class

We have a new column in the database, but at this point the Product class would still just ignore it. To have it lookup, and save into the correct table, we must tell it that the property we are wanting to translate is a multilanguage field. To do so, we must change its definition.

Open up Product.php, located in the classes/ folder.

Scroll down until you find the following line, part of the $definition property:

'unity'                     => ['type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isString'],

To make any field translatable, we can simply add ‘lang’ => true as follows

'unity'                     => ['type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isString', 'lang' => true],

Please notice that, as always, using an override is strongly recommended, instead of editing core files.

Step 3 – Editing the back office

The controller

This is the most complicated part, as we will have to edit both the admin controller for products, and the correct template. For our example, the template is prices.tpl, but it will be different if the field you want to translate is in another tab.

Let’s start with the controller. The prices template does not offer us any option for translating fields, and therefore misses the indispensable $languages variable.
Open up AdminProductsController, located in controllers/admin

We are interested in the method called initFormPrices, so once you find it you can simply clone that to an override, or continue editing the core.

Right after $data is assigned, at the very beginning of the function, but before $product = $obj, add the following

if (!$this->default_form_language) {
    $this->getLanguages();
}
$data->assign(array(
    'languages'=> $this->_languages,
    'id_lang' => $this->context->language->id,
    'default_form_language' => $this->default_form_language,
));

Explanation: Nothing too complex here, we are first checking if languages are loaded, and if not, assigning them to the controller. Then, we simply assign that class property to the template, along with a few other required ones. Please notice we do not use a common smarty assign, but the $data variable instead.

The template

Time to make our changes visible in the back office! For the unity field, let’s open up *admin folder*/themes/default/template/controllers/products/prices.tpl

Locate the input with id unity, which will look more or less like the following:

<input id="unity" name="unity" type="text" value="{$product->unity|htmlentitiesUTF8}"  maxlength="255" onkeyup="if (isArrowKey(event)) return ;unitySecond();" onchange="unitySecond();"/>

Instead of this input, we will use a handy template PrestaShop makes available to us. Replace the above with the following code:

{include file="controllers/products/input_text_lang.tpl"
languages=$languages
input_class="{$class_input_ajax}{if !$product->id || Configuration::get('PS_FORCE_FRIENDLY_PRODUCT')}copy2friendlyUrl{/if} updateCurrentText"
input_value=$product->unity
input_name="unity"}

Save and refresh, and you will see the new field, translatable, appearing in the prices table of the back office. Time to test it, and see if it’s saving properly.
We can take an extra step and translate the preview below as well:

<span id="unity_second">{$product->unity}</span>

to

<span id="unity_second">{$product->unity.{$id_lang}}</span>

At this point we can go ahead and test the Front Office. If everything has been done correctly, as soon as you change language, the class should automatically pick the correct translation for the field. Neat!

You like the tuts and want to say "thank you"? Well, you can always feel free to donate:

  • Marcin

    Hi, thanks for tutorial, unfortunately on the front i have an empty $product->unity… have no idea why, all works fine in BO except fact I had to remove ajax from input_class part:

    {include file=”controllers/products/input_text_lang.tpl”
    languages=$languages
    input_class=”{$class_input_ajax}{if !$product->id || Configuration::get(‘PS_FORCE_FRIENDLY_PRODUCT’)}copy2friendlyUrl{/if} updateCurrentText”
    input_value=$product->unity
    input_name=”unity”}

    Prestashop 1.6.1.12

    • NemoPS

      Marcin,
      Are you sure you set it up in the class so that it draws from that new column? What is the error reading?

      • Marcin

        Yeah I am sure, tried to repear whole process dozens of time but with the same result – it looked like back office used new field in db while front office old.

        Finally I’ve made a new value “unity_text” and added new function Product::getUnityText (https://scr.hu/60do86) and it works okay now.

You like the tuts and want to say "thank you"? Well, you can always feel free to donate: