I'm writing Content Management software in PHP (which should not be bigger then 3kb when minified), but what engine should I use for languages (english, dutch, german, chinese, etc...)? I was thinking of creating a function called
function _(){}
that reads strings from a file (a .ini file or similar). But does somebody has an (preferably one with as less code as possible) engine that might be smaller or faster?
I'm not sure if these engines exist already, if not, please say and I will use the _() function.
If I were you I would make my translation function like such (which I believe is very similar to gettext): make it into an sprintf()-like function and translate based on the format string, like so:
function __() {
$a = func_get_args();
$a[0] = lookup_translation($a[0]);
return call_user_func_array("sprintf", $a);
}
Now, you can use the function simply like this:
echo __("Thanks for logging in, %s!", $username);
And in a data file somewhere you have:
"Thanks for logging in, %s!"="Merci pour enlogger, %s!" (*)
The advantages of this are:
You don't have to think up identifiers for every single message: __("login_message", $username), __("logout_message", $username), etc...
You don't immediately have to write a translation for the string, which you would have to if you just used an identifier. You can defer the translation until later, once you're done coding and everything works in English.
(Similarly) You don't have to translate all strings for all languages at once, but you can do it in chunks
For maximum convenience, I would make the __ function log untranslated messages somewhere, so you don't have to go hunting for untranslated strings. Let the system tell you what needs to be translated!
(*) Disclaimer: I don't speak French ;)
You can't use _() because this is a build-in function for internationalization. You are free to roll your own function (call it __()) or use the build-in one which uses the widespread gettext system.
Drupal, for example, uses function t() for this purposes.
Related
I have language files with translations of content in a website.
Each different language will load a different file.
Now I would like to have something like this, that I need to echo on the page and include in a email sent on form submit:
$lang["booking_mail_header"]='Dear '.$first_name.', thank you for your contact!';
The problems here is that $lang[] is loaded before $first_name is defined and $first_name is user inputed content, thus unsafe.
I thought about using eval() and then thought again and didn't. Is there another way?
The variable in this point of the script has already passed this regex check:
preg_match('/^[a-öA-Ö0-9-. ]*$/', $first_name)
You could just make it a template, e.g.
$lang["booking_mail_header"]='Dear %s, thank you for your contact!';
then use that with sprintf
$msg=sprintf($lang["booking_mail_header"], $first_name);
You could also get cleverer, and use numbered arguments, which would allow your templates to reorder the inputs to sprintf, e.g.
$lang["format_name"]='%2$s, %1$s';
$msg=sprintf($lang["format_name"], $first_name, $last_name);
Once you've understood that, consider using gettext, which uses the same basic idea, but wraps it up in some standard tools, which can aid keeping your translations maintained. Using that, you wouldn't keep you translations in an array, you'd just wrap your natural language in a _() wrapper, e.g.
$msg=sprintf(_('Dear %1$s, thank you for your contact!'), $first_name);
gettext tools can extract the natural language wrapped by the _() function into a separate file for translation. A translator would use a standard tool like poedit to produce these translations. At runtime, you select an appropriate translated version of this file, and _() will return that translation.
I'm writing a wordpress plugin and planning it's drupal implementation i'm wrapping wordpress functions into adapters. So i wrote an adapter for the __() which is simply
class Ai1ec_Wordpress_Template_Adapter implements Ai1ec_Template_Adapter {
...
public function translate( $text ) {
return __( $text, AI1EC_PLUGIN_NAME );
}
I'm not a big expert of gettext and a collegue wrote me:
will fail when the code is parsed by xgettext to generate the .pot
file. WP i18n functions such as __() require that a string literal is
passed as the first argument, never a variable. And IIRC, the same
holds true for Drupal's t() function.
I've read the codex entries
http://codex.wordpress.org/I18n_for_WordPress_Developers#Placeholders
http://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/t/7
And couldn't find out something exactly related to this. Can soemone explain me exactly why this wouldn't work and how could i write something which could be compatible with Wordpress and Drupal?
In general your colleague is correct, if you pass variables to translation functions they will not get translated unless the same string is passed in as a literal elsewhere. This is because generating the translation template does not run the code, it searches over it for particular function names. The translation methods have 2 purposes, one is to translate the parameter, the second is to identify to the translation template generation program which strings should be included in the translation template file.
You need to tell the translation template generation code (usually the xgettext) program that the parameters to your function are translatable strings. With xgettext this can be done with the -k parameter. WordPress may already have its own wrapper to xgettext that you can use.
The drupal document you linked explicitly says you should not pass variables to t() unless you are sure that the text is passed as a literal elsewhere.
Both the Wordpress and Drupal versions should take strings held in variables.
The Drupal version is somewhat confusingly worded. What the Drupal docs are saying is that you should be careful if the source of the original text is user generated.
$foo = 'bar';
($foo == 'bar') == true;
I am building a multilingual application in PHP + CodeIgniter. I have settled upon using gettext for UI text translation, and so far it has proven efficient and easy to work with.
But now I am facing something really annoying: the gettext() function only accepts one parametre, while I'd like a printf-like behaviour that I get from Zend Framework's gettext adapter, where I can use %1$s, %2$s etc. as placeholders and then specify the replacement strings as additional parametres to Zend view's translate() function.
I do not wish to ditch gettext due to the easy translation management with .po files and poEdit (I can get it updated with a single click, after all). What are my options?
I have already tried writing a helper to interact with gettext: run the first argument through gettext and then run strtr on the resulting string. Are there any other/better approaches you would recommend?
It's quite simple actually, you define a variadic function like this:
function myGettext($id)
{
return vsprintf(gettext($id), array_slice(func_get_args(), 1));
}
Now doing myGettext('%u %s in a %s', 3, 'monkeys', 'tree') will return the expected string with the placeholders replaced by the remaining arguments. You obviously also need to implement a plural aware function that calls ngettext() instead.
Regarding poEdit, you have to modify the keywords it searches for, it's been a while since I last used it but it was quite simple, the only problem I faced was identifying keywords for plural support (see this).
Hope it helps!
Reading about Kohana templates and saw something I've never seen before:
$this->template->title = __('Welcome To Acme Widgets');
What does __('Text') mean? What is it? What does it do?
In Kohana (version 3) the function is defined in system/base.php and is a convenience function to aid (as the other answers have mentioned) internationalization. You provide a string (with, optionally, some placeholders to substitute values into the finished text) which is then interpreted and, if required, a translation is returned.
Contrary to assumptions in other answers, this does not use gettext.
A very basic example would be (this particular string is already translated into English, Spanish and French in Kohana):
// 1. In your bootstrap.php somewhere below the Kohana::init line
I18n::lang('fr');
// 2. In a view
echo __("Hello, world!"); // Bonjour, monde!
The double '__' is used for Localization in CakePHP (and possible other frameworks)
http://book.cakephp.org/view/163/Localization-in-CakePHP
It means someone created a function named __ (That's two underscores next to one another.)
My guess is it defined somewhere in the Kohana documentation.
It's string gettext ( string $message ): http://php.net/manual/en/function.gettext.php
Returns a translated string if one is
found in the translation table, or the
submitted message if not found.
The __() is just an alias for it. So __("some text") is equivalent to gettext("some text")
edit: Actually if it's two underscores than it isn't gettext(). The alias for gettext() is one underscore.
Second edit: It looks like __() might be another alias for gettext(). With a slightly different meaning from _(). See here: http://groups.google.com/group/cake-php/browse_thread/thread/9f501e31a4d4130d?pli=1
Third and final edit: Here's an article explaining it in more detail. Looks like it isn't a built in function, but rather something that is commonly added in a lot of frameworks. It is essentially an alias of gettext - it performs the same function. However, it isn't a direct alias (I don't think). It is implemented in and is specific to the framework. It searches for and returns a localization or translation of the string it is given. For more, see this blog post: http://www.eatmybusiness.com/food/2007/04/13/what-on-earth-does-a-double-underscore-then-parenthesis-mean-in-php-__/7/
// Display a translated message
echo __('Hello, world');
// With parameter replacement
echo __('Hello, :user', array(':user' => $username));
See http://kohanaframework.org/3.2/guide/api/I18n for details.
I would like to know if I can use a gt function on a variable with php?
eg. : echo _($var);
Feel free to. But you need to make sure the possible contents of the variable makes it into .po/.mo files. (one of the ways to do assure it is to create a dummy file never processed except for by xgettext, containing _("translate me"); expressions).
I don't think gettext will recognize a variable since it scans the source code. If you want to include variables in a string, it's better to use
sprintf()
For example
echo sprintf(_("There are %d results!"), $numResults);
In gettext, the translator will see
There are %d results!
so therefore it can easily be translated as long as he/she knows that %d is a variable. When the script gets executed, gettext will first replace the translation, and then sprintf will insert the variable $numResults. Good luck! I just got done internationalizing my site.