Main  /  Edit version 1  /  Edit version 2  /   /  Users Area

Difference "Internationalization and Localization" ver. 1 versus ver. 2

Content:

<!--toc-->
## Introduction
CppCMS has a sophisticated internationalization and
localization support. During CppCMS development localization
tools were submitted to [Boost Project](http://www.boost.org)
and accepted as [Boost.Locale](http://www.boost.org/libs/locale/index.html) library.
So you can find exactly the same code in `boost::locale`
and `booster::locale` namespace. The only difference is
the namespace. So I strongly recommend reading extensive
localization tutorials you can find for Boost.Locale
as they are applicable as-is for CppCMS's `booster::locale`.
So please refer to [Boost.Locale](http://www.boost.org/libs/locale/index.html) documentation for any problems or questions you have.
In this tutorial we would see how Boost.Locale is integrated
to CppCMS and how to use it for CppCMS development.
## Concepts
All locale related information is hold in `std::locale` object. CppCMS allows to use context specific locale and
change it according to the needs.
## Example
Lets create a simple web site that greets us in two languages English and Hebrew.
We would have following URLs:
- `/hello` - redirects to `/hello/en_US`
- `/hello/en_US` - greeting in English
- `/hello/he_IL` - greeting in Hebrew
We would see how to set the application's locale and
how to translate different messages from the
templates and from the application itself.
## Preparing the Sources
### View
Let's define our view's render function
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
</head>
<% if rtl %>
<body dir="rtl">
<% else %>
<body>
<% end %>
<h1><% gt "We want to say" %></h1>
<p><%= message %></p>
<p><a href="he_IL">he</a>/<a href="en_US">en</a></p>
</body>
<html>
Now let's note different parts step by step:
- Line 3: we use `UTF-8` encoding - which is the recommended default encoding
- Line 10: `<% gt "We want to say" %>` - show localized message.
"We want to say" would be translated to the locale we
want to use using special dictionaries or if there is
no translation - original string would be displayed.
- line 5: `<% if rtl %>` - check if the language is Right-To-Left language like Hebrew. If it is we change the directionality of the text. Using this condition we can also
alter different layout parameters.
The condition would be true of the "LTR" message is
translated to "RTL" message in our templates.
The rest is the usual.
### Content
It would be very simple:
struct message : public cppcms::base_content {
std::string message;
};
We would see how we would be able to localize the `message`
as well.
### Controller
We define our `hello` class:
hello(cppcms::service &srv) :
cppcms::application(srv)
{
dispatcher().assign("^/(en_US|he_IL)/?$",&hello::say_hello,this,1);
dispatcher().assign("^(.*)$",&hello::redirect,this);
}
In the first assignment we map between the URL and the function: `say_hello`, we path the locale (he\_IL or en\_US) as a parameter.
We also define a simple redirect function that would redirects use to `en_US` by default:
void redirect()
{
response().set_redirect_header(request().script_name() + "/en_US");
}
Now let's see how we handle a language:
void say_hello(std::string lang)
{
context().locale(lang + ".UTF-8");
content::message c;
c.message=translate("Hello World");
render("message",c);
}
First we define current locale as `en_US.UTF-8` or `he_IL.UTF-8`.
Now the correct locale would be associated with
the output stream and with the current request/response context.
Then we translate a "Hello World" message using
`cppcms::application::translate(...)` member functions
that use current `context()`'s locale.
Then we finally render the content. Because
we setup the correct locale this
would let the template engine know in which locale
the message "We want to say" should be translated.
Please note, even when we do not define the locale explicitly, the default system locale would be used
or the first locale defined in `localization.locales` list.
## Extracting Messages
Now when we prepared all the sources we want to
extract all the messages we want to translate.
Full Boost.Locale tutorial about message translation
can be found [here](http://www.boost.org/doc/libs/1_48_0/libs/locale/doc/html/messages_formatting.html) but let's
see the process in few words.
The messages are distributed all over our source code: cpp files templates and so on. We can use `xgettext` tool that
is a part of `gettext` project to extract such messages,
however we need to have all C++ sources.
So we need to compile our view:
cppcms_tmpl_cc -d hello view.tmpl -o view.cpp
And then extract the messages from both `view.cpp` and
our `hello.cpp` using xgettext as following:
xgettext --keyword=translate:1,1t view.cpp hello.cpp
What we get is a file called `messages.po` that would
look like:
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
...
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: view.tmpl:9
msgid "LTR"
msgstr ""
#: view.tmpl:14
msgid "We want to say"
msgstr ""
#: hello.cpp:25
msgid "Hello World"
msgstr ""
That includes three messages:
- "LTR" - the directionality of the language.
- "We want to say" - extracted from the templates
- "Hello World" - extracted from the sources.
Now we can translate them to Hebrew and create
a file "hello.po" that looks like:
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: view.tmpl:6
msgid "LTR"
msgstr "RTL"
#: view.tmpl:11
msgid "We want to say"
msgstr "אנחנו רוצים לומר"
#: hello.cpp:21
msgid "Hello World"
msgstr "שלום עולם"
Note: "LTR" is - translated to RTL as Hebrew is right-to-left language.
We create an appropriate directory structure to search
files in:
locale/he/LC_MESSAGES/
Then we compile it to the binary mo file as:
msgfmt hello.po -o locale/he/LC_MESSAGES/hello.mo
This `hello.mo` file can be used by the localization Engine.
## Configuration
Now we need to tell CppCMS what locale to use and were
to take the localization catalogs:
It is done via configuration file as following:
"localization" : {
"messages" : {
"paths" : [ "./locale" ],
"domains" : [ "hello" ]
},
"locales" : [ "he_IL.UTF-8", "en_US.UTF-8" ]
}
- `localization.messages.paths` specifies the path to
the `locale` directory the holds `he/LC_MESSAGES/hello.mo`
catalog.
- `localization.messages.domains` specifies the catalog name - in our case `hello` and
- `localization.locales` defines locales we want to support
in our application. The first one becomes the default
one.
## Running Our Sample
So once we got following files:
./config.js
# Configuration File
./hello
# Executable
./locale
./locale/he
./locale/he/LC_MESSAGES
./locale/he/LC_MESSAGES/hello.mo
# Messages Catalog
We can run our application
./hello -c config.js
And see how localization works `:-)` by visiting
<!--toc-->
## Introduction
CppCMS has a sophisticated internationalization and
localization support. During CppCMS development localization
tools were submitted to [Boost Project](http://www.boost.org)
and accepted as [Boost.Locale](http://www.boost.org/libs/locale/index.html) library.
So you can find exactly the same code in `boost::locale`
and `booster::locale` namespace. The only difference is
the namespace. So I strongly recommend reading extensive
localization tutorials you can find for Boost.Locale
as they are applicable as-is for CppCMS's `booster::locale`.
So please refer to [Boost.Locale](http://www.boost.org/libs/locale/index.html) documentation for any problems or questions you have.
In this tutorial we would see how Boost.Locale is integrated
to CppCMS and how to use it for CppCMS development.
## Concepts
All locale related information is hold in `std::locale` object. CppCMS allows to use context specific locale and
change it according to the needs.
## Example
Lets create a simple web site that greets us in two languages English and Hebrew.
We would have following URLs:
- `/hello` - redirects to `/hello/en_US`
- `/hello/en_US` - greeting in English
- `/hello/he_IL` - greeting in Hebrew
We would see how to set the application's locale and
how to translate different messages from the
templates and from the application itself.
## Preparing the Sources
### View
Let's define our view's render function
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
</head>
<% if rtl %>
<body dir="rtl">
<% else %>
<body>
<% end %>
<h1><% gt "We want to say" %></h1>
<p><%= message %></p>
<p><a href="he_IL">he</a>/<a href="en_US">en</a></p>
</body>
<html>
Now let's note different parts step by step:
- Line 3: we use `UTF-8` encoding - which is the recommended default encoding
- Line 10: `<% gt "We want to say" %>` - show localized message.
"We want to say" would be translated to the locale we
want to use using special dictionaries or if there is
no translation - original string would be displayed.
- line 5: `<% if rtl %>` - check if the language is Right-To-Left language like Hebrew. If it is we change the directionality of the text. Using this condition we can also
alter different layout parameters.
The condition would be true of the "LTR" message is
translated to "RTL" message in our templates.
The rest is the usual.
### Content
It would be very simple:
struct message : public cppcms::base_content {
std::string message;
};
We would see how we would be able to localize the `message`
as well.
### Controller
We define our `hello` class:
hello(cppcms::service &srv) :
cppcms::application(srv)
{
dispatcher().assign("^/(en_US|he_IL)/?$",&hello::say_hello,this,1);
dispatcher().assign("^(.*)$",&hello::redirect,this);
}
In the first assignment we map between the URL and the function: `say_hello`, we path the locale (he\_IL or en\_US) as a parameter.
We also define a simple redirect function that would redirects use to `en_US` by default:
void redirect()
{
response().set_redirect_header(request().script_name() + "/en_US");
}
Now let's see how we handle a language:
void say_hello(std::string lang)
{
context().locale(lang + ".UTF-8");
content::message c;
c.message=translate("Hello World");
render("message",c);
}
First we define current locale as `en_US.UTF-8` or `he_IL.UTF-8`.
Now the correct locale would be associated with
the output stream and with the current request/response context.
Then we translate a "Hello World" message using
`cppcms::application::translate(...)` member functions
that use current `context()`'s locale.
Then we finally render the content. Because
we setup the correct locale this
would let the template engine know in which locale
the message "We want to say" should be translated.
Please note, even when we do not define the locale explicitly, the default system locale would be used
or the first locale defined in `localization.locales` list.
## Extracting Messages
Now when we prepared all the sources we want to
extract all the messages we want to translate.
Full Boost.Locale tutorial about message translation
can be found [here](http://www.boost.org/doc/libs/1_48_0/libs/locale/doc/html/messages_formatting.html) but let's
see the process in few words.
The messages are distributed all over our source code: cpp files templates and so on. We can use `xgettext` tool that
is a part of `gettext` project to extract such messages,
however we need to have all C++ sources.
So we need to compile our view:
cppcms_tmpl_cc -d hello view.tmpl -o view.cpp
And then extract the messages from both `view.cpp` and
our `hello.cpp` using xgettext as following:
xgettext --keyword=translate:1,1t view.cpp hello.cpp
What we get is a file called `messages.po` that would
look like:
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
...
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: view.tmpl:9
msgid "LTR"
msgstr ""
#: view.tmpl:14
msgid "We want to say"
msgstr ""
#: hello.cpp:25
msgid "Hello World"
msgstr ""
That includes three messages:
- "LTR" - the directionality of the language.
- "We want to say" - extracted from the templates
- "Hello World" - extracted from the sources.
Now we can translate them to Hebrew and create
a file "hello.po" that looks like:
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: view.tmpl:6
msgid "LTR"
msgstr "RTL"
#: view.tmpl:11
msgid "We want to say"
msgstr "אנחנו רוצים לומר"
#: hello.cpp:21
msgid "Hello World"
msgstr "שלום עולם"
Note: "LTR" is - translated to RTL as Hebrew is right-to-left language.
We create an appropriate directory structure to search
files in:
locale/he/LC_MESSAGES/
Then we compile it to the binary mo file as:
msgfmt hello.po -o locale/he/LC_MESSAGES/hello.mo
This `hello.mo` file can be used by the localization Engine.
## Configuration
Now we need to tell CppCMS what locale to use and were
to take the localization catalogs:
It is done via configuration file as following:
"localization" : {
"messages" : {
"paths" : [ "./locale" ],
"domains" : [ "hello" ]
},
"locales" : [ "he_IL.UTF-8", "en_US.UTF-8" ]
}
- `localization.messages.paths` specifies the path to
the `locale` directory the holds `he/LC_MESSAGES/hello.mo`
catalog.
- `localization.messages.domains` specifies the catalog name - in our case `hello` and
- `localization.locales` defines locales we want to support
in our application. The first one becomes the default
one.
## Running Our Sample
So once we got following files:
./config.js
# Configuration File
./hello
# Executable
./locale
./locale/he
./locale/he/LC_MESSAGES
./locale/he/LC_MESSAGES/hello.mo
# Messages Catalog
We can run our application
./hello -c config.js
And see how localization works `:-)` by visiting
<http://localhost:8080/hello> URL.

Sidebar:

## Related
- [Boost.Locale](http://www.boost.org/libs/locale/index.html)
## Related
- [Boost.Locale](http://www.boost.org/libs/locale/index.html)
← [JSON RPC](http://cppcms.com/wikipp/en/page/cppcms_1x_json_rpc)
[Advanced Caching.](http://cppcms.com/wikipp/en/page/cppcms_1x_adv_caching)→

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page


Valid CSS | Valid XHTML 1.0