SSbits - Home page
Site by Carbon Crayon
Submit a Post >

Tutorials - Big bits of code to help you do more

Using Translatable to create a Simple Multilingual Site

SSBtranslatable2

I recently had a request to build a multilingual site for an accountant who wanted to enter content in EnglishRomanian and Russian, and wanted their site visitors to be able to switch languages by clicking on the image of the country flag - and I was pleasantly surprised to learn how quick and easy it is to implement using Silverstripe's Translatable class.

1. Set the default site locale

For me, I'm based in the UK, so my default local is en_GB, so in /mystie/_config.php, I added:

// Set the site locale
i18n::set_locale('en_GB');

2. Enable Translations in Silverstripe (Translatable)

Add the following lines to the /mysite/_config.php file

//default translation
Translatable::set_default_locale('en_GB');

/* restrict the language select dropdown in the admin 
   to only those languages that you will actually use.  
   In my case, UK English, Romanian and Russian */
Translatable::set_allowed_locales(array(
   'en_GB', //UK English
   'ro_RO', //Romanian
   'ru_RU'  //Russian
   )
);

3. Make your SiteTree and SiteConfig Translatable

SilverStripe needs to know which parts of our site we want to Translate so we tell it by adding the following to mysite/_config.php:

Object::add_extension('SiteTree', 'Translatable');
Object::add_extension('SiteConfig', 'Translatable'); // 2.4 or newer only

  Now  run /dev/build/ to rebuild the Database with the relevant translateable fields.

4. Add a simple language switcher to your template

Now that our site is translatable, we need to let users switch between languages so add this to your site template, (e.g. themes/yourtheme/templates/Page.ss):

<% if Translations %>
<div id="lang" class="clear">
  <ul class="clear">
  <% control Translations %>
    <li>
    	<a href="$Link" hreflang="$Locale.RFC1766" title="$Title - $Locale.Nice">
    		<img src="$ThemeDir/images/lang-<% sprintf(_t('IMAGE','%2.2s'),$Locale.RFC1766) %>.gif">
    	</a>
    </li>
 <% end_control %>
 </ul>	
</div>				
<% end_if %>

Incase you are wondering, RFC1766 is an ISO Language Identification Code Standard in which they have a "TAG" (not in the HTML/XML sense) for each language to identify what language is spoken and in what region. The language code list can be downloaded in CSV and Spreadsheet format here. However, Silverstripe uses underscores in the language code to seperate the language from the region in which it is spoken - and it also uses Uppercase letters for the region, so I have put together a simple Excel spreadsheet of Language codes available.

5. Add your flag images to the theme images folder,

Carefully following the naming convention used in the previous step add the flag images to themes/yourtheme/images.

In my case, I used the following image names:
lang-en.gif (UK flag for English language)
lang-ro.gif (Romanian flag)
lang-ru.gif (Russian flag)

Remember to flush your site template cache by adding /?flush=1 to the url.

6. Create your pages in the SiteTree. 

To add content other languages, use the new 'Translations' tab in the admin and off you go!

7. (Optional) Make DataObjects Translatable

To make a DataObject translatable, you must add the following to your mysite/_config.php:

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

Don't forget to run a /dev/build to rebuild the database afterwards.

Please note: When creating dataobjects in other languages, there is currently a bug in translatable causing all dataobjects to be added to the database using the default locale rather than selected locale.  In my case, I had to manually change the locales of the Romanian and Russian dataobjects in the database table from en_GB to en_RO and en_RU, respectively the very first time that I created the dataobject in a language other than the default.

That's all!  Good luck with creating your multilingual site!

Related Links

Official SS Translatable docs

SilverStripe rfc1766 Language Identification Codes spreadsheet

Special Thanks

Special thanks go to Aram Balakjian for their contributions to this post.

Darren-Lee avatar

Darren-Lee

Darren-Lee is an independent solutions architect facilitating start-ups, small businesses and non-profit organisations with web and mobile solutions based on open-source technology.

  • Darren-Lee
    09/04/2011 6:58pm (3 years ago)

    Apologies for typo in the above post - locales, "en_RO" and "en_RU" should say "ro_RO" and "ru_RU", respectively. I get Aram to change it.

  • dendeffe
    11/04/2011 9:46am (3 years ago)

    Nice write up Darren. Certainly easier then the language switcher I'm using now. Will have to give this a try.

  • swaiba
    11/04/2011 9:46am (3 years ago)

    Just a quick note that I've used this method as it comes straight out of the SS book. the flags are available here... http://www.famfamfam.com/lab/icons/flags/

  • Darren-Lee
    11/04/2011 10:29am (3 years ago)

    @dendeffe - Thanks - I'm encouraged as this is my first SSbits write-up.

    @swaiba - I can't believe it! Don't you just hate it when that happens? I had to go trawling through the forums for these answers - and all the time it was sitting in my SS book right under my nose! Next time I'll try the book first :) Many thanks for the link to the flags - very useful.

  • swaiba
    11/04/2011 10:43am (3 years ago)

    no problem - I've posted a bit of this on the forum from time to time - no I can just link to this :)

    I re-read the book every now again and normally find something new/useful that I'd forgotten since the first read.

  • Marcus Dalgren
    11/04/2011 10:40pm (3 years ago)

    For anyone doing a multilingual site keep in mind that entity translations (common in some modules) don't use the Translatable locale, they use the i18n locale. On the public site you probably want the entity translations to match the Translatable locale so set i18n locale = Translatable locale in your controller.

  • Morven
    16/04/2011 1:53am (3 years ago)

    Very comprehensive writeup, got a couple of these sites in the pipline. Hopefully this will make my life a bit easier :)

  • Darren-Lee
    16/04/2011 12:11pm (3 years ago)

    @Mo - cheers, dude. Glad you think this can help.
    @Marcus - thanks for the tip. Do you think, you can post an explicit example of what you mean for the benefit of all...? Even if you only post the one-line of code that goes into the controller, I'm sure many will find it helpful/useful. Many thanks.

  • spyrosk
    21/04/2011 9:13am (3 years ago)

    Hi Darren, really nice work, thank you!
    Quick question though, have you been able to change your url's to include non-Latin words? Or are they being transformed like this:

    www.yoursite.com/page-5/page-20

    I've been searching for this for quite some time but haven't been able to solve it.

  • Darren-Lee
    21/04/2011 11:57am (3 years ago)

    @spyrosk - glad you find it useful.
    I've not tried to change url to include non-latin words.

    On the site that I did, the English looks like this:
    http://www.yoursite.co.uk/services/

    the Romanian looks like this:
    http://www.yoursite.co.uk/services-ro-RO/

    ...and the Russian looks like this:
    http://www.yoursite.co.uk/services-ru-RU/

    The other way of accessing the other translations is like this:
    English (same as above)
    Romanian: http://www.yoursite.co.uk/services/?locale=ro_RO
    Russian: http://www.yoursite.co.uk/services/?locale=ru_RU

    Not sure if this answers your question or even helps you at all...
    If I've understood you correctly, are you saying that if one of your languages were Russian, you would like to see Russian characters in the URL?

  • spyrosk
    21/04/2011 2:21pm (3 years ago)

    Yes, although it's not a Russian site, I would like to be able to have non latin urls, which are beneficial to search engine rankings, but haven't been able to do so.

    Here's the thread in the forums in which I'm asking this as well:
    http://www.silverstripe.org/general-questions/show/15769

    From my understanding it has to do with SS's allowed characters in the urls but I haven't found a solution yet.
    Thank you again!

  • Pali
    24/04/2011 2:22pm (3 years ago)

    dont use i18n setup in mysite/_config.php, but place it in Page_Controller's init() method:

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

    so entity translations will match Translatable locale...

  • Kafil
    26/05/2011 1:21pm (3 years ago)

    Hi Darren
    I am a silverstripe beginner, you tutorial helped me a lot.
    I wanted to know if it is possible to have url like
    http://www.yoursite.co.uk/RO/services
    instead of
    http://www.yoursite.co.uk/services-ro-RO/
    so http://www.domain.com/lang/page

    I am using silverstripe 2.4.5

  • Darren-Lee
    26/05/2011 11:19pm (3 years ago)

    Hi Kafil,

    Glad you found the post helpful. There are several different ways to do what you need. The following posts come to mind.

    1) http://silverstripe.org/archive/show/4221
    2) http://doc.silverstripe.org/old/recipes:multilingual_content

    I have also read posts by people who have created a language node in the root of the sitetree for each language and then created pages under each of the language nodes in the appropriate language.

    I hope this helps.

  • Kafil
    01/06/2011 6:18pm (3 years ago)

    Hi Darren,
    Thanks for the links , will try the methods mentioned in there and see if i can achieve what i want :)

  • swaiba
    05/07/2011 7:16pm (3 years ago)

    Want widgets with that?

    http://silverstripe.org/widgets-2/show/11375

  • Axel Larator
    06/07/2011 8:24pm (3 years ago)

    Hello Darren,

    I followed the same thoughts, but made some tiny modifications, which I found in several SS related documentations.
    My website is in German/English and the language switching works like a charm. The translation of the pages is done via the Admin tool.

    The switch between German and English is done via <% control Translations %> in the footer section ( <% if Locale == "de_DE" %> ), done on the page level.(i.e. Impressum == Imprint).
    Plus an URL pointer in the sidebar, that points to the homepage of the other language. Take a look at valuegrid.com or valuegrid.de.

    In MyPage

    Translatable::set_default_locale('de_DE');
    Translatable::enable();
    Translatable::set_default_lang('de');

    Object::add_extension('SiteTree', 'Translatable');
    Object::add_extension('SiteConfig', 'Translatable'); // 2.4 or newer only

    Translatable::set_allowed_locales(array('de_DE', 'en_US'));

    // Set the site locale
    // i18n::set_locale('de_DE');
    // set the current locale based on the current translation language
    i18n::set_locale(Translatable::get_current_locale());

    switch(Translatable::get_current_locale()){
    case 'de_DE':
    setlocale(LC_TIME, 'de_DE', 'de_DE.UTF8', 'German', 'de-DE');
    break;
    case 'en_US':
    setlocale(LC_TIME, 'en_US', 'en_US.UTF8', 'English', 'en-US');
    break;
    }

  • Wezzlee
    06/07/2011 9:16pm (3 years ago)

    Hi thanks for the guide. This really helped me out. There is only one problem. I also use the ImageGallery module and this method does not seem to work with this module :( Anyone suggestions?

  • Wezzlee
    06/07/2011 9:25pm (3 years ago)

    Never mind I already figured out what was causing the problem.

  • Wezzlee
    06/07/2011 9:25pm (3 years ago)

    Never mind I already figured out what was causing the problem.

  • Darren-Lee
    10/08/2011 10:58pm (3 years ago)

    @Pali - thanks for sharing. Sorry I did not acknowledge your post before.
    @Axel - thank you so much for sharing - that's the spirit of the SilverStripe community.
    @Wezzlee - so you had a problem with the ImageGallery and then you solved it... did you ever think about sharing in a bit more detail about the problem you faced and then sharing the solution too? I think it would help the community to know a bit more about the problem you faced and what you did to solve your problem...

  • lerni
    26/08/2011 9:00am (3 years ago)

    To make DataObjects work with Translatable & DataObjectManager I've put a onBeforeWrite hook in the DataObjects. like...
    public function onBeforeWrite() {
    parent::onBeforeWrite();
    $this->Locale = Translatable::get_current_locale();
    }

    and also used this patch:
    http://open.silverstripe.org/attachment/ticket/4199/2.4.2-Translatable-FormField-controller-hack.diff

    what other/smarter solutions do others use?

  • Steven
    14/11/2011 2:44pm (3 years ago)

    Hello Darren,

    Maybe you can help me with this, since nobody could on the Silverstripe forum.

    How can you make Silverstripe see what your current language is using the t_ function?

    I tried translating a site, but it only works half. I use the dropdown on the left to switch between languages (I don't use the tab "Translations") and that works. Also, I have a translation file in the mysite/lang/ folder for the parts I want translated in mij .ss files. That also works, but only for the default language. Making a second translation file and switching between languages doesn't work unfortunately.

    In the .ss code I use this;
    <% _t('ProductHolder.VIEW','View') %>

    And in the translate file I use this;
    $lang['nl_NL']['ProductHolder']['VIEW'] = 'Toon';

    So, for nl_NL it works, but when I do this;
    $lang['en_GB']['ProductHolder']['VIEW'] = 'View';

    It doesn't work when I go to the English page.

    It seems the template doesn't see which language the user is in.

    Best regards,
    Steven

  • Adil Aliyev
    28/01/2012 9:44pm (3 years ago)

    Great. It helped me.

  • If_Else
    31/01/2012 1:46pm (3 years ago)

    Hello,

    I' trying to build a linking widget for internal links but can't get a tranlslatable Sitetree to work right it keeps showing my default locale.

    Can anybody help me

  • Aaron
    08/03/2012 4:59pm (3 years ago)

    Hi guys,

    Im new round these parts, trying to get Translatable to work on my Silverstripe website, I have followed this tutorial and have 3 site trees with various pages all successfully translated, however every word is in my default (english) across all the sites?? I cannot work it out.

    I am using version 2.4.6 and like I said have all the code from the tutorial in place but unfortunately none of the content is being translated at all.

    Does anyone have any ideas why this could be? I thought possibly due to the doc type not being set correctly although this and all meta tags, utf-8 etc are all standard from installation as never touched them.

    Would really appreciate any advice or suggestions on this as really puzzled.

    Thanks :)

    ps - great website and resources for someone new to Silverstripe, well done

  • ilovemoon
    10/04/2012 11:57am (2 years ago)

    Hi Darren,
    This is a great help, thanks so much.

    Is there a way to detect if a visitor is visiting from a country (say Spain) and giving them that language without them having to click on the flag?

  • siorp
    20/03/2013 10:27am (1 year ago)

    Hi all! Hope someone can help me.
    I've installed a SS 3.0.5, the translatable module, follow this very helpful post and the blog module. Everything seems to work fine but the template blog that doesn't change the language of "posted by..." the date format etc.

    I read a lot of posts but I am too dummy to solve the problem. Can someone help me?
    In my my site/_config.php I've set:
    i18n::set_locale('de_DE');
    Translatable::set_default_locale('de_DE');
    Translatable::set_allowed_locales(array('de_DE', 'it_IT', 'en_US'));
    // Important: Call add_extension() after setting the default locale
    Object::add_extension('SiteTree', 'Translatable');
    Object::add_extension('SiteConfig', 'Translatable');

    But still the template doesn't change when I switch to another language.

    Any idea?

    Thanks in advance.
    Pier

  • siorp
    20/03/2013 10:31am (1 year ago)

    PS you can see the website I am working to here: sitiper.it/blog

  • Timothy
    05/06/2013 4:58am (1 year ago)

    Thank you so much this was too easy! I spent ages trying to figure it out with the official docs, then I found your post. You put it in such a straightforward way unlike the official. Very much appreciated!

  • Timothy
    05/06/2013 10:29pm (1 year ago)

    Do you have an example of how to use the _T() function in a .js file?
    ie.

    $('#Form_ContactForm_LastName').attr("placeholder", "Nom *");

    What I want to be able to do is something like:

    $('#Form_ContactForm_LastName').attr("placeholder", "_t('Page.LastName', 'Last Name')");

    ?

  • Timothy
    05/06/2013 10:29pm (1 year ago)

    Do you have an example of how to use the _T() function in a .js file?
    ie.

    $('#Form_ContactForm_LastName').attr("placeholder", "Nom *");

    What I want to be able to do is something like:

    $('#Form_ContactForm_LastName').attr("placeholder", "_t('Page.LastName', 'Last Name')");

    ?

Post a comment ...

You cannot post comments until you have logged in. Login Here.

Advertisement

Site of the Month

Find SSbits on

Top Contributers

Rank Avatar Name
1 article image Aram Balakjian
2 article image Daniel Hensby
3 article image Marcus Dalgren
4 article image Hamish Campbell
5 article image Ty Barho
6 article image Martijn van Nieuwenhoven
7 article image Darren-Lee
8 article image Roman Schmid
9 article image Matt Clegg
10 article image dalesaurus

View full leaderboard


Advertisement