URL structure for multilanguage site

203 views
Skip to first unread message

jiri

unread,
Apr 18, 2009, 7:14:30 AM4/18/09
to web2py Web Framework
Hello,

I am new to web2py and I am working on multi-language site using this
framework. What is the best way to structure URLs for such site?
Previously I used this scheme (see below) in Pylons framework, it was
mapped using routing module to "lang" parameter and then correct
language was set up just before selected controller function (by URL)
was called. What I need to do to use this scheme in web2py or what is
the recommended way to do this?

/en/about/
/en/products/
...
/de/about/
/de/products/
...
/es/about/
/es/products/
...


Jiri

Jason Brower

unread,
Apr 18, 2009, 10:09:21 AM4/18/09
to web...@googlegroups.com
It's my understanding the web2py takes care of all the multi language
stuff automatically, no need to set it in the browser.
Just set the language file and make sure to put a T("") Around ya
strings.
br-
Jason Brower

Iceberg

unread,
Apr 18, 2009, 10:49:40 AM4/18/09
to web2py Web Framework
By the way, I believe the T("...") handles short phrase better, but if
you need to deal with some long article such as company background
description, it will also be a good choice to manually organize your
file as:
yourapp/static/en/about.html
yourapp/static/de/about.html
...

mdipierro

unread,
Apr 18, 2009, 11:35:31 AM4/18/09
to web2py Web Framework
routes_in = (
('/yourapp/static/(?P<any>.*)','/yourapp/static/$any'),
('/yourapp/$language/(?P<any>.*)','/yourapp/default/$any?_language=
$language'),
)

and in your model

if request.vars._language: T.force(request.vars._language)

Massimo

mdipierro

unread,
Apr 18, 2009, 11:41:31 AM4/18/09
to web2py Web Framework
Personally I do not user routes much and I like to do

if request.vars.force_language: session.force_language
if session.force_language: T.force(force_language)

and have button in the 'index' page that reload the index page in
various languages

<a href="{{=URL(r=request,vars=dict(force_language='fr-
fr'))}}">French</a>

Because of the session var, web2py will remember my preferred
language.

Massimo

jiri

unread,
Apr 19, 2009, 6:03:00 AM4/19/09
to web2py Web Framework
Thanks, routes_in fragment seems to be what I was looking for. Session
variable for remembering last selected language - I like that, I am
going to include that also.

I am not sure about handling language purely using sessions in
general. It could be worthful if you have an app like webmail for
example and you want to translate it. But in case of site with content
in multiple languages I believe that right way is to have pages
(content) in different languages to have different URLs. How can
search engine handle different language version of page/article if
language is handled using sessions(and browser language setting)
only?

Jiri

mdipierro

unread,
Apr 19, 2009, 11:05:40 AM4/19/09
to web2py Web Framework

Jiri Zahradil

unread,
Apr 19, 2009, 12:08:28 PM4/19/09
to web...@googlegroups.com
I tried to investigate that and it is clear that content localized by session/browser preferance only *cannot* be properly indexed by search engines. Localized version of content must have 1) own URL, 2) must have properly set Content-Language in HTTP headers (can be set by meta tag also).

--
Jiri

Anthon

unread,
Apr 27, 2009, 4:24:29 AM4/27/09
to web2py Web Framework
Oops, and the second line has a problem as well:
> if session.force_language: T.force(force_language)
if session.force_language: T.force(session.force_language)

Anthon

unread,
Apr 27, 2009, 4:20:04 AM4/27/09
to web2py Web Framework

On Apr 18, 5:41 pm, mdipierro <mdipie...@cs.depaul.edu> wrote:
> Personally I do not user routes much and I like to do
>
I thinks the following line:
> if request.vars.force_language: session.force_language
Should be:
if request.vars.force_language:
session.language = request.vars.force_language
> if session.force_language: T.force(force_language)
>

Jiri Zahradil

unread,
Mar 15, 2010, 7:36:05 PM3/15/10
to aure, web2py
Hi,

@1 yes, routes_in does the magic for you, it works perfectly for me, you should also consider to modifying routes_out to convert links back to /yourapp/en/.... format or you can do it "manually" in your templates ...

@2 yes, internalization framework T(...) should be used just for application labels and short text, for content you should definitely use database backed text. For small and fixed number of languages (2-3) I would use database columns like text_en, text_fr. If you need to support many languages, I would recomend create extra table with structure: ID, LANGUAGE, TEXT and link it to your table with content and replace your text field with reference to ID in this new table. Then you can select correct translation using ID and selected language.

Jiri

2010/3/15 aure <aurelie...@googlemail.com>
Please, I would need some help for developing a multilanguage website.


1. I would like to use different URLs for each language:

/myapp/en/index.html
/myapp/en/user.html
...

/myapp/fr/index.html
/myapp/fr/user.html
...

My problem is that I would rather avoid making duplicates of
index.html in different languages. I need only one such file, but I
want the URL to show like /myapp/en/index.html for an English version
of the page and /myapp/fr/index.html for a French version. How can
this be achieved?

Is the method described by Massimo (with routes_in...) the solution to
my problem? (I have tried to play with it but have not managed to get
it to actually work).

2. Then, it seems it would be best not using T(...) when the content
is big, let us say for a post on a blog. Am I right? In that case
would it be a good solution to have a table in the database storing
posts with a language column to differentiate them by language?

Thanks in advance.

Aurelien


On 19 avr 2009, 17:08, Jiri Zahradil <jiri.zahra...@gmail.com> wrote:
> I tried to investigate that and it is clear that content localized by
> session/browser preferance only *cannot* be properly indexed by search
> engines. Localized version of content must have 1) own URL, 2) must have
> properly set Content-Language in HTTP headers (can be set by meta tag also).
> --
> Jiri
>

aure

unread,
Mar 16, 2010, 6:53:15 AM3/16/10
to web2py-users
Hi,

Thank you, Jiri.

After your answer I have tried again and found what my problem exactly
is. I have used routes_in exactly as shown in Massimo's post and added
the other line given in my model. And yes it works just fine when I
type the URL http://.../myapp/en/index
(it displays the view index.html located in /myapp/default/). But I
get "Invalid Controlĺer" if I try to access the URL with another
language, e.g. http://.../myapp/fr/index. Has someone any idea why
this does not work?

Thanks to your answer, I now understand why I should also use
routes_out. But here as well it fails to work. Here is what I have
tried:

routes_out = ('/myapp/default/(?P<any>.*)','/myapp/_language/$any')

Thank you,
Aurelien

On 16 mar, 00:36, Jiri Zahradil <jiri.zahra...@gmail.com> wrote:
> Hi,
>
> @1 yes, routes_in does the magic for you, it works perfectly for me, you
> should also consider to modifying routes_out to convert links back to
> /yourapp/en/.... format or you can do it "manually" in your templates ...
>
> @2 yes, internalization framework T(...) should be used just for application
> labels and short text, for content you should definitely use database backed
> text. For small and fixed number of languages (2-3) I would use database
> columns like text_en, text_fr. If you need to support many languages, I
> would recomend create extra table with structure: ID, LANGUAGE, TEXT and
> link it to your table with content and replace your text field with
> reference to ID in this new table. Then you can select correct translation
> using ID and selected language.
>
> Jiri
>

> 2010/3/15 aure <aureliengir...@googlemail.com>

Wikus van de Merwe

unread,
Mar 16, 2010, 12:44:14 PM3/16/10
to web2py-users
Aurelien, if your routes_in rule is:
('/app/(en|fr)/(.*)', r'/app/default/\2/\1')

then for /app/fr/function you will get /app/default/function/fr
and for /app/en/function/arg1/arg2 you will get /app/default/function/
arg1/arg2/en

Your rule for routes_out now should be:
('/app/default/(.*)/(en|fr)', r'/app/\2/\1')

so for /app/default/function/fr you will get /app/fr/function

aure

unread,
Mar 18, 2010, 7:22:00 AM3/18/10
to web2py-users
So here is the full procedure I have been using.

1. As explained by Massimo and Wikus, in order to use two languages
(here French -fr- and English -en-) I wrote the following code in file
"routes.py" found in the "web2py" folder:

#---routes.py---#
routes_in = (
('/app/static/(?P<any>.*)','/app/static/$any'),
('/app/(en|fr)/(.*)',r'/app/default/\2/\1?_language=\1')
)

routes_out = (
('/app/static/(?P<any>.*)','/app/static/$any'),
('/app/default/(.*)/(en|fr)',r'/app/\2/\1')
)
#---------------#

where "app" has to be replaced by the actual name of the application

REMARKS:
I do not know why, but without the line in routes_in and routes_out:

('/llyow/static/(?P<any>.*)','/llyow/static/$any'),

which seems to be doing nothing (or not?) I get this error:

File "/home/aurelien/Documents/Webdesign/web2py/web2py/gluon/
rewrite.py", line 49, in load
for (k, v) in symbols['routes_in']:
ValueError: too many values to unpack

(Could someone explain what this line actually does, and why it seems
to be required?)

2. As explained by Massimo, I then added this line to my model:

if request.vars._language: T.force(request.vars._language)

3. I also provided links to switch manually between languages by
adding the following code in file "views/layout.html":

<a href="{{=URL(request.application,'en','index')}}">en</a>
<a href="{{=URL(request.application,'fr','index')}}">fr</a>

4. Finally I added a 'current' language argument to ALL the internal
links, like here for the "search" link:

{{=A(T('search'),_href=URL(r=request,f='search',args=[request.vars._language]))}}

It makes sure that thelanguage preference gets carried on through the
browsing session.

5. Finally, as I could not get it to work correctlv for French I tried
a few things and I then realised that I only had fr-fr.py in my
"languages" folder. I saved a copy of it that I named "fr.py" and it
did the magic. (What would be required to use a file like "fr-fr.py"
instead?)

That is about everything.

Thanks again for the ones who helped!

Aurelien

On 16 mar, 17:44, Wikus van de Merwe <dupakrop...@googlemail.com>
wrote:

Christopher Steel

unread,
Mar 18, 2010, 7:36:11 AM3/18/10
to web2py-users
Jiri, Aure and Wikus,

I am also working on a multilingual project and I am sure some other
folks are as well. We could really use some working examples of
internationalization, especially using URL's and routes_in and
routes_out and table setups.

If you all are up to doing short "slice" you can visit

http://www.web2pyslices.com/main/default/index and contribute one
or more working examples.

Here is a link to a good one that Massimo did on creating Audit Trails
as an example:

http://www.web2pyslices.com/main/slices/take_slice/35

The other option is "donating" a working application although this
happens less frequently because of work related restrictions and/or
licensing. Web2pyslices is fast and easy and because you can use code
snippits you don't risk giving away any state or corporate secrets ; )

Thanks,

Chris

On Mar 16, 12:44 pm, Wikus van de Merwe <dupakrop...@googlemail.com>
wrote:

Christopher Steel

unread,
Mar 18, 2010, 7:49:53 AM3/18/10
to web2py-users
Wow, I swear people using web2py can read minds. 14 minutes before my
above post aure posts a solution...

aure, do you want to put that up on web2pyslices or I could do it for
you.


Thank you!

Chris

On Mar 18, 7:36 am, Christopher Steel <chris.st...@gmail.com> wrote:
> Jiri, Aure and Wikus,
>
> I am also working on a multilingual project and I am sure some other
> folks are as well. We could really use some working examples of
> internationalization, especially using URL's and routes_in and
> routes_out and table setups.
>
> If you all are up to doing short "slice" you can visit
>

>    http://www.web2pyslices.com/main/default/indexand contribute one

aure

unread,
Mar 18, 2010, 8:47:14 AM3/18/10
to web2py-users
Hi Chris,

I don't know. There still are a few things I do not really understand.
I would be happy if some people can answer my questions before...

But if you understand these things better than I do, do put it up on
web2pyslices!

Aurelien

On 18 mar, 12:49, Christopher Steel <chris.st...@gmail.com> wrote:
> Wow, I swear people using web2py can read minds. 14 minutes before my
> above post aure posts a solution...
>
> aure, do you want to put that up on web2pyslices or I could do it for
> you.
>
> Thank you!
>
> Chris
>
> On Mar 18, 7:36 am, Christopher Steel <chris.st...@gmail.com> wrote:
>
> > Jiri, Aure and Wikus,
>
> > I am also working on a multilingual project and I am sure some other
> > folks are as well. We could really use some working examples of
> > internationalization, especially using URL's and routes_in and
> > routes_out and table setups.
>
> > If you all are up to doing short "slice" you can visit
>

> >    http://www.web2pyslices.com/main/default/indexandcontribute one

mdipierro

unread,
Mar 18, 2010, 9:28:29 AM3/18/10
to web2py-users
Mind you can also do

#---routes.py---#
routes_in = (
('/app/static/$anything','/app/static/$anything'),
('/app/$language/$anything',r'/app/default/$anything/$language?
_language=$language')
)

routes_out = (
('/app/static/$anything','/app/static/$anything'),
('/app/default/$anything/$language',r'/app/$language/$anything')
)
#---------------#

as $anything will match (.*) and $language ([\w-]+)

Chris Steel

unread,
Mar 18, 2010, 12:59:20 PM3/18/10
to web...@googlegroups.com
I will add stuff as we get answers and build a little collection of internationalization stuff in one location. I am trying to work out a way to deal with the regional/dialect issue as well (fr-fr, fr-ca) etc.

I for one have never messed with routes_in and routes_out but I think Jiri is right, this is required for google listings and such. I had some issues with characters with accents in URL's in a previous application, have you run into any problems with accents? The other issue is that I have never programmed in Python before but I figure if I have gotten this far and I am only on page 188 of Learning Python by Mark Lutz's 1100 page 4th Edition, then I should be OK, it will just take me longer until I get up to speed, but so far I totally love it. ; )

Cheers,

Chris

--
You received this message because you are subscribed to the Google Groups "web2py-users" group.
To post to this group, send email to web...@googlegroups.com.
To unsubscribe from this group, send email to web2py+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/web2py?hl=en.




--
Christopher Steel
Owner
Vishpala.com
IT Consulting and Project Management

Christopher Steel

unread,
Mar 18, 2010, 6:00:56 PM3/18/10
to web2py-users
Hi Aurelien,

Questions 3 and 5

this for our menu's, we are building in some WAI-ARIA / Accessibility
stuff, which is unfinished but as you see I am using en-en and fr-fr
for reasons I will reveal after this example (with unfinished aria):

<h1>{{=T('Language Menu')}}</h1>
<div style="text-align: left;">
<div id="nav_aria" >
<ul id="navigation_choose_preferred_interface_language"
role="navigation" aria-labelledby="nav_aria_lang_menu" tabindex="-1">
<h3 class="inline"
id="nav_aria_interface_lang_menu">{{=T('Language Settings:')}}</h3>
[<li><a href="{{=URL(r=request,vars=dict(_language='en-
en'))}}">{{=T('English')}} : en-en</a></li>
|<li><a href="{{=URL(r=request,vars=dict(_language='it-
it'))}}">{{=T('Italian')}}: it-it</a></li>
|<li><a href="{{=URL(r=request,vars=dict(_language='fr-
fr'))}}">{{=T('French')}}: fr-fr</a></li>
]
</ul>
</div>
</div>.
{{if session._uc_debugging_on == 'True':}}

I ended up opted for primary and secondary languages tags after
spending too much time researching language tags and the secondary
tags in particular. In the end I opted to use them for reasons of
tradition and due to the KISS principle (with good reason!)

See the following document for the highlight of my misadventure in
seeking further into on secondary tags, the last of many similar
documents I found on my search. As far as I can tell they are used out
"of tradition" (Netscape) although please feel free to try
implementing the "Best Practices" (This is kind of a joke, you will
get it when (if) your read the document or decide to go on a similar
"wild goose" chase... but, gee what a promising title no.!

"Everything you ever wanted to know about language tags but where
afraid to ask"

Network Working Group A. Phillips,
Ed.
Request for Comments: 5646
Lab126
BCP: 47 M. Davis,
Ed.\
Obsoletes: 4646
Google
Category: Best Current Practice September
2009

Tags for Identifying Languages

"Best Current Practice" - Tags for Identifying Languages

http://www.rfc-editor.org/rfc/bcp/bcp47.txt

May ?od have mercy on your soul...


>
>
> 4. Finally I added a 'current' language argument to ALL the internal
> links, like here for the "search" link:
>
> {{=A(T('search'),_href=URL(r=request,f='search',args=[request.vars._language]))}}
>
> It makes sure that thelanguage preference gets carried on through the
> browsing session.
>
> 5. Finally, as I could not get it to work correctlv for French I tried
> a few things and I then realised that I only had fr-fr.py in my
> "languages" folder. I saved a copy of it that I named "fr.py" and it
> did the magic. (What would be required to use a file like "fr-fr.py"
> instead?)
>

5. (Again)
I started out using a single tag, thinking that after I discovered
"true meaning" behind the secondary tag I could better logically
implement it. Now I just implement it cause that's what everyone else
does (not my style but I think in the end it is the most logical
approach)

Cheers,

Chris

Chris Steel

unread,
Dec 15, 2012, 2:15:06 AM12/15/12
to web...@googlegroups.com
Your layout

.../en/about ... seems very logical to me. I would go with that.

As far as translating longer blocks of text such as a blog entry, why not use a language indicator in your database table for each entry. For example

lang == en
title == 'My title'
blog_entry == my entry

then for another language

lang == fr
title == sujet ici
blog_entry == mes choose, mais, en francais...

C.

On Fri, Dec 14, 2012 at 7:59 AM, <yale...@gmail.com> wrote:
суббота, 18 апреля 2009 г., 16:14:30 UTC+5 пользователь jiri написал:
I also faced such problem.
"T" is not very suitable loya large text (blogs).
Tell us how you coped with this challenge?
This question is very important for me.

Or do you still have done all through the "T" and used a database for save large texts.
Can lay out in detail how to multilaguage site.

ps
I'm new to python and web2py, not much kick :) 
and my english is not very

--
 
 
 



--
Christopher Steel


Reply all
Reply to author
Forward
0 new messages