Search code examples
silverstripesilverstripe-4

How to access Locale field values through ::get() using Silverstripe Fluent


We are working on a project using Silverstripe with the Fluent module to enable multiple translations.

Here's an example Data Object with Fluent enabled. First we create the Data Object & explicitly set the CMS fields:

namespace Yard;

use SilverStripe\ORM\DataObject;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TextField;

class Milkshake extends DataObject {
  private static $table_name = 'Milkshake';

  private static $db = [
    'Title' => 'Varchar(255)'
  ]

  public function getCMSFields() {
    $fields = new FieldList(
        new TextField('Title', 'Milkshake Title', null, 255)
    );
    $this->extend('updateCMSFields', $fields);
    return $fields;
  }
}

Then we set Title as translatable in a YML file:

Yard\Milkshake:
  extensions:
    - 'TractorCow\Fluent\Extension\FluentExtension'
  translate:
    - 'Title'

This gives us an object with a translatable Title field that can have different values in different locales. It creates the following database table:

Milkshake_Localised

ID | RecordID | Locale | Title

So far so good, except using:

$milkshake = Milkshake::get()->first() doesn't return the localised data & pulls from the Milkshake table.

I think it could be possible to use:

$locale= FluentState::singleton()->getLocale();
$milkshake = Milkshake_Localised::get()->filter(['Locale' => $locale])->first();

But this feels clumsy & has no fallback if the locale data doesn't exist for that field (at which point it should fall back to the default locale, or failing that the original Milkshake field).

What is the correct way to access Locale data in Fluent so there is a fallback if required?


Solution

  • I got the desired behaviour by wrapping the get command in "withState"

    use TractorCow\Fluent\State\FluentState; 
    
    $milkshake = FluentState::singleton()->withState(function (FluentState $state) {
     return Milkshake::get()->first(); 
    });