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:
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...
35 Comments:
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
is this just the extracted page, or did you modify anything?
I haven´t modified it, just uploded it to my webserver.
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
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.
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
It still don´t work. Are there any server requirement to be met like globalregister on etc?
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
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.
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
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
:D from our last with the tutorial for the last comment/question. working again
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 :(
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
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.
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
Sorry, ten minutes later I found a possible working solution:
{literal}
function _( str ) {
return str;
}
var example = {/literal} '{ _("translate me") }' {literal};
{/literal}
Best,
Mario
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
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
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 :)
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
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
Post a Comment
Subscribe to Post Comments [Atom]
<< Home