<!--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:
|
We also define a simple redirect function that would redirects user 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. |
<http://localhost:8080/hello> URL.
|
|
---
|
|
← [JSON RPC][prev]
|
| [Top](#maincontent)
|
| [Advanced Caching][next] →
|
|
[prev]: /wikipp/en/page/cppcms_1x_json_rpc
|
[next]: /wikipp/en/page/cppcms_1x_adv_caching |