📜 ⬆️ ⬇️

Localization of projects written using Catalyst MVC Framework

Catalyst Web Framework Suppose there are still desperate comrades studying and proving the advantages of Perl over other web development tools. More rarely, among them are those who rated the Catalyst framework without fearing the lack of documentation in Russian. I believe that those who are interested in this post are already familiar with how to create a new project, add missing parts to View TT and install the CPAN .

I believe that one of the most important factors separating manual crafts from the program is its localization. For this reason, starting to learn a new platform, after studying ideology, I find out the mechanism of localization.

Since Perl means gettext , but not everything is so simple. Let's go to practice.

Project preparation


To begin with, we will create a new project or open an existing one, say MyApp . Take the update_po.sh script from the MojoMojo project and put it in the ./script project ./script . In order for this script to become suitable, it is necessary to do the following manipulation on it, I hope none of the authors will not mind.
')
We make the replacement of MOJOMOJO_DIR with PROJECT_DIR in the whole file.
 # Default setting PERL_DEFAULT=`which perl` PROJECT_DIR="." PROJECT_NAME="MyApp" 

Add a local variable PROJECT_NAME with the name of your project and make a replacement in the entire MojoMojo file with $PROJECT_NAME .

For the operation of this script, another po2json.pl program is needed , it is saved in ./script . Both files are executable.
UPD
The po2json script is part of the module Locale::Simple


If you look at the update_po.sh code, you can see that the collection of strings for localization occurs in the following files and directories:

If necessary, the script can be corrected for your projects.
Create a directory ./lib/MyApp/I18N , it will be our .po files. If we use javascript, then we need to create a directory ./root/static/json .

Code and settings


We add View :: TT, we name class HTML. If we have an existing project with our own presentation, we can skip this item.
  $ ./script/myapp_create.pl view HTML TT 

This command creates a file ./lib/MyApp/View/HTML.pm . In its configuration section, add a path that will indicate where the templates will be located:
 __PACKAGE__->config( TEMPLATE_EXTENSION => '.tt', INCLUDE_PATH => [ MyApp->path_to('root', 'base'), ], render_die => 1, ); 

For simplicity in ./lib/MyApp.pm we do this default view:
 __PACKAGE__->config( name => 'MyApp', default_view => 'HTML', 'View::HTML' => { ENCODING => 'UTF-8', }, ... 

and in the plug-in declaration, add I18N and Unicode :
 use Catalyst qw/ -Debug ConfigLoader Static::Simple I18N Unicode ... 

The I18N plugin adds loc() or localize() to the project. About other features you can read here Catalyst :: Plugin :: I18N .

We proceed to the design of the first localized page. Let's try two call options at the same time. The first one transfers the line from the controller to the template using the stash tool, we will display it in the page header. The second reflects the line in the body of the page by means of the function call in the template engine.
Modify the function responsible for the root page in ./lib/MyApp/Controller/Root.pm :
 sub index :Path :Args(0) { my ( $self, $c ) = @_; $c->stash->{title} = $c->loc("Home Page"); } 

Create a template for our index page ./root/base/index.tt
 <!doctype html> <html> <head> <meta charset="utf-8" /> <title>[% title %]</title> </head> <body> [% c.loc("Hello World!") %] </body> <html> 

We start and check. If errors have occurred: fix / reload modules with CPAN.

Now go to the translation of our page. We create empty files for Russian and, say, German localization:
  $ touch ./lib/MyApp/I18N/ru.po ./lib/MyApp/I18N/de.po 

and fill them with the script, which was discussed at the beginning of the article:
  $ ./script/update_po.sh ru de 
If any errors occur, add the missing modules to the CPAN.

Now edit these files using the example of the “native”:
 "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru\n" #: root/base/index.tt:8 msgid "Hello World!" msgstr " !" #: lib/MyApp/Controller/Root.pm:32 msgid "Home Page" msgstr " " 

save, restart the server and go to the page. If the Russian language is your priority in your browser, then your acquaintances from the first class should caress your eyes.

If the project source code is update_po.sh restart update_po.sh with the update_po.sh languages, the old data in the .po files is saved.

Database


For correct storage and use of localized information in View, it is necessary for the driver, when connected to the database, to report that the information is transmitted in utf8. To do this, in the connection configuration, specify a parameter equal to one, which is different for each SQL database: sqlite_unicode, mysql_enable_utf8, pg_enable_utf8, odbc_utf8_on, etc.
 <Model::DB> <connect_info> dsn dbi:mysql:database user username password password mysql_enable_utf8 1 </connect_info> </Model::DB> 
See the documentation for the DBI driver for details.

Crutches


If we output already localized information via TT , for example, from a database or a text file, then we are very likely to see krakozyabry. To cure us, this function will help:
 sub enc { my ( $self, $str ) = @_; utf8::decode($str); return $str; } 

we insert it into ./lib/MyApp.pm , respectively, we can call this function as from perl :
  $c->stash->{field} = $c->enc($data); 

so in TT :
  [% c.enc(list.field) %] 

There is another way for TT , is to create a filter. To do this, you need to define FILTERS in the configuration of the view ./lib/MyApp/View/HTML.pm
 __PACKAGE__->config( TEMPLATE_EXTENSION => '.tt', INCLUDE_PATH => [ MyApp->path_to('root', 'base'), ], render_die => 1, FILTERS => { enc => sub { utf8::decode($_[0]); $_[0]; }, } ); 

Called the filter in this way:
  [% list.field | enc %] 

But there is with him some kind of BAG when using data and dbi.

Javascript


First of all, you need to add a wrapper function, preferably in the form of a loadable file:
 function loc(str) { if ( (typeof(locale) === 'undefined') || (typeof locale[str] === 'undefined') ) return str; return locale[str] } 

and in the page header add the download of the translated localization data
 ... <script src="[% c.uri_for_static('json/') _ c.language _ '.po.json' %]" type="text/javascript"></script> </head> 

Editing of localization files occurs in two stages: call update_po.sh and edit the localization file in ./lib/MyApp/I18N ; call update_po.sh again to update the ./root/static/json/[lang].po.json file.

PS:


This article covers a very small part of the localization issues of a project for Catalyst, but it is sufficient to start.

Source: https://habr.com/ru/post/146893/


All Articles