diff options
-rw-r--r-- | data/docs/index | 1 | ||||
-rw-r--r-- | lib/VNDB/Func.pm | 10 | ||||
-rw-r--r-- | lib/VNDB/Handler/Chars.pm | 135 | ||||
-rw-r--r-- | lib/VNDB/Handler/Discussions.pm | 130 | ||||
-rw-r--r-- | lib/VNDB/Handler/Misc.pm | 89 | ||||
-rw-r--r-- | lib/VNDB/Handler/Producers.pm | 74 | ||||
-rw-r--r-- | lib/VNDB/Handler/Releases.pm | 165 | ||||
-rw-r--r-- | lib/VNDB/Handler/Staff.pm | 82 | ||||
-rw-r--r-- | lib/VNDB/Handler/Tags.pm | 215 | ||||
-rw-r--r-- | lib/VNDB/Handler/Traits.pm | 112 | ||||
-rw-r--r-- | lib/VNDB/Handler/ULists.pm | 70 | ||||
-rw-r--r-- | lib/VNDB/Handler/Users.pm | 280 | ||||
-rw-r--r-- | lib/VNDB/Handler/VNBrowse.pm | 14 | ||||
-rw-r--r-- | lib/VNDB/Handler/VNEdit.pm | 125 | ||||
-rw-r--r-- | lib/VNDB/Handler/VNPage.pm | 222 |
15 files changed, 911 insertions, 813 deletions
diff --git a/data/docs/index b/data/docs/index index 05a345f7..05339b6a 100644 --- a/data/docs/index +++ b/data/docs/index @@ -16,5 +16,4 @@ <li><a href="/d11">Database API</a></li> <li><a href="/d14">Database Dumps</a></li> <li><a href="/d8">Development</a></li> - <li><a href="/d17">Interface Translation</a></li> </ul> diff --git a/lib/VNDB/Func.pm b/lib/VNDB/Func.pm index 7549207f..6af8f5bf 100644 --- a/lib/VNDB/Func.pm +++ b/lib/VNDB/Func.pm @@ -11,7 +11,7 @@ use VNDBUtil; our @EXPORT = (@VNDBUtil::EXPORT, qw| clearfloat cssicon tagscore mt minage fil_parse fil_serialize parenttags childtags charspoil imgpath imgurl - fmtvote fmtmedia fmtvnlen fmtage fmtdatestr fmtdate fmtuser fmtrating + fmtvote fmtmedia fmtvnlen fmtage fmtdatestr fmtdate fmtuser fmtrating fmtspoil json_encode json_decode script_json form_compare |); @@ -287,6 +287,14 @@ sub fmtrating { 'masterpiece']->[shift()-1]; } +# Turn a spoiler level into a string +sub fmtspoil { + ['neutral', + 'no spoiler', + 'minor spoiler', + 'major spoiler']->[shift()+1]; +} + # JSON::XS::encode_json converts input to utf8, whereas the below functions diff --git a/lib/VNDB/Handler/Chars.pm b/lib/VNDB/Handler/Chars.pm index e11588b4..459bdf21 100644 --- a/lib/VNDB/Handler/Chars.pm +++ b/lib/VNDB/Handler/Chars.pm @@ -40,27 +40,27 @@ sub page { [ alias => 'Aliases', diff => qr/[ ,\n\.]/ ], [ desc => 'Description', diff => qr/[ ,\n\.]/ ], [ gender => 'Gender', serialize => sub { $self->{genders}{$_[0]} } ], - [ b_month => 'Birthday/month',serialize => sub { $_[0]||mt '_revision_empty' } ], - [ b_day => 'Birthday/day', serialize => sub { $_[0]||mt '_revision_empty' } ], - [ s_bust => 'Bust', serialize => sub { $_[0]||mt '_revision_empty' } ], - [ s_waist => 'Waist', serialize => sub { $_[0]||mt '_revision_empty' } ], - [ s_hip => 'Hip', serialize => sub { $_[0]||mt '_revision_empty' } ], - [ height => 'Height', serialize => sub { $_[0]||mt '_revision_empty' } ], - [ weight => 'Weight', serialize => sub { $_[0]||mt '_revision_empty' } ], + [ b_month => 'Birthday/month',serialize => sub { $_[0]||'[empty]' } ], + [ b_day => 'Birthday/day', serialize => sub { $_[0]||'[empty]' } ], + [ s_bust => 'Bust', serialize => sub { $_[0]||'[empty]' } ], + [ s_waist => 'Waist', serialize => sub { $_[0]||'[empty]' } ], + [ s_hip => 'Hip', serialize => sub { $_[0]||'[empty]' } ], + [ height => 'Height', serialize => sub { $_[0]||'[empty]' } ], + [ weight => 'Weight', serialize => sub { $_[0]||'[empty]' } ], [ bloodt => 'Blood type', serialize => sub { $self->{blood_types}{$_[0]} } ], - [ main => 'Main character',htmlize => sub { $_[0] ? sprintf '<a href="/c%d">c%d</a>', $_[0], $_[0] : mt '_revision_empty' } ], - [ main_spoil=> 'Spoiler', serialize => sub { mt "_spoil_$_[0]" } ], + [ main => 'Main character',htmlize => sub { $_[0] ? sprintf '<a href="/c%d">c%d</a>', $_[0], $_[0] : '[empty]' } ], + [ main_spoil=> 'Spoiler', serialize => \&fmtspoil ], [ image => 'Image', htmlize => sub { - return $_[0] ? sprintf '<img src="%s" />', imgurl(ch => $_[0]) : mt '_chdiff_image_none'; + return $_[0] ? sprintf '<img src="%s" />', imgurl(ch => $_[0]) : 'No image'; }], [ traits => 'Traits', join => '<br />', split => sub { map sprintf('%s<a href="/i%d">%s</a> (%s)', $_->{group}?qq|<b class="grayedout">$_->{groupname} / </b> |:'', - $_->{tid}, $_->{name}, mt("_spoil_$_->{spoil}")), @{$_[0]} + $_->{tid}, $_->{name}, fmtspoil $_->{spoil}), @{$_[0]} }], [ vns => 'Visual novels', join => '<br />', split => sub { map sprintf('<a href="/v%d">v%d</a> %s %s (%s)', $_->{vid}, $_->{vid}, $_->{rid}?sprintf('[<a href="/r%d">r%d</a>]', $_->{rid}, $_->{rid}):'', - $self->{char_roles}{$_->{role}}, mt("_spoil_$_->{spoil}")), @{$_[0]}; + $self->{char_roles}{$_->{role}}, fmtspoil $_->{spoil}), @{$_[0]}; }], ); } @@ -83,7 +83,7 @@ sub page { } if(@$inst) { div class => 'mainbox'; - h1 mt '_charp_instances'; + h1 'Other instances'; $self->charTable($_, 1, $_ != $inst->[0], 0, !$r->{main} ? $_->{main_spoil} : $_->{main_spoil} > $r->{main_spoil} ? $_->{main_spoil} : $r->{main_spoil}) for @$inst; end; } @@ -97,8 +97,8 @@ sub charOps { my $spoil = $self->authPref('spoilers')||0; p id => 'charops'; # Note: Order of these links is hardcoded in JS - a href => '#', $spoil == $_ ? (class => 'sel') : (), mt "_spoilset_$_" for (0..2); - a href => '#', class => 'sec'.($self->authPref('traits_sexual') ? ' sel' : ''), mt '_charp_sexual' if $sexual; + a href => '#', $spoil == $_ ? (class => 'sel') : (), ['Hide spoilers', 'Show minor spoilers', 'Spoil me!']->[$_] for (0..2); + a href => '#', class => 'sec'.($self->authPref('traits_sexual') ? ' sel' : ''), 'Show sexual traits' if $sexual; end; } @@ -113,7 +113,7 @@ sub charTable { # image div class => 'charimg'; if(!$r->{image}) { - p mt '_charp_noimg'; + p 'No image uploaded yet'; } else { img src => imgurl(ch => $r->{image}), alt => $r->{name}; } @@ -139,23 +139,24 @@ sub charTable { if($r->{alias}) { $r->{alias} =~ s/\n/, /g; Tr; - td class => 'key', mt '_charp_alias'; + td class => 'key', 'Aliases'; td $r->{alias}; end; } if($r->{height} || $r->{s_bust} || $r->{s_waist} || $r->{s_hip}) { Tr; - td class => 'key', mt '_charp_meas'; + td class => 'key', 'Measurements'; td join ', ', - $r->{height} ? mt('_charp_meas_h', $r->{height}) : (), - $r->{weight} ? mt('_charp_meas_w', $r->{weight}) : (), - $r->{s_bust} || $r->{s_waist} || $r->{s_hip} ? mt('_charp_meas_bwh', $r->{s_bust}||'??', $r->{s_waist}||'??', $r->{s_hip}||'??') : (); + $r->{height} ? "Height: $r->{height}cm" : (), + $r->{weight} ? "Weight: $r->{weight}kg" : (), + $r->{s_bust} || $r->{s_waist} || $r->{s_hip} ? + sprintf 'Bust-Waist-Hips: %s-%s-%scm', $r->{s_bust}||'??', $r->{s_waist}||'??', $r->{s_hip}||'??' : (); end; } if($r->{b_month} && $r->{b_day}) { Tr; - td class => 'key', mt '_charp_bday'; - td mt '_charp_bday_fmt', $r->{b_day}, mt "_month_$r->{b_month}"; + td class => 'key', 'Birthday'; + td $r->{b_day}.' '.[qw{January February March April May June July August September October November December}]->[$r->{b_month}-1]; end; } @@ -187,7 +188,7 @@ sub charTable { my %vns; push @{$vns{$_->{vid}}}, $_ for(sort { !defined($a->{rid})?1:!defined($b->{rid})?-1:$a->{rtitle} cmp $b->{rtitle} } @{$r->{vns}}); Tr; - td class => 'key', mt $vn ? '_charp_releases' : '_charp_vns'; + td class => 'key', $vn ? 'Releases' : 'Visual novels'; td; my $first = 0; for my $g (sort { $vns{$a}[0]{vntitle} cmp $vns{$b}[0]{vntitle} } keys %vns) { @@ -215,7 +216,7 @@ sub charTable { b class => 'grayedout', "r$_->{rid}:"; a href => "/r$_->{rid}", $_->{rtitle}; } else { - txt mt '_charp_vns_other'; + txt 'All other releases'; } end; } @@ -227,7 +228,7 @@ sub charTable { if(@{$r->{seiyuu}}) { Tr; - td class => 'key', mt '_charp_voice'; + td class => 'key', 'Voiced by'; td; my $last_name = ''; for my $s (sort { $a->{name} cmp $b->{name} } @{$r->{seiyuu}}) { @@ -245,7 +246,7 @@ sub charTable { if($r->{desc}) { Tr class => 'nostripe'; td class => 'chardesc', colspan => 2; - h2 mt '_charp_description'; + h2 'Description'; p; lit bb2html $r->{desc}, 0, 1; end; @@ -292,7 +293,7 @@ sub edit { { post => 'desc', required => 0, maxlength => 5000, default => '' }, { post => 'gender', required => 0, default => 'unknown', enum => [ keys %{$self->{genders}} ] }, { post => 'image', required => 0, default => 0, template => 'id' }, - { post => 'bday', required => 0, default => '', regex => [ qr/^\d{2}-\d{2}$/, mt('_chare_form_bday_err') ] }, + { post => 'bday', required => 0, default => '', regex => [ qr/^(?:[01]?[0-9])-(?:[0123]?[0-9])$/, 'Birthday must be in MM-DD format.' ] }, { post => 's_bust', required => 0, default => 0, template => 'uint', max => 32767 }, { post => 's_waist', required => 0, default => 0, template => 'uint', max => 32767 }, { post => 's_hip', required => 0, default => 0, template => 'uint', max => 32767 }, @@ -359,60 +360,60 @@ sub edit { $frm->{editsum} //= sprintf 'Reverted to revision c%d.%d', $id, $rev if !$copy && $rev; $frm->{editsum} = sprintf 'New character based on c%d.%d', $id, $r->{rev} if $copy; - my $title = mt $r ? ($copy ? '_chare_title_copy' : '_chare_title_edit', $r->{name}) : '_chare_title_add'; + my $title = !$r ? 'Add new character' : $copy ? "Copy $r->{name}" : "Edit $r->{name}"; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('c', $r, $copy ? 'copy' : 'edit') if $r; $self->htmlEditMessage('c', $r, $title, $copy); $self->htmlForm({ frm => $frm, action => $r ? "/c$id/".($copy ? 'copy' : 'edit') : '/c/new', editsum => 1, upload => 1 }, - chare_geninfo => [ mt('_chare_form_generalinfo'), - [ input => name => mt('_chare_form_name'), short => 'name' ], - [ input => name => mt('_chare_form_original'), short => 'original' ], - [ static => content => mt('_chare_form_original_note') ], - [ text => name => mt('_chare_form_alias'), short => 'alias', rows => 3 ], - [ static => content => mt('_chare_form_alias_note') ], - [ text => name => mt('_chare_form_desc').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'desc', rows => 6 ], - [ select => name => mt('_chare_form_gender'),short => 'gender', options => [ + chare_geninfo => [ 'General info', + [ input => name => 'Name (romaji)', short => 'name' ], + [ input => name => 'Original name', short => 'original' ], + [ static => content => 'The original name of the character, leave blank if it is already in the Latin alphabet.' ], + [ text => name => 'Aliases', short => 'alias', rows => 3 ], + [ static => content => '(Un)official aliases, separated by a newline.' ], + [ text => name => 'Description<br /><b class="standout">English please!</b>', short => 'desc', rows => 6 ], + [ select => name => 'Gender',short => 'gender', options => [ map [ $_, $self->{genders}{$_} ], keys %{$self->{genders}} ] ], - [ input => name => mt('_chare_form_bday'), short => 'bday', width => 100, post => ' '.mt('_chare_form_bday_fmt') ], - [ input => name => mt('_chare_form_bust'), short => 's_bust', width => 50, post => ' cm' ], - [ input => name => mt('_chare_form_waist'), short => 's_waist',width => 50, post => ' cm' ], - [ input => name => mt('_chare_form_hip'), short => 's_hip', width => 50, post => ' cm' ], - [ input => name => mt('_chare_form_height'),short => 'height', width => 50, post => ' cm' ], - [ input => name => mt('_chare_form_weight'),short => 'weight', width => 50, post => ' kg' ], - [ select => name => mt('_chare_form_bloodt'),short => 'bloodt', options => [ + [ input => name => 'Birthday', short => 'bday', width => 100,post => ' MM-DD (e.g. "01-26" for the 26th of January)' ], + [ input => name => 'Bust', short => 's_bust', width => 50, post => ' cm' ], + [ input => name => 'Waist', short => 's_waist',width => 50, post => ' cm' ], + [ input => name => 'Hips', short => 's_hip', width => 50, post => ' cm' ], + [ input => name => 'Height', short => 'height', width => 50, post => ' cm' ], + [ input => name => 'Weight', short => 'weight', width => 50, post => ' kg' ], + [ select => name => 'Blood type',short => 'bloodt', options => [ map [ $_, $self->{blood_types}{$_} ], keys %{$self->{blood_types}} ] ], [ static => content => '<br />' ], - [ input => name => mt('_chare_form_main'), short => 'main', width => 50, post => ' '.mt('_chare_form_main_note') ], - [ select => name => mt('_chare_form_main_spoil'), short => 'main_spoil', options => [ - map [$_, mt("_spoil_$_")], 0..2 ] ], + [ input => name => 'Instance of',short => 'main', width => 50, post => ' ID of the main character - the character of which this is an instance of.' ], + [ select => name => 'Spoiler', short => 'main_spoil', options => [ + map [$_, fmtspoil $_], 0..2 ] ], ], - chare_img => [ mt('_chare_image'), [ static => nolabel => 1, content => sub { + chare_img => [ 'Image', [ static => nolabel => 1, content => sub { div class => 'img'; - p mt '_chare_image_none' if !$frm->{image}; + p 'No image uploaded yet' if !$frm->{image}; img src => imgurl(ch => $frm->{image}) if $frm->{image}; end; div; - h2 mt '_chare_image_id'; + h2 'Image ID'; input type => 'text', class => 'text', name => 'image', id => 'image', value => $frm->{image}||''; - p mt '_chare_image_id_msg'; + p 'Use a character image that is already on the server. Set to \'0\' to remove the current image.'; br; br; - h2 mt '_chare_image_upload'; + h2 'Upload new image'; input type => 'file', class => 'text', name => 'img', id => 'img'; - p mt('_chare_image_upload_msg'); + p 'Image must be in JPEG or PNG format and at most 1MiB. Images larger than 256x300 will automatically be resized. Image must be safe for work!'; end; }]], - chare_traits => [ mt('_chare_traits'), + chare_traits => [ 'Traits', [ hidden => short => 'traits' ], [ static => nolabel => 1, content => sub { - h2 mt '_chare_traits_sel'; + h2 'Current traits'; table; tbody id => 'traits_tbl'; - Tr id => 'traits_loading'; td colspan => '3', mt('_js_loading'); end; + Tr id => 'traits_loading'; td colspan => '3', 'Loading...'; end; end; end; - h2 mt '_chare_traits_add'; + h2 'Add trait'; table; Tr; td class => 'tc_name'; input id => 'trait_input', type => 'text', class => 'text'; end; td colspan => 2, ''; @@ -420,14 +421,14 @@ sub edit { }], ], - chare_vns => [ mt('_chare_vns'), + chare_vns => [ 'Visual novels', [ hidden => short => 'vns' ], [ static => nolabel => 1, content => sub { - h2 mt '_chare_vns_sel'; + h2 'Selected visual novels'; table; tbody id => 'vns_tbl'; - Tr id => 'vns_loading'; td colspan => '4', mt('_js_loading'); end; + Tr id => 'vns_loading'; td colspan => '4', 'Loading...'; end; end; end; - h2 mt '_chare_vns_add'; + h2 'Add visual novel'; table; Tr; td class => 'tc_vnadd'; input id => 'vns_input', type => 'text', class => 'text'; end; td colspan => 3, ''; @@ -497,22 +498,22 @@ sub list { what => 'vns', }); - $self->htmlHeader(title => mt '_charb_title'); + $self->htmlHeader(title => 'Browse characters'); my $quri = uri_escape($f->{q}); form action => '/c/all', 'accept-charset' => 'UTF-8', method => 'get'; div class => 'mainbox'; - h1 mt '_charb_title'; + h1 'Browse characters'; $self->htmlSearchBox('c', $f->{q}); p class => 'browseopts'; for ('all', 'a'..'z', 0) { - a href => "/c/$_?q=$quri", $_ eq $fch ? (class => 'optselected') : (), $_ eq 'all' ? mt('_char_all') : $_ ? uc $_ : '#'; + a href => "/c/$_?q=$quri", $_ eq $fch ? (class => 'optselected') : (), $_ eq 'all' ? 'ALL' : $_ ? uc $_ : '#'; } end; p class => 'filselect'; a id => 'filselect', href => '#c'; - lit '<i>▸</i> '.mt('_js_fil_filters').'<i></i>'; + lit '<i>▸</i> Filters<i></i>'; end; end; input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil}; @@ -521,8 +522,8 @@ sub list { if(!@$list) { div class => 'mainbox'; - h1 mt '_charb_noresults'; - p mt '_charb_noresults_msg'; + h1 'No results'; + p 'No characters found that matched your criteria.'; end; } diff --git a/lib/VNDB/Handler/Discussions.pm b/lib/VNDB/Handler/Discussions.pm index fe96374a..1a905b7b 100644 --- a/lib/VNDB/Handler/Discussions.pm +++ b/lib/VNDB/Handler/Discussions.pm @@ -42,7 +42,7 @@ sub thread { $self->htmlHeader(title => $t->{title}, noindex => 1); div class => 'mainbox'; h1 $t->{title}; - h2 mt '_thread_postedin'; + h2 'Posted in'; ul; for (sort { $a->{type}.$a->{iid} cmp $b->{type}.$b->{iid} } @{$t->{boards}}) { li; @@ -69,7 +69,7 @@ sub thread { td class => 'tc1'; a href => "/t$tid.$_->{num}", name => $_->{num}, "#$_->{num}"; if(!$_->{hidden}) { - lit ' '.mt "_thread_byuser", $_; + lit ' by '.fmtuser($_); br; txt fmtdate $_->{date}, 'full'; } @@ -78,15 +78,15 @@ sub thread { if(caneditpost($self, $_)) { i class => 'edit'; txt '< '; - a href => "/t$tid.$_->{num}/edit", mt '_thread_editpost'; + a href => "/t$tid.$_->{num}/edit", 'edit'; txt ' >'; end; } if($_->{hidden}) { - i class => 'deleted', mt '_thread_deletedpost'; + i class => 'deleted', 'Post deleted.'; } else { lit bb2html $_->{msg}; - i class => 'lastmod', mt '_thread_lastmodified', $_->{edited} if $_->{edited}; + i class => 'lastmod', 'Last modified on '.fmtdate($_->{edited}, 'full') if $_->{edited}; } end; end; @@ -97,8 +97,8 @@ sub thread { if($t->{locked}) { div class => 'mainbox'; - h1 mt '_thread_noreply_title'; - p class => 'center', mt '_thread_noreply_locked'; + h1 'Reply'; + p class => 'center', 'This thread has been locked, you can\'t reply to it anymore'; end; } elsif($t->{count} <= $page*25 && $self->authCan('board')) { form action => "/t$tid/reply", method => 'post', 'accept-charset' => 'UTF-8'; @@ -106,20 +106,20 @@ sub thread { fieldset class => 'submit'; input type => 'hidden', class => 'hidden', name => 'formcode', value => $self->authGetCode("/t$tid/reply"); h2; - txt mt '_thread_quickreply_title'; - b class => 'standout', ' ('.mt('_inenglish').')'; + txt 'Quick reply'; + b class => 'standout', ' (English please!)'; end; textarea name => 'msg', id => 'msg', rows => 4, cols => 50, ''; br; - input type => 'submit', value => mt('_thread_quickreply_submit'), class => 'submit'; - input type => 'submit', value => mt('_thread_quickreply_full'), class => 'submit', name => 'fullreply'; + input type => 'submit', value => 'Reply', class => 'submit'; + input type => 'submit', value => 'Go advanced...', class => 'submit', name => 'fullreply'; end; end; end 'form'; } elsif(!$self->authCan('board')) { div class => 'mainbox'; - h1 mt '_thread_noreply_title'; - p class => 'center', mt '_thread_noreply_login'; + h1 'Reply'; + p class => 'center', 'You must be logged in to reply to this thread.'; end; } @@ -295,41 +295,41 @@ sub edit { # generate html my $url = !$tid ? "/t/$board/new" : !$num ? "/t$tid/reply" : "/t$tid.$num/edit"; - my $title = mt !$tid ? '_postedit_newthread' : - !$num ? ('_postedit_replyto', $t->{title}) : - '_postedit_edit'; + my $title = !$tid ? 'Start new thread' : + !$num ? "Reply to $t->{title}" : + 'Edit post'; $self->htmlHeader(title => $title, noindex => 1); $self->htmlForm({ frm => $frm, action => $url }, 'postedit' => [$title, - [ static => label => mt('_postedit_form_username'), content => fmtuser($p ? ($p->{uid}, $p->{username}) : ($self->authInfo->{id}, $self->authInfo->{username})) ], + [ static => label => 'Username', content => fmtuser($p ? ($p->{uid}, $p->{username}) : ($self->authInfo->{id}, $self->authInfo->{username})) ], !$tid || $num == 1 ? ( - [ input => short => 'title', name => mt('_postedit_form_title') ], - [ input => short => 'boards', name => mt('_postedit_form_boards') ], - [ static => content => mt('_postedit_form_boards_info') ], + [ input => short => 'title', name => 'Thread title' ], + [ input => short => 'boards', name => 'Board(s)' ], + [ static => content => 'Read <a href="/d9.2">d9.2</a> for information about how to specify boards.' ], $self->authCan('boardmod') ? ( - [ check => name => mt('_postedit_form_locked'), short => 'locked' ], + [ check => name => 'Locked', short => 'locked' ], ) : (), ) : ( - [ static => label => mt('_postedit_form_topic'), content => qq|<a href="/t$tid">|.xml_escape($t->{title}).'</a>' ], + [ static => label => 'Topic', content => qq|<a href="/t$tid">|.xml_escape($t->{title}).'</a>' ], ), $self->authCan('boardmod') ? ( - [ check => name => mt('_postedit_form_hidden'), short => 'hidden' ], + [ check => name => 'Hidden', short => 'hidden' ], $num ? ( - [ check => name => mt('_postedit_form_nolastmod'), short => 'nolastmod' ], + [ check => name => 'Don\'t update last modified field', short => 'nolastmod' ], ) : (), ) : (), - [ text => name => mt('_postedit_form_msg').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'msg', rows => 25, cols => 75 ], - [ static => content => mt('_postedit_form_msg_format') ], + [ text => name => 'Message<br /><b class="standout">English please!</b>', short => 'msg', rows => 25, cols => 75 ], + [ static => content => 'See <a href="/d9.3">d9.3</a> for the allowed formatting codes' ], (!$tid || $num == 1) ? ( [ static => content => '<br />' ], - [ check => short => 'poll', name => mt('_postedit_form_poll_add') ], + [ check => short => 'poll', name => 'Add poll' ], $num && $frm->{poll_question} ? ( - [ static => content => '<b class="standout">'.mt('_postedit_form_poll_warning').'</b>' ] + [ static => content => '<b class="standout">All votes will be reset if any changes to the poll fields are made!</b>' ] ) : (), - [ input => short => 'poll_question', name => mt('_postedit_form_poll_q'), width => 250 ], - [ text => short => 'poll_options', name => mt('_postedit_form_poll_opt').'<br /><i>'.mt('_postedit_form_poll_optmax', $self->{poll_options}).'</i>', rows => 8, cols => 35 ], - [ input => short => 'poll_max_options',width => 16, post => ' '.mt('_postedit_form_poll_max') ], - [ check => short => 'poll_preview', name => mt('_postedit_form_poll_view') ], - [ check => short => 'poll_recast', name => mt('_postedit_form_poll_recast') ], + [ input => short => 'poll_question', name => 'Poll question', width => 250 ], + [ text => short => 'poll_options', name => "Poll options<br /><i>one per line,<br />$self->{poll_options} max</i>", rows => 8, cols => 35 ], + [ input => short => 'poll_max_options',width => 16, post => ' Number of options voter is allowed to choose' ], + [ check => short => 'poll_preview', name => 'Allow users to view poll results before voting' ], + [ check => short => 'poll_recast', name => 'Allow users to change their vote' ], ) : (), ]); $self->htmlFooter; @@ -353,7 +353,7 @@ sub vote { { post => 'option', multi => 1, mincount => 1, maxcount => $t->{poll_max_options}, enum => [ map $_->[0], @{$t->{poll_options}} ] } ); if($f->{_err}) { - $self->htmlHeader(title => mt '_poll_error'); + $self->htmlHeader(title => 'Poll error'); $self->htmlFormError($f, 1); $self->htmlFooter; return; @@ -380,7 +380,7 @@ sub board { $self->dbVNGet(id => $iid)->[0]; return $self->resNotFound if $iid && !$obj; my $ititle = $obj && ($obj->{title}||$obj->{name}||$obj->{username}); - my $title = !$obj ? $self->{discussion_boards}{$type} || 'All boards' : mt '_disboard_item_title', $ititle; + my $title = !$obj ? $self->{discussion_boards}{$type} || 'All boards' : "Related discussions for $ititle"; my($list, $np) = $self->dbThreadGet( $type ne 'all' ? (type => $type) : (), @@ -398,7 +398,7 @@ sub board { div class => 'mainbox'; h1 $title; p; - a href => '/t', mt '_disboard_rootlink'; + a href => '/t', 'Discussion board'; txt ' > '; a href => "/t/$type", $self->{discussion_boards}{$type}||'All boards'; if($iid) { @@ -412,16 +412,16 @@ sub board { fieldset class => 'search'; input type => 'text', name => 'bq', id => 'bq', class => 'text'; input type => 'hidden', name => 'b', value => $type if $type ne 'all'; - input type => 'submit', class => 'submit', value => mt '_searchbox_submit'; + input type => 'submit', class => 'submit', value => 'Search!'; end 'fieldset'; } p class => 'center'; if(!@$list) { - b mt '_disboard_nothreads'; + b 'No related threads found'; br; br; - a href => "/t/$type$iid/new", mt '_disboard_createyourown'; + a href => "/t/$type$iid/new", 'Why not create one yourself?'; } else { - a href => '/t/'.($iid ? $type.$iid : $type ne 'ge' ? 'db' : $type).'/new', mt '_disboard_startnew' if $type ne 'all'; + a href => '/t/'.($iid ? $type.$iid : $type ne 'ge' ? 'db' : $type).'/new', 'Start a new thread' if $type ne 'all'; } end; end 'div'; @@ -436,13 +436,13 @@ sub board { sub index { my $self = shift; - $self->htmlHeader(title => mt('_disindex_title'), noindex => 1, feeds => [ 'posts', 'announcements' ]); + $self->htmlHeader(title => 'Discussion board index', noindex => 1, feeds => [ 'posts', 'announcements' ]); form action => '/t/search', method => 'get'; div class => 'mainbox'; - h1 mt '_disindex_title'; + h1 'Discussion board index'; fieldset class => 'search'; input type => 'text', name => 'bq', id => 'bq', class => 'text'; - input type => 'submit', class => 'submit', value => mt '_searchbox_submit'; + input type => 'submit', class => 'submit', value => 'Search!'; end 'fieldset'; p class => 'browseopts'; a href => '/t/all', 'All boards'; @@ -481,14 +481,14 @@ sub search { ); return $self->resNotFound if $frm->{_err}; - $self->htmlHeader(title => mt('_dissearch_title'), noindex => 1); - $self->htmlForm({ frm => $frm, action => '/t/search', method => 'get', nosubmit => 1, noformcode => 1 }, 'boardsearch' => [mt('_dissearch_title'), - [ input => short => 'bq', name => mt('_dissearch_query') ], - [ check => short => 't', name => mt('_dissearch_titleonly') ], - [ select => short => 'b', name => mt('_dissearch_boards'), multi => 1, size => scalar keys %{$self->{discussion_boards}}, + $self->htmlHeader(title => 'Search the discussion board', noindex => 1); + $self->htmlForm({ frm => $frm, action => '/t/search', method => 'get', nosubmit => 1, noformcode => 1 }, 'boardsearch' => ['Search the discussion board', + [ input => short => 'bq', name => 'Query' ], + [ check => short => 't', name => 'Only search thread titles' ], + [ select => short => 'b', name => 'Boards', multi => 1, size => scalar keys %{$self->{discussion_boards}}, options => [ map [$_,$self->{discussion_boards}{$_}], keys %{$self->{discussion_boards}} ] ], [ static => content => sub { - input type => 'submit', class => 'submit', tabindex => 10, value => mt '_searchbox_submit'; + input type => 'submit', class => 'submit', tabindex => 10, value => 'Search!'; } ], ]); return $self->htmlFooter if !$frm->{bq}; @@ -535,8 +535,8 @@ sub search { my $url = '/t/search?'.join ';', 'bq='.uri_escape($frm->{bq}), $frm->{t} ? 't=1' : (), map "b=$_", keys %boards; if(!@$l) { div class => 'mainbox'; - h1 mt '_dissearch_noresults_title'; - p mt '_dissearch_noresults_msg'; + h1 'No results'; + p 'No threads or messages found matching your criteria.'; end; } elsif($frm->{t}) { _threadlist($self, $l, $frm, $np, $url, 'all'); @@ -549,9 +549,9 @@ sub search { class => 'postsearch', header => [ sub { td class => 'tc1_1', ''; td class => 'tc1_2', ''; }, - [ mt '_dissearch_col_date' ], - [ mt '_dissearch_col_user' ], - [ mt '_dissearch_col_msg' ], + [ 'Date' ], + [ 'User' ], + [ 'Message' ], ], row => sub { my($s, $n, $l) = @_; @@ -590,17 +590,17 @@ sub _threadlist { pageurl => $url, class => 'discussions', header => [ - [ mt '_threadlist_col_topic' ], - [ mt '_threadlist_col_replies' ], - [ mt '_threadlist_col_starter' ], - [ mt '_threadlist_col_lastpost' ], + [ 'Topic' ], + [ 'Replies' ], + [ 'Starter' ], + [ 'Last post' ], ], row => sub { my($self, $n, $o) = @_; Tr; td class => 'tc1'; a $o->{locked} ? ( class => 'locked' ) : (), href => "/t$o->{id}"; - span class => 'pollflag', '['.mt('_threadlist_poll').']' if $o->{haspoll}; + span class => 'pollflag', '[poll]' if $o->{haspoll}; txt shorten $o->{title}, 50; end; b class => 'boards'; @@ -645,24 +645,24 @@ sub _poll { table class => 'votebooth'; if($allow_vote && $t->{poll_max_options} > 1) { thead; Tr; td colspan => 3; - i mt('_poll_choose', $t->{poll_max_options}); + i "You may choose up to $t->{poll_max_options} options"; end; end; end; } tfoot; Tr; td class => 'tc1'; - input type => 'submit', class => 'submit', value => mt('_poll_vote') if $allow_vote; + input type => 'submit', class => 'submit', value => 'Vote' if $allow_vote; if(!$self->authCan('board')) { - b class => 'standout', mt('_poll_novote_login'); + b class => 'standout', 'You must be logged in to be able to vote.'; } end; td class => 'tc2', colspan => 2; if($t->{poll_preview} || @$own_votes) { if(!$num_votes) { - i mt('_poll_no_votes'); + i 'Nobody voted yet.'; } elsif(!$preview && !@$own_votes) { - a href => $url.'?pollview=1', id => 'pollpreview', mt('_poll_results'); + a href => $url.'?pollview=1', id => 'pollpreview', 'View results'; } else { - txt mt('_poll_total_votes', $num_votes); + txt sprintf '%d vote%s total', $num_votes, $num_votes == 1 ? '' : 's'; } } end; diff --git a/lib/VNDB/Handler/Misc.pm b/lib/VNDB/Handler/Misc.pm index a6f6401b..08439513 100644 --- a/lib/VNDB/Handler/Misc.pm +++ b/lib/VNDB/Handler/Misc.pm @@ -35,12 +35,16 @@ TUWF::register( sub homepage { my $self = shift; - $self->htmlHeader(title => mt('_site_title'), feeds => [ keys %{$self->{atom_feeds}} ]); + $self->htmlHeader(title => 'The Visual Novel Database', feeds => [ keys %{$self->{atom_feeds}} ]); div class => 'mainbox'; - h1 mt '_site_title'; + h1 'The Visual Novel Database'; p class => 'description'; - lit mt '_home_intro'; + txt 'VNDB.org strives to be a comprehensive database for information about visual novels.'; + br; + txt 'This website is built as a wiki, meaning that anyone can freely add' + .' and contribute information to the database, allowing us to create the' + .' largest, most accurate and most up-to-date visual novel database on the web.'; end; # with filters applied it's signifcantly slower, so special-code the situations with and without filters @@ -66,17 +70,16 @@ sub homepage { # Recent changes td; h1; - a href => '/hist', mt '_home_recentchanges'; txt ' '; - a href => '/feeds/changes.atom'; cssicon 'feed', mt '_atom_feed'; end; + a href => '/hist', 'Recent Changes'; txt ' '; + a href => '/feeds/changes.atom'; cssicon 'feed', 'Atom Feed'; end; end; my $changes = $self->dbRevisionGet(results => 10, auto => 1); ul; for (@$changes) { li; - lit mt '_home_recentchanges_item', $_->{type}, - sprintf('<a href="%s" title="%s">%s</a>', "/$_->{type}$_->{itemid}.$_->{rev}", - xml_escape($_->{ioriginal}||$_->{ititle}), xml_escape shorten $_->{ititle}, 33), - $_; + txt "$_->{type}:"; + a href => "/$_->{type}$_->{itemid}.$_->{rev}", title => $_->{ioriginal}||$_->{ititle}, shorten $_->{ititle}, 33; + lit " by ".fmtuser($_); end; } end; @@ -86,8 +89,8 @@ sub homepage { td; my $an = $self->dbThreadGet(type => 'an', sort => 'id', reverse => 1, results => 2); h1; - a href => '/t/an', mt '_home_announcements'; txt ' '; - a href => '/feeds/announcements.atom'; cssicon 'feed', mt '_atom_feed'; end; + a href => '/t/an', 'Announcements'; txt ' '; + a href => '/feeds/announcements.atom'; cssicon 'feed', 'Atom Feed'; end; end; for (@$an) { my $post = $self->dbPostGet(tid => $_->{id}, num => 1)->[0]; @@ -103,18 +106,17 @@ sub homepage { # Recent posts td; h1; - a href => '/t/all', mt '_home_recentposts'; txt ' '; - a href => '/feeds/posts.atom'; cssicon 'feed', mt '_atom_feed'; end; + a href => '/t/all', 'Recent Posts'; txt ' '; + a href => '/feeds/posts.atom'; cssicon 'feed', 'Atom Feed'; end; end; my $posts = $self->dbThreadGet(what => 'lastpost boardtitles', results => 10, sort => 'lastpost', reverse => 1, notusers => 1); ul; for (@$posts) { my $boards = join ', ', map $self->{discussion_boards}{$_->{type}}.($_->{iid}?' > '.$_->{title}:''), @{$_->{boards}}; li; - lit mt '_home_recentposts_item', $_->{ldate}, - sprintf('<a href="%s" title="%s">%s</a>', "/t$_->{id}.$_->{count}", - xml_escape("Posted in $boards"), xml_escape shorten $_->{title}, 25), - {uid => $_->{luid}, username => $_->{lusername}}; + txt fmtage($_->{ldate}).' '; + a href => "/t$_->{id}.$_->{count}", title => "Posted in $boards", shorten $_->{title}, 25; + lit ' by '.fmtuser($_->{luid}, $_->{lusername}); end; } end; @@ -126,7 +128,7 @@ sub homepage { # Random visual novels td; h1; - a href => '/v/rand', mt '_home_randomvn'; + a href => '/v/rand', 'Random visual novels'; end; my $random = $self->filFetchDB(vn => undef, undef, {results => 10, sort => 'rand'}); ul; @@ -141,7 +143,7 @@ sub homepage { # Upcoming releases td; h1; - a href => '/r?fil=released-0;o=a;s=released', mt '_home_upcoming'; + a href => '/r?fil=released-0;o=a;s=released', 'Upcoming releases'; end; my $upcoming = $self->filFetchDB(release => undef, undef, {results => 10, released => 0, what => 'platforms'}); ul; @@ -161,7 +163,7 @@ sub homepage { # Just released td; h1; - a href => '/r?fil=released-1;o=d;s=released', mt '_home_justreleased'; + a href => '/r?fil=released-1;o=d;s=released', 'Just released'; end; my $justrel = $self->filFetchDB(release => undef, undef, {results => 10, sort => 'released', reverse => 1, released => 1, what => 'platforms'}); ul; @@ -207,7 +209,7 @@ sub history { $type eq 'c' ? $self->dbCharGet(id => $id)->[0] : $type eq 's' ? $self->dbStaffGet(id => $id)->[0] : $type eq 'v' ? $self->dbVNGet(id => $id)->[0] : undef; - my $title = mt $type ? ('_hist_title_item', $obj->{title} || $obj->{name} || $obj->{username}) : '_hist_title'; + my $title = $type ? 'Edit history of '.($obj->{title} || $obj->{name} || $obj->{username}) : 'Recent changes'; return $self->resNotFound if $type && !$obj->{id}; # get the edit history @@ -243,36 +245,36 @@ sub history { h1 $title; if($type ne 'u') { p class => 'browseopts'; - a !$f->{m} ? (class => 'optselected') : (), href => $u->(m => 0), mt '_hist_filter_showauto'; - a $f->{m} ? (class => 'optselected') : (), href => $u->(m => 1), mt '_hist_filter_hideauto'; + a !$f->{m} ? (class => 'optselected') : (), href => $u->(m => 0), 'Show automated edits'; + a $f->{m} ? (class => 'optselected') : (), href => $u->(m => 1), 'Hide automated edits'; end; } if(!$type || $type eq 'u') { if($self->authCan('dbmod')) { p class => 'browseopts'; - a $f->{h} == 1 ? (class => 'optselected') : (), href => $u->(h => 1), mt '_hist_filter_hidedel'; - a $f->{h} == -1 ? (class => 'optselected') : (), href => $u->(h => -1), mt '_hist_filter_showdel'; + a $f->{h} == 1 ? (class => 'optselected') : (), href => $u->(h => 1), 'Hide deleted items'; + a $f->{h} == -1 ? (class => 'optselected') : (), href => $u->(h => -1), 'Show deleted items'; end; } p class => 'browseopts'; - a !$f->{t} ? (class => 'optselected') : (), href => $u->(t => ''), mt '_hist_filter_alltypes'; - a $f->{t} eq 'v' ? (class => 'optselected') : (), href => $u->(t => 'v'), mt '_hist_filter_onlyvn'; - a $f->{t} eq 'r' ? (class => 'optselected') : (), href => $u->(t => 'r'), mt '_hist_filter_onlyreleases'; - a $f->{t} eq 'p' ? (class => 'optselected') : (), href => $u->(t => 'p'), mt '_hist_filter_onlyproducers'; - a $f->{t} eq 's' ? (class => 'optselected') : (), href => $u->(t => 's'), mt '_hist_filter_onlystaff'; - a $f->{t} eq 'c' ? (class => 'optselected') : (), href => $u->(t => 'c'), mt '_hist_filter_onlychars'; - a $f->{t} eq 'a' ? (class => 'optselected') : (), href => $u->(t => 'a'), mt '_hist_filter_nochars'; + a !$f->{t} ? (class => 'optselected') : (), href => $u->(t => ''), 'Show all items'; + a $f->{t} eq 'v' ? (class => 'optselected') : (), href => $u->(t => 'v'), 'Only visual novels'; + a $f->{t} eq 'r' ? (class => 'optselected') : (), href => $u->(t => 'r'), 'Only releases'; + a $f->{t} eq 'p' ? (class => 'optselected') : (), href => $u->(t => 'p'), 'Only producers'; + a $f->{t} eq 's' ? (class => 'optselected') : (), href => $u->(t => 's'), 'Only staff'; + a $f->{t} eq 'c' ? (class => 'optselected') : (), href => $u->(t => 'c'), 'Only characters'; + a $f->{t} eq 'a' ? (class => 'optselected') : (), href => $u->(t => 'a'), 'All except characters'; end; p class => 'browseopts'; - a !$f->{e} ? (class => 'optselected') : (), href => $u->(e => 0), mt '_hist_filter_allactions'; - a $f->{e} == 1 ? (class => 'optselected') : (), href => $u->(e => 1), mt '_hist_filter_onlyedits'; - a $f->{e} == -1 ? (class => 'optselected') : (), href => $u->(e => -1), mt '_hist_filter_onlynew'; + a !$f->{e} ? (class => 'optselected') : (), href => $u->(e => 0), 'Show all changes'; + a $f->{e} == 1 ? (class => 'optselected') : (), href => $u->(e => 1), 'Only edits'; + a $f->{e} == -1 ? (class => 'optselected') : (), href => $u->(e => -1), 'Only newly created pages'; end; } if($type eq 'v') { p class => 'browseopts'; - a !$f->{r} ? (class => 'optselected') : (), href => $u->(r => 0), mt '_hist_filter_exrel'; - a $f->{r} ? (class => 'optselected') : (), href => $u->(r => 1), mt '_hist_filter_increl'; + a !$f->{r} ? (class => 'optselected') : (), href => $u->(r => 0), 'Exclude edits of releases'; + a $f->{r} ? (class => 'optselected') : (), href => $u->(r => 1), 'Include edits of releases'; end; } end 'div'; @@ -285,10 +287,9 @@ sub history { sub docpage { my($self, $did) = @_; - my $l = '.'.$self->{l10n}->language_tag(); my $f = sprintf('%s/data/docs/%d', $VNDB::ROOT, $did); my $F; - open($F, '<:utf8', $f.$l) or open($F, '<:utf8', $f) or return $self->resNotFound; + open($F, '<:utf8', $f) or return $self->resNotFound; my @c = <$F>; close $F; @@ -308,7 +309,7 @@ sub docpage { }e; s{^:INC:(.+)\r?\n$}{ $f = sprintf('%s/data/docs/%s', $VNDB::ROOT, $1); - open($F, '<:utf8', $f.$l) or open($F, '<:utf8', $f) or die $!; + open($F, '<:utf8', $f) or die $!; my $ii = join('', <$F>); close $F; $ii; @@ -347,13 +348,13 @@ sub docpage { sub nospam { my $self = shift; - $self->htmlHeader(title => mt '_nospam_title', noindex => 1); + $self->htmlHeader(title => 'Could not send form', noindex => 1); div class => 'mainbox'; - h1 mt '_nospam_title'; + h1 'Could not send form'; div class => 'warning'; - h2 mt '_nospam_subtitle'; - p mt '_nospam_msg'; + h2 'Error'; + p 'The form could not be sent, please make sure you have Javascript enabled in your browser.'; end; end; diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm index 4d8c985d..f3a167c2 100644 --- a/lib/VNDB/Handler/Producers.pm +++ b/lib/VNDB/Handler/Producers.pm @@ -23,7 +23,7 @@ sub rg { my $p = $self->dbProducerGet(id => $pid, what => 'relgraph')->[0]; return $self->resNotFound if !$p->{id} || !$p->{rgraph}; - my $title = mt '_prodrg_title', $p->{name}; + my $title = "Relation graph for $p->{name}"; return if $self->htmlRGHeader($title, 'p', $p); $p->{svg} =~ s/id="node_p$pid"/id="graph_current"/; @@ -63,14 +63,14 @@ sub page { [ lang => 'Language', serialize => sub { "$_[0] ($self->{languages}{$_[0]})" } ], [ website => 'Website', diff => 1 ], [ l_wp => 'Wikipedia link',htmlize => sub { - $_[0] ? sprintf '<a href="http://en.wikipedia.org/wiki/%s">%1$s</a>', xml_escape $_[0] : mt '_revision_nolink' + $_[0] ? sprintf '<a href="http://en.wikipedia.org/wiki/%s">%1$s</a>', xml_escape $_[0] : '[empty]' }], [ desc => 'Description', diff => qr/[ ,\n\.]/ ], [ relations => 'Relations', join => '<br />', split => sub { my @r = map sprintf('%s: <a href="/p%d" title="%s">%s</a>', $self->{prod_relations}{$_->{relation}}[1], $_->{id}, xml_escape($_->{original}||$_->{name}), xml_escape shorten $_->{name}, 40 ), sort { $a->{id} <=> $b->{id} } @{$_[0]}; - return @r ? @r : (mt '_revision_empty'); + return @r ? @r : ('[empty]'); }], ); } @@ -80,16 +80,16 @@ sub page { h1 $p->{name}; h2 class => 'alttitle', $p->{original} if $p->{original}; p class => 'center'; - txt mt '_prodpage_langtype', $self->{languages}{$p->{lang}}, $self->{producer_types}{$p->{type}}; - lit '<br />'.html_escape mt '_prodpage_aliases', $p->{alias} if $p->{alias}; + txt "$self->{languages}{$p->{lang}} $self->{producer_types}{$p->{type}}"; + lit '<br />a.k.a. '.html_escape $p->{alias} if $p->{alias}; my @links = ( - $p->{website} ? [ 'homepage', $p->{website} ] : (), - $p->{l_wp} ? [ 'wikipedia', "http://en.wikipedia.org/wiki/$p->{l_wp}" ] : (), + $p->{website} ? [ 'Homepage', $p->{website} ] : (), + $p->{l_wp} ? [ 'Wikipedia', "http://en.wikipedia.org/wiki/$p->{l_wp}" ] : (), ); br if @links; for(@links) { - a href => $_->[1], mt "_prodpage_$_->[0]"; + a href => $_->[1], $_->[0]; txt ' - ' if $_ ne $links[$#links]; } end 'p'; @@ -130,10 +130,10 @@ sub _releases { # prodpage_(dev|pub) my $r = $self->dbReleaseGet(pid => $p->{id}, results => 999, what => 'vn platforms'); div class => 'mainbox'; - a href => '#', id => 'expandprodrel', mt '_js_collapse'; - h1 mt '_prodpage_rel'; + a href => '#', id => 'expandprodrel', 'collapse'; + h1 'Releases'; if(!@$r) { - p mt '_prodpage_norel'; + p 'We have currently no visual novels by this producer.'; end; return; } @@ -154,8 +154,8 @@ sub _releases { i; lit fmtdatestr $vn{$v->{vid}}[0]{released}; end; a href => "/v$v->{vid}", title => $v->{original}, $v->{title}; span '('.join(', ', - (grep($_->{developer}, @{$vn{$v->{vid}}}) ? mt '_prodpage_dev' : ()), - (grep($_->{publisher}, @{$vn{$v->{vid}}}) ? mt '_prodpage_pub' : ()) + (grep($_->{developer}, @{$vn{$v->{vid}}}) ? 'developer' : ()), + (grep($_->{publisher}, @{$vn{$v->{vid}}}) ? 'publisher' : ()) ).')'; end; end; @@ -173,14 +173,14 @@ sub _releases { end; td class => 'tc4'; a href => "/r$rel->{id}", title => $rel->{original}||$rel->{title}, $rel->{title}; - b class => 'grayedout', ' '.mt '_vnpage_rel_patch' if $rel->{patch}; + b class => 'grayedout', ' (patch)' if $rel->{patch}; end; td class => 'tc5', join ', ', - ($rel->{developer} ? mt '_prodpage_dev' : ()), ($rel->{publisher} ? mt '_prodpage_pub' : ()); + ($rel->{developer} ? 'developer' : ()), ($rel->{publisher} ? 'publisher' : ()); td class => 'tc6'; if($rel->{website}) { a href => $rel->{website}, rel => 'nofollow'; - cssicon 'external', mt '_vnpage_rel_extlink'; + cssicon 'external', 'External link'; end; } else { txt ' '; @@ -262,35 +262,35 @@ sub edit { $frm->{lang} = 'ja' if !$pid && !defined $frm->{lang}; $frm->{editsum} = sprintf 'Reverted to revision p%d.%d', $pid, $rev if $rev && !defined $frm->{editsum}; - my $title = mt $pid ? ('_pedit_title_edit', $p->{name}) : '_pedit_title_add'; + my $title = $pid ? "Edit $p->{name}" : 'Add new producer'; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('p', $p, 'edit') if $pid; $self->htmlEditMessage('p', $p, $title); $self->htmlForm({ frm => $frm, action => $pid ? "/p$pid/edit" : '/p/new', editsum => 1 }, - 'pedit_geninfo' => [ mt('_pedit_form_generalinfo'), - [ select => name => mt('_pedit_form_type'), short => 'type', + 'pedit_geninfo' => [ 'General info', + [ select => name => 'Type', short => 'type', options => [ map [ $_, $self->{producer_types}{$_} ], keys %{$self->{producer_types}} ] ], - [ input => name => mt('_pedit_form_name'), short => 'name' ], - [ input => name => mt('_pedit_form_original'), short => 'original' ], - [ static => content => mt('_pedit_form_original_note') ], - [ input => name => mt('_pedit_form_alias'), short => 'alias', width => 400 ], - [ static => content => mt('_pedit_form_alias_note') ], - [ select => name => mt('_pedit_form_lang'), short => 'lang', + [ input => name => 'Name (romaji)', short => 'name' ], + [ input => name => 'Original name', short => 'original' ], + [ static => content => 'The original name of the producer, leave blank if it is already in the Latin alphabet.' ], + [ input => name => 'Aliases', short => 'alias', width => 400 ], + [ static => content => '(Un)official aliases, separated by a comma.' ], + [ select => name => 'Primary language', short => 'lang', options => [ map [ $_, "$_ ($self->{languages}{$_})" ], keys %{$self->{languages}} ] ], - [ input => name => mt('_pedit_form_website'), short => 'website' ], - [ input => name => mt('_pedit_form_wikipedia'), short => 'l_wp', pre => 'http://en.wikipedia.org/wiki/' ], - [ text => name => mt('_pedit_form_desc').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'desc', rows => 6 ], - ], 'pedit_rel' => [ mt('_pedit_form_rel'), + [ input => name => 'Website', short => 'website' ], + [ input => name => 'Wikipedia link', short => 'l_wp', pre => 'http://en.wikipedia.org/wiki/' ], + [ text => name => 'Description<br /><b class="standout">English please!</b>', short => 'desc', rows => 6 ], + ], 'pedit_rel' => [ 'Relations', [ hidden => short => 'prodrelations' ], [ static => nolabel => 1, content => sub { - h2 mt '_pedit_rel_sel'; + h2 'Selected producers'; table; tbody id => 'relation_tbl'; # to be filled using javascript end; end; - h2 mt '_pedit_rel_add'; + h2 'Add producer'; table; Tr id => 'relation_new'; td class => 'tc_prod'; @@ -303,7 +303,7 @@ sub edit { end; end; td class => 'tc_add'; - a href => '#', mt '_js_add'; + a href => '#', 'add'; end; end; end 'table'; @@ -356,16 +356,16 @@ sub list { page => $f->{p} ); - $self->htmlHeader(title => mt '_pbrowse_title'); + $self->htmlHeader(title => 'Browse producers'); div class => 'mainbox'; - h1 mt '_pbrowse_title'; + h1 'Browse producers'; form action => '/p/all', 'accept-charset' => 'UTF-8', method => 'get'; $self->htmlSearchBox('p', $f->{q}); end; p class => 'browseopts'; for ('all', 'a'..'z', 0) { - a href => "/p/$_", $_ eq $char ? (class => 'optselected') : (), $_ eq 'all' ? mt('_char_all') : $_ ? uc $_ : '#'; + a href => "/p/$_", $_ eq $char ? (class => 'optselected') : (), $_ eq 'all' ? 'ALL' : $_ ? uc $_ : '#'; } end; end; @@ -373,9 +373,9 @@ sub list { my $pageurl = "/p/$char" . ($f->{q} ? "?q=$f->{q}" : ''); $self->htmlBrowseNavigate($pageurl, $f->{p}, $np, 't'); div class => 'mainbox producerbrowse'; - h1 mt $f->{q} ? '_pbrowse_searchres' : '_pbrowse_list'; + h1 $f->{q} ? 'Search results' : 'Producer list'; if(!@$list) { - p mt '_pbrowse_noresults'; + p 'No results found'; } else { # spread the results over 3 equivalent-sized lists my $perlist = @$list/3 < 1 ? 1 : @$list/3; diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index 436ace91..f71d89f4 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -42,13 +42,13 @@ sub page { map sprintf('<a href="/v%d" title="%s">%s</a>', $_->{vid}, $_->{original}||$_->{title}, shorten $_->{title}, 50), @{$_[0]}; } ], [ type => 'Type' ], - [ patch => 'Patch', serialize => sub { mt $_[0] ? '_revision_yes' : '_revision_no' } ], - [ freeware => 'Freeware', serialize => sub { mt $_[0] ? '_revision_yes' : '_revision_no' } ], - [ doujin => 'Doujin', serialize => sub { mt $_[0] ? '_revision_yes' : '_revision_no' } ], + [ patch => 'Patch', serialize => sub { $_[0] ? 'Yes' : 'No' } ], + [ freeware => 'Freeware', serialize => sub { $_[0] ? 'Yes' : 'No' } ], + [ doujin => 'Doujin', serialize => sub { $_[0] ? 'Yes' : 'No' } ], [ title => 'Title (romaji)', diff => 1 ], [ original => 'Original title', diff => 1 ], - [ gtin => 'JAN/UPC/EAN', serialize => sub { $_[0]||mt '_revision_empty' } ], - [ catalog => 'Catalog number', serialize => sub { $_[0]||mt '_revision_empty' } ], + [ gtin => 'JAN/UPC/EAN', serialize => sub { $_[0]||'[empty]' } ], + [ catalog => 'Catalog number', serialize => sub { $_[0]||'[empty]' } ], [ languages => 'Language', join => ', ', split => sub { map $self->{languages}{$_}, @{$_[0]} } ], [ website => 'Website' ], [ released => 'Release date', htmlize => \&fmtdatestr ], @@ -62,7 +62,7 @@ sub page { [ ani_ero => 'Ero animation', serialize => sub { $self->{animated}[$_[0]] } ], [ producers => 'Producers', join => '<br />', split => sub { map sprintf('<a href="/p%d" title="%s">%s</a> (%s)', $_->{id}, $_->{original}||$_->{name}, shorten($_->{name}, 50), - join(', ', $_->{developer} ? mt '_reldiff_developer' :(), $_->{publisher} ? mt '_reldiff_publisher' :()) + join(', ', $_->{developer} ? 'developer' :(), $_->{publisher} ? 'publisher' :()) ), @{$_[0]}; } ], ); @@ -91,7 +91,7 @@ sub _infotable { table class => 'stripe'; Tr; - td class => 'key', mt '_relinfo_vnrel'; + td class => 'key', 'Relation'; td; for (@{$r->{vn}}) { a href => "/v$_->{vid}", title => $_->{original}||$_->{title}, shorten $_->{title}, 60; @@ -101,27 +101,27 @@ sub _infotable { end; Tr; - td mt '_relinfo_title'; + td 'Title'; td $r->{title}; end; if($r->{original}) { Tr; - td mt '_relinfo_original'; + td 'Original title'; td $r->{original}; end; } Tr; - td mt '_relinfo_type'; + td 'Type'; td; cssicon "rt$r->{type}", $r->{type}; - txt ' '.mt '_relinfo_type_format', ucfirst($r->{type}), $r->{patch}?1:0; + txt sprintf ' %s%s', ucfirst($r->{type}), $r->{patch} ? ', patch' : ''; end; end; Tr; - td mt '_relinfo_lang'; + td 'Language'; td; for (@{$r->{languages}}) { cssicon "lang $_", $self->{languages}{$_}; @@ -132,13 +132,15 @@ sub _infotable { end; Tr; - td mt '_relinfo_publication'; - td mt $r->{patch} ? '_relinfo_pub_patch' : '_relinfo_pub_nopatch', $r->{freeware}?0:1, $r->{doujin}?0:1; + td 'Publication'; + td join ', ', + $r->{freeware} ? 'Freeware' : 'Non-free', + $r->{patch} ? () : ($r->{doujin} ? 'doujin' : 'commercial'); end; if(@{$r->{platforms}}) { Tr; - td mt '_relinfo_platform', scalar @{$r->{platforms}}; + td 'Platorm'.(@{$r->{platforms}} == 1 ? '' : 's'); td; for(@{$r->{platforms}}) { cssicon $_, $self->{platforms}{$_}; @@ -151,36 +153,36 @@ sub _infotable { if(@{$r->{media}}) { Tr; - td mt '_relinfo_media', scalar @{$r->{media}}; + td @{$r->{media}} == 1 ? 'Medium' : 'Media'; td join ', ', map fmtmedia($_->{medium}, $_->{qty}), @{$r->{media}}; end; } if($r->{resolution}) { Tr; - td mt '_relinfo_resolution'; + td 'Resolution'; td $self->{resolutions}[$r->{resolution}][0]; end; } if($r->{voiced}) { Tr; - td mt '_relinfo_voiced'; + td 'Voiced'; td $self->{voiced}[$r->{voiced}]; end; } if($r->{ani_story} || $r->{ani_ero}) { Tr; - td mt '_relinfo_ani'; + td 'Animation'; td join ', ', - $r->{ani_story} ? mt('_relinfo_ani_story', $self->{animated}[$r->{ani_story}]):(), - $r->{ani_ero} ? mt('_relinfo_ani_ero', $self->{animated}[$r->{ani_ero}] ):(); + $r->{ani_story} ? "Story: $self->{animated}[$r->{ani_story}]" : (), + $r->{ani_ero} ? "Ero scenes: $self->{animated}[$r->{ani_ero}]" : (); end; } Tr; - td mt '_relinfo_released'; + td 'Released'; td; lit fmtdatestr $r->{released}; end; @@ -188,7 +190,7 @@ sub _infotable { if($r->{minage} >= 0) { Tr; - td mt '_relinfo_minage'; + td 'Age rating'; td minage $r->{minage}; end; } @@ -197,7 +199,7 @@ sub _infotable { my @prod = grep $_->{$t}, @{$r->{producers}}; if(@prod) { Tr; - td mt "_relinfo_$t", scalar @prod; + td ucfirst($t).(@prod == 1 ? '' : 's'); td; for (@prod) { a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 60; @@ -217,16 +219,16 @@ sub _infotable { if($r->{catalog}) { Tr; - td mt '_relinfo_catalog'; + td 'Catalog no.'; td $r->{catalog}; end; } if($r->{website}) { Tr; - td mt '_relinfo_links'; + td 'Links'; td; - a href => $r->{website}, rel => 'nofollow', mt '_relinfo_website'; + a href => $r->{website}, rel => 'nofollow', 'Official website'; end; end; } @@ -234,16 +236,15 @@ sub _infotable { if($self->authInfo->{id}) { my $rl = $self->dbRListGet(uid => $self->authInfo->{id}, rid => $r->{id})->[0]; Tr; - td mt '_relinfo_user'; + td 'User options'; td; Select id => 'listsel', name => $self->authGetCode("/r$r->{id}/list"); - option value => -2, - mt !$rl ? '_relinfo_user_notlist' : ('_relinfo_user_inlist', $self->{rlist_status}[$rl->{status}]); - optgroup label => mt '_relinfo_user_setstatus'; + option value => -2, !$rl ? 'not on your list' : "Status: $self->{rlist_status}[$rl->{status}]"; + optgroup label => 'Set status'; option value => $_, $self->{rlist_status}[$_] for (0..$#{$self->{rlist_status}}); end; - option value => -1, mt '_relinfo_user_del' if $rl; + option value => -1, 'remove from list' if $rl; end; end; end 'tr'; @@ -364,7 +365,7 @@ sub edit { $frm->{title} = $v->{title} if !defined $frm->{title} && !$r; $frm->{original} = $v->{original} if !defined $frm->{original} && !$r; - my $title = mt $rid ? ($copy ? '_redit_title_copy' : '_redit_title_edit', $r->{title}) : ('_redit_title_add', $v->{title}); + my $title = !$rid ? "Add release to $v->{title}" : $copy ? "Copy $r->{title}" : "Edit $r->{title}"; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('r', $r, $copy ? 'copy' : 'edit') if $rid; $self->htmlMainTabs('v', $v, 'edit') if $vid; @@ -378,41 +379,43 @@ sub _form { my($self, $r, $v, $frm, $copy) = @_; $self->htmlForm({ frm => $frm, action => $r ? "/r$r->{id}/".($copy ? 'copy' : 'edit') : "/v$v->{id}/add", editsum => 1 }, - rel_geninfo => [ mt('_redit_form_geninfo'), - [ select => short => 'type', name => mt('_redit_form_type'), + rel_geninfo => [ 'General info', + [ select => short => 'type', name => 'Type', options => [ map [ $_, $_ ], @{$self->{release_types}} ] ], - [ check => short => 'patch', name => mt('_redit_form_patch') ], - [ check => short => 'freeware', name => mt('_redit_form_freeware') ], - [ check => short => 'doujin', name => mt('_redit_form_doujin') ], - [ input => short => 'title', name => mt('_redit_form_title'), width => 450 ], - [ input => short => 'original', name => mt('_redit_form_original'), width => 450 ], - [ static => content => mt '_redit_form_original_note' ], - [ select => short => 'languages', name => mt('_redit_form_languages'), multi => 1, + [ check => short => 'patch', name => 'This release is a patch to another release.' ], + [ check => short => 'freeware', name => 'Freeware (i.e. available at no cost)' ], + [ check => short => 'doujin', name => 'Doujin (self-published, not by a company)' ], + [ input => short => 'title', name => 'Title (romaji)', width => 450 ], + [ input => short => 'original', name => 'Original title', width => 450 ], + [ static => content => 'The original title of this release, leave blank if it already is in the Latin alphabet.' ], + [ select => short => 'languages', name => 'Language(s)', multi => 1, options => [ map [ $_, "$_ ($self->{languages}{$_})" ], keys %{$self->{languages}} ] ], - [ input => short => 'gtin', name => mt('_redit_form_gtin') ], - [ input => short => 'catalog', name => mt('_redit_form_catalog') ], - [ input => short => 'website', name => mt('_redit_form_website') ], - [ date => short => 'released', name => mt('_redit_form_released') ], - [ static => content => mt('_redit_form_released_note') ], - [ select => short => 'minage', name => mt('_redit_form_minage'), + [ input => short => 'gtin', name => 'JAN/UPC/EAN' ], + [ input => short => 'catalog', name => 'Catalog number' ], + [ input => short => 'website', name => 'Official website' ], + [ date => short => 'released', name => 'Release date' ], + [ static => content => 'Leave month or day blank if they are unknown' ], + [ select => short => 'minage', name => 'Age rating', options => [ map [ $_, minage $_, 1 ], @{$self->{age_ratings}} ] ], - [ textarea => short => 'notes', name => mt('_redit_form_notes').'<br /><b class="standout">'.mt('_inenglish').'</b>' ], - [ static => content => mt('_redit_form_notes_note') ], + [ textarea => short => 'notes', name => 'Notes<br /><b class="standout">English please!</b>' ], + [ static => content => + 'Miscellaneous notes/comments, information that does not fit in the above fields.' + .' E.g.: Censored/uncensored or for which releases this patch applies.' ], ], - rel_format => [ mt('_redit_form_format'), - [ select => short => 'resolution', name => mt('_redit_form_resolution'), options => [ + rel_format => [ 'Format', + [ select => short => 'resolution', name => 'Resolution', options => [ map [ $_, @{$self->{resolutions}[$_]} ], 0..$#{$self->{resolutions}} ] ], - [ select => short => 'voiced', name => mt('_redit_form_voiced'), options => [ + [ select => short => 'voiced', name => 'Voiced', options => [ map [ $_, $self->{voiced}[$_] ], 0..$#{$self->{voiced}} ] ], - [ select => short => 'ani_story', name => mt('_redit_form_ani_story'), options => [ + [ select => short => 'ani_story', name => 'Story animation', options => [ map [ $_, $self->{animated}[$_] ], 0..$#{$self->{animated}} ] ], - [ select => short => 'ani_ero', name => mt('_redit_form_ani_ero'), options => [ - map [ $_, $_ ? $self->{animated}[$_] : mt('_redit_form_ani_ero_none') ], 0..$#{$self->{animated}} ] ], - [ static => content => mt('_redit_form_ani_ero_note') ], + [ select => short => 'ani_ero', name => 'Ero animation', options => [ + map [ $_, $_ ? $self->{animated}[$_] : 'Unknown / no ero scenes' ], 0..$#{$self->{animated}} ] ], + [ static => content => 'Animation in erotic scenes, leave to unknown if there are no ero scenes.' ], [ hidden => short => 'media' ], [ static => nolabel => 1, content => sub { - h2 mt '_redit_form_platforms'; + h2 'Platforms'; div class => 'platforms'; for my $p (sort keys %{$self->{platforms}}) { span; @@ -426,38 +429,38 @@ sub _form { } end; - h2 mt '_redit_form_media'; + h2 'Media'; div id => 'media_div', ''; }], ], - rel_prod => [ mt('_redit_form_prod'), + rel_prod => [ 'Producers', [ hidden => short => 'producers' ], [ static => nolabel => 1, content => sub { - h2 mt('_redit_form_prod_sel'); + h2 'Selected producers'; table; tbody id => 'producer_tbl'; end; end; - h2 mt('_redit_form_prod_add'); + h2 'Add producer'; table; Tr; td class => 'tc_name'; input id => 'producer_input', type => 'text', class => 'text'; end; td class => 'tc_role'; Select id => 'producer_role'; - option value => 1, mt '_redit_form_prod_dev'; - option value => 2, selected => 'selected', mt '_redit_form_prod_pub'; - option value => 3, mt '_redit_form_prod_both'; + option value => 1, 'Developer'; + option value => 2, selected => 'selected', 'Publisher'; + option value => 3, 'Both'; end; end; - td class => 'tc_add'; a id => 'producer_add', href => '#', mt '_js_add'; end; + td class => 'tc_add'; a id => 'producer_add', href => '#', 'add'; end; end; end 'table'; }], ], - rel_vn => [ mt('_redit_form_vn'), + rel_vn => [ 'Visual novels', [ hidden => short => 'vn' ], [ static => nolabel => 1, content => sub { - h2 mt('_redit_form_vn_sel'); + h2 'Selected visual novels'; table class => 'stripe'; tbody id => 'vn_tbl'; end; end; - h2 mt('_redit_form_vn_add'); + h2 'Add visual novel'; div; input id => 'vn_input', type => 'text', class => 'text'; - a href => '#', id => 'vn_add', mt '_js_add'; + a href => '#', id => 'vn_add', 'add'; end; }], ], @@ -487,15 +490,15 @@ sub browse { $f->{q} ? ( search => $f->{q} ) : (), }); - $self->htmlHeader(title => mt('_rbrowse_title')); + $self->htmlHeader(title => 'Browse releases'); form method => 'get', action => '/r', 'accept-charset' => 'UTF-8'; div class => 'mainbox'; - h1 mt '_rbrowse_title'; + h1 'Browse releases'; $self->htmlSearchBox('r', $f->{q}); p class => 'filselect'; a id => 'filselect', href => '#r'; - lit '<i>▸</i> '.mt('_js_fil_filters').'<i></i>'; + lit '<i>▸</i> Filters<i></i>'; end; end; input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil}; @@ -511,10 +514,10 @@ sub browse { pageurl => "$uri;s=$f->{s};o=$f->{o}", sorturl => $uri, header => [ - [ mt('_rbrowse_col_released'), 'released' ], - [ mt('_rbrowse_col_minage'), 'minage' ], + [ 'Released', 'released' ], + [ 'Rating', 'minage' ], [ '', '' ], - [ mt('_rbrowse_col_title'), 'title' ], + [ 'Title', 'title' ], ], row => sub { my($s, $n, $l) = @_; @@ -537,9 +540,15 @@ sub browse { ) if @$list; if(($f->{q} || $f->{fil}) && !@$list) { div class => 'mainbox'; - h1 mt '_rbrowse_noresults_title'; + h1 'No results found'; div class => 'notice'; - p mt '_rbrowse_noresults_msg'; + p; + txt 'Sorry, couldn\'t find anything that comes through your filters. You might want to disable a few filters to get more results.'; + br; br; + txt 'Also, keep in mind that we don\'t have all information about all releases.' + .' So e.g. filtering on screen resolution will exclude all releases of which we don\'t know it\'s resolution,' + .' even though it might in fact be in the resolution you\'re looking for.'; + end end; end; } diff --git a/lib/VNDB/Handler/Staff.pm b/lib/VNDB/Handler/Staff.pm index baaa059e..b58759ec 100644 --- a/lib/VNDB/Handler/Staff.pm +++ b/lib/VNDB/Handler/Staff.pm @@ -40,7 +40,7 @@ sub page { [ lang => 'Language', serialize => sub { "$_[0] ($self->{languages}{$_[0]})" } ], [ l_site => 'Official page', diff => 1 ], [ l_wp => 'Wikipedia link', htmlize => sub { - $_[0] ? sprintf '<a href="http://en.wikipedia.org/wiki/%s">%1$s</a>', xml_escape $_[0] : mt '_revision_nolink' + $_[0] ? sprintf '<a href="http://en.wikipedia.org/wiki/%s">%1$s</a>', xml_escape $_[0] : '[empty]' }], [ l_twitter => 'Twitter account', diff => 1 ], [ l_anidb => 'AniDB creator ID', serialize => sub { $_[0] // '' } ], @@ -68,12 +68,12 @@ sub page { end; end; Tr; - td class => 'key', mt '_staff_language'; + td class => 'key', 'Language'; td $self->{languages}{$s->{lang}}; end; if(@{$s->{aliases}}) { Tr; - td class => 'key', mt('_staff_aliases', scalar @{$s->{aliases}}); + td class => 'key', @{$s->{aliases}} == 1 ? 'Alias' : 'Aliases'; td; table class => 'aliases'; for my $alias (@{$s->{aliases}}) { @@ -89,17 +89,17 @@ sub page { end; } my @links = ( - $s->{l_site} ? [ 'site', $s->{l_site} ] : (), - $s->{l_wp} ? [ 'wp', "http://en.wikipedia.org/wiki/$s->{l_wp}" ] : (), - $s->{l_twitter} ? [ 'twitter', "https://twitter.com/$s->{l_twitter}" ] : (), - $s->{l_anidb} ? [ 'anidb', "http://anidb.net/cr$s->{l_anidb}" ] : (), + $s->{l_site} ? [ 'Official page', $s->{l_site} ] : (), + $s->{l_wp} ? [ 'Wikipedia', "http://en.wikipedia.org/wiki/$s->{l_wp}" ] : (), + $s->{l_twitter} ? [ 'Twitter', "https://twitter.com/$s->{l_twitter}" ] : (), + $s->{l_anidb} ? [ 'AniDB', "http://anidb.net/cr$s->{l_anidb}" ] : (), ); if(@links) { Tr; - td class => 'key', mt '_staff_links'; + td class => 'key', 'Links'; td; for(@links) { - a href => $_->[1], mt "_staff_l_$_->[0]"; + a href => $_->[1], $_->[0]; br if $_ != $links[$#links]; } end; @@ -123,16 +123,16 @@ sub _roles { my($self, $s) = @_; return if !@{$s->{roles}}; - h1 class => 'boxtitle', mt '_staff_credits'; + h1 class => 'boxtitle', 'Credits'; $self->htmlBrowse( items => $s->{roles}, class => 'staffroles', header => [ - [ mt '_staff_col_title' ], - [ mt '_staff_col_released' ], - [ mt '_staff_col_role' ], - [ mt '_staff_col_as' ], - [ mt '_staff_col_note' ], + [ 'Title' ], + [ 'Released' ], + [ 'Role' ], + [ 'As' ], + [ 'Note' ], ], row => sub { my($r, $n, $l) = @_; @@ -152,16 +152,16 @@ sub _cast { my($self, $s) = @_; return if !@{$s->{cast}}; - h1 class => 'boxtitle', mt '_staff_voiced', scalar @{$s->{cast}}; + h1 class => 'boxtitle', sprintf 'Voiced characters (%d)', scalar @{$s->{cast}}; $self->htmlBrowse( items => $s->{cast}, class => 'staffroles', header => [ - [ mt '_staff_col_title' ], - [ mt '_staff_col_released' ], - [ mt '_staff_col_cast' ], - [ mt '_staff_col_as' ], - [ mt '_staff_col_note' ], + [ 'Title' ], + [ 'Released' ], + [ 'Cast' ], + [ 'As' ], + [ 'Note' ], ], row => sub { my($r, $n, $l) = @_; @@ -208,7 +208,7 @@ sub edit { { post => 'lang', enum => [ keys %{$self->{languages}} ] }, { post => 'l_wp', required => 0, maxlength => 150, default => '' }, { post => 'l_site', required => 0, template => 'weburl', maxlength => 250, default => '' }, - { post => 'l_twitter', required => 0, maxlength => 16, default => '', regex => [ qr/^\S+$/, mt('_staffe_form_tw_err') ] }, + { post => 'l_twitter', required => 0, maxlength => 16, default => '', regex => [ qr/^\S+$/, 'Invalid twitter username' ] }, { post => 'l_anidb', required => 0, template => 'id', default => undef }, { post => 'aliases', template => 'json', json_sort => ['name','orig'], json_fields => [ { field => 'name', required => 1, maxlength => 200 }, @@ -249,24 +249,24 @@ sub edit { $frm->{editsum} //= sprintf 'Reverted to revision s%d.%d', $sid, $rev if $rev; $frm->{lang} = 'ja' if !$sid && !defined $frm->{lang}; - my $title = mt $s ? ('_staffe_title_edit', $s->{name}) : '_staffe_title_add'; + my $title = $s ? "Edit $s->{name}" : 'Add staff member'; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('s', $s, 'edit') if $s; $self->htmlEditMessage('s', $s, $title); $self->htmlForm({ frm => $frm, action => $s ? "/s$sid/edit" : '/s/new', editsum => 1 }, - staffe_geninfo => [ mt('_staffe_form_generalinfo'), + staffe_geninfo => [ 'General info', [ hidden => short => 'name' ], [ hidden => short => 'original' ], [ hidden => short => 'primary' ], [ json => short => 'aliases' ], $sid && @{$s->{aliases}} ? - [ static => content => mt('_staffe_form_different') ] : (), - [ static => label => mt('_staffe_form_names'), content => sub { + [ static => content => 'You may choose a different primary name.' ] : (), + [ static => label => 'Names', content => sub { table id => 'names'; thead; Tr; td class => 'tc_id'; end; - td class => 'tc_name', mt '_staffe_form_name'; - td class => 'tc_original', mt '_staffe_form_original'; td; end; + td class => 'tc_name', 'Name (romaji)'; + td class => 'tc_original', 'Original'; td; end; end; end; tbody id => 'alias_tbl'; # filled with javascript @@ -274,15 +274,15 @@ sub edit { end; }], [ static => content => '<br />' ], - [ text => name => mt('_staffe_form_note').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'desc', rows => 4 ], - [ select => name => mt('_staffe_form_gender'),short => 'gender', options => [ + [ text => name => 'Staff note<br /><b class="standout">English please!</b>', short => 'desc', rows => 4 ], + [ select => name => 'Gender',short => 'gender', options => [ map [ $_, $self->{genders}{$_} ], qw(unknown m f) ] ], - [ select => name => mt('_staffe_form_lang'), short => 'lang', + [ select => name => 'Primary language', short => 'lang', options => [ map [ $_, "$_ ($self->{languages}{$_})" ], keys %{$self->{languages}} ] ], - [ input => name => mt('_staffe_form_site'), short => 'l_site' ], - [ input => name => mt('_staffe_form_wikipedia'), short => 'l_wp', pre => 'http://en.wikipedia.org/wiki/' ], - [ input => name => mt('_staffe_form_twitter'), short => 'l_twitter' ], - [ input => name => mt('_staffe_form_anidb'), short => 'l_anidb' ], + [ input => name => 'Official page', short => 'l_site' ], + [ input => name => 'Wikipedia link', short => 'l_wp', pre => 'http://en.wikipedia.org/wiki/' ], + [ input => name => 'Twitter username', short => 'l_twitter' ], + [ input => name => 'AniDB creator ID', short => 'l_anidb' ], [ static => content => '<br />' ], ]); @@ -315,21 +315,21 @@ sub list { $quri = '?'.$quri if $quri; my $pageurl = "/s/$char$quri"; - $self->htmlHeader(title => mt '_sbrowse_title'); + $self->htmlHeader(title => 'Browse staff'); form action => '/s/all', 'accept-charset' => 'UTF-8', method => 'get'; div class => 'mainbox'; - h1 mt '_sbrowse_title'; + h1 'Browse staff'; $self->htmlSearchBox('s', $f->{q}); p class => 'browseopts'; for ('all', 'a'..'z', 0) { - a href => "/s/$_$quri", $_ eq $char ? (class => 'optselected') : (), $_ eq 'all' ? mt('_char_all') : $_ ? uc $_ : '#'; + a href => "/s/$_$quri", $_ eq $char ? (class => 'optselected') : (), $_ eq 'all' ? 'ALL' : $_ ? uc $_ : '#'; } end; p class => 'filselect'; a id => 'filselect', href => '#s'; - lit '<i>▸</i> '.mt('_js_fil_filters').'<i></i>'; + lit '<i>▸</i> Filters<i></i>'; end; end; input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil}; @@ -338,9 +338,9 @@ sub list { $self->htmlBrowseNavigate($pageurl, $f->{p}, $np, 't'); div class => 'mainbox staffbrowse'; - h1 mt $f->{q} ? '_sbrowse_searchres' : '_sbrowse_list'; + h1 $f->{q} ? 'Search results' : 'Staff list'; if(!@$list) { - p mt '_sbrowse_noresults'; + p 'No results found'; } else { # spread the results over 3 equivalent-sized lists my $perlist = @$list/3 < 1 ? 1 : @$list/3; diff --git a/lib/VNDB/Handler/Tags.pm b/lib/VNDB/Handler/Tags.pm index 64c69caa..61a3e2b3 100644 --- a/lib/VNDB/Handler/Tags.pm +++ b/lib/VNDB/Handler/Tags.pm @@ -49,7 +49,7 @@ sub tagpage { tag_exc => undef, }); - my $title = mt '_tagp_title', $t->{meta}?0:1, $t->{name}; + my $title = ($t->{meta} ? 'Meta tag: ' : 'Tag: ').$t->{name}; $self->htmlHeader(title => $title, noindex => $t->{state} != 2); $self->htmlMainTabs('g', $t); @@ -58,25 +58,29 @@ sub tagpage { h1 $title; if($t->{state} == 1) { div class => 'warning'; - h2 mt '_tagp_del_title'; + h2 'Tag deleted'; p; - lit mt '_tagp_del_msg'; + txt 'This tag has been removed from the database, and cannot be used or re-added.'; + br; + txt 'File a request on the '; + a href => '/t/db', 'discussion board'; + txt ' if you disagree with this.'; end; end; } else { div class => 'notice'; - h2 mt '_tagp_pending_title'; - p mt '_tagp_pending_msg'; + h2 'Waiting for approval'; + p 'This tag is waiting for a moderator to approve it. You can still use it to tag VNs as you would with a normal tag.'; end; } end 'div'; } div class => 'mainbox'; - a class => 'addnew', href => "/g$tag/add", mt '_tagp_addchild' if $self->authCan('tag') && $t->{state} != 1; + a class => 'addnew', href => "/g$tag/add", 'Create child tag' if $self->authCan('tag') && $t->{state} != 1; h1 $title; - parenttags($t, mt('_tagp_indexlink'), 'g'); + parenttags($t, 'Tags', 'g'); if($t->{description}) { p class => 'description'; @@ -84,44 +88,44 @@ sub tagpage { end; } p class => 'center'; - b mt('_tagp_cat'); + b 'Category'; br; txt $self->{tag_categories}{$t->{cat}}; end; if(@{$t->{aliases}}) { p class => 'center'; - b mt('_tagp_aliases'); + b 'Aliases'; br; lit xml_escape($_).'<br />' for (@{$t->{aliases}}); end; } end 'div'; - childtags($self, mt('_tagp_childs'), 'g', $t) if @{$t->{childs}}; + childtags($self, 'Child tags', 'g', $t) if @{$t->{childs}}; if(!$t->{meta} && $t->{state} == 2) { form action => "/g$t->{id}", 'accept-charset' => 'UTF-8', method => 'get'; div class => 'mainbox'; - a class => 'addnew', href => "/g/links?t=$tag", mt '_tagp_rawvotes'; - h1 mt '_tagp_vnlist'; + a class => 'addnew', href => "/g/links?t=$tag", 'Recently tagged'; + h1 'Visual novels'; p class => 'browseopts'; - a href => "/g$t->{id}?fil=$f->{fil};m=0", $f->{m} == 0 ? (class => 'optselected') : (), mt '_spoilset_0'; - a href => "/g$t->{id}?fil=$f->{fil};m=1", $f->{m} == 1 ? (class => 'optselected') : (), mt '_spoilset_1'; - a href => "/g$t->{id}?fil=$f->{fil};m=2", $f->{m} == 2 ? (class => 'optselected') : (), mt '_spoilset_2'; + a href => "/g$t->{id}?fil=$f->{fil};m=0", $f->{m} == 0 ? (class => 'optselected') : (), 'Hide spoilers'; + a href => "/g$t->{id}?fil=$f->{fil};m=1", $f->{m} == 1 ? (class => 'optselected') : (), 'Show minor spoilers'; + a href => "/g$t->{id}?fil=$f->{fil};m=2", $f->{m} == 2 ? (class => 'optselected') : (), 'Spoil me!'; end; p class => 'filselect'; a id => 'filselect', href => '#v'; - lit '<i>▸</i> '.mt('_js_fil_filters').'<i></i>'; + lit '<i>▸</i> Filters<i></i>'; end; end; input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil}; if(!@$list) { - p; br; br; txt mt '_tagp_novn'; end; + p; br; br; txt 'This tag has not been linked to any visual novels yet, or they were hidden because of your spoiler settings or default filters.'; end; } - p; br; txt mt '_tagp_cached'; end; + p; br; txt 'The list below also includes all visual novels linked to child tags. This list is cached, it can take up to 24 hours after a visual novel has been tagged for it to show up on this page.'; end; end 'div'; end 'form'; $self->htmlBrowseVN($list, $f, $np, "/g$t->{id}?fil=$f->{fil};m=$f->{m}", 1) if @$list; @@ -170,7 +174,7 @@ sub tagedit { push @{$frm->{_err}}, \sprintf 'Tag <a href="/g%d">%s</a> already exists!', $_->{id}, xml_escape $_->{name} for @dups; for(@parents, @merge) { my $c = $self->dbTagGet(name => $_, noid => $tag); - push @{$frm->{_err}}, [ 'parents', 'func', [ 0, mt '_tagedit_err_notfound', $_ ]] if !@$c; + push @{$frm->{_err}}, "Tag '$_' not found" if !@$c; $_ = $c->[0]{id}; } } @@ -204,48 +208,57 @@ sub tagedit { $frm->{parents} ||= join ', ', map $_->{name}, @{$t->{parents}}; } - my $title = $par ? mt('_tagedit_title_add', $par->{name}) : $tag ? mt('_tagedit_title_edit', $t->{name}) : mt '_tagedit_title_new'; + my $title = $par ? "Add child tag to $par->{name}" : $tag ? "Edit tag: $t->{name}" : 'Add new tag'; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('g', $par || $t, 'edit') if $t || $par; if(!$self->authCan('tagmod')) { div class => 'mainbox'; - h1 mt '_tagedit_req_title'; + h1 'Requesting new tag'; div class => 'notice'; - h2 mt '_tagedit_req_subtitle'; + h2 'Your tag must be approved'; p; - lit mt '_tagedit_req_msg'; + txt 'Because all tags have to be approved by moderators, it can take a while before it will show up in the tag list' + .' or on visual novel pages. You can still vote on tag even if it has not been approved yet, though.'; + br; br; + txt 'Also, make sure you\'ve read the '; + a href => '/d10', 'guidelines'; + txt ' so you can predict whether your tag will be accepted or not.'; end; end; end; } $self->htmlForm({ frm => $frm, action => $par ? "/g$par->{id}/add" : $tag ? "/g$tag/edit" : '/g/new' }, 'tagedit' => [ $title, - [ input => short => 'name', name => mt '_tagedit_frm_name' ], + [ input => short => 'name', name => 'Primary name' ], $self->authCan('tagmod') ? ( $tag ? - [ static => label => mt('_tagedit_frm_by'), content => fmtuser($t->{addedby}, $t->{username}) ] : (), - [ select => short => 'state', name => mt('_tagedit_frm_state'), options => [ - map [$_, mt '_tagedit_frm_state'.$_], 0..2 ] ], - [ checkbox => short => 'meta', name => mt '_tagedit_frm_meta' ], + [ static => label => 'Added by', content => fmtuser($t->{addedby}, $t->{username}) ] : (), + [ select => short => 'state', name => 'State', options => [ + [0, 'Awaiting moderation'], [1, 'Deleted/hidden'], [2, 'Approved'] ] ], + [ checkbox => short => 'meta', name => 'This is a meta-tag (only to be used as parent for other tags, not for linking to VN entries)' ], $tag ? - [ static => content => mt '_tagedit_frm_meta_warn' ] : (), + [ static => content => 'WARNING: Checking this option or selecting "Deleted" as state will permanently delete all existing VN relations!' ] : (), ) : (), - [ select => short => 'cat', name => mt('_tagedit_frm_cat'), options => [ + [ select => short => 'cat', name => 'Category', options => [ map [$_, $self->{tag_categories}{$_}], keys %{$self->{tag_categories}} ] ], $self->authCan('tagmod') && $tag ? ( - [ checkbox => short => 'catrec', name => mt '_tagedit_frm_catrec' ], - [ static => content => mt '_tagedit_frm_catrec_warn' ], + [ checkbox => short => 'catrec', name => 'Also edit all child tags to have this category' ], + [ static => content => 'WARNING: This will overwrite the category field for all child tags, this action can not be reverted!' ], ) : (), - [ textarea => short => 'alias', name => mt('_tagedit_frm_alias'), cols => 30, rows => 4 ], - [ textarea => short => 'description', name => mt '_tagedit_frm_desc' ], - [ static => content => mt '_tagedit_frm_desc_msg' ], - [ input => short => 'parents', name => mt '_tagedit_frm_parents' ], - [ static => content => mt '_tagedit_frm_parents_msg' ], + [ textarea => short => 'alias', name => "Aliases\n(separated by newlines)", cols => 30, rows => 4 ], + [ textarea => short => 'description', name => 'Description' ], + [ static => content => 'What should the tag be used for? Having a good description helps users choose which tags to link to a VN.' ], + [ input => short => 'parents', name => 'Parent tags' ], + [ static => content => 'Comma separated list of tag names to be used as parent for this tag.' ], $self->authCan('tagmod') ? ( - [ part => title => mt '_tagedit_frm_merge' ], - [ input => short => 'merge', name => mt '_tagedit_frm_merge_tags' ], - [ static => content => mt '_tagedit_frm_merge_msg' ], + [ part => title => 'Merge tags' ], + [ input => short => 'merge', name => 'Tags to merge' ], + [ static => content => + 'Comma separated list of tag names to merge into this one.' + .' All votes and aliases/names will be moved over to this tag, and the old tags will be deleted.' + .' Just leave this field empty if you don\'t intend to do a merge.' + .'<br />WARNING: this action cannot be undone!' ], ) : (), ]); $self->htmlFooter; @@ -293,21 +306,21 @@ sub taglist { search => $f->{q} ); - $self->htmlHeader(title => mt '_tagb_title'); + $self->htmlHeader(title => 'Browse tags'); div class => 'mainbox'; - h1 mt '_tagb_title'; + h1 'Browse tags'; form action => '/g/list', 'accept-charset' => 'UTF-8', method => 'get'; input type => 'hidden', name => 't', value => $f->{t}; $self->htmlSearchBox('g', $f->{q}); end; p class => 'browseopts'; - a href => "/g/list?q=$f->{q};t=-1", $f->{t} == -1 ? (class => 'optselected') : (), mt '_tagb_state-1'; - a href => "/g/list?q=$f->{q};t=0", $f->{t} == 0 ? (class => 'optselected') : (), mt '_tagb_state0'; - a href => "/g/list?q=$f->{q};t=1", $f->{t} == 1 ? (class => 'optselected') : (), mt '_tagb_state1'; - a href => "/g/list?q=$f->{q};t=2", $f->{t} == 2 ? (class => 'optselected') : (), mt '_tagb_state2'; + a href => "/g/list?q=$f->{q};t=-1", $f->{t} == -1 ? (class => 'optselected') : (), 'All'; + a href => "/g/list?q=$f->{q};t=0", $f->{t} == 0 ? (class => 'optselected') : (), 'Awaiting moderation'; + a href => "/g/list?q=$f->{q};t=1", $f->{t} == 1 ? (class => 'optselected') : (), 'Deleted'; + a href => "/g/list?q=$f->{q};t=2", $f->{t} == 2 ? (class => 'optselected') : (), 'Accepted'; end; if(!@$t) { - p mt '_tagb_noresults'; + p 'No results found'; } end 'div'; if(@$t) { @@ -319,8 +332,8 @@ sub taglist { pageurl => "/g/list?t=$f->{t};q=$f->{q};s=$f->{s};o=$f->{o}", sorturl => "/g/list?t=$f->{t};q=$f->{q}", header => [ - [ mt('_tagb_col_added'), 'added' ], - [ mt('_tagb_col_name'), 'name' ], + [ 'Created', 'added' ], + [ 'Tag', 'name' ], ], row => sub { my($s, $n, $l) = @_; @@ -329,8 +342,8 @@ sub taglist { td class => 'tc3'; a href => "/g$l->{id}", $l->{name}; if($f->{t} == -1) { - b class => 'grayedout', ' '.mt '_tagb_note_awaiting' if $l->{state} == 0; - b class => 'grayedout', ' '.mt '_tagb_note_del' if $l->{state} == 1; + b class => 'grayedout', ' awaiting moderation' if $l->{state} == 0; + b class => 'grayedout', ' deleted' if $l->{state} == 1; } end; end 'tr'; @@ -371,46 +384,46 @@ sub taglinks { return '/g/links'.($qs?"?$qs":'') }; - $self->htmlHeader(noindex => 1, title => mt '_taglink_title'); + $self->htmlHeader(noindex => 1, title => 'Tag link browser'); div class => 'mainbox'; - h1 mt '_taglink_title'; + h1 'Tag link browser'; div class => 'warning'; - h2 mt '_taglink_spoil_title'; - p mt '_taglink_spoil_msg'; + h2 'Spoiler warning'; + p 'This list displays the tag votes of individual users. Spoilery tags are not hidden, and may not even be correctly flagged as such.'; end; br; if($f->{u} || $f->{t} || $f->{v}) { - p mt '_taglink_fil_active'; + p 'Active filters:'; ul; if($f->{u}) { my $o = $self->dbUserGet(uid => $f->{u})->[0]; li; - txt '['; a href => $url->(u=>0), mt '_js_remove'; txt '] '; - txt mt '_taglink_fil_user'; txt ' '; + txt '['; a href => $url->(u=>0), 'remove'; txt '] '; + txt 'User:'; txt ' '; a href => "/u$o->{id}", $o->{username}; end; } if($f->{t}) { my $o = $self->dbTagGet(id => $f->{t})->[0]; li; - txt '['; a href => $url->(t=>0), mt '_js_remove'; txt '] '; - txt mt '_taglink_fil_tag'; txt ' '; + txt '['; a href => $url->(t=>0), 'remove'; txt '] '; + txt 'Tag:'; txt ' '; a href => "/g$o->{id}", $o->{name}; end; } if($f->{v}) { my $o = $self->dbVNGet(id => $f->{v})->[0]; li; - txt '['; a href => $url->(v=>0), mt '_js_remove'; txt '] '; - txt mt '_taglink_fil_vn'; txt ' '; + txt '['; a href => $url->(v=>0), 'remove'; txt '] '; + txt 'Visual novel:'; txt ' '; a href => "/v$o->{id}", $o->{title}; end; } end 'ul'; } - p mt '_taglink_fil_add' unless $f->{v} && $f->{u} && $f->{t}; + p 'Click the arrow beside a user, tag or VN to add it as a filter.' unless $f->{v} && $f->{u} && $f->{t}; end 'div'; $self->htmlBrowse( @@ -421,12 +434,12 @@ sub taglinks { pageurl => $url->(), sorturl => $url->(s=>0,o=>0), header => [ - [ mt('_taglink_col_date'), 'date' ], - [ mt('_taglink_col_user') ], - [ mt('_taglink_col_rating') ], - [ mt('_taglink_col_tag'), 'tag' ], - [ mt('_taglink_col_spoiler') ], - [ mt('_taglink_col_vn'), ], + [ 'Date', 'date' ], + [ 'User' ], + [ 'Rating' ], + [ 'Tag', 'tag' ], + [ 'Spoiler' ], + [ 'Visual novel' ], ], row => sub { my($s, $n, $l) = @_; @@ -443,7 +456,7 @@ sub taglinks { a href => $url->(t=>$l->{tag}), class => 'setfil', '> ' if !$f->{t}; a href => "/g$l->{tag}", $l->{name}; end; - td class => 'tc5', !defined $l->{spoiler} ? ' ' : mt "_spoil_$l->{spoiler}"; + td class => 'tc5', !defined $l->{spoiler} ? ' ' : fmtspoil $l->{spoiler}; td class => 'tc6'; a href => $url->(v=>$l->{vid}), class => 'setfil', '> ' if !$f->{v}; a href => "/v$l->{vid}", shorten $l->{title}, 50; @@ -518,48 +531,50 @@ sub vntagmod { } - my $title = mt '_tagv_title', $v->{title}; + my $title = "Add/remove tags for $v->{title}"; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('v', $v, 'tagmod'); div class => 'mainbox'; h1 $title; div class => 'notice'; - h2 mt '_tagv_msg_title'; + h2 'Tagging'; ul; - li; lit mt '_tagv_msg_guidelines'; end; - li mt '_tagv_msg_submit'; - li mt '_tagv_msg_cache'; + li; txt 'Make sure you have read the '; a href => '/d10', 'guidelines'; txt '!'; end; + li 'Don\'t forget to hit the submit button on the bottom of the page to make your changes permanent.'; + li 'Some tag information on the site is cached, it can take up to an hour for your changes to be visible everywhere.'; end; end; end 'div'; - $self->htmlForm({ action => "/v$vid/tagmod", nosubmit => 1 }, tagmod => [ mt('_tagv_frm_title'), + $self->htmlForm({ action => "/v$vid/tagmod", nosubmit => 1 }, tagmod => [ 'Tags', [ hidden => short => 'taglinks', value => '' ], [ static => nolabel => 1, content => sub { table class => 'tgl stripe'; thead; Tr; td ''; - td colspan => $self->authCan('tagmod') ? 3 : 2, class => 'tc_you', mt '_tagv_col_you'; - td colspan => 3, class => 'tc_others', mt '_tagv_col_others'; + td colspan => $self->authCan('tagmod') ? 3 : 2, class => 'tc_you', 'You'; + td colspan => 3, class => 'tc_others', 'Others'; end; Tr; - td class => 'tc_tagname', mt '_tagv_col_tag'; - td class => 'tc_myvote', mt '_tagv_col_rating'; + td class => 'tc_tagname', 'Tag'; + td class => 'tc_myvote', 'Rating'; td class => 'tc_myover', 'O' if $self->authCan('tagmod'); - td class => 'tc_myspoil', mt '_tagv_col_spoiler'; - td class => 'tc_allvote', mt '_tagv_col_rating'; - td class => 'tc_allspoil', mt '_tagv_col_spoiler'; + td class => 'tc_myspoil', 'Spoiler'; + td class => 'tc_allvote', 'Rating'; + td class => 'tc_allspoil', 'Spoiler'; td class => 'tc_allwho', ''; end; end 'thead'; tfoot; Tr; td colspan => 6; - input type => 'submit', class => 'submit', value => mt('_tagv_save'), style => 'float: right'; + input type => 'submit', class => 'submit', value => 'Save changes', style => 'float: right'; input id => 'tagmod_tag', type => 'text', class => 'text', value => ''; - input id => 'tagmod_add', type => 'button', class => 'submit', value => mt '_tagv_add'; + input id => 'tagmod_add', type => 'button', class => 'submit', value => 'Add tag'; br; p; - lit mt '_tagv_addmsg'; + txt 'Check the '; a href => '/g', 'tag list'; txt ' to browse all available tags.'; + br; + txt 'Can\'t find what you\'re looking for? '; a href => '/g/new', 'Request a new tag'; txt '.'; end; end; end; end 'tfoot'; @@ -599,11 +614,11 @@ sub _tagmod_list { td class => 'tc_allvote'; tagscore $t->{rating}; i $t->{overruled} ? (class => 'grayedout') : (), " ($t->{cnt})"; - b class => 'standout', style => 'font-weight: bold', title => mt('_tagv_overruletip'), ' !' if $t->{overruled}; + b class => 'standout', style => 'font-weight: bold', title => 'Tag overruled. All votes other than that of the moderator who overruled it will be ignored.', ' !' if $t->{overruled}; end; td class => 'tc_allspoil', sprintf '%.2f', $t->{spoiler}; td class => 'tc_allwho'; - a href => "/g/links?v=$vid;t=$t->{id}", mt '_tagv_who'; + a href => "/g/links?v=$vid;t=$t->{id}", 'Who?'; end; end; } @@ -614,26 +629,26 @@ sub _tagmod_list { sub tagindex { my $self = shift; - $self->htmlHeader(title => mt '_tagidx_title'); + $self->htmlHeader(title => 'Tag index'); div class => 'mainbox'; - a class => 'addnew', href => "/g/new", mt '_tagidx_create' if $self->authCan('tag'); - h1 mt '_tagidx_search'; + a class => 'addnew', href => "/g/new", 'Create new tag' if $self->authCan('tag'); + h1 'Search tags'; form action => '/g/list', 'accept-charset' => 'UTF-8', method => 'get'; $self->htmlSearchBox('g', ''); end; end; my $t = $self->dbTTTree(tag => 0, 2); - childtags($self, mt('_tagidx_tree'), 'g', {childs => $t}); + childtags($self, 'Tag tree', 'g', {childs => $t}); table class => 'mainbox threelayout'; Tr; # Recently added td; - a class => 'right', href => '/g/list', mt '_tagidx_browseall'; + a class => 'right', href => '/g/list', 'Browse all tags'; my $r = $self->dbTagGet(sort => 'added', reverse => 1, results => 10, state => 2); - h1 mt '_tagidx_recent'; + h1 'Recently added'; ul; for (@$r) { li; @@ -647,9 +662,9 @@ sub tagindex { # Popular td; - a class => 'addnew', href => "/g/links", mt '_tagidx_rawtags'; + a class => 'addnew', href => "/g/links", 'Recently tagged'; $r = $self->dbTagGet(sort => 'items', reverse => 1, meta => 0, results => 10); - h1 mt '_tagidx_popular'; + h1 'Popular tags'; ul; for (@$r) { li; @@ -662,10 +677,10 @@ sub tagindex { # Moderation queue td; - h1 mt '_tagidx_queue'; + h1 'Awaiting moderation'; $r = $self->dbTagGet(state => 0, sort => 'added', reverse => 1, results => 10); ul; - li mt '_tagidx_queue_empty' if !@$r; + li 'Moderation queue empty! yay!' if !@$r; for (@$r) { li; txt fmtage $_->{added}; @@ -675,9 +690,9 @@ sub tagindex { } li; br; - a href => '/g/list?t=0;o=d;s=added', mt '_tagidx_queue_link'; + a href => '/g/list?t=0;o=d;s=added', 'Moderation queue'; txt ' - '; - a href => '/g/list?t=1;o=d;s=added', mt '_tagidx_denied'; + a href => '/g/list?t=1;o=d;s=added', 'Denied tags'; end; end; end; diff --git a/lib/VNDB/Handler/Traits.pm b/lib/VNDB/Handler/Traits.pm index 979ea0d6..adce5ef7 100644 --- a/lib/VNDB/Handler/Traits.pm +++ b/lib/VNDB/Handler/Traits.pm @@ -31,7 +31,7 @@ sub traitpage { ); return $self->resNotFound if $f->{_err}; - my $title = mt '_traitp_title', $t->{meta}?0:1, $t->{name}; + my $title = sprintf '%s: %s', $t->{meta} ? 'Meta trait' : 'Trait', $t->{name}; $self->htmlHeader(title => $title, noindex => $t->{state} != 2); $self->htmlMainTabs('i', $t); @@ -40,25 +40,27 @@ sub traitpage { h1 $title; if($t->{state} == 1) { div class => 'warning'; - h2 mt '_traitp_del_title'; + h2 'Trait deleted'; p; - lit mt '_traitp_del_msg'; + txt 'This trait has been removed from the database, and cannot be used or re-added. File a request on the '; + a href => '/t/db', 'discussion board'; + txt ' if you disagree with this.'; end; end; } else { div class => 'notice'; - h2 mt '_traitp_pending_title'; - p mt '_traitp_pending_msg'; + h2 'Waiting for approval'; + p 'This trait is waiting for a moderator to approve it.'; end; } end 'div'; } div class => 'mainbox'; - a class => 'addnew', href => "/i$trait/add", mt '_traitp_addchild' if $self->authCan('edit') && $t->{state} != 1; + a class => 'addnew', href => "/i$trait/add", 'Create child trait' if $self->authCan('edit') && $t->{state} != 1; h1 $title; - parenttags($t, mt('_traitp_indexlink'), 'i'); + parenttags($t, 'Traits', 'i'); if($t->{description}) { p class => 'description'; @@ -67,19 +69,19 @@ sub traitpage { } if($t->{sexual}) { p class => 'center'; - b mt '_traitp_sexual'; + b 'Sexual content'; end; } if($t->{alias}) { p class => 'center'; - b mt('_traitp_aliases'); + b 'Aliases'; br; lit html_escape($t->{alias}); end; } end 'div'; - childtags($self, mt('_traitp_childs'), 'i', $t) if @{$t->{childs}}; + childtags($self, 'Child traits', 'i', $t) if @{$t->{childs}}; if(!$t->{meta} && $t->{state} == 2) { my($chars, $np) = $self->filFetchDB(char => $f->{fil}, {}, { @@ -92,25 +94,25 @@ sub traitpage { form action => "/i$t->{id}", 'accept-charset' => 'UTF-8', method => 'get'; div class => 'mainbox'; - h1 mt '_traitp_charlist'; + h1 'Characters'; p class => 'browseopts'; - a href => "/i$trait?m=0", $f->{m} == 0 ? (class => 'optselected') : (), mt '_spoilset_0'; - a href => "/i$trait?m=1", $f->{m} == 1 ? (class => 'optselected') : (), mt '_spoilset_1'; - a href => "/i$trait?m=2", $f->{m} == 2 ? (class => 'optselected') : (), mt '_spoilset_2'; + a href => "/i$trait?m=0", $f->{m} == 0 ? (class => 'optselected') : (), 'Hide spoilers'; + a href => "/i$trait?m=1", $f->{m} == 1 ? (class => 'optselected') : (), 'Show minor spoilers'; + a href => "/i$trait?m=2", $f->{m} == 2 ? (class => 'optselected') : (), 'Spoil me!'; end; p class => 'filselect'; a id => 'filselect', href => '#c'; - lit '<i>▸</i> '.mt('_js_fil_filters').'<i></i>'; + lit '<i>▸</i> Filters<i></i>'; end; end; input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil}; if(!@$chars) { - p; br; br; txt mt '_traitp_nochars'; end; + p; br; br; txt 'This trait has not been linked to any characters yet, or they were hidden because of your spoiler settings.'; end; } - p; br; txt mt '_traitp_cached'; end; + p; br; txt 'The list below also includes all characters linked to child traits. This list is cached, it can take up to 24 hours after a character has been edited for it to show up on this page.'; end; end 'div'; end 'form'; @$chars && $self->charBrowseTable($chars, $np, $f, "/i$trait?m=$f->{m};fil=$f->{fil}"); @@ -153,7 +155,7 @@ sub traitedit { if(!$frm->{_err}) { for(@parents) { my $c = $self->dbTraitGet(id => $_); - push @{$frm->{_err}}, [ 'parents', 'func', [ 0, mt '_tagedit_err_notfound', $_ ]] if !@$c; + push @{$frm->{_err}}, "Trait '$_' not found" if !@$c; $group //= $c->[0]{group}||$c->[0]{id} if @$c; } } @@ -192,38 +194,38 @@ sub traitedit { $frm->{parents} ||= join ' ', map $_->{id}, @{$t->{parents}}; } - my $title = $par ? mt('_traite_title_add', $par->{name}) : $t ? mt('_traite_title_edit', $t->{name}) : mt '_traite_title_new'; + my $title = $par ? "Add child trait to $par->{name}" : $t ? "Edit trait: $t->{name}" : 'Add new trait'; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('i', $par || $t, 'edit') if $t || $par; if(!$self->authCan('tagmod')) { div class => 'mainbox'; - h1 mt '_traite_req_title'; + h1 'Requesting new trait'; div class => 'notice'; - h2 mt '_traite_req_subtitle'; + h2 'Your trait must be approved'; p; - lit mt '_traite_req_msg'; + lit 'Because all traits have to be approved by moderators, it can take a while before your trait will show up in the listings or can be used on character entries.'; end; end; end; } $self->htmlForm({ frm => $frm, action => $par ? "/i$par->{id}/add" : $t ? "/i$trait/edit" : '/i/new' }, 'traitedit' => [ $title, - [ input => short => 'name', name => mt '_traite_frm_name' ], + [ input => short => 'name', name => 'Primary name' ], $self->authCan('tagmod') ? ( $t ? - [ static => label => mt('_traite_frm_by'), content => fmtuser($t->{addedby}, $t->{username}) ] : (), - [ select => short => 'state', name => mt('_traite_frm_state'), options => [ - map [$_, mt '_traite_frm_state'.$_], 0..2 ] ], - [ checkbox => short => 'meta', name => mt '_traite_frm_meta' ] + [ static => label => 'Added by', content => fmtuser($t->{addedby}, $t->{username}) ] : (), + [ select => short => 'state', name => 'State', options => [ + [0,'Awaiting moderation'], [1,'Deleted/hidden'], [2,'Approved'] ] ], + [ checkbox => short => 'meta', name => 'This is a meta trait (only to be used as parent for other traits, not for direct use with characters)' ] ) : (), - [ checkbox => short => 'sexual', name => mt '_traite_frm_sexual' ], - [ textarea => short => 'alias', name => mt('_traite_frm_alias'), cols => 30, rows => 4 ], - [ textarea => short => 'description', name => mt '_traite_frm_desc' ], - [ input => short => 'parents', name => mt '_traite_frm_parents' ], - [ static => content => mt '_traite_frm_parents_msg' ], + [ checkbox => short => 'sexual', name => 'Indicates sexual content' ], + [ textarea => short => 'alias', name => "Aliases\n(Separated by newlines)", cols => 30, rows => 4 ], + [ textarea => short => 'description', name => 'Description' ], + [ input => short => 'parents', name => 'Parent traits' ], + [ static => content => 'List of trait IDs to be used as parent for this trait, separated by a space.' ], $self->authCan('tagmod') ? ( - [ input => short => 'order', name => mt('_traite_frm_gorder'), width => 50, post => ' '.mt('_traite_frm_gorder_msg') ], + [ input => short => 'order', name => 'Group number', width => 50, post => ' (Only used if this trait is a group. Used for ordering, lowest first)' ], ) : (), ]); @@ -267,21 +269,21 @@ sub traitlist { search => $f->{q} ); - $self->htmlHeader(title => mt '_traitb_title'); + $self->htmlHeader(title => 'Browse traits'); div class => 'mainbox'; - h1 mt '_traitb_title'; + h1 'Browse traits'; form action => '/i/list', 'accept-charset' => 'UTF-8', method => 'get'; input type => 'hidden', name => 't', value => $f->{t}; $self->htmlSearchBox('i', $f->{q}); end; p class => 'browseopts'; - a href => "/i/list?q=$f->{q};t=-1", $f->{t} == -1 ? (class => 'optselected') : (), mt '_traitb_state-1'; - a href => "/i/list?q=$f->{q};t=0", $f->{t} == 0 ? (class => 'optselected') : (), mt '_traitb_state0'; - a href => "/i/list?q=$f->{q};t=1", $f->{t} == 1 ? (class => 'optselected') : (), mt '_traitb_state1'; - a href => "/i/list?q=$f->{q};t=2", $f->{t} == 2 ? (class => 'optselected') : (), mt '_traitb_state2'; + a href => "/i/list?q=$f->{q};t=-1", $f->{t} == -1 ? (class => 'optselected') : (), 'All'; + a href => "/i/list?q=$f->{q};t=0", $f->{t} == 0 ? (class => 'optselected') : (), 'Awaiting moderation'; + a href => "/i/list?q=$f->{q};t=1", $f->{t} == 1 ? (class => 'optselected') : (), 'Deleted'; + a href => "/i/list?q=$f->{q};t=2", $f->{t} == 2 ? (class => 'optselected') : (), 'Accepted'; end; if(!@$t) { - p mt '_traitb_noresults'; + p 'No results found'; } end 'div'; if(@$t) { @@ -293,8 +295,8 @@ sub traitlist { pageurl => "/i/list?t=$f->{t};q=$f->{q};s=$f->{s};o=$f->{o}", sorturl => "/i/list?t=$f->{t};q=$f->{q}", header => [ - [ mt('_traitb_col_added'), 'added' ], - [ mt('_traitb_col_name'), 'name' ], + [ 'Created', 'added' ], + [ 'Trait', 'name' ], ], row => sub { my($s, $n, $l) = @_; @@ -306,8 +308,8 @@ sub traitlist { } a href => "/i$l->{id}", $l->{name}; if($f->{t} == -1) { - b class => 'grayedout', ' '.mt '_traitb_note_awaiting' if $l->{state} == 0; - b class => 'grayedout', ' '.mt '_traitb_note_del' if $l->{state} == 1; + b class => 'grayedout', ' awaiting moderation' if $l->{state} == 0; + b class => 'grayedout', ' deleted' if $l->{state} == 1; } end; end 'tr'; @@ -321,26 +323,26 @@ sub traitlist { sub traitindex { my $self = shift; - $self->htmlHeader(title => mt '_traiti_title'); + $self->htmlHeader(title => 'Trait index'); div class => 'mainbox'; - a class => 'addnew', href => "/i/new", mt '_traiti_create' if $self->authCan('edit'); - h1 mt '_traiti_search'; + a class => 'addnew', href => "/i/new", 'Create new trait' if $self->authCan('edit'); + h1 'Search traits'; form action => '/i/list', 'accept-charset' => 'UTF-8', method => 'get'; $self->htmlSearchBox('i', ''); end; end; my $t = $self->dbTTTree(trait => 0, 2); - childtags($self, mt('_traiti_tree'), 'i', {childs => $t}, 'order'); + childtags($self, 'Trait tree', 'i', {childs => $t}, 'order'); table class => 'mainbox threelayout'; Tr; # Recently added td; - a class => 'right', href => '/i/list', mt '_traiti_browseall'; + a class => 'right', href => '/i/list', 'Browse all traits'; my $r = $self->dbTraitGet(sort => 'added', reverse => 1, results => 10); - h1 mt '_traiti_recent'; + h1 'Recently added'; ul; for (@$r) { li; @@ -355,7 +357,7 @@ sub traitindex { # Popular td; - h1 mt '_traiti_popular'; + h1 'Popular traits'; ul; $r = $self->dbTraitGet(sort => 'items', reverse => 1, results => 10); for (@$r) { @@ -370,10 +372,10 @@ sub traitindex { # Moderation queue td; - h1 mt '_traiti_queue'; + h1 'Awaiting moderation'; $r = $self->dbTraitGet(state => 0, sort => 'added', reverse => 1, results => 10); ul; - li mt '_traiti_queue_empty' if !@$r; + li 'Moderation queue empty! yay!' if !@$r; for (@$r) { li; txt fmtage $_->{added}; @@ -384,9 +386,9 @@ sub traitindex { } li; br; - a href => '/i/list?t=0;o=d;s=added', mt '_traiti_queue_link'; + a href => '/i/list?t=0;o=d;s=added', 'Moderation queue'; txt ' - '; - a href => '/i/list?t=1;o=d;s=added', mt '_traiti_denied'; + a href => '/i/list?t=1;o=d;s=added', 'Denied traits'; end; end; end; diff --git a/lib/VNDB/Handler/ULists.pm b/lib/VNDB/Handler/ULists.pm index a19be8e9..f30397b7 100644 --- a/lib/VNDB/Handler/ULists.pm +++ b/lib/VNDB/Handler/ULists.pm @@ -155,17 +155,17 @@ sub votelist { $f->{c} ne 'all' ? ($type eq 'u' ? 'vn_char' : 'user_char', $f->{c}) : (), ); - my $title = mt $type eq 'v' ? '_votelist_title_vn' : '_votelist_title_user', $obj->{title} || $obj->{username}; + my $title = $type eq 'v' ? "Votes for $obj->{title}" : "Votes by $obj->{username}"; $self->htmlHeader(noindex => 1, title => $title); $self->htmlMainTabs($type => $obj, 'votes'); div class => 'mainbox'; h1 $title; p class => 'browseopts'; for ('all', 'a'..'z', 0) { - a href => "/$type$id/votes?c=$_", $_ eq $f->{c} ? (class => 'optselected') : (), $_ eq 'all' ? mt('_char_all') : $_ ? uc $_ : '#'; + a href => "/$type$id/votes?c=$_", $_ eq $f->{c} ? (class => 'optselected') : (), $_ eq 'all' ? 'ALL' : $_ ? uc $_ : '#'; } end; - p mt '_votelist_novotes' if !@$list; + p 'No votes to list. :-(' if !@$list; end; if($own) { @@ -181,9 +181,9 @@ sub votelist { pageurl => "/$type$id/votes?c=$f->{c};o=$f->{o};s=$f->{s}", sorturl => "/$type$id/votes?c=$f->{c}", header => [ - [ mt('_votelist_col_date'), 'date' ], - [ mt('_votelist_col_vote'), 'vote' ], - [ mt('_votelist_col_'.($type eq 'v'?'user':'vn')), 'title' ], + [ 'Cast', 'date' ], + [ 'Vote', 'vote' ], + [ $type eq 'v' ? 'User' : 'Visual novel', 'title' ], ], row => sub { my($s, $n, $l) = @_; @@ -206,7 +206,7 @@ sub votelist { Select name => 'batchedit', id => 'batchedit'; option value => -2, '-- with selected --'; optgroup label => 'Change vote'; - option value => $_, "$_ (".mt("_vote_$_").')' for (reverse 1..10); + option value => $_, sprintf '%d (%s)', $_, fmtrating $_ for (reverse 1..10); end; option value => -1, 'revoke'; end; @@ -256,19 +256,19 @@ sub wishlist { page => $f->{p}, ); - my $title = $own ? mt('_wishlist_title_my') : mt('_wishlist_title_other', $u->{username}); + my $title = $own ? 'My wishlist' : "$u->{username}'s wishlist"; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('u', $u, 'wish'); div class => 'mainbox'; h1 $title; if(!@$list && $f->{f} == -1) { - p mt '_wishlist_noresults'; + p 'Wishlist empty...'; end; return $self->htmlFooter; } p class => 'browseopts'; a $f->{f} == $_ ? (class => 'optselected') : (), href => "/u$uid/wish?f=$_", - $_ == -1 ? mt '_wishlist_prio_all' : $self->{wishlist_status}[$_] + $_ == -1 ? 'All priorities' : $self->{wishlist_status}[$_] for (-1..$#{$self->{wishlist_status}}); end; end 'div'; @@ -286,9 +286,9 @@ sub wishlist { pageurl => "/u$uid/wish?f=$f->{f};o=$f->{o};s=$f->{s}", sorturl => "/u$uid/wish?f=$f->{f}", header => [ - [ mt('_wishlist_col_title') => 'title' ], - [ mt('_wishlist_col_prio') => 'wstat' ], - [ mt('_wishlist_col_added') => 'added' ], + [ 'Title' => 'title' ], + [ 'Priority' => 'wstat' ], + [ 'Added' => 'added' ], ], row => sub { my($s, $n, $i) = @_; @@ -308,12 +308,12 @@ sub wishlist { input type => 'checkbox', class => 'checkall', name => 'sel', value => 0; txt ' '; Select name => 'batchedit', id => 'batchedit'; - option mt '_wishlist_select'; - optgroup label => mt '_wishlist_changeprio'; + option '-- with selected --'; + optgroup label => 'Change priority'; option value => $_, $self->{wishlist_status}[$_] for (0..$#{$self->{wishlist_status}}); end; - option value => -1, mt '_wishlist_remove'; + option value => -1, 'remove from wishlist'; end; end; end; @@ -373,7 +373,7 @@ sub vnlist { $f->{t} >= 0 ? (status => $f->{t}) : (), ); - my $title = $own ? mt '_rlist_title_my' : mt '_rlist_title_other', $u->{username}; + my $title = $own ? 'My visual novel list' : "$u->{username}'s visual novel list"; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('u', $u, 'list'); @@ -396,16 +396,16 @@ sub vnlist { h1 $title; p class => 'browseopts'; for ('all', 'a'..'z', 0) { - a href => $url->(c => $_), $_ eq $f->{c} ? (class => 'optselected') : (), $_ eq 'all' ? mt('_char_all') : $_ ? uc $_ : '#'; + a href => $url->(c => $_), $_ eq $f->{c} ? (class => 'optselected') : (), $_ eq 'all' ? 'ALL' : $_ ? uc $_ : '#'; } end; p class => 'browseopts'; - a href => $url->(v => 0), 0 == $f->{v} ? (class => 'optselected') : (), mt '_rlist_all'; - a href => $url->(v => 1), 1 == $f->{v} ? (class => 'optselected') : (), mt '_rlist_voted_only'; - a href => $url->(v => -1), -1 == $f->{v} ? (class => 'optselected') : (), mt '_rlist_voted_none'; + a href => $url->(v => 0), 0 == $f->{v} ? (class => 'optselected') : (), 'All'; + a href => $url->(v => 1), 1 == $f->{v} ? (class => 'optselected') : (), 'Only voted'; + a href => $url->(v => -1), -1 == $f->{v} ? (class => 'optselected') : (), 'Hide voted'; end; p class => 'browseopts'; - a href => $url->(t => -1), -1 == $f->{t} ? (class => 'optselected') : (), mt '_rlist_all'; + a href => $url->(t => -1), -1 == $f->{t} ? (class => 'optselected') : (), 'All'; a href => $url->(t => $_), $_ == $f->{t} ? (class => 'optselected') : (), $self->{vnlist_status}[$_] for 0..$#{$self->{vnlist_status}}; end; end 'div'; @@ -433,11 +433,11 @@ sub _vnlist_browse { header => [ [ '' ], sub { td class => 'tc2', id => 'expandall'; lit '▸'; end; }, - [ mt('_rlist_col_title') => 'title' ], + [ 'Title' => 'title' ], [ '' ], [ '' ], - [ mt('_rlist_col_status') ], - [ mt('_rlist_col_releases').'*' ], - [ mt('_rlist_col_vote') => 'vote' ], + [ 'Status' ], + [ 'Releases*' ], + [ 'Vote' => 'vote' ], ], row => sub { my($s, $n, $i) = @_; @@ -492,25 +492,25 @@ sub _vnlist_browse { td class => 'tc2'; input type => 'checkbox', name => 'rid', value => 0, class => 'checkall'; end; td class => 'tc3_6', colspan => 4; Select id => 'vns', name => 'vns'; - option value => -2, mt '_rlist_withvn'; - optgroup label => mt '_rlist_changestat'; + option value => -2, '-- with selected VNs --'; + optgroup label => 'Change status'; option value => $_, $self->{vnlist_status}[$_] for (0..$#{$self->{vnlist_status}}); end; - option value => 999, mt '_rlist_setnote'; - option value => -1, mt '_rlist_del'; + option value => 999, 'Set note'; + option value => -1, 'remove from list'; end; Select id => 'rel', name => 'rel'; - option value => -2, mt '_rlist_withrel'; - optgroup label => mt '_rlist_changestat'; + option value => -2, '-- with selected releases --'; + optgroup label => 'Change status'; option value => $_, $self->{rlist_status}[$_] for (0..$#{$self->{rlist_status}}); end; - option value => -1, mt '_rlist_del'; + option value => -1, 'remove from list'; end; - input type => 'submit', value => mt '_rlist_update'; + input type => 'submit', value => 'Update'; end; - td class => 'tc7_8', colspan => 2, mt '_rlist_releasenote'; + td class => 'tc7_8', colspan => 2, '* Obtained/total'; end 'tr'; }) : (), ); diff --git a/lib/VNDB/Handler/Users.pm b/lib/VNDB/Handler/Users.pm index 989b5286..5b6888cb 100644 --- a/lib/VNDB/Handler/Users.pm +++ b/lib/VNDB/Handler/Users.pm @@ -35,7 +35,7 @@ sub userpage { my $votes = $u->{c_votes} && $self->dbVoteStats(uid => $uid); my $list_visible = !$u->{hide_list} || ($self->authInfo->{id}||0) == $u->{id} || $self->authCan('usermod'); - my $title = mt '_userpage_title', $u->{username}; + my $title = "$u->{username}'s profile"; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('u', $u); div class => 'mainbox userpage'; @@ -44,7 +44,7 @@ sub userpage { table class => 'stripe'; Tr; - td class => 'key', mt '_userpage_username'; + td class => 'key', 'Username'; td; txt ucfirst($u->{username}).' ('; a href => "/u$uid", "u$uid"; @@ -53,12 +53,12 @@ sub userpage { end; Tr; - td mt '_userpage_registered'; + td 'Registered'; td fmtdate $u->{registered}; end; Tr; - td mt '_userpage_edits'; + td 'Edits'; td; if($u->{c_changes}) { a href => "/u$uid/hist", $u->{c_changes}; @@ -69,17 +69,18 @@ sub userpage { end; Tr; - td mt '_userpage_votes'; + td 'Votes'; td; if(!$list_visible) { - txt mt '_userpage_hidden'; + txt 'hidden'; } elsif($votes) { my($total, $count) = (0, 0); for (1..@$votes) { $count += $votes->[$_-1][0]; $total += $votes->[$_-1][1]; } - lit mt '_userpage_votes_item', "/u$uid/votes", $count, sprintf '%.2f', $total/$count/10; + a href => "/u$uid/votes", $count; + txt sprintf ' (%.2f average)', $total/$count/10; } else { txt '-'; } @@ -87,31 +88,36 @@ sub userpage { end; Tr; - td mt '_userpage_tags'; + td 'Tags'; td; if(!$u->{c_tags}) { txt '-'; } else { - txt mt '_userpage_tags_item', $u->{c_tags}, $u->{tagcount}, $u->{tagvncount}; - txt ' '; - a href => "/g/links?u=$uid"; lit mt('_userpage_tags_browse').' »'; end; + txt sprintf '%d vote%s on %d distinct tag%s and %d visual novel%s. ', + $u->{c_tags}, $u->{c_tags} == 1 ? '' : 's', + $u->{tagcount}, $u->{tagcount} == 1 ? '' : 's', + $u->{tagvncount}, $u->{tagvncount} == 1 ? '' : 's'; + a href => "/g/links?u=$uid"; lit 'Browse tags »'; end; } end; end; Tr; - td mt '_userpage_list'; - td !$list_visible ? mt('_userpage_hidden') : - mt('_userpage_list_item', $u->{releasecount}, $u->{vncount}); + td 'List stats'; + td !$list_visible ? 'hidden' : + sprintf '%d release%s of %d visual novel%s.', + $u->{releasecount}, $u->{releasecount} == 1 ? '' : 's', + $u->{vncount}, $u->{vncount} == 1 ? '' : 's'; end; Tr; - td mt '_userpage_forum'; + td 'Forum stats'; td; - lit mt '_userpage_forum_item',$u->{postcount}, $u->{threadcount}; + txt sprintf '%d post%s, %d new thread%s. ', + $u->{postcount}, $u->{postcount} == 1 ? '' : 's', + $u->{threadcount}, $u->{threadcount} == 1 ? '' : 's'; if($u->{postcount}) { - txt ' '; - a href => "/u$uid/posts"; lit mt('_userpage_forum_browse').' »'; end; + a href => "/u$uid/posts"; lit 'Browse posts »'; end; } end; end; @@ -120,7 +126,7 @@ sub userpage { if($votes && $list_visible) { div class => 'mainbox'; - h1 mt '_userpage_votestats'; + h1 'Vote statistics'; $self->htmlVoteStats(u => $u, $votes); end; } @@ -128,7 +134,7 @@ sub userpage { if($u->{c_changes}) { my $list = $self->dbRevisionGet(uid => $uid, results => 5); h1 class => 'boxtitle'; - a href => "/u$uid/hist", mt '_userpage_changes'; + a href => "/u$uid/hist", 'Recent changes'; end; $self->htmlBrowseHist($list, { p => 1 }, 0, "/u$uid/hist"); } @@ -143,12 +149,19 @@ sub login { my $tm = $self->dbThrottleGet(norm_ip($self->reqIP)); if($tm-time() > $self->{login_throttle}[1]) { - $self->htmlHeader(title => mt '_login_title'); + $self->htmlHeader(title => 'Login'); div class => 'mainbox'; - h1 mt '_login_title'; + h1 'Login'; div class => 'warning'; - h2 mt '_login_throttle_title'; - p; lit mt '_login_throttle_msg'; end; + h2 'Maximum failed login attempts reached.'; + p; + txt 'Login has been temporarily disabled for your IP address. You can wait a few hours and try again,' + .' or you can try from a different IP address. If you forgot your password, you can still use the '; + a href => '/u/newpass', 'password reset'; + txt ' functionality. If you still have trouble logging in, send a mail to '; + a href => 'mailto:contact@vndb.org', 'contact@vndb.org'; + txt '.'; + end; end; end 'div'; $self->htmlFooter; @@ -173,13 +186,13 @@ sub login { } } - $self->htmlHeader(noindex => 1, title => mt '_login_title'); - $self->htmlForm({ frm => $frm, action => '/u/login' }, login => [ mt('_login_title'), + $self->htmlHeader(noindex => 1, title => 'Login'); + $self->htmlForm({ frm => $frm, action => '/u/login' }, login => [ 'Login', [ hidden => short => 'ref', value => $ref ], - [ input => short => 'usrname', name => mt '_login_username' ], - [ static => content => '<a href="/u/register">'.mt('_login_register').'</a>' ], - [ passwd => short => 'usrpass', name => mt '_login_password' ], - [ static => content => '<a href="/u/newpass">'.mt('_login_forgotpass').'</a>' ], + [ input => short => 'usrname', name => 'Username' ], + [ static => content => '<a href="/u/register">No account yet?</a>' ], + [ passwd => short => 'usrpass', name => 'Password' ], + [ static => content => '<a href="/u/newpass">Forgot your password?</a>' ], ]); $self->htmlFooter; } @@ -211,22 +224,28 @@ sub newpass { my $token; ($token, $o{passwd}) = $self->authPrepareReset(); $self->dbUserEdit($u->{id}, %o); - $self->mail(mt('_newpass_mail_body', $u->{username}, $self->reqBaseURI()."/u$u->{id}/setpass?t=$token"), + my $body = sprintf + "Hello %s,\n\nYour VNDB.org login has been disabled, you can now set a new password by following the link below:\n\n" + ."%s\n\nNow don't forget your password again! :-)\n\nvndb.org", + $u->{username}, $self->reqBaseURI()."/u$u->{id}/setpass?t=$token"; + $self->mail($body, To => $frm->{mail}, From => 'VNDB <noreply@vndb.org>', - Subject => mt('_newpass_mail_subject', $u->{username}), + Subject => "Password reset for $u->{username}", ); return $self->resRedirect('/u/newpass/sent', 'post'); } } - $self->htmlHeader(title => mt('_newpass_title'), noindex => 1); + $self->htmlHeader(title => 'Forgot password', noindex => 1); div class => 'mainbox'; - h1 mt '_newpass_title'; - p mt '_newpass_msg'; + h1 'Forgot password'; + p 'Forgot your password and can\'t login to VNDB anymore?' + .' Don\'t worry! Just give us the email address you used to register on VNDB,' + .' and we\'ll send you instructions to set a new password within a few minutes!'; end; - $self->htmlForm({ frm => $frm, action => '/u/newpass' }, newpass => [ mt('_newpass_reset_title'), - [ input => short => 'mail', name => mt '_newpass_mail' ], + $self->htmlForm({ frm => $frm, action => '/u/newpass' }, newpass => [ 'Reset password', + [ input => short => 'mail', name => 'Email' ], ]); $self->htmlFooter; } @@ -235,11 +254,11 @@ sub newpass { sub newpass_sent { my $self = shift; return $self->resRedirect('/') if $self->authInfo->{id}; - $self->htmlHeader(title => mt('_newpass_sent_title'), noindex => 1); + $self->htmlHeader(title => 'New password', noindex => 1); div class => 'mainbox'; - h1 mt '_newpass_sent_title'; + h1 'New password'; div class => 'notice'; - p mt '_newpass_sent_msg'; + p 'Your password has been reset and instructions to set a new one should reach your mailbox in a few minutes.'; end; end; $self->htmlFooter; @@ -274,11 +293,12 @@ sub setpass { } } - $self->htmlHeader(title => mt('_setpass_title', $u->{username}), noindex => 1); - $self->htmlForm({ frm => $frm, action => "/u$u->{id}/setpass?t=$t" }, setpass => [ mt('_setpass_title', $u->{username}), - [ static => nolabel => 1, content => mt '_setpass_msg' ], - [ passwd => short => 'usrpass', name => mt('_setpass_password') ], - [ passwd => short => 'usrpass2', name => mt('_setpass_confirm') ], + $self->htmlHeader(title => "Set password for $u->{username}", noindex => 1); + $self->htmlForm({ frm => $frm, action => "/u$u->{id}/setpass?t=$t" }, setpass => [ "Set password for $u->{username}", + [ static => nolabel => 1, content => 'Now you can set a password for your account.' + .' You will be logged in automatically after your password has been saved.' ], + [ passwd => short => 'usrpass', name => 'Password' ], + [ passwd => short => 'usrpass2', name => 'Confirm password' ], ]); $self->htmlFooter; } @@ -299,7 +319,7 @@ sub register { ); my $num = $self->{stats}{[qw|vn releases producers|]->[ $frm->{type} - 1 ]}; push @{$frm->{_err}}, 'Question was not correctly answered. Are you sure you are a human?' - if !$frm->{_err} && ($frm->{answer} > $num || $frm->{answer} < $num*0.995); + if !$frm->{_err} && ($frm->{answer} > $num*1.005 || $frm->{answer} < $num*0.995); push @{$frm->{_err}}, 'Someone already has this username, please choose another name' if $frm->{usrname} eq 'anonymous' || !$frm->{_err} && $self->dbUserGet(username => $frm->{usrname})->[0]{id}; push @{$frm->{_err}}, 'Someone already registered with that email address' @@ -314,26 +334,34 @@ sub register { if(!$frm->{_err}) { my($token, $pass) = $self->authPrepareReset(); my $uid = $self->dbUserAdd($frm->{usrname}, $pass, $frm->{mail}); - $self->mail(mt('_register_mail_body', $frm->{usrname}, $self->reqBaseURI()."/u$uid/setpass?t=$token"), + my $body = sprintf "Hello %s,\n\n" + ."Someone has registered an account on VNDB.org with your email address. To confirm your registration, follow the link below.\n\n" + ."%s\n\n" + ."If you don't remember creating an account on VNDB.org recently, please ignore this e-mail.\n\n" + ."vndb.org", + $frm->{usrname}, $self->reqBaseURI()."/u$uid/setpass?t=$token"; + $self->mail($body, To => $frm->{mail}, From => 'VNDB <noreply@vndb.org>', - Subject => mt('_register_mail_subject', $frm->{usrname}), + Subject => "Confirm registration for $frm->{usrname}", ); return $self->resRedirect('/u/register/done', 'post'); } } - $self->htmlHeader(title => mt('_register_title'), noindex => 1); + $self->htmlHeader(title => 'Create an account', noindex => 1); my $type = $frm->{type} || floor(rand 3)+1; - $self->htmlForm({ frm => $frm, action => '/u/register' }, register => [ mt('_register_title'), + $self->htmlForm({ frm => $frm, action => '/u/register' }, register => [ 'Create an account', [ hidden => short => 'type', value => $type ], - [ input => short => 'usrname', name => mt '_register_username' ], - [ static => content => mt '_register_username_msg' ], - [ input => short => 'mail', name => mt '_register_mail' ], - [ static => content => mt('_register_mail_msg').'<br /><br />' ], - [ static => content => '<br /><br />'.mt('_register_question', $type-1) ], - [ input => short => 'answer', name => mt '_register_answer' ], + [ input => short => 'usrname', name => 'Username' ], + [ static => content => 'Preferred username. Must be lowercase and can only consist of alphanumeric characters.' ], + [ input => short => 'mail', name => 'Email' ], + [ static => content => 'Your email address will only be used in case you lose your password.' + .' We will never send spam or newsletters unless you explicitly ask us for it or we get hacked.<br /><br />' ], + [ static => content => sprintf '<br /><br />How many %s do we have in the database? (Hint: look to your left)', + ['visual novels', 'releases', 'producers']->[$type-1] ], + [ input => short => 'answer', name => 'Answer' ], ]); $self->htmlFooter; } @@ -342,11 +370,11 @@ sub register { sub register_done { my $self = shift; return $self->resRedirect('/') if $self->authInfo->{id}; - $self->htmlHeader(title => mt('_register_done_title'), noindex => 1); + $self->htmlHeader(title => 'Account created', noindex => 1); div class => 'mainbox'; - h1 mt '_register_done_title'; + h1 'Account created'; div class => 'notice'; - p mt '_register_done_msg'; + p 'Your account has been created! In a few minutes, you should receive an email with instructions to set your password.'; end; end; $self->htmlFooter; @@ -423,45 +451,48 @@ sub edit { $frm->{usrpass} = $frm->{usrpass2} = $frm->{curpass} = ''; # create the page - $self->htmlHeader(title => mt('_usere_title'), noindex => 1); + $self->htmlHeader(title => 'My account', noindex => 1); $self->htmlMainTabs('u', $u, 'edit'); if($self->reqGet('d')) { div class => 'mainbox'; - h1 mt '_usere_saved_title'; + h1 'Settings saved'; div class => 'notice'; - p mt '_usere_saved_msg'; + p 'Settings successfully saved.'; end; end } - $self->htmlForm({ frm => $frm, action => "/u$uid/edit" }, useredit => [ mt('_usere_title'), - [ part => title => mt '_usere_geninfo' ], + $self->htmlForm({ frm => $frm, action => "/u$uid/edit" }, useredit => [ 'My account', + [ part => title => 'General info' ], $self->authCan('usermod') ? ( - [ input => short => 'usrname', name => mt('_usere_username') ], - [ select => short => 'perms', name => mt('_usere_perm'), multi => 1, size => (scalar keys %{$self->{permissions}}), options => [ + [ input => short => 'usrname', name => 'Username' ], + [ select => short => 'perms', name => 'Permissions', multi => 1, size => (scalar keys %{$self->{permissions}}), options => [ map [ $_, $_ ], sort keys %{$self->{permissions}} ] ], - [ check => short => 'ign_votes', name => mt '_usere_ignvotes' ], + [ check => short => 'ign_votes', name => 'Ignore votes in VN statistics' ], ) : ( - [ static => label => mt('_usere_username'), content => $frm->{usrname} ], + [ static => label => 'Username', content => $frm->{usrname} ], ), - [ input => short => 'mail', name => mt '_usere_mail' ], - - [ part => title => mt '_usere_changepass' ], - [ static => content => mt '_usere_changepass_msg' ], - [ passwd => short => 'curpass', name => mt '_usere_curpass' ], - [ passwd => short => 'usrpass', name => mt '_usere_password' ], - [ passwd => short => 'usrpass2', name => mt '_usere_confirm' ], - - [ part => title => mt '_usere_options' ], - [ check => short => 'hide_list', name => mt '_usere_flist', "/u$uid/list", "/u$uid/votes", "/u$uid/wish" ], - [ check => short => 'show_nsfw', name => mt '_usere_fnsfw' ], - [ check => short => 'traits_sexual', name => mt '_usere_fsextraits' ], - [ check => short => 'tags_all', name => mt '_usere_ftags' ], - [ select => short => 'tags_cat', name => mt('_usere_tagcats'), multi => 1, size => 3, + [ input => short => 'mail', name => 'Email' ], + + [ part => title => 'Change password' ], + [ static => content => 'Leave blank to keep your current password' ], + [ passwd => short => 'curpass', name => 'Current Password' ], + [ passwd => short => 'usrpass', name => 'New Password' ], + [ passwd => short => 'usrpass2', name => 'Confirm password' ], + + [ part => title => 'Options' ], + [ check => short => 'hide_list', name => + qq{Don't allow other people to see my visual novel list (<a href="/u$uid/list">/u$uid/list</a>), + votes (<a href="/u$uid/votes">/u$uid/votes</a>) and wishlist (<a href="/u$uid/wish">/u$uid/wish</a>).} ], + [ check => short => 'show_nsfw', name => 'Disable warnings for images that are not safe for work.' ], + [ check => short => 'traits_sexual', name => 'Show sexual traits by default on character pages.' ], + [ check => short => 'tags_all', name => 'Show all tags by default on visual novel pages.' ], + [ select => short => 'tags_cat', name => 'Tag categories', multi => 1, size => 3, options => [ map [ $_, $self->{tag_categories}{$_} ], keys %{$self->{tag_categories}} ] ], - [ select => short => 'spoilers', name => mt('_usere_spoilers'), options => [ map [ $_, mt '_spoilset_'.$_ ], 0..2 ] ], - [ select => short => 'skin', name => mt('_usere_skin'), width => 300, options => [ + [ select => short => 'spoilers', name => 'Spoiler level', options => [ + [0, 'Hide spoilers'], [1, 'Show only minor spoilers'], [2, 'Show all spoilers'] ]], + [ select => short => 'skin', name => 'Preferred skin', width => 300, options => [ map [ $_, $self->{skins}{$_}[0].($self->debug?" [$_]":'') ], sort { $self->{skins}{$a}[0] cmp $self->{skins}{$b}[0] } keys %{$self->{skins}} ] ], - [ textarea => short => 'customcss', name => mt '_usere_css' ], + [ textarea => short => 'customcss', name => 'Additional <a href="http://en.wikipedia.org/wiki/Cascading_Style_Sheets">CSS</a>' ], ]); $self->htmlFooter; } @@ -481,13 +512,13 @@ sub posts { my($posts, $np) = $self->dbPostGet(uid => $uid, hide => 1, what => 'thread', page => $f->{p}, sort => 'date', reverse => 1); - my $title = mt '_uposts_title', $u->{username}; + my $title = "Posts made by $u->{username}"; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs(u => $u, 'posts'); div class => 'mainbox'; h1 $title; if(!@$posts) { - p mt '_uposts_noresults', $u->{username}; + p "$u->{username} hasn't made any posts yet."; } end; @@ -500,8 +531,8 @@ sub posts { header => [ [ '' ], [ '' ], - [ mt '_uposts_col_date' ], - [ mt '_uposts_col_title' ], + [ 'Date' ], + [ 'Title' ], ], row => sub { my($s, $n, $l) = @_; @@ -574,16 +605,16 @@ sub list { ); return $self->resNotFound if $f->{_err}; - $self->htmlHeader(noindex => 1, title => mt '_ulist_title'); + $self->htmlHeader(noindex => 1, title => 'Browse users'); div class => 'mainbox'; - h1 mt '_ulist_title'; + h1 'Browse users'; form action => '/u/all', 'accept-charset' => 'UTF-8', method => 'get'; $self->htmlSearchBox('u', $f->{q}); end; p class => 'browseopts'; for ('all', 'a'..'z', 0) { - a href => "/u/$_", $_ eq $char ? (class => 'optselected') : (), $_ eq 'all' ? mt('_char_all') : $_ ? uc $_ : '#'; + a href => "/u/$_", $_ eq $char ? (class => 'optselected') : (), $_ eq 'all' ? 'ALL' : $_ ? uc $_ : '#'; } end; end; @@ -605,11 +636,11 @@ sub list { pageurl => "/u/$char?o=$f->{o};s=$f->{s};q=$f->{q}", sorturl => "/u/$char?q=$f->{q}", header => [ - [ mt('_ulist_col_username'), 'username' ], - [ mt('_ulist_col_registered'), 'registered' ], - [ mt('_ulist_col_votes'), 'votes' ], - [ mt('_ulist_col_edits'), 'changes' ], - [ mt('_ulist_col_tags'), 'tags' ], + [ 'Username', 'username' ], + [ 'Registered', 'registered' ], + [ 'Votes', 'votes' ], + [ 'Edits', 'changes' ], + [ 'Tags', 'tags' ], ], row => sub { my($s, $n, $l) = @_; @@ -683,19 +714,27 @@ sub notifies { reverse => $f->{r} == 1, ); - $self->htmlHeader(title => mt('_usern_title'), noindex => 1); + $self->htmlHeader(title => 'My notifications', noindex => 1); $self->htmlMainTabs(u => $u); div class => 'mainbox'; - h1 mt '_usern_title'; + h1 'My notifications'; p class => 'browseopts'; - a !$f->{r} ? (class => 'optselected') : (), href => "/u$uid/notifies?r=0", mt '_usern_o_unread'; - a $f->{r} ? (class => 'optselected') : (), href => "/u$uid/notifies?r=1", mt '_usern_o_alsoread'; + a !$f->{r} ? (class => 'optselected') : (), href => "/u$uid/notifies?r=0", 'Unread notifications'; + a $f->{r} ? (class => 'optselected') : (), href => "/u$uid/notifies?r=1", 'All notifications'; end; - p mt '_usern_nonotifies' if !@$list; + p 'No notifications!' if !@$list; end; my $code = $self->authGetCode("/u$uid/notifies"); + my %ntypes = ( + pm => 'Private Message', + dbdel => 'Entry you contributed to has been deleted', + listdel => 'VN in your (wish)list has been deleted', + dbedit => 'Entry you contributed to has been edited', + announce => 'Site announcement', + ); + if(@$list) { form action => "/u$uid/notifies?r=$f->{r};formcode=$code", method => 'post', id => 'notifies'; $self->htmlBrowse( @@ -706,10 +745,10 @@ sub notifies { pageurl => "/u$uid/notifies?r=$f->{r}", header => [ [ '' ], - [ mt '_usern_col_type' ], - [ mt '_usern_col_age' ], - [ mt '_usern_col_id' ], - [ mt '_usern_col_act' ], + [ 'Type' ], + [ 'Age' ], + [ 'ID' ], + [ 'Action' ], ], row => sub { my($s, $n, $l) = @_; @@ -717,16 +756,17 @@ sub notifies { td class => 'tc1'; input type => 'checkbox', name => 'notifysel', value => "$l->{id}"; end; - td class => 'tc2', mt "_usern_type_$l->{ntype}"; + td class => 'tc2', $ntypes{$l->{ntype}}; td class => 'tc3', fmtage $l->{date}; td class => 'tc4'; a href => "/u$uid/notify/$l->{id}", "$l->{ltype}$l->{iid}".($l->{subid}?".$l->{subid}":''); end; td class => 'tc5 clickable', id => "notify_$l->{id}"; - lit mt '_usern_n_'.( - $l->{ltype} eq 't' ? ($l->{subid} == 1 ? 't_new' : 't_reply') - : 'item_edit'), - sprintf('<i>%s</i>', xml_escape $l->{c_title}), sprintf('<i>%s</i>', xml_escape $l->{username}); + lit sprintf + $l->{ltype} ne 't' ? 'Edit of %s by %s' : + $l->{subid} == 1 ? 'New thread %s by %s' : 'Reply to %s by %s', + sprintf('<i>%s</i>', xml_escape $l->{c_title}), + sprintf('<i>%s</i>', xml_escape $l->{username}); end; end 'tr'; }, @@ -735,9 +775,9 @@ sub notifies { td colspan => 5; input type => 'checkbox', class => 'checkall', name => 'notifysel', value => 0; txt ' '; - input type => 'submit', name => 'markread', value => mt '_usern_but_markread'; - input type => 'submit', name => 'remove', value => mt '_usern_but_remove'; - b class => 'grayedout', ' '.mt '_usern_autodel'; + input type => 'submit', name => 'markread', value => 'mark selected read'; + input type => 'submit', name => 'remove', value => 'remove selected'; + b class => 'grayedout', ' (Read notifications are automatically removed after one month)'; end; end; } @@ -747,17 +787,19 @@ sub notifies { form method => 'post', action => "/u$uid/notifies?formcode=$code"; div class => 'mainbox'; - h1 mt '_usern_set_title'; - div class => 'notice', mt '_usern_set_saved' if $saved; + h1 'Settings'; + div class => 'notice', 'Settings successfully saved.' if $saved; p; for('nodbedit', 'announce') { - my $def = $_ eq 'nodbedit'? 0 : 1; + my $def = $_ eq 'nodbedit' ? 0 : 1; input type => 'checkbox', name => "notify_$_", id => "notify_$_", value => $def, ($self->authPref("notify_$_")||0) == $def ? (checked => 'checked') : (); - label for => "notify_$_", ' '.mt("_usern_set_$_"); + label for => "notify_$_", $_ eq 'nodbedit' + ? ' Notify me about edits of database entries I contributed to.' + : ' Notify me about site announcements.'; br; } - input type => 'submit', name => 'set', value => mt '_usern_set_submit'; + input type => 'submit', name => 'set', value => 'Save'; end; end; end 'form'; diff --git a/lib/VNDB/Handler/VNBrowse.pm b/lib/VNDB/Handler/VNBrowse.pm index cef51f11..af9a7d70 100644 --- a/lib/VNDB/Handler/VNBrowse.pm +++ b/lib/VNDB/Handler/VNBrowse.pm @@ -72,7 +72,7 @@ sub list { $self->resRedirect('/v'.$list->[0]{id}, 'temp') if $f->{q} && @$list == 1 && $f->{p} == 1; - $self->htmlHeader(title => mt('_vnbrowse_title'), search => $f->{q}); + $self->htmlHeader(title => 'Browse visual novels', search => $f->{q}); my $quri = uri_escape($f->{q}); form action => '/v/all', 'accept-charset' => 'UTF-8', method => 'get'; @@ -86,26 +86,26 @@ sub list { }; div class => 'mainbox'; - h1 mt '_vnbrowse_title'; + h1 'Browse visual novels'; $self->htmlSearchBox('v', $f->{q}); p class => 'browseopts'; for ('all', 'a'..'z', 0) { - a href => $url->($_), $_ eq $char ? (class => 'optselected') : (), $_ eq 'all' ? mt('_char_all') : $_ ? uc $_ : '#'; + a href => $url->($_), $_ eq $char ? (class => 'optselected') : (), $_ eq 'all' ? 'ALL' : $_ ? uc $_ : '#'; } end; if($uid) { p class => 'browseopts'; - a href => $url->($char, 'vnlist'), $f->{vnlist} ? (class => 'optselected') : (), mt('_vnbrowse_vnlist'); - a href => $url->($char, 'wish' ), $f->{wish} ? (class => 'optselected') : (), mt('_vnbrowse_wishlist'); + a href => $url->($char, 'vnlist'), $f->{vnlist} ? (class => 'optselected') : (), 'User VN list'; + a href => $url->($char, 'wish' ), $f->{wish} ? (class => 'optselected') : (), 'Wishlist'; end 'p'; } p class => 'filselect'; a id => 'filselect', href => '#v'; - lit '<i>▸</i> '.mt('_vnbrowse_fil_title').'<i></i>'; + lit '<i>▸</i> Visual Novel Filters<i></i>'; end; a id => 'rfilselect', href => '#r'; - lit '<i>▸</i> '.mt('_rbrowse_fil_title').'<i></i>'; + lit '<i>▸</i> Release filters<i></i>'; end; end; input type => 'hidden', class => 'hidden', name => 'fil', id => 'fil', value => $f->{fil}; diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm index 1319cd43..91217aa2 100644 --- a/lib/VNDB/Handler/VNEdit.pm +++ b/lib/VNDB/Handler/VNEdit.pm @@ -44,12 +44,18 @@ sub addform { return edit($self, undef, undef, 1) if !@$l && !$frm->{_err}; } - $self->htmlHeader(title => mt('_vnedit_title_add'), noindex => 1); + $self->htmlHeader(title => 'Add a new visual novel', noindex => 1); if(@$l) { div class => 'mainbox'; - h1 mt '_vnedit_dup_title'; + h1 'Possible duplicates found'; div class => 'warning'; - p; lit mt '_vnedit_dup_msg'; end; + p; + txt 'The following is a list of visual novels that match the title(s) you gave.' + .' Please check this list to avoid creating a duplicate visual novel entry.' + .' Be especially wary of items that have been deleted! To see why an entry has been deleted, click on its title.'; + br; br; + txt 'To add the visual novel anyway, hit the "Continue and ignore duplicates" button below.'; + end; end; ul; for(@$l) { @@ -63,12 +69,12 @@ sub addform { } $self->htmlForm({ frm => $frm, action => '/v/add', continue => @$l ? 2 : 1 }, - vn_add => [ mt('_vnedit_title_add'), - [ input => short => 'title', name => mt('_vnedit_frm_title'), width => 450 ], - [ input => short => 'original', name => mt('_vnedit_original'), width => 450 ], - [ static => content => mt '_vnedit_original_msg' ], - [ textarea => short => 'alias', name => mt('_vnedit_alias'), rows => 4 ], - [ static => content => mt '_vnedit_alias_msg' ], + vn_add => [ 'Add a new visual novel', + [ input => short => 'title', name => 'Title (romaji)', width => 450 ], + [ input => short => 'original', name => 'Original title', width => 450 ], + [ static => content => 'The original title of this visual novel, leave blank if it already is in the Latin alphabet.' ], + [ textarea => short => 'alias', name => 'Aliases', rows => 4 ], + [ static => content => 'List of alternative titles or abbreviations. One line for each alias.' ], ]); $self->htmlFooter; } @@ -196,7 +202,7 @@ sub edit { !exists $frm->{$_} && ($frm->{$_} = $b4{$_}) for (keys %b4); $frm->{editsum} = sprintf 'Reverted to revision v%d.%d', $vid, $rev if $rev && !defined $frm->{editsum}; - my $title = $vid ? mt('_vnedit_title_edit', $v->{title}) : mt '_vnedit_title_add'; + my $title = $vid ? "Edit $v->{title}" : 'Add a new visual novel'; $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('v', $v, 'edit') if $vid; $self->htmlEditMessage('v', $v, $title); @@ -249,51 +255,61 @@ sub _form { my($self, $v, $frm, $r, $chars) = @_; my $import = @$chars ? $self->dbVNImportSeiyuu($v->{id}, [ map $_->{id}, @$chars ]) : []; $self->htmlForm({ frm => $frm, action => $v ? "/v$v->{id}/edit" : '/v/new', editsum => 1, upload => 1 }, - vn_geninfo => [ mt('_vnedit_geninfo'), - [ input => short => 'title', name => mt('_vnedit_frm_title'), width => 450 ], - [ input => short => 'original', name => mt('_vnedit_original'), width => 450 ], - [ static => content => mt '_vnedit_original_msg' ], - [ textarea => short => 'alias', name => mt('_vnedit_alias'), rows => 4 ], - [ static => content => mt '_vnedit_alias_msg' ], - [ textarea => short => 'desc', name => mt('_vnedit_desc').'<br /><b class="standout">'.mt('_inenglish').'</b>', rows => 10 ], - [ static => content => mt '_vnedit_desc_msg' ], - [ select => short => 'length', name => mt('_vnedit_length'), width => 450, options => + vn_geninfo => [ 'General info', + [ input => short => 'title', name => 'Title (romaji)', width => 450 ], + [ input => short => 'original', name => 'Original title', width => 450 ], + [ static => content => 'The original title of this visual novel, leave blank if it already is in the Latin alphabet.' ], + [ textarea => short => 'alias', name => 'Aliases', rows => 4 ], + [ static => content => + 'List of alternative titles or abbreviations. One line for each alias.' + .' Can include both official (japanese/english) titles and unofficial titles used around net.<br />' + .' Titles that are listed in the releases should not be added here!' ], + [ textarea => short => 'desc', name => 'Description<br /><b class="standout">English please!</b>', rows => 10 ], + [ static => content => + 'Short description of the main story. Please do not include spoilers, and don\'t forget to list' + .' the source in case you didn\'t write the description yourself. Formatting codes are allowed.' ], + [ select => short => 'length', name => 'Length', width => 450, options => [ map [ $_ => fmtvnlen $_, 2 ], 0..$#{$self->{vn_lengths}} ] ], - [ input => short => 'l_wp', name => mt('_vnedit_links'), pre => 'http://en.wikipedia.org/wiki/' ], + [ input => short => 'l_wp', name => 'External links', pre => 'http://en.wikipedia.org/wiki/' ], [ input => short => 'l_encubed', pre => 'http://novelnews.net/tag/', post => '/' ], [ input => short => 'l_renai', pre => 'http://renai.us/game/', post => '.shtml' ], - [ input => short => 'anime', name => mt '_vnedit_anime' ], - [ static => content => mt '_vnedit_anime_msg' ], + [ input => short => 'anime', name => 'Anime' ], + [ static => content => + 'Whitespace separated list of <a href="http://anidb.net/">AniDB</a> anime IDs.' + .' E.g. "1015 3348" will add <a href="http://anidb.net/a1015">Shingetsutan Tsukihime</a>' + .' and <a href="http://anidb.net/a3348">Fate/stay night</a> as related anime.<br />' + .' Note: It can take a few minutes for the anime titles to appear on the VN page.' ], ], - vn_img => [ mt('_vnedit_image'), [ static => nolabel => 1, content => sub { + vn_img => [ 'Image', [ static => nolabel => 1, content => sub { div class => 'img'; - p mt '_vnedit_image_none' if !$frm->{image}; + p 'No image uploaded yet' if !$frm->{image}; img src => imgurl(cv => $frm->{image}) if $frm->{image}; end; div; - h2 mt '_vnedit_image_id'; + h2 'Image ID'; input type => 'text', class => 'text', name => 'image', id => 'image', value => $frm->{image}||''; - p mt '_vnedit_image_id_msg'; + p 'Use a VN image that is already on the server. Set to \'0\' to remove the current image.'; br; br; - h2 mt '_vnedit_image_upload'; + h2 'Upload new image'; input type => 'file', class => 'text', name => 'img', id => 'img'; - p mt('_vnedit_image_upload_msg'); + p 'Preferably the cover of the CD/DVD/package. Image must be in JPEG or PNG format' + .' and at most 5MB. Images larger than 256x400 will automatically be resized.'; br; br; br; - h2 mt '_vnedit_image_nsfw'; + h2 'NSFW'; input type => 'checkbox', class => 'checkbox', id => 'img_nsfw', name => 'img_nsfw', $frm->{img_nsfw} ? (checked => 'checked') : (); - label class => 'checkbox', for => 'img_nsfw', mt '_vnedit_image_nsfw_check'; - p mt '_vnedit_image_nsfw_msg'; + label class => 'checkbox', for => 'img_nsfw', 'Not Safe For Work'; + p 'Please check this option if the image contains nudity, gore, or is otherwise not safe in a work-friendly environment.'; end 'div'; }]], - vn_staff => [ mt('_vnedit_staff'), + vn_staff => [ 'Staff', [ json => short => 'credits' ], [ static => nolabel => 1, content => sub { # propagate staff ids and names to javascript @@ -304,13 +320,15 @@ sub _form { script_json staffdata => \%staff_data; div class => 'warning'; - lit mt '_vnedit_staff_msg'; + lit 'Please check the <a href="/d2.3">staff editing guidelines</a>. You can' + .' <a href="/s/new">create a new staff entry</a> if it is not in the database yet,' + .' but please <a href="/s/all">check for aliasses first</a>.'; end; br; table; tbody id => 'credits_tbl'; - Tr id => 'credits_loading'; td colspan => '4', mt('_js_loading'); end; + Tr id => 'credits_loading'; td colspan => '4', 'Loading...'; end; end; end; - h2 mt '_vnstaffe_add'; + h2 'Add staff'; table; Tr; td class => 'tc_staff'; input id => 'credit_input', type => 'text', class => 'text'; end; @@ -321,7 +339,7 @@ sub _form { # Cast tab is only shown for VNs with some characters listed. # There's no way to add voice actors in new VN edits since character list # would be empty anyway. - @{$chars} ? (vn_cast => [ mt('_vnedit_cast'), + @{$chars} ? (vn_cast => [ 'Cast', [ json => short => 'seiyuu' ], [ static => nolabel => 1, content => sub { if (@$import) { @@ -329,17 +347,17 @@ sub _form { map { my $c = $_; +{ map { $_ => $c->{$_} } qw|cid sid aid name| } } @$import ]; div id => 'cast_import'; - a href => '#', title => mt('_vnedit_cast_import_title'), mt '_vnedit_cast_import'; + a href => '#', title => 'Import character cast from related visual novels', 'Import cast'; end; } table; tbody id => 'cast_tbl'; - Tr id => 'cast_loading'; td colspan => '4', mt '_js_loading'; end; + Tr id => 'cast_loading'; td colspan => '4', 'Loading...'; end; end; end; - h2 mt '_vnedit_cast_add'; + h2 'Add cast'; table; Tr; td class => 'tc_char'; Select id =>'cast_chars'; - option value => '', mt '_vnedit_cast_sel_char'; + option value => '', 'Select character'; for my $i (0..$#$chars) { my($name, $id) = @{$chars->[$i]}{qw|name id|}; # append character IDs to coinciding names @@ -349,7 +367,7 @@ sub _form { option value => $id, $name; } end; - txt ' '.mt '_vnedit_voiced_by'; + txt ' voiced by'; end; td class => 'tc_staff'; input id => 'cast_input', type => 'text', class => 'text'; @@ -358,43 +376,43 @@ sub _form { end; end; }]]) : (), - vn_rel => [ mt('_vnedit_rel'), + vn_rel => [ 'Relations', [ hidden => short => 'vnrelations' ], [ static => nolabel => 1, content => sub { - h2 mt '_vnedit_rel_sel'; + h2 'Selected relations'; table; tbody id => 'relation_tbl'; # to be filled using javascript end; end; - h2 mt '_vnedit_rel_add'; + h2 'Add relation'; table; Tr id => 'relation_new'; td class => 'tc_vn'; input type => 'text', class => 'text'; end; td class => 'tc_rel'; - txt mt('_vnedit_rel_isa').' '; + txt 'is an '; input type => 'checkbox', id => 'official', checked => 'checked'; - label for => 'official', mt '_vnedit_rel_official'; + label for => 'official', 'official'; Select; option value => $_, $self->{vn_relations}{$_}[1] for (keys %{$self->{vn_relations}}); end; - txt ' '.mt '_vnedit_rel_of'; + txt ' of'; end; td class => 'tc_title', $v ? $v->{title} : ''; td class => 'tc_add'; - a href => '#', mt '_js_add'; + a href => '#', 'add'; end; end; end 'table'; }], ], - vn_scr => [ mt('_vnedit_scr'), !@$r ? ( - [ static => nolabel => 1, content => mt '_vnedit_scrnorel' ], + vn_scr => [ 'Screenshots', !@$r ? ( + [ static => nolabel => 1, content => 'No releases in the database yet. Screenshots can only be uploaded after a release has been added.' ], ) : ( [ json => short => 'screenshots' ], [ static => nolabel => 1, content => sub { @@ -407,7 +425,12 @@ sub _form { staticurl => $self->{url_static}, }; div class => 'warning'; - lit mt '_vnedit_scrmsg'; + lit 'Please keep the following in mind when uploading screenshots:<br />' + .'- Screenshots have to be in the native resolution of the game,<br />' + .'- Remove any window borders and make sure the image is unmarked,<br />' + .'- Don\'t only upload event CGs.<br />' + .'Please read the <a href="/d2#6">guidelines</a> for more information.<br />' + .'Make sure to submit the form after the upload has finished!'; end; br; table class => 'stripe'; diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 70ba3402..e0590c37 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -29,7 +29,7 @@ sub rg { my $v = $self->dbVNGet(id => $vid, what => 'relgraph')->[0]; return $self->resNotFound if !$v->{id} || !$v->{rgraph}; - my $title = mt '_vnrg_title', $v->{title}; + my $title = "Relation graph for $v->{title}"; return if $self->htmlRGHeader($title, 'v', $v); $v->{svg} =~ s/id="node_v$vid"/id="graph_current"/; @@ -59,17 +59,17 @@ my @rel_cols = ( { # Title id => 'tit', sort_field => 'title', - column_string => '_relinfo_title', + column_string => 'Title', draw => sub { a href => "/r$_[0]{id}", shorten $_[0]{title}, 60 }, }, { # Type id => 'typ', sort_field => 'type', - button_string => '_relinfo_type', + button_string => 'Type', default => 1, - draw => sub { cssicon "rt$_[0]{type}", $_[0]{type}; txt mt '_vnpage_rel_patch' if $_[0]{patch} }, + draw => sub { cssicon "rt$_[0]{type}", $_[0]{type}; txt '(patch)' if $_[0]{patch} }, }, { # Languages id => 'lan', - button_string => '_relinfo_lang', + button_string => 'Language', default => 1, has_data => sub { !!@{$_[0]{languages}} }, draw => sub { @@ -81,15 +81,15 @@ my @rel_cols = ( }, { # Publication id => 'pub', sort_field => 'publication', - column_string => '_relinfo_publication', + column_string => 'Publication', column_width => 70, - button_string => '_relinfo_publication', + button_string => 'Publication', default => 1, what => 'extended', - draw => sub { txt mt $_[0]{patch} ? '_relinfo_pub_patch' : '_relinfo_pub_nopatch', $_[0]{freeware}?0:1, $_[0]{doujin}?0:1 }, + draw => sub { txt join ', ', $_[0]{freeware} ? 'Freeware' : 'Non-free', $_[0]{patch} ? () : ($_[0]{doujin} ? 'doujin' : 'commercial') }, }, { # Platforms id => 'pla', - button_string => '_redit_form_platforms', + button_string => 'Platforms', default => 1, what => 'platforms', has_data => sub { !!@{$_[0]{platforms}} }, @@ -98,12 +98,12 @@ my @rel_cols = ( cssicon $_, $TUWF::OBJ->{platforms}{$_}; br if $_ ne $_[0]{platforms}[$#{$_[0]{platforms}}]; } - txt mt '_unknown' if !@{$_[0]{platforms}}; + txt 'Unknown' if !@{$_[0]{platforms}}; }, }, { # Media id => 'med', - column_string => '_redit_form_media', - button_string => '_redit_form_media', + column_string => 'Media', + button_string => 'Media', what => 'media', has_data => sub { !!@{$_[0]{media}} }, draw => sub { @@ -111,13 +111,13 @@ my @rel_cols = ( txt fmtmedia($_->{medium}, $_->{qty}); br if $_ ne $_[0]{media}[$#{$_[0]{media}}]; } - txt mt '_unknown' if !@{$_[0]{media}}; + txt 'Unknown' if !@{$_[0]{media}}; }, }, { # Resolution id => 'res', sort_field => 'resolution', - column_string => '_relinfo_resolution', - button_string => '_relinfo_resolution', + column_string => 'Resolution', + button_string => 'Resolution', na_for_patch => 1, default => 1, what => 'extended', @@ -126,15 +126,15 @@ my @rel_cols = ( if($_[0]{resolution}) { txt $TUWF::OBJ->{resolutions}[$_[0]{resolution}][0]; } else { - txt mt '_unknown'; + txt 'Unknown'; } }, }, { # Voiced id => 'voi', sort_field => 'voiced', - column_string => '_relinfo_voiced', + column_string => 'Voiced', column_width => 70, - button_string => '_relinfo_voiced', + button_string => 'Voiced', na_for_patch => 1, default => 1, what => 'extended', @@ -143,38 +143,38 @@ my @rel_cols = ( }, { # Animation id => 'ani', sort_field => 'ani_ero', - column_string => '_relinfo_ani', + column_string => 'Animation', column_width => 110, - button_string => '_relinfo_ani', + button_string => 'Animation', na_for_patch => '1', what => 'extended', has_data => sub { !!($_[0]{ani_story} || $_[0]{ani_ero}) }, draw => sub { txt join ', ', - $_[0]{ani_story} ? mt('_relinfo_ani_story', $TOWF::OBJ->{animated}[$_[0]{ani_story}]):(), - $_[0]{ani_ero} ? mt('_relinfo_ani_ero', $TOWF::OBJ->{animated}[$_[0]{ani_ero}] ):(); - txt mt '_unknown' if !$_[0]{ani_story} && !$_[0]{ani_ero}; + $_[0]{ani_story} ? "Story: $TUWF::OBJ->{animated}[$_[0]{ani_story}]" :(), + $_[0]{ani_ero} ? "Ero scenes: $TUWF::OBJ->{animated}[$_[0]{ani_ero}]":(); + txt 'Unknown' if !$_[0]{ani_story} && !$_[0]{ani_ero}; }, }, { # Released id => 'rel', sort_field => 'released', - column_string => '_relinfo_released', - button_string => '_relinfo_released', + column_string => 'Released', + button_string => 'Released', default => 1, draw => sub { lit fmtdatestr $_[0]{released} }, }, { # Age rating id => 'min', sort_field => 'minage', - button_string => '_relinfo_minage', + button_string => 'Age rating', default => 1, has_data => sub { $_[0]{minage} != -1 }, draw => sub { txt minage $_[0]{minage} }, }, { # Notes id => 'not', sort_field => 'notes', - column_string => '_redit_form_notes', + column_string => 'Notes', column_width => 400, - button_string => '_redit_form_notes', + button_string => 'Notes', default => 1, what => 'extended', has_data => sub { !!$_[0]{notes} }, @@ -189,7 +189,7 @@ sub releases { my $v = $self->dbVNGet(id => $vid)->[0]; return $self->resNotFound if !$v->{id}; - my $title = mt('_vnpage_rel_title', $v->{title}); + my $title = "Releases for $v->{title}"; $self->htmlHeader(title => $title); $self->htmlMainTabs('v', $v, 'releases'); @@ -217,7 +217,7 @@ sub releases { h1 $title; if(!@$r) { - td mt '_vnpage_rel_none'; + td 'We don\'t have any information about releases of this visual novel yet...'; } else { _releases_buttons($self, $f, $url, $r); } @@ -233,7 +233,7 @@ sub _releases_buttons { # Column visibility p class => 'browseopts'; - a href => $url->($_->{id}, $f->{$_->{id}} ? 0 : 1), $f->{$_->{id}} ? (class => 'optselected') : (), mt $_->{button_string} + a href => $url->($_->{id}, $f->{$_->{id}} ? 0 : 1), $f->{$_->{id}} ? (class => 'optselected') : (), $_->{button_string} for (grep $_->{button_string}, @rel_cols); end; @@ -242,9 +242,9 @@ sub _releases_buttons { my $all_unselected = !grep $_->{button_string} && $f->{$_->{id}}, @rel_cols; my $all_url = sub { $url->(map +($_->{id},$_[0]), grep $_->{button_string}, @rel_cols); }; p class => 'browseopts'; - a href => $all_url->(1), $all_selected ? (class => 'optselected') : (), mt '_all_on'; - a href => $all_url->(0), $all_unselected ? (class => 'optselected') : (), mt '_all_off'; - a href => $url->('cw', $f->{cw} ? 0 : 1), $f->{cw} ? (class => 'optselected') : (), mt '_vnpage_restrict_column_width'; + a href => $all_url->(1), $all_selected ? (class => 'optselected') : (), 'All on'; + a href => $all_url->(0), $all_unselected ? (class => 'optselected') : (), 'All off'; + a href => $url->('cw', $f->{cw} ? 0 : 1), $f->{cw} ? (class => 'optselected') : (), 'Restrict column width'; end; # Platform/language filters @@ -255,7 +255,7 @@ sub _releases_buttons { p class => 'browseopts'; for('all', sort keys %opts) { a href => $url->($option, $_), $_ eq $f->{$option} ? (class => 'optselected') : (); - $_ eq 'all' ? txt mt '_all' : cssicon "$csscat $_", $txt->{$_}; + $_ eq 'all' ? txt 'All' : cssicon "$csscat $_", $txt->{$_}; end 'a'; } end 'p'; @@ -287,7 +287,7 @@ sub _releases_table { Tr; for my $c (@col) { td class => 'key'; - txt mt $c->{column_string} if $c->{column_string}; + txt $c->{column_string} if $c->{column_string}; for($c->{sort_field} ? (0,1) : ()) { my $active = $f->{s} eq $c->{sort_field} && !$f->{o} == !$_; a href => $url->(o => $_, s => $c->{sort_field}) if !$active; @@ -311,7 +311,7 @@ sub _releases_table { td $cspan > 1 ? (colspan => $cspan) : (), $col[$c]{column_width} && $f->{cw} ? (style => "max-width: $col[$c]{column_width}px") : (); if($r->{patch} && $col[$c]{na_for_patch}) { - txt mt '_vnpage_na_for_patches'; + txt 'NA for patches'; } else { $col[$c]{draw}->($r); } @@ -357,19 +357,19 @@ sub page { # image div class => 'vnimg'; if(!$v->{image}) { - p mt '_vnpage_noimg'; + p 'No image uploaded yet'; } else { p $v->{img_nsfw} ? (id => 'nsfw_hid', $self->authPref('show_nsfw') ? () : (class => 'hidden')) : (); img src => imgurl(cv => $v->{image}), alt => $v->{title}; - i mt '_vnpage_imgnsfw_foot' if $v->{img_nsfw}; + i 'Flagged as NSFW' if $v->{img_nsfw}; end; if($v->{img_nsfw}) { p id => 'nsfw_show', $self->authPref('show_nsfw') ? (class => 'hidden') : (); - txt mt('_vnpage_imgnsfw_msg'); + txt 'This image has been flagged as Not Safe For Work.'; br; br; - a href => '#', mt '_vnpage_imgnsfw_show'; + a href => '#', 'Show me anyway'; br; br; - txt mt '_vnpage_imgnsfw_note'; + txt '(This warning can be disabled in your account)'; end; } } @@ -378,39 +378,39 @@ sub page { # general info table class => 'stripe'; Tr; - td class => 'key', mt '_vnpage_vntitle'; + td class => 'key', 'Title'; td $v->{title}; end; if($v->{original}) { Tr; - td mt '_vnpage_original'; + td 'Original title'; td $v->{original}; end; } if($v->{alias}) { $v->{alias} =~ s/\n/, /g; Tr; - td mt '_vnpage_alias'; + td 'Aliases'; td $v->{alias}; end; } if($v->{length}) { Tr; - td mt '_vnpage_length'; + td 'Length'; td fmtvnlen $v->{length}, 1; end; } my @links = ( - $v->{l_wp} ? [ 'wp', 'http://en.wikipedia.org/wiki/%s', $v->{l_wp} ] : (), - $v->{l_encubed} ? [ 'encubed', 'http://novelnews.net/tag/%s/', $v->{l_encubed} ] : (), - $v->{l_renai} ? [ 'renai', 'http://renai.us/game/%s.shtml', $v->{l_renai} ] : (), + $v->{l_wp} ? [ 'Wikipedia', 'http://en.wikipedia.org/wiki/%s', $v->{l_wp} ] : (), + $v->{l_encubed} ? [ 'Encubed', 'http://novelnews.net/tag/%s/', $v->{l_encubed} ] : (), + $v->{l_renai} ? [ 'Renai.us', 'http://renai.us/game/%s.shtml', $v->{l_renai} ] : (), ); if(@links) { Tr; - td mt '_vnpage_links'; + td 'Links'; td; for(@links) { - a href => sprintf($_->[1], $_->[2]), mt "_vnpage_l_$_->[0]"; + a href => sprintf($_->[1], $_->[2]), $_->[0]; txt ', ' if $_ ne $links[$#links]; } end; @@ -425,7 +425,7 @@ sub page { Tr class => 'nostripe'; td class => 'vndesc', colspan => 2; - h2 mt '_vnpage_description'; + h2 'Description'; p; lit $v->{desc} ? bb2html $v->{desc} : '-'; end; @@ -444,11 +444,11 @@ sub page { my $tags_cat = $self->authPref('tags_cat') || $self->{default_tags_cat}; a href => "#$_", $tags_cat =~ /\Q$_/ ? (class => 'tsel') : (), lc $self->{tag_categories}{$_} for keys %{$self->{tag_categories}}; my $spoiler = $self->authPref('spoilers') || 0; - a href => '#', class => 'sec'.($spoiler == 0 ? ' tsel' : ''), lc mt '_spoilset_0'; - a href => '#', $spoiler == 1 ? (class => 'tsel') : (), lc mt '_spoilset_1'; - a href => '#', $spoiler == 2 ? (class => 'tsel') : (), lc mt '_spoilset_2'; - a href => '#', class => 'sec'.($self->authPref('tags_all') ? '': ' tsel'), mt '_vnpage_tags_summary'; - a href => '#', $self->authPref('tags_all') ? (class => 'tsel') : (), mt '_vnpage_tags_all'; + a href => '#', class => 'sec'.($spoiler == 0 ? ' tsel' : ''), lc 'Hide spoilers'; + a href => '#', $spoiler == 1 ? (class => 'tsel') : (), lc 'Show minor spoilers'; + a href => '#', $spoiler == 2 ? (class => 'tsel') : (), lc 'Spoil me!'; + a href => '#', class => 'sec'.($self->authPref('tags_all') ? '': ' tsel'), 'summary'; + a href => '#', $self->authPref('tags_all') ? (class => 'tsel') : (), 'all'; end; div id => 'vntags'; for (@$t) { @@ -467,12 +467,12 @@ sub page { clearfloat; # fix tabs placement when tags are hidden ul class => 'maintabs notfirst'; if(@$chars) { - li class => 'left '.(!$char ? ' tabselected' : ''); a href => "/v$v->{id}#main", name => 'main', mt '_vnpage_tab_main'; end; - li class => 'left '.($char ? ' tabselected' : ''); a href => "/v$v->{id}/chars#chars", name => 'chars', mt '_vnpage_tab_chars'; end; + li class => 'left '.(!$char ? ' tabselected' : ''); a href => "/v$v->{id}#main", name => 'main', 'main'; end; + li class => 'left '.($char ? ' tabselected' : ''); a href => "/v$v->{id}/chars#chars", name => 'chars', 'characters'; end; } if($self->authCan('edit')) { - li; a href => "/c/new?vid=$v->{id}", mt '_vnpage_char_add'; end; - li; a href => "/v$v->{id}/add", mt '_vnpage_rel_add'; end; + li; a href => "/c/new?vid=$v->{id}", 'add character'; end; + li; a href => "/v$v->{id}/add", 'add release'; end; } end; } @@ -506,57 +506,56 @@ sub _revision { [ desc => 'Description', diff => qr/[ ,\n\.]/ ], [ length => 'Length', serialize => sub { fmtvnlen $_[0] } ], [ l_wp => 'Wikipedia link', htmlize => sub { - $_[0] ? sprintf '<a href="http://en.wikipedia.org/wiki/%s">%1$s</a>', xml_escape $_[0] : mt '_revision_nolink' + $_[0] ? sprintf '<a href="http://en.wikipedia.org/wiki/%s">%1$s</a>', xml_escape $_[0] : '[empty]' }], [ l_encubed => 'Encubed tag', htmlize => sub { - $_[0] ? sprintf '<a href="http://novelnews.net/tag/%s/">%1$s</a>', xml_escape $_[0] : mt '_revision_nolink' + $_[0] ? sprintf '<a href="http://novelnews.net/tag/%s/">%1$s</a>', xml_escape $_[0] : '[empty]' }], [ l_renai => 'Renai.us link', htmlize => sub { - $_[0] ? sprintf '<a href="http://renai.us/game/%s.shtml">%1$s</a>', xml_escape $_[0] : mt '_revision_nolink' + $_[0] ? sprintf '<a href="http://renai.us/game/%s.shtml">%1$s</a>', xml_escape $_[0] : '[empty]' }], [ credits => 'Credits', join => '<br />', split => sub { my @r = map sprintf('<a href="/s%d" title="%s">%s</a> [%s]%s', $_->{id}, xml_escape($_->{original}||$_->{name}), xml_escape($_->{name}), xml_escape($self->{staff_roles}{$_->{role}}), $_->{note} ? ' ['.xml_escape($_->{note}).']' : ''), sort { $a->{id} <=> $b->{id} || $a->{role} cmp $b->{role} } @{$_[0]}; - return @r ? @r : (mt '_revision_empty'); + return @r ? @r : ('[empty]'); }], [ seiyuu => 'Seiyuu', join => '<br />', split => sub { - my @r = map sprintf('<a href="/s%d" title="%s">%s</a> %s%s', - $_->{id}, xml_escape($_->{original}||$_->{name}), xml_escape($_->{name}), - mt('_staff_as', xml_escape($_->{cname})), + my @r = map sprintf('<a href="/s%d" title="%s">%s</a> as %s%s', + $_->{id}, xml_escape($_->{original}||$_->{name}), xml_escape($_->{name}), xml_escape($_->{cname}), $_->{note} ? ' ['.xml_escape($_->{note}).']' : ''), sort { $a->{id} <=> $b->{id} || $a->{cid} <=> $b->{cid} || $a->{note} cmp $b->{note} } @{$_[0]}; - return @r ? @r : (mt '_revision_empty'); + return @r ? @r : ('[empty]'); }], [ relations => 'Relations', join => '<br />', split => sub { my @r = map sprintf('[%s] %s: <a href="/v%d" title="%s">%s</a>', - mt($_->{official} ? '_vndiff_rel_official' : '_vndiff_rel_unofficial'), - $self->{vn_relations}{$_->{relation}}[1], $_->{id}, xml_escape($_->{original}||$_->{title}), xml_escape shorten $_->{title}, 40 + $_->{official} ? 'official' : 'unofficial', $self->{vn_relations}{$_->{relation}}[1], + $_->{id}, xml_escape($_->{original}||$_->{title}), xml_escape shorten $_->{title}, 40 ), sort { $a->{id} <=> $b->{id} } @{$_[0]}; - return @r ? @r : (mt '_revision_empty'); + return @r ? @r : ('[empty]'); }], [ anime => 'Anime', join => ', ', split => sub { my @r = map sprintf('<a href="http://anidb.net/a%d">a%1$d</a>', $_->{id}), sort { $a->{id} <=> $b->{id} } @{$_[0]}; - return @r ? @r : (mt '_revision_empty'); + return @r ? @r : ('[empty]'); }], [ screenshots => 'Screenshots', join => '<br />', split => sub { my @r = map sprintf('[%s] <a href="%s" data-iv="%dx%d">%d</a> (%s)', $_->{rid} ? qq|<a href="/r$_->{rid}">r$_->{rid}</a>| : 'no release', imgurl(sf => $_->{id}), $_->{width}, $_->{height}, $_->{id}, - mt($_->{nsfw} ? '_vndiff_nsfw_notsafe' : '_vndiff_nsfw_safe') + $_->{nsfw} ? 'Not safe' : 'Safe' ), @{$_[0]}; - return @r ? @r : (mt '_revision_empty'); + return @r ? @r : ('[empty]'); }], [ image => 'Image', htmlize => sub { my $url = imgurl(cv => $_[0]); if($_[0]) { - return $_[1]->{img_nsfw} && !$self->authPref('show_nsfw') ? "<a href=\"$url\">".mt('_vndiff_image_nsfw').'</a>' : "<img src=\"$url\" />"; + return $_[1]->{img_nsfw} && !$self->authPref('show_nsfw') ? "<a href=\"$url\">(NSFW)</a>" : "<img src=\"$url\" />"; } else { - return mt '_vndiff_image_none'; + return 'No image'; } }], - [ img_nsfw => 'Image NSFW', serialize => sub { mt $_[0] ? '_vndiff_nsfw_notsafe' : '_vndiff_nsfw_safe' } ], + [ img_nsfw => 'Image NSFW', serialize => sub { $_[0] ? 'Not safe' : 'Safe' } ], ); } @@ -571,7 +570,7 @@ sub _producers { my %dev = map $_->{developer} ? ($_->{id} => $_) : (), map @{$_->{producers}}, @$r; my @dev = values %dev; Tr; - td mt "_vnpage_developer"; + td 'Developer'; td; for (@dev) { a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 30; @@ -583,7 +582,7 @@ sub _producers { if(grep $_->{publisher}, map @{$_->{producers}}, @$r) { Tr; - td mt "_vnpage_publisher"; + td 'Publishers'; td; for my $l (@lang) { my %p = map $_->{publisher} ? ($_->{id} => $_) : (), map @{$_->{producers}}, grep grep($_ eq $l, @{$_->{languages}}), @$r; @@ -611,14 +610,14 @@ sub _relations { Tr; - td mt '_vnpage_relations'; + td 'Relations'; td class => 'relations'; dl; for(sort keys %rel) { dt $self->{vn_relations}{$_}[1]; dd; for (@{$rel{$_}}) { - b class => 'grayedout', mt('_vnpage_relations_unofficial').' ' if !$_->{official}; + b class => 'grayedout', '[unofficial] ' if !$_->{official}; a href => "/v$_->{id}", title => $_->{original}||$_->{title}, shorten $_->{title}, 40; br; } @@ -634,12 +633,12 @@ sub _anime { my($self, $v) = @_; Tr; - td mt '_vnpage_anime'; + td 'Related anime'; td class => 'anime'; for (sort { ($a->{year}||9999) <=> ($b->{year}||9999) } @{$v->{anime}}) { if(!$_->{lastfetch} || !$_->{year} || !$_->{title_romaji}) { b; - lit mt '_vnpage_anime_noinfo', $_->{id}, "http://anidb.net/a$_->{id}"; + lit sprintf '[no information available at this time: <a href="http://anidb.net/a%d">%1$d</a>]', $_->{id}; end; } else { b; @@ -673,36 +672,36 @@ sub _useroptions { my $wish = $self->dbWishListGet(uid => $self->authInfo->{id}, vid => $v->{id})->[0]; Tr; - td mt '_vnpage_uopt'; + td 'User options'; td; if($vote || !$wish) { Select id => 'votesel', name => $self->authGetCode("/v$v->{id}/vote"); - option value => -3, $vote ? mt '_vnpage_uopt_voted', fmtvote($vote->{vote}) : mt '_vnpage_uopt_novote'; - optgroup label => $vote ? mt '_vnpage_uopt_changevote' : mt '_vnpage_uopt_dovote'; - option value => $_, "$_ (".mt("_vote_$_").')' for (reverse 1..10); - option value => -2, mt '_vnpage_uopt_othvote'; + option value => -3, $vote ? 'your vote: '.fmtvote($vote->{vote}) : 'not voted yet'; + optgroup label => $vote ? 'Change vote' : 'Vote'; + option value => $_, "$_ (".fmtrating($_).')' for (reverse 1..10); + option value => -2, 'Other'; end; - option value => -1, mt '_vnpage_uopt_delvote' if $vote; + option value => -1, 'revoke' if $vote; end; br; } Select id => 'listsel', name => $self->authGetCode("/v$v->{id}/list"); - option $list ? mt '_vnpage_uopt_vnlisted', $self->{vnlist_status}[$list->{status}] : mt '_vnpage_uopt_novn'; - optgroup label => $list ? mt '_vnpage_uopt_changevn' : mt '_vnpage_uopt_addvn'; + option $list ? "VN list: $self->{vnlist_status}[$list->{status}]" : 'not on your VN list'; + optgroup label => $list ? 'Change status' : 'Add to VN list'; option value => $_, $self->{vnlist_status}[$_] for (0..$#{$self->{vnlist_status}}); end; - option value => -1, mt '_vnpage_uopt_delvn' if $list; + option value => -1, 'remove from VN list' if $list; end; br; if(!$vote || $wish) { Select id => 'wishsel', name => $self->authGetCode("/v$v->{id}/wish"); - option $wish ? mt '_vnpage_uopt_wishlisted', $self->{wishlist_status}[$wish->{wstat}] : mt '_vnpage_uopt_nowish'; - optgroup label => $wish ? mt '_vnpage_uopt_changewish' : mt '_vnpage_uopt_addwish'; + option $wish ? "wishlist: $self->{wishlist_status}[$wish->{wstat}]" : 'not on your wishlist'; + optgroup label => $wish ? 'Change status' : 'Add to wishlist'; option value => $_, $self->{wishlist_status}[$_] for (0..$#{$self->{wishlist_status}}); end; - option value => -1, mt '_vnpage_uopt_delwish' if $wish; + option value => -1, 'remove from wishlist' if $wish; end; } end; @@ -750,9 +749,9 @@ sub _releases { my($self, $v, $r) = @_; div class => 'mainbox releases'; - h1 mt '_vnpage_rel'; + h1 'Releases'; if(!@$r) { - p mt '_vnpage_rel_none'; + p 'We don\'t have any information about releases of this visual novel yet...'; end; return; } @@ -789,7 +788,7 @@ sub _releases { end; td class => 'tc4'; a href => "/r$rel->{id}", title => $rel->{original}||$rel->{title}, $rel->{title}; - b class => 'grayedout', ' '.mt '_vnpage_rel_patch' if $rel->{patch}; + b class => 'grayedout', ' (patch)' if $rel->{patch}; end; td class => 'tc5'; if($self->authInfo->{id}) { @@ -803,7 +802,7 @@ sub _releases { a href => "/affiliates/new?rid=$rel->{id}", 'a' if $self->authCan('affiliate'); if($rel->{website}) { a href => $rel->{website}, rel => 'nofollow'; - cssicon 'external', mt '_vnpage_rel_extlink'; + cssicon 'external', 'External link'; end; } else { txt ' '; @@ -823,15 +822,14 @@ sub _screenshots { if(grep $_->{nsfw}, @{$v->{screenshots}}) { p class => 'nsfwtoggle'; - lit mt '_vnpage_scr_showing', - sprintf('<i id="nsfwshown">%d</i>', $self->authPref('show_nsfw') ? scalar @{$v->{screenshots}} : scalar grep(!$_->{nsfw}, @{$v->{screenshots}})), - scalar @{$v->{screenshots}}; - txt " "; - a href => '#', id => "nsfwhide", mt '_vnpage_scr_nsfwhide'; + txt 'Showing '; + i id => 'nsfwshown', $self->authPref('show_nsfw') ? scalar @{$v->{screenshots}} : scalar grep(!$_->{nsfw}, @{$v->{screenshots}}); + txt sprintf ' out of %d screenshot%s. ', scalar @{$v->{screenshots}}, @{$v->{screenshots}} == 1 ? '' : 's'; + a href => '#', id => "nsfwhide", 'show/hide NSFW'; end; } - h1 mt '_vnpage_scr'; + h1 'Screenshots'; for my $rel (@$r) { my @scr = grep $_->{rid} && $rel->{id} == $_->{rid}, @{$v->{screenshots}}; @@ -847,7 +845,7 @@ sub _screenshots { class => sprintf('scrlnk%s%s', $_->{nsfw} ? ' nsfw':'', $_->{nsfw}&&!$self->authPref('show_nsfw')?' hidden':''), 'data-iv' => "$_->{width}x$_->{height}:scr"; img src => imgurl(st => $_->{id}), - width => $w, height => $h, alt => mt '_vnpage_scr_num', $_->{id}; + width => $w, height => $h, alt => "Screenshot #$_->{id}"; end; } end; @@ -861,9 +859,9 @@ sub _stats { my $stats = $self->dbVoteStats(vid => $v->{id}, 1); div class => 'mainbox'; - h1 mt '_vnpage_stats'; + h1 'User stats'; if(!grep $_->[0] > 0, @$stats) { - p mt '_vnpage_stats_none'; + p 'Nobody has voted on this visual novel yet...'; } else { $self->htmlVoteStats(v => $v, $stats); } @@ -916,7 +914,7 @@ sub _charsum { div class => 'mainbox charsum summarize'; $self->charOps(0) if $has_spoilers; - h1 mt '_vnpage_charsum'; + h1 'Character summary'; div class => 'charsum_list'; for my $c (@l) { div class => 'charsum_bubble'.($has_spoilers ? ' '.charspoil(_charspoillvl $v->{id}, $c) : ''); @@ -926,7 +924,7 @@ sub _charsum { end; if(@{$c->{seiyuu}}) { div class => 'actor'; - txt mt '_charp_voice'; + txt 'Voiced by'; @{$c->{seiyuu}} > 1 ? br : txt ' '; for my $s (sort { $a->{name} cmp $b->{name} } @{$c->{seiyuu}}) { a href => "/s$s->{sid}", title => $s->{original}||$s->{name}, $s->{name}; @@ -947,7 +945,7 @@ sub _staff { return if !@{$v->{credits}}; div class => 'mainbox staff summarize', 'data-summarize-height' => 100, id => 'staff'; - h1 mt '_vnpage_staff'; + h1 'Staff'; for my $r (keys %{$self->{staff_roles}}) { my @s = grep $_->{role} eq $r, @{$v->{credits}}; next if !@s; |