Catalyst::Plugin::I18N::PathPrefix - Language prefix in the request path
Version 0.07
# in MyApp.pm use Catalyst qw/ I18N I18N::PathPrefix /; __PACKAGE__->config('Plugin::I18N::PathPrefix' => { valid_languages => [qw/en de fr/], fallback_language => 'en', language_independent_paths => qr{ ^( votes/ | captcha/numeric/ ) }x, }); __PACKAGE__->setup; # now the language is selected based on requests paths: # # http://www.example.com/en/foo/bar -> sets $c->language to 'en', # dispatcher sees /foo/bar # # http://www.example.com/de/foo/bar -> sets $c->language to 'de', # dispatcher sees /foo/bar # # http://www.example.com/fr/foo/bar -> sets $c->language to 'fr', # dispatcher sees /foo/bar # # http://www.example.com/foo/bar -> sets $c->language from # Accept-Language header, # dispatcher sees /foo/bar # in a controller sub language_switch : Private { # the template will display the language switch $c->stash('language_switch' => $c->language_switch_options); }
This module allows you to put the language selector as a prefix to the path part of the request URI without requiring any modifications to the controllers (like restructuring all the controllers to chain from a common base controller).
(Internally it strips the language code from $c->req->path and appends it to $c->req->base so that the invariant $c->req->uri eq $c->req->base . $c->req->path still remains valid, but the dispatcher does not see the language code - it uses $c->req->path only.)
$c->req->path
$c->req->base
$c->req->uri eq $c->req->base . $c->req->path
Throughout this document 'language code' means ISO 639-1 2-letter language codes, case insensitively (eg. 'en', 'de', 'it', 'EN'), just like I18N::LangTags supports them.
Note: You have to load Catalyst::Plugin::I18N if you load this plugin.
Note: HTTP already have a standard way (ie. Accept-Language header) to allow the user specify the language (s)he prefers the page to be delivered in. Unfortunately users often don't set it properly, but more importantly Googlebot does not really support it (but requires that you always serve documents of the same language on the same URI). So if you want a SEO-optimized multi-lingual site, you have to have different (sub)domains for the different languages, or resort to putting the language selector into the URL.
You can use these configuration options under the 'Plugin::I18N::PathPrefix' key:
'Plugin::I18N::PathPrefix'
valid_languages => \@language_codes
The language codes that are accepted as path prefix.
fallback_language => $language_code
The fallback language code used if the URL contains no language prefix and Catalyst::Plugin::I18N cannot auto-detect the preferred language from the Accept-Language header or none of the detected languages are found in "valid_languages".
Accept-Language
language_independent_paths => $regex
If the URI path is matched by $regex, do not add language prefix and ignore if there's one (and pretend as if the URI did not contain any language prefix, ie. rewrite $c->req->uri, $c->req->base and $c->req->path to remove the prefix from them).
$regex
$c->req->uri
Use a regex that matches all your paths that return language independent information.
If you don't set this config option or you set it to an undefined value, no paths will be handled as language independent ones.
debug => $boolean
If set to a true value, "prepare_path_prefix" logs its actions (using $c->log->debug(...)).
$c->log->debug(...)
Overridden (wrapped with an an after modifier) from "setup_finalize" in Catalyst.
after
Sets up the package configuration.
Overridden (wrapped with an an after modifier) from "prepare_path" in Catalyst.
Calls $c->prepare_path_prefix after the original method.
$c->prepare_path_prefix
$c->prepare_path_prefix()
Returns: N/A
If $c->req->path is matched by the "language_independent_paths" configuration option then calls $c->set_languages_from_language_prefix with the value of the "fallback_language" configuration option and returns.
$c->set_languages_from_language_prefix
Otherwise, if $c->req->path starts with a language code listed in the "valid_languages" configuration option, then splits language prefix from $c->req->path then appends it to $c->req->base and calls $c->set_languages_from_language_prefix with this language prefix.
Otherwise, it tries to select an appropriate language code:
It picks the first language code $c->languages that is also present in the "valid_languages" configuration option.
$c->languages
If no such language code, uses the value of the "fallback_language" configuration option.
Then appends this language code to $c->req->base and the path part of $c->req->uri, finally calls $c->set_languages_from_language_prefix with that language code.
$c->set_languages_from_language_prefix($language_code)
Sets $c->languages to $language_code.
$language_code
Called from both "prepare_path_prefix" and "switch_language" (ie. always called when $c->languages is set by this module).
You can wrap this method (using eg. the "after" in Moose method modifier) so you can store the language code into the stash if you like:
after prepare_path_prefix => sub { my $c = shift; $c->stash('language' => $c->language); };
$c->uri_for_in_language($language_code => @uri_for_args)
Returns: $uri_object
$uri_object
The same as "uri_for" in Catalyst but returns the URI with the $language_code path prefix (independently of what the current language is).
Internally this method temporarily sets the paths in $c->req, calls "uri_for" in Catalyst then resets the paths. Ineffective, but you usually call it very infrequently.
$c->req
Note: You should not call this method to generate language-independent paths, as it will generate invalid URLs currently (ie. the language independent path prefixed with the language prefix).
Note: This module intentionally does not override "uri_for" in Catalyst but provides this method instead: "uri_for" in Catalyst is usually called many times per request, and most of the cases you want it to use the current language; not overriding it can be a significant performance saving. YMMV.
$c->switch_language($language_code)
Changes $c->req->base to end with $language_code and calls $c->set_languages_from_language_prefix with $language_code.
Useful if you want to switch the language later in the request processing (eg. from a request parameter, from the session or from the user object).
$c->language_switch_options()
Returns: { $language_code => { name => $language_name, uri => $uri }, ... }
{ $language_code => { name => $language_name, uri => $uri }, ... }
Returns a data structure that contains all the necessary data (language code, name, URL of the same page) for displaying a language switch widget on the page.
The data structure is a hashref with one key for each valid language code (see the "valid_languages" config option) (in all-lowercase format) and the value is a hashref that contains the following key-value pairs:
The localized (translated) name of the language. (The actual msgid used in $c->loc() is the English name of the language, returned by "name" in I18N::LangTags::List.)
$c->loc()
The URL of the equivalent of the current page in that language (ie. the language prefix replaced).
You can find an example TT2 HTML template for the language switch included in the distribution.
Catalyst::Plugin::I18N, Catalyst::TraitFor::Request::PerLanguageDomains
Norbert Buchmuller, <norbi at nix.hu>
<norbi at nix.hu>
Please report any bugs or feature requests to bug-catalyst-plugin-i18n-pathprefix at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-Plugin-I18N-PathPrefix. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
bug-catalyst-plugin-i18n-pathprefix at rt.cpan.org
You can find documentation for this module with the perldoc command.
perldoc Catalyst::Plugin::I18N::PathPrefix
You can also look for information at:
RT: CPAN's request tracker
http://rt.cpan.org/NoAuth/Bugs.html?Dist=Catalyst-Plugin-I18N-PathPrefix
AnnoCPAN: Annotated CPAN documentation
http://annocpan.org/dist/Catalyst-Plugin-I18N-PathPrefix
CPAN Ratings
http://cpanratings.perl.org/d/Catalyst-Plugin-I18N-PathPrefix
Search CPAN
http://search.cpan.org/dist/Catalyst-Plugin-I18N-PathPrefix/
Thanks for Larry Leszczynski for the idea of appending the language prefix to $c->req->base after it's split off of $c->req->path (http://dev.catalystframework.org/wiki/wikicookbook/urlpathprefixing).
Thanks for Tomas (t0m) Doran <bobtfish@bobtfish.net> for the code reviews, improvement ideas and mentoring in general.
Copyright 2010 Norbert Buchmuller, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install Catalyst::Plugin::I18N::PathPrefix, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Catalyst::Plugin::I18N::PathPrefix
CPAN shell
perl -MCPAN -e shell install Catalyst::Plugin::I18N::PathPrefix
For more information on module installation, please visit the detailed CPAN module installation guide.