diff lib/IMPL/Resources/StringLocaleMap.pm @ 407:c6e90e02dd17 ref20150831

renamed Lib->lib
author cin
date Fri, 04 Sep 2015 19:40:23 +0300
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/IMPL/Resources/StringLocaleMap.pm	Fri Sep 04 19:40:23 2015 +0300
@@ -0,0 +1,143 @@
+package IMPL::Resources::StringLocaleMap;
+use strict;
+
+use List::Util qw(first);
+use IMPL::lang qw(:base);
+use IMPL::Const qw(:prop);
+use IMPL::declare {
+	require => {
+		Resources => 'IMPL::Resources',
+		StringMap => 'IMPL::Resources::StringMap',
+		Exception => 'IMPL::Exception',
+		FS => 'File::Spec'
+	},
+	base => {
+		'IMPL::Object' => '@_'
+	},
+	props => [
+		_maps => PROP_RW,
+		name => PROP_RW,
+		paths => PROP_RW | PROP_LIST
+	]
+};
+
+sub CTOR {
+	my ($this,$data,$parent) = @_;
+	
+	if (is($data, StringMap)) {
+		$this->_maps({ default => $data });
+	} elsif ( ref($data) eq 'HASH' ) {
+		$this->_maps({ default => StringMap->new($data,$parent)});
+	} else {
+		# в данном случае таблица строк по-умолчанию будет загружена
+		# из файла при необходимости
+		$this->_maps({});
+	}
+}
+
+sub GetString {
+	my ($this,$id,$args) = @_;
+	
+	my $locale = Resources->currentLocale || 'default';
+	my $map;
+	
+	#warn "id: $id,\t\tlocale: $locale";
+	
+	if(not $map = $this->_maps->{$locale}) {
+		my $default = $this->GetDefaultMap();
+		$map = $this->LoadMap($locale,$default);
+		if (is($map,StringMap)) {
+			#nop
+		} elsif (ref($map) eq 'HASH') {
+			$map = StringMap->new($map,$default);
+		} elsif( not $map ) {
+			$map = $default;
+		} else {
+			die Exception->new("ResolveLocale returned unexpected data", $map);
+		}
+		
+		$this->_maps->{$locale} = $map;
+	}
+	
+	return $map->GetString($id,$args);
+}
+
+sub GetDefaultMap {
+	my ($this) = @_;
+	
+	my $map = $this->_maps->{default};
+	return $map
+		if $map;
+	
+	$map = $this->LoadMap('default') || StringMap->new({});
+	$this->_maps->{default} = $map;
+	
+	return $map;
+}
+
+sub LoadMap {
+	my ($this,$locale,$default) = @_;
+	
+	my @spec = split /_/, $locale;
+	
+	my @locales;
+	
+	do {
+		push @locales, join('_', @spec);
+	} while(pop @spec);
+	
+	my $file = first { -f } map {
+		my $path = $_;
+		
+		map {
+			my $name = FS->catfile($path,$_,$this->name);
+			("$name.s", "$name.p");
+		} @locales;
+	} $this->paths;
+	
+	if($file) {
+		if ($file =~ /\.s$/) {
+			return $this->LoadStringMap($file);
+		} else {
+			return $this->LoadPerlMap($file,$default);
+		}
+	}
+	
+	return;
+}
+
+sub LoadPerlMap {
+	my ($self,$file,$parent) = @_;
+	
+	my $data = do $file;
+	my $e = $@;
+	die Exception->new("Failed to load file '$file'", $e) if $e;
+	die IOException->new("Failed to load file '$file'", $!) if not defined $data and $!;
+	die Exception->new("Failed to load file '$file'", "A hash data is expected") unless ref($data) eq 'HASH';
+	
+	return StringMap->new($data,$parent);
+}
+
+sub LoadStringMap {
+    my ($this,$fname) = @_;
+    
+    open my $hRes, "<:encoding(utf-8)", $fname or die "Failed to open file $fname: $!";
+    local $_;
+    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;
\ No newline at end of file