Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Adding CatalystX::I18N::Maketext to my DBIC schema

by mkchris (Sexton)
on Jan 23, 2022 at 22:56 UTC ( [id://11140755]=perlquestion: print w/replies, xml ) Need Help??

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

Hello folks - sorry, I thought I had got there after my last post, however I only got as far as accessing from a separate PL file. I'm now trying to ensure I can load the lexicon with the schema load and not everytime I call a method in my result / resultset classes (which seems like a really terrible idea). So to try and give a complete picture, here's the script I eventually got to work:
#!/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; # Load the Catalyst config my $tt_config = Config::ZOMG->new( name => "TopTable" ); my $config_hash = $tt_config->load; # Load the locales from the config my (@locales, %inheritance, $config); $config = $config_hash->{I18N}{locales}; foreach my $locale (keys %$config) { push(@locales, $locale); $inheritance{$locale} = $config->{$locale}{inherits} if defined $con +fig->{$locale}{inherits}; } # Get the directory where the messages are defined my $dir = Path::Class::Dir->new( "$Bin/..", "root", "locale" ); # Load the lexicon TopTable::Maketext->load_lexicon( locales => \@locales, directories => [$dir], gettext_style => 1, inheritance => \%inheritance, ); my $lang = TopTable::Maketext->get_handle( "en_GB" ); printf "%s\n", $lang->maketext( "menu.title.league-tables", "Division +Three" ); 1;
Here's my TopTable::Maketext:
package TopTable::Maketext; use strict; use warnings; use parent qw(CatalystX::I18N::Maketext); 1;
Now here's my schema file:
use utf8; package TopTable::Schema; # Created by DBIx::Class::Schema::Loader # DO NOT MODIFY THE FIRST PART OF THIS FILE use Moose; use MooseX::MarkAsMethods autoclean => 1; extends 'DBIx::Class::Schema'; __PACKAGE__->load_namespaces; # Created by DBIx::Class::Schema::Loader v0.07037 @ 2013-12-03 11:04:4 +4 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uMxbZipkwEqVJYByeZhY5Q # You can replace this text with custom code or comments, and it will +be preserved on regeneration __PACKAGE__->meta->make_immutable(inline_constructor => 0); 1;
I'm very much a Moose novice I'm afraid, but believed if I added a 'lang' attribute with a builder method that sets all that up, I could then access that from my DB methods:
use utf8; package TopTable::Schema; # Created by DBIx::Class::Schema::Loader # DO NOT MODIFY THE FIRST PART OF THIS FILE use Moose; use MooseX::MarkAsMethods autoclean => 1; extends 'DBIx::Class::Schema'; __PACKAGE__->load_namespaces; # Created by DBIx::Class::Schema::Loader v0.07037 @ 2013-12-03 11:04:4 +4 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uMxbZipkwEqVJYByeZhY5Q use FindBin qw( $Bin ); use TopTable::Maketext; has "lang" => ( is => "ro", isa => "TopTable::Maketext", builder => "_set_maketext", required => 1, ); sub _set_maketext { my ( $self ) = @_; my $class = $self->class; my $app = $self->_app; my (@locales, %inheritance); my $config = $app->config->{I18N}{locales}; $app->log->debug( sprintf( "app: %s, class: %s", $app, $class ) ); printf( "app: %s, class: %s", $app, $class ); foreach my $locale (keys %$config) { push(@locales, $locale); $inheritance{$locale} = $config->{$locale}{inherits} if defined $c +onfig->{$locale}{inherits}; } my $dir = Path::Class::Dir->new( "$Bin/..", "root", "locale" ); TopTable::Maketext->load_lexicon( locales => \@locales, directories => [$dir], gettext_style => 1, inheritance => \%inheritance, ); return TopTable::Maketext->get_handle( "en_GB" ); } # You can replace this text with custom code or comments, and it will +be preserved on regeneration __PACKAGE__->meta->make_immutable(inline_constructor => 0); 1;
This however, doesn't work - the 'lang' method is accessible, but returns undef - I have added this as a test in one of my resultset methods: $logger->( "debug", $self->result_source->schema->lang->maketext("menu.title.league-tables", "Division Three") ); But this gives an error:
[error] Caught exception in TopTable::Controller::Admin::Bans->process +_form "Can't call method "maketext" on an undefined value at D:\Perso +nal\Dev\Web\www.mkttl.co.uk\TopTable\lib/TopTable/Schema/ResultSet/Ba +n.pm line 88."
Grateful for any advice, thanks so much! I hope I've provided enough to see what's going on.

Replies are listed 'Best First'.
Re: Adding CatalystX::I18N::Maketext to my DBIC schema
by mkchris (Sexton) on Jan 27, 2022 at 14:31 UTC
    Greetings! I have, with the very kind assistance of someone on Stack Overflow, sorted this, so am posting the solution here. I have since learned that people like that it's disclosed if a question is cross-posted here and at SO, so apologies that I didn't do this - I know for future questions. I first set the lang attribute to lazy:
    use FindBin qw( $Bin ); use TopTable::Maketext; has "lang" => ( is => "ro", isa => "TopTable::Maketext", builder => "_set_maketext", lazy => 1, ); sub _set_maketext { my ( $self ) = @_; my $class = $self->class; my $app = $self->_app; my (@locales, %inheritance); my $config = $app->config->{I18N}{locales}; $app->log->debug( sprintf( "app: %s, class: %s", $app, $class ) ); printf( "app: %s, class: %s", $app, $class ); foreach my $locale (keys %$config) { push(@locales, $locale); $inheritance{$locale} = $config->{$locale}{inherits} if defined $c +onfig->{$locale}{inherits}; } my $dir = Path::Class::Dir->new( "$Bin/..", "root", "locale" ); TopTable::Maketext->load_lexicon( locales => \@locales, directories => [$dir], gettext_style => 1, inheritance => \%inheritance, ); return TopTable::Maketext->get_handle( "en_GB" ); }
    This worked, but produced the message Lexicon has already been loaded for TopTable::Maketext, which suggested Catalyst loading the lexicon was a global action, so actually I was able to get the _set_maketext method down to:
    sub _set_maketext { return TopTable::Maketext->get_handle( "en_GB" ); }
    So far so good, but I then had to work out how to get the user's locale into the call to get_handle(). I have managed to get this working using an ACCEPT_CONTEXT sub in the model (note the if ref( $c ) eq "TopTable" check - as the comment says, the model seems to get called by Catalyst as part of the instantiation, before my code kicks in, and in these cases, $c is the string "TopTable", not a ref to the TopTable object so we can't call ->locale on it):
    package TopTable::Model::DB; use strict; use base 'Catalyst::Model::DBIC::Schema'; __PACKAGE__->config( schema_class => 'TopTable::Schema', connect_info => { dsn => 'dbi:mysql:toptable', user => '', password => '', } ); use TopTable::Maketext; sub ACCEPT_CONTEXT { my ( $self, $c ) = @_; # We have to check the ref of $c here because this model seems to ge +t called by Catalyst as part of the instantiation, before my code kic +ks in # and in these cases, $c is the string "TopTable", not a ref to the +TopTable object. $self->schema->_set_maketext( TopTable::Maketext->get_handle( $c->lo +cale ) ) if ref( $c ) eq "TopTable"; return $self; } 1;
    I've changed the schema thus:
    use TopTable::Maketext; has "lang" => ( is => "ro", isa => "TopTable::Maketext", writer => "_set_maketext", );
    This is now working as expected, hurrah!
      I have since learned that people like that it's disclosed if a question is cross-posted here and at SO, so apologies that I didn't do this - I know for future questions.

      Thanks for following up here and for your apologies, which I accept on behalf of all of us. In case it isn't obvious, this is not just a PerlMonksism nor an SO-ism. Anytime you ask the same question in multiple places on the web it is only polite to inform the total strangers whom you are asking to provide you with expert advice for free that the question has been asked elsewhere too - and always include the links. There is rarely any point in someone answering the question if it has already been answered several times over elsewhere.


      🦛

        Makes absolutely perfect sense and now that you put it like that, it seems obvious! Thanks for your patience.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11140755]
Approved by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-18 21:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found