view lib/IMPL/Resources/Strings.pm @ 418:3f38dabaf5cc ref20150831

sync
author cin
date Mon, 28 Dec 2015 15:11:35 +0300
parents c6e90e02dd17
children
line wrap: on
line source

package IMPL::Resources::Strings;
use strict;

use File::Spec;
use List::Util qw(first);
use IMPL::require {
    StringMap => 'IMPL::Resources::StringLocaleMap'
};

our @Locations;
my %maps;

sub import {
    my ($self,$refStrings,%options) = @_;
    
    no strict 'refs';
    
    my $class = caller;
    my $methods = $options{methods};
    
    if (ref $refStrings eq 'HASH') {
        my $map = $self->_GetMapForClass($class,$refStrings);
        
        while(my ($str,$format) = each %$refStrings) {
            *{"${class}::$str"} = sub {
                shift if $methods;
                my $args = @_ == 1 ? shift : { @_ };
                
                return $map->GetString($str,$args);
            }
        }
    }    
}

sub _GetResourceLocations {
	my ($self,$class) = @_;
	
	my @classNamespace = split /::/,$class;
    
    my $classShortName = pop @classNamespace;
    
    my @paths = map File::Spec->catdir($_,@classNamespace), @Locations;

    # 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 );
    
    if ($fullModulePath) {

        # '/full/path/to/Foo/Bar.pm' -> '/full/path/to/Foo/locale/' 
        my ($vol,$dir,$file) = File::Spec->splitpath($fullModulePath);
        push @paths, File::Spec->catpath($vol,File::Spec->catdir($dir,'locale'),'');
    }
    
    return \@paths, $classShortName;
}

sub _GetMapForClass {
	my ($self,$class,$data) = @_;
	
	my $map;
	
	unless ($map) {
	
		my ($paths,$name) = $self->_GetResourceLocations($class);
		
		$map = StringMap->new($data);
		$map->name($name);
		$map->paths($paths);
		
		$maps{$class} = $map;
	
	}
	
	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"
};

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