Class Translatable
The Translatable decorator allows your DataObjects to have versions in
different languages, defining which fields are can be translated. Translatable
can be applied to any DataObject subclass, but is mostly used with
SiteTree. Translatable is compatible with the Versioned
extension. To avoid cluttering up the database-schema of the 99% of sites
without multiple languages, the translation-feature is disabled by default.
Locales (e.g. 'en_US') are used in Translatable for identifying a record by language, see section "Locales and Language Tags".
Configuration
Through Object::add_extension()
Enabling Translatable throughObject::add_extension() in your
_config.php:
Object::add_extension('MyClass', 'Translatable');
This is the recommended approach for enabling Translatable.
Through $extensions
class MyClass extends DataObject { static $extensions = array( "Translatable" ); }
Make sure to rebuild the database through /dev/build after enabling
translatable. Use the correct Translatable::set_default_locale() before building the
database for the first time, as this locale will be written on all new
records.
"Default" locales
Important: If the "default language" of your site is not US-English (en_US), please ensure to set the appropriate default language for your content before building the database with Translatable enabled:
Translatable::set_default_locale(<locale>); // e.g. 'de_DE' or 'fr_FR'
For the Translatable class, a "locale" consists of a language code plus a region code separated by an underscore, for example "de_AT" for German language ("de") in the region Austria ("AT"). See http://www.w3.org/International/articles/language-tags/ for a detailed description.
Usage
Getting a translation for an existing instance:
$translatedObj = Translatable::get_one_by_locale('MyObject', 'de_DE');
Getting a translation for an existing instance:
$obj = DataObject::get_by_id('MyObject', 99); // original language $translatedObj = $obj->getTranslation('de_DE');
Getting translations through Translatable::set_current_locale(). This
is not a recommended approach, but sometimes inavoidable (e.g. for
Versioned methods).
$origLocale = Translatable::get_current_locale(); Translatable::set_current_locale('de_DE'); $obj = Versioned::get_one_by_stage('MyObject', "ID = 99"); Translatable::set_current_locale($origLocale);
Creating a translation:
$obj = new MyObject(); $translatedObj = $obj->createTranslation('de_DE');
Usage for SiteTree
Translatable can be used for subclasses of SiteTree as well.
Object::add_extension('SiteTree', 'Translatable'); Object::add_extension('SiteConig', 'Translatable');
If a child page translation is requested without the parent page already
having a translation in this language, the extension will recursively create
translations up the tree. Caution: The "URLSegment" property is enforced to be
unique across languages by auto-appending the language code at the end. You'll
need to ensure that the appropriate "reading language" is set before showing
links to other pages on a website through $_GET['locale']. Pages in different
languages can have different publication states through the Versioned
extension.
Note: You can't get Children() for a parent page in a different language through set_current_locale(). Get the translated parent first.
// wrong Translatable::set_current_locale('de_DE'); $englishParent->Children(); // right $germanParent = $englishParent->getTranslation('de_DE'); $germanParent->Children();
Translation groups
Each translation can have one or more related pages in other languages. This relation is optional, meaning you can create translations which have no representation in the "default language". This means you can have a french translation with a german original, without either of them having a representation in the default english language tree. Caution: There is no versioning for translation groups, meaning associating an object with a group will affect both stage and live records.
SiteTree database table (abbreviated) ^ ID ^ URLSegment ^ Title ^ Locale ^
| 1 | about-us | About us | en_US |
| 2 | ueber-uns | Über uns | de_DE |
| 3 | contact | Contact | en_US |
SiteTree_translationgroups database table ^ TranslationGroupID ^ OriginalID ^
| 99 | 1 |
| 99 | 2 |
| 199 | 3 |
Character Sets
Caution: Does not apply any character-set conversion, it is assumed that all content is stored and represented in UTF-8 (Unicode). Please make sure your database and HTML-templates adjust to this.
Permissions
Authors without administrative access need special permissions to edit locales other than the default locale.
- TRANSLATE_ALL: Translate into all locales
- Translate_<locale>: Translate a specific locale. Only available for
all locales set in
Translatable::set_allowed_locales().
Note: If user-specific view permissions are required, please overload
SiteTree->canView().
Uninstalling/Disabling
Disabling Translatable after creating translations will lead to all pages being shown in the default sitetree regardless of their language. It is advised to start with a new database after uninstalling Translatable, or manually filter out translated objects through their "Locale" property in the database.
- Extension
-
DataObjectDecorator
-
Translatable
implements
PermissionProvider
Author: Ingo Schommer <ingo (at) silverstripe (dot) com>
Author: Michael Gall <michael (at) wakeless (dot) net>
Author: Bernat Foj Capell <bernat@silverstripe.com>
See: http://doc.silverstripe.org/doku.php?id=multilingualcontent
Located at sapphire/core/model/Translatable.php
Methods summary
public static
|
|
public static
string
|
#
choose_site_locale( mixed $langsAvailable = array() )
Choose the language the site is currently on. |
public static
string
|
#
default_locale( )
Get the current reading language. This value has to be set before the schema is built with translatable enabled, any changes after this can cause unintended side-effects. |
public static
|
#
set_default_locale( mixed $locale )
Set default language. Please set this value before creating any database records (like pages), as this locale will be attached to all new records. |
public static
string
|
#
get_current_locale( )
Get the current reading language. If its not chosen, call |
public static
|
#
set_current_locale( string $locale )
Set the reading language, either namespaced to 'site' (website content) or
'cms' (management backend). This value is used in |
public static
|
#
get_one_by_locale( string $class, string $locale, string $filter = '', boolean $cache = false, string $orderby = "" )
Get a singleton instance of a class in the given language. |
public static
mixed
|
#
get_by_locale( string $class, string $locale, string $filter = '', string $sort = '', string $join = "", string $limit = "", string $containerClass = "DataObjectSet", string $having = "" )
Get all the instances of the given class translated to the given language |
public static
boolean
|
|
public static
|
#
enable_locale_filter( )
Enables automatic filtering by locale. This is normally called after is has
been disabled using |
public static
|
#
disable_locale_filter( )
Disables automatic locale filtering in |
public
array
|
#
getTranslatedLocales( )
Gets all translations for this specific page. Doesn't include the language of the current record. |
public
array
|
#
getAllowedLocalesForMember(
Gets all locales that a member can access as defined by |
public static
array
|
#
get_langs_by_id( string $class, integer $id )
Get a list of languages in which a given element has been translated. |
public static
|
|
public static
|
|
public static
boolean
|
|
public
|
|
public
|
|
public
array
|
|
public
|
#
augmentSQL(
Changes any SELECT query thats not filtering on an ID to limit by the current
language defined in |
public
|
#
augmentDatabase( )
Create <table>_translation database table to enable tracking of "translation groups" in which each related translation of an object acts as a sibling, rather than a parent->child relation. |
public
|
|
public
|
#
addTranslationGroup( integer $originalID, boolean $overwrite = false )
Add a record to a "translation group", so its relationship to other translations based off the same object can be determined later on. See class header for further comments. |
public
integer
|
#
getTranslationGroup( )
Gets the translation group for the current record. This ID might equal the record ID, but doesn't have to - it just points to one "original" record in the list. |
public
|
#
removeTranslationGroup( )
Removes a record from the translation group lookup table. Makes no assumptions on other records in the group - meaning if this happens to be the last record assigned to the group, this group ceases to exist. |
public
boolean
|
#
isVersionedTable( string $table )
Determine if a table needs Versioned support This is called at db/build time |
public
|
#
contentcontrollerInit( mixed $controller )
Note: The bulk of logic is in ModelAsController->getNestedController() and ContentController->handleRequest() |
public
|
|
public
|
|
public
|
#
onBeforeWrite( )
Recursively creates translations for parent pages in this language if they aren't existing already. This is a necessity to make nested pages accessible in a translated CMS page tree. It would be more userfriendly to grey out untranslated pages, but this involves complicated special cases in AllChildrenIncludingDeleted(). |
public
|
|
public
|
|
public
|
#
alternateGetByLink( string $URLSegment, integer|null $parentID )
Attempt to get the page for a link in the default language that has been translated. |
public
|
#
updateCMSFields(
If the record is not shown in the default language, this method will try to autoselect a master language which is shown alongside the normal formfields as a readonly representation. This gives translators a powerful tool for their translation workflow without leaving the translated page interface. Translatable also adds a new tab "Translation" which shows existing translations, as well as a formaction to create new translations based on a dropdown with available languages. |
public
array
|
#
getTranslatableFields( )
Get the names of all translatable fields on this class as a numeric array. |
public
string
|
|
public
|
|
public
|
#
getTranslations( string $locale = null, string $stage = null )
Gets all related translations for the current object, excluding itself. See
|
public
|
#
getTranslation( String $locale, mixed $stage = null )
Gets an existing translation based on the language code. Use |
public
|
#
createTranslation( string $locale )
Creates a new translation for the owner object of this decorator. Checks
|
public
boolean
|
#
canTranslate(
Caution: Does not consider the |
public
boolean
|
|
public
boolean
|
#
hasTranslation( string $locale )
Returns TRUE if the current record has a translation in this language. Use
|
public
|
|
public
string
|
|
public
|
#
providePermissions( )
Return a map of permission codes to add to the dropdown shown in the Security
section of the CMS. array( |
public static
array
|
#
get_existing_content_languages( string $className = 'SiteTree', mixed $where = '' )
Get a list of languages with at least one element translated in (including the default language) |
public static
string
|
#
get_homepage_link_by_locale( mixed $locale )
Get the RelativeLink value for a home page in another locale. This is found by searching for the default home page in the default language, then returning the link to the translated version (if one exists). |
public static
|
|
public static
|
#
set_allowed_locales( array $locales )
Define all locales which in which a new translation is allowed. Checked in
|
public static
array
|
#
get_allowed_locales( )
Get all locales which are generally permitted to be translated. Use |
public static
|
|
public static
|
|
public static
|
|
public static
|
|
public static
|
|
public static
|
|
public static
|
|
public static
|
|
public static
|
#
get_by_lang( mixed $class, mixed $lang, mixed $filter = '', mixed $sort = '', mixed $join = "", mixed $limit = "", mixed $containerClass = "DataObjectSet", mixed $having = "" )
|
public static
|
#
get_one_by_lang( mixed $class, mixed $lang, mixed $filter = '', mixed $cache = false, mixed $orderby = "" )
|
public
boolean
|
#
isTranslation( )
Determines if the record has a locale, and if this locale is different from
the "default locale" set in |
public static
|
|
public
|
|
public
|
|
public
boolean
|
#
augmentValidURLSegment( )
Extends the SiteTree::validURLSegment() method, to do checks appropriate to Translatable |
Methods inherited from DataObjectDecorator
augmentWrite(),
can(),
canCreate(),
canDelete(),
flushCache(),
load_extra_statics(),
onAfterDelete(),
populateDefaults(),
updateCMSActions(),
updateFieldLabels(),
updateFrontEndFields(),
updateSummaryFields()
Methods inherited from Extension
clearOwner(),
getOwner(),
get_classname_without_arguments()
Magic methods summary
Properties summary
protected static
string
|
$default_locale |
#
The 'default' language. |
protected static
string
|
$current_locale |
#
The language in which we are reading dataobjects. |
protected static
mixed
|
$tableList |
#
A cached list of existing tables |
protected
array
|
$translatableFields |
#
An array of fields that can be translated. |
protected
array
|
$original_values |
#
A map of the field values of the original (untranslated) DataObject record |
protected static
boolean
|
$locale_filter_enabled |
#
If this is set to TRUE then |
protected static
array
|
$allowed_locales |
#
All locales in which a translation can be created. This limits the choice in the CMS language dropdown in the "Translation" tab, as well as the language dropdown above the CMS tree. If not set, it will default to showing all common locales. |