punkish has asked for the wisdom of the Perl Monks concerning the following question:

I have the usual Apache/Perl/CGI::Application setup -- one instance script in index.cgi, a bunch of packages, setup, and a bunch of HTML::Templates. So, run mode "welcome" uses welcome.tmpl, rm edit uses edit.tmpl and so on.

Right. Now we want to set up all the templates in different languages. So when folks from Germany visit the website, they get welcome.de.tmpl, folks from Latin America get welcome.es.tmpl, and us folks get welcome.en.tmpl.

Easy to do with Apache and its content negotiation. The browser (hopefully) sends a header, and Apache serves the correct language pages. Of course, if some goes snafu, the browser doesn't send the correct header, or the user simply wants to see another language, I can have a pull-down menu or some such widget to let the user switch languages.

But, everything is being intercepted and acted upon by our favorite language, so how do I do the content negotiation with Perl/CGI::Application?

Update: I guess I could make lang specific index.cgi... so, index.en.cgi, index.de.cgi, and so on, which then would call the appropriate templates. But that would be so lame... any changes in my program and I would have to make the change as many times as my lang versions. Oh what to do, what to do?

--

when small people start casting long shadows, it is time to go to bed

Replies are listed 'Best First'.
Re: content negotiation with Apache/cgi
by Rhandom (Curate) on Apr 24, 2007 at 14:47 UTC
    First I would get the accept_language, either like the first poster mentioned, or simply using:
    $ENV{HTTP_ACCEPT_LANGUAGE}

    The second step, is I would override your path for your templates. Both HTML::Template and Template::Toolkit allow you to specify an arrayref of paths to look for your templates. I would unshift your language override directory on to the front of your path arrayref (in HTML::Template - INCLUDE_PATH in TT). That way, it will find you language override templates - but will fall back to your default templates if a language override can't be found.

    my $base_dir_abs = "/var/www/templates"; my $default_lang = 'en'; my $lang = lc $ENV{'HTTP_ACCEPT_LANGUAGE'} my @dirs = ("$base_dir_abs/$default_lang"); if ($lang && $lang ne $default_lang && $lang =~ /^(\w{2})/ # may look like "en-us" && -d "$base_dir_abs/$1") { unshift @dirs, "$base_dir_abs/$1"; } my $tt = Template->new({ INCLUDE_PATH => \@dirs }); $tt->process($file); OR my $ht = HTML::Template->new( filename => $file, path => \@dirs, );


    Update: adding specification for how to store your content.

    # Your directory structure may look like /var/www/templates/en/my_cgi/index.html /var/www/templates/en/my_cgi/step2.html /var/www/templates/en/my_cgi/step3.html /var/www/templates/en/another_cgi/index.html /var/www/templates/sp/my_cgi/index.html /var/www/templates/sp/my_cgi/step2.html /var/www/templates/sp/another_cgi/index.html

    If the CGI is passed HTTP_ACCEPT_LANGUAGE of sp and $file = 'my_cgi/index.html'; then you'll get /var/www/templates/sp/my_cgi/index.html. If you call it with a language other than "sp" then you'll always get /var/www/templates/en/my_cgi/index.html (well - always until you override my_cgi/index.html in that other language).

    Likewise for templates such as my_cgi/step3.html that don't exist in sp - you'll always fall back and get en/my_cgi/step3.html.

    my @a=qw(random brilliant braindead); print $a[rand(@a)];
      Rhandom++ for a most thorough and clear explanation of what to do. Much appreciation.
      --

      when small people start casting long shadows, it is time to go to bed
Re: content negotiation with Apache/cgi
by MonkE (Hermit) on Apr 24, 2007 at 13:16 UTC
    With the CGI module, you can use the http() method to obtain the ACCEPT_LANGUAGE header from the client's request. Is that what you need?
    use CGI qw/:standard/; # use one of the following forms $requested_language = http('Accept-language'); $requested_language = http('Accept_language'); # take action based on the client's list of acceptable languages ...
      Right. That is part of what I need, assuming I can get to Accept-Language from CGI::Application.

      My task lies beyond that. Do I make Apache serve lang specific index.cgi (index.de.cgi or index.es.cgi and so on), or do I use a single index.cgi which somehow manages to serve different templates (welcome.en.tmpl or welcome.es.tmpl and so on). This is where my confusion lies, and here is where I welcome advice.

      --

      when small people start casting long shadows, it is time to go to bed
Re: content negotiation with Apache/cgi
by benmaynard (Initiate) on Apr 24, 2007 at 19:28 UTC
    Something here may help http://osdir.com/ml/lang.perl.modules.html-template/2005-05/index.html It seems to deal with the concept of locales and storing translations in databases and using one set of templates. Seems like a nice unique way of dealing with the problem. I am often a little uncomfortable when it comes to mangling paths in a cgi script.