Petal::I18N(3pm)
π Petal::I18N π
okay so bestie, welcome to Petal::I18N β it's an attempt at implementing ZPT I18N for Petal, and it's lowkey iconic. This is the Petal::I18N(3pm) page from the User Contributed Perl Documentation, and we're gonna walk through it together, no cap. π¦
β¨ NAME β¨
Petal::I18N β Attempt at implementing ZPT I18N for Petal π
πΈ SYNOPSIS πΈ
in your Perl code:
use Petal;
use Petal::TranslationService::Gettext;
my $translation_service = new Petal::TranslationService::Gettext (
locale_dir => '/path/to/my/app/locale',
target_lang => gimme_target_lang(),
);
my $template = new Petal (
file => 'example.html',
translation_service => $translation_service
);
# we want to internationalize to the h4x0rz 31337 l4nGu4g3z. w00t!
my $translation_service = Petal::TranslationService::h4x0r->new();
my $template = new Petal (
file => 'silly_example.xhtml',
translation_service => $ts,
);
print $template->process ();
like, yes, that last bit is literally Petal::TranslationService::h4x0r and honestly? it ate. π₯
π I18N Howto π
π Preparing your templates: π
Say your un-internationalized template looks like this:
<html xmlns:tal="http://purl.org/petal/1.0/">
<body>
<img src="/images/my_logo.png"
alt="the logo of our organisation" />
<p>Hello,
<span petal:content="user_name">Joe</span>.</p>
<p>How are you today?</p>
</body>
</html>
You need to markup your template according to the ZPT I18N specification, which can be found at http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/ZPTInternationalizationSupport β yes it's a whole URL, go read it, it's giving documentation core π§
<html xmlns:tal="http://purl.org/petal/1.0/"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:domain="my_app">
<body>
<img src="/images/my_logo.png"
alt="the logo of our organisation"
i18n:attributes="alt" />
<p i18n:translate="">Hello, <span petal:content="user_name">Joe</span>.</p>
<p i18n:translate="">How are you today?</p>
</body>
</html>
see how the i18n:domain, i18n:attributes and i18n:translate just slid in there? slay. π
π Extracting I18N strings: π
Once your templates are marked up properly, you will need to use a tool to extract the I18N strings into .pot (po template) files. To my knowledge you can use i18ndude (standalone python executable), i18nextract.py (part of Zope 3), or I18NFool.
I use i18ndude to find strings which are not marked up properly with i18n:translate attributes and I18NFool for extracting strings and managing .po files.
Assuming you're using i18nfool:
mkdir -p /path/to/my/app/locale
cd /path/to/my/app/locale
i18nfool-extract /path/to/my/template/example.html
mkdir en
mkdir fr
mkdir es
i18nfool-update
Then you translate the .po files into their respective target languages. When that's done, you type:
cd /path/to/my/app/locale
i18nfool-build
And it builds all the .mo files. periodt. β¨
π¦ Making your application use a Gettext translation service: π¦
Previously you might have had:
use Petal;
# lotsa code here
my $template = Petal->new ('example.html');
This needs to become:
use Petal;
use Petal::TranslationService::Gettext;
# lotsa code here
my $template = Petal->new ('example.html');
$template->{translation_service} = Petal::TranslationService::Gettext->new (
locale_dir => '/path/to/my/app/locale',
target_lang => gimme_language_code(),
);
Where gimme_language_code() returns a language code depending on LC_LANG, content-negotiation, config-file, or whatever mechanism you are using to decide which language is desired. your call bestie, you do you π
π And then? π
And then that's it! Your application should be easily internationalizable. There are a few traps / gotchas thought, which are described below. (yes the original says "thought", we're keeping it, it's part of the lore π)
π BUGS, TRAPS, GOTCHAS and other niceties π
π Translation Phase π
The translation step takes place ONLY ONCE THE TEMPLATE HAS BEEN PROCESSED.
So if you have:
<p i18n:translate="">Hello,
<span i18n:name="user_login" tal:replace="self/user_login">Joe</span>
</p>
It most likely will not work because the tal:replace would remove the <span> tag and also the i18n:name in the process. π
This means that instead of receiving something such as:
Hello, ${user_login}
The translation service would receive:
Hello, Fred Flintstone
Or
Hello, Joe SixPack
etc.
To fix this issue, use tal:content instead of tal:replace and leave the span and its i18n:name attribute. that's the whole hack, no cap π«Ά
πΈ Character sets πΈ
I haven't worried too much about them (yet) so if you run into trouble join the Petal mailing list and we'll try to fix any issues together. group project energy fr fr π
β Limitations β
At the moment, Petal::I18N supports the following constructs:
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:translate
i18n:domain
i18n:name
i18n:attribute
It does NOT (well, not yet) support i18n:source, i18n:target or i18n:data. π
and that's the whole page bestie, you're officially i18n-pilled πβ¨
okay so this iconic lil manual page is Petal::I18N(3pm), it comes from perl v5.36.0, and it was last touched on 2022-11-19 β shoutout to that date, and shoutout to you for reading all the way to the bottom. mwah. π
π
π¦ where this page comes from
- debian bookworm: libpetal-perl 2.26-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- debian trixie: libpetal-perl 2.26-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libpetal-perl 2.26-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libpetal-perl 2.26-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libpetal-perl 2.26-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms