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!