NAME

Catalyst::Plugin::I18N::Manual - (Draft) I18N and L10N with Catalyst and Template Toolkit.

OUTLINE

Prerequisites:
 - perl >= 5.8.0
 - Catalyst >= 5.33
 - Catalyst::Plugin::I18N >= 0.04
 - Catalyst::Plugin::Unicode >= 0.2
 - Catlayst::View::TT && Template-Toolkit >= 2.14
 - GNU gettext utilities
 - An editor that understands UTF-8 and Byte Order Mark (BOM)

$ catalyst.pl MyApp
created "MyApp"
created "MyApp/script"
created "MyApp/lib"
created "MyApp/root"
created "MyApp/root/static"
created "MyApp/root/static/images"
created "MyApp/t"
created "MyApp/lib/MyApp"
created "MyApp/lib/MyApp/Model"
created "MyApp/lib/MyApp/View"
created "MyApp/lib/MyApp/Controller"
created "MyApp/lib/MyApp.pm"
created "MyApp/Makefile.PL"
created "MyApp/README"
created "MyApp/Changes"
created "MyApp/t/01app.t"
created "MyApp/t/02pod.t"
created "MyApp/t/03podcoverage.t"
created "MyApp/root/static/images/catalyst_logo.png"
created "MyApp/root/static/images/btn_120x50_built.png"
created "MyApp/root/static/images/btn_120x50_built_shadow.png"
created "MyApp/root/static/images/btn_120x50_powered.png"
created "MyApp/root/static/images/btn_120x50_powered_shadow.png"
created "MyApp/root/static/images/btn_88x31_built.png"
created "MyApp/root/static/images/btn_88x31_built_shadow.png"
created "MyApp/root/static/images/btn_88x31_powered.png"
created "MyApp/root/static/images/btn_88x31_powered_shadow.png"
created "MyApp/root/favicon.ico"
created "MyApp/script/myapp_cgi.pl"
created "MyApp/script/myapp_fastcgi.pl"
created "MyApp/script/myapp_server.pl"
created "MyApp/script/myapp_test.pl"
created "MyApp/script/myapp_create.pl"

$ cd MyApp
$ vim lib/MyApp.pm

use Catalyst qw/-Debug I18N Unicode/;

sub begin : Private {
    my ( $self, $c ) = @_;
    
    my $locale = $c->request->param('locale');
    
    $c->response->headers->push_header( 'Vary' => 'Accept-Language' );  # hmm vary and param?
    $c->languages( $locale ? [ $locale ] : undef );
}

sub default : Private {
    my ( $self, $c ) = @_;

    my $name = $c->request->param('name') || $c->loc('Guest');

    $c->response->content_type('text/plain; charset=utf-8');
    $c->response->body( $c->loc( 'Welcome [_1]!', $name ) );
}

$ mkdir lib/MyApp/I18N
$ xgettext.pl --output=lib/MyApp/I18N/messages.pot --directory=lib/
$ ls lib/MyApp/I18N/
messages.pot

$ msginit --input=lib/MyApp/I18N/messages.pot --output=lib/MyApp/I18N/sv.po --locale=sv
Created lib/MyApp/I18N/sv.po.

$ vim lib/MyApp/I18N/sv.po

"Content-Type: text/plain; charset=utf-8\n"

#: lib/MyApp.pm:50
msgid "Guest"
msgstr "Gäst"

#. ($name)
#: lib/MyApp.pm:54
msgid "Welcome %1!"
msgstr "Välkommen %1!"

$ perl script/myapp_server.pl
[Fri Dec  2 03:52:45 2005] [catalyst] [debug] Debug messages enabled
[Fri Dec  2 03:52:47 2005] [catalyst] [debug] Loaded plugins:
.------------------------------------------------------------------------------.
| Catalyst::Plugin::I18N                                                       |
| Catalyst::Plugin::Unicode                                                    |
'------------------------------------------------------------------------------'

[Fri Dec  2 03:52:47 2005] [catalyst] [debug] Loaded dispatcher "Catalyst::Dispatcher"
[Fri Dec  2 03:52:47 2005] [catalyst] [debug] Loaded engine "Catalyst::Engine::HTTP"
[Fri Dec  2 03:52:47 2005] [catalyst] [debug] Found home "/Users/chansen/MyApp"
[Fri Dec  2 03:52:48 2005] [catalyst] [debug] Initialized i18n "MyApp::I18N"
[Fri Dec  2 03:52:48 2005] [catalyst] [debug] Loaded Private actions:
.----------------------+----------------------------------------+--------------.
| Private              | Class                                  | Method       |
+----------------------+----------------------------------------+--------------+
| /default             | MyApp                                  | default      |
'----------------------+----------------------------------------+--------------'

[Fri Dec  2 03:52:48 2005] [catalyst] [info] MyApp powered by Catalyst 5.57
You can connect to your server at http://localhost:3000

# point your browser to http://localhost:3000/?name=Joe
# output should render:

Välkommen Joe!

$ vim lib/MyApp.pm

sub default : Private {

    # ...

    $c->response->body( $c->loc( 'Welcome to my homepage [_1]!', $name ) );
}

$ xgettext.pl --output=lib/MyApp/I18N/messages.pot --directory=lib/
$ msgmerge --update lib/MyApp/I18N/sv.po lib/MyApp/I18N/messages.pot
. done.

$ vim lib/MyApp/I18N/sv.po

#. ($name)
#: lib/MyApp.pm:54
msgid "Welcome to my homepage %1!"
msgstr "Välkommen till min hemsida %1!"

$ perl script/myapp_server.pl

# point your browser to http://localhost:3000/?name=Joe
# output should render:

Välkommen till min hemsida Joe!

$ perl script/myapp_create.pl view TT TT
 exists "/Users/chansen/MyApp/script/../lib/MyApp/View"
 exists "/Users/chansen/MyApp/script/../t"
created "/Users/chansen/MyApp/script/../lib/MyApp/View/TT.pm"
created "/Users/chansen/MyApp/script/../t/view_TT.t"

$ vim lib/MyApp.pm

sub default : Private {
    my ( $self, $c ) = @_;

    my $name = $c->request->param('name') || $c->loc('Guest');

    $c->response->content_type('text/plain; charset=utf-8');
    $c->stash(
        name     => $name,
        template => 'test.tt' 
    );
    
    $c->forward('MyApp::View::TT');
}

$ vim root/test.tt # Save file in UTF-8 with BOM

[% c.loc( 'Welcome to my place [_1]!', c.stash.name ) %]

$ xgettext.pl --output=lib/MyApp/I18N/messages.pot --directory=lib/ --directory=root/
$ msgmerge --update lib/MyApp/I18N/sv.po lib/MyApp/I18N/messages.pot
. done.    

$ vim lib/MyApp/I18N/sv.po

#. (c.stash.name)
#: root/test.tt:1
msgid "Welcome to my place %1!"
msgstr "Välkommen till mitt ställe %1!"

$ perl script/myapp_server.pl 
[Fri Dec  2 05:12:58 2005] [catalyst] [debug] Debug messages enabled
[Fri Dec  2 05:12:58 2005] [catalyst] [debug] Loaded plugins:
.------------------------------------------------------------------------------.
| Catalyst::Plugin::I18N                                                       |
| Catalyst::Plugin::Unicode                                                    |
'------------------------------------------------------------------------------'

[Fri Dec  2 05:12:58 2005] [catalyst] [debug] Loaded dispatcher "Catalyst::Dispatcher"
[Fri Dec  2 05:12:58 2005] [catalyst] [debug] Loaded engine "Catalyst::Engine::HTTP"
[Fri Dec  2 05:12:58 2005] [catalyst] [debug] Found home "/Users/chansen/MyApp"
[Fri Dec  2 05:12:58 2005] [catalyst] [debug] Initialized i18n "MyApp::I18N"
[Fri Dec  2 05:12:59 2005] [catalyst] [debug] Loaded components:
.-------------------------------------------------------------------+----------.
| Class                                                             | Type     |
+-------------------------------------------------------------------+----------+
| MyApp::View::TT                                                   | instance |
'-------------------------------------------------------------------+----------'

[Fri Dec  2 05:12:59 2005] [catalyst] [debug] Loaded Private actions:
.----------------------+----------------------------------------+--------------.
| Private              | Class                                  | Method       |
+----------------------+----------------------------------------+--------------+
| /default             | MyApp                                  | default      |
'----------------------+----------------------------------------+--------------'

[Fri Dec  2 05:12:59 2005] [catalyst] [info] MyApp powered by Catalyst 5.57
You can connect to your server at http://localhost:3000

# point your browser to http://localhost:3000/?name=Joe
# output should render:

Välkommen till mitt ställe Joe!   

INTRODUCTION

INTERNATIONALIZATION

CONTENT NEGOTIATION

Server-driven

Agent-driven

LOCALIZATION

STAYING IN SYNC

TEMPLATE TOOLKIT

RESOURCES

Documentation

Definitions

Internationalization and localization

http://en.wikipedia.org/wiki/Internationalization_and_localization

Locale

http://en.wikipedia.org/wiki/Locale

Byte Order Mark (BOM)

http://en.wikipedia.org/wiki/Byte_Order_Mark

Character encoding

http://en.wikipedia.org/wiki/Character_encoding

Collation

http://en.wikipedia.org/wiki/Collation

Content Negotiation

http://en.wikipedia.org/wiki/Content_Negotiation

Unicode

http://en.wikipedia.org/wiki/Unicode

Guides

Guidelines, Checklists, and Resources

http://www.i18nguy.com/guidelines.html

Localisation Guide

http://translate.sourceforge.net/wiki/guide/start

Perl

Perl Locale handling

http://search.cpan.org/dist/perl/pod/perllocale.pod

Perl Unicode introduction

http://search.cpan.org/dist/perl/pod/perluniintro.pod

Perl Unicode support

http://search.cpan.org/dist/perl/pod/perlunicode.pod

Unicode-processing issues in Perl and how to cope with it

http://www.ahinea.com/en/tech/perl-unicode-struggle.html

Web Localization in Perl

http://search.cpan.org/dist/Locale-Maketext-Lexicon/docs/webl10n.html

Localization and Perl: gettext breaks, Maketext fixes

http://search.cpan.org/dist/Locale-Maketext/lib/Locale/Maketext/TPJ13.pod

Lessons Learned with Perl and UTF-8

http://www.justatheory.com/computers/programming/perl/utf8_trials.html

UTF-8 and Perl (In Five Minutes)

Slides from a talk given by Mark Fowler.

http://www.twoshortplanks.com/talks/utf8/perlandutf8.pdf

Perl Loves UTF-8

Slides from a talk given by Tom Insam.

http://jerakeen.org/slush/talk-perl-loves-utf8

Perl I18N Mailing List

http://lists.cpan.org/showlist.cgi?name=perl-i18n

Perl Unicode Mailing List

http://lists.cpan.org/showlist.cgi?name=perl-unicode

Portals

Google Directory - Computers > Software > Globalization

http://www.google.com/Top/Computers/Software/Globalization/

Internationalization (I18N), Localization (L10N), Standards, and Amusements

http://www.i18nguy.com/

Standards

RFC 2616 Hypertext Transfer Protocol -- HTTP/1.1

http://www.w3.org/Protocols/rfc2616/rfc2616.html

Section 12: Content Negotiation

http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12

Section 13: Caching in HTTP

http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13

Section 13.6: Caching Negotiated Responses

http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6

RFC 3066 Tags for the Identification of Languages

http://www.faqs.org/rfcs/rfc3066.html

Web

W3C Internationalization (I18N) Activity

http://www.w3.org/International/

Authoring Techniques for XHTML & HTML Internationalization: Characters and Encodings 1.0

http://www.w3.org/TR/i18n-html-tech-char/

Authoring Techniques for XHTML & HTML Internationalization: Specifying the language of content 1.0

http://www.w3.org/TR/i18n-html-tech-lang/

Locale Repositories

Common Locale Data Repository (CLDR)

http://www.unicode.org/cldr/

International Components for Unicode (ICU)

http://www-306.ibm.com/software/globalization/icu/index.jsp

Modules

Character Encoding, Collation and Normalization

Encode

http://search.cpan.org/dist/Encode/

Unicode::Collate

http://search.cpan.org/dist/Unicode-Collate/

Unicode::Normalize

http://search.cpan.org/dist/Unicode-Normalize/

Currency

Locale::Currency::Format

http://search.cpan.org/dist/Locale-Currency-Format/

Math::Currency

http://search.cpan.org/dist/Math-Currency/

Dates

DateTime

http://search.cpan.org/dist/DateTime/

DateTime::Locale

http://search.cpan.org/dist/DateTime-Locale/

DateTime::TimeZone

http://search.cpan.org/dist/DateTime-TimeZone/

Language Tags, Identification and Negotiation

HTTP::Negotiate

http://search.cpan.org/dist/libwww-perl/lib/HTTP/Negotiate.pm

I18N::AcceptLanguage

http://search.cpan.org/dist/I18N-AcceptLanguage/

I18N::LangTags

http://search.cpan.org/dist/I18N-LangTags/

http://search.cpan.org/dist/I18N-LangTags/lib/I18N/LangTags/Detect.pm

Message Catalogs

Locale::Maketext

http://search.cpan.org/dist/Locale-Maketext/

http://search.cpan.org/dist/Locale-Maketext/lib/Locale/Maketext/TPJ13.pod

Locale::Maketext::Lexicon

http://search.cpan.org/dist/Locale-Maketext-Lexicon/

http://search.cpan.org/dist/Locale-Maketext-Lexicon/docs/webl10n.html

http://search.cpan.org/dist/Locale-Maketext-Lexicon/script/xgettext.pl

Locale::Maketext::Simple

Provides a simple interface to Locale::Maketext::Lexicon.

http://search.cpan.org/dist/Locale-Maketext-Simple/

libintl-perl

http://search.cpan.org/dist/libintl-perl/lib/Locale/Messages.pm

http://search.cpan.org/dist/libintl-perl/lib/Locale/TextDomain.pm

Numbers

Number::Format

http://search.cpan.org/dist/Number-Format/

Tools

GNU gettext utilities

http://www.gnu.org/software/gettext/

http://www.gnu.org/software/gettext/manual/html_chapter/gettext.html

http://gnuwin32.sourceforge.net/packages/gettext.htm

gtranslator

Translation tool for Gnome. Supports gettext catalogs.

http://gtranslator.sourceforge.net/

Ini Translator

Translation tool for Windows 98/Me/XP/2000. Supports several formats, including gettext catalogs.

http://initranslator.sourceforge.net/

KBabel

Translation tool for KDE. Supports gettext catalogs.

http://i18n.kde.org/tools/kbabel/

LocFactory Editor

Translation tool for Mac OS X. Supports sevral formats, including gettext catalogs.

http://www.triplespin.com/en/products/locfactoryeditor.html

poEdit

A cross-platform gettext catalogs editor.

http://www.poedit.org/

AUTHOR

Christian Hansen ch@ngmedia.com

COPYRIGHT

This program is free software, you can redistribute it and/or modify it under the same terms as Perl itself.