Re: [Catalyst] Multi-language and REST

2008-05-04 Thread Daniel McBrearty
Haven't been looking in here for a while, just saw this thread.

I have a multilingual app at http://www.engoi.com which uses Chained
to do this. It works really well, and makes Do Not Repeat Yourself
quite easy to achieve.

In fact, for many actions, *two* languages are selected - the native
and target language of the user.  You can see the way this maps to
URI's easily enough by looking around.

Browser detection happens if you go to the domain root, and redirects
you straight to the home page in your language. It's pretty simple.

BTW don't let the fact that many pages are actually served static fool
you. All content is developed in Catalyst, I use a script to generate
html pages for stuff which is not actually dynamic in behaviour, and
some shennaigans with URL's and server config to make it all work
together.

Cat is very powerful and flexible and lets you do things many, many ways.

Daniel

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-28 Thread Matt Rosin
I think other cases show it is not only an i18n issue.

In a business listings site I made I have
x.com/dir/CityName/Business_Services/Advertising for example.

The top level category Business_Services is optional as the secondary
level category name is unique. The CityName could be any city in the
state, or All_Cities.
No city means All_Cities.
If there is a city but no topic, it shows table of contents for that city only.
A top level topic but no secondary level topic, it shows a blog on that topic.

As Bill Moseley does, after the dir (which is Dir.pm) I check if there
is a valid city.

I also made some experimental tags to modify behavior. So you could
add /show_all_cities at the end and it would do that regardless of
the city. (decided not to use that). Also was going to add a
/tags:(x,y,z,w) style supplement to be able to submit a set of
unordered tags but this also proved overkill. However when doing
faceted metadata search the order really isn't important and so order
in the url sholdn't be either I think.

This suggests to me that it would be useful to create a general url
windowing module that lets you specify (and validate urls to) an url
format in which certain segments of it may be structured differently.
By window I mean it lets you look at and define segments of urls. It
could pick up collisions between adjacent keywords too. Could also pad
missing virtual folder names (like setting All_Cities if not present).

I guess you'd define subs for each window spec.

The definition would see x.com/dir/[CITYSPEC]/[MAJORSPEC]]/[MINORSPEC]

It need not be complicated as the purpose is human readability. I know
Accept-Language is good REST but it is less intuitive and personally I
detest being forced to read a Japanese page for a website that has
perfectly good English on it.

It might be useful if you could define a certain format, like
-MMDD for a publication date, for a certain spec. Then it would be
easy to pick up on whether it is present or not and you could easily
handle x.com/Jones/2008-0428 as well as x.com/Fiction/Jones and
even x.com/Jones/EarlyWorks (if you allow the date spec to include
EarlyWorks, defined as within 10 years of the first PubDate on
record).

Anyway the fr/en switch is a small subset of this functionality which
is otherwise very useful for helping users (and hopefully Google)
intuitively navigate orthogonal metadata (think Author, PubDate,
Topic) or data organized into hierarchies with crosslinks, like a
Yahoo style topic hierarchy. I suppose this is too long a post but it
would benefit all catalyst sites if created. I suppose UrlFu or the
like.

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-28 Thread Octavian Rasnita

From: Matt Rosin [EMAIL PROTECTED]
FWIW after all that such a module should allow keys stored in cookies

to supplement/overwrite the url. So instead of prepending lang code, I
could keep the same url but have a javascript language button set the
language.


I think that the pages with different content (in different languages) 
should have a unique URL (for allowing the search engines to index all the 
pages).


I first made an application in a single language then I needed to make it 
multilanguage, and the most easy way I found was to add the language ID in 
the query string, like:  ?lang=FR.


The app uses Catalyst::Plugin::I18N. If the request doesn't contain any lang 
variable and any lang cookie, it gets the languages prefered by the browser 
and displays the page in the most apropriate language.
If the request contains the lang cookie, the app displays the pages using 
that language.


If the request contains the lang variable, it also displays the page using 
that language.


The links which should be used for changing the language send a lang 
variable, and a cook variable. When the app receives both of these 
variables, it displays the site in the specified language, and it also sets 
a cookie with that language, and the next time the visitor will visit the 
site, he will see the page displayed in the previously chosen language. This 
won't happen if this wasn't his choice, but only a browser preference.


For doing this I use the code I put below. I put it in the Root.pm, in the 
auto subroutine, so it is executed for all the other controllers and it sets 
the lang var in the stash for using it later in those controllers if needed 
(for sending emails in the chosen language, for example).


Of course, after doing this, I also needed to modify some templates and 
controllers in which I hard-coded URLs because I needed to insert lang=[% 
lang %].


HTH

Octavian

Here is the code I use:

my $lang = $c-req-param('lang');
my $cook = $c-req-param('cook');

if ($lang and $cook) {
#set cookie
$c-res-cookies-{lang} = {value = $lang, domain = 
$c-config-{cookie_domain}, path = '/', expires = '+1y'};


$c-languages([$lang]);
}
elsif ($lang) {
$c-languages([$lang]);
}
elsif ($c-req-cookies-{lang}) {
$lang = $c-req-cookies-{lang}-value;
$c-languages([$lang]);
}
else {
#read the browser prefered languages
my @accept_language = split /,/, $c-req-header('Accept-Language');
my @langs;
foreach(@accept_language) {
s/;.*$//;
s/-.*$//;
push (@langs, $_);
}

$c-languages([EMAIL PROTECTED]);
$lang = $c-language; #the chosen language
}

$c-stash-{lang} = $lang;



___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


[Catalyst] Multi-language and REST

2008-04-25 Thread Ian Docherty
I have been pondering how to take an existing Catalyst application and 
make it multi-lingual.


I would prefer to use a RESTful method, so this would translate /foo/bar 
to /en/foo/bar or /fr/foo/bar (for English and French respectively).


The problem as I see it is how to do this. I don't want to move all my 
controllers, e.g. MyApp::Controller::Foo::Bar to 
MyApp::Controller::Lang::Foo::Bar


What other alternatives are there?

Regards
Ian

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-25 Thread Knut-Olav Hoven
On Friday 25 April 2008 14:44:38 Ian Docherty wrote:
 I have been pondering how to take an existing Catalyst application and
 make it multi-lingual.

 I would prefer to use a RESTful method, so this would translate /foo/bar
 to /en/foo/bar or /fr/foo/bar (for English and French respectively).

The elegang solution is to make use of the request header Accept-Language, but 
not many users know how to change this setting in their browsers.

http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#z12


 The problem as I see it is how to do this. I don't want to move all my
 controllers, e.g. MyApp::Controller::Foo::Bar to
 MyApp::Controller::Lang::Foo::Bar

 What other alternatives are there?

 Regards
 Ian

 ___
 List: Catalyst@lists.scsys.co.uk
 Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
 Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
 Dev site: http://dev.catalyst.perl.org/



-- 
Knut-Olav Hoven
Systemutvikler   mob: +47 986 71 700
Linpro AShttp://www.linpro.no/


signature.asc
Description: This is a digitally signed message part.
___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-25 Thread Christopher H. Laco

Ian Docherty wrote:
I have been pondering how to take an existing Catalyst application and 
make it multi-lingual.


I would prefer to use a RESTful method, so this would translate /foo/bar 
to /en/foo/bar or /fr/foo/bar (for English and French respectively).


The problem as I see it is how to do this. I don't want to move all my 
controllers, e.g. MyApp::Controller::Foo::Bar to 
MyApp::Controller::Lang::Foo::Bar


What other alternatives are there?

Regards
Ian


Well, I'm sure there's a somewhat elegant way to do this with Chained, 
but it the other controllers don't use Chained now, that could get fun.


The brute force way is to inspect the request and rip out the language 
portion before sending it on to get dispatched...just like the Flavour 
plugin does with file extensions:


sub prepare_path {}






signature.asc
Description: OpenPGP digital signature
___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-25 Thread Bill Moseley
On Fri, Apr 25, 2008 at 01:44:38PM +0100, Ian Docherty wrote:
 I have been pondering how to take an existing Catalyst application and 
 make it multi-lingual.
 
 I would prefer to use a RESTful method, so this would translate /foo/bar 
 to /en/foo/bar or /fr/foo/bar (for English and French respectively).
 
 The problem as I see it is how to do this. I don't want to move all my 
 controllers, e.g. MyApp::Controller::Foo::Bar to 
 MyApp::Controller::Lang::Foo::Bar

I check if the prefix is a valid language (if it's one of the language
files I loaded at startup), if so I then remove it from the request
path and append it to the request base.

-- 
Bill Moseley
[EMAIL PROTECTED]


___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-25 Thread Ian Docherty

Christopher H. Laco wrote:

Ian Docherty wrote:
I have been pondering how to take an existing Catalyst application 
and make it multi-lingual.


I would prefer to use a RESTful method, so this would translate 
/foo/bar to /en/foo/bar or /fr/foo/bar (for English and French 
respectively).


The problem as I see it is how to do this. I don't want to move all 
my controllers, e.g. MyApp::Controller::Foo::Bar to 
MyApp::Controller::Lang::Foo::Bar


What other alternatives are there?

Regards
Ian


Well, I'm sure there's a somewhat elegant way to do this with Chained, 
but it the other controllers don't use Chained now, that could get fun.
I have considered chained, and would be prepared to re-write the 
existing controllers. A bigger decision would be renaming the 
controllers or moving them.


e.g. existing MyApp::Controller::Foo::Bar maps to URI /foo/bar

To match against /lang/foo/bar either I can leave the controller where 
it is (lib/MyApp/Controller/Foo/Bar.pm) or move it 
(lib/MyApp/Controller/Lang/Foo/Bar)


The first approach is less work (only using chained) the second is more 
work, but maps the URI namespace more logically to the Class names.


What would people do if they were writing a Catalyst App from scratch 
with this feature? That would tell me what the 'best practice' is even 
if it means a big re-write exercise.


The brute force way is to inspect the request and rip out the language 
portion before sending it on to get dispatched...just like the Flavour 
plugin does with file extensions:


sub prepare_path {}
One of my pet peeves  is exemplified in the 'Flavour' plugin. It is such 
minimal documentation that it neither tells you what it does or why it 
does it. OK, I can look at the code, but it is too much effort unless I 
think I have a good reason to do so. I assume in this case that it is 
something to do with date strings in the URI (for blogging?). I can't be 
ar**d!


___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-25 Thread Dave Rolsky

On Fri, 25 Apr 2008, Ian Docherty wrote:


http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#z12

Yes, I have done this previously, it is elegant, but not RESTful and does not 
make it easy for users to change their settings on a site-by-site basis 
dynamically, as you could if you provided a language selection box on each 
page.


Why do you say it's not RESTful?

I think it's very RESTful, but it depends on how you think about it. If 
the language of the content is basically an issue of formatting, then 
switching language based on a header is perfect. The client provides 
sufficient information to produce a correct response _on each request_ as 
part of HTTP. This is basically the essence of REST.


OTOH, if you consider each language's content fundamentally separate 
things, then each language should have its own set of URIs.



-dave

/*==
VegGuide.Org
Your guide to all that's veg
==*/

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-25 Thread Ian Docherty

Dave Rolsky wrote:

On Fri, 25 Apr 2008, Ian Docherty wrote:


http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#z12

Yes, I have done this previously, it is elegant, but not RESTful and 
does not make it easy for users to change their settings on a 
site-by-site basis dynamically, as you could if you provided a 
language selection box on each page.


Why do you say it's not RESTful?

I think it's very RESTful, but it depends on how you think about it. 
If the language of the content is basically an issue of formatting, 
then switching language based on a header is perfect. The client 
provides sufficient information to produce a correct response _on each 
request_ as part of HTTP. This is basically the essence of REST.


OTOH, if you consider each language's content fundamentally separate 
things, then each language should have its own set of URIs.
Yes, this is exactly what I had in mind. I did not (and still don't) 
consider the language of the content as 'formatting', the content for 
each language is different (in my mind).


I don't really want this to start another flame-war about RESTful etc. 
this point is outside of my original request so I won't respond (on 
list) to this off-topic subject any more.


Regards
Ian

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-25 Thread Christopher H. Laco

Dave Rolsky wrote:

On Fri, 25 Apr 2008, Ashley wrote:

I agree that it's content, not formatting. If CSS/client-side-JS can 
(in a practical fashion) change it, it's formatting, otherwise, it's 
content.


I should have used the word representation. With REST, you'd have the 
same URI for one resource, but you might offer it as HTML, JSON, and 
plain text based on what the client requests.


Given the Accept-Language header, you could do the same thing with 
language.



-dave


Could and should. I've taken the approach using the REST controller that 
if anyone wants to get at a resource easier (easier to alter the uri 
than the headers), then use the content-type query param. I think the 
same should be true for language.


If changing Accept-Language is too much, (or people want to view a 
language other than their native), then look at language= in the query 
params first..if it's empty...honor Accept-Language... rather than 
forcing /lang/ at the front of all urls.




signature.asc
Description: OpenPGP digital signature
___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-25 Thread Ashley

On Apr 25, 2008, at 10:28 AM, Christopher H. Laco wrote:
If changing Accept-Language is too much, (or people want to view a  
language other than their native), then look at language= in the  
query params first..if it's empty...honor Accept-Language... rather  
than forcing /lang/ at the front of all urls.


I like the idea (and you could even cookie language prefs instead of  
a query string solution which would be more expensive/complex with  
the URI rewrites) but giving up a large chunk of one's search engine  
results for a more purist interface is a pretty high price. As of  
last year (haven't checked recently) the googlebot couldn't even  
correctly index pages served as application/xhtml. Some bots might do  
the right thing with headers for their target language base(s) but I  
doubt it's many, if even a minority, of them yet.


It's not a transport issue (like HTML/PDF/JSON/XML/etc) which makes  
perfect sense for header control because the clients and client-side  
stuff is being written now in tandem, it's different content and the  
target clients are laden with legacy behavior. I like PUT and DELETE  
too but I'm not going to abandon POST as their stand-in (or fall- 
back) any time soon.




___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Multi-language and REST

2008-04-25 Thread Ian Docherty

Christopher H. Laco wrote:

Ian Docherty wrote:

Christopher H. Laco wrote:

Ian Docherty wrote:
I have been pondering how to take an existing Catalyst application 
and make it multi-lingual.


I would prefer to use a RESTful method, so this would translate 
/foo/bar to /en/foo/bar or /fr/foo/bar (for English and French 
respectively).


The problem as I see it is how to do this. I don't want to move all 
my controllers, e.g. MyApp::Controller::Foo::Bar to 
MyApp::Controller::Lang::Foo::Bar


What other alternatives are there?

Regards
Ian


Well, I'm sure there's a somewhat elegant way to do this with 
Chained, but it the other controllers don't use Chained now, that 
could get fun.
I have considered chained, and would be prepared to re-write the 
existing controllers. A bigger decision would be renaming the 
controllers or moving them.


e.g. existing MyApp::Controller::Foo::Bar maps to URI /foo/bar

To match against /lang/foo/bar either I can leave the controller 
where it is (lib/MyApp/Controller/Foo/Bar.pm) or move it 
(lib/MyApp/Controller/Lang/Foo/Bar)


The first approach is less work (only using chained) the second is 
more work, but maps the URI namespace more logically to the Class names.


What would people do if they were writing a Catalyst App from scratch 
with this feature? That would tell me what the 'best practice' is 
even if it means a big re-write exercise.


The brute force way is to inspect the request and rip out the 
language portion before sending it on to get dispatched...just like 
the Flavour plugin does with file extensions:


sub prepare_path {}
One of my pet peeves  is exemplified in the 'Flavour' plugin. It is 
such minimal documentation that it neither tells you what it does or 
why it does it. OK, I can look at the code, but it is too much effort 
unless I think I have a good reason to do so. I assume in this case 
that it is something to do with date strings in the URI (for 
blogging?). I can't be ar**d!





It does just what just what Bill suggested.

I check if the prefix is a valid language (if it's one of the language
files I loaded at startup), if so I then remove it from the request
path and append it to the request base.

In prepare_path.. you inspect the requested path.. yank out the 
language.. then pass along the remaining path...which should map to 
your existing controllers just fine.
I have actually taken a look at the Flavour plugin (can't see for the 
life of me why it is called that!) and it gives an example of yanking 
off the //mm/dd at the start of a path, putting the values into 
accessors of flavour (e.g. $c-flavour-year) leaving the rest of the 
path to be processed as normal. This is pretty much what I want to do 
for the language so thanks for pointing out the plugin to me.


I am pretty confident that I can now write a plugin to strip out a 
language from the start of a path in the same way.


Looking at the Catalyst best practices, am I going to be polluting the 
catalyst namespace by writing this as a plugin? I can't see any 
alternative (making it a base Controller is actually what I am trying to 
avoid).


Any suggestions as to a namespace for this? Catalyst::Plugin::LangURI 
perhaps?


As far as chained goes... I thought there was an example floating 
around that has Root::lang as Chained, then all other modules Chaine 
against /lang as their root instead of /...
I should not need this if I do the above then I can leave my existing 
controllers unchanged (and unchained).


-=Chris




___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/