summaryrefslogtreecommitdiff
path: root/lib/VNDB/L10N.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/VNDB/L10N.pm')
-rw-r--r--lib/VNDB/L10N.pm189
1 files changed, 189 insertions, 0 deletions
diff --git a/lib/VNDB/L10N.pm b/lib/VNDB/L10N.pm
new file mode 100644
index 00000000..d4ff872c
--- /dev/null
+++ b/lib/VNDB/L10N.pm
@@ -0,0 +1,189 @@
+
+use strict;
+use warnings;
+
+{
+ package VNDB::L10N;
+ use base 'Locale::Maketext';
+
+ sub fallback_languages { ('en') };
+
+ # used for the language switch interface, language tags must
+ # be the same as in the languages hash in global.pl
+ sub languages { ('en', 'ru') }
+
+ sub maketext {
+ my $r = eval { shift->SUPER::maketext(@_) };
+ return $r if defined $r;
+ warn "maketext failed for '@_': $@\n";
+ return $_[0]||''; # not quite sure we want this
+ }
+
+ # can be called as either a subroutine or a method
+ sub loadfile {
+ my %lang = (
+ en => \%VNDB::L10N::en::Lexicon,
+ ru => \%VNDB::L10N::ru::Lexicon,
+ );
+
+ open my $F, '<:utf8', $VNDB::ROOT.'/data/lang.txt' or die "Opening language file: $!\n";
+ my($empty, $line, $key, $lang) = (0, 0);
+ while(<$F>) {
+ chomp;
+ $line++;
+
+ # ignore intro
+ if(!defined $key) {
+ $key = 0 if /^\/intro$/;
+ next;
+ }
+ # ignore comments
+ next if /^#/;
+ # key
+ if(/^:(.+)$/) {
+ $key = $1;
+ $lang = undef;
+ $empty = 0;
+ next;
+ }
+ # locale string
+ if(/^([a-z_-]{2,7})[ *]: (.+)$/) {
+ $lang = $1;
+ die "Unknown language on #$line: $lang\n" if !$lang{$lang};
+ die "Unknown key for locale on #$line\n" if !$key;
+ $lang{$lang}{$key} = $2;
+ $empty = 0;
+ next;
+ }
+ # multi-line locale string
+ if($lang && /^\s+([^\s].*)$/) {
+ $lang{$lang}{$key} .= ''.("\n"x$empty)."\n$1";
+ $empty = 0;
+ next;
+ }
+ # empty string (count them in case they're part of a multi-line locale string)
+ if(/^\s*$/) {
+ $empty++;
+ next;
+ }
+ # something we didn't expect
+ die "Don't know what to do with line $line\n" unless /^([a-z_-]{2,7})[ *]:/;
+ }
+ close $F;
+ }
+}
+
+
+{
+ package VNDB::L10N::en;
+ use base 'VNDB::L10N';
+ use POSIX 'strftime';
+ use YAWF 'xml_escape';
+ our %Lexicon;
+
+ sub quant {
+ return $_[1]==1 ? $_[2] : $_[3];
+ }
+
+ # Argument: unix timestamp
+ # Returns: age
+ sub age {
+ my $a = time-$_[1];
+ return sprintf '%d %s ago',
+ $a > 60*60*24*365*2 ? ( $a/60/60/24/365, 'years' ) :
+ $a > 60*60*24*(365/12)*2 ? ( $a/60/60/24/(365/12), 'months' ) :
+ $a > 60*60*24*7*2 ? ( $a/60/60/24/7, 'weeks' ) :
+ $a > 60*60*24*2 ? ( $a/60/60/24, 'days' ) :
+ $a > 60*60*2 ? ( $a/60/60, 'hours' ) :
+ $a > 60*2 ? ( $a/60, 'min' ) :
+ ( $a, 'sec' );
+ }
+
+ # argument: unix timestamp and optional format (compact/full)
+ # return value: yyyy-mm-dd
+ # (maybe an idea to use cgit-style ages for recent timestamps)
+ sub date {
+ my($s, $t, $f) = @_;
+ return strftime '%Y-%m-%d', gmtime $t if !$f || $f eq 'compact';
+ return strftime '%Y-%m-%d at %R', gmtime $t;
+ }
+
+ # argument: database release date format (yyyymmdd)
+ # y = 0000 -> unknown
+ # y = 9999 -> TBA
+ # m = 99 -> month+day unknown
+ # d = 99 -> day unknown
+ # return value: (unknown|TBA|yyyy|yyyy-mm|yyyy-mm-dd)
+ # if date > now: <b class="future">str</b>
+ sub datestr {
+ my $self = shift;
+ my $date = sprintf '%08d', shift||0;
+ my $future = $date > strftime '%Y%m%d', gmtime;
+ my($y, $m, $d) = ($1, $2, $3) if $date =~ /^([0-9]{4})([0-9]{2})([0-9]{2})$/;
+
+ my $str = $y == 0 ? 'unknown' : $y == 9999 ? 'TBA' :
+ $m == 99 ? sprintf('%04d', $y) :
+ $d == 99 ? sprintf('%04d-%02d', $y, $m) :
+ sprintf('%04d-%02d-%02d', $y, $m, $d);
+
+ return $str if !$future;
+ return qq|<b class="future">$str</b>|;
+ }
+
+ # Arguments: (uid, username), or a hashref containing that info
+ sub userstr {
+ my $self = shift;
+ my($id,$n) = ref($_[0])eq'HASH'?($_[0]{uid}||$_[0]{requester}, $_[0]{username}):@_;
+ return !$id ? '[deleted]' : '<a href="/u'.$id.'">'.$n.'</a>';
+ }
+
+ # Arguments: index, @list. returns $list[index]
+ sub index {
+ shift;
+ return $_[shift||0];
+ }
+
+ # Shortcut for <a href="arg1">arg2</a>
+ sub url {
+ return sprintf '<a href="%s">%s</a>', xml_escape($_[1]), xml_escape($_[2]);
+ }
+
+ # <br />
+ sub br { return '<br />' }
+}
+
+
+
+{
+ package VNDB::L10N::ru;
+ use base 'VNDB::L10N::en';
+ our %Lexicon;
+
+ sub quant {
+ my($self, $num, $single, $couple, $lots) = @_;
+ return $single if ($num % 10) == 1 && ($num % 100) != 11;
+ return $couple if ($num % 10) >= 2 && ($num % 10) <= 4 && !(($num % 100) >= 12 && ($num % 100) <= 14);
+ return $lots;
+ }
+
+ sub age {
+ my $self = shift;
+ my $a = time-shift;
+ use utf8;
+ my @l = (
+ $a > 60*60*24*365*2 ? ( $a/60/60/24/365, 'год', 'года', 'лет' ) :
+ $a > 60*60*24*(365/12)*2 ? ( $a/60/60/24/(365/12), 'месяц', 'месяца', 'месяцев' ) :
+ $a > 60*60*24*7*2 ? ( $a/60/60/24/7, 'неделя', 'недели', 'недель' ) :
+ $a > 60*60*24*2 ? ( $a/60/60/24, 'день', 'дня', 'дней' ) :
+ $a > 60*60*2 ? ( $a/60/60, 'час', 'часа', 'часов' ) :
+ $a > 60*2 ? ( $a/60, 'минута', 'минуты', 'минут' ) :
+ ( $a, 'секунда', 'секунды', 'секунд' )
+ );
+ return sprintf '%d %s назад', $l[0], $self->quant(@l);
+ }
+
+}
+
+
+1;
+