将 CatalystX::I18N::Maketext 添加到我的 DBIC 模式

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

抱歉,我以为我是在 之后到达那里的,但是我只能从一个单独的 PL 文件访问。我现在正试图确保我可以使用模式加载来加载词典,而不是每次我在结果/结果集中调用方法时 类(这似乎是一个非常糟糕的想法)。

因此,为了尝试给出一个完整的画面,这是我最终开始工作的脚本:

#!/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 $config->{$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;

这是我的 TopTable::Maketext:

package TopTable::Maketext;

use strict;
use warnings;
use parent qw(CatalystX::I18N::Maketext);

1;

现在这是我的架构文件:

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:44
# 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;

恐怕我是一个 Moose 新手,但相信如果我添加一个 'lang' 属性和一个设置所有这些的构建器方法,我就可以从我的数据库方法中访问它:

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:44
# 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 $config->{$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;

然而,这不起作用 - 'lang' 方法是可访问的,但 returns undef - 我已将此作为测试添加到我的结果集方法之一中: $logger->( "debug", $self->result_source->schema->lang->maketext("menu.title.league-tables", "Division Three") ); 但这给出了一个错误: [error] Caught exception in TopTable::Controller::Admin::Bans->process_form "Can't call method "maketext" on an undefined value at D:\Personal\Dev\Web\www.mkttl.co.uk\TopTable\lib/TopTable/Schema/ResultSet/Ban.pm line 88."

感谢任何建议,非常感谢!我希望我已经提供了足够的信息来了解发生了什么。

在@simbabque 非常友善和耐心的帮助下,我设法解决了这个问题。

simbabque 建议我将 lang 属性设置为 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 $config->{$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" );
}

这有效,但产生了消息 Lexicon has already been loaded for TopTable::Maketext,这表明 Catalyst 加载词典是一个全局操作,所以实际上我能够将 _set_maketext 方法归结为:

sub _set_maketext {
  return TopTable::Maketext->get_handle( "en_GB" );
}

到目前为止一切顺利,但我随后不得不弄清楚如何将用户的语言环境设置到对 get_handle() 的调用中。

再次,在 simbabque 的帮助下,我已经设法在模型中使用 ACCEPT_CONTEXT sub(注意 if ref( $c ) eq "TopTable" 检查 - 正如评论所说,模型似乎在我的代码开始之前,作为实例化的一部分被 Catalyst 调用,在这些情况下,$c 是字符串“TopTable”,而不是 TopTable 对象的引用,因此我们不能在其上调用 ->locale ):

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 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.
  $self->schema->_set_maketext( TopTable::Maketext->get_handle( $c->locale ) ) if ref( $c ) eq "TopTable";
  return $self;
}

1;

我这样更改了架构:

use TopTable::Maketext;

has "lang" => (
  is => "ro",
  isa => "TopTable::Maketext",
  writer => "_set_maketext",
);

现在一切正常,simbabque 的帮助非常宝贵!