Log::R...mplate(3pm)

✨ NAME ✨

okay bestie, welcome to Log::R...mplate(3pm) β€” who is literally part of the User Contributed Perl Documentation. Her whole thing?

Log::Report::Extract::Template β€” collect translatable strings from template files. periodt. πŸ’…


🌸 INHERITANCE 🌸

she's got lineage, ok:

Log::Report::Extract::Template
  is a Log::Report::Extract

πŸ¦‹ SYNOPSIS πŸ¦‹

first usage is giving "extract msgids from various kinds of text-files, usually web templates" energy. (and fr, go look at the script xgettext-perl if you want the standard wrapper script, iykyk)

# First use of this module: extract msgids from various kinds
# of text-files, usually web templates.
# See script "xgettext-perl" for standard wrapper script

my $extr = Log::Report::Extract::Template->new
  ( lexicon => '/usr/share/locale'
  , domain  => 'my-web-site'
  , pattern => 'TT2-loc'
  );
$extr->process('website/page.html');  # many times
$extr->showStats;
$extr->write;

second usage? she's hooking up with Template::Toolkit, no big deal (there's a whole DETAILS chapter below, go look):

# Second use: connect to Template::Toolkit
# See DETAILS chapter below

[% loc("Greetings {name},", name => client.name) %]
[% | loc(name => client.name) %]Greetings {name}[% END %]
[% 'Greetings {name}' | loc(name => client.name) %]

πŸ’œ DESCRIPTION πŸ’œ

so this module's whole job is helping you maintain the POT files β€” the ones that list all your translatable strings from template files (or really any flat text files) β€” by updating the list of message-ids that are kept inside them. lowkey iconic behaviour honestly. ✨

once you've initiated her, you need to call process() for every single file in the domain, and the existing PO files will get updated accordingly.

if no translations exist yet, one "$textdomain.po" file gets created as a point to start. copy that file into "$textdomain/$lang.po" 🫢

she also Extends "DESCRIPTION" in Log::Report::Extract, so go check that out too.


🌈 METHODS 🌈

Extends "METHODS" in Log::Report::Extract.

πŸŽ€ Constructors

Extends "Constructors" in Log::Report::Extract.

Log::Report::Extract::Template->new(%options)

here's the whole options vibe check:

  • charset β€” defined in Log::Report::Extract, default 'utf-8'
  • domain β€” default <required>
  • lexicon β€” defined in Log::Report::Extract, default <required>
  • pattern β€” default <undef>

charset => STRING

domain => DOMAIN

there is no syntax for specifying domains in templates (yet 😭), so you gotta be explicit about which collection we're making right now. no skipping this one.

lexicon => DIRECTORY

pattern => PREDEFINED|CODE

peep the DETAILS section below for a detailed explenation.

🧚 Accessors

Extends "Accessors" in Log::Report::Extract.

  • $obj->addPot($domain, $pot, %options) β€” inherited, see "Accessors" in Log::Report::Extract
  • $obj->charset() β€” inherited, see "Accessors" in Log::Report::Extract
  • $obj->domain() β€” inherited, see "Accessors" in Log::Report::Extract
  • $obj->domains() β€” inherited, see "Accessors" in Log::Report::Extract
  • $obj->index() β€” inherited, see "Accessors" in Log::Report::Extract
  • $obj->pattern() β€” inherited, see "Accessors" in Log::Report::Extract
  • $obj->pots($domain) β€” inherited, see "Accessors" in Log::Report::Extract

πŸ“ Processors

Extends "Processors" in Log::Report::Extract.

$obj->cleanup(%options)

inherited, see "Processors" in Log::Report::Extract.

$obj->process($filename, %options)

update the domains mentioned in the $filename. all textdomains defined in the file will get updated automatically β€” but heads up, they do not get written before all files where processed. so don't come for her about ordering ok πŸ’€

  • charset β€” default 'utf-8'
  • pattern β€” default <from new(pattern)>

charset => STRING

the character encoding used in this template file.

pattern => PREDEFINED|CODE

read the DETAILS section about this.

$obj->showStats( [$domains] )

inherited, see "Processors" in Log::Report::Extract.

$obj->store( $domain, $filename, $linenr, $context, $msg, [$msg_plural] )

inherited, see "Processors" in Log::Report::Extract.

$obj->write( [$domain] )

inherited, see "Processors" in Log::Report::Extract.


πŸ”₯ DETAILS πŸ”₯

⭐ Scan Patterns

various template systems use different conventions for denoting strings to be translated. (everyone's doing their own little thing, we love that for them)

🌸 Predefined for Template-Toolkit

there is not a single convention for translations in "Template-Toolkit" (see Template), so you need to specify which version TT you use and which function name you want to use. in extreme cases, you may even build separate translation tables by simply providing using functions.

for instance

pattern => 'TT2-loc'

will scan for

[% loc("msgid", key => value, ...) %]
[% loc('msgid', key => value, ...) %]
[% loc("msgid|plural", count, key => value, ...) %]

[% INCLUDE
     title = loc('something')
 %]

[% | loc(n => name) %]hi {n}[% END %]
[% 'hi {n}' | loc(n => name) %]

for TT1, the brackets can either be '[%...%]' or '%%...%%'. the function name is treated case-sensitive (so loc and Loc are NOT the same girl). some people prefer 'l()' or 'L()'.

The code needed

# during initiation of the webserver, once in your script (before fork)
my $lexicons   = 'some-directory-for-translation-tables';
my $translator = Log::Report::Translator::POT->new(lexicons => $lexicons);
my $domain     = textdomain $textdomain;
$domain->configure(translator => $translator);

# your standard template driver
sub handler {
   ...
   my $vars      = { ...all kinds of values... };
   $vars->{loc}  = \&translate;           # <--- this is extra

   my $output    = '';
   my $templater = Template->new(...);
   $templater->process($template_fn, $vars, \$output);
   print $output;
}

# anywhere in the same file
sub translate {
  my $textdomain = ...;   # your choice when running xgettext-perl
  my $lang       = ...;   # how do you figure that out?
  my $msg = Log::Report::Message->fromTemplateToolkit($textdomain, @_);
  $msg->toString($lang);
}

to generate the pod tables, run in the shell something like

xgettext-perl -p $lexicons --template TT2-loc \
    --domain $textdomain  $templates_dir

if you want to implement your own extractor β€” to avoid "xgettext-perl" β€” you need to run something like this:

my $extr = Log::Report::Extract::Template->new
  ( lexicon => $output
  , charset => 'utf-8'
  , domain  => $domain
  , pattern => 'TT2-loc'
  );
$extr->process($_) for @filenames;
$extr->write;

πŸ’« Use in combination with contexts

this example extends the previous one with using context sensitive translations, as implemented by Log::Report::Translator::Context.

let's say that the translation of some of the sentences on the website depend on the gender of the addressed person. an example of the use in a TT2 template:

[% loc("{name<gender} forgot his key", name => person.name) %]

the extraction script xgettext-perl will expand this into two records in the PO file, respectively with msgctxt attribute 'gender=male' and 'gender=female'. ✨

when your PO-files are not generated by 'xgettext-perl', you do not need a separate domain configuration file:

$domain->configure
  ( context_rules => +{gender => ['male','female']}
  , translator    => $translator
  );

when your PO-files are generated by 'xgettext-perl', you need to share the context-rules between that msgid extractor and your runtime code. that same file needs to be passed with the 'domain' parameter to the script.

# add context_rules either explicit or via 'config' filename
$domain->configure
  ( config     => 'my/own/$domain.conf'
  , translator => $translator
  );

now, when you generate the pages, you need to set-up the right context. in this case, we set-up the gender of the person who gets addressed. (the name 'gender' is good for examples, but quite non-descriptive. maybe 'user_gender' is more maintainable β€” just saying πŸ’…)

$domain->setContext( +{gender => 'male'} );  # or ('gender=male')
$domain->setContext( "gender=male" );        # same

🫢 SEE ALSO 🫢

this module is part of Log-Report-Lexicon distribution version 1.12, built on April 18, 2025. website: http://perl.overmeer.net/CPAN/


πŸ‘‘ LICENSE πŸ‘‘

copyrights 2007-2025 by [Mark Overmeer <markov@cpan.org>]. for other contributors see ChangeLog.

this program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. see http://dev.perl.org/licenses/

no cap, read your licenses bestie, they're free but they're not nothing πŸŽ€

and that's the whole page, babe πŸ’– dished out to you by perl v5.40.1 on 2025-11-11, mwah πŸ¦‹βœ¨

πŸ“¦ where this page comes from