DataObjects: Translatable or not?

DataObjects: Translatable or not?

It is not just pages and the siteConfig that can be made translatable - the same goes for any DataObject in SilverStripe by just adding

Object::add_extension('MyTranslatableObject', 'Translatable');

So how do you decide what to make translatable and what not? Or: what happens to a DataObject when it has been made Translatable?

  1. A new database field 'Locale' is created.
  2. Queries like DataObject::get will automatically become localized and return only objects belonging to the current Locale
  3. A TranslationGroup table is made to track the relation between related translated objects

The locale field and localized queries

In the case of a simple lookup table, or an object that is only ever going to be used in relation to a specific page, making that object Translatable is not absolutely necessary.

In a localized query SilverStripe will automatically add the current Locale as an extra fillter, so only objects that belong to the current language are returned. If that's what you're aiming at, you should definitely make such an object translatable.

Show all objects

But Translatable or not, there might be situations where you still want to show all objects. In that case you can temporary disable the Locale filter before performing the query:

$result = DataObject::get('MyTranslatableObject');

But how about he translation group?

Adding a Locale field and filtering on same Locale is something you could easily do yourself. But one other real objective of Translatable is the creation of a Translation group where the relation between translated objects is secured. For Pages this is nicely implemented by the 'create translation' button, but there is no such thing for custom DataObjects.


When a page is translated, related objects are not translated alongside. You have to add them anew, and at that point there is no relation between the original object and the newly added translation. The ComplexTableField and its brethren have no facilities for that.


ModelAdmin has no native support for Translatable. Oh, you can add new locales, but I haven't even an idea whether the search is localized - and based on what Locale (test this)... There is a TranslatableModelAdmin module available on GitHub, that I haven't tested yet, but that is said to offer some tools to manage Translatable DataObjects...

Conclusion: the Locale and Localized queries are no problem. But maintaining consistent Translation groups - and use them - is not very obvious. One use for a consistent Translation Group would be the use of 'hints'. So definitely something to look into

Note: also think of a 'create Translation' button in the ComplexTableField that really translates a DataObject, copying it to the pages counterpart in the other language as well???

 Fix: ComplexTableField and Translatable objects

Adding DataObjects to a translated Page using the ComplexTableField (CTF) poses no problem - as long as the objects themselves are not set to Translatable! Once they are made Translatable and a Locale field is added, things go wrong. For some reason the Locale is always set to the default. That can leave you with a DataObject pointing to the ID of a dutch Page, but having the en_US locale. You'll find it displays fine after adding it and closing the popup, but then disappears once you turn back to that Page later.

Possible solution: this patch

There are two glitches though:

1. When scaffolding is used to build the popup, the Locale field is displayed as an editable TextField, where I think it should be a HiddenField. Adding a getCMSFields() method like this should fix this:

function getCMSFields() {
	$fields = parent::getCMSFields();

	if (Object::has_extension($this->ClassName, 'Translatable'){

		// this works, but is a bit rough
		// $fields->push(new HiddenField('Locale', 'Locale'));

		// this is nice, but I haven't tested it yet...
		$fields->ReplaceField('Locale',new HiddenField('Locale', 'Locale'));
	return $fields;

2. In a custom function like getCMSFieldsForPopup(), where no parent::get... is used, you should add the Locale yourself:

$fields->push(new HiddenField('Locale', 'Locale'));


The SilverStripe guys have built a module TranslatableModelAdmin that can be found here on GitHub. It is supposed to provide support for translatable objects (nothing more) but I haven't tested it yet.


  • Hi there,
    I think it would be a good idea to post a question like this on the SilverStripe forums ( You'll find me there quite often as well :-)

    Anyway, I did a DataObject::get('Page') and found the query to be localized in my 246 version... (did you do a ?showqueries=1 to see the actual query?)


    Verstuurd door Martine, 02/01/2012 12:08pm (8 jaar geleden)

  • Hi,

    im using this really simple setup, but im surprised with odd behaviour.

    This code will return only localized pages:
    return DataObject::get("SiteTree");

    this is returning all pages - doesn't care about locale:
    return DataObject::get("Page");

    SS version:
    SS 2.4.6


    mysite/code/Page.php >> Page_Controller:

    public function init() {


    if($this->dataRecord->hasExtension('Translatable')) {
    setlocale(LC_TIME, $this->dataRecord->Locale . ".utf8");


    Is this standard behaviour?



    Verstuurd door Pali, 28/12/2011 3:28pm (8 jaar geleden)

Het versturen van reacties is uitgeschakeld.

RSS feed voor reacties op deze pagina