Mercurial > pub > Impl
view Lib/IMPL/Resources/Strings.pm @ 250:129e48bb5afb
DOM refactoring
ObjectToDOM methods are virtual
QueryToDOM uses inflators
Fixed transform for the complex values in the ObjectToDOM
QueryToDOM doesn't allow to use complex values (HASHes) as values for nodes (overpost problem)
author | sergey |
---|---|
date | Wed, 07 Nov 2012 04:17:53 +0400 |
parents | 7c517134c42f |
children | bbc0da7ef90e |
line wrap: on
line source
use strict; use warnings; package IMPL::Resources::Strings; use File::Spec; use List::Util qw(first); use IMPL::Resources::Format qw(FormatMessage); our $Locale ||= 'default'; our $Encoding ||= 'utf-8'; our @Locations; sub import { my ($self,$refStrings,%options) = @_; no strict 'refs'; my $class = caller; if (ref $refStrings eq 'HASH') { my %map; while(my ($name,$format) = each %$refStrings) { $map{default}{$name} = $format; *{"${class}::$name"} = sub { my $args = @_ == 1 ? shift : { @_ }; return _FormatMapMessage($class,$name,\%map,$Locale,$args); } } } } sub _FormatMapMessage { my ($class,$msg,$map,$locale,$args) = @_; if (not exists $map->{$locale} ) { $map->{$locale} = LoadStrings($class,$locale); } return FormatMessage( ($map->{$locale} || $map->{default})->{$msg}, $args ); } sub LoadStrings { my ($class,$locale) = @_; # Foo::Bar -> ('Foo','Bar') my @classNamespace = split /::/,$class; my $classShortName = pop @classNamespace; # Foo::Bar -> 'Foo/Bar.pm' my $classModuleName = File::Spec->catfile(@classNamespace,"${classShortName}.pm"); # 'Foo/Bar.pm' -> '/full/path/to/Foo/Bar.pm' my $fullModulePath = first { -f } map( File::Spec->catfile($_,$classModuleName), @INC ); my @ways = map { my @path = ($_); push @path,$Locale; File::Spec->catfile($_,$Locale,@classNamespace,$classShortName); } @Locations; if ($fullModulePath) { # '/full/path/to/Foo/Bar.pm' -> '/full/path/to/Foo' my ($vol,$dir,$file) = File::Spec->splitpath($fullModulePath); my $baseDir = File::Spec->catpath($vol,$dir,''); # '/full/path/to/Foo' -> '/full/path/to/Foo/locale/En_US/Bar' push @ways, File::Spec->catfile($baseDir,'locale',$Locale,$classShortName); } my $mapFile = first { -f } @ways; return unless $mapFile; return ParseStringsMap($mapFile); } sub ParseStringsMap { my ($fname) = @_; open my $hRes, "<:encoding($Encoding)", findFile($fname) or die "Failed to open file $fname: $!"; my %Map; my $line = 1; while (<$hRes>) { chomp; $line ++ and next if /^\s*$/; if (/^(\w+)\s*=\s*(.*)$/) { $Map{$1} = $2; } else { die "Invalid resource format in $fname at $line"; } $line ++; } return \%Map; } 1; __END__ =pod =head1 NAME C<IMPL::Resources::Strings> - Строковые ресурсы =head1 SYNOPSIS =begin code package Foo; use IMPL::Resources::Strings { msg_say_hello => "Hello, %name%!", msg_module_name => "Simple Foo class" }, auto => 1, locale => 'en-US'; sub InviteUser { my ($this,$uname) = @_; print msg_say_hello(name => $uname); } =end code =head1 DESCRIPTION Импортирует в целевой модуль функции, которые возвращают локализованные параметризованные сообщения. При импорте ищутся модули по следующему алгоритму: В каталогах из массива C<@Locations> ищется файл с относительным путем C<$Locale/$ModName>, где C<$Locale> - глобальная переменная модуля C<IMPL::Resourses::Strings>, а переменная C<$ModName> получена путем замены 'C<::>' в имени целевого модуля на 'C</>'. Если файл не был найден, то производится поиск в каталоге, где расположен сам модуль, файла с относительным путем C<locale/$Locale/$ShortModName>, где C<$ShortModeName> - последняя часть после 'C<::>' из имени целевого модуля. Если файл не найден, то используются строки, указанные при объявлении сообщений в целевом модуле. =head1 FORMAT =begin code text msg_name = any text with named %params% msg_hello = hello, %name%!!! msg_resolve = this is a value of the property: %user.age% msg_short_err = %error.Message% msg_full_err = %error% =end code text =cut