http://qs1969.pair.com?node_id=11140649

mkchris has asked for the wisdom of the Perl Monks concerning the following question:

Hi everyone - apologies, I'll try and make this as clear as I can. I have a Catalyst app that has internationalisation via CatalystX::I18N. This includes the ability to call $c->maketext($msgid, $params). Essentially, I want to be able to use these in my DB model so that I can generate response messages in the relevant language. The only way I have thought of to do this so far (don't shoot me, I know it's not recommended!) is by passing $c->maketext as part of the parameters into the method I'm calling:
$c->model("DB::$resultset")->do_something({ language => sub{ $c->maketext( @_ ); } });
What I would like is to be able to use a maketext model (which seems to be available via CatalystX::I18N::Model::Maketext) so that I can use App::Maketext in my result and resultset classes and then use ->maketext() directly in those, if that makes sense? I have set this up and can debug the following:
$c->log->debug( sprintf( "maketext: '%s'", $c->maketext("menu.title. +news") ) ); $c->log->debug( sprintf( "model maketext: '%s'", $c->model("maketext") +->maketext("menu.title.news") ) );
Both of these give the same output from the function calls:
[debug] maketext: 'News Index' [debug] model maketext: 'News Index'
However, I don't seem to be able to call this from outside Catalyst (which I need to be able to call it from the DB model) - I've run up a little test script and I was initially trying to load the config from my app's config file:
#!/usr/bin/perl use strict; use warnings; use FindBin qw( $Bin ); use lib "$Bin/../lib"; use App::Maketext; use Config::ZOMG; my $config = Config::ZOMG->new( name => 'App' ); my $config_hash = $config->load; my $maketext_info = $config_hash->{"Model::Maketext"}; my $lang = TopTable::Maketext->new($maketext_info); printf "%s\n", $lang->maketext( "menu.title.news" );
However, I get the foillowing response:
maketext doesn't know how to say: menu.title.news as needed at bin\maketext-demo.pl line 16.
Then I thought I'd pass in the directories manually (at least for the time being):
my $dir = Path::Class::Dir->new( "$Bin/..", "root", "locale" ); my $lang = TopTable::Maketext->new(directories => $dir);
Finally I tried passing in the locale as well:
my $dir = Path::Class::Dir->new( "$Bin/..", "root", "locale" ); my $lang = TopTable::Maketext->new(directories => $dir, locales => "en +-GB");
All of which give the same result. I am sure I'm missing something about the way it all hangs together and would be hugely greatful for any pointers that could be given! Many thanks in advance.

Replies are listed 'Best First'.
Re: Catalyst: accessing maketext from a model
by kcott (Archbishop) on Jan 21, 2022 at 13:35 UTC

    G'day mkchris,

    I was unable to find TopTable::Maketext which you've used here and in your reply. I also don't know where bin\maketext-demo.pl is located (also used in both nodes). Please provide links to those.

    I've front-paged this post to hopefully give it a wider audience: weekend attendance is often less than during the week and posts can drop off the radar.

    — Ken

      Hello kcott, thanks so much for taking the time to reply and to put my post on the front page! Apologies, I should have been clearer - TopTable is my Catalyst project, so effectively TopTable::Maketext is the equivalent of MyApp::Maketext, referred to in CatalystX::I18N::Maketext. maketext-demo.pl is just a file I'm calling manually to try and test it - the contents of this file and output from it are detailed in my reply to the original post.
Re: Catalyst: accessing maketext from a model
by mkchris (Sexton) on Jan 21, 2022 at 12:35 UTC
    Okay, doing a bit more digging: According to the CatalystX::I18N docs, CatalystX::I18N::Maketext is a 'Helpful wrapper around Locale::Maketext. Can also be used outside of Catalyst'. I have MyApp::Maketext setup as directed:
    package MyApp::Maketext; use strict; use warnings; use parent qw(CatalystX::I18N::Maketext); 1;
    I have a little test script running, the setup for which is this:
    #!/usr/bin/perl use strict; use warnings; use FindBin qw( $Bin ); use lib "$Bin/../lib"; use TopTable::Maketext; use Path::Class::Dir; my $dir = Path::Class::Dir->new( "$Bin/..", "root", "locale" ); TopTable::Maketext->load_lexicon( locales => ["en_GB"], # Required directories => [$dir], # Required gettext_style => 0, # Optional, Default 1 );
    I am then trying two different ways to get a handle to the maketext() method:
    my $lang = TopTable::Maketext->get_handle; printf "%s\n", $lang->maketext( "menu.title.news" );
    Gives the following result: Can't call method "maketext" on an undefined value at bin\maketext-demo.pl line 23. If I swap ->get_handle to ->new:
    my $lang = TopTable::Maketext->new; printf "%s\n", $lang->maketext( "menu.title.news" );
    I get the following:
    maketext doesn't know how to say: menu.title.news as needed at bin\maketext-demo.pl line 23.
    I'm at a bit of a loss as to what to try next! Thank you so much in advance for any pointers anyone can give.
Re: Catalyst: accessing maketext from a model
by mkchris (Sexton) on Jan 22, 2022 at 00:29 UTC
    Hi everyone - I have finally got my head around this - this is the code that eventually worked:
    #!/usr/bin/perl use strict; use warnings; use FindBin qw( $Bin ); use lib "$Bin/../lib"; use Data::Dumper::Concise; use TopTable::Maketext; use Config::ZOMG; use Path::Class::Dir; my $tt_config = Config::ZOMG->new( name => 'TopTable' ); my $config_hash = $tt_config->load; my (@locales, %inhertiance, $config); $config = $config_hash->{I18N}{locales}; foreach my $locale (keys %$config) { push(@locales, $locale); $inhertiance{$locale} = $config->{$locale}{inherits} if defined $con +fig->{$locale}{inherits}; } my $dir = Path::Class::Dir->new( "$Bin/..", "root", "locale" ); TopTable::Maketext->load_lexicon( locales => \@locales, directories => [$dir], gettext_style => 1, inheritance => \%inhertiance, ); my $lang = TopTable::Maketext->get_handle( "en_GB" ); printf "%s\n", $lang->maketext( "menu.title.league-tables", "Division +Three" ); 1;
    This gives the correct value of:
    League Tables for Division Three
    Thank you for putting up with me spamming here!