I recently had to deal with the internationalization of Web
applications on the Node.js + Express, on which I am working, and I
think turned out quite well (foreign users very happy, and I can see a
noticeable influx of traffic from non-English speaking countries). Internationalization strategy, which I will describe, not too much tied to the Node and can go to any web application.
I often use the multilingual website or go to English-language websites around the world, so I have a good idea of what requirements must be satisfied Internationalization:
After all should get something like this structure:
Equality between languages and enable the use of subdomains to switch between the languages of any page simply by adding a national subdomain:
Both pages should work and look the same, except that the second will be in Japanese.
The heading of the page, I can easily put a link on the same page in another language:
You can also use the technique of rel = "Alternate" hreflang = "x" , the search engine Google to help better understand the structure of my site. If I put this line in the header of the page, Google will show a localized version in search results.
It is very important to help the user find the content to him, especially if the decline the transfer or redirect. Links to alternate languages in the header - that's good, but even better to withdraw the notification at the top of the page, prompting the user to switch to the native language (and here attempt to automatically guess the language is quite appropriate):
As it turned out, to realize it's not that easy. The easiest way - to look in the Accepted language request header, but this works only if your site is fully dynamic and never cached.
If not, then you need to consider how and where to connect the cache.
In my case I use Nginx to multiple servers Node / Express. So, cache all that, a server application on the Node, including notification to the proposal to switch the language.
The result has to manage the notification to the client. And here we have another obstacle on the client means DOM / JavaScript can not reliably determine the appropriate language.
So we need to report to the application server in addition to the desired language.
I used the module Nginx AcceptedLanguage . I set the cookie, indicating the language and gave it to the client. Here is how the configuration looks Nginx:
Now all I had to do on the client - it's cookie and display a notification if the language does not match the language of the page.
Thus Nginx continues aggressively cache all content, and on the client correctly displays a message asking to visit the localized version of the page.
I wrote my Node.js module for internationalization. It uses the following strategy:
Since a limited set of servers to process multiple requests at the same time, the logic of internationalization can not be shared, it should work for each request separately. I've seen solutions, such as i18n-node , which suggest that the server at the same time will produce pages in one language only. In practice, this does not work, especially in an asynchronous world Node.js.
If you come query sets the preferred language for the common object of internationalization, it can lead to the fact that the server will return in response to another query incorrect language version:
At a minimum, you should make sure that the information on the preferred language is not lost in time, the current request (in my module is implemented).
In practice, this means that you need to add the property
The logic of internationalization behaves differently at design and prodakshene.
In Design:
In prodakshene:
The two key differences - the dynamic loading and translation updates. During development it is useful to update them with each change to see the result of their actions, and do not forget to put a single line. In prodakshene not assume their static files - pull the disc at each request is silly.
Line, in need of translation, can be anywhere: in the application code, templates, and even (God forbid!) In styles.
In my application, I just made sure that the JavaScript and CSS were no lines of text. If I need to dynamically generate some text in the application, I would have made it through the patterns using a bit of my micro-templating .
I think it is very important to avoid contact with any strings to be translated into files CSS or JavaScript, so the files are cached or even desirable to place on CDN. Naturally, you can create multiple versions of JavaScript and CSS files when building the project, but I prefer not to complicate the build process.
The only exception in my application, when the code contains translatable strings - code representations Express, where I use an object attached to the request
I use a template swig , but the technique of translation will be about the same for any templating:
A string wrapped in a call to
For now I'll translate the application, without the need for third-party translators. The application is still very small, there are only a few dozen lines to translate.
I can share a few tricks that can help you survive a little longer without the involvement of a professional translator:
I'm working on internationalizing the site a couple of weeks, so I'm sure many more will change when the site will grow. However, the translation has already tangible results, visits became much more, thanks in part to the fact that Google has indexed the localized page. My module internationalization is a great help to me, and I hope to be able to facilitate the transfer and others.
I often use the multilingual website or go to English-language websites around the world, so I have a good idea of what requirements must be satisfied Internationalization:
- Full equality between languages. The same content should be available to all.
- Different language versions must be in subdomains. Use separate top-level domains for different languages - too expensive and not necessary. In addition, because it is more convenient to switch between languages by editing the URL.
- No automatic translation. Nothing is worse than to stumble on an unreadable version of the site because the server Framed curve machine translation, guided by your IP or language settings of the computer. The same URL should always point to the same language version.
- No automatic redirect to the national version of the site. Around the same reasons as in the previous paragraph - if I go to foo.com, I do not need to send to es.foo.com only because the server thought I was from Spain. Instead it is better to show a notification to (presumably) my own language and suggest manually enter the national version.
After all should get something like this structure:
- domain.com - basic (English) version;
- ja.domain.com - Japanese version;
- XX.domain.com - other languages.
Equality between languages and enable the use of subdomains to switch between the languages of any page simply by adding a national subdomain:
- domain.com / search? q = mountain
- ja.domain.com / search? q = mountain
Both pages should work and look the same, except that the second will be in Japanese.
The heading of the page, I can easily put a link on the same page in another language:
You can also use the technique of rel = "Alternate" hreflang = "x" , the search engine Google to help better understand the structure of my site. If I put this line in the header of the page, Google will show a localized version in search results.
<link rel="alternate" hreflang="ja" href="http://ja.domain.com/" />
The server side
It is very important to help the user find the content to him, especially if the decline the transfer or redirect. Links to alternate languages in the header - that's good, but even better to withdraw the notification at the top of the page, prompting the user to switch to the native language (and here attempt to automatically guess the language is quite appropriate):
As it turned out, to realize it's not that easy. The easiest way - to look in the Accepted language request header, but this works only if your site is fully dynamic and never cached.
If not, then you need to consider how and where to connect the cache.
In my case I use Nginx to multiple servers Node / Express. So, cache all that, a server application on the Node, including notification to the proposal to switch the language.
The result has to manage the notification to the client. And here we have another obstacle on the client means DOM / JavaScript can not reliably determine the appropriate language.
So we need to report to the application server in addition to the desired language.
I used the module Nginx AcceptedLanguage . I set the cookie, indicating the language and gave it to the client. Here is how the configuration looks Nginx:
set_from_accept_language $lang en ja; add_header Set-Cookie lang=$lang;
Now all I had to do on the client - it's cookie and display a notification if the language does not match the language of the page.
Thus Nginx continues aggressively cache all content, and on the client correctly displays a message asking to visit the localized version of the page.
The logic of internationalization
I wrote my Node.js module for internationalization. It uses the following strategy:
- All translations are stored in files in the format of JSON;
- These files are used to translate on the fly at the time of use;
- Translated by a conventional method, by calling the
__("Some string")
. If a translation exists, the string"Some string"
is replaced by the translation, if not used directly.
Since a limited set of servers to process multiple requests at the same time, the logic of internationalization can not be shared, it should work for each request separately. I've seen solutions, such as i18n-node , which suggest that the server at the same time will produce pages in one language only. In practice, this does not work, especially in an asynchronous world Node.js.
If you come query sets the preferred language for the common object of internationalization, it can lead to the fact that the server will return in response to another query incorrect language version:
At a minimum, you should make sure that the information on the preferred language is not lost in time, the current request (in my module is implemented).
In practice, this means that you need to add the property
i18n
object to request
, in the same way as is usually added to the middleware Express: app.use(function(req, res, next) { req.i18n = new i18n(/* options... */); next(); });
Organization of work
The logic of internationalization behaves differently at design and prodakshene.
In Design:
- Translation files are loaded at kazhdm request;
- Translation files are dynamically updated after any change;
- Show warning and debug messages.
In prodakshene:
- All translation files are cached;
- Files are never updated dynamically;
- Warning and debug messages are displayed.
The two key differences - the dynamic loading and translation updates. During development it is useful to update them with each change to see the result of their actions, and do not forget to put a single line. In prodakshene not assume their static files - pull the disc at each request is silly.
Code Organization
Line, in need of translation, can be anywhere: in the application code, templates, and even (God forbid!) In styles.
In my application, I just made sure that the JavaScript and CSS were no lines of text. If I need to dynamically generate some text in the application, I would have made it through the patterns using a bit of my micro-templating .
I think it is very important to avoid contact with any strings to be translated into files CSS or JavaScript, so the files are cached or even desirable to place on CDN. Naturally, you can create multiple versions of JavaScript and CSS files when building the project, but I prefer not to complicate the build process.
The only exception in my application, when the code contains translatable strings - code representations Express, where I use an object attached to the request
i18n
: module.exports = { index: function(req, res) { req.render("index", { title: req.i18n.__("My Site Title"), desc: req.i18n.__("My Site Description") }); } };
I use a template swig , but the technique of translation will be about the same for any templating:
{% extends "page.swig" %} {% block content %} <h1>{{ __("Welcome to:") }} {{ title }}</h1> <p>{{ desc }}</p> {% endblock %}
A string wrapped in a call to
__(...)
is replaced by the translation. Actual translation
For now I'll translate the application, without the need for third-party translators. The application is still very small, there are only a few dozen lines to translate.
I can share a few tricks that can help you survive a little longer without the involvement of a professional translator:
- Use ready-made translations of open source projects. There are many open source projects and frameworks containing professional translation interface elements. For example, the framework Drupal has many such transfers in a convenient format. I found there are several ready-made phrases.
- Look to similar language projects. If there are examples of high-quality multilingual sites that implement similar to your functionality, you can take the translation there. My current application - a search engine, so many lines on the pages of Google to exactly match mine.
- Google Translate. Yeah, yeah, I know what you're thinking, but I am very impressed with the progress of Google Translate in recent years, especially in the translation of certain words and expressions. Now there were even different versions of the translation with their probability, which is very bad.
Findings
I'm working on internationalizing the site a couple of weeks, so I'm sure many more will change when the site will grow. However, the translation has already tangible results, visits became much more, thanks in part to the fact that Google has indexed the localized page. My module internationalization is a great help to me, and I hope to be able to facilitate the transfer and others.
0 commentaires:
Enregistrer un commentaire