What is the best way for supporting a multi-language site in smarty template?
I have read http://smarty.incutio.com/?page=SmartyMultilanguageSupport
and http://www.smarty.net/docsv2/fr/language.config.variables.tpl and now I can't make a decision which option I will to use.
Are there other options?
I use a $_get['lang'] to get the language to be used. In the template, for every pages I get 2 ifs, one if EN another if FR and I generate the code accordingly.
The header footer and meta data comes from database and based on the language, the row required by the language will be fetched.
I read language from cookies and set/change it with http request. Based on the languge used, I just change field names (in php) to query from database (including all strings on page - they are stored for each language in different fields - I know that this is not very scalable, but will be enough for this kind of sites). Additionally I set one smarty variable to language code and when needed (rarely, because strings are already localised), I use smarty {if $language ...} structures to change output.
Someone might find this interesting. Basically lang variable to get the current language and loads a file via config_load. Both are basically the same, just that your first link has all the functions needed packed into a small module.
http://www.freesoftwaremagazine.com/articles/creating_multilingual_website_smarty
Related
Hi to all developers...
I'm new to Laravel. I want to build a complex web application and it's important to support at least 2 language. Unfortunately, One of these language is LTR and other is RTL!My questions are:
Some parts of website have static content, like headers, navigation items, sidebar content or... . As I understand, I must create files in lang directory and based on selected language, load proper data. Is it right? In this way, Is it possible to load these static data from lang directory files cause slower app and bad performance? (compare with static views, blade files that have content and don't need to load small piece of data from lang directory).
Considering first question, is it better to have one set of views for one language and another set of views for second language? (each set of views have their static data and don't require use lang files to full parts of header, sidebar and...)
As I said, I must have a LTR and a RTL layout in order to have best UI. So I must have separate stylesheets and loads based on choosen language, is it right?
I have some questions for multi language database design, but I start a new discussion later. Thanks for your attention and I hope that you guide me and say your opinions...
Some parts of website have static content, like headers, navigation items, sidebar content or... . As I understand, I must create files in lang directory and based on selected language, load proper data. Is it right? In this way, Is it possible to load these static data from lang directory files cause slower app and bad performance? (compare with static views, blade files that have content and don't need to load small piece of data from lang directory)
Yes, by all means make sure you abstract your language from your views. This is a good practice that you will definitely want to do to save yourself multiple identical views per language (nightmare!).
When you program anything there is a performance overhead. When you use functionality such as this, you're making your life a lot easier. The performance hit is tiny. Don't use this as a reason to not do this.
Considering first question, is it better to have one set of views for one language and another set of views for second language? (each set of views have their static data and don't require use lang files to full parts of header, sidebar and...)
No, this is a nightmare scenario for most developers. Maintaining multiple brittle views due to language eats up time when separation of these concerns at the beginning removes any need for this to happen.
As I said, I must have a LTR and a RTL layout in order to have best UI. So I must have separate stylesheets and loads based on choosen language, is it right?
LTR and RTL is a problem wholly solvable using some simple CSS alone, no need to have separate style sheets. Instead, using a single class on the body you can apply the correct styling. <body class="{{ $rtl ? 'rtl' : 'ltr'}}">. Now you can use CSS' direction property to define the direction text reads.
As you are using Laravel, leverage the framework as much as you can. There is no need for you to re-invent the wheel with this.
I am creating a website for a local company and I am splitting off the header for each page into a individual php page which I then include into each page. I was wondering what would be the best practice to insert individual description and title content into the php header for each individual page. Should I create a php variable before the included header.php link and then insert that variable argument into the title and description tags in the php file? Each variable would have different titles and description depending on what page it's on. Or would it make more sense to someone include these different description and title content into another external php page? If you have a even more correct/easier way that would also work best with SEO please let me know. Thanks!
I would suggest creating a Metadata object definition, with all of the properties required (description, tags, etc). Then instantiate a Metadata object for each page of the site, just before including your header, and use the values of the current Metadata object in the header.
split your logic (and titles, page information, dynamic content) from your templates via an MVC type architecture
here are some easy to learn templating engines (and I believe the two most popular)
http://www.smarty.net
http://twig.sensiolabs.org
You can read about MVC architecture here: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
However you do it, basically what you suggest initially is one of the best ways. Define a variable, or object, or whatever, in each page before the inclusion of the header.php file (again, whether that's a template, or just a regular php inclusion, up to you). Then just set them to whatever you want for each page, and you're good to go.
Personally, I would recommend using a template engine like Smarty.
As for SEO, that's an entirely different conversation. That's more related to the content of the variables, as opposed to the implementation of them.
I have a site with texts in 2 languages. How should I go between the pages so that from the point that he clicked to change the language he will see it and the moment he clicks the other language, it will change back?
An option is that when the user clicks the link to change the language I will store it into the session and use it. But I've heard it won't work well with the search engines.
A second option is to pass the language variable through the URL to every page.
Third option is to smartly use the zend extension ability.
(Using PHP + Zend Framework).
SEO is very important to me.
EDIT:
The texts that are in the site(and that are in several languages), are entered by an admin. It works now with languages objects that I've created with the option for the admin to add texts in each of them. So when I'll enter the first page(of which the text can be changed) I'll see it in English and when I click the Russian flag it will display that page(and the others later) in Russian.
Using Zend_Locale or translate won't work for me(I think), and passing through the URL is an option. The question is if it is the best one?
It is best to pass it along as a parameter in the URL, google uses locale=en for this. It would also be ok to store it in the session only if the user is logged into your website and selected a preferred locale or something. That way search engines can index the different locales with different urls, but your users would see pages in whatever locale they have chosen.
Zend Framework provides a pretty solid set of tools for this.
Start with Zend_Locale and Zend_Translate
It ought to be possible to tweak ZF's routing to contain a segment that indicates the locale. So you'd end up something like /:locale/:controller/:action (or similar). Your URLs would then look like http://example.com/en/some-controller/some-action.
Note that there's more than just translation of language. You can also localize the display of numbers, currency, dates, etc.
Come back with more specific questions once you've played with those.
I am working on a large multilingual website and I am considering different approaches for making it multilingual. The possible alternatives I can think of are:
The Gettext functions with generation of .po files
One MySQL table with the translations and a unique string ID for each text
PHP-files with arrays containing the different translations with unique string IDs
As far as I have understood the Gettext functions should be most efficient, but my requirement is that it should be possible to change a text string in the original reference language (English) without the other translations of that string automatically reverting back to English just because a couple of words changed. Is this possible with Gettext?
What is the least resource demanding solution?
Is using the Gettext functions or PHP files with arrays more or less equally resource demanding?
Any other suggestions for more efficient solutions?
A few considerations:
1. Translations
Who will be doing the translations? People that are also connected to the site? A translation agency? When using Gettext you'll be working with 'pot' (.po) files. These files contain the message ID and the message string (the translation). Example:
msgid "A string to be translated would go here"
msgstr ""
Now, this looks just fine and understandable for anyone who needs to translate this. But what happens when you use keywords, like Mike suggests, instead of full sentences? If someone needs to translate a msgid called "address_home", he or she has no clue if this is should be a header "Home address" or that it's a full sentence. In this case, make sure to add comments to the file right before you call on the gettext function, like so:
/// This is a comment that will be included in the pot file for the translators
gettext("ready_for_lost_episode");
Using xgettext --add-comments=/// when creating the .po files will add these comments. However, I don't think Gettext is ment to be used this way. Also, if you need to add comments with every text you want to display you'll a) probably make an error at some point, b) you're whole script will be filled with the texts anyway, only in comment form, c) the comments needs to be placed directly above the Gettext function, which isn't always convient, depending on the position of the function in your code.
2. Maintenance
Once your site grows (even further) and your language files along with it, it might get pretty hard to maintain all the different translations this way. Every time you add a text, you need to create new files, send out the files to translators, receive the files back, make sure the structure is still intact (eager translators are always happy to translate the syntax as well, making the whole file unusable :)), and finish with importing the new translations. It's doable, sure, but be aware with possible problems on this end with large sites and many different languages.
Another option: combine your 2nd and 3rd alternative:
Personally, I find it more useful to manage the translation using a (simple) CMS, keeping the variables and translations in a database and export the relevent texts to language files yourself:
add variables to the database (e.g.: id, page, variable);
add translations to these variables (e.g.: id, varId, language, translation);
select relevant variables and translations, write them to a file;
include the relevant language file in your site;
create your own function to display a variables text:
text('var'); or maybe something like __('faq','register','lost_password_text');
Point 3 can be as simple as selecting all the relevant variables and translations from the database, putting them in an array and writing the serlialized array to a file.
Advantages:
Maintenance. Maintaining the texts can be a lot easier for big projects. You can group variables by page, sections or other parts within your site, by simply adding a column to your database that defines to which part of the site this variable belongs. That way you can quickly pull up a list of all the variables used in e.g. the FAQ page.
Translating. You can display the variable with all the translations of all the different languages on a single page. This might be useful for people who can translate texts into multiple languages at the same time. And it might be useful to see other translations to get a feel for the context so that the translation is as good as possible. You can also query the database to find out what has been translated and what hasn't. Maybe add timestamps to keep track of possible outdated translations.
Access. This depends on who will be translating. You can wrap the CMS with a simple login to grant access to people from a translation agency if need be, and only allow them to change certain languages or even certain parts of the site. If this isn't an option you can still output the data to a file that can be manually translated and import it later (although this might come with the same problems as mentioned before.). You can add one of the translations that's already there (English or another main language) as context for the translator.
All in all I think you'll find that you'll have a lot more control over the translations this way, especially in the long run. I can't tell you anything about speed or efficiency of this approach compared to the native gettext function. But, depending on the size of the language files, I don't think it'll be a big difference. If you group the variables by page or section, you can alway include only the required parts.
After some testing I finally decided to go more or less with the lines of Alecs' combination of the second and third alternative.
Gettext problem
I tried to set up the whole gettext-system first to try it out, but it turned out to be much more complicated then I thought. The problem is that Windows and Unix systems use different language shortnames for setlocale(). For the moment I'm running my dev-server on Windows with Wamp, while the final site will run on Linux. After I went through a couple of dozen guides, forums, questions etc. and restarting the server after each modification. I couldn't get it setup properly in any easy way it seemed. Additionally gettext is not threadsafe, to update the language file the server needs to be restarted or a hack needs to be used, there is no easy way of handling different versions of language files or handling the original English text without modifying the source or using Mikes suggestion, which as Alec pointed out isn't optimal.
Solution
So I ended up with what I think is the best solution based on Alecs response:
Save all the translations in a DB with the fields; language, page, var_key, version, revision and last_modified_time - where the version is corresponds to versions of the original translation (English), while revision allows the translator to modify/correct the finalized translations within a version.
Use a kind of CMS for translation, which is connected to the DB and handles different versions and allows for an easy overview of which languages are translated, in which version and how complete the translations are.
When a revision of a version is finalized a cache files are generated - each file contains an array with only the var_key and text-translation for one language and one page and are named with the ISO 639-1 names of the languages and the page name like: lang/en_index.php These language files are then simply included and wrapped in a function t($var_key) which allows for using the DB during the development, while then changed to only use the cache files.
Performance
I never got around to test gettext, but according to the link Mike posted the difference in performance between using an array and gettext is totally acceptable for me for the benefits which a custom system gives as described above. However, I compared using an array with 20 translated text-strings in an array compared to retrieving the same 20 text-strings from a MySQL DB. It turned out that using an array included from a file was aeound 6 times faster than retrieving all the 20 strings at the same time from the MySQL DB. It was no really scientific benchmark and the results may surely vary on different systems and setups, but it clearly shows exactly what I expected - that it would be much slower using a DB than using an array directly, which is why I choose to generate cache-files for the array instead of using the DB.
As a comparison I also tested how fast it was to only output simple echos with the same text. It turned out to be around 20 times faster than using arrays from an included file, but well - then it is not possible to translate without having different versions of the page for different languages, which defies the purpose of dynamic pages. Then it is better to also use a good cachesystem.
Performance test source files:
PHP: http://pastie.org/964082
MySQL table: http://pastie.org/964115
It is surely not perfect, but at least creates an idea about the performance differences.
Rather than having to use the English text as the keys you could arbitrarily do this but also provide english translations i.e.
gettext key is 'hello'
You then have your various language translations of this and an english translation of this that is also 'hello', then if you want to update the english version of the string you can leave the key alone and just update the english translation.
Situation is simple. I'm starting to develop a website that should be localized based on visitor's origin IP address.
It's a PHP-MySQL stack. How do I go about the multilingual text content? I am thinking of having a language table in the database with the primary key as content identifier, another column for page identifier and separate columns for content in each language. Appropriate page content will be fetched as an array in the requested language and then displayed on the page.
Is this an efficient solution? I somewhat feel ridiculous to make database calls just for static content. I thought of having PHP definition files for each language and load the definitions during page load. But updating the definitions for each language are going to be like editing the files manually.
Has someone come out with an efficient solution for this kind of situation? Any input is much appreciated.
If the content is static like you say, why not use Gettext?
It's the standard regarding localization of content and has been discussed lots of times in StackOverflow.