TranslatableDataObject: Insanely simple translation

3 Apr

TranslatableDataObject: Insanely simple translation

It turns out French-speaking SilverStripe developers are hard to come by. Now that I have contracts with two SilverStripe developers in France, I’m thinking I may have found my niche — my very, very targeted niche.

I was doing work for one my my new clients last week  who needed to add translations to his ModelAdmin-managed DataObjects. The Translatable module was failing him. As robust and well-supported as it is, we can identify the limitations of the Translatable module quite easily:

  1. It works only with SiteTree descendants
  2. It requires a UI (much like Versioned)

This opens up a need for a simple, code-based translation tool, and what I came up with is TranslatableDataObject.

Usage

MyDataObject.php

static $db = array (
  'Title' => 'Varchar',
  'Description' => 'Text'
);

_config.php

TranslatableDataObject::set_locales(array(
  'en_GB',
  'fr_FR',
  'it_IT'
 ));

 TranslatableDataObject::register('MyDataObject', array(
  'Title',
  'Description'
 ));

Running /dev/build will now add the following fields to MyDataObject:

  • Title__en_GB
  • Title__fr_FR
  • Title__it_IT
  • Description__en_GB
  • Description__fr_FR
  • Description__it_IT

To add the edit fields to the CMS, you have several options.

1. Add all translated fields for all languages to a given tab

foreach($this->getTranslationFields() as $field) {
   $f->addFieldToTab("Root.Translations", $field);
}

2. Add all translations for a given field name to a tab

foreach($this->getTranslationFields("Description") as $field) {
   $f->addFieldToTab("Root.Descriptions", $field);
 }

 foreach($this->getTranslationFields("Title") as $field) {
   $f->addFieldToTab("Root.Titles", $field);
 }

3. Add all fields for a given translation to a tab

foreach($this->getTranslationFields(null, "fr_FR") as $field) {
   $f->addFieldToTab("Root.FR", $field);
}

foreach($this->getTranslationFields(null, "en_GB") as $field) {
  $f->addFieldToTab("Root.EN", $field);
}

Retrieving the translation on the template

You can use the $T() accessor to retrive the correct field based on the current locale.

$T(Title)

$T(Description)

Limitations

Unlike Translatable, this utility does not create new records for each translation. Translations are added horizontally (i.e. with new columns) rather than vertically (i.e. with new rows). That creates a scalability problem. If you have 10 languages and eight fields that require translation, you’ve just added 80 columns to your table, which, in my understanding of MySQL, will blow things up. Therefore, use this module only for limited translation needs. In my experience, that’s usually all people need, but, then again, I’m in the US, where internationalization is like garnishing a cheeseburger — it’s a nice gesture, but no one really cares.

Getting the code

Umm, it’s on Github.

https://github.com/unclecheese/TranslatableDataObject

13 Responses to “TranslatableDataObject: Insanely simple translation”

  1. francisco 20. Apr, 2012 at 9:20 pm #

    well… i think it looks really interesting and easy to use. thats all what i need for a module. truly UC’s quality :)

  2. Robert 27. Apr, 2012 at 4:29 am #

    Great stuff … like always.

    *Thumbs Up*

  3. Herbert Cuba Garcia 01. May, 2012 at 6:04 pm #

    Hi Uncle Cheese!

    Great little writeup! Im always impressed of the tidy and simple code you always produce. I, myslef, have also tried to solve the translatable module problems that our web projects face. We are mainly developing ecommerce sites and use our own module for e-commerce sites on Silverstripe. The biggest issue we have regarding languages is that we dont want to translate relations between dataobjects and/or sitetrees. We want same structure, but want to translate single fields only.

    I made a small module called multilingual that is based on the multilingual recipe that you, yourself use. Its a bit more “automatic” than yours, but it also lacks the cleanness in code that yours have. Please, you are more than welcome to have a look and maybe contribute? I think one could merge these two “modules” to one great multilingual/translatabledataobject module.

    https://github.com/kreationsbyran/multilingual

  4. Sewer 31. May, 2012 at 2:56 pm #

    Thanks for useful module.
    I noticed strange behaviour, when I tried to add multilingual fields to DataObject by using decorator (to File class, precisely). Multilingual fields showed up, but they were all in main tab, regardless of what I tried to do in updateCMSFields() function.

  5. Paul 15. Aug, 2012 at 11:45 pm #

    Thank you very much for this extension!
    Is it possible to use it on a page too?
    Thank you

    • unclecheese 16. Nov, 2012 at 1:17 pm #

      Yes, you can use this on pages, but it doesn’t support translatable URLs.

  6. Eduardo Cesario 16. Nov, 2012 at 12:37 pm #

    Hi there Uncle!
    I have a question: where should be placed your Translatable.php code in the site?

    Thanks a lot

    • unclecheese 16. Nov, 2012 at 1:16 pm #

      You can put it in your code directory!

      • Eduardo Cesario 16. Nov, 2012 at 1:23 pm #

        Sorry to bother you again, but it seems like designers need more specifications to work with:

        MyDataObject.php
        That file is placed in mysite/code ?

        _config.php
        is mysite/_config.php wich i need to add those lines?

        TranslatableDataObject.php
        where exactly shoud be placed?
        in mysite/code ?

        thanks for your patience

        Eduardo

        • unclecheese 18. Nov, 2012 at 11:50 am #

          Yeah, you should never be modifying anything outside your mysite (or themes) directory.

          • Sabin Farley 22. Jan, 2013 at 9:17 am #

            Hi Uncle, using 3.0.3 along Translatable, gives me a blank screen upon rebuild. Followed your instructions closely. I presume your code is for SS3 as it was offered last April.

            Is there a way i can detect which language is on?

            Like,

            Thanks!

  7. Thomas B. Nielsen 27. Mar, 2013 at 8:49 am #

    Hi UC, thank you for this code, it helps a lot!

    I’, using SS2.4 but i can’t get the Option 3 to work.
    Trying to create a tab for each language – but it just gives me all fields, even if im using the language filter.

    Can you share an example of how that is done?

    (It would also be nice to see the complete code for the demo – all the relevant parts put together)

    Thank you for sharing all your nice work.

  8. Tom 12. Jul, 2013 at 1:39 pm #

    Hi Aaron, Great Stuff! I’m trying to implement this with a relatively small project which is done with the Silverstripe 3.1 (beta 3). There were some compatibility issues which I could manage to fix but one problem is still bothering! Saving the Object with a Field type of HTMLText causes an error. Varchar and Text types are working properly.
    ERROR [User Error]: Uncaught Exception: HtmlEditorField->saveInto(): This field should save into a HTMLText or HTMLVarchar field.
    Do you have any idea?
    I am using the Translatable Module and the Better Buttons (your another great stuff!!!) as well.
    Thank you very much in advance!

Leave a Reply