Translating an Enum dropdown

Translating an enum

Creating a standard dropdown based on the values of an Enum db field isn't too difficult. The Enum class offers an enumValues() method, that will return the array ready to populate the DropDown. But, unfortunately, translating an Enum using the SilverStripe Enum class is not possible. The enumValues() method returns an array of options where both key an value contain the original enum values. Wouldn't it be great if enumValues() were to translate the value?

Note: (25-01-2012) this code will work, but it needs the language for the current language to be present!

The i18nEnum class

There's more then one way to do this, and I chose to extend the Enum class, which works quite nicely:

/mysite/code/i18nEnum.php

<?php
class i18nEnum extends Enum {

	/*
	 *  returns Enum values as a simple array
	 */  
	function getEnum() {
		return $this->enum; 
	}


	/*
	 *  Override the enumValues method and return a translated array
	 *  The translations always default to the original Enum values
	 *
	 *  $namespace: the namespace to use for the translations. Defaults
	 *              to 'Enum', but you should use the ClassName of the class 
	 *              that owns the Enum.
	 *
	 *              SomObject->enumValues($this->ClassName, true);
	 */ 
	function enumValues($namespace = 'Enum' , $hasEmpty = false) {
		$translatedOptions = array();

		$options = ($hasEmpty) ? 
			array_merge(array('' => ''), $this->enum) : 
			$this->enum;


		if (!empty($options)) {
			foreach ($options as $value) {
				$translatedOptions[$value] = _t("$namespace.$value", $value);
			}
		}
		return $translatedOptions; 
	}
}

Note: the only thing the i18nEnum can do, is provide an opening - a means to translate it. It's up to the object that owns the Enum, to provide the actual translations, since it knows what values its Enum contains...

Creating an i18nEnum on your page

In this example we're creating a color Enim on the page, and a dropdown field to display them:

/mysite/code/MyPage.php

<?php
class MyPage extends Page {


	// create an Enum that holds some colors
	public static $db = array(
		'Colors' => "i18nEnum('red, green, blue', 'red')"
	);


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

		// get the translated array to populate the dropdown. Note that for
		// the i18nEnum, we can provide a namespace for the translations 
		$namespace = 'MyPage';
		$options = $this->dbObject('Colors')->enumValues($namespace);

		$fields->addFieldToTab(
			'Root.Content.Main',
			new DropDownField(
				'Colors',
				_t('MyPage.SOMECOLORS','Some colors'),
				$options
		));

		return $fields;
	}
}

The language file

Make sure the languagefile now contains the following entries:

/mysite/lang/en_US.php

<?php

global $lang;

$lang['en_US']['MyPage']['red'] = 'red';
$lang['en_US']['MyPage']['green'] = 'green';
$lang['en_US']['MyPage']['blue'] = 'blue';

The i18nTextCollector

Instead of entering these values by hand, we can of course prepare the Page class in such a way that we can use the i18nTextCollector to generate the language file. Read up on this article 'Generate your languagefiles' how to use the this class and what the issues with the mysite module are. We'll use the Page's provideEntities method to automate this, just like we'd do for any other Page property. The simple version:

/mysite/code/MyPage.php

<?php
class MyPage extends Page {

	...

	function provideI18nEntities() {

		$entities = parent::provideI18nEntities();

		$entities["MyPage.red"] = array('red');
		$entities["MyPage.green"] = array('green');
		$entities["MyPage.blue"] = array('blue');

		return $entities;
	}
}

Or the more complex 'automatic' version - if its a large Enum:

/mysite/code/MyPage.php

<?php
class MyPage extends Page {

	...

	function provideI18nEntities() {

		$entities = parent::provideI18nEntities();

		$namespace = $this->ClassName;

		// get the original Enum values as a simple array
		$colorArray = $this->dbObject('Colors')->getEnum();

		foreach($colorArray as $color) {
			$entities["{$namespace}.{$color}"] = array($color);
		}
		return $entities;
	}
}

That's it :-)

Comments

Het versturen van reacties is uitgeschakeld.

RSS feed voor reacties op deze pagina