PHP tag pre-processor [Language]


Is a traditional Template Engine used to achieve the above? More precisely, the string output e.g. Edwin completed test session Ensure browser compatibility.

Can anyone confirm this? Has anyone been doing something like this in PHP, that has the confidence to share some of their experience. What’s best for performance as well.

Have a look at this.

http://twig.sensiolabs.org/doc/extensions/i18n.html

and this

Whereas the former is what you are looking for in this thread.

However, you’ll also need the latter (or something similar to it within your model/ database abstraction layer, if you intend to have multi-lingual content on your site/ in your application too.

Scott

1 Like

Whereas the former is what you are looking for in this thread.

Where?

However, you’ll also need the latter (or something similar to it within
your model/ database abstraction layer, if you intend to have
multi-lingual content on your site/ in your application too.

Please explain!

I found this, http://stackoverflow.com/questions/7683133/does-php-have-a-feature-like-pythons-template-strings

So I guess, I must build a separate String Template Engine in PHP that takes care of this part.

What you seem to be asking for is what is called phrasing in translation work in programming. You want to build phrases with different languages. That is what the i18n extension for Twig is for.

If you are looking to have a proper multilingual site, then the content would need to be translated too. To do that, you must have entities that are also translatable. That is what the translatable extension for Doctrine offers.

In other words, the i18n extension is for translating programmatic phrases in an application. The translatable extension is for translating content.

Scott

1 Like

Is this really done on Social Networks too?

And yes, we’ve been doing something like this with symfony, which does utilise twig.

So you have a lot of separate files with your String definitions?
I thought, I would store each line in a TXT file, read it into array, and then somehow, grab a line and replace the tags in it.

Maybe this could help out, now you might see what I have in my mind, still curious on how this is done.

As Scott mentioned earlier, if you want this to be multilingual then Gettext is one of your best bet.

It can be used with Twig as mentioned earlier (uses php gettext functions), or directly by using the gettext functionality in php though, please note that the php version of gettext is missing some functionality and it caches the mo file (so if you update it, restart php).

The content/phrases are then translated into Gettext .po files, and you can pass those along to the translators for easy translation of the content. Or on larger projects consider using Transifex (Note. you convert the .po files to binary files .mo before uploading it to the website)

If using Twig is appropriate in your case depends on the content that need to be translated. If it is just smaller strings, I would store it in a database, and then create the .po file yourself by parsing the table. With a proper design, the column would contain any plural info that need to be passed, together with the message as well as the fields that is needed to be replaced.

When processing, you just use str_replace and you are good.

1 Like

@TheRedDevil, I have a different way of doing multiple translations. What my main issue is, is to know if there’s a better way to STORE Text Strings, e.g. this link: http://stackoverflow.com/questions/7683133/does-php-have-a-feature-like-pythons-template-strings

Template Strings.

Now, is this normally done with one folder (DIR), and plenty of single standalone files with different strings, and depending on what you might need, grab the contents of one file, process and replace the {tags} with values.

Or, is it better to define all of them inside one single file array[]?

greetings.tpl.txt

['welcome'] = 'Welcome {firstname} {lastname}'.
['good_morning'] = 'Good morning {firstname}'.
['good_afternoon'] = 'Good afternoon {firstname}'

EDIT: Here’s another example, https://github.com/oren/string-template-example/blob/master/template.txt

If it was me I’d lean towards using gettext because that’s what I’m most recently familiar with using and because

xgettext extracts all marked messages from a set of C files and initializes a PO file with empty translations

which can then be translated

#: wp-db-backup.php:239
msgid "Progress:"
msgstr "Stato:"

#: wp-db-backup.php:248
msgid "Navigating away from this page will cause your backup to fail."
msgstr "Abbandonare questa pagina farà fallire la procedura di backup."

#: wp-db-backup.php:295
#: wp-db-backup.php:1098
#, php-format
msgid "Your backup has been emailed to %s"
msgstr "Il backup è stato inviato per email a %s"

#: wp-db-backup.php:362
msgid "Creating backup file..."
msgstr "Creazione del file di backup..."

Discourse uses transiflex that works with YML files

    no_value: "No"
    yes_value: "Sí"
    generic_error: "Lo sentimos, ha ocurrido un error."
    generic_error_with_reason: "Ha ocurrido un error: %{error}"
    sign_up: "Registrarse"
    log_in: "Iniciar sesión"
    age: "Edad"
    joined: "Registrado"

phpBB2 uses PHP files with language arrays

$lang['Click_return_topic'] = 'Click %sHere%s to return to the topic'; // %s's here are for uris, do not remove!
$lang['Click_return_login'] = 'Click %sHere%s to try again';
$lang['Click_return_forum'] = 'Click %sHere%s to return to the forum';
$lang['Click_view_message'] = 'Click %sHere%s to view your message';
$lang['Click_return_modcp'] = 'Click %sHere%s to return to the Moderator Control Panel';
$lang['Click_return_group'] = 'Click %sHere%s to return to group information';

$lang['Admin_panel'] = 'Go to Administration Panel';

In my experience using arrays does work, but I prefer the way gettext generates the empty translation file, it shows what files the text is used in, and I like being able to easily see the actual text instead of needing to remember what text goes with the “key”

Symfony has a translation component that might save you some work or at least give you some more ideas on organizing things. In particular it supports placeholders for things like name. The code boils down to:

$translated = $translator->trans(
  'Hello %name%',
  array('%name%' => $name)
);

Lots of different ways to configure the translation component. The above example, in yaml, would look like:

'Hello %name%': Bonjour %name%

More info at: http://symfony.com/doc/current/components/translation/usage.html

On the question of one file or multiple files, I’d say it depends on the size of the application. If you have to constantly load in tons of translations, which you don’t need for most of your application’s pages, then that might cause unnecessary overhead. If it is a small application, one file might do. If your application is going to have to scale well, you might even think about database storage of phrases and caching them.

Scott

There are many ways to do site translation depending on your requirements. Let me share a method I used once that was not mentioned here. My requirement was one translation file (for easy editing in one place - but you could use any other storage format like a database) and best performance (I didn’t want translation logic to performed on each page request). I used both the translation file and a template engine (Smarty, but I believe the same could be done with other template engines). The template engine was normally used on the whole site for html rendering.

My translation file looked like this:

$trans_table = array(
    "DE PAGE_NOT_FOUND" => "Nicht gefunden",
    "EN PAGE_NOT_FOUND" => "Page Not Found",
    "DE DEFAULT_PAGE_TITLE" => "Kleine Schule",
    "EN DEFAULT_PAGE_TITLE" => "Small School",
    ...
);

Eventually it got as big as 70 KB but this wasn’t problematic at all - you could use a database if it got really huge, no problem.

In templates this was used like this:

<title>## DEFAULT_PAGE_TITLE ##</title>

or for items with parameters (much more rare) that had %s placeholders replaced with sprintf, I used my custom function:

<title>{translate('DEFAULT_PAGE_TITLE', $param1, $param2)}</title>

Naturally, the parametrized translations had to be parsed on every page request. However, I managed to get rid of all translation overhead for unparametrized translations with a trick in Smarty. Smarty compiles templates to PHP code and allows for multiple compiled versions of the same template based on a supplied compile_id. Therefore, I used the language token as the compile_id so that every template compiled to two PHP files (because I had two languages). And then I used another feature of Smarty - pre-filters. With the pre-filters I replaced all unparametrized translation placeholders with the actual translated texts before compilation so that

<title>## DEFAULT_PAGE_TITLE ##</title>

became

<title>Small School</title>

for the English compiled template, and

<title>Kleine Schule</title>

for the German compiled template.

Then it was only a matter of telling Smarty which compile_id to use on page display.

Thanks to this set-up static translations had zero performance impact on the site because the translating logic was only performed once the template was compiled (changed) and then was cached - so the translation table didn’t even have to be loaded on subsequent requests. I had very few parametrized translations so I didn’t bother creating a specific template expansions for them before the compilation stage (I simply used the translate($placeholder, $params) function in the templates). But for improving their performance I might compile them to something like this:

<title>{sprintf("Small School Number %s", $schoolNumber)}</title>

for English compiled templates, etc.

This may not be a method that is most elegant, because it needs to make use of features that not every template engine supports - otherwise we would need to write our own template compiling solution - at least just for expanding the language placeholders to actual text into separate files. However, I don’t think there are many/any other solutions that would equal or beat this in terms of performance :smiley:

I’ve changed my position.

I’ve been busy messing with UTF-8 metaphone() iconv() mb_string_convert() and other functions trying to bang together a script that works with strings.

I made some progress, but no matter what I managed to come up with, if it worked at all, some compromise was always present to balance between false positives and false negatives, i.e. nothing was ideal.

Then I took a look at PHP’s Intl functions
http://php.net/manual/en/book.intl.php
I needed to uncomment “intl.dll” in the ini and unzip the correct ICU

into the “extras” folder, but WOW!
I am super impressed. For example, a small sample of the 294 possible transliterations for the string “California”

Latin-Hangul
string(15) "차리폴니아"
Latin-Hebrew
string(20) "קַלִפֳרנִַ"
Latin-Hiragana
string(21) "かりふぉるにあ"
Latin-Jamo
string(33) "차리폴니아"
Latin-Kannada
string(30) "ಚಲಿೞೊರ್ನಿಅ"
Latin-Katakana
string(21) "カリフォルニア"
Latin-Malayalam
string(30) "ചലിഫൊര്നിഅ"
Latin-NumericPinyin
string(10) "California"
Latin-Oriya
string(33) "ଚଲିଫ଼ୋର୍ନିଅ"
Latin-Syriac
string(18) "Cܲܠ݂fܿܪܢ݂ܲ"
Latin-Tamil
string(30) "சலிபொர்நிஅ"
Latin-Telugu
string(30) "చలిఫొర్నిఅ"
Latin-Thaana
string(21) "Cަލިފޮރްނިަ"
Latin-Thai
string(30) "จะลิโฟรนิะ"

Not that every server will have Intl enabled / ICU installed, but if it is it’s definately worth looking into.

@TheRedDevil, @s_molinari, @Jeff_Mott, @Gandalf, @ahundiak, @Lemon_Juice, @mawburn Please see my latest question, I think, you might understand what I was out for, but failed explaining: Storing, maintaining, and using String Templates with PHP

I still fail to see how your new question is different from this one. You don’t want third-party template engines - fine, you don’t have to. For example, my implementation used a template engine but it’s not required, the same solution can be rolled on one’s own. But for the most part you will be reimplementing what existing template engines already do.

You’ve been given plenty of advice here but don’t expect that you will be presented with a single best solution to your problem. Programming is an art and science and requires THINKING - there are many ways to achieve the same result. Take whatever pieces you’ve been given, add your own, start thinking and programming.

Looks to me like you haven’t read it.

I’ve changed it back.

I was confusing transliteration with translation.

Similar, but not quite the same thing.

Still a very useful tool to have in the toolbox, but not applicable here.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.