Friday
30
July
2010

How to add missing translations

Hy interested ones.

Today I want to get you informed about translation logging.

A site is always a living place. Existing content is changed, new content is available.

But when you have a multilingual site then this can create problems. You have to keep the translations up to date, otherwise your visitors will not see what you want them to see. So how can this be archived?

Zend_Translate contains all to handle this situation. First let’s create the wished translation adapter.

$translate = new Zend_Translate(array(
    'adapter' => Zend_Translate::AN_CSV,
    'content' => 'C:\www\translations\',
    'locale'    => 'en',
    'scan'      => Zend_Translate::LOCALE_DIRECTORY,
));

Our translation file for en should contain the following content:

Untranslated message;Untranslated message (EN)

Translation itself works from this point on.

Next we need to keep aware of untranslated messages. This is done by using a log. So let’s create a log to write to.

$writer = new Zend_Log_Writer_Stream('C:\www\translations\untranslated.txt');
$logger = new Zend_Log($writer);

Now let’s attach the log to the translation adapter.

$translate->setOptions(array(
    'log'   => $logger;
));

All messages which are untranslated will now be written into the file untranslated.txt as soon as the translation should occur. Of course this is only the simplest example. You can do much more things.

When someone wants to get a translation for our message in a language which is not translated you will have a new entry within the log file. Let’s expect someone wants to have a translation for german. He will get Untranslated message in return, which is the source message… this is correct behaviour from the users point of view. But our log file will now look like this:

2010-07-30T12:10:18+02:00 NOTICE (5): Untranslated message within 'de': Untranslated message

The message looks confusing? Then let’s change the output for our log:

$translate->setOptions(array(
    'logMessage'   => '%locale%;%message%';
));

Now our log will like like this:

2010-07-30T12:10:18+02:00 NOTICE (5): de;Untranslated message

Ok… but this is still no proper csv file. We want to have locale and message, and nothing more. Well, then let’s change the log formatter. Because timestamp and severity are created by Zend_Log. To change this you need to attach a formatter to your log.

$formatter = new Zend_Log_Formatter_Simple('%message%' . PHP_EOL);
$writer = new Zend_Log_Writer_Stream('C:\www\translations\untranslated.txt');
$writer->setFormatter($formatter);
 
$logger = new Zend_Log($writer);

Ok… that’s it. Now your log will look like this:

de;Untranslated message

Our full example looks like this:

$formatter = new Zend_Log_Formatter_Simple('%message%' . PHP_EOL);
$writer = new Zend_Log_Writer_Stream('C:\www\translations\untranslated.txt');
$writer->setFormatter($formatter);
	
$logger = new Zend_Log($writer);
	
$translate = new Zend_Translate(array(
    'adapter' => Zend_Translate::AN_CSV,
    'content' => 'C:\www\translations\',
    'locale'    => 'en',
    'log'   => $logger,
    'logMessage'   => '%locale%;%message%',
    'scan'      => Zend_Translate::LOCALE_DIRECTORY,
));

Zend_Log can also be used to add those “log” messages into a database. There is just one thing which can not be done this way.

It is not possible to recognise if a message has already been written or not. This means in the worst case that many messages will be duplicated into our log. On the other hand can you see which translations are requested many times and should be translated sooner than others. Anyhow… the above described features can be very usefull when your site is bigger or contains more than one translation file.

Have a nice frameworking

Greetings
Thomas Weidner
I18N Team Leader, Zend Framework

Zend Framework Advisory Board Member
Zend Certified Engineer for Zend Framework

Back to top
  1. Paul

    Tuesday, August 10, 2010 - 22:44:40

    $translate->setOptions(array(
    ‘log’ => $logger;
    ));

    minor correction:

    $translate->setOptions(array(
    ‘log’ => $logger
    ));

  2. Paul

    Tuesday, August 10, 2010 - 23:01:05

    //Send to Firebug Console Missing Translation;
    $writer = new Zend_Log_Writer_Firebug();
    $logger = new Zend_Log($writer);

    $translate->setOptions(array(
    ‘log’ => $logger
    ));

    ############################################

    Any reason the above should not work?

  3. thomasw

    Tuesday, August 10, 2010 - 23:14:19

    No firebug… no log…

    Also it could be problematic to have firebug always open 24h a day, and get the response from all other users of your site within your firebug session.

  4. Paul

    Thursday, August 12, 2010 - 01:15:43

    too bad.

    not 7/24 - conditional to non-prod environment;

    put all the code in one lump so it would make sense.

    but actually I have a sendToFirebug func which output only if dev environment. pretty handy. do the same thing for db profiler.

    thanks,
    - p

  5. Peter

    Friday, November 12, 2010 - 18:41:46

    You wouldn’t happen to know a solution for new lines would you? I’m logging untranslated strings to a log file, just like you, and read it into my mysql table with translations, and it all works just peachy. Until that is, there is a new line in my to translate string and the string is written in the log across 2 (or more lines) and hence, strings will not be entered correctly into my translation arrays.

  6. thomasw

    Friday, November 12, 2010 - 21:17:51

    How new lines are handled depends on the used adapter
    CSV for example needs an >”< sign to allow new line chars

    The same problems can occur by using other adapters. Generally it depends on the file format.

  7. postNuKe

    Sunday, February 20, 2011 - 23:06:45

    Its necesary include ‘logUntranslated’ => true, in array options