Magento, being the behemoth it is, supports a wide range of functionality. One of the simplest but most powerful features is the locale aware, translation system.

I'm not going to go into how the translation system works because people smarter than I have already covered that in great detail. However, what I want to point out today, could help you down the line when you have to change your translation strings or more importantly, when other people have to change your translation strings.


You can instruct Magento to add a string to the translation engine by using the "double-underscore method" __('Translate me'). Behind the scenes, the function simply takes all the arguments passed to __(), shifts the first item off the arguments array, i.e. the text to be translated, and creates a new Mage_Core_Model_Translate_Expr object, it then puts the object back to the top of the stack of arguments and sends it on to Mage_Core_Model_Translate class, which works some locale magic and some other functionality related to translating via config xml files and eventually calls the native PHP function vsprintf.

The problem

The vsprintf function takes the format string parameter and an array of values to be substituted into the format string. Typically, that looks something like this:

$text = vsprintf('Hello %s', array('John'));
// or in Magento (in a template)
$text = $this->__('Hello %s', 'John');
// 'Hello John'

Using the `%s` specifier, we instruct the function to replace %s with a string value, in this case 'John'.

What you may not know, is how limited this approach can be, for instance, what if you want to use the same variable twice in one sentence. Using the above approach, you end up with something like this:

text = $this->__('Hello %s, my name is also %s', 'John', 'John');
// 'Hello John, my name is also John'

Also, if you have more than one variable in your format string and you need to change the structure of your sentence, which might mean swapping the order of variables, you'll have to go back into your template and swap the variables around.

$text = $this->__('Hello %s, my name is %s.', 'John', 'Pete');
// With this format string, you can't change the order to say:
// 'Hello Pete, my name is John.'

If you're not a programmer or have no idea what HTML is, then changing translation strings, which should be simple for anyone, becomes an impossible task and you end up handing the task over to someone else on your team.

A better way

The code above breaks the Don't Repeat Yourself principle pretty effectively. In order to be a responsible developer and not break the single worst offence a programmer can commit, we can leverage Argument Swapping.

Argument Swapping gives us a method to define a number for a particular variable. We can now use variable swapping to solve the problem above:

$text = $this->__('Hello %1$s, my name is also %1$s', 'John');
// 'Hello John, my name is also John'

Being responsible

If you've ever had to manage translation strings where someone hasn't used variable swapping in their format string, then you've likely had to go back into the template and re-order how the variables were passed in, this process is time consuming and very frustrating. Let's be responsible developers and format all our strings with variable swapping in mind, that way, when we have to change the wording but not the variables, we can make the change in one place and we're done. Here's an example of how that might work.

// Before:
$this->__('Error [%1$s]: The %2$s field is invalid.', $error, $field);
// After:
$this->__('The %2$s field is invalid: %1$s' $error, $field);

Hopefully I've convinced you that this is the best way to format your translation strings, if you have anything you'd like to add or discuss, please leave a comment below.