html-template-users Mailing List for HTML::Template (Page 35)
Brought to you by:
samtregar
You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(42) |
Jul
(80) |
Aug
(77) |
Sep
(97) |
Oct
(65) |
Nov
(80) |
Dec
(39) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(63) |
Feb
(47) |
Mar
(45) |
Apr
(63) |
May
(67) |
Jun
(51) |
Jul
(78) |
Aug
(37) |
Sep
(45) |
Oct
(59) |
Nov
(50) |
Dec
(70) |
2004 |
Jan
(23) |
Feb
(90) |
Mar
(37) |
Apr
(53) |
May
(111) |
Jun
(71) |
Jul
(35) |
Aug
(58) |
Sep
(35) |
Oct
(35) |
Nov
(35) |
Dec
(20) |
2005 |
Jan
(51) |
Feb
(19) |
Mar
(20) |
Apr
(8) |
May
(26) |
Jun
(14) |
Jul
(49) |
Aug
(24) |
Sep
(20) |
Oct
(49) |
Nov
(17) |
Dec
(53) |
2006 |
Jan
(12) |
Feb
(26) |
Mar
(45) |
Apr
(19) |
May
(19) |
Jun
(13) |
Jul
(11) |
Aug
(9) |
Sep
(10) |
Oct
(16) |
Nov
(17) |
Dec
(13) |
2007 |
Jan
(9) |
Feb
(12) |
Mar
(28) |
Apr
(33) |
May
(12) |
Jun
(12) |
Jul
(19) |
Aug
(4) |
Sep
(4) |
Oct
(5) |
Nov
(5) |
Dec
(13) |
2008 |
Jan
(6) |
Feb
(7) |
Mar
(14) |
Apr
(16) |
May
(3) |
Jun
(1) |
Jul
(12) |
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(9) |
2009 |
Jan
(9) |
Feb
|
Mar
(10) |
Apr
(1) |
May
|
Jun
(6) |
Jul
(5) |
Aug
(3) |
Sep
(7) |
Oct
(1) |
Nov
(15) |
Dec
(1) |
2010 |
Jan
|
Feb
|
Mar
|
Apr
(9) |
May
|
Jun
|
Jul
(5) |
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
(3) |
Mar
|
Apr
(28) |
May
|
Jun
|
Jul
(3) |
Aug
(4) |
Sep
(3) |
Oct
|
Nov
(8) |
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
(2) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(2) |
Dec
|
2016 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
From: Sam T. <sa...@tr...> - 2005-02-23 15:14:32
|
On Tue, 22 Feb 2005, Jonathan Lang wrote: > Could HTML::TEMPLATE be reworked to allow for a more XML-friendly syntax? Sure. Check out the filter option to new(). You can easily add support for almost any syntax you can imagine! -sam |
From: Jonathan L. <dat...@ya...> - 2005-02-23 07:32:58
|
Could HTML::TEMPLATE be reworked to allow for a more XML-friendly syntax? What I have in mind: Depreciate the current syntaxes for variables and inclusions. Replace the former with an Entity-based model: &VAR.variable_name; Replace the latter with a Processor Instruction-based model: <?TMPL_INCLUDE url ?> The biggest benefit of doing this is that a syntax-highlighting editor won't choke on it. Don't get me wrong: I understand the need for (some) backward compatability; that's why I suggest depreciating the current variable and include syntax instead of outright removing it. ===== Jonathan "Dataweaver" Lang __________________________________ Do you Yahoo!? Yahoo! Mail - Easier than ever with enhanced search. Learn more. http://info.mail.yahoo.com/mail_250 |
From: Cees H. <ce...@si...> - 2005-02-17 14:40:36
|
Justin Simoni wrote: > Hello all, > > Been looking for a while for this answer, and seem to think it must have > been asked before, although both the archives mentioned in the docs are > down. So here goes: > > Is there an easy way to pass a Hash to HTML::Template in hopes to use > the key/value pairs, without putting it in a <TMPL_LOOP>? > > Along with HTML::Template, I'm also familiar with Template-Toolkit. It > had the dot syntax, where you can navigate a complex data structure like - > > $this->{that}->{then}->{some} > > like this: > > [% this.that.then.some %] > > I can't find anything similar in HTML::Template, except to put a > <TMPL_LOOP> around the block of HTML when I want to access a value in a > hash. I guess this is fine with me - as long as performance isn't > completely dismal; You could walk your way down the data structure and flatten it out using the dot notation. Here is a quick example of how you could do that. Note that it is not heavily tested, and doesn't take into consideration tied variables, code refs, objects, etc... Also, since it is recursive, it probably isn't that efficient! sub flatten { my $item = shift; my $keypart = shift || ''; my $data = shift || {}; if (ref $item eq 'HASH') { while (my($k,$v) = each %$item) { $data = flatten($v, $keypart.'.'.$k, $data); } } elsif (ref $item eq 'ARRAY') { for (my $i=0; $i < @$item; $i++) { $data = flatten($item->[$i], $keypart.'.'.$i, $data); } } else { $data->{substr($keypart,1)} = $item; } return $data; } my $struct = { test1 => 'value1', test2 => [qw(a b c d e f)], test3 => { test3a => [qw(g h i)], test3b => 'value3b' }, test4 => 'value4', }; my $data = flatten($struct); And if you dump the resulting hash out, you get the following: test1 = value1 test2.0 = a test2.1 = b test2.2 = c test2.3 = d test2.4 = e test2.5 = f test3.test3a.0 = g test3.test3a.1 = h test3.test3a.2 = i test3.test3b = value3b test4 = value4 Of course, if you really need this functionality, why not just use Template Toolkit since you already know it? Use the best tool for the job... Sometimes that will be HTML::Template, sometimes it may be something else. Cheers, Cees > > To clarify, in my Perl code, I have a hash that holds any errors that > may have been put forth from an HTML form. Something like: > > my %errors = (forgot_name => 1, impossible_zipcode => 1, > is_the_unabomber => 0); > > my theoretically HTML would be something like: > > <TMPL_IF EXPR="errors.forgot_name == 1"> > > <p>You forgot your name!</p> > > </TMPL_IF> > > > Thanks for your time! > > justinSimoni.Artist > -- > .: art http://justinsimoni.com > .: phone 720 436 7701 > > > > ------------------------------------------------------- > SF email is sponsored by - The IT Product Guide > Read honest & candid reviews on hundreds of IT Products from real users. > Discover which products truly live up to the hype. Start reading now. > http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click > _______________________________________________ > Html-template-users mailing list > Htm...@li... > https://lists.sourceforge.net/lists/listinfo/html-template-users > > |
From: Justin S. <ju...@sk...> - 2005-02-17 05:06:32
|
Hello all, Been looking for a while for this answer, and seem to think it must have been asked before, although both the archives mentioned in the docs are down. So here goes: Is there an easy way to pass a Hash to HTML::Template in hopes to use the key/value pairs, without putting it in a <TMPL_LOOP>? Along with HTML::Template, I'm also familiar with Template-Toolkit. It had the dot syntax, where you can navigate a complex data structure like - $this->{that}->{then}->{some} like this: [% this.that.then.some %] I can't find anything similar in HTML::Template, except to put a <TMPL_LOOP> around the block of HTML when I want to access a value in a hash. I guess this is fine with me - as long as performance isn't completely dismal; To clarify, in my Perl code, I have a hash that holds any errors that may have been put forth from an HTML form. Something like: my %errors = (forgot_name => 1, impossible_zipcode => 1, is_the_unabomber => 0); my theoretically HTML would be something like: <TMPL_IF EXPR="errors.forgot_name == 1"> <p>You forgot your name!</p> </TMPL_IF> Thanks for your time! justinSimoni.Artist -- .: art http://justinsimoni.com .: phone 720 436 7701 |
From: Sam T. <sa...@tr...> - 2005-02-11 21:41:36
|
On Fri, 11 Feb 2005, Scottsweep wrote: > I'm working from the standpoint of not making associate any more > complex, actually less so from the end user standpoint. From the standpoint of the maintainer it definitely looks more complex. > The thought of instantiating another object to do what can be done > in a few lines of code internally seems far more complex to me. These days I prefer less code in more modules. HTML::Template has reached a point where I'm extremely reluctant to add code to do work that could be done just as well in a separate module. Since this job can be handled outside of HTML::Template, I think it should be. -sam |
From: Scottsweep <sco...@ya...> - 2005-02-11 19:54:27
|
Sam, I'm working from the standpoint of not making associate any more complex, actually less so from the end user standpoint. If you look at the code all I've done is added three checks for ($associated_object->can('param') && $option{associate_by_methods}), their associated blocks of code (which are duplicates of existing) and a 17 line function to lookup the methods. The thought of instantiating another object to do what can be done in a few lines of code internally seems far more complex to me. This should also be a boost in performance as you are going directly against the object's methods rather than a layer of indirection that param creates. If a new function is created in my object I only need add the TMPL_VAR to the .tmpl without the need to add support for it to a param method. Of course all of the existing param functionalty will still work as is, so I'm not suggesting a rework of what is already there, just a great deal more flexibility from a small bit of code. diff -u output (pod included): --- /usr/local/lib/perl5/site_perl/5.8.4/HTML/Template.pm 2004-06-18 13:42:06.000000000 -0400 +++ ./Template.pm 2005-02-11 14:33:42.998984000 -0500 @@ -712,6 +712,28 @@ =item * +associate_by_methods - this will force HTML::Template to look at an objects +methods and retrieve data from them rather than via param (i.e., associated +object does not need to define param). This should maintain backwards +compatibility with existing param use. + +=item * + +associate_by_methods_respect_privacy - this is a prefix that will be looked +for when examining object methods, if found then those methods will not be +useable in the template. Setting to 1 will cause the default of '_' to be +used. This allows you to actually keep private methods private: + + my $template = HTML::Template->new(filename => 'template.tmpl', + associate => [$query, $other_obj], + associate_by_methods => 1, + associate_by_methods_respect_privacy => 1); + + $other_obj->_some_private_method(); # '_some_private_method' is NOT a TMPL_VAR + $other_obj->some_public_method(); # 'some_public_method' is a TMPL_VAR + +=item * + case_sensitive - setting this option to true causes HTML::Template to treat template variable names case-sensitively. The following example would only set one parameter without the "case_sensitive" option: @@ -2538,6 +2560,36 @@ } } +# This accepts an object or package name and will return a list of methods +# +# $self->_get_object_methods('HTML::Template',1) +# would return ['associateCGI','carp','clear_params','confess','croak','md5_hex','new','new_array_ref','new_file','new_filehandle','new_scalar_ref','output','param','query'] +# +# Params: +# pkg - either an object or package/module name to be examined +# respect_private - This is a prefix to hide private methods from the list. +# Defaults to '_' if set to 1. TODO://let a regex be passed +# +# Based on function and symTable from http://search.cpan.org/~mpocock/MRP-1.0/MRP/Introspection.pm +# +sub _get_object_methods { + my $self = shift; + my $pkg = shift; + my $respect_private = shift; # won't return methods beginning with an this value, '_' by default + $respect_private = '_' if($respect_private == 1); + $pkg = (ref $pkg || $pkg) . '::'; + + my @methods; + my ($name, $glob); + + no strict 'refs'; + while(($name, $glob) = each %{\%$pkg}) { + defined (*$glob{CODE}) && do { push @methods, $name unless($respect_private && $name =~ /^$respect_private/) }; + } + + return @methods; +} + # obsolete implementation of associate sub associateCGI { @@ -2600,36 +2652,56 @@ # globalize vars - this happens here to localize the circular # references created by global_vars. $self->_globalize_vars() if ($options->{global_vars}); - - # support the associate magic, searching for undefined params and - # attempting to fill them from the associated objects. + if (scalar(@{$options->{associate}})) { - # prepare case-mapping hashes to do case-insensitive matching + # prepare case-mapping hashes to do case-insensitive matching # against associated objects. This allows CGI.pm to be # case-sensitive and still work with asssociate. my (%case_map, $lparam); foreach my $associated_object (@{$options->{associate}}) { # what a hack! This should really be optimized out for case_sensitive. - if ($options->{case_sensitive}) { - map { - $case_map{$associated_object}{$_} = $_ - } $associated_object->param(); - } else { - map { - $case_map{$associated_object}{lc($_)} = $_ - } $associated_object->param(); + if ($associated_object->can('param') && !$options->{associate_by_methods}) { + if ($options->{case_sensitive}) { + map { + $case_map{$associated_object}{$_} = $_ + } $associated_object->param(); + } else { + map { + $case_map{$associated_object}{lc($_)} = $_ + } $associated_object->param(); + } + } else { ### get the object's methods + if ($options->{case_sensitive}) { + map { + $case_map{$associated_object}{$_} = $_ + } $self->_get_object_methods($associated_object,$options->{associate_by_methods_respect_privacy}); + } else { + map { + $case_map{$associated_object}{lc($_)} = $_ + } $self->_get_object_methods($associated_object,$options->{associate_by_methods_respect_privacy}); + } } + } foreach my $param (keys %{$self->{param_map}}) { unless (defined($self->param($param))) { OBJ: foreach my $associated_object (reverse @{$options->{associate}}) { - $self->param($param, scalar $associated_object->param($case_map{$associated_object}{$param})), last OBJ - if (exists($case_map{$associated_object}{$param})); + + if ($associated_object->can('param') && !$options->{associate_by_methods}) { ### + print STDERR "\n". ref($associated_object) . "::param('" . $case_map{$associated_object}{$param} . "');\n"; + $self->param($param, scalar $associated_object->param($case_map{$associated_object}{$param})), last OBJ + if (exists($case_map{$associated_object}{$param})); + } else { + my $method = $case_map{$associated_object}{$param}; + $self->param($param, scalar $associated_object->$method), last OBJ + if (exists($case_map{$associated_object}{$param})); + } + } } } - } + } use vars qw($line @parse_stack); local(*line, *parse_stack); @@ -3331,3 +3403,4 @@ USA =cut + --- Sam Tregar <sa...@tr...> wrote: > On Fri, 11 Feb 2005, Scottsweep wrote: > > > I want to propose the following PATCH to > > HTML::Template. This would allow objects to be > > associated without the need to define a param > method > > (all public methods can be TMPL_VARs). > > This seems like a reasonable thing to want, but I > think it would be > better done with a wrapper object. Imagine: > > use HTML::Template; > use Class::ParamWrapper; > > my $t = HTML::Template->new(filename => $foo, > associate => > Class::ParamWrapper->new($some_object)); > > Class::ParamWrapper would provide a param() method > which proxies calls > to the wrapped object. You can add any > configuration you need to the > Class::ParamWrapper->new() call. > > This has the benefit of not increasing the > complexity of > HTML::Template's associate implementation which is > already pretty > unmanageable. It also opens up your code to use in > other contexts. > > -sam > > PS: If you want to submit a patch in the future > please prepare it > using 'diff -u'. > __________________________________ Do you Yahoo!? Yahoo! Mail - Helps protect you from nasty viruses. http://promotions.yahoo.com/new_mail |
From: Sam T. <sa...@tr...> - 2005-02-11 17:01:56
|
On Fri, 11 Feb 2005, Scottsweep wrote: > I want to propose the following PATCH to > HTML::Template. This would allow objects to be > associated without the need to define a param method > (all public methods can be TMPL_VARs). This seems like a reasonable thing to want, but I think it would be better done with a wrapper object. Imagine: use HTML::Template; use Class::ParamWrapper; my $t = HTML::Template->new(filename => $foo, associate => Class::ParamWrapper->new($some_object)); Class::ParamWrapper would provide a param() method which proxies calls to the wrapped object. You can add any configuration you need to the Class::ParamWrapper->new() call. This has the benefit of not increasing the complexity of HTML::Template's associate implementation which is already pretty unmanageable. It also opens up your code to use in other contexts. -sam PS: If you want to submit a patch in the future please prepare it using 'diff -u'. |
From: Scottsweep <sco...@ya...> - 2005-02-11 16:51:05
|
Hello all, I want to propose the following PATCH to HTML::Template. This would allow objects to be associated without the need to define a param method (all public methods can be TMPL_VARs). It adds two options (see section 2 below) to maintain backwards compatability with param use. As I understand associate was originally added as a means for working with a CGI object, but as things have grown the need to just associate a plain old blessed object has grown. I am of the opinion that requiring a param method for objects is not always practical. There are 3 below sections to modify/replace in HTML::Template. I've tested and it appears to work well, but please don't trust me and take a look for yourself. Additional possibilities: What would make this really powerful is adding an 'associate' method to the class, rather than just in the constructor. This would allow examination of the template before the object is associated. The developer could then alter the object based on what is visible in the template. Of course non-constructor binding of associated objects can be achieved with: push(@{$template->{options}->{associate}}, $my_object), but it'd be a hack, breaking OO, etc. Thanks, Scott Connelly ################################################################################ #111111111111111111111111111111111111111111111111111111111111111111111111111111# #REPLACE LINES 1015 - 1020 (only LINE 1017 has changed) WITH # make sure objects in associate area support param() foreach my $object (@{$options->{associate}}) { if($object->can('param') && !$options->{associate_by_methods}) { croak("HTML::Template->new called with associate option, containing object of type " . ref($object) . " which lacks a param() method!"); } ################################################################################ #222222222222222222222222222222222222222222222222222222222222222222222222222222# #LINE 2604 - 2633 ##################### # support for two new options: # - associate_by_methods - this will force HTML::Template to look at an # objects methods and retrieve data from them # rather than via param (i.e., associated # object does not need to define param). This # should maintain backwards compatibility with # existing param use. # # - associate_by_methods_respect_privacy - this is a prefix that will # be looked for when examining object methods, # if found then those methods will not be # useable in the template. Setting to 1 will # cause the default of '_' to be used. This # allows you to actually keep private methods # private. I.e., $my_object->_some_private_method() # would not be available as a TMPL_VAR, while # $my_object->some_public_method() would. if (scalar(@{$options->{associate}})) { # prepare case-mapping hashes to do case-insensitive matching # against associated objects. This allows CGI.pm to be # case-sensitive and still work with asssociate. my (%case_map, $lparam); foreach my $associated_object (@{$options->{associate}}) { # what a hack! This should really be optimized out for case_sensitive. if ($associated_object->can('param') && !$options->{associate_by_methods}) { ### if ($options->{case_sensitive}) { map { $case_map{$associated_object}{$_} = $_ } $associated_object->param(); } else { map { $case_map{$associated_object}{lc($_)} = $_ } $associated_object->param(); } } else { ### get the object's methods if ($options->{case_sensitive}) { map { $case_map{$associated_object}{$_} = $_ } $self->_get_object_methods($associated_object,$options->{associate_by_methods_respect_privacy}); } else { map { $case_map{$associated_object}{lc($_)} = $_ } $self->_get_object_methods($associated_object,$options->{associate_by_methods_respect_privacy}); } } } foreach my $param (keys %{$self->{param_map}}) { unless (defined($self->param($param))) { OBJ: foreach my $associated_object (reverse @{$options->{associate}}) { if ($associated_object->can('param') && !$options->{associate_by_methods}) { $self->param($param, scalar $associated_object->param($case_map{$associated_object}{$param})), last OBJ if (exists($case_map{$associated_object}{$param})); } else { my $method = $case_map{$associated_object}{$param}; $self->param($param, scalar $associated_object->$method), last OBJ if (exists($case_map{$associated_object}{$param})); } } } } } ################################################################################ #333333333333333333333333333333333333333333333333333333333333333333333333333333# # Add to module where appropriate ###################### # # _get_object_methods # # This accepts an object or package name and will return a list of methods # # $self->_get_object_methods('HTML::Template',1) # would return ['associateCGI','carp','clear_params','confess','croak','md5_hex','new','new_array_ref','new_file','new_filehandle','new_scalar_ref','output','param','query'] # # Params: # pkg - either an object or package/module name to be examined # respect_private - This is a prefix to hide private methods from the list. # Defaults to '_' if set to 1. TODO://let a regex be passed # # Based on function and symTable from http://search.cpan.org/~mpocock/MRP-1.0/MRP/Introspection.pm # sub _get_object_methods { my $self = shift; my $pkg = shift; my $respect_private = shift; # won't return methods beginning with an this value, '_' by default $respect_private = '_' if($respect_private == 1); $pkg = (ref $pkg || $pkg) . '::'; my @methods; my ($name, $glob); no strict 'refs'; while(($name, $glob) = each %{\%$pkg}) { defined (*$glob{CODE}) && do { push @methods, $name unless($respect_private && $name =~ /^$respect_private/) }; } return @methods; } __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com |
From: Thomas G. <gi...@gm...> - 2005-02-10 12:19:58
|
Am Thu, 10.Feb.2005 um 12:54:23 +0100 schraubte Thomas Nyman: > Hi > > I have also added tmpl_if conditionals so that if there is no info in > loop one a certain text is displayed. Which also works fine. The issue > however is that if loop one is empty but loop two is not then the > conditional should not apply. But since loop one is empty , i.e false, > the conditional is displayed. What i need is something along the lines > if loop one is empty but not loop two then display loop two else > display conditional. Hi, this seems to be similar to my problem some days ago (TMPL_OR). Maybe you try solving it using HTML::Template::Expr, as well :) Cheers, Tom -- The world is coming to an end ... SAVE YOUR BUFFERS!!! |
From: Alex K. <ka...@ra...> - 2005-02-10 12:04:15
|
* Thomas Nyman <th...@te...> [February 10 2005, 14:54]: > the conditional is displayed. What i need is something along the lines > if loop one is empty but not loop two then display loop two else > display conditional. Pass additional boolean (not_one_and_two => !@loop_one && @loop_two) from your Perl code and check it inside template with a simple <tmpl_if>. -- Alex Kapranoff, $n=["1another7Perl213Just3hacker49"=~/\d|\D*/g]; $$n[0]={grep/\d/,@$n};print"@$n{1..4}\n" |
From: Thomas N. <th...@te...> - 2005-02-10 11:54:43
|
Hi Beginning the get the hang of templates and am very pleased with it. I have a small problem however. I have a xx.tmpl that contains two loops, tmpl_loop name=one and tmpl_loop name=two now loop one can be empty while loop two is not and vice versa. Also both loops could be empty. I have also added tmpl_if conditionals so that if there is no info in loop one a certain text is displayed. Which also works fine. The issue however is that if loop one is empty but loop two is not then the conditional should not apply. But since loop one is empty , i.e false, the conditional is displayed. What i need is something along the lines if loop one is empty but not loop two then display loop two else display conditional. I've been trying different wasu with no success..either it cant be done or Iits just that my train of thought cant seem to leave the station. Any help would be appreciated |
From: Tobias G. <lis...@e-...> - 2005-01-31 19:16:21
|
Pete Prodoehl wrote: >> [1] valid XHTML, working: >> >> <title><tmpl_var name="title"/></title> > > Does this work? It's not really xhtml, but valid xml. > <title><!-- tmpl_var name="title" --></title> This will work. It's more difficult, when it comes to attribute values, where html comments will not work. But {% tmpl_var name="title" %} works well for me now. I simply replace this with a filter. Tobias |
From: Pete P. <pet...@cy...> - 2005-01-31 15:05:38
|
Tobias Grimm wrote: > Hi! > > Is there any way to use a valid XHTML document as template? As far as I > tried this seems to be not possible. > > e.g.: > > [1] valid XHTML, working: > > <title><tmpl_var name="title"/></title> Does this work? <title><!-- tmpl_var name="title" --></title> I've built sites using H::T that are valid XHTML, but I focus on the output, not the template itself... Pete |
From: Roger B. W. <ro...@fi...> - 2005-01-26 18:32:29
|
On Wed, Jan 26, 2005 at 04:39:20PM +0100, Thomas Nyman wrote: >Thanks for the tip..its working like clockwork. I though i'd be bold >and ask another question. I do not quite grasp references and arrays >etc. I would like to take and element in fetchall_array({}) and check >it against current date, but i seem to be unable to understand how i >access the actual content and not just the hashref code. Would be much >appreciated it if you could steer me right on that one. A simple cookbook answer would solve this problem. If you read perldoc perlreftut, it will solve this and a great many related problems. R |
From: Ragan, S. <sr...@bc...> - 2005-01-26 15:50:47
|
You should check out this reference to data structures in perl. Once you get a handle on this you're whole perl experience will change. http://www.perldoc.com/perl5.8.0/pod/perldsc.html Good luck Steve Steve Ragan Sr. Internet Developer Internet Services Division Bernard C. Harris Publishing Co., Inc. 2500 Westchester Ave. Purchase, NY 10577 (914) 641-3948 sr...@bc... <mailto:sr...@bc...> -----Original Message----- From: htm...@li... [mailto:htm...@li...]On Behalf Of Thomas Nyman Sent: Wednesday, January 26, 2005 10:39 AM To: Cees Hek Cc: htm...@li... Subject: Re: [htmltmpl] New to this - conditional problem i think Thanks for the tip..its working like clockwork. I though i'd be bold and ask another question. I do not quite grasp references and arrays etc. I would like to take and element in fetchall_array({}) and check it against current date, but i seem to be unable to understand how i access the actual content and not just the hashref code. Would be much appreciated it if you could steer me right on that one. Thanks in advance 2005-01-21 kl. 21.50 skrev Cees Hek: > fetchall_arrayref({} ------------------------------------------------------- This SF.Net email is sponsored by: IntelliVIEW -- Interactive Reporting Tool for open source databases. Create drag-&-drop reports. Save time by over 75%! Publish reports on the web. Export to DOC, XLS, RTF, etc. Download a FREE copy at http://www.intelliview.com/go/osdn_nl _______________________________________________ Html-template-users mailing list Htm...@li... https://lists.sourceforge.net/lists/listinfo/html-template-users |
From: Thomas N. <th...@te...> - 2005-01-26 15:39:33
|
Thanks for the tip..its working like clockwork. I though i'd be bold and ask another question. I do not quite grasp references and arrays etc. I would like to take and element in fetchall_array({}) and check it against current date, but i seem to be unable to understand how i access the actual content and not just the hashref code. Would be much appreciated it if you could steer me right on that one. Thanks in advance 2005-01-21 kl. 21.50 skrev Cees Hek: > fetchall_arrayref({} |
From: Mark F. <mar...@ea...> - 2005-01-24 17:51:56
|
Cees Hek provided me with a solution using H::T's filter. I think Sam suggested a filter first but, I didn't understand. (I would'nt have figured this out without seeing the sample Cees gave me.) It involves passing the language value to H::T's load_tmpl method. Then override H::T's _cache_key method to add the language value to the key H::T uses to cache the template. This lets you load a language-neutral template, update it for a language, and H::T will cache it uniquely by template-name and language. Another advantage is that I can generate all my pull-down (select/option) lists *in the filter* and they become permanent parts of the cached template -- not reevaluated with each output. When I create the string of select/option values, I add a "<TMPL_VAR NAME=form_control_name . $key>". Each time the page is reevaluated for output only this variable is evaluted (to replace it with "selected=selected"). This way the only variable template content is truly dynamic -- could change from display to display. It seems like this would be a significant performance boost. (I don't know.) I put most of the page-specific initialization like this into a module which is loaded when the filter fires. It gets called from the filter and performs the work. Because it's a module, variables/objects in the filter's namespace can be transferred into the module (by reference) using "$Static_page_init::{$page_name}::variable_name = $self->{my_db_handler}". References to logging subroutines can be passed in. (I do this just once after the module is loaded.) Another advantage to this modular design is that the language-translation handles, page initialization modules, etc., can be dropped after their use. Since it's one-time initialization there' no need to keep them around (using memory). Ultimately, I end up with a single language-translation handle used for dynamic (display to display) message translation. A very small lexicon for the page. I'm very happy with this solution. It does exactly what I was trying to do. And, makes selection/option lists more static like I'd always thought they should be. Below is a more detailed example with samples. It may be hard to follow since this complicated (and involves Locale::Maketext). I could create a small working example if people thought it would be useful. Thanks for everyone putting up with my ramblings! I hope this ends up being useful to someone else. ============== Detailed Example ============ The following describes a way to use H::T to 1. Perform efficient language translation upon templates 2. Minimize the number of duplicated templates which can result from supporting multiple languages (reducing the duplicated page structure and ongoing maintenance costs). 3. Cache templates unique by language -- not merely filename. 4. Cache templates in a manner that the bulk of language translation is cached and not re-evaluated with each display. 5. Use Locale::Maketext in a manner that lexicons are kept small and used as needed. 6. Avoid retention in memory of language translation objects/packages if, as stated in #4, the translation is one-time. 7. Use a language negotiation method other than Locale::Maketext (because the lexicons are used in a way that breaks Locale::Maketext's negotiation which is based upon a file structure it expects on disk). The example system uses CGI::App. But, this is not required. My CGI::App inherets from "superclassMyApp.pm" (which itself inherets from CGI::Application) containing the following pieces of code: 1. A subclass for H::T's _cache_key method. This method retrieves the "$language" value that was passed into H::T's load_tmp call. It uses the value (something like "en-US") to make the cached template unique by path, filename and language. ==============================>>> CUT HERE <<<================================== #*************************************************************************** **** # _cache_key # # subclass of H::T's method so we can cache templates by language. #*************************************************************************** **** sub _cache_key { my $self = shift; my $options = $self->{options}; return $self->SUPER::_cache_key().$options->{language}; } ==============================>>> CUT HERE <<<================================== 2. A method named "prepare_page_for_language" which is called from every C::A "run_mode" that displays a page. This method: 2a. Contains the following fragment of code to load the template. Notice the "language =>" parameter. That's what feeds the above-mentioned overriden _cache_key method. ==============================>>> CUT HERE <<<================================== #--------------------------------------------------------------------------- ---- # Load the template with site-wide and page-specific filter. #--------------------------------------------------------------------------- ---- $self->{template} = $self->load_tmpl($page . '.html', filter => [ { sub => $filter, format => 'scalar' }, ], cache => 1, double_file_cache => 1, file_cache_dir => '/tmp', language => $self->{session}->{LANGUAGE}, # pass this for the custom _cache_key method ); ==============================>>> CUT HERE <<<================================== 2b. The filter referred to by the above "load_tmpl." The filter is defined immediately prior to the above fragment. By creating the filter inside the same "prepare_page_for_language" method, the anonymous subroutine will be within scope of all the variables in the method. The goal of the filter is to initialize a template as much as possible so that needless H::T re-evaluation does not occur. So that the cached template's dynamic content is truly part of the display-by-display state change. In the case of language translation, reevaluating a template's static text for each display could be significant. The filter deals with three distinct preprocessing steps: 1. Language translation that occurs for all site's pages, where the content is static (header, footer, navigation bar text, title text, etc.). Once these items are generated they will not change for as long as the page is cached and redisplayed. 2. Language translation that occurs for a specific page being loaded, where the content is static (captions, form titles, sub-area navigation link text). Similar to site-wide text, this will not change for as long as the page is cached and redisplayed. This text only exists on this specific page. The translation handle won't be used for other pages (unlike the static site-wide handle). 3. Page initialization that occurs for the specific page, but does not necessarily involve language translation. For example, A "ROBOTS" "NOINDEX" might be set using a page-specific initialization routine since, once this is set it remains this value (like language translation) for as long as the page remains cached. This routine might generate select/option list values so that the only thing that has to be re-evaluated (by H::T) is the "selected" attribute (without having to redo TMPL_LOOPs). The goal is to eliminate (while we're going to the trouble) stuff that H::T would have to superflously re-evaluate for each display. The targets of these three preprocessing steps are represented by <LANG_SITE NAME=blah>, <LANG_PAGE NAME=blah> and <INIT_PAGE NAME=blah> tags. The filter follows: ==============================>>> CUT HERE <<<================================== #--------------------------------------------------------------------------- ---- # Subroutine used by H::T. Must be defined within this CGI::App method (in order # to be within scope of the variables it accesses). #--------------------------------------------------------------------------- ---- my $filter = sub { my $text_ref = shift; $filter_fired = 1; # so we know a page was loaded after tmpl_load (below) #--------------------------------------------------------------------------- -- # Load the sitewide language-translation handle for static content if it # hasn't already been loaded. (After all the pages are loaded for a CGI::App # module this handle is deleted.) #--------------------------------------------------------------------------- -- if (!exists($self->{LH}{'_sitewide'}{'_static'}{$self->{session}->{LANGUAGE}})) { $self->new_LH('_sitewide', '_static'); } #--------------------------------------------------------------------------- -- # Perform sitewide translation. For every LANG_SITE tag, send the value to the # sitewide language-translation handle (static content). #--------------------------------------------------------------------------- -- $$text_ref =~ s#<LANG_SITE +NAME\=([^>]*)>#$self->{LH}{'_sitewide'}{'_static'}{$self->{session}->{LANGU AGE}}->maketext($1)#eg; #--------------------------------------------------------------------------- -- # Load the page-specific language translation handle for static content. # Process all "LANG_PAGE" tags. Also load the page-specific module for # initializing a template in ways beyond "LANG_PAGE" translation. # # (We have to test if this is not already loaded because H::T calls the filter # multiple times when it loades a template). #--------------------------------------------------------------------------- -- if (!exists($self->{LH}{$page}{'_static'}{$self->{session}->{LANGUAGE}})) { $self->new_LH($page, '_static'); if ($perform_page_init) { my $module = 'Static_page_init::' . $page; eval "require $module"; } } #--------------------------------------------------------------------------- -- # Perform page-specific translation. For every LANG_PAGE tag, send the value # to the page-specific language-translation handle (static content). #--------------------------------------------------------------------------- -- $$text_ref =~ s#<LANG_PAGE +NAME\=([^>]*)>#$self->{LH}{$page}{'_static'}{$self->{session}->{LANGUAGE}}- >maketext($1)#eg; #--------------------------------------------------------------------------- -- # Call the page-specific initialization routine. #--------------------------------------------------------------------------- -- if ($perform_page_init) { no strict "refs"; &{'Static_page_init::' . $page . '::set_static_values'}($text_ref, $self->{LH}{$page}{'_static'}{$self->{session}->{LANGUAGE}}); use strict "refs"; } #--------------------------------------------------------------------------- -- # Perform common page initialization. # 1. Set the navigation bar's "selected". # 2. If the page is not "main", set the "NO" in front of "INDEX". (In the case # of "main" the tag will be stripped and the page will be indexed.) # 3. Eliminate any unset INIT_PAGE tags. #--------------------------------------------------------------------------- -- $$text_ref =~ s#<INIT_PAGE +NAME=$hdr_nav_selected># class="selected"#g; if ($page ne 'main') { $$text_ref =~ s#<INIT_PAGE +NAME=HDR_ROBOTS_INDEX>#NO#g; } $$text_ref =~ s#<INIT_PAGE +NAME\=[^>]+>##g; }; ==============================>>> CUT HERE <<<================================== The filter sets a variable to let me know it was executed by "H::T". It's the only way I can know after the 'tmpl_load' if H::T performed processing for a new template, or reused a cached copy. 2c. The following fragment of code is placed after "tmpl_load." If the filter was executed, this piece of code will - Get rid of the page-specific language handle (and package) (since neither are expected to be used again unless H::T senses that it needs to load a template again to replace a cached copy). - Adds a pagename to a hash so we can determine when all the pages a C::A module might display have been loaded (for a language). - Get rid of the site-wide language handle (and package) if all the pages have been loaded. - Loads the page-specific langauge handle for dynamic content (msgs, etc.) This is used as long as the page remains cached. ==============================>>> CUT HERE <<<================================== #--------------------------------------------------------------------------- ---- # After loading a page determine if the filter executed. If it did, perform # post-initialization processing. #--------------------------------------------------------------------------- ---- if ($filter_fired) { $filter_fired = 0; my $module = $self->{session}->{LANGUAGE}; $module =~ s/\-/_/; $module = lc($module); #--------------------------------------------------------------------------- -- # Delete the page-specific language-translation handle for static content, and # the module for page-specific initialization. After a page is loaded and # cached these aren't used any longer. #--------------------------------------------------------------------------- -- delete($self->{LH}{$page}{'_static'}{$self->{session}->{LANGUAGE}}); delete_package('lang::' . $page . '::_static::' . $module); delete_package('Static_page_init::' . $page); #--------------------------------------------------------------------------- -- # Add the page-name to a hash of page-names known to have been loaded. #--------------------------------------------------------------------------- -- ${$loaded_pages{$self->{session}->{LANGUAGE}}}{$page} = 1; #--------------------------------------------------------------------------- -- # If the total number of pages displayable have been loaded, delete the site- # wide language-translation handle for static content. After all pages are # loaded and cached, this isn't needed any longer (unless H::T refreshes # the cache, when it will be reloaded in the filter and deleted here, again.) #--------------------------------------------------------------------------- -- if (keys %{$loaded_pages{$self->{session}->{LANGUAGE}}} == $max_pages) { delete($self->{LH}{'_sitewide'}{'_static'}{$self->{session}->{LANGUAGE}}); delete_package('lang::_sitewide::_static::' . $module); } #--------------------------------------------------------------------------- -- # Load the page's language-translation handle for dynamic content. We keep # this for each redisplay. (Test if it's already loaded. The cached template # may have been refreshed causing the filter to fire. No need to reload the # handle). #--------------------------------------------------------------------------- -- if (!exists($self->{LH}{$page}{'_dynamic'}{$self->{session}->{LANGUAGE}})) { $self->new_LH($page, '_dynamic'); } } # end filter fired ==============================>>> CUT HERE <<<================================== That's all there is to it. For additional clarification 1. The superclassMyApp.pm (which my C::A modules inheret from) contains: - The following relevant statements: use base 'CGI::Application'; use strict; use Symbol qw(delete_package); - The following "our" variables: our ($max_pages, $perform_page_init, $hdr_nav_selected); our (%loaded_pages); Those variables are filled in by subclassing C::A's "cgiapp_init" and calling it with cgiapp_init(2, 0, 'HDR_NAV_MAIN'); - The prepare_page_for_language method, which is called from any C::A runmode as: $self->prepare_page_for_language('main'); where 'main' is the page to load. 2. The filter checks if the language handles have been created before creating them. It may not be intuitive, but H::T executes the filter multiple times when it loads the template. Therefore, it can't be assumed that the filter is being exeucted for the first or last time (for a page). The conditional is used to determine if it's necessary to load the language handles. And, the "filter_fired" variable is used to determine afterwards if anything happened (so cleanup can occur). 3. The subroutine to create language handles (referenced throughout the above sample code) looks like the following. It is contained within superclassMyApp.pm. It loads Locale::Maketext language handles in a more granular manner than L::M expects. For this reason, it loads the package and performs a "new" instead of "get_handle" (which performs language negotiation. I use use "I18N::AcceptLanguage" for that.) ==============================>>> CUT HERE <<<================================== #*************************************************************************** **** # new_LH # # Common process to create a Locale::Maketext handle. We create 'sitewide', # 'page::_static' and 'page::_dynamic'. We use Maketext's "->new" method because # it has an inefficient language negotiation feature. #*************************************************************************** **** sub new_LH { my $self = shift; my ($page, $type) = @_; # Start: use maketext's -> new method (bypass negotiation) my $module = $self->{session}->{LANGUAGE}; $module =~ s/\-/_/; $module = 'lang::' . $page . '::' . $type . '::' . lc($module); eval "require $module"; $self->{LH}{$page}{$type}{$self->{session}->{LANGUAGE}} = $module->new(); # End: use maketext's -> new method (bypass negotiation) return; } ==============================>>> CUT HERE <<<================================== - The language modules (lexicons) are in a directory structure as follows: ~/lang/_sitewide/_static/en_us ~/lang/main/_static/en_us ~/lang/main/_dynamic/en_us ~/lang/main/help/_static/en_us # examples of lexicons for sub-pages, in ~/lang/main/help/_dynamic/en_us # which case $page is "main::help" Common translation materials can be shared by using something like this in a language module (lexicon) $shared_sidenav = do '/home/fm/bin/lang/profile/static/shared/sidenav/en_us.include'; Which refers to a file containing: ==============================>>> CUT HERE <<<================================== { sidenav_text => (['Area 1', 'Area 2', 'Area 3', 'Area 4', 'Area 5', 'Area 6', 'Area 7']), sidenav_link_title => (['Go to area 1.', 'Go to area 2.', 'Go to area 3.', 'Go to area 4.', 'Go to area 5.', 'Go to area 6.', 'Go to area 7.']) } ==============================>>> CUT HERE <<<================================== The lexicon will then relate these two tags: <LANG_PAGE NAME=SIDENAV_TEXT> <LANG_PAGE NAME=SIDENAV_TEXT> to text this way: 'SIDENAV_TEXT' => ${$shared_sidenav}{sidenav_text}, 'SIDENAV_LINK_TITLE' => ${$shared_sidenav}{sidenav_link_title}, And return an array ref of the same 7 items through different lexicons (specific to different pages where the sidenav text is needed). 4. The page-specific initialization modules are stored in the file location such as: ~/Static_page_init/main.pm ~/Static_page_init/main/help.pm # an example of a sub-page Common processing (like generating the side-navigation links) can be shared by required libraries. === end |
From: Thomas N. <th...@te...> - 2005-01-21 21:59:54
|
Thanks for the answer..gives me something to look into. I dont think i've really got a grip on hashes..not to mention an array of hashes..but now i have a place to start. The tmpl example was perfect! Once again many thanks from a frozen north. Thomas 2005-01-21 kl. 21.50 skrev Cees Hek: > Thomas Nyman wrote: >> push @{$rows}, $_ while $_ = $sth->fetchrow_hashref(); >> i figured..hey this is a hash so i can use >> if (exists $rows{$fornamn}) etc .. but alas no. apparently push gets >> an array and not a hash if I now get it correctly. > > Actually, what you have is an array of hashes. So $rows contains a > reference to an array, and you are pushing references to hashes onto > that array. So $rows{$fornamn} doesn't make sense, since $rows is an > array reference. What you want is $rows->[0]->{$fornamn}, which will > look for the hash key $fornamn in hash that exists in the first (0th) > entry of the array. > > You can also simplify your while statement above by using some DBI > tricks. This will do the same thing as your while statement above: > > $rows = $sth->fetchall_arrayref({}); > > That will give you an array of hashrefs without needing to worry about > looping and pushing the values individually. > >> Anyway, i was thinking, maybe i can set a conditional in the template >> so that depending on the value of a row i can output different html >> code. What i need is to alert the uses that his or her query resulted >> in no hits. I tried searching in the list but i'm not quite sure what >> to search for. I would very much appreciate it if someone could help >> me in the right direction. > > You should be able to check for the existence of $rows in the template > to see if it contains any values. And you can also do conditionals on > the hash values as well: > > <TMPL_IF rows> > <TMPL_LOOP rows> > <TMPL_IF fornamn> > <TMPL_VAR fornamn><BR /> > <TMPL_ELSE> > no value > </TMPL_IF> > </TMPL_LOOP> > <TMPL_ELSE> > No rows returned > </TMPL_IF> > > Cheers, > > Cees |
From: Cees H. <ce...@si...> - 2005-01-21 20:51:23
|
Thomas Nyman wrote: > push @{$rows}, $_ while $_ = $sth->fetchrow_hashref(); > > i figured..hey this is a hash so i can use > > if (exists $rows{$fornamn}) etc .. but alas no. apparently push gets an > array and not a hash if I now get it correctly. Actually, what you have is an array of hashes. So $rows contains a reference to an array, and you are pushing references to hashes onto that array. So $rows{$fornamn} doesn't make sense, since $rows is an array reference. What you want is $rows->[0]->{$fornamn}, which will look for the hash key $fornamn in hash that exists in the first (0th) entry of the array. You can also simplify your while statement above by using some DBI tricks. This will do the same thing as your while statement above: $rows = $sth->fetchall_arrayref({}); That will give you an array of hashrefs without needing to worry about looping and pushing the values individually. > Anyway, i was thinking, maybe i can set a conditional in the template so > that depending on the value of a row i can output different html code. > What i need is to alert the uses that his or her query resulted in no > hits. I tried searching in the list but i'm not quite sure what to > search for. I would very much appreciate it if someone could help me in > the right direction. You should be able to check for the existence of $rows in the template to see if it contains any values. And you can also do conditionals on the hash values as well: <TMPL_IF rows> <TMPL_LOOP rows> <TMPL_IF fornamn> <TMPL_VAR fornamn><BR /> <TMPL_ELSE> no value </TMPL_IF> </TMPL_LOOP> <TMPL_ELSE> No rows returned </TMPL_IF> Cheers, Cees |
From: Thomas N. <th...@te...> - 2005-01-21 10:26:22
|
Hi all I'm new to html-template and fairly new to perl too. Anyway I have managed to set up a html form that inputs certain values to a perlscript which in turn queries an mysql database and then outputs the results using html:template and it works very nicely with one exception. If i enter a value in the form that is not in the database i receive an error. Since i use push @{$rows}, $_ while $_ = $sth->fetchrow_hashref(); i figured..hey this is a hash so i can use if (exists $rows{$fornamn}) etc .. but alas no. apparently push gets an array and not a hash if I now get it correctly. Anyway, i was thinking, maybe i can set a conditional in the template so that depending on the value of a row i can output different html code. What i need is to alert the uses that his or her query resulted in no hits. I tried searching in the list but i'm not quite sure what to search for. I would very much appreciate it if someone could help me in the right direction. Thanks |
From: Peter L. <pe...@pe...> - 2005-01-20 21:28:00
|
We're very pleased to announce that Krang v1.101 is now available. Notable changes in this release: * Fixes to the session caching improvements that were added in the 1.100 release - bulk-edit now works again, as does search-form clearing. * bin/krang_publish now has a --not_on_desk option, to limit publishing of content to those items not sitting on a desk within the CMS. * Thumbnailing of extreme aspect-ratio images (e.g. 200x5 pixels) has been fixed. * Improved support for MySQL 4.1.x - Krang should now work fine on MySQL 4.1.8 (the first "stable" release) or higher. * Services that run on unprivileged ports no longer use sudo on startup. For more information about Krang, visit the Krang website: http://krang.sourceforge.net/ There you can download Krang, view screenshots, read documentation, join our mailing-lists and access the CVS tree. Detailed change-log here: http://krang.sf.net/docs/changelog.html Krang is an Open Source web-publisher / content-management system designed for large-scale magazine-style websites. It is a 100% Perl application using Apache/mod_perl and MySQL, as well as numerous CPAN modules. Krang provides a powerful and easy to use story and media editing environment for magazine editors, as well as a complete template development environment for web designers. On the back-end, Perl programmers can customize Krang to control the data entered in the story editor and add code to drive the templates to build output. Krang can be enhanced with add-ons containing new skins and other new features. Krang easily handles large data sets and can manage multiple websites in a single installation. - the Krang team ---- Peter Leonard pe...@pe... |
From: Tobias G. <lis...@e-...> - 2005-01-20 00:08:05
|
Michael Lloyd wrote: > I wrote the following filter for that reason (and also WYSIWYG editors), but Ah... I didn't thought of implementing this as a filter for Html::Template. This might have some impact on the performance, but I think it's worth a try. Thanks for the hint! Now I just need a nice tool to translate the XHTML using a po-file. The only thing I know of is xml2po (Python). But I think this shouldn't be hard to do in Perl too. Tobias |
From: Michael L. <mi...@go...> - 2005-01-19 18:16:47
|
I wrote the following filter for that reason (and also WYSIWYG editors), but didn't get any feedback on whether this was worth trying to integrate. sub filter_template { my $text_ref = shift @_; $$text_ref =~ s/\{%(.*?)%\}/<tmpl_var name="$1">/g; } It seems that HTML/XHTML validation should be possible by default. I considered using *vanguard_compatibility_mode* flag but since I know nothing of vangard or how long it would remain compatible.... -----Original Message----- From: htm...@li... [mailto:htm...@li...] On Behalf Of Tobias Grimm Sent: Tuesday, January 18, 2005 6:51 PM To: htm...@li... Subject: [htmltmpl] Valid XHTML templates Hi! Is there any way to use a valid XHTML document as template? As far as I tried this seems to be not possible. e.g.: [1] valid XHTML, working: <title><tmpl_var name="title"/></title> [2] valid XHTML, but not working: <option value="<tmpl_var name>"><tmpl_var name="name"/></option> [3] invalid XHTML, not working either <option value="<tmpl_var name>"><tmpl_var name="name"/></option> [4] invalid XHTML, but working (just removed the slash, this worked in [1]!) <option value="<tmpl_var name>"><tmpl_var name="name"></option> The template needs to be valid xml, to be processed for translations. My current solution is to transform the valid XHTML to an invalid template that HTML::Template can deal with. But I would prefer feeding HTML::Template directly with the XHTML file. Any ideas? Someone mentioned a patch to use {%TMPL_xxx%} instead of <TMPL_xxx>. Is there already a working version of this patch available? bye, Tobias ------------------------------------------------------- The SF.Net email is sponsored by: Beat the post-holiday blues Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek. It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt _______________________________________________ Html-template-users mailing list Htm...@li... https://lists.sourceforge.net/lists/listinfo/html-template-users |
From: Mark F. <mar...@ea...> - 2005-01-19 05:37:22
|
From: "Mathew Robertson" <mat...@re...> > >provide a different template for each language I initially went this way. But, I didn't like duplicating page structure. I found that I *really* like to keep everything in Locale::Maketext lexicons. But, the downsides are: 1. The Locale::Maketext is geared towards one large project. Not small pages. The more I moved constant/static text out of templates, the more the lexicon grew with text individual C::A modules would never need. That's a lot to load. 2. I have a lot of TMPL_VARs to replace with Locale::Maketext calls. Which leads me to want to perform an initialization of the template with replacement of text that would have more naturally been in the template if it were not for language differences. 3. As those one-time TMPL_VARs grow in number, they worry me that they add to the re-evaluation of the template. Even *if* I go through an initialization process to perform all the PARAMs only once, they'll still be re-evaluated with every "->output." (Steve's suggestion will eliminate that concern). 4. Paragraph text is a little clumsy in Locale::Maketext. I'm tempted to TMPL_INCLUDE the fragments. But, I have to get creative to specify language-specific fragments because TMPL_INCLUDE doesn't handle a variable filename. To get around #1, I use Locale::Maketext in a way not intended. Instead of putting all my language into one "en_us" file within a single directory, I've created individual subdirectories mirroring the structure of the pages. In the lowest level is the "sitewide" language file. It is loaded and applied used for all pages for the site. Language files for specific pages are in subdirectories for each page. Like: /L10N/lang/sitewide/en-us /"/"/page-a/dynamic/en-us /"/"/page-a/static/en-us /"/"/page-a/sub-page-1/dynamic/en-us /"/"/page-a/sub-page-1/static/en-us /"/"/page-b/dynamic/en-us /"/"/page-b/static/en-us In my CGI::App "prerun" I detect the page hasn't been loaded yet, load the Locale::Maketext for sitewide (if it's not loaded yet), and the page-specific "static" language file. I can apply the page-specific static translation and discard the handle. I load the dynamic language file and keep that handle in a hash for as long as I keep the partially-processed page in a hash. This works really well for me. I only load as much Locale::Maktext lexicon as I need for a page. I only keep as much as I need for display-by-display changes. The "static" lexicons are dropped immediately after first-time use. The "sitewide" handle can be dropped when it is determined all the pages for a CGI::App module have been loaded. Because of the nature of Locale::Maketext's lexicon objects, I can put common language structures subroutines that can be required by all the lexicons that need it. One problem is that Locale::Maketext expects language lexicons in a single directory and uses them for determining what languages are available. So, I do my own negotiation of which language to use and call L::M's "->new" method instead of "->get_handle." I'm happier keeping the negitiation of language outside of L::M. This works really good! It's just the three things I mentioned regarding H::T. 1. It would work better if H::T had a way to perform an "internal_output" and replace its internal template with whatever the result of the "output" was (without eliminating empty tags). 2. If evaluations of TMPL_VARs could re-evaluate (maybe based upon an attribute on the VAR) so that a VAR containing a VAR could be processed. 3. If TMPL_INCLUDE was capable of resolving a filename like "my_text.<TMPL_VAR NAME=LANG>". This would let a single template be used for all languages. A lot of heavy lifting could be done as part of the page initialization. The page could then be minimally processed for as long as it remains in the cache (either H::T's or the application's own hash of templates like I'm doing). Steve's suggestion (to run a template through, then regex some munged tags) might be a good way to get around these things. Mark |
From: Mathew R. <mat...@re...> - 2005-01-19 03:08:12
|
> The three things I've found that make multi-language processing = difficult > with H::T are: >=20 > 1. One-time evaluation of a template's page-specific vars (so that > subsequent displays can deal only in truly variable evaluations). > 2. No way to say <tmpl_include name=3D"constant_text_<tmpl_var = name=3DLANG>"> to > use language-specific text determined at run time. > 3. No way to recurse variables which may have been evaluated with text = that > contains variables. >=20 > #2 and 3 are troubling because, if I can't pull in fragments of a page = (for > a language), then I'm likely to use "Locale::Maketext" to provide me = with > what may be lengthy fragments. If the fragments contain markup (like a > link), then I'm stuck because the fragment's link will contain an = attribute: > "title=3D<TMPL_VAR NAME=3DLINK_TITLE_TEXT>" which will not be = evaluated. >=20 > Feeding ->output back into new H::T objects can get around a lot of = this. It > would be a lot easier if those 3 features were available. They don't = seem > like they would require too much kludging. FWIW, the company I work for uses H::T for page generation, and we = handle an arbitrary number of languages. Currently we have the product = translated into 4 different languages, and we have two more on the way. = H::T is used in combination with the Locale::MakePhrase package.... = however, I use a modified H::T.... The reason that I made a custom package of H::T was that the only = solutions that I could see to make language translations work was: a) provide a different template for each language, then use the = appropriate one based on users' language b) use H::T::E with a callback function so that static template strings = could run though the translation engine b) modify H::T so that it supports custom TMPL_xxx tags so that static = template strings could run through the translation engine Points (a) and (b) require no changes to H::T, and I can say from = experience that it works reasonably well. However, I found: <TMPL_VAR EXPR=3D"catalog('some static string')">=20 to be more nasty than: <TMPL_CATALOG "some static string"> so I chose to modify H::T. In the process, I added some extra features = to H::T. If you need more info on how I do language translations, let me know... Mathew |