Tuesday, March 18, 2008

First Piins OS release: Smarty & I18N

Yipiiieh, here we go. Our first public Piins open source release (MIT license). We've decided to release Smarty plugins that make life with Smarty and i18n easy (well, at least as easy as I18N can be per se).

Wolfram Schlich posted a nice overview of best practices to internationalize Smarty templates. His overview can be read in this mailinglist archive.

Unfortunately none of the provided best practices seemed to be compliant to the standard GNU i18n library gettext, as employed in many applications. Hence we thought about implementing our own, which turned out to be both - incredibly easy and very handy.

We would like to share this library with you including a little tutorial how to use it. The files for the i18n & smarty tutorial can be downloaded as well.

We've also hosted it on Google code as the Google code piins-smarty project.

Help us making the library better by posting the bugs you found :) ah and by the way, there are many more libraries to come, such as:
  • php-DAL: data access layer for PHP and MySQL, built on PDO. Allows stored procedure call with easy access
  • php-DAL-generator: auto generate the DAL (data access layer) for your MySQL database (including stored procedures).
  • php-MVC: a very lightweight MVC framework for PHP with complete i18n/L10n support
  • .NET enterprise libraries compiled for Mono on Unix systems
  • and much much more...
Enjoy & stay tuned!

Labels: , ,

35 Comments:

Anonymous Anonymous said...

Hi,

I have installed this packade but when i point my webbrowser to it i get errors, adn can´t change lang.
Link to my install http://copy112.modulargaming.com/i18n2

April 14, 2008 at 9:56 PM  
Blogger Karlheinz Toni said...

is this just the extracted page, or did you modify anything?

April 14, 2008 at 10:49 PM  
Anonymous Anonymous said...

I haven´t modified it, just uploded it to my webserver.

April 15, 2008 at 10:32 AM  
Blogger Karlheinz Toni said...

hi,

it looks like the file your smarty.cnf is not readable. could you make sure, it has got the appropriate rights...

unable to read resource: "/home/copy112/public_html///library/piins.smarty/smarty.cnf"

also, can you make sure, that this is the right path it should be in?

otherwise we might have a bug in the resolution of the document-root.

thanks and all the bests,
charly

April 15, 2008 at 2:24 PM  
Anonymous Anonymous said...

I Can remove the error by copy the smarty.cnf to template/config but i still can´t change lang and i get include erors. i Have also tried to skip the path checker and inoput the dockument root myself but no reslut.

April 15, 2008 at 2:59 PM  
Blogger Karlheinz Toni said...

hi,

the original error went away, because you moved the file to another directory.

you have to change the include paths as well if you move.

the easiest way to do it, I presume is restore the original state and for the sake of argument make everything accessible, i.e.

change in the console to

cd /home/copy112/public_html

and type

sudo chmod -R 777 .

which changes your files to readable/editable/executable by everyone.

does it work then?

cheers,
charly

April 15, 2008 at 9:15 PM  
Anonymous Anonymous said...

It still don´t work. Are there any server requirement to be met like globalregister on etc?

April 15, 2008 at 9:43 PM  
Blogger Karlheinz Toni said...

now the error:

/home/copy112/public_html///library/piins.smarty/smarty.cnf

is back.

does this file exist and what is the access configuration of that file?

try:

vi /home/copy112/public_html///library/piins.smarty/smarty.cnf

does it open the file?

cheers,
charly

April 15, 2008 at 10:11 PM  
Blogger Bojacob said...

Hello,

I downloaded your example page directory, but it doesn't seem to be working. When I click on "German," nothing is translated and the includes between <@ @> turn into this:

{*x* include file=i18nPlural.tpl *x*}

This only happens for includes and not the other <@ @>

I'm compiled the .po file, but it's still not working.

I'm running Ubuntu 7.10
PHP Version 5.2.3

gettext in phpinfo() shows as enabled.

April 29, 2008 at 7:45 PM  
Blogger Karlheinz Toni said...

Hi Bojacob,

do you have an URL that you can access it from the outside?

This problem occurs if the smarty.cnf file could not be included properly in the /library/piins.smarty directory.

Open the index.php file and add the following two lines in line 25 of index.php

echo FileUtils::resolveDocumentRoot().dirname($_SERVER['REQUEST_URI'])."/library/piins.smarty/smarty.cnf";
exit();

Access the site again and see if the file path to the smarty.cnf file is right.

If not, delete those two lines again and put the path to the smarty.cnf directly in line 25, like this:

$smarty->config_load("/my/absolute/path/to/library/piins.smarty/smarty.cnf");

Hope this helps...

Bests,
Charly

April 30, 2008 at 7:40 PM  
Anonymous Anonymous said...

Your tutorial page seems broken

http://blog.piins.com/api/smarty_i18n/index.php

gives

/piins/blog//api/smarty_i18n/library/piins.smarty/smarty.cnf

May 2, 2008 at 10:40 AM  
Blogger Karlheinz Toni said...

:D from our last with the tutorial for the last comment/question. working again

May 2, 2008 at 10:47 AM  
Blogger Bojacob said...

Hello Toni,

The path to the cnf file is correct. When I try to point it to an invalid cnf, the { *x* are gone for the includes, but there is still no translation at all.

I've tried it both on my machine and on my webhost:

http://www.bojacob.net/stuff/index.php

Still no luck :(

May 2, 2008 at 5:45 PM  
Blogger Karlheinz Toni said...

Hi bojacob,

the problem was due to a bug in prefilter.smartyTags.php

It is now removed and the newest version is available via: http://blog.piins.com/api/smarty_i18n/i18n.tar.gz

Bests,
Charly

May 2, 2008 at 6:25 PM  
Blogger Bojacob said...

Still not there yet. The {*x* are gone from my local website, but they're still present in my blog webhost (Dreamhost)

There's no translation on both hosts. I've edited the CNF file over and over with no luck. I'm sure I have the locale file present in both my system and website. I compiled them again just to be sure.

Also, you have a google-analytics script in your templates :p

I caught your Meebo meessage. I'm on Meebo in my blog if you want to chat.

May 3, 2008 at 12:25 PM  
Anonymous Anonymous said...

Hi,

I have uploaded everything in my hosted webserver (gettext enabled) at the root level:

http://www.fishcatch.org/index.php

I don't get any error but when I click "German" everything remains the same, the index.php?l=de_DE page still displays English.

Any suggestion?

Thank you in advance.

July 5, 2008 at 8:22 PM  
Blogger Karlheinz Toni said...

Hi Mario,

did you have a look at:

http://www.fishcatch.org/library/piins.smarty/smarty.cnf

?

and see if the paths are right?

Bests,
Charly

July 6, 2008 at 3:53 PM  
Anonymous Anonymous said...

Hi Charly,

thank you for the quick reply.

Oops... Changed from
localesDir = "i18n/locales"
to
localesDir = "/locales"
and everything is working fine.

Now I'll start to embed it deeper in my project; I'll keep you posted, hopefully with some more clever comment :-)

Best,

Mario

July 7, 2008 at 1:28 PM  
Blogger Karlheinz Toni said...

Hi Mario,

thanks a lot for that :) happy to help any time.

If you have got any questions/feature suggestions, etc. just let us know. We're very keen to develop the library further.

If you want we can put you on our showcase page as well...?

Bests,
Charly

July 7, 2008 at 1:41 PM  
Anonymous Anonymous said...

Hi Charly,

i'll be happy to be showcased and also to give credit to your solution, but ETA for my public release is September to be optimistic.

In the meanwhile, I am still on the questions side! Too early for suggestions...

Question: I expected Poedit, the .PO file editor, to be able to scan, with the "Update from sources" command, a .TPL file (in a given directory) containing for example:

<@ _("Choose language") @>

But I haven't succeeded in doing so, the result so far has been always 0 (new or obsolete) original strings.

Went through the gettext and poedit documentation but didn't see an answer.

Any hint?

Best,

Mario

July 7, 2008 at 7:52 PM  
Blogger Karlheinz Toni said...

maybe you've referenced the existing PO file?

That already includes a "Choose language" string...

Can you change it to something else, and try again?

Bests,
Charly

July 7, 2008 at 8:45 PM  
Anonymous Anonymous said...

Let me give you the full picture, hoping this will help some future Smarty & I18N newbie, as I am.

After setting up the whole tutorial in the root folder, I managed to have it working with my preexisting Smarty library and my templates/locales/resources folders.

Next goal: creating a new mario.PO in addition to piinsI18n.PO and using it with new .TPL files to experiment a bit.

To do so from PoEdit created a "New Catalog", in its Settings|Paths added the path to my .TPL files. That's where the "Update from sources" command doesn't work. Even with strings other than "Choose language", already checked.

Studying further, I wonder if I should start a "New Catalog from POT file" (template). But how to create a .POT file? I found this interesting tutorial at http://blog.northclick.de/archives/20. But, as you can see from the last post, it is not working with .TPL files (but working with .PHP ones).

So, I guess the broader question is: what's the process you would recommend to create (and maintain) your own .PO files?

Best,

Mario

July 7, 2008 at 11:42 PM  
Blogger Karlheinz Toni said...

Hi Mario,

thanks for the clear picture.

I'd use the xgettext utility as described in http://blog.piins.com/api/smarty_i18n/help.php?l=en_GB

xgettext -C -c --keyword=_ --default-domain piinsI18n ./templates/*.tpl

Which system are you using, then I can advise on how to install xgettext on that one.

Bests,
Charly

July 8, 2008 at 12:17 AM  
Anonymous Anonymous said...

Hi Charly,

after some tests, I feel more confortamble expliciting where the output .POT file should be created and its name, so the command becomes something like:

xgettext -C -c --from-code=utf-8 --keyword=_ --default-domain=mario --output=/path/to/locales/mario.pot ./templates/*.tpl

Anyway this bit is now working, thanks a lot, and I am moving deeper. One issue for sure I will be facing is multiple textDomains, since I would like at least one for the backend and one for the frontend.

On the client side I am using both Ubuntu Hardy and Windows XP. Webserver as of now is Linux hosted, little control over there.

Best,

Mario

July 9, 2008 at 8:08 PM  
Anonymous Anonymous said...

Hi Charly,

here I am again.

I have an issue with UTF-8 characters and I would greatly appreciate your opinion.

Everything works fine if I place the gettext() or _() function, containing the string to be translated, in the .tpl file, as per your tutorial.

But if the same function (same string) is placed in a .php file, the result assigned to a Smarty variable, then displayed in the same above .tpl file (therefore same Doctype etc.), the UTF-8 coding is lost (for example "this is" translated into Italian "questo è" is shown as "questo ?"). As you can see standard Western style characters are ok (for example "confirm" translated into Italian "conferma").

Consider that I have just one .POT (and one .PO) file showing the original string and its translation at 2 different locations (the .tpl file and .php file), can't see any error in that.

Best,

Mario

July 30, 2008 at 10:24 PM  
Blogger Karlheinz Toni said...

Hi Mario,

sounds awesome :) Thanks for the update on that.

As for the i18n in the php files: did you bind your textdomain to the codeset, e.g.

$domain = 'your_text_domain';
bindtextdomain($domain,'./translations_path');
textdomain($domain);
bind_textdomain_codeset($domain,'UTF-8');

You might want to check out this URL, too:
http://uk3.php.net/bind_textdomain_codeset

for the Smarty templates, we've programmed an automatic inclusion of these lines in the templates (via the smarty i18n modules).

Hope this helps.

Bests,
Charly

July 31, 2008 at 11:03 AM  
Anonymous Anonymous said...

Hi Charly,

you are 100% right, thanks a lot, now is working.

I was missing the

bind_textdomain_codeset($domain,'UTF-8');

line.

[ For anyone wondering why I needed the i18n in the PHP files: I am using PEAR QuickForm package and its ArraySmarty renderer, the form data and error messages seem to be easier set on the PHP side. ]

Best,

Mario

July 31, 2008 at 10:20 PM  
Blogger Karlheinz Toni said...

nice :)

btw: have you seen our contact import and message sending API - http://api.piins.com

we license it for free to start-ups. If you're interested, just drop me a mail here http://piins.net/contact/core/contact/1 and I'll set you up.

Bests,
Charly

August 1, 2008 at 12:10 AM  
Anonymous Anonymous said...

Hi Charly,

thank you for the offer, I sent you an email about that.

Inelegantly but quickly solved the multiple textDomains issue, I am facing another problem...

As you pointed out in yr comments in the smarty.cnf file, default smarty delimiters { _("translate me") } have problems with css/javascript compliance and you suggested to adopt custom tags for i18n such as <@ _("translate me") @>.

Nevertheless so far I stayed with the default, because I am heavily using PEAR QuickForm package and its ArraySmarty renderer and didn't feel the need to mess with it.

But I am hitting a wall with my (little) javascript, where

function _( str ) {
return str;
}
var example = { _("translate me") };

"obviously" doesn't work.

Questions:
1) would

var example = <@ _("translate me") @>;

work?

2) any possible workaround to keep using the default delimiters?

Best,

Mario

August 7, 2008 at 12:09 PM  
Anonymous Anonymous said...

Sorry, ten minutes later I found a possible working solution:

{literal}

function _( str ) {
return str;
}
var example = {/literal} '{ _("translate me") }' {literal};

{/literal}

Best,

Mario

August 7, 2008 at 12:40 PM  
Blogger Karlheinz Toni said...

Hi Mario,

I was just typing this literal plugin as you replied yourself :D

As to your first question, yes, the

var example = <@ _("translate me") @>;

would work. We're using it ourselves and this was the main reason for implementing it in first place (plus the CSS obviously).

But the literal solution works just as fine. You might wanna be doing some some performance tests on that as I'm not too sure about the php-eval performance there. Or you might wanna put that on the list for later performance improve - so that you'll have another look at it if you need to.

We're always working like:
1.) Make it work (you did that perfectly)
2.) Make it right
3.) Make it fast

I very much enjoyed to read http://c2.com/cgi/wiki?PrematureOptimization about that...

Cheers,
Charly

August 7, 2008 at 12:50 PM  
Anonymous Anonymous said...

Hi,

I wonder whether there is an elegant solution for the following problem. Suppose I need the following HTML as output of the template engine:

---
Please <a href="login.php">login</a> to access this feature.
---

I don't feel that having a-href stuff in translatable text is a nice thing to do, but the problem is the translatable strings are intermixed with non-translatable. The best I can come up with is to register 'sprintf' smarty plugin function and have something like

<@ sprintf format=_("Please %slogin%s to access this feature.") p1="&ly;a href=\"login.php\"> p2="</a>" @>

I guess this could work, but still %slogin%s could confuse the translator... Any ideas?

Regards,
Alex

August 27, 2008 at 8:58 AM  
Blogger Bojacob said...

Finally found out why I was having so much trouble getting this to work :)

It turns out the locale wasn't installed on my Ubuntu 7.10 server. I found by doing:

root@nas:~# locale -a
C
de_DE
en_AU.utf8
en_BW.utf8
en_CA.utf8
---snip

ar_KW.utf8 wasn't in there, so I had to add it.


root@nas:~# locale-gen ar_KW.UTF-8
Generating locales...
ar_KW.UTF-8... done
Generation complete.


Voila, now it's working perfectly :)

October 1, 2008 at 9:52 PM  
Blogger Karlheinz Toni said...

Hi Bojacob,

thanks for that information. We'll include that in the tutorial in case someone misses the OS locales, which seems like a likely case...

Sry not to have it included in first place. How r u doing otherwise?

Bests,
Charly

October 2, 2008 at 12:05 AM  
Blogger MapMyRun said...

Can you please update your google code with your *x* patch?

Amazingly frustrating when trying to debug the *x* issue thinking that your patch has made it to your code base!

ie,
http://blog.piins.com/api/smarty_i18n/i18n.tar.gz

February 19, 2009 at 2:45 PM  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home