Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Archive /

Our old forums are still available as a read-only archive.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo

Pretty i18n URLs: alternative (for multilingual pages)


Go to End


5 Posts   4832 Views

Avatar
Anatol

126 Posts

24 November 2008 at 5:46pm

Edited: 24/11/2008 6:12pm

Hi,

I am currently building my first multilingual Silverstripe site. Here is an alternative way (compare recipes:pretty_i18n_urls) to build pretty URLs of the kind en.domain.com/news/ instead of domain.com/news/?lang=en

It does not require any changes in the Silverstripe core code, but you may have to add some DNS entries for your domain.

All the magic happens in the .htaccess file. Simply add the red lines to your .htaccess file and adjust them to your needs:

### SILVERSTRIPE START ###
RewriteEngine On
RewriteBase /


# MULTILINGUAL SUBDOMAIN SETTINGS
RewriteCond %{HTTP_HOST} ^(en|mi)\.domain\.com
RewriteRule ^(.*) $1?lang=%1&%{QUERY_STRING}

RewriteCond %{REQUEST_URI} !(\.gif)|(\.jpg)|(\.png)|(\.css)|(\.js)|(\.php)$ 

RewriteCond %{REQUEST_URI} ^(.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* sapphire/main.php?url=%1&%{QUERY_STRING} [L]
### SILVERSTRIPE END ###

(en|mi) are the language codes for the available translations of your site. In this case it's English and Māori, for e.g. English, French and German just use (en|fr|de) instead.

In the same line also replace \.domain\.com with your domain name.

This simply translates the URL en.domain.com/news/ to domain.com/news/?lang=en. No links or references to files and images need to be changed.

URLs such as www.domain.com, domain.com, www.domain.com/news and domain.com/news will display your default language.

I had to add CNAME entries to my DNS records to make it work, i.e.:

Name: mi.domain.com
TTL: 3600
Type: CNAME
Value: domain.com. (add the trailing dot ".")

And the same for en.domain.com

(It may take a couple of minutes to a few hours until these new DNS entries are propagated and you can see the effect.)

This method solves a couple of problems I had with multilingual pages:

* The URL is unique for each language (no browser caching problems and no need to set "HTTP::set_cache_age(0);" in the _config.php file which would slow down everything)

* I would like to use the existing pretty_i18n_urls recipe but I never liked that "you need to have distinct page names for all languages. /en/news and /fr/news will give you the news page from the default language. SS does not honor language/page combinations, it.seems" It is no problem to have the same page name for all languages with the method described here.

* I quite like that I don't have to touch core code (or any PHP code).

This method is not yet much tested but so far it works for me without problems. Any comments and suggestions are welcome.

Just as a thought (this is completely untested): I think with another .htaccess rewrite rule it should be quite easy to enable translated images. You would just have to check a folder that contains language specific images: if the image exists then use it, otherwise use the image of the default language.

I hope this is helpful.

Cheers!
Anatol

Avatar
kudesign

Community Member, 64 Posts

28 November 2008 at 1:41am

Kiora, thanks for an innovative way to deal with multi-lingual! if i want to switch between 3 or 4 different languages, do I just add in additional languages in the .htaccess file? e.g:

# MULTILINGUAL SUBDOMAIN SETTINGS
RewriteCond %{HTTP_HOST} ^(en|mi)\.domain\.com
RewriteCond %{HTTP_HOST} ^(fr|mi)\.domain\.com
RewriteCond %{HTTP_HOST} ^(zh|mi)\.domain\.com
RewriteRule ^(.*) $1?lang=%1&%{QUERY_STRING}

sorry, I am new to coding... cheers!!

Avatar
Anatol

126 Posts

28 November 2008 at 10:25am

Edited: 28/11/2008 10:27am

Hi,

Just do the changes in one line:

# MULTILINGUAL SUBDOMAIN SETTINGS
RewriteCond %{HTTP_HOST} ^(en|mi|fr|zh)\.domain\.com
RewriteRule ^(.*) $1?lang=%1&%{QUERY_STRING}

Don't forget to change the domain to your domain name in the same line.

What the RewriteCond line does is that it checks the subdomain of your domain name. If it is e.g. Māori (mi.domain.com) it will simply translate that url and open the page domain.com/?lang=mi . This happens internally on the server, the URL in the browser remains mi.domain.com .

To explain what is happening e.g. for the domain mi.domain.com:

RewriteCond %{HTTP_HOST} ^(en|mi|fr|zh)\.domain\.com

This line checks if the domain 'domain.com' has a subdomain 'en' or 'mi' or 'fr' or 'zh'. If it does then the URL is translated in the following line:

RewriteRule ^(.*) $1?lang=%1&%{QUERY_STRING}

^(.*) is a regular expression and for Silverstripe URLs it contains the page name (e.g. mi.domain.com/news/ . The value in brackets (.*) - in this example 'news/' - is stored in the variable $1. The subdomain in brackets (en|mi|fr|zh) from the RewriteCond line is stored in the variable %1 - in this example 'mi'. So knowing that $1 is 'news/' and %1 is 'mi' you can easily rewrite the URL.

The {QUERY_STRING} in the RewriteRule line simply ensures that other values (e.g. mi.domain.com/news/?executeForm=SearchForm&Search=test) will be passed on, too.

So $1?lang=%1&%{QUERY_STRING} is the translated string.

e.g. a slightly more complex URL like
mi.domain.com/news/?executeForm=SearchForm&Search=test
becomes
/news/?lang=mi&executeForm=SearchForm&Search=test
on the server side.

Anyway, the only line you need to adjust is RewriteCond.

Rewrite Rules (the Apache mod_rewrite module) can be very powerful. I'm certainly no expert, but I find my way around with some trial and error. There are many tutorials out there to make things clearer. A beginners one is http://www.workingwith.me.uk/articles/scripting/mod_rewrite

Cheers!
Anatol

Avatar
kudesign

Community Member, 64 Posts

28 November 2008 at 12:59pm

Edited: 28/11/2008 1:01pm

Anatol, thanks for your detailed reply!

In your opinion, is silverstripe an ideal CMS for dev a multi-lingual site? I came across another CMS called quick.CMS, it does multi-lingual contents out-of-the-box. Modx also allow easy setup for multilingual contents, it uses redirect... I prefer the SS user interface, and all I want to know is if SS is worth my time doing further dev with multi-lingual.

I am having abit of a trouble enabling i18n, getting the ?lang=en ?lang=zh ?lang=fr to work in my url, was wondering if you could briefly talk me through the process?

1. in mysite/_config.php, I enabled

i18n::enable();

2. I set the locale to
i18n::set_locale('en_GB'); 

3. I did a text collect: http://<mysite>/i18n/textcollector/
4. I made dataobject translatable
 
class Team extends DataObject {
  static $db = array(
    "Name" => "Varchar",
    "FoundedDate" => "Date",
    "Description" => "Text",
  );
  
  // we don't want all fields to be translated (wouldn't make sense for a date, right?)
  static $extensions = array(
    "Translatable('Description')"
  );
} 

5. I ran a /db/build/flush=1

6. In CMS, I added under the 'Translation' tab, the languages I wanted to include for my site.

Is that all I needed to do to enable multilingual contents? I can't seem to get ?lang=en, ?lang=zh, ?lang=fr to work properly... Please check for me.

Thank you very much!

Avatar
kudesign

Community Member, 64 Posts

28 November 2008 at 2:11pm

Hi Anatol,

I have got it to work now, just needed to run a i18n/textcollector/ everytime I add a new language in the cms. Will try the .htaccess mod_rewrite function you suggested today, thank you very much for your great support. When you pop down to Christchurch, let me know, I will show you around.