Creating a bilingual site - php

I have been working on a site from last 2 years.
Now my client want's make it bilingual, with English and Chinese.
Any idea what should I do for it?

You can have seperate constant files, each file has a bunch of constants in it, then you go through the pages replacing actual sentences with the constants.
Have a cookie that selects the correct constants file that the user has chosen.
This sort of design is good as it allows for more language to be added easily in the future.
It is however a pain in the ass to do.
You could go for some sort of automated translator but it wont read naturally.

I had to do this and since you are working with PHP, I recommend gettext
http://php.net/manual/en/book.gettext.php
And here's an article to get you started on it
http://mel.melaxis.com/devblog/2005/08/06/localizing-php-web-sites-using-gettext/
The benefit of gettext is that the translator never has to touch the code. Rather, the translator works by translating .po files with Poedit ( http://www.poedit.net/ ). You place those .po files in your locale directories from which php-gettext accesses and uses it to replace the strings. Have fun and good luck, I got it to work pretty well

Decent introduction article on the subject:
http://onlamp.com/pub/a/php/2002/11/28/php_i18n.html
We could really do with more info.

Related

Gettext blog posts different languages

I've been looking already over a month for a universal solution and hadn't come up with any.
I need to have my website international everywhere, not just UI. I also need to have my blog posts multilingual, but they are dynamic (created via CMS).
There are two problems:
I can use GNU Gettext for UI's localization but barely can imagine to use it for blog posts (except using some scary things, like parsing and editing .po files through PHP, then compiling it to .mo with unreliable scripts, then using some tricks to avoid Gettext cache...). So I've come up with an idea to make some database-based localization for dynamic content.
But it means that I need to use two different localization systems: GNU Gettext and database-based. It's ridiculous. So I need to make all localization database-based.
Am I right? Are there smarter solutions? Would appreciate a lot any advice.
Do it the other way round.
Extract the translatable strings from your database into a .pot file, for example 'database.pot'. When you extract the messages from your php sources, do it (more or less) like this:
xgettext *.php database.pot
You can always use .po or .pot files as input to xgettext.
Then, use your regular translation workflow, and once you have to translated .po files, parse the translations out of the files, and write them back into the database.

Make a translation for PO files

We are working on web application in PHP and use gettext to handle strings for translation. Here is my question what we are struggling right now.
If we use kind of words/id for a string for example "menu-feature" and we would like to display it in English as "Our main Features" we can do it of course and for example first English translation will be made by a person with access to application. So than we will have "EN" po file ready.
But if we would like to send it to other translator for example Norwegian so this person will see again only our "IDs". How he/she can find what we had in mind exactly with that ID ??
Do we have bad way of thinking about using PO files? Is a some good way to make it correctly?
Common practice is to use the whole actual string in the default language as the msgid, for exactly the reason you've lined out: translators would have a much harder time figuring out the meaning behind each of your placeholders.
That said, you can add comments to each of the ids as a hint for translators. I think those lines start with a # in the .po file. They should also show up in Poedit, Virtaal or whatever they're using.
I haven't used poedit in a while, but why don't you just copy the English file, call it Norwegian, import it in poedit and start editing?

Extract translation phrases from Magento

I'm relatively new to Magento and working on a site build for a client and they simply need a list of phrases used throughout the site to be sent to a translator. I'm a little surprised that there isn't something simple and built into Magento for easily pulling this stuff out, which is why I'm writing here now. Is there a relatively simple way to extract translation phrases from a Magento app? Something built in that might not be obvious (to me)? or some useful library out there? This includes everything used in the templates (or controllers) like so:
$this->__("Some phrase on my website...");
... as well as cases in the layout XML where the 'translate' attribute is set, etc.
And taking this one step further, I'm aware of the available translations available from Magento here: http://www.magentocommerce.com/translations -- is there something simple to make sure I'm not double-doing it for phrases that might already exist in these packs?
And further still, is there a something to pull all translatables out of the database?
And if the answer for all this turns out to be 'no', I need to be very thorough with this so any advice on pitfalls or particular spots I need to be aware of where I might not think of pulling translations from, how you might have achieved something like this before, etc. -- I would love to hear your tips. Thanks!
I know I'm late, but anyway, I’ve just uploaded an extension that does that: Language CSV Files Generator.
It only extracts strings from .php and .phtml files, I have no idea of how to get the .xml ones. Hope that someone out there could share some idea.
hope you like it
Take a look in /app/locale/(language_country)/*.csv files.
There are different solutions to get the strings from CSV files of Magento:
check the links The Ultimate Guide to Translating Magento (using Translation Memory software)
and How to translate Magento using OmegaT software

PHP Localization Best Practices? gettext?

We are in the process of making our website international, allowing multiple languages.
I've looked into php's "gettext" however, if I understand it right, I see a big flaw:
If my webpage has let's say "Hello World" as a static text. I can put the string as <?php echo gettext("Hello World"); ?>, generate the po/mo files using a tool. Then I would give the file to a translator to work on.
A few days later we want to change the text in English to say "Hello Small World"?
Do I change the value in gettext? Do I create an english PO file and change it there?
If you change the gettext it will consider it as a new string and you'll instantly loose the current translation ...
It seems to me that gradually, the content of the php file will have old text everywhere.
Or people translating might have to be told "when you see Hello World, instead, translate Hello Small World".
I don't know I'm getting confused.
In other programming languages, I've seen that they use keywords such as web.home.featured.HelloWorld.
What is the best way to handle translations in PHP?
Thanks
You basically asked and answered your own question, the answer might just be having a slightly better understanding of how PO files work.
Within the PO file you have a msgid and a msgstr. The msgid is the value which is replaced with the msgstr within the PHP file depending on the localization.
Now you can make those msgid's anything you would like, you could very well make it:
<?php echo _("web.home.featured.HelloWorld"); ?>
And then you would never touch this string again within the source, you only edit the string through the PO files.
So basically the answer to your question is you make the gettext values identifiers for what the string should say, however the translators typically use the default language files text as the basis for conversion, not the identifier itself.
I hope this is clear.
I know an answer has been accepted, and the above answer is good. But there is another issue with using permanent machine-style keys like thing.stuff.widget when working with Gettext.
While using permanent keys is a better approach to development, Gettext is not set up for that style of working and this can complicate your workflow.
If you present a translator with a PO file populated with keys in place of source text, they may not know what the English should be. So you'd have to provide them with a second file containing source language translations for them to compare to. Not the end of the world, but more fiddly for them and not how Gettext was designed. (square peg, round hole etc..)
I think PO is perfectly fine as a file format for translations in PHP, and especially recommended if you're not working with a framework that has a good l10n module, but that doesn't mean it's good for workflow and your translation process.
I suggest you arrive at a workflow that allows your programmers to work with permanent keys, your translators work with words, and gives you a MO file out the other end. Take a look at Loco for one solution to this.
Alternatively use a different interim file format that allows the use of keys and words. TMX is one example. If you still want to use Gettext at runtime you can convert the files.
Currently, I am dealing with the same issue. The common practice with gettext is to use the English text as the key. Recently, our copy editor changed whole bunch of English text (other languages are hardly touched) so we have to change all the source code all the PO files.
We are switching to a neutral key. Since we already have some sites on Java. We will use the same property name format.

Most efficient approach for multilingual PHP website

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.

Categories