From 9ba57996ed6d7fe3dd0d0c1fe5e1b3827b8a2b8a Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 25 Sep 2009 18:37:54 +0200 Subject: Use inline SVG for relation graphs The graphs are now stored in the DB in SVG format, the static/rg/ directory can be removed (not used anymore). SVG data is stored using the xml data type, so now I can say for sure you'd need at least PostgreSQL 8.3. This feature still needs some tweaking, though. Current state isn't perfect. --- .gitignore | 1 - ChangeLog | 4 ++ README | 4 +- data/style.css | 7 ++++ lib/Multi/RG.pm | 91 ++++++++++++++++++++++++++++++--------------- lib/VNDB/DB/VN.pm | 4 +- lib/VNDB/Handler/VNPage.pm | 23 ++++++++++-- util/init.pl | 2 +- util/updates/update_2.8.sql | 16 ++++++++ 9 files changed, 113 insertions(+), 39 deletions(-) create mode 100644 util/updates/update_2.8.sql diff --git a/.gitignore b/.gitignore index 59f221ff..2baf1a87 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ /static/s/*/style.css /static/s/*/boxbg.png /static/cv/ -/static/rg/ /static/sf/ /static/st/ /static/robots.txt diff --git a/ChangeLog b/ChangeLog index 2a269f21..9cb2bbd3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +git - ? + - Converted relation graphs to use inline SVG + - Relation graphs now use the color scheme of selected skin + 2.7 - 2009-09-24 - Improved styling of the threeboxes layout - Blacklist a users' votes from the VN vote statistics diff --git a/README b/README index 5177b6e2..1060c544 100644 --- a/README +++ b/README @@ -12,7 +12,7 @@ Requirements global requirements: Linux, or an OS that resembles Linux. Chances are VNDB won't run on Windows. - PostgreSQL 8.3 recommended, 8.1 may also work + PostgreSQL 8.3+ perl 5.10 recommended, 5.8 may also work A webserver that works with YAWF (lighttpd and Apache are known to work) @@ -41,6 +41,8 @@ Requirements Maintenance: PerlIO::gzip RG: + XML::Parser + XML::Writer graphviz (/usr/bin/dot is used by default) Sitemap: XML::Writer diff --git a/data/style.css b/data/style.css index 53255c74..0772dda8 100644 --- a/data/style.css +++ b/data/style.css @@ -1182,3 +1182,10 @@ a .icons { cursor: pointer } .icons.ko { background-position: -61px -88px; } .icons.vi { background-position: -61px -99px; } + +/* Relation graph colors */ +svg .border { fill: none; stroke: $border$ } +svg .edge polygon.border { fill: $border$ } +svg .nodebg { fill: $tabbg$; stroke: $tabbg$ } +svg text { fill: $maintext$ } + diff --git a/lib/Multi/RG.pm b/lib/Multi/RG.pm index e427caf2..4ae0516e 100644 --- a/lib/Multi/RG.pm +++ b/lib/Multi/RG.pm @@ -9,6 +9,8 @@ use strict; use warnings; use POE 'Wheel::Run', 'Filter::Stream'; use Encode 'encode_utf8'; +use XML::Parser; +use XML::Writer; use Time::HiRes 'time'; @@ -17,14 +19,13 @@ sub spawn { POE::Session->create( package_states => [ $p => [qw| - _start shutdown check_rg creategraph getrel builddot buildgraph savegraph + _start shutdown check_rg creategraph getrel builddot savegraph finish proc_stdin proc_stdout proc_stderr proc_closed proc_child |], ], heap => { font => 'Arial', fsize => [ 9, 7, 10 ], # nodes, edges, node_title - imgdir => '/www/vndb/static/rg', moy => [qw| Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec |], dot => '/usr/bin/dot', check_delay => 3600, @@ -104,12 +105,10 @@ sub builddot { # num, res my $gv = qq|graph rgraph {\n|. - qq|\tratio = "compress"\n|. - qq|\tgraph [ bgcolor="#ffffff00" ]\n|. qq|\tnode [ fontname = "$_[HEAP]{font}", shape = "plaintext",|. - qq| fontsize = $_[HEAP]{fsize}[0], style = "setlinewidth(0.5)", fontcolor = "#cccccc", color = "#225588" ]\n|. + qq| fontsize = $_[HEAP]{fsize}[0], fontcolor = "#333333", color = "#111111" ]\n|. qq|\tedge [ labeldistance = 2.5, labelangle = -20, labeljust = 1, minlen = 2, dir = "both",|. - qq| fontname = $_[HEAP]{font}, fontsize = $_[HEAP]{fsize}[1], arrowsize = 0.7, color = "#225588", fontcolor = "#cccccc" ]\n|; + qq| fontname = $_[HEAP]{font}, fontsize = $_[HEAP]{fsize}[1], arrowsize = 0.7, color = "#111111", fontcolor = "#333333" ]\n|; # insert all nodes, ordered by release date for (sort { $a->{date} <=> $b->{date} } @$vns) { @@ -128,7 +127,7 @@ sub builddot { # num, res $gv .= sprintf qq|\tv%d [ URL = "/v%d", tooltip = "%s" label=<|. - q||. + q|
|. q||. q||. qq|
%s
%s %s
> ]\n|, @@ -161,49 +160,79 @@ sub builddot { # num, res $gv .= "}\n"; - # get ID - $_[KERNEL]->post(pg => query => 'INSERT INTO relgraph (cmap) VALUES (\'\') RETURNING id', undef, 'buildgraph', \$gv); -} - - -sub buildgraph { # num, res, \$gv - $_[HEAP]{gid} = $_[ARG1][0]{id}; - $_[HEAP]{graph} = sprintf('%s/%02d/%d.png', $_[HEAP]{imgdir}, $_[ARG1][0]{id} % 100, $_[ARG1][0]{id}); - $_[HEAP]{cmap} = ''; - - # roughly equivalent to: - # cat layout.txt | dot -Tpng -o graph.png -Tcmapx + # Pass our dot file to graphviz + $_[HEAP]{svg} = ''; $_[HEAP]{proc} = POE::Wheel::Run->new( Program => $_[HEAP]{dot}, - ProgramArgs => [ '-Tpng', '-o', $_[HEAP]{graph}, '-Tcmapx' ], + ProgramArgs => [ '-Tsvg' ], StdioFilter => POE::Filter::Stream->new(), StdinEvent => 'proc_stdin', StdoutEvent => 'proc_stdout', StderrEvent => 'proc_stderr', CloseEvent => 'proc_closed', ); - $_[HEAP]{proc}->put(${$_[ARG2]}); + $_[HEAP]{proc}->put($gv); } sub savegraph { - my $vids = join ',', sort map int, keys %{$_[HEAP]{nodes}}; + # Before saving the SVG output, we'll modify it a little: + # - Remove comments + # - Add svg: prefix to all tags + # - Remove xmlns declarations (this is set in the html) + # - Remove elements (unused) + # - Remove id attributes (unused) + # - Remove first <polygon> element (emulates the background color) + # - Replace stroke and fill attributes with classes (so that coloring is done in CSS) + my $svg = ''; + my $w = XML::Writer->new(OUTPUT => \$svg); + my $p = XML::Parser->new; + $p->setHandlers( + Start => sub { + my($expat, $el, %attr) = @_; + return if $el eq 'title' || $expat->in_element('title'); + return if $el eq 'polygon' && $expat->depth == 2; + + $attr{class} = 'border' if $attr{stroke} && $attr{stroke} eq '#111111'; + $attr{class} = 'nodebg' if $attr{fill} && $attr{fill} eq '#222222'; + + delete @attr{qw|stroke fill id xmlns xmlns:xlink|}; + $el eq 'path' || $el eq 'polygon' + ? $w->emptyTag("svg:$el", %attr) + : $w->startTag("svg:$el", %attr); + }, + End => sub { + my($expat, $el) = @_; + return if $el eq 'title' || $expat->in_element('title'); + return if $el eq 'polygon' && $expat->depth == 2; + $w->endTag("svg:$el") if $el ne 'path' && $el ne 'polygon'; + }, + Char => sub { + my($expat, $str) = @_; + return if $expat->in_element('title'); + $w->characters($str) if $str !~ /^[\s\t\r\n]*$/s; + } + ); + $p->parsestring($_[HEAP]{svg}); + $w->end(); - # chmod graph - chmod 0666, $_[HEAP]{graph}; + # save the processed SVG in the database and fetch graph ID + $_[KERNEL]->post(pg => query => 'INSERT INTO vn_graphs (svg) VALUES (?) RETURNING id', [ $svg ], 'finish'); +} - # save the image map in the database - $_[KERNEL]->post(pg => do => 'UPDATE relgraph SET cmap = ? WHERE id = ?', - [ "<!-- V:$vids -->\n$_[HEAP]{cmap}", $_[HEAP]{gid} ]); + +sub finish { # num, res + my $id = $_[ARG1][0]{id}; + my $vids = join ',', sort map int, keys %{$_[HEAP]{nodes}}; # update the VN table - $_[KERNEL]->post(pg => do => "UPDATE vn SET rgraph = ? WHERE id IN($vids)", [ $_[HEAP]{gid} ]); + $_[KERNEL]->post(pg => do => "UPDATE vn SET rgraph = ? WHERE id IN($vids)", [ $id ]); # log - $_[KERNEL]->call(core => log => 'Generated relation graph in %.2fs, V: %s', time-$_[HEAP]{start}, $vids); + $_[KERNEL]->call(core => log => 'Generated VN relation graph #%d in %.2fs, V: %s', $id, time-$_[HEAP]{start}, $vids); # clean up - delete @{$_[HEAP]}{qw| start vid nodes rels gid graph cmap proc |}; + delete @{$_[HEAP]}{qw| start vid nodes rels svg proc |}; # check for more things to do $_[KERNEL]->yield('check_rg'); @@ -216,7 +245,7 @@ sub proc_stdin { $_[HEAP]{proc}->shutdown_stdin; } sub proc_stdout { - $_[HEAP]{cmap} .= $_[ARG0]; + $_[HEAP]{svg} .= $_[ARG0]; } sub proc_stderr { $_[KERNEL]->call(core => log => 'GraphViz STDERR: %s', $_[ARG0]); diff --git a/lib/VNDB/DB/VN.pm b/lib/VNDB/DB/VN.pm index b3603985..c6499350 100644 --- a/lib/VNDB/DB/VN.pm +++ b/lib/VNDB/DB/VN.pm @@ -76,7 +76,7 @@ sub dbVNGet { $o{what} =~ /changes/ ? 'JOIN users u ON u.id = c.requester' : (), $o{what} =~ /relgraph/ ? - 'JOIN relgraph rg ON rg.id = v.rgraph' : (), + 'JOIN vn_graphs vg ON vg.id = v.rgraph' : (), ); my $tag_ids = $o{tags_include} && join ',', @{$o{tags_include}[1]}; @@ -86,7 +86,7 @@ sub dbVNGet { qw|vr.alias vr.image vr.img_nsfw vr.length vr.desc vr.l_wp vr.l_encubed vr.l_renai vr.l_vnn| ) : (), $o{what} =~ /changes/ ? ( qw|c.requester c.comments v.latest u.username c.rev c.causedby|, q|extract('epoch' from c.added) as added|) : (), - $o{what} =~ /relgraph/ ? 'rg.cmap' : (), + $o{what} =~ /relgraph/ ? 'vg.svg' : (), $o{what} =~ /ranking/ ? '(SELECT COUNT(*)+1 FROM vn iv WHERE iv.hidden = false AND iv.c_popularity > v.c_popularity) AS ranking' : (), $tag_ids ? qq|(SELECT AVG(tvb.rating) FROM tags_vn_bayesian tvb WHERE tvb.tag IN($tag_ids) AND tvb.vid = v.id AND spoiler <= $o{tags_include}[0] GROUP BY tvb.vid) AS tagscore| : (), diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 361963a8..5e0fc9dc 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -23,20 +23,37 @@ sub rand { sub rg { my($self, $vid) = @_; + # TODO: browser detection + notice, this trick gives some ugly results in IE + my $v = $self->dbVNGet(id => $vid, what => 'relgraph')->[0]; return 404 if !$v->{id} || !$v->{rgraph}; my $title = mt '_vnrg_title', $v->{title}; + $self->resHeader('Content-Type' => 'application/xhtml+xml'); + + # This is a REALLY ugly hack, need find a proper solution in YAWF + no warnings 'redefine'; + my $sub = \&YAWF::XML::html; + *YAWF::XML::html = sub () { + lit q|<!DOCTYPE html PUBLIC + "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" + "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">|; + tag 'html', + xmlns => "http://www.w3.org/1999/xhtml", + 'xmlns:svg' => 'http://www.w3.org/2000/svg', + 'xmlns:xlink' => 'http://www.w3.org/1999/xlink'; + }; $self->htmlHeader(title => $title); + *YAWF::XML::html = $sub; + $self->htmlMainTabs('v', $v, 'rg'); div class => 'mainbox'; h1 $title; - lit $v->{cmap}; p class => 'center'; - img src => sprintf('%s/rg/%02d/%d.png', $self->{url_static}, $v->{rgraph}%100, $v->{rgraph}), - alt => $title, usemap => '#rgraph'; + lit $v->{svg}; end; end; + $self->htmlFooter; } diff --git a/util/init.pl b/util/init.pl index 5c171705..ac533174 100755 --- a/util/init.pl +++ b/util/init.pl @@ -22,7 +22,7 @@ print "\n"; print "Creating directory structures...\n"; -for my $d (qw| cv rg st sf |) { +for my $d (qw| cv st sf |) { print " /static/$d\n"; mkdir "$ROOT/static/$d" or die "mkdir '$ROOT/static/$d': $!\n"; for my $i (0..99) { diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql new file mode 100644 index 00000000..a48c1e73 --- /dev/null +++ b/util/updates/update_2.8.sql @@ -0,0 +1,16 @@ + +-- !BEFORE! running this SQL file, make sure to kill Multi, +-- After running this SQL file, also make sure to do a: +-- $ rm -r static/rg/ +-- And start multi again + +-- VN Relation graphs are stored in the database as SVG - no cmaps and .png anymore +UPDATE vn SET rgraph = NULL; +ALTER TABLE vn DROP CONSTRAINT vn_rgraph_fkey; +DROP TABLE relgraph; +CREATE TABLE vn_graphs ( + id SERIAL PRIMARY KEY, + svg xml NOT NULL +); +ALTER TABLE vn ADD FOREIGN KEY (rgraph) REFERENCES vn_graphs (id); + -- cgit v1.2.3 From ce6687f3766fdeca78cad90d3e461ed889ed37d6 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 25 Sep 2009 18:56:34 +0200 Subject: Multi::Maintenance: Check for and remove unused relation graphs daily And updated some comments while I was at it --- lib/Multi/Maintenance.pm | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm index e29c7b52..423def75 100644 --- a/lib/Multi/Maintenance.pm +++ b/lib/Multi/Maintenance.pm @@ -17,12 +17,12 @@ sub spawn { package_states => [ $p => [qw| _start shutdown set_daily daily set_monthly monthly log_stats - vncache tagcache vnpopularity + vncache tagcache vnpopularity cleangraphs usercache statscache revcache logrotate |], ], heap => { - daily => [qw|vncache tagcache vnpopularity|], + daily => [qw|vncache tagcache vnpopularity cleangraphs|], monthly => [qw|usercache statscache revcache logrotate|], @_, }, @@ -99,24 +99,30 @@ sub log_stats { # num, res, action, time sub vncache { - # this takes about 30s to complete. We really need to search for an alternative + # this takes about 40s to complete. We really need to search for an alternative # method of keeping the c_* columns in the vn table up-to-date. $_[KERNEL]->post(pg => do => 'SELECT update_vncache(0)', undef, 'log_stats', 'vncache'); } sub tagcache { - # this still takes "only" about 3 seconds max. Let's hope that doesn't increase too much. + # takes about 18 seconds max. ouch, but still kind-of acceptable $_[KERNEL]->post(pg => do => 'SELECT tag_vn_calc()', undef, 'log_stats', 'tagcache'); } sub vnpopularity { - # still takes at most 2 seconds. Againt, let's hope that doesn't increase... + # still takes at most 2 seconds. let's hope that doesn't increase... $_[KERNEL]->post(pg => do => 'SELECT update_vnpopularity()', undef, 'log_stats', 'vnpopularity'); } +sub cleangraphs { + # should be pretty fast + $_[KERNEL]->post(pg => do => 'DELETE FROM vn_graphs vg WHERE NOT EXISTS(SELECT 1 FROM vn WHERE rgraph = vg.id)', + undef, 'log_stats', 'cleangraphs'); +} + # # M O N T H L Y J O B S -- cgit v1.2.3 From 836eb84c9be9197b5ca842a755051f4230df7600 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 25 Sep 2009 20:16:47 +0200 Subject: Handler::VNPage: Added simple browser detection for XHTML If a browser does support the application/xhtml+xml mime, let's assume it also supports SVG (to my knowledge, this is the case in any recent browser). OTOH, browsers not supporting that mime type are sure to not support SVG, either. --- data/lang.txt | 8 ++++++++ lib/VNDB/Handler/VNPage.pm | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index 494bad8f..e7ae5cfc 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -2898,6 +2898,14 @@ ru : Когда загружаете скриншоты, пожалуйста п en : Relation graph for [_1] ru : Схема связей для [_1] +:_vnrg_notsupp +en : Not supported +ru*: + +:_vnrg_notsupp_msg +en : Your browser sucks, it doesn't have the functionality to render our nice relation graphs. +ru*: + # VN Diff viewer (/v+.+) diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 5e0fc9dc..f31b3eeb 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -23,12 +23,24 @@ sub rand { sub rg { my($self, $vid) = @_; - # TODO: browser detection + notice, this trick gives some ugly results in IE - my $v = $self->dbVNGet(id => $vid, what => 'relgraph')->[0]; return 404 if !$v->{id} || !$v->{rgraph}; my $title = mt '_vnrg_title', $v->{title}; + + if(($self->reqHeader('Accept')||'') !~ /application\/xhtml\+xml/) { + $self->htmlHeader(title => $title); + $self->htmlMainTabs('v', $v, 'rg'); + div class => 'mainbox'; + h1 $title; + div class => 'warning'; + h2 mt '_vnrg_notsupp'; + p mt '_vnrg_notsupp_msg'; + end; + end; + $self->htmlFooter; + return; + } $self->resHeader('Content-Type' => 'application/xhtml+xml'); # This is a REALLY ugly hack, need find a proper solution in YAWF -- cgit v1.2.3 From c160933061f58a0f64a6037c1db8b79fb725b495 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 26 Sep 2009 10:59:18 +0200 Subject: Converted VN relations to ENUM data type and made them translatable OK, these are actually two separate things: to make the relations translatable they didn't necessarily have to be stored as enum, and I could've also converted them to enum but not have it translatable. Nevertheless, it was easier to just do both at the same time. Also note how I used the string "$____vnrel_<rel>____$" as identifier in the relation graphs while I could have used something a lot shorter ("$<rel>$" would have been fine, for example). This is done so that graphviz can make some space for those relations - the long identifier gives a slightly more realistic representation of the actual length of the relation titles. --- ChangeLog | 2 ++ data/global.pl | 26 +++++++++++++------------- data/lang.txt | 43 +++++++++++++++++++++++++++++++++++++++++++ lib/Multi/RG.pm | 22 +++++++--------------- lib/VNDB/Handler/VNEdit.pm | 15 +++++++-------- lib/VNDB/Handler/VNPage.pm | 6 ++++-- static/f/forms.js | 7 ++++--- util/updates/update_2.8.sql | 18 ++++++++++++++++++ 8 files changed, 98 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9cb2bbd3..7f965f2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ git - ? - Converted relation graphs to use inline SVG - Relation graphs now use the color scheme of selected skin + - VN relations are translatable in both the interface and the graphs + - Converted VN relations to an enum data type 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/global.pl b/data/global.pl index 4ab04d5b..aff1c6e1 100644 --- a/data/global.pl +++ b/data/global.pl @@ -46,19 +46,19 @@ our %S = (%S, 'TV Special', 'Music Video', ], - vn_relations => [ - # Name, Reverse-- - [ 'Sequel', 0 ], - [ 'Prequel', 1 ], - [ 'Same setting', 0 ], - [ 'Alternative version', 0 ], - [ 'Shares characters', 0 ], - [ 'Side story', 0 ], - [ 'Parent story', 1 ], - [ 'Same series', 0 ], - [ 'Fandisc', 0 ], - [ 'Original game', 1 ], - ], + vn_relations => { + # id => [ order, reverse ] + seq => [ 0, 'preq' ], + preq => [ 1, 'seq' ], + set => [ 2, 'set' ], + alt => [ 3, 'alt' ], + char => [ 4, 'char' ], + side => [ 5, 'par' ], + par => [ 6, 'side' ], + ser => [ 7, 'ser' ], + fan => [ 8, 'orig' ], + orig => [ 9, 'fan' ], + }, age_ratings => { -1 => [ 'Unknown' ], 0 => [ 'All ages' ,'CERO A' ], diff --git a/data/lang.txt b/data/lang.txt index e7ae5cfc..45722c42 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -291,6 +291,49 @@ en : Other ru : Другая +# VN relations + +:_vnrel_seq +en : Sequel +ru*: + +:_vnrel_preq +en : Prequel +ru*: + +:_vnrel_set +en : Same setting +ru*: + +:_vnrel_alt +en : Alternative version +ru*: + +:_vnrel_char +en : Shares characters +ru*: + +:_vnrel_side +en : Side story +ru*: + +:_vnrel_par +en : Parent story +ru*: + +:_vnrel_ser +en : Same series +ru*: + +:_vnrel_fan +en : Fandisc +ru*: + +:_vnrel_orig +en : Original game +ru*: + + # producer types :_ptype_co diff --git a/lib/Multi/RG.pm b/lib/Multi/RG.pm index 4ae0516e..be12fd17 100644 --- a/lib/Multi/RG.pm +++ b/lib/Multi/RG.pm @@ -78,8 +78,8 @@ sub getrel { # num, res, vid $_[HEAP]{nodes}{$id} = 1; for($_[ARG0] > 0 ? @{$_[ARG1]} : ()) { - $_[HEAP]{rels}{$id.'-'.$_->{id}} = reverserel($_->{relation}) if $id < $_->{id}; - $_[HEAP]{rels}{$_->{id}.'-'.$id} = $_->{relation} if $id > $_->{id}; + $_[HEAP]{rels}{$id.'-'.$_->{id}} = $VNDB::S{vn_relations}{$_->{relation}}[1] if $id < $_->{id}; + $_[HEAP]{rels}{$_->{id}.'-'.$id} = $_->{relation} if $id > $_->{id}; if(!exists $_[HEAP]{nodes}{$_->{id}}) { $_[HEAP]{nodes}{$_->{id}} = 0; @@ -147,14 +147,13 @@ sub builddot { # num, res # [older game] -> [newer game] if($_->[4] > $_->[3]) { ($_->[0], $_->[1]) = ($_->[1], $_->[0]); - $_->[2] = reverserel($_->[2]); + $_->[2] = $VNDB::S{vn_relations}{$_->[2]}[1]; } + my $rev = $VNDB::S{vn_relations}{$_->[2]}[1]; my $label = - $VNDB::S{vn_relations}[$_->[2]][1] - ? qq|headlabel = "$VNDB::S{vn_relations}[$_->[2]][0]", taillabel = "$VNDB::S{vn_relations}[$_->[2]-1][0]"| : - $VNDB::S{vn_relations}[$_->[2]+1][1] - ? qq|headlabel = "$VNDB::S{vn_relations}[$_->[2]][0]", taillabel = "$VNDB::S{vn_relations}[$_->[2]+1][0]"| - : qq|label = " $VNDB::S{vn_relations}[$_->[2]][0]"|; + $rev ne $_->[2] + ? qq|headlabel = "\$____vnrel_$_->[2]____\$", taillabel = "\$____vnrel_${rev}____\$"| + : qq|label = "\$____vnrel_$_->[2]____\$"|; $gv .= qq|\tv$$_[1] -- v$$_[0] [ $label ]\n|; } @@ -258,12 +257,5 @@ sub proc_child { } - -# non-POE helper function -sub reverserel { # relation - return $VNDB::S{vn_relations}[$_[0]][1] ? $_[0]-1 : $VNDB::S{vn_relations}[$_[0]+1][1] ? $_[0]+1 : $_[0]; -} - - 1; diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm index f09d6ddd..591e24a6 100644 --- a/lib/VNDB/Handler/VNEdit.pm +++ b/lib/VNDB/Handler/VNEdit.pm @@ -57,7 +57,7 @@ sub edit { if(!$frm->{_err}) { # parse and re-sort fields that have multiple representations of the same information my $anime = { map +($_=>1), grep /^[0-9]+$/, split /[ ,]+/, $frm->{anime} }; - my $relations = [ map { /^([0-9]+),([0-9]+),(.+)$/ && (!$vid || $2 != $vid) ? [ $1, $2, $3 ] : () } split /\|\|\|/, $frm->{relations} ]; + my $relations = [ map { /^([a-z]+),([0-9]+),(.+)$/ && (!$vid || $2 != $vid) ? [ $1, $2, $3 ] : () } split /\|\|\|/, $frm->{relations} ]; my $screenshots = [ map /^[0-9]+,[01],[0-9]+$/ ? [split /,/] : (), split / +/, $frm->{screenshots} ]; $frm->{anime} = join ' ', sort { $a <=> $b } keys %$anime; @@ -202,7 +202,8 @@ sub _form { td class => 'tc2'; txt ' is a '; Select; - option value => $_, $self->{vn_relations}[$_][0] for (0..$#{$self->{vn_relations}}); + option value => $_, mt "_vnrel_$_" + for (sort { $self->{vn_relations}{$a}[0] <=> $self->{vn_relations}{$b}[0] } keys %{$self->{vn_relations}}); end; txt ' of'; end; @@ -250,11 +251,9 @@ sub _updreverse { # compare %old and %new for (keys %$old, keys %$new) { if(exists $$old{$_} and !exists $$new{$_}) { - $upd{$_} = -1; - } elsif((!exists $$old{$_} and exists $$new{$_}) || ($$old{$_} != $$new{$_})) { - $upd{$_} = $$new{$_}; - if ($self->{vn_relations}[$upd{$_} ][1]) { $upd{$_}-- } - elsif($self->{vn_relations}[$upd{$_}+1][1]) { $upd{$_}++ } + $upd{$_} = undef; + } elsif((!exists $$old{$_} and exists $$new{$_}) || ($$old{$_} ne $$new{$_})) { + $upd{$_} = $self->{vn_relations}{$$new{$_}}[1]; } } @@ -264,7 +263,7 @@ sub _updreverse { for my $i (keys %upd) { my $r = $self->dbVNGet(id => $i, what => 'extended relations anime screenshots')->[0]; my @newrel = map $_->{id} != $vid ? [ $_->{relation}, $_->{id} ] : (), @{$r->{relations}}; - push @newrel, [ $upd{$i}, $vid ] if $upd{$i} != -1; + push @newrel, [ $upd{$i}, $vid ] if $upd{$i}; $self->dbVNEdit($i, relations => \@newrel, editsum => "Reverse relation update caused by revision v$vid.$rev", diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index f31b3eeb..a479bf64 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -58,6 +58,8 @@ sub rg { $self->htmlHeader(title => $title); *YAWF::XML::html = $sub; + $v->{svg} =~ s/\$___(_vnrel_[a-z]+)____\$/mt $1/eg; + $self->htmlMainTabs('v', $v, 'rg'); div class => 'mainbox'; h1 $title; @@ -228,7 +230,7 @@ sub _revision { }], [ relations => join => '<br />', split => sub { my @r = map sprintf('%s: <a href="/v%d" title="%s">%s</a>', - $self->{vn_relations}[$_->{relation}][0], $_->{id}, xml_escape($_->{original}||$_->{title}), xml_escape shorten $_->{title}, 40 + mt("_vnrel_$_->{relation}"), $_->{id}, xml_escape($_->{original}||$_->{title}), xml_escape shorten $_->{title}, 40 ), sort { $a->{id} <=> $b->{id} } @{$_[0]}; return @r ? @r : (mt '_vndiff_none'); }], @@ -295,7 +297,7 @@ sub _relations { td class => 'relations'; dl; for(sort keys %rel) { - dt $self->{vn_relations}[$_][0]; + dt mt "_vnrel_$_"; dd; for (@{$rel{$_}}) { a href => "/v$_->{id}", title => $_->{original}||$_->{title}, shorten $_->{title}, 40; diff --git a/static/f/forms.js b/static/f/forms.js index ce9daab5..8c3e4e8b 100644 --- a/static/f/forms.js +++ b/static/f/forms.js @@ -199,7 +199,7 @@ function relLoad() { // fetch the relation types from the add new relation selectbox l = x('relation_new').getElementsByTagName('select')[0].options; for(i=0;i<l.length;i++) - relTypes[Math.floor(l[i].value)] = l[i].text; + relTypes[l[i].value] = l[i].text; // read the current relations l = x('relations').value.split('|||'); @@ -247,7 +247,7 @@ function relAdd(rel, vid, title) { o.appendChild(t); var options = ''; - for(var i=0;i<relTypes.length;i++) + for(var i in relTypes) options += '<option value="'+i+'"'+(i == rel ? ' selected="selected"' : '')+'>'+qq(relTypes[i])+'</option>'; t = document.createElement('td'); t.className = 'tc2'; @@ -289,10 +289,11 @@ function relSerialize() { var l = x('relation_tbl').getElementsByTagName('tr'); for(i=0;i<l.length;i++) { var title = l[i].getElementsByTagName('td')[0]; + var rel = l[i].getElementsByTagName('select')[0]; title = title.innerText || title.textContent; title = title.substr(title.indexOf(':')+1); r += (r ? '|||' : '') - +l[i].getElementsByTagName('select')[0].selectedIndex + +rel.options[rel.selectedIndex].value +','+l[i].id.substr(12)+','+title; } x('relations').value = r; diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index a48c1e73..f9704be3 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -14,3 +14,21 @@ CREATE TABLE vn_graphs ( ); ALTER TABLE vn ADD FOREIGN KEY (rgraph) REFERENCES vn_graphs (id); + +-- VN relations stored as enum +CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); +ALTER TABLE vn_relations ALTER COLUMN relation DROP DEFAULT; +ALTER TABLE vn_relations ALTER COLUMN relation TYPE vn_relation USING + CASE + WHEN relation = 0 THEN 'seq'::vn_relation + WHEN relation = 1 THEN 'preq' + WHEN relation = 2 THEN 'set' + WHEN relation = 3 THEN 'alt' + WHEN relation = 4 THEN 'char' + WHEN relation = 5 THEN 'side' + WHEN relation = 6 THEN 'par' + WHEN relation = 7 THEN 'ser' + WHEN relation = 8 THEN 'fan' + ELSE 'orig' + END; + -- cgit v1.2.3 From b7fbaa1fbce414dfbab49f6d5ae0e9eaf882d45e Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 26 Sep 2009 11:38:21 +0200 Subject: Properly handle UTF-8 in relation graph SVGs This is a workaround for a bug in DBD::Pg: http://rt.cpan.org/Public/Bug/Display.html?id=40199 Also added a charset to the content type header of the relation graph pages, though this wasn't really necessary for my Firefox to work. --- lib/VNDB/DB/VN.pm | 5 +++++ lib/VNDB/Handler/VNPage.pm | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/VNDB/DB/VN.pm b/lib/VNDB/DB/VN.pm index c6499350..9c411794 100644 --- a/lib/VNDB/DB/VN.pm +++ b/lib/VNDB/DB/VN.pm @@ -5,6 +5,7 @@ use strict; use warnings; use Exporter 'import'; use VNDB::Func 'gtintype'; +use Encode 'decode_utf8'; our @EXPORT = qw|dbVNGet dbVNAdd dbVNEdit dbVNImageId dbVNCache dbScreenshotAdd dbScreenshotGet dbScreenshotRandom|; @@ -101,6 +102,10 @@ sub dbVNGet { join(', ', @select), join(' ', @join), \%where, $o{order}, ); + if($o{what} =~ /relgraph/) { + $_->{svg} = decode_utf8($_->{svg}) for @$r; + } + if(@$r && $o{what} =~ /(anime|relations|screenshots)/) { my %r = map { $r->[$_]{anime} = []; diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index a479bf64..f244c098 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -41,7 +41,7 @@ sub rg { $self->htmlFooter; return; } - $self->resHeader('Content-Type' => 'application/xhtml+xml'); + $self->resHeader('Content-Type' => 'application/xhtml+xml; charset=UTF-8'); # This is a REALLY ugly hack, need find a proper solution in YAWF no warnings 'redefine'; -- cgit v1.2.3 From af9f6b31f054f3bdec55fb161846d25aed2687af Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 26 Sep 2009 12:02:29 +0200 Subject: Display full release dates in relation graphs Interface consistency --- ChangeLog | 1 + lib/Multi/RG.pm | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7f965f2f..e78fc489 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ git - ? - Converted relation graphs to use inline SVG - Relation graphs now use the color scheme of selected skin - VN relations are translatable in both the interface and the graphs + - Full date is displayed in graphs instead of only month/year - Converted VN relations to an enum data type 2.7 - 2009-09-24 diff --git a/lib/Multi/RG.pm b/lib/Multi/RG.pm index be12fd17..52f737c5 100644 --- a/lib/Multi/RG.pm +++ b/lib/Multi/RG.pm @@ -113,7 +113,12 @@ sub builddot { # num, res # insert all nodes, ordered by release date for (sort { $a->{date} <=> $b->{date} } @$vns) { my $date = sprintf '%08d', $_->{date}; - $date =~ s#^([0-9]{4})([0-9]{2}).+#$1==0?'N/A':$1==9999?'TBA':(($2&&$2<13?($_[HEAP]{moy}[$2-1].' '):'').$1)#e; + $date =~ s{^([0-9]{4})([0-9]{2})([0-9]{2})$}{ + $1 == 0 ? 'unknown' + : $1 == 9999 ? 'TBA' + : $2 == 99 ? $1 + : $3 == 99 ? "$1-$2" : "$1-$2-$3" + }e; my $title = $_->{title}; $title = substr($title, 0, 27).'...' if length($title) > 30; -- cgit v1.2.3 From 6728e7dbb5f06eb1d523dadafa2512099d638c56 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 26 Sep 2009 13:53:58 +0200 Subject: Use more readable font for the relation titles in the VN relgraph I would also change the font of the VN titles + info, but those boxes are fixed width and changing the font isn't guaranteed to keep the text within the boxes. This problem doesn't exist with the relation titles. --- data/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/data/style.css b/data/style.css index 0772dda8..8255aca8 100644 --- a/data/style.css +++ b/data/style.css @@ -1188,4 +1188,5 @@ svg .border { fill: none; stroke: $border$ } svg .edge polygon.border { fill: $border$ } svg .nodebg { fill: $tabbg$; stroke: $tabbg$ } svg text { fill: $maintext$ } +svg .edge text { font: 8px "Tahoma" } -- cgit v1.2.3 From 2c6f9360a25fd576fce5b35f3f512c05429d9d57 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 27 Sep 2009 09:38:43 +0200 Subject: Multi::RG: Removed unused variable --- lib/Multi/RG.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Multi/RG.pm b/lib/Multi/RG.pm index 52f737c5..1ee69911 100644 --- a/lib/Multi/RG.pm +++ b/lib/Multi/RG.pm @@ -26,7 +26,6 @@ sub spawn { heap => { font => 'Arial', fsize => [ 9, 7, 10 ], # nodes, edges, node_title - moy => [qw| Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec |], dot => '/usr/bin/dot', check_delay => 3600, @_, -- cgit v1.2.3 From 9d733c1d82f5b2b8013d3d921f66cc962fea8048 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 27 Sep 2009 10:01:46 +0200 Subject: Converted anime.type to ENUM and made them translatable Again, two separate but related things. --- ChangeLog | 6 ++++-- data/global.pl | 12 +----------- data/lang.txt | 31 +++++++++++++++++++++++++++++++ lib/Multi/Anime.pm | 13 ++++++++++++- lib/VNDB/Handler/VNPage.pm | 2 +- util/updates/update_2.8.sql | 15 +++++++++++++++ 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index e78fc489..6e360dda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,8 +2,10 @@ git - ? - Converted relation graphs to use inline SVG - Relation graphs now use the color scheme of selected skin - VN relations are translatable in both the interface and the graphs - - Full date is displayed in graphs instead of only month/year - - Converted VN relations to an enum data type + - Full date is displayed in graphs instead of only month/year + - Converted to ENUM data type: + - vn_relations.relation + - anime.type 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/global.pl b/data/global.pl index aff1c6e1..58ae6a89 100644 --- a/data/global.pl +++ b/data/global.pl @@ -35,17 +35,7 @@ our %S = (%S, producer_types => [qw|co in ng|], discussion_boards => [qw|an db v p u|], vn_lengths => [ 0..5 ], - anime_types => [ - # AniDB anime type starts counting at 1, 0 = unknown - # we start counting at 0, with NULL being unknown - 'TV Series', - 'OVA', - 'Movie', - 'Other', - 'Web', - 'TV Special', - 'Music Video', - ], + anime_types => [qw|tv ova mov oth web spe mv|], vn_relations => { # id => [ order, reverse ] seq => [ 0, 'preq' ], diff --git a/data/lang.txt b/data/lang.txt index 45722c42..197a0cdc 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -364,6 +364,37 @@ en : Trial ru : Триальный +# Anime types + +:_animetype_tv +en : TV Series +ru*: + +:_animetype_ova +en : OVA +ru*: + +:_animetype_mov +en : Movie +ru*: + +:_animetype_oth +en : Other +ru*: + +:_animetype_web +en : Web +ru*: + +:_animetype_spe +en : TV Special +ru*: + +:_animetype_mv +en : Music Video +ru*: + + # Discussion board types :_dboard_an diff --git a/lib/Multi/Anime.pm b/lib/Multi/Anime.pm index 03134925..df2f6424 100644 --- a/lib/Multi/Anime.pm +++ b/lib/Multi/Anime.pm @@ -70,6 +70,17 @@ sub spawn { lm => 0, # timestamp of last outgoing message, 0=no running msg aid => 0, # anime ID of the last sent ANIME command tag => int(rand()*50000), + # anime types as returned by AniDB (lowercased) + anime_types => { + 'unknown' => undef, # NULL + 'tv series' => 'tv', + 'ova' => 'ova', + 'movie' => 'mov', + 'other' => 'oth', + 'web' => 'web', + 'tv special' => 'spe', + 'music video' => 'mv', + }, }, ); } @@ -224,7 +235,7 @@ sub receivepacket { # input, wheelid $col[2] = undef if !$col[2] || $col[2] =~ /^0,/; $col[3] = $1 if $col[3] =~ /^([0-9]+)/; # remove multi-year stuff $col[3] = undef if !$col[3]; - $col[4] = (grep lc($VNDB::S{anime_types}[$_]) eq lc($col[4]), 0..$#{$VNDB::S{anime_types}})[0]; + $col[4] = $_[HEAP]{anime_types}{ lc($col[4]) }; $col[5] = undef if !$col[5]; $col[6] = undef if !$col[6]; $_[KERNEL]->post(pg => do => 'UPDATE anime diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index f244c098..74aef27f 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -337,7 +337,7 @@ sub _anime { txt '] '; end; acronym title => $_->{title_kanji}||$_->{title_romaji}, shorten $_->{title_romaji}, 50; - b ' ('.(defined $_->{type} ? $self->{anime_types}[$_->{type}].', ' : '').$_->{year}.')'; + b ' ('.(defined $_->{type} ? mt("_animetype_$_->{type}").', ' : '').$_->{year}.')'; txt "\n"; } } diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index f9704be3..e72af294 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -32,3 +32,18 @@ ALTER TABLE vn_relations ALTER COLUMN relation TYPE vn_relation USING ELSE 'orig' END; + +-- Anime types stored as enum +CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); +ALTER TABLE anime ALTER COLUMN type TYPE anime_type USING + CASE + WHEN type = 0 THEN 'tv'::anime_type + WHEN type = 1 THEN 'ova' + WHEN type = 2 THEN 'mov' + WHEN type = 3 THEN 'oth' + WHEN type = 4 THEN 'web' + WHEN type = 5 THEN 'spe' + WHEN type = 6 THEN 'mv' + ELSE NULL + END; + -- cgit v1.2.3 From aba49d2d9a94654393523efcc358e8cbe27d75cf Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 27 Sep 2009 12:53:15 +0200 Subject: Wrote LangFile module to handle lang.txt files Figured I'd need to do some automated processing on that file in the future, and considering the format was made to be easy to handle for humans (and not computers), this module will come in handy. I wrote that small POD for brainstorming the API, before typing even a single line of code. --- lib/LangFile.pm | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/VNDB/L10N.pm | 56 ++++++---------------- 2 files changed, 152 insertions(+), 43 deletions(-) create mode 100644 lib/LangFile.pm diff --git a/lib/LangFile.pm b/lib/LangFile.pm new file mode 100644 index 00000000..3c5ab1e2 --- /dev/null +++ b/lib/LangFile.pm @@ -0,0 +1,139 @@ + + +package LangFile; + + +sub new { + my($class, $action, $file) = @_; + open my $F, $action eq 'read' ? '<:utf8' : '>:utf8', $file or die "Opening $file: $!"; + return bless { + act => $action, + FH => $F, + # status vars for reading + intro => 1, + last => [], + }, $class; +} + + +sub read { + my $self = shift; + my $FH = $self->{FH}; + my @lines; + my $state = ''; + my($lang, $sync); + + while((my $l = shift(@{$self->{last}}) || <$FH>)) { + $l =~ s/[\r\n\t\s]+$//; + + # header + if($self->{intro}) { + push @lines, $l; + next if $l ne '/intro'; + $self->{intro} = 0; + return [ 'space', @lines ]; + } + + # key + if(!$state && $l =~ /^:(.+)$/) { + return [ 'key', $1 ]; + } + + # space + if((!$state || $state eq 'space') && ($l =~ /^#/ || $l eq '')) { + $state = 'space'; + push @lines, $l; + } elsif($state eq 'space') { + push @{$self->{last}}, "$l\n"; + return [ 'space', @lines ]; + } + + # tl + if(!$state && $l =~ /^([a-z_-]{2})([ *]):(?: (.+)|)$/) { + $lang = $1; + $sync = $2 eq '*' ? 0 : 1; + push @lines, $3||''; + $state = 'tl'; + } elsif($state eq 'tl' && $l =~ /^\s{5}(.+)$/) { + push @lines, $1; + } elsif($state eq 'tl' && $l eq '') { + push @lines, $l; + } elsif($state eq 'tl') { + my $trans = join "\n", @lines; + push @{$self->{last}}, "\n" while $trans =~ s/\n$//; + push @{$self->{last}}, $l; + return [ 'tl', $lang, $sync, $trans ]; + } + + die "Don\'t know what to do with \"$l\"" if !$state; + } + if($state eq 'space') { + return [ 'space', @lines ]; + } + if($state eq 'tl') { + my $trans = join "\n", @lines; + push @{$self->{last}}, "\n" while $trans =~ s/\n$//; + return [ 'tl', $lang, $sync, $trans ]; + } + return undef; +} + + +sub write { + my($self, @line) = @_; + my $FH = $self->{FH}; + + my $t = shift @line; + + if($t eq 'space') { + print $FH "$_\n" for @line; + } + + if($t eq 'key') { + print $FH ":$line[0]\n"; + } + + if($t eq 'tl') { + my($lang, $sync, $text) = @line; + $text =~ s/\n([^\n])/\n $1/g; + $text = " $text" if $text ne ''; + printf $FH "%s%s:%s\n", $lang, $sync ? ' ' : '*', $text; + } +} + + +sub close { + my $self = shift; + close $self->{FH}; +} + +1; + +__END__ +=pod + +=head1 NAME + +LangFile - Simple object oriented interface for the parsing and creation of lang.txt + +=head1 USAGE + + use LangFile; + my $read = LangFile->new(read => "data/lang.txt"); + my $write = LangFile->new(write => "lang-copy.txt"); + + while((my $line = $read->read())) { + # $line is an arrayref in one of the following formats: + # [ 'space', @lines ] + # unparsed lines, like the header, newlines and comments + # [ 'key', $key ] + # key line, $key is key name + # [ 'tl', $lang, $sync, $text ] + # translation line(s), $lang = language tag, $sync = 1/0, $text = translation (can include newlines) + # $line is undef on EOF, $read->next() die()s on a parsing error + + # create an identical copy of $read in $write + $write->write(@$line); + } + $write->close; + diff --git a/lib/VNDB/L10N.pm b/lib/VNDB/L10N.pm index d4ff872c..c2423f53 100644 --- a/lib/VNDB/L10N.pm +++ b/lib/VNDB/L10N.pm @@ -5,6 +5,7 @@ use warnings; { package VNDB::L10N; use base 'Locale::Maketext'; + use LangFile; sub fallback_languages { ('en') }; @@ -25,51 +26,20 @@ use warnings; en => \%VNDB::L10N::en::Lexicon, ru => \%VNDB::L10N::ru::Lexicon, ); - - open my $F, '<:utf8', $VNDB::ROOT.'/data/lang.txt' or die "Opening language file: $!\n"; - my($empty, $line, $key, $lang) = (0, 0); - while(<$F>) { - chomp; - $line++; - - # ignore intro - if(!defined $key) { - $key = 0 if /^\/intro$/; - next; - } - # ignore comments - next if /^#/; - # key - if(/^:(.+)$/) { - $key = $1; - $lang = undef; - $empty = 0; - next; - } - # locale string - if(/^([a-z_-]{2,7})[ *]: (.+)$/) { - $lang = $1; - die "Unknown language on #$line: $lang\n" if !$lang{$lang}; - die "Unknown key for locale on #$line\n" if !$key; - $lang{$lang}{$key} = $2; - $empty = 0; - next; - } - # multi-line locale string - if($lang && /^\s+([^\s].*)$/) { - $lang{$lang}{$key} .= ''.("\n"x$empty)."\n$1"; - $empty = 0; - next; - } - # empty string (count them in case they're part of a multi-line locale string) - if(/^\s*$/) { - $empty++; - next; + my $r = LangFile->new(read => "$VNDB::ROOT/data/lang.txt"); + my $key; + while(my $l = $r->read) { + my($t, @l) = @$l; + $key = $l[0] if $t eq 'key'; + if($t eq 'tl') { + my($lang, undef, $text) = @l; + next if !$text; + die "Unknown language \"$l->[1]\"\n" if !$lang{$lang}; + die "Unknown key for translation \"$lang: $text\"\n" if !$key; + $lang{$lang}{$key} = $text; } - # something we didn't expect - die "Don't know what to do with line $line\n" unless /^([a-z_-]{2,7})[ *]:/; } - close $F; + $r->close; } } -- cgit v1.2.3 From c1aacd6e74e965069541f61bea232ee4363bc1b2 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 27 Sep 2009 18:54:26 +0200 Subject: Added script for performing common operations on lang.txt Even though the LangFile module is rather low-level, writing this script was pretty easy. --- util/lang.pl | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100755 util/lang.pl diff --git a/util/lang.pl b/util/lang.pl new file mode 100755 index 00000000..28950f0f --- /dev/null +++ b/util/lang.pl @@ -0,0 +1,152 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Cwd 'abs_path'; +our $ROOT; +BEGIN { ($ROOT = abs_path $0) =~ s{/util/lang\.pl$}{}; } + +use lib $ROOT.'/lib'; +use LangFile; + +my $langtxt = "$ROOT/data/lang.txt"; + + +sub usage { + print <<__; +$0 stats + Prints some stats. + +$0 add <lang> [<file>] + Adds new (empty) translation lines for language <lang> to <file> (defaults to + the global lang.txt) for keys that don't have a TL line yet. + +$0 only <lang>[,..] <outfile> + Makes a copy of lang.txt to <outfile> and removes all translations except the + ones of langauge <lang> (comma-seperated list of tags) + +$0 merge <lang> <file> + Merges <file> into lang.txt, copying over all the translations of <lang> in + <file> while ignoring any other changes. Keys in <file> not present in + lang.txt are silently ignored. Keys in lang.txt but not in <file> remain + unaffected. Make sure each key in lang.txt already has a line for <lang>, + otherwise do an 'add' first. + +$0 reorder <lang1>,<lang2>,.. + Re-orders the translation lines in lang.txt using the specified order. +__ + exit; +} + + +sub stats { + my $r = LangFile->new(read => $langtxt); + my $keys = 0; + my %lang; + while(my $l = $r->read()) { + $keys++ if $l->[0] eq 'key'; + if($l->[0] eq 'tl') { + $lang{$l->[1]} ||= [0,0]; + $lang{$l->[1]}[0]++; + $lang{$l->[1]}[1]++ if $l->[2]; + } + } + print "lang lines sync unsync\n"; + printf "%3s %4d (%3d%%) %4d (%3d%%) %4d\n", $_, + $lang{$_}[0], $lang{$_}[0]/$keys*100, $lang{$_}[1], $lang{$_}[1]/$keys*100, $keys-$lang{$_}[1] + for keys %lang; + printf "Total keys: %d\n", $keys; +} + + +sub add { + my($lang, $file) = @_; + $file ||= $langtxt; + my $r = LangFile->new(read => $file); + my $w = LangFile->new(write => "$file~"); + my $k = 0; + while((my $l = $r->read())) { + if($k && $l->[0] ne 'tl') { + $k = 0; + $w->write('tl', $lang, 0, ''); + } + $k = 1 if $l->[0] eq 'key'; + $k = 0 if $l->[0] eq 'tl' && $l->[1] eq $lang; + $w->write(@$l); + } + $r->close; + $w->close; + rename "$file~", $file or die $!; +} + + +sub only { + my($lang, $out) = @_; + my @lang = split /,/, $lang; + my $r = LangFile->new(read => $langtxt); + my $w = LangFile->new(write => $out); + while((my $l = $r->read())) { + $w->write(@$l) unless $l->[0] eq 'tl' && !grep $_ eq $l->[1], @lang; + } + $r->close; + $w->close; +} + + +sub merge { + my($lang, $file) = @_; + + # read all translations in $lang in $file + my $trans = LangFile->new(read => $file); + my($key, %trans); + while((my $l = $trans->read)) { + $key = $l->[1] if $l->[0] eq 'key'; + $trans{$key} = [ $l->[2], $l->[3] ] if $l->[0] eq 'tl' && $l->[1] eq $lang; + } + $trans->close; + + # now update lang.txt + my $r = LangFile->new(read => $langtxt); + my $w = LangFile->new(write => "$langtxt~"); + while((my $l = $r->read)) { + $key = $l->[1] if $l->[0] eq 'key'; + ($l->[2], $l->[3]) = @{$trans{$key}} if $l->[0] eq 'tl' && $l->[1] eq $lang && $trans{$key}; + $w->write(@$l); + } + $r->close; + $w->close; + rename "$langtxt~", $langtxt or die $!; +} + + +sub reorder { + my @lang = split /,/, shift; + my $r = LangFile->new(read => $langtxt); + my $w = LangFile->new(write => "$langtxt~"); + my($key, %tl); + while((my $l = $r->read)) { + if($key && $l->[0] ne 'tl') { + $tl{$_} && $w->write(@{delete $tl{$_}}) for(@lang); + $w->write(@{$tl{$_}}) for sort keys %tl; + $key = undef; + %tl = (); + } + $key = $l->[1] if $l->[0] eq 'key'; + $tl{$l->[1]} = $l if $l->[0] eq 'tl'; + $w->write(@$l) unless $l->[0] eq 'tl'; + } + $r->close; + $w->close; + rename "$langtxt~", $langtxt or die $!; +} + + +usage if !@ARGV; +my $act = shift; +stats if $act eq 'stats'; +add @ARGV if $act eq 'add'; +only @ARGV if $act eq 'only'; +merge @ARGV if $act eq 'merge'; +reorder @ARGV if $act eq 'reorder'; + -- cgit v1.2.3 From cd414f4cf51744ecb9b468ce6f38be72c2054d4a Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 30 Sep 2009 18:41:56 +0200 Subject: Added Hungarian to the list of languages Mainly because someone offered to translate the interface into Hungarian, and interface languages are directly linked with database languages. --- ChangeLog | 1 + data/global.pl | 2 +- data/lang.txt | 4 ++++ data/style.css | 1 + static/f/icons.png | Bin 9403 -> 9474 bytes 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6e360dda..5966c38d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,7 @@ git - ? - Converted to ENUM data type: - vn_relations.relation - anime.type + - New language: Hungarian 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/global.pl b/data/global.pl index 58ae6a89..22e18670 100644 --- a/data/global.pl +++ b/data/global.pl @@ -31,7 +31,7 @@ our %S = (%S, [qw| hist board boardmod edit tag mod lock del tagmod |], # 4 [qw| hist board boardmod edit tag mod lock del tagmod usermod |], # 5 ], - languages => [qw|cs da de en es fi fr it ja ko nl no pl pt ru sv tr vi zh|], + languages => [qw|cs da de en es fi fr hu it ja ko nl no pl pt ru sv tr vi zh|], producer_types => [qw|co in ng|], discussion_boards => [qw|an db v p u|], vn_lengths => [ 0..5 ], diff --git a/data/lang.txt b/data/lang.txt index 197a0cdc..306ff2d9 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -157,6 +157,10 @@ ru : Финский en : French ru : Французский +:_lang_hu +en : Hungarian +ru*: + :_lang_it en : Italian ru : Итальянский diff --git a/data/style.css b/data/style.css index 8255aca8..0eeb0f73 100644 --- a/data/style.css +++ b/data/style.css @@ -1170,6 +1170,7 @@ a .icons { cursor: pointer } .icons.fr { background-position: -48px -66px; } .icons.it { background-position: -48px -77px; } .icons.ja { background-position: -48px -88px; } +.icons.hu { background-position: -48px -99px; } .icons.nl { background-position: -61px 0px; } .icons.no { background-position: -61px -11px; } diff --git a/static/f/icons.png b/static/f/icons.png index 78ec79fc..42c9004d 100644 Binary files a/static/f/icons.png and b/static/f/icons.png differ -- cgit v1.2.3 From c7f7fdbff9901940914ddcb77299fd7c6ec0fdc3 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 2 Oct 2009 10:35:14 +0200 Subject: JS: Moved <script> tags to bottom of the page and removed DOMLoad() Time to clean up the javascript code a bit, this is a start... --- lib/VNDB/Util/LayoutHTML.pm | 9 ++--- static/f/forms.js | 21 ++++++++-- static/f/script.js | 96 +++++++++++++++++---------------------------- 3 files changed, 56 insertions(+), 70 deletions(-) diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm index 85971ba9..99b615b5 100644 --- a/lib/VNDB/Util/LayoutHTML.pm +++ b/lib/VNDB/Util/LayoutHTML.pm @@ -14,6 +14,7 @@ sub htmlHeader { # %options->{ title, js, noindex, search } my($self, %o) = @_; my $skin = $self->reqParam('skin') || $self->authInfo->{skin} || $self->{skin_default}; $skin = $self->{skin_default} if !$self->{skins}{$skin} || !-d "$VNDB::ROOT/static/s/$skin"; + $self->{js} = $o{js}; # save for use in htmlFooter # heading html; @@ -22,12 +23,6 @@ sub htmlHeader { # %options->{ title, js, noindex, search } Link rel => 'shortcut icon', href => '/favicon.ico', type => 'image/x-icon'; Link rel => 'stylesheet', href => $self->{url_static}.'/s/'.$skin.'/style.css?'.$self->{version}, type => 'text/css', media => 'all'; Link rel => 'search', type => 'application/opensearchdescription+xml', title => 'VNDB VN Search', href => $self->{url}.'/opensearch.xml'; - if($o{js}) { - script type => 'text/javascript', src => $self->{url_static}.'/f/forms.js?'.$self->{version}; end; - } - script type => 'text/javascript', src => $self->{url_static}.'/f/script.js?'.$self->{version}; - # most browsers don't like a self-closing <script> tag... - end; if($self->authInfo->{customcss}) { (my $css = $self->authInfo->{customcss}) =~ s/\n/ /g; style type => 'text/css', $css; @@ -163,6 +158,8 @@ sub htmlFooter { a href => $self->{source_url}, mt '_footer_source'; end; end; # /div maincontent + script type => 'text/javascript', src => $self->{url_static}.'/f/script.js?'.$self->{version}, ''; + script type => 'text/javascript', src => $self->{url_static}.'/f/forms.js?'.$self->{version}, '' if $self->{js}; end; # /body end; # /html diff --git a/static/f/forms.js b/static/f/forms.js index 8c3e4e8b..6eaa5cb7 100644 --- a/static/f/forms.js +++ b/static/f/forms.js @@ -1,6 +1,3 @@ -// various form functions -// called by script.js - function qq(v) { return v.replace(/&/g,"&").replace(/</,"<").replace(/>/,">").replace(/"/g,'"'); } @@ -954,3 +951,21 @@ function tglSerialize() { } + + +// load + +if(x('relations')) + relLoad(); +if(x('jt_box_vn_scr')) + scrLoad(); +if(x('media')) + medLoad(); +if(x('jt_box_rel_vn')) + vnpLoad('vn'); +if(x('jt_box_rel_prod')) + vnpLoad('producers'); +if(x('taglinks')) + tglLoad(); + + diff --git a/static/f/script.js b/static/f/script.js index 987963dc..ba8861ee 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -2,15 +2,6 @@ /* G L O B A L S T U F F */ function x(y){return document.getElementById(y)} -function cl(o,f){if(x(o))x(o).onclick=f} -function DOMLoad(y){var d=0;var f=function(){if(d++)return;y()}; -if(document.addEventListener)document.addEventListener("DOMCont" -+"entLoaded",f,false);document.write("<script id=_ie defer src=" -+"javascript:void(0)><\/script>");document.getElementById('_ie') -.onreadystatechange=function(){if(this.readyState=="complete")f() -};if(/WebKit/i.test(navigator.userAgent))var t=setInterval( -function(){if(/loaded|complete/.test(document.readyState)){ -clearInterval(t);f()}},10);window.onload=f;} var http_request = false; function ajax(url, func) { @@ -18,7 +9,7 @@ function ajax(url, func) { http_request.abort(); http_request = (window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest(); if(http_request == null) { - alert("Your browse does not support the functionality this website requires."); + alert("Your browser does not support the functionality this website requires."); return; } http_request.onreadystatechange = function() { @@ -38,7 +29,7 @@ function setCookie(n,v) { date.setTime(date.getTime()+(365*24*60*60*1000)); document.cookie = n+'='+v+'; expires='+date.toGMTString()+'; path=/'; } -function readCookie(n) { +function getCookie(n) { var l = document.cookie.split(';'); for(var i=0; i<l.length; i++) { var c = l[i]; @@ -347,10 +338,6 @@ function dtSerialize(obj) { -/* O N L O A D E V E N T */ - -DOMLoad(function() { - // search box var i = x('sq'); i.onfocus = function () { @@ -447,12 +434,13 @@ DOMLoad(function() { } // Advanced search - cl('advselect', function() { - var e = x('advoptions'); - e.className = e.className.indexOf('hidden')>=0 ? '' : 'hidden'; - this.getElementsByTagName('i')[0].innerHTML = e.className.indexOf('hidden')>=0 ? '▸' : '▾'; - return false; - }); + if(x('advselect')) + x('advselect').onload = function() { + var e = x('advoptions'); + e.className = e.className.indexOf('hidden')>=0 ? '' : 'hidden'; + this.getElementsByTagName('i')[0].innerHTML = e.className.indexOf('hidden')>=0 ? '▸' : '▾'; + return false; + }; // auto-complete tag search if(x('advselect') && x('ti')) { @@ -480,10 +468,10 @@ DOMLoad(function() { // update spoiler cookie on VN search radio button if(x('sp_0')) { - cl('sp_0', function(){setCookie('tagspoil',0)}); - cl('sp_1', function(){setCookie('tagspoil',1)}); - cl('sp_2', function(){setCookie('tagspoil',2)}); - if((i = readCookie('tagspoil')) == null) + x('sp_0').onload = function(){setCookie('tagspoil',0)}; + x('sp_1').onload = function(){setCookie('tagspoil',1)}; + x('sp_2').onload = function(){setCookie('tagspoil',2)}; + if((i = getCookie('tagspoil')) == null) i = 1; x('sp_'+i).checked = true; } @@ -501,25 +489,26 @@ DOMLoad(function() { }; // NSFW toggle for screenshots - cl('nsfwhide', function() { - var s=0; - var l = x('screenshots').getElementsByTagName('div'); - for(var i=0;i<l.length;i++) { - if(l[i].className.indexOf('nsfw') >= 0) { - if(l[i].className.indexOf('hidden') >= 0) { + if(x('nsfwhide')) + x('nsfwhide').onload = function() { + var s=0; + var l = x('screenshots').getElementsByTagName('div'); + for(var i=0;i<l.length;i++) { + if(l[i].className.indexOf('nsfw') >= 0) { + if(l[i].className.indexOf('hidden') >= 0) { + s++; + l[i].className = 'nsfw'; + l[i].getElementsByTagName('a')[0].className = ''; + } else { + l[i].className += ' hidden'; + l[i].getElementsByTagName('a')[0].className = 'hidden'; + } + } else s++; - l[i].className = 'nsfw'; - l[i].getElementsByTagName('a')[0].className = ''; - } else { - l[i].className += ' hidden'; - l[i].getElementsByTagName('a')[0].className = 'hidden'; - } - } else - s++; - } - x('nsfwshown').innerHTML = s; - return false; - }); + } + x('nsfwshown').innerHTML = s; + return false; + }; // initialize image viewer ivInit(); @@ -549,7 +538,7 @@ DOMLoad(function() { } return false; }; - tvsSet(readCookie('tagspoil'), true); + tvsSet(getCookie('tagspoil'), true); } // Javascript tabs @@ -567,7 +556,7 @@ DOMLoad(function() { // expand/collapse edit summaries on */hist if(x('history_comments')) { setcomment = function() { - var e = readCookie('histexpand') == 1; + var e = getCookie('histexpand') == 1; var l = x('history_comments'); l.innerHTML = e ? 'collapse' : 'expand'; while(l.nodeName.toLowerCase() != 'table') @@ -584,7 +573,7 @@ DOMLoad(function() { }; setcomment(); x('history_comments').onclick = function () { - setCookie('histexpand', readCookie('histexpand') == 1 ? 0 : 1); + setCookie('histexpand', getCookie('histexpand') == 1 ? 0 : 1); setcomment(); return false; }; @@ -604,20 +593,6 @@ DOMLoad(function() { if(l[i].className == 'dateinput') dtLoad(l[i]); - // forms.js - if(x('relations')) - relLoad(); - if(x('jt_box_vn_scr')) - scrLoad(); - if(x('media')) - medLoad(); - if(x('jt_box_rel_vn')) - vnpLoad('vn'); - if(x('jt_box_rel_prod')) - vnpLoad('producers'); - if(x('taglinks')) - tglLoad(); - // make some fields readonly when patch flag is set if(x('jt_box_rel_geninfo')) { var func = function() { @@ -632,4 +607,3 @@ DOMLoad(function() { for(i=0; i<document.forms.length; i++) document.forms[i].action = document.forms[i].action.replace(/\/nospam\?/,''); -}); -- cgit v1.2.3 From 94af15ac32be7c73940f9cf66cb2a6621831a479 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 2 Oct 2009 13:20:19 +0200 Subject: JS: Wrote minimal JS library and converted image viewer This *should* be more standards-compliant, and *should* work in all major browsers. But I really have to test that. --- static/f/script.js | 199 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 147 insertions(+), 52 deletions(-) diff --git a/static/f/script.js b/static/f/script.js index ba8861ee..1c1a298e 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -1,17 +1,13 @@ -/* G L O B A L S T U F F */ - -function x(y){return document.getElementById(y)} +/* M I N I M A L J A V A S C R I P T L I B R A R Y */ var http_request = false; function ajax(url, func) { if(http_request) http_request.abort(); http_request = (window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest(); - if(http_request == null) { - alert("Your browser does not support the functionality this website requires."); - return; - } + if(http_request == null) + return alert("Your browser does not support the functionality this website requires."); http_request.onreadystatechange = function() { if(!http_request || http_request.readyState != 4 || !http_request.responseText) return; @@ -41,6 +37,103 @@ function getCookie(n) { return null; } +function x(y) { // deprecated + return document.getElementById(y) +} +function byId(n) { + return document.getElementById(n) +} +function byName(){ + var d = arguments.length > 1 ? arguments[0] : document; + var n = arguments.length > 1 ? arguments[1] : arguments[0]; + return d.getElementsByTagName(n); +} +function byClass() { // [class], [parent, class], [tagname, class], [parent, tagname, class] + var par = typeof arguments[0] == 'object' ? arguments[0] : document; + var tag = arguments.length == 2 && typeof arguments[0] == 'string' ? arguments[0] : arguments.length == 3 ? arguments[1] : '*'; + var c = arguments[arguments.length-1]; + var l = byName(par, tag); + var ret = []; + for(var i=0; i<l.length; i++) + if(hasClass(l[i], c)) + ret[ret.length-1] = l[i]; + return ret; +} + +/* wrapper around DOM element creation + * tag('string') -> createTextNode + * tag('tagname', tag(), 'string', ..) -> createElement(), appendChild(), .. + * tag('tagname', { class: 'meh', title: 'Title' }) -> createElement(), setAttribute().. + * tag('tagname', { <attributes> }, <elements>) -> create, setattr, append */ +function tag() { + if(arguments.length == 1) + return typeof arguments[0] != 'object' ? document.createTextNode(arguments[0]) : arguments[0]; + var el = typeof document.createElementNS != 'undefined' + ? document.createElementNS('http://www.w3.org/1999/xhtml', arguments[0]) + : document.createElement(arguments[0]); + for(var i=1; i<arguments.length; i++) { + if(arguments[i] == null) + continue; + if(typeof arguments[i] == 'object' && !arguments[i].appendChild) { + for(attr in arguments[i]) { + if(attr == 'style') + el.setAttribute(attr, arguments[i][attr]); + else + el[ attr == 'class' ? 'className' : attr ] = arguments[i][attr]; + } + } else + el.appendChild(tag(arguments[i])); + } + return el; +} +function addBody(el) { + if(document.body.appendChild) + document.body.appendChild(el); + else if(document.documentElement.appendChild) + document.documentElement.appendChild(el); + else if(document.appendChild) + document.appendChild(el); +} +function setContent(el, content) { + setText(el, ''); + el.appendChild(content); +} +function getText(obj) { + return obj.textContent || obj.innerText || ''; +} +function setText(obj, txt) { + if(obj.textContent != null) + obj.textContent = txt; + else + obj.innerText = txt; +} + +function listClass(obj) { + var n = obj.className; + if(!n) + return []; + return n.split(/ /); +} +function hasClass(obj, c) { + var l = listClass(obj); + for(var i=0; i<l.length; i++) + if(l[i] == c) + return true; + return false; +} +function addClass(obj, c) { + if(!hasClass(obj, c)) + obj.className = (obj.className ? obj.className+' ' : '') + c; +} +function removeClass(obj, c) { + var l = listClass(obj); + var n = []; + for(var i=0; i<l.length; i++) + if(l[i] != c) + n[n.length] = l[i]; + obj.className = n.join(' '); +} + @@ -48,25 +141,22 @@ function getCookie(n) { function ivInit() { var init = 0; - var l = document.getElementsByTagName('a'); + var l = byName('a'); for(var i=0;i<l.length;i++) if(l[i].rel.substr(0,3) == 'iv:') { init++; l[i].onclick = ivView; } - if(init && !x('iv_view')) { - var d = document.createElement('div'); - d.id = 'iv_view'; - d.innerHTML = '<b id="ivimg"></b><br />' - +'<a href="#" id="ivfull"> </a>' - +'<a href="#" onclick="return ivClose()" id="ivclose">close</a>' - +'<a href="#" onclick="return ivView(this)" id="ivprev">« previous</a>' - +'<a href="#" onclick="return ivView(this)" id="ivnext">next »</a>'; - document.body.appendChild(d); - d = document.createElement('b'); - d.id = 'ivimgload'; - d.innerHTML = 'Loading...'; - document.body.appendChild(d); + if(init && !byId('iv_view')) { + addBody(tag('div', {id: 'iv_view'}, + tag('b', {id:'ivimg'}, ''), + tag('br', null), + tag('a', {href:'#', id:'ivfull'}, ''), + tag('a', {href:'#', onclick: ivClose, id:'ivclose'}, 'close'), + tag('a', {href:'#', onclick: ivView, id:'ivprev'}, '« previous'), + tag('a', {href:'#', onclick: ivView, id:'ivnext'}, 'next »') + )); + addBody(tag('b', {id:'ivimgload'}, 'Loading...')); } } @@ -74,37 +164,40 @@ function ivView(what) { what = what && what.rel ? what : this; var u = what.href; var opt = what.rel.split(':'); - d = x('iv_view'); + var view = byId('iv_view'); + var next = byId('ivnext'); + var prev = byId('ivprev'); + var full = byId('ivfull'); - // fix prev/next links (if any) + // fix prev/next links (if any) if(opt[2]) { - var ol = document.getElementsByTagName('a'); + var ol = byName('a'); var l=[]; for(i=0;i<ol.length;i++) if(ol[i].rel.substr(0,3) == 'iv:' && ol[i].rel.indexOf(':'+opt[2]) > 4 && ol[i].className.indexOf('hidden') < 0 && ol[i].id != 'ivprev' && ol[i].id != 'ivnext') l[l.length] = ol[i]; for(i=0;i<l.length;i++) if(l[i].href == u) { - x('ivnext').style.visibility = l[i+1] ? 'visible' : 'hidden'; - x('ivnext').href = l[i+1] ? l[i+1].href : '#'; - x('ivnext').rel = l[i+1] ? l[i+1].rel : ''; - x('ivprev').style.visibility = l[i-1] ? 'visible' : 'hidden'; - x('ivprev').href = l[i-1] ? l[i-1].href : '#'; - x('ivprev').rel = l[i-1] ? l[i-1].rel : ''; + next.style.visibility = l[i+1] ? 'visible' : 'hidden'; + next.href = l[i+1] ? l[i+1].href : '#'; + next.rel = l[i+1] ? l[i+1].rel : ''; + prev.style.visibility = l[i-1] ? 'visible' : 'hidden'; + prev.href = l[i-1] ? l[i-1].href : '#'; + prev.rel = l[i-1] ? l[i-1].rel : ''; } } else - x('ivnext').style.visibility = x('ivprev').style.visibility = 'hidden'; + next.style.visibility = prev.style.visibility = 'hidden'; - // calculate dimensions + // calculate dimensions var w = Math.floor(opt[1].split('x')[0]); var h = Math.floor(opt[1].split('x')[1]); var ww = typeof(window.innerWidth) == 'number' ? window.innerWidth : document.documentElement.clientWidth; var wh = typeof(window.innerHeight) == 'number' ? window.innerHeight : document.documentElement.clientHeight; var st = typeof(window.pageYOffset) == 'number' ? window.pageYOffset : document.body && document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop; if(w+100 > ww || h+70 > wh) { - x('ivfull').href = u; - x('ivfull').innerHTML = w+'x'+h; - x('ivfull').style.visibility = 'visible'; + full.href = u; + setText(full, w+'x'+h); + full.style.visibility = 'visible'; if(w/h > ww/wh) { // width++ h *= (ww-100)/w; w = ww-100; @@ -113,31 +206,36 @@ function ivView(what) { h = wh-70; } } else - x('ivfull').style.visibility = 'hidden'; + full.style.visibility = 'hidden'; var dw = w; var dh = h+20; dw = dw < 200 ? 200 : dw; - // update document - d.style.display = 'block'; - x('ivimg').innerHTML = '<img src="'+u+'" onclick="ivClose()" onload="document.getElementById(\'ivimgload\').style.top=\'-400px\'" style="width: '+w+'px; height: '+h+'px" />'; - d.style.width = dw+'px'; - d.style.height = dh+'px'; - d.style.left = ((ww - dw) / 2 - 10)+'px'; - d.style.top = ((wh - dh) / 2 + st - 20)+'px'; - x('ivimgload').style.left = ((ww - 100) / 2 - 10)+'px'; - x('ivimgload').style.top = ((wh - 20) / 2 + st)+'px'; + // update document + view.style.display = 'block'; + setContent(x('ivimg'), tag('img', {src:u, onclick:ivClose, + onload: function() { byId('ivimgload').style.top='-400px'; }, + style: 'width: '+w+'px; height: '+h+'px' + })); + view.style.width = dw+'px'; + view.style.height = dh+'px'; + view.style.left = ((ww - dw) / 2 - 10)+'px'; + view.style.top = ((wh - dh) / 2 + st - 20)+'px'; + byId('ivimgload').style.left = ((ww - 100) / 2 - 10)+'px'; + byId('ivimgload').style.top = ((wh - 20) / 2 + st)+'px'; return false; } function ivClose() { - x('iv_view').style.display = 'none'; - x('iv_view').style.top = '-5000px'; - x('ivimgload').style.top = '-400px'; - x('ivimg').innerHTML = ''; + byId('iv_view').style.display = 'none'; + byId('iv_view').style.top = '-5000px'; + byId('ivimgload').style.top = '-400px'; + setText(byId('ivimg'), ''); return false; } +ivInit(); + @@ -510,9 +608,6 @@ function dtSerialize(obj) { return false; }; - // initialize image viewer - ivInit(); - // vnlist dropdown var l = document.getElementsByTagName('a'); for(var i=0;i<l.length;i++) -- cgit v1.2.3 From 391f25648b5df7d17bbb8968c0c78b080f94218d Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 2 Oct 2009 15:09:48 +0200 Subject: JS: Rewrote release list dropdown Abstacted a simple set of reusable functions for generating dropdown lists, as I'm likely going to need that more often. --- data/style.css | 18 +++--- lib/VNDB/Handler/VNPage.pm | 2 +- static/f/script.js | 140 +++++++++++++++++++++++++++------------------ 3 files changed, 96 insertions(+), 64 deletions(-) diff --git a/data/style.css b/data/style.css index 0eeb0f73..02dca828 100644 --- a/data/style.css +++ b/data/style.css @@ -694,14 +694,16 @@ a.addnew { margin: 0; } -#vldd { position: absolute; left: -500px; border: 1px solid $border$; background-color: $secbg$; width: 180px; } -#vldd ul { float: left; width: 90px; list-style-type: none; margin: 0; padding: 0 } -#vldd li b { display: block; font-weight: normal; padding-left: 5px; } -#vldd li i { display: block; font-style: normal; padding-left: 10px; } -#vldd li a { display: block; padding-left: 10px; color: $link$; border: 0; } -#vldd li a:hover { background: url($_boxbg$) repeat } -#vldd ul.full { width: 180px; text-align: center; } -#vldd ul.full li a { padding: 0 } +#dd_box { position: absolute; left: -500px; border: 1px solid $border$; background-color: $secbg$; } +#dd_box ul { list-style-type: none; margin: 0; padding: 0 } +#dd_box li b { display: block; font-weight: normal; padding-left: 5px; } +#dd_box li i { display: block; font-style: normal; padding-left: 10px; } +#dd_box li a { display: block; padding-left: 10px; color: $link$; border: 0; } +#dd_box li a:hover { background: url($_boxbg$) repeat } +#dd_box .vrdd { width: 180px; } +#dd_box .vrdd ul { float: left; width: 90px; } +#dd_box .vrdd ul.full { width: 180px; text-align: center; } +#dd_box .vrdd ul.full li a { padding: 0 } diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 74aef27f..126aa504 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -426,7 +426,7 @@ sub _releases { end; td class => 'tc5'; if($self->authInfo->{id}) { - a href => "/r$rel->{id}", id => "rlsel_$rel->{id}"; + a href => "/r$rel->{id}", id => "rlsel_$rel->{id}", class => 'vnrlsel'; lit $rel->{ulist} ? liststat $rel->{ulist} : '--'; end; } else { diff --git a/static/f/script.js b/static/f/script.js index 1c1a298e..fce39a11 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -56,7 +56,7 @@ function byClass() { // [class], [parent, class], [tagname, class], [parent, tag var ret = []; for(var i=0; i<l.length; i++) if(hasClass(l[i], c)) - ret[ret.length-1] = l[i]; + ret[ret.length] = l[i]; return ret; } @@ -239,74 +239,112 @@ ivInit(); +/* D R O P D O W N */ +function ddInit(obj, align, contents) { + obj.dd_align = align; // only 'left' and 'bottom' supported at the moment + obj.dd_contents = contents; + document.onmousemove = ddMouseMove; + if(!byId('dd_box')) + addBody(tag('div', {id:'dd_box', dd_used: false})); +} -/* V N L I S T D R O P D O W N */ +function ddHide() { + var box = byId('dd_box'); + setText(box, ''); + box.style.left = '-500px'; + box.dd_used = false; +} -var rstat = [ 'Unknown', 'Pending', 'Obtained', 'On loan', 'Deleted' ]; -var vstat = [ 'Unknown', 'Playing', 'Finished', 'Stalled', 'Dropped' ]; -function vlDropDown(e) { +function ddMouseMove(e) { e = e || window.event; - var tg = e.target || e.srcElement; - while(tg && (tg.nodeType == 3 || tg.nodeName.toLowerCase() != 'a')) - tg = tg.parentNode; - - var o = x('vldd'); - if(!o && (!tg || tg.id.substr(0,6) != 'rlsel_')) + var lnk = e.target || e.srcElement; + while(lnk && (lnk.nodeType == 3 || !lnk.dd_align)) + lnk = lnk.parentNode; + var box = byId('dd_box'); + if(!box.dd_used && !lnk) return; - if(o) { + if(box.dd_used) { var mouseX = e.pageX || (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft); var mouseY = e.pageY || (e.clientY + document.body.scrollTop + document.documentElement.scrollTop); - if((mouseX < ddx-5 || mouseX > ddx+o.offsetWidth+100 || mouseY < ddy-5 || mouseY > ddy+o.offsetHeight+5) - || (tg && tg.id.substr(0,6) == 'rlsel_' && tg.id != 'rlsel_'+o.relId)) { - document.body.removeChild(o); - o = null; - } + if((mouseX < ddx-10 || mouseX > ddx+box.offsetWidth+10 || mouseY < ddy-10 || mouseY > ddy+box.offsetHeight+10) + || (lnk && lnk.id == box.dd_id)) + ddHide(); } - if(!o && tg) { - o = tg; + + if(!box.dd_used && lnk) { + var content = lnk.dd_contents(lnk, box); + if(content == null) + return; + setContent(box, content); + box.dd_id = lnk.id; + box.dd_used = true; + + var o = lnk; ddx = ddy = 0; do { ddx += o.offsetLeft; ddy += o.offsetTop; } while(o = o.offsetParent); - ddx -= 185; - var cu = tg.id.substr(6); - var st = tg.innerHTML.split(' / '); - if(st[0].indexOf('loading') >= 0) - return; - var r = '<ul><li><b>Release status</b></li>'; - for(var i=0;i<rstat.length;i++) - r += st[0] && st[0].indexOf(rstat[i]) >= 0 ? '<li><i>'+rstat[i]+'</i></li>' : '<li><a href="#" onclick="return vlMod('+cu+',\'r'+i+'\')">'+rstat[i]+'</a></li>'; - r += '</ul><ul><li><b>Play status</b></li>'; - for(var i=0;i<vstat.length;i++) - r += st[1] && st[1].indexOf(vstat[i]) >= 0 ? '<li><i>'+vstat[i]+'</i></li>' : '<li><a href="#" onclick="return vlMod('+cu+',\'v'+i+'\')">'+vstat[i]+'</a></li>'; - r += '</ul>'; - if(tg.innerHTML != '--') - r += '<ul class="full"><li><a href="#" onclick="return vlMod('+cu+',\'del\')">Remove from VN list</a></li></ul>'; - - o = document.createElement('div'); - o.id = 'vldd'; - o.relId = tg.id.substr(6); - o.style.left = ddx+'px'; - o.style.top = ddy+'px'; - o.innerHTML = r; - document.body.appendChild(o); + if(lnk.dd_align == 'left') + ddx -= box.offsetWidth; + if(lnk.dd_align == 'bottom') + ddy += lnk.offsetHeight; + box.style.left = ddx+'px'; + box.style.top = ddy+'px'; + } +} + + + +// release list dropdown on VN pages + +var rstat = [ 'Unknown', 'Pending', 'Obtained', 'On loan', 'Deleted' ]; +var vstat = [ 'Unknown', 'Playing', 'Finished', 'Stalled', 'Dropped' ]; +function rlDropDown(lnk) { + var relid = lnk.id.substr(6); + var st = getText(lnk).split(' / '); + if(st[0].indexOf('loading') >= 0) + return null; + + var rs = tag('ul', tag('li', tag('b', 'Release status'))); + var vs = tag('ul', tag('li', tag('b', 'Play status'))); + for(var i=0;i<rstat.length;i++) { + if(st[0] && st[0].indexOf(rstat[i]) >= 0) + rs.appendChild(tag('li', tag('i', rstat[i]))); + else + rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+i, onclick:rlMod}, rstat[i]))); + } + for(var i=0;i<vstat.length;i++) { + if(st[0] && st[0].indexOf(vstat[i]) >= 0) + vs.appendChild(tag('li', tag('i', vstat[i]))); + else + vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+i, onclick:rlMod}, vstat[i]))); } + + return tag('div', {class:'vrdd'}, rs, vs, st[0] == '--' ? null : + tag('ul', {class:'full'}, tag('li', tag('a', {href:'#', rl_rid: relid, rl_act:'del', onclick:rlMod}, 'Remove from VN List'))) + ); } -function vlMod(rid, act) { - document.body.removeChild(x('vldd')); - x('rlsel_'+rid).innerHTML = '<b class="patch">loading...</b>'; - ajax('/xml/rlist.xml?id='+rid+';e='+act, function(hr) { - x('rlsel_'+rid).innerHTML = hr.responseXML.getElementsByTagName('rlist')[0].firstChild.nodeValue; +function rlMod() { + var lnk = byId('rlsel_'+this.rl_rid); + ddHide(); + setContent(lnk, tag('b', {class: 'patch'}, 'loading...')); + ajax('/xml/rlist.xml?id='+this.rl_rid+';e='+this.rl_act, function(hr) { + // TODO: get rid of innerHTML here... + lnk.innerHTML = hr.responseXML.getElementsByTagName('rlist')[0].firstChild.nodeValue; }); return false; } - +{ + var l = byClass('a', 'vnrlsel'); + for(var i=0;i<l.length;i++) + ddInit(l[i], 'left', rlDropDown); +} @@ -608,14 +646,6 @@ function dtSerialize(obj) { return false; }; - // vnlist dropdown - var l = document.getElementsByTagName('a'); - for(var i=0;i<l.length;i++) - if(l[i].id.substr(0,6) == 'rlsel_') { - document.onmousemove = vlDropDown; - break; - } - // VN tag spoiler options if(x('tagops')) { l = x('tagops').getElementsByTagName('a'); -- cgit v1.2.3 From acf2bf6be93125689e2f72d7360e5a5a8033d05b Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 3 Oct 2009 09:31:59 +0200 Subject: JS: Rewrote VN tagspoil & JS tabs and merged addClass and removeClass --- lib/VNDB/Handler/VNPage.pm | 1 + static/f/script.js | 164 ++++++++++++++++++++++----------------------- 2 files changed, 80 insertions(+), 85 deletions(-) diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 126aa504..16f80ef1 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -179,6 +179,7 @@ sub page { my $t = $self->dbTagStats(vid => $v->{id}, order => 'avg(tv.vote) DESC', minrating => 0, results => 999); if(@$t) { div id => 'tagops'; + # NOTE: order of these links is hardcoded in JS a href => '#', mt '_vnpage_tags_spoil0'; a href => '#', class => 'tsel', mt '_vnpage_tags_spoil1'; a href => '#', mt '_vnpage_tags_spoil2'; diff --git a/static/f/script.js b/static/f/script.js index fce39a11..9b82fa33 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -121,16 +121,18 @@ function hasClass(obj, c) { return true; return false; } -function addClass(obj, c) { - if(!hasClass(obj, c)) - obj.className = (obj.className ? obj.className+' ' : '') + c; -} -function removeClass(obj, c) { +function setClass(obj, c, set) { var l = listClass(obj); var n = []; - for(var i=0; i<l.length; i++) - if(l[i] != c) - n[n.length] = l[i]; + if(set) { + n = l; + if(!hasClass(obj, c)) + n[n.length] = c; + } else { + for(var i=0; i<l.length; i++) + if(l[i] != c) + n[n.length] = l[i]; + } obj.className = n.join(' '); } @@ -352,19 +354,20 @@ function rlMod() { /* J A V A S C R I P T T A B S */ function jtInit() { + if(!byId('jt_select')) + return; var sel = ''; var first = ''; - var l = x('jt_select').getElementsByTagName('a'); - for(var i=0;i<l.length;i++) - if(l[i].id.substr(0,7) == 'jt_sel_') { - l[i].onclick = jtSel; - if(!first) - first = l[i].id; - if(location.hash && l[i].id == 'jt_sel_'+location.hash.substr(1)) - sel = l[i].id; - } - if(!first) + var l = byName(byId('jt_select'), 'a'); + if(l.length < 1) return; + for(var i=0; i<l.length; i++) { + l[i].onclick = jtSel; + if(!first) + first = l[i].id; + if(location.hash && l[i].id == 'jt_sel_'+location.hash.substr(1)) + sel = l[i].id; + } if(!sel) sel = first; jtSel(sel, 1); @@ -374,69 +377,84 @@ function jtSel(which, nolink) { which = typeof(which) == 'string' ? which : which && which.id ? which.id : this.id; which = which.substr(7); - var l = x('jt_select').getElementsByTagName('a'); - for(var i=0;i<l.length;i++) - if(l[i].id.substr(0,7) == 'jt_sel_') { - var name = l[i].id.substr(7); - if(name != 'all') - x('jt_box_'+name).style.display = name == which || which == 'all' ? 'block' : 'none'; - var o = x('jt_sel_'+name).parentNode; - if(o.className.indexOf('tabselected') >= 0) { - if(name != which) - o.className = o.className.replace(/tabselected/, ''); - } else - if(name == which) - o.className += ' tabselected'; - } + var l = byName(byId('jt_select'), 'a'); + for(var i=0;i<l.length;i++) { + var name = l[i].id.substr(7); + if(name != 'all') + byId('jt_box_'+name).style.display = name == which || which == 'all' ? 'block' : 'none'; + var tab = l[i].parentNode; + setClass(tab, 'tabselected', name == which); + } if(!nolink) location.href = '#'+which; return false; } +jtInit(); + -/* Tag VN spoilers */ -/* lvl = null to not change lvl, lim = null to not change limit */ +/* V N P A G E T A G S P O I L E R S */ + +function tvsInit() { + if(!byId('tagops')) + return; + var l = byName(byId('tagops'), 'a'); + for(var i=0;i<l.length; i++) + l[i].onclick = tvsClick; + tvsSet(getCookie('tagspoil'), true); +} + +function tvsClick() { + var sel; + var l = byName(byId('tagops'), 'a'); + for(var i=0; i<l.length; i++) + if(l[i] == this) { + if(i < 3) { + tvsSet(i, null); + setCookie('tagspoil', i); + } else + tvsSet(null, i == 3 ? true : false); + } + return false; +} + function tvsSet(lvl, lim) { - var l = x('tagops').getElementsByTagName('a'); - for(var i=0;i<l.length;i++) { - if(i < 3) { - if(lvl == null) { /* determine level */ - if(l[i].className.indexOf('tsel') >= 0) - lvl = i; - } else { /* set level */ - if(i == lvl && l[i].className.indexOf('tsel') < 0) - l[i].className += ' tsel'; - else if(i != lvl && l[i].className.indexOf('tsel') >= 0) - l[i].className = l[i].className.replace(/tsel/, ''); - } - } else { - if(lim == null) { /* determine limit */ - if(l[i].className.indexOf('tsel') >= 0) - lim = i == 3; - } else { /* set limit */ - if((i == 3) == lim && l[i].className.indexOf('tsel') < 0) - l[i].className += ' tsel'; - else if((i == 3) != lim && l[i].className.indexOf('tsel') >= 0) - l[i].className = l[i].className.replace(/tsel/, ''); - } + /* set/get level and limit to/from the links */ + var l = byName(byId('tagops'), 'a'); + for(var i=0; i<l.length; i++) { + if(i < 3) { /* spoiler level */ + if(lvl != null) + setClass(l[i], 'tsel', i == lvl); + if(lvl == null && hasClass(l[i], 'tsel')) + lvl = i; + } else { /* display limit (3 = summary) */ + if(lim != null) + setClass(l[i], 'tsel', lim == (i == 3)); + if(lim == null && hasClass(l[i], 'tsel')) + lim = i == 3; } } - l = x('vntags').getElementsByTagName('span'); + /* update tag visibility */ + l = byName(byId('vntags'), 'span'); lim = lim ? 15 : 999; var s=0; for(i=0;i<l.length;i++) { - if((lvl < l[i].className.substr(6, 1) || s>=lim) && l[i].className.indexOf('hidden') < 0) - l[i].className += ' hidden'; - if(lvl >= l[i].className.substr(6, 1) && ++s<=lim && l[i].className.indexOf('hidden') >= 0) - l[i].className = l[i].className.replace(/hidden/, ''); + var thislvl = l[i].className.substr(6, 1); + if(thislvl <= lvl && s < lim) { + setClass(l[i], 'hidden', false); + s++; + } else + setClass(l[i], 'hidden', true); } return false; } +tvsInit(); + @@ -646,30 +664,6 @@ function dtSerialize(obj) { return false; }; - // VN tag spoiler options - if(x('tagops')) { - l = x('tagops').getElementsByTagName('a'); - for(i=0;i<l.length;i++) - l[i].onclick = function() { - var l = x('tagops').getElementsByTagName('a'); - var sel = 0; - for(var i=0;i<l.length;i++) - if(l[i] == this) { - if(i < 3) { - tvsSet(i, null); - setCookie('tagspoil', i); - } else - tvsSet(null, i==3?true:false); - } - return false; - }; - tvsSet(getCookie('tagspoil'), true); - } - - // Javascript tabs - if(x('jt_select')) - jtInit(); - // spoiler tags l = document.getElementsByTagName('b'); for(i=0;i<l.length;i++) -- cgit v1.2.3 From 73161140fba0d7775beca37deaffb78d766f42cd Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 3 Oct 2009 10:03:43 +0200 Subject: JS: Rewrote date selector and fixed onclick bug added in c7f7fdbf --- static/f/script.js | 85 +++++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/static/f/script.js b/static/f/script.js index 9b82fa33..06aa0d8f 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -458,40 +458,51 @@ tvsInit(); -/* date input */ +/* D A T E I N P U T */ + var months = ['January','February','March','April','May','June','July','August','September','October','November','December']; -function dtLoad(obj) { - var r = Math.floor(obj.value) || 0; - var v = [ Math.floor(r/10000), Math.floor(r/100)%100, r%100 ]; - var i; - r = '<select onchange="dtSerialize(this)" style="width: 70px"><option value="0">-year-</option>'; - for(i=1980; i<=(new Date()).getFullYear()+5; i++) - r += '<option value="'+i+'"'+(i == v[0] ? ' selected="selected"':'')+'>'+i+'</option>'; - r += '<option value="9999"'+(v[0] == 9999 ? ' selected="selected"':'')+'>TBA</option>'; - r += '</select><select onchange="dtSerialize(this)" style="width: 100px"><option value="99">-month-</option>'; - for(i=1; i<=12; i++) - r += '<option value="'+i+'"'+(i == v[1] ? ' selected="selected"':'')+'>'+months[i-1]+'</option>'; - r += '</select><select onchange="dtSerialize(this)" style="width: 70px"><option value="99">-day-</option>'; - for(i=1; i<=31; i++) - r += '<option value="'+i+'"'+(i == v[2] ? ' selected="selected"':'')+'>'+i+'</option>'; - r += '</select>'; - v = document.createElement('div'); - v.obj = obj; - v.innerHTML = r; - obj.parentNode.insertBefore(v, obj); -} -function dtSerialize(obj) { - obj = obj.parentNode; - var l = obj.getElementsByTagName('select'); - var v = [ l[0].options[l[0].selectedIndex].value*1, l[1].options[l[1].selectedIndex].value*1, l[2].options[l[2].selectedIndex].value*1 ]; - obj = obj.obj; - if(v[0] == 0) obj.value = 0; - else if(v[0] == 9999) obj.value = 99999999; - else obj.value = v[0]*10000 + v[1]*100 + (v[1]==99?99:v[2]); + +function dateLoad(obj) { + var val = Math.floor(obj.value) || 0; + val = [ Math.floor(val/10000), Math.floor(val/100)%100, val%100 ]; + + var year = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:0}, '-year-')); + for(var i=1980; i<=(new Date()).getFullYear()+5; i++) + year.appendChild(tag('option', {value: i, selected: i==val[0]}, i)); + year.appendChild(tag('option', {value: 9999, selected: val[0]==9999}, 'TBA')); + + var month = tag('select', {style: 'width: 100px', onchange: dateSerialize}, tag('option', {value:99}, '-month-')); + for(var i=1; i<=12; i++) + month.appendChild(tag('option', {value: i, selected: i==val[1]}, months[i-1])); + + var day = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:99}, '-day-')); + for(var i=1; i<=31; i++) + day.appendChild(tag('option', {value: i, selected: i==val[2]}, i)); + + obj.parentNode.insertBefore(tag('div', {date_obj: obj}, year, month, day), obj); +} + +function dateSerialize() { + var div = this.parentNode; + var sel = byName(div, 'select'); + var val = [ + sel[0].options[sel[0].selectedIndex].value*1, + sel[1].options[sel[1].selectedIndex].value*1, + sel[2].options[sel[2].selectedIndex].value*1 + ]; + div.date_obj.value = val[0] == 0 ? 0 : val[0] == 9999 ? 99999999 : val[0]*10000+val[1]*100+(val[1]==99?99:val[2]); + alert(div.date_obj.value); +} + +{ + var l = byClass('input', 'dateinput'); + for(i=0; i<l.length; i++) + dateLoad(l[i]); } + // search box var i = x('sq'); i.onfocus = function () { @@ -589,7 +600,7 @@ function dtSerialize(obj) { // Advanced search if(x('advselect')) - x('advselect').onload = function() { + x('advselect').onclick = function() { var e = x('advoptions'); e.className = e.className.indexOf('hidden')>=0 ? '' : 'hidden'; this.getElementsByTagName('i')[0].innerHTML = e.className.indexOf('hidden')>=0 ? '▸' : '▾'; @@ -622,9 +633,9 @@ function dtSerialize(obj) { // update spoiler cookie on VN search radio button if(x('sp_0')) { - x('sp_0').onload = function(){setCookie('tagspoil',0)}; - x('sp_1').onload = function(){setCookie('tagspoil',1)}; - x('sp_2').onload = function(){setCookie('tagspoil',2)}; + x('sp_0').onclick = function(){setCookie('tagspoil',0)}; + x('sp_1').onclick = function(){setCookie('tagspoil',1)}; + x('sp_2').onclick = function(){setCookie('tagspoil',2)}; if((i = getCookie('tagspoil')) == null) i = 1; x('sp_'+i).checked = true; @@ -644,7 +655,7 @@ function dtSerialize(obj) { // NSFW toggle for screenshots if(x('nsfwhide')) - x('nsfwhide').onload = function() { + x('nsfwhide').onclick = function() { var s=0; var l = x('screenshots').getElementsByTagName('div'); for(var i=0;i<l.length;i++) { @@ -706,12 +717,6 @@ function dtSerialize(obj) { document.body.appendChild(d); } - // date selector - l = document.getElementsByTagName('input'); - for(i=0;i<l.length;i++) - if(l[i].className == 'dateinput') - dtLoad(l[i]); - // make some fields readonly when patch flag is set if(x('jt_box_rel_geninfo')) { var func = function() { -- cgit v1.2.3 From c4ad807678926c4915c8c26b9b108250535053f7 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 3 Oct 2009 11:26:37 +0200 Subject: JS: Rewrote/updated most of the minor onload functions --- static/f/script.js | 277 ++++++++++++++++++++++++++++------------------------- 1 file changed, 148 insertions(+), 129 deletions(-) diff --git a/static/f/script.js b/static/f/script.js index 06aa0d8f..148c76df 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -176,7 +176,7 @@ function ivView(what) { var ol = byName('a'); var l=[]; for(i=0;i<ol.length;i++) - if(ol[i].rel.substr(0,3) == 'iv:' && ol[i].rel.indexOf(':'+opt[2]) > 4 && ol[i].className.indexOf('hidden') < 0 && ol[i].id != 'ivprev' && ol[i].id != 'ivnext') + if(ol[i].rel.substr(0,3) == 'iv:' && ol[i].rel.indexOf(':'+opt[2]) > 4 && !hasClass(l[i], 'hidden') && ol[i].id != 'ivprev' && ol[i].id != 'ivnext') l[l.length] = ol[i]; for(i=0;i<l.length;i++) if(l[i].href == u) { @@ -503,8 +503,11 @@ function dateSerialize() { - // search box - var i = x('sq'); +/* M I S C S T U F F */ + +// search box +{ + var i = byId('sq'); i.onfocus = function () { if(this.value == 'search') { this.value = ''; @@ -517,54 +520,153 @@ function dateSerialize() { this.style.fontStyle = 'italic' } }; +} +// VN Voting (/v+) +if(byId('votesel')) { + byId('votesel').onchange = function() { + var s = this.options[this.selectedIndex].value; + if(s == 1 && !confirm( + "You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, " + +"meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played.\n" + +"Are you really sure this visual novel matches that description?")) + return; + if(s == 10 && !confirm( + "You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, " + +"meaning this is one of the best visual novels you've ever played and it's unlikely " + +"that any other game could ever be better than this one.\n" + +"It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully!")) + return; + if(s) + location.href = location.href.replace(/\.[0-9]+/, '')+'/vote?v='+s; + }; +} - // VN Voting - i = x('votesel'); - if(i) - i.onchange = function() { - var s = this.options[this.selectedIndex].value; - if(s == 1 && !confirm( - "You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, " - +"meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played.\n" - +"Are you really sure this visual novel matches that description?")) - return; - if(s == 10 && !confirm( - "You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, " - +"meaning this is one of the best visual novels you've ever played and it's unlikely " - +"that any other game could ever be better than this one.\n" - +"It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully!")) - return; - if(s) - location.href = location.href.replace(/\.[0-9]+/, '')+'/vote?v='+s; - }; +// Advanced search (/v/*, /r) +if(byId('advselect')) { + byId('advselect').onclick = function() { + var box = byId('advoptions'); + var hidden = !hasClass(box, 'hidden'); + setClass(box, 'hidden', hidden); + setText(byName(this, 'i')[0], hidden ? '▸' : '▾'); + return false; + }; +} - // VN Wishlist editing - i = x('wishsel'); - if(i) - i.onchange = function() { - if(this.selectedIndex != 0) - location.href = location.href.replace(/\.[0-9]+/, '')+'/wish?s='+this.options[this.selectedIndex].value; - }; - // Batch Wishlist editing - i = x('batchedit'); - if(i) - i.onchange = function() { - var frm = this; - while(frm.nodeName.toLowerCase() != 'form') - frm = frm.parentNode; - if(this.selectedIndex != 0) - frm.submit(); - }; +// Spoiler filters -> cookie (/v/*) +if(byId('sp_0')) { + byId('sp_0').onclick = function() { setCookie('tagspoil', 0) }; + byId('sp_1').onclick = function() { setCookie('tagspoil', 1) }; + byId('sp_2').onclick = function() { setCookie('tagspoil', 2) }; + var spoil = getCookie('tagspoil'); + byId('sp_'+(spoil == null ? 1 : spoil)).checked = true; +} + +// NSFW VN image toggle (/v+) +if(byId('nsfw_show')) { + var msg = byId('nsfw_show'); + var img = byId('nsfw_hid'); + byName(msg, 'a')[0].onclick = function() { + msg.style.display = 'none'; + img.style.display = 'block'; + return false; + }; + img.onclick = function() { + msg.style.display = 'block'; + img.style.display = 'none'; + }; +} + +// NSFW toggle for screenshots (/v+) +if(byId('nsfwhide')) { + byId('nsfwhide').onclick = function() { + var shown = 0; + var l = byName(byId('screenshots'), 'div'); + for(var i=0; i<l.length; i++) { + if(hasClass(l[i], 'nsfw')) { + var hidden = !hasClass(l[i], 'hidden'); + setClass(l[i], 'hidden', hidden); + setClass(byName(l[i], 'a')[0], 'hidden', hidden); // for the image viewer + if(!hidden) + shown++; + } else + shown++; + } + setText(byId('nsfwshown'), shown); + return false; + }; +} + +// VN Wishlist dropdown box (/v+) +if(byId('wishsel')) { + byId('wishsel').onchange = function() { + if(this.selectedIndex != 0) + location.href = location.href.replace(/\.[0-9]+/, '') + +'/wish?s='+this.options[this.selectedIndex].value; + }; +} + +// Release list dropdown box (/r+) +if(byId('listsel')) { + byId('listsel').onchange = function() { + if(this.selectedIndex != 0) + location.href = location.href.replace(/\.[0-9]+/, '') + +'/list?e='+this.options[this.selectedIndex].value; + }; +} + +// BBCode spoiler tags +{ + var l = byClass('b', 'spoiler'); + for(var i=0; i<l.length; i++) { + l[i].onmouseover = function() { setClass(this, 'spoiler', false); setClass(this, 'spoiler_shown', true) }; + l[i].onmouseout = function() { setClass(this, 'spoiler', true); setClass(this, 'spoiler_shown', false) }; + } +} + +// vndb.org domain check +if(location.hostname != 'vndb.org') { + addBody(tag('div', {id:'debug'}, + tag('h2', 'This is not VNDB!'), + 'The real VNDB is ', + tag('a', {href:'http://vndb.org/'}, 'here'), + '.' + )); +} + +// make some fields readonly when patch flag is set (/r+/edit) +if(byId('jt_box_rel_geninfo')) { + var func = function() { + byId('doujin').disabled = + byId('resolution').disabled = + byId('voiced').disabled = + byId('ani_story').disabled = + byId('ani_ero').disabled = + byId('patch').checked; + }; + func(); + byId('patch').onclick = func; +} + +// Batch edit wishlist dropdown box (/u+/wish) +if(byId('batchedit')) { + byId('batchedit').onchange = function() { + if(this.selectedIndex == 0) + return true; + var frm = this; + while(frm.nodeName.toLowerCase() != 'form') + frm = frm.parentNode; + frm.submit(); + }; +} + +// spam protection on all forms +setTimeout(function() { + for(i=1; i<document.forms.length; i++) + document.forms[i].action = document.forms[i].action.replace(/\/nospam\?/,''); +}, 500); - // Release list editing - i = x('listsel'); - if(i) - i.onchange = function() { - if(this.selectedIndex != 0) - location.href = location.href.replace(/\.[0-9]+/, '')+'/list?e='+this.options[this.selectedIndex].value; - }; // User VN list // (might want to make this a bit more generic, as it's now also used for the user tag list) @@ -598,15 +700,6 @@ function dateSerialize() { }; } - // Advanced search - if(x('advselect')) - x('advselect').onclick = function() { - var e = x('advoptions'); - e.className = e.className.indexOf('hidden')>=0 ? '' : 'hidden'; - this.getElementsByTagName('i')[0].innerHTML = e.className.indexOf('hidden')>=0 ? '▸' : '▾'; - return false; - }; - // auto-complete tag search if(x('advselect') && x('ti')) { var fields=['ti','te']; @@ -631,58 +724,6 @@ function dateSerialize() { ); } - // update spoiler cookie on VN search radio button - if(x('sp_0')) { - x('sp_0').onclick = function(){setCookie('tagspoil',0)}; - x('sp_1').onclick = function(){setCookie('tagspoil',1)}; - x('sp_2').onclick = function(){setCookie('tagspoil',2)}; - if((i = getCookie('tagspoil')) == null) - i = 1; - x('sp_'+i).checked = true; - } - - // show/hide NSFW VN image - if(x('nsfw_show')) - x('nsfw_show').getElementsByTagName('a')[0].onclick = function() { - x('nsfw_show').style.display = 'none'; - x('nsfw_hid').style.display = 'block'; - x('nsfw_hid').onclick = function() { - x('nsfw_show').style.display = 'block'; - x('nsfw_hid').style.display = 'none'; - }; - return false - }; - - // NSFW toggle for screenshots - if(x('nsfwhide')) - x('nsfwhide').onclick = function() { - var s=0; - var l = x('screenshots').getElementsByTagName('div'); - for(var i=0;i<l.length;i++) { - if(l[i].className.indexOf('nsfw') >= 0) { - if(l[i].className.indexOf('hidden') >= 0) { - s++; - l[i].className = 'nsfw'; - l[i].getElementsByTagName('a')[0].className = ''; - } else { - l[i].className += ' hidden'; - l[i].getElementsByTagName('a')[0].className = 'hidden'; - } - } else - s++; - } - x('nsfwshown').innerHTML = s; - return false; - }; - - // spoiler tags - l = document.getElementsByTagName('b'); - for(i=0;i<l.length;i++) - if(l[i].className == 'spoiler') { - l[i].onmouseover = function() { this.className = 'spoiler_shown' }; - l[i].onmouseout = function() { this.className = 'spoiler' }; - } - // expand/collapse edit summaries on */hist if(x('history_comments')) { setcomment = function() { @@ -709,25 +750,3 @@ function dateSerialize() { }; } - // Are we really vndb? - if(location.hostname != 'vndb.org') { - var d = document.createElement('div'); - d.setAttribute('id', 'debug'); - d.innerHTML = '<h2>This is not VNDB!</h2>The real VNDB is <a href="http://vndb.org/">here</a>.'; - document.body.appendChild(d); - } - - // make some fields readonly when patch flag is set - if(x('jt_box_rel_geninfo')) { - var func = function() { - x('doujin').disabled = x('resolution').disabled = x('voiced').disabled = x('ani_story').disabled = x('ani_ero').disabled = x('patch').checked; - }; - func(); - x('patch').onclick = func; - } - - // spam protection on all forms - if(document.forms.length >= 1) - for(i=0; i<document.forms.length; i++) - document.forms[i].action = document.forms[i].action.replace(/\/nospam\?/,''); - -- cgit v1.2.3 From 5a3e3f05d2355229b7620aa7aab874bdbf8d8027 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 3 Oct 2009 11:57:27 +0200 Subject: JS: Updated and generalized list expand/collapse functions --- data/style.css | 6 +++--- lib/VNDB/Handler/Users.pm | 4 ++-- lib/VNDB/Util/CommonHTML.pm | 4 ++-- static/f/script.js | 46 +++++++++++++++++++++------------------------ 4 files changed, 28 insertions(+), 32 deletions(-) diff --git a/data/style.css b/data/style.css index 02dca828..a511d01d 100644 --- a/data/style.css +++ b/data/style.css @@ -479,13 +479,13 @@ div.mainbox.history td.tc1_2 { } div.mainbox.history td.tc2 { width: 65px; } div.mainbox.history td.tc3 { width: 90px } -tr.editsum td { +tr.collapse td { color: $grayedout$; padding-top: 0; text-align: right; } -a#history_comments { float: right } -a#history_comments:hover { border-bottom: none } +a#expandlist { float: right } +a#expandlist:hover { border-bottom: none } diff --git a/lib/VNDB/Handler/Users.pm b/lib/VNDB/Handler/Users.pm index d6193ddc..32bf96cd 100644 --- a/lib/VNDB/Handler/Users.pm +++ b/lib/VNDB/Handler/Users.pm @@ -386,7 +386,7 @@ sub posts { [ '' ], [ '' ], [ mt '_uposts_col_date' ], - sub { td; a href => '#', id => 'history_comments', 'expand'; txt mt '_uposts_col_title'; end; } + sub { td; a href => '#', id => 'expandlist', 'expand'; txt mt '_uposts_col_title'; end; } ], row => sub { my($s, $n, $l) = @_; @@ -396,7 +396,7 @@ sub posts { td class => 'tc3', $self->{l10n}->date($l->{date}); td class => 'tc4'; a href => "/t$l->{tid}.$l->{num}", $l->{title}; end; end; - Tr class => $n % 2 ? 'editsum odd hidden' : 'editsum hidden'; + Tr class => $n % 2 ? 'collapse odd hidden' : 'collapse hidden'; td colspan => 4; lit bb2html $l->{msg}, 150; end; diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index b1eb6432..1298af00 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -501,7 +501,7 @@ sub htmlHistory { sub { td colspan => 2, class => 'tc1', mt '_hist_col_rev' }, [ mt '_hist_col_date' ], [ mt '_hist_col_user' ], - sub { td; a href => '#', id => 'history_comments', 'expand'; txt mt '_hist_col_page'; end; } + sub { td; a href => '#', id => 'expandlist', 'expand'; txt mt '_hist_col_page'; end; } ], row => sub { my($s, $n, $i) = @_; @@ -524,7 +524,7 @@ sub htmlHistory { end; end; if($i->{comments}) { - Tr class => $n % 2 ? 'editsum odd hidden' : 'editsum hidden'; + Tr class => $n % 2 ? 'collapse odd hidden' : 'collapse hidden'; td colspan => 5; lit bb2html $i->{comments}, 150; end; diff --git a/static/f/script.js b/static/f/script.js index 148c76df..4ab704f0 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -660,6 +660,27 @@ if(byId('batchedit')) { }; } +// expand/collapse listings (/*/hist, /u+/posts) +if(byId('expandlist')) { + var lnk = byId('expandlist'); + setexpand = function() { + var exp = getCookie('histexpand') == 1; + setText(lnk, exp ? 'collapse' : 'expand'); + var tbl = lnk; + while(tbl.nodeName.toLowerCase() != 'table') + tbl = tbl.parentNode; + var l = byClass(tbl, 'tr', 'collapse'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'hidden', !exp); + }; + setexpand(); + lnk.onclick = function () { + setCookie('histexpand', getCookie('histexpand') == 1 ? 0 : 1); + setexpand(); + return false; + }; +} + // spam protection on all forms setTimeout(function() { for(i=1; i<document.forms.length; i++) @@ -724,29 +745,4 @@ setTimeout(function() { ); } - // expand/collapse edit summaries on */hist - if(x('history_comments')) { - setcomment = function() { - var e = getCookie('histexpand') == 1; - var l = x('history_comments'); - l.innerHTML = e ? 'collapse' : 'expand'; - while(l.nodeName.toLowerCase() != 'table') - l = l.parentNode; - l = l.getElementsByTagName('tr'); - for(var i=0;i<l.length;i++) - //alert(l[i].className); - if(l[i].className.indexOf('editsum') >= 0) { - if(!e && l[i].className.indexOf('hidden') < 0) - l[i].className += ' hidden'; - if(e && l[i].className.indexOf('hidden') >= 0) - l[i].className = l[i].className.replace(/hidden/, ''); - } - }; - setcomment(); - x('history_comments').onclick = function () { - setCookie('histexpand', getCookie('histexpand') == 1 ? 0 : 1); - setcomment(); - return false; - }; - } -- cgit v1.2.3 From c6267dcb9c5e1a444f722cd3ac35300644945912 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 3 Oct 2009 13:35:27 +0200 Subject: JS: Rewrote and generalized row group expand code --- data/style.css | 6 ++-- lib/VNDB/Handler/Tags.pm | 6 ++-- lib/VNDB/Handler/ULists.pm | 6 ++-- lib/VNDB/Handler/Users.pm | 2 +- lib/VNDB/Util/CommonHTML.pm | 2 +- static/f/script.js | 72 ++++++++++++++++++++++++--------------------- 6 files changed, 49 insertions(+), 45 deletions(-) diff --git a/data/style.css b/data/style.css index a511d01d..94a47a72 100644 --- a/data/style.css +++ b/data/style.css @@ -479,7 +479,7 @@ div.mainbox.history td.tc1_2 { } div.mainbox.history td.tc2 { width: 65px; } div.mainbox.history td.tc3 { width: 90px } -tr.collapse td { +tr.msgsum td { color: $grayedout$; padding-top: 0; text-align: right; @@ -907,8 +907,8 @@ a.addnew { /***** User VN list browser ******/ -.relhid_but, #relhidall { cursor: pointer } -.relhid_but i, #relhidall i { font-style: normal } +#expandall, .collapse_but { cursor: pointer } +#expandall i, .collapse_but i { font-style: normal } .browse.rlist .tc2 { width: 100px; } .browse.rlist .tc3 { width: 70px; } .browse.rlist .relhid .tc1 { padding-left: 40px; width: 70px; } diff --git a/lib/VNDB/Handler/Tags.pm b/lib/VNDB/Handler/Tags.pm index ae240d38..8484ad96 100644 --- a/lib/VNDB/Handler/Tags.pm +++ b/lib/VNDB/Handler/Tags.pm @@ -529,7 +529,7 @@ sub usertags { header => [ sub { td class => 'tc1'; - b id => 'relhidall'; + b id => 'expandall'; lit '<i>▸</i> '.mt('_tagu_col_num').' '; end; lit $f->{s} eq 'cnt' && $f->{o} eq 'a' ? "\x{25B4}" : qq|<a href="/u$u->{id}/tags?o=a;s=cnt">\x{25B4}</a>|; @@ -542,7 +542,7 @@ sub usertags { row => sub { my($s, $n, $l) = @_; Tr $n % 2 ? (class => 'odd') : (); - td class => 'tc1 relhid_but', id => "tag$l->{id}"; + td class => 'tc1 collapse_but', id => "tag$l->{id}"; lit "<i>▸</i> $l->{cnt}"; end; td class => 'tc2', colspan => 2; @@ -550,7 +550,7 @@ sub usertags { end; end; for(@{$l->{vns}}) { - Tr class => "relhid tag$l->{id}"; + Tr class => "collapse collapse_tag$l->{id}"; td class => 'tc1_1'; tagscore $_->{vote}; end; diff --git a/lib/VNDB/Handler/ULists.pm b/lib/VNDB/Handler/ULists.pm index 7d1a9304..049ef48a 100644 --- a/lib/VNDB/Handler/ULists.pm +++ b/lib/VNDB/Handler/ULists.pm @@ -285,7 +285,7 @@ sub _vnlist_browse { pageurl => $url->('page'), header => [ [ mt('_rlist_col_title') => 'title', 3 ], - sub { td class => 'tc2', id => 'relhidall'; lit '<i>▸</i>'.mt('_rlist_col_releases').'*'; end; }, + sub { td class => 'tc2', id => 'expandall'; lit '<i>▸</i>'.mt('_rlist_col_releases').'*'; end; }, [ mt('_rlist_col_vote') => 'vote' ], ], row => sub { @@ -294,7 +294,7 @@ sub _vnlist_browse { td class => 'tc1', colspan => 3; a href => "/v$i->{vid}", title => $i->{original}||$i->{title}, shorten $i->{title}, 70; end; - td class => 'tc2'.(@{$i->{rels}} ? ' relhid_but' : ''), id => 'vid'.$i->{vid}; + td class => 'tc2'.(@{$i->{rels}} ? ' collapse_but' : ''), id => 'vid'.$i->{vid}; lit '<i>▸</i>'; my $obtained = grep $_->{rstat}==2, @{$i->{rels}}; my $finished = grep $_->{vstat}==2, @{$i->{rels}}; @@ -307,7 +307,7 @@ sub _vnlist_browse { end; for (@{$i->{rels}}) { - Tr class => "relhid vid$i->{vid}"; + Tr class => "collapse relhid collapse_vid$i->{vid}"; td class => 'tc1'.($own ? ' own' : ''); input type => 'checkbox', name => 'sel', value => $_->{rid} if $own; diff --git a/lib/VNDB/Handler/Users.pm b/lib/VNDB/Handler/Users.pm index 32bf96cd..2708f66e 100644 --- a/lib/VNDB/Handler/Users.pm +++ b/lib/VNDB/Handler/Users.pm @@ -396,7 +396,7 @@ sub posts { td class => 'tc3', $self->{l10n}->date($l->{date}); td class => 'tc4'; a href => "/t$l->{tid}.$l->{num}", $l->{title}; end; end; - Tr class => $n % 2 ? 'collapse odd hidden' : 'collapse hidden'; + Tr class => $n % 2 ? 'collapse msgsum odd hidden' : 'collapse msgsum hidden'; td colspan => 4; lit bb2html $l->{msg}, 150; end; diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index 1298af00..e0fe65d2 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -524,7 +524,7 @@ sub htmlHistory { end; end; if($i->{comments}) { - Tr class => $n % 2 ? 'collapse odd hidden' : 'collapse hidden'; + Tr class => $n % 2 ? 'collapse msgsum odd hidden' : 'collapse msgsum hidden'; td colspan => 5; lit bb2html $i->{comments}, 150; end; diff --git a/static/f/script.js b/static/f/script.js index 4ab704f0..ccfaceba 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -1,3 +1,5 @@ +var expanded_icon = '▾'; +var collapsed_icon = '▸'; /* M I N I M A L J A V A S C R I P T L I B R A R Y */ @@ -300,7 +302,6 @@ function ddMouseMove(e) { } - // release list dropdown on VN pages var rstat = [ 'Unknown', 'Pending', 'Obtained', 'On loan', 'Deleted' ]; @@ -548,7 +549,7 @@ if(byId('advselect')) { var box = byId('advoptions'); var hidden = !hasClass(box, 'hidden'); setClass(box, 'hidden', hidden); - setText(byName(this, 'i')[0], hidden ? '▸' : '▾'); + setText(byName(this, 'i')[0], hidden ? collapsed_icon : expanded_icon); return false; }; } @@ -681,6 +682,41 @@ if(byId('expandlist')) { }; } +// collapse/expand row groups (/u+/tags, /u+/list) (limited to one table on a page) +if(byId('expandall')) { + var table = byId('expandall'); + while(table.nodeName.toLowerCase() != 'table') + table = table.parentNode; + var heads = byClass(table, 'td', 'collapse_but'); + var allhid = false; + + var alltoggle = function() { + allhid = !allhid; + var l = byClass(table, 'tr', 'collapse'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'hidden', allhid); + setText(byName(byId('expandall'), 'i')[0], allhid ? collapsed_icon : expanded_icon); + for(var i=0; i<heads.length; i++) + setText(byName(heads[i], 'i')[0], allhid ? collapsed_icon : expanded_icon); + return false; + } + byId('expandall').onclick = alltoggle; + alltoggle(); + + var singletoggle = function() { + var l = byClass(table, 'tr', 'collapse_'+this.id); + if(l.length < 1) + return; + var hid = !hasClass(l[0], 'hidden'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'hidden', hid); + setText(byName(this, 'i')[0], hid ? collapsed_icon : expanded_icon); + }; + for(var i=0; i<heads.length; i++) + heads[i].onclick = singletoggle; +} + + // spam protection on all forms setTimeout(function() { for(i=1; i<document.forms.length; i++) @@ -689,38 +725,6 @@ setTimeout(function() { - // User VN list - // (might want to make this a bit more generic, as it's now also used for the user tag list) - i = x('relhidall'); - if(i) { - var l = document.getElementsByTagName('tr'); - for(var i=0;i<l.length;i++) - if(l[i].className.indexOf('relhid') >= 0) - l[i].style.display = 'none'; - var l = document.getElementsByTagName('td'); - for(var i=0;i<l.length;i++) - if(l[i].className.indexOf('relhid_but') >= 0) - l[i].onclick = function() { - var l = document.getElementsByTagName('tr'); - for(var i=0;i<l.length;i++) - if(l[i].className.substr(7) == this.id) { - l[i].style.display = l[i].style.display == 'none' ? '' : 'none'; - this.getElementsByTagName('i')[0].innerHTML = l[i].style.display == 'none' ? '▸' : '▾'; - } - }; - var allhid = 1; - x('relhidall').onclick = function() { - allhid = !allhid; - var l = document.getElementsByTagName('tr'); - for(var i=0;i<l.length;i++) - if(l[i].className.indexOf('relhid') >= 0) { - l[i].style.display = allhid ? 'none' : ''; - x(l[i].className.substr(7)).getElementsByTagName('i')[0].innerHTML = allhid ? '▸' : '▾'; - } - this.getElementsByTagName('i')[0].innerHTML = allhid ? '▸' : '▾'; - }; - } - // auto-complete tag search if(x('advselect') && x('ti')) { var fields=['ti','te']; -- cgit v1.2.3 From 8569df99347d81a553933bff3a1530e4330b6165 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 3 Oct 2009 16:02:28 +0200 Subject: JS: Converted and improved dropdown search and moved to script.js Also converted the last onload function in script.js. I think I'll merge forms.js into script.js when converting that functionality. The total file probably wouldn't larger than 15kB gzipped, which is still smaller than the jquery core, and that doesn't even do anything by itself. --- static/f/forms.js | 176 -------------------------------------------- static/f/script.js | 212 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 186 insertions(+), 202 deletions(-) diff --git a/static/f/forms.js b/static/f/forms.js index 6eaa5cb7..57513735 100644 --- a/static/f/forms.js +++ b/static/f/forms.js @@ -8,182 +8,6 @@ function shorten(v, l) { - - - /***********************************\ - * D R O P D O W N S E A R C H * - \***********************************/ - - -function dsInit(obj, url, trfunc, serfunc, retfunc, parfunc) { - obj.setAttribute('autocomplete', 'off'); - obj.onkeydown = dsKeyDown; - obj.onblur = function() { - // timeout to make sure the tr.onclick event is called before we've hidden the object - setTimeout(function () { - if(x('ds_box')) - x('ds_box').style.top = '-500px'; - }, 500) - }; - // all local data is stored in the DOM input object - obj.returnFunc = retfunc; - obj.trFunc = trfunc; - obj.serFunc = serfunc; - obj.parFunc = parfunc; - obj.searchURL = url; - obj.selectedId = 0; -} - -function dsKeyDown(ev) { - var c = document.layers ? ev.which : document.all ? event.keyCode : ev.keyCode; - var obj = this; - - if(c == 9) // tab - return true; - - // do some processing when the enter key has been pressed - if(c == 13) { - var o = obj; - while(o && o.nodeName.toLowerCase() != 'form') - o = o.parentNode; - if(o) { - var oldsubmit = o.onsubmit; - o.onsubmit = function() { return false }; - setTimeout(function() { o.onsubmit = oldsubmit }, 100); - } - - if(obj.selectedId != 0) - obj.value = obj.serFunc(x('ds_box_'+obj.selectedId).itemData, obj); - if(obj.returnFunc) - obj.returnFunc(); - if(x('ds_box')) - x('ds_box').style.top = '-500px'; - obj.selectedId = 0; - - return false; - } - - // process up/down keys - if(x('ds_box') && (c == 38 || c == 40)) { - var l = x('ds_box').getElementsByTagName('tr'); - if(l.length < 1) - return true; - - if(obj.selectedId == 0) { - if(c == 38) // up - obj.selectedId = l[l.length-1].id.substr(7); - else - obj.selectedId = l[0].id.substr(7); - } else { - var sel = null; - for(var i=0;i<l.length;i++) - if(l[i].id == 'ds_box_'+obj.selectedId) { - if(c == 38) // up - sel = i>0 ? l[i-1] : l[l.length-1]; - else - sel = l[i+1] ? l[i+1] : l[0]; - } - obj.selectedId = sel.id.substr(7); - } - - for(var i=0;i<l.length;i++) - l[i].className = l[i].id == 'ds_box_'+obj.selectedId ? 'selected' : ''; - return true; - } - - // this.value isn't available in a keydown event - setTimeout(function() { - dsSearch(obj); - }, 10); - - return true; -} - -function dsSearch(obj) { - var b = x('ds_box'); - var v = obj.parFunc ? obj.parFunc(obj.value) : obj.value; - - // show/hide the ds_box div - if(v.length < 2) { - if(b) { - b.style.top = '-500px'; - b.innerHTML = '<b>Loading...</b>'; - } - obj.selectedId = 0; - return; - } - if(!b) { - b = document.createElement('div'); - b.setAttribute('id', 'ds_box'); - b.innerHTML = '<b>Loading...</b>'; - document.body.appendChild(b); - } - - // position the div - var ddx=0; - var ddy=obj.offsetHeight; - var o = obj; - do { - ddx += o.offsetLeft; - ddy += o.offsetTop; - } while(o = o.offsetParent); - - b.style.position = 'absolute'; - b.style.left = ddx+'px'; - b.style.top = ddy+'px'; - b.style.width = obj.offsetWidth+'px'; - - // perform search - ajax(obj.searchURL + encodeURIComponent(v), function(hr) { - dsResults(hr, obj); - }); -} - -function dsResults(hr, obj) { - var l = hr.responseXML.getElementsByTagName('item'); - var b = x('ds_box'); - if(l.length < 1) { - b.innerHTML = '<b>No results...</b>'; - obj.selectedId = 0; - return; - } - - b.innerHTML = '<table><tbody></tbody></table>'; - tb = b.getElementsByTagName('tbody')[0]; - for(var i=0;i<l.length;i++) { - var id = l[i].getAttribute('id'); - var tr = document.createElement('tr'); - tr.setAttribute('id', 'ds_box_'+id); - tr.itemData = l[i]; - if(obj.selectedId == id) - tr.setAttribute('class', 'selected'); - tr.onmouseover = function() { - obj.selectedId = this.id.substr(7); - var l = x('ds_box').getElementsByTagName('tr'); - for(var i=0;i<l.length;i++) - l[i].className = l[i].id == 'ds_box_'+obj.selectedId ? 'selected' : ''; - }; - tr.onclick = function() { - obj.value = obj.serFunc(this.itemData, obj); - if(obj.returnFunc) - obj.returnFunc(); - if(x('ds_box')) - x('ds_box').style.top = '-500px'; - obj.selectedId = 0; - }; - obj.trFunc(l[i], tr); - tb.appendChild(tr); - } - - if(obj.selectedId != 0 && !x('ds_box_'+obj.selectedId)) - obj.selectedId = 0; -} - - - - - - /*****************************\ * V N R E L A T I O N S * \*****************************/ diff --git a/static/f/script.js b/static/f/script.js index ccfaceba..715e6240 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -138,6 +138,10 @@ function setClass(obj, c, set) { obj.className = n.join(' '); } +function shorten(v, l) { + return qq(v.length > l ? v.substr(0, l-3)+'...' : v); +} + @@ -504,6 +508,167 @@ function dateSerialize() { +/* D R O P D O W N S E A R C H */ + +function dsInit(obj, url, trfunc, serfunc, retfunc, parfunc) { + obj.setAttribute('autocomplete', 'off'); + obj.onkeydown = dsKeyDown; + obj.onblur = function() { setTimeout(function () { byId('ds_box').style.top = '-500px'; }, 500) }; + obj.ds_returnFunc = retfunc; + obj.ds_trFunc = trfunc; + obj.ds_serFunc = serfunc; + obj.ds_parFunc = parfunc; + obj.ds_searchURL = url; + obj.ds_selectedId = 0; + obj.ds_dosearch = null; + if(!byId('ds_box')) + addBody(tag('div', {id: 'ds_box', style: 'position: absolute; top: -500px'}, tag('b', 'Loading...'))); +} + +function dsKeyDown(ev) { + var c = document.layers ? ev.which : document.all ? event.keyCode : ev.keyCode; + var obj = this; + + if(c == 9) // tab + return true; + + // do some processing when the enter key has been pressed + if(c == 13) { + var frm = obj; + while(frm && frm.nodeName.toLowerCase() != 'form') + frm = frm.parentNode; + if(frm) { + var oldsubmit = frm.onsubmit; + frm.onsubmit = function() { return false }; + setTimeout(function() { frm.onsubmit = oldsubmit }, 100); + } + + if(obj.ds_selectedId != 0) + obj.value = obj.ds_serFunc(byId('ds_box_'+obj.ds_selectedId).ds_itemData, obj); + if(obj.ds_returnFunc) + obj.ds_returnFunc(); + byId('ds_box').style.top = '-500px'; + obj.ds_selectedId = 0; + + return false; + } + + // process up/down keys + if(c == 38 || c == 40) { + var l = byName(byId('ds_box'), 'tr'); + if(l.length < 1) + return true; + + // get new selected id + if(obj.ds_selectedId == 0) { + if(c == 38) // up + obj.ds_selectedId = l[l.length-1].id.substr(7); + else + obj.ds_selectedId = l[0].id.substr(7); + } else { + var sel = null; + for(var i=0; i<l.length; i++) + if(l[i].id == 'ds_box_'+obj.ds_selectedId) { + if(c == 38) // up + sel = i>0 ? l[i-1] : l[l.length-1]; + else + sel = l[i+1] ? l[i+1] : l[0]; + } + obj.ds_selectedId = sel.id.substr(7); + } + + // set selected class + for(var i=0; i<l.length; i++) + setClass(l[i], 'selected', l[i].id == 'ds_box_'+obj.ds_selectedId); + return true; + } + + // perform search after a timeout + if(obj.ds_dosearch) + clearTimeout(obj.ds_dosearch); + obj.ds_dosearch = setTimeout(function() { + dsSearch(obj); + }, 500); + + return true; +} + +function dsSearch(obj) { + var box = byId('ds_box'); + var val = obj.ds_parFunc ? obj.ds_parFunc(obj.value) : obj.value; + + clearTimeout(obj.ds_dosearch); + obj.ds_dosearch = null; + + // hide the ds_box div + if(val.length < 2) { + box.style.top = '-500px'; + setContent(box, tag('b', 'Loading...')); + obj.ds_selectedId = 0; + return; + } + + // position the div + var ddx=0; + var ddy=obj.offsetHeight; + var o = obj; + do { + ddx += o.offsetLeft; + ddy += o.offsetTop; + } while(o = o.offsetParent); + + box.style.position = 'absolute'; + box.style.left = ddx+'px'; + box.style.top = ddy+'px'; + box.style.width = obj.offsetWidth+'px'; + + // perform search + ajax(obj.ds_searchURL + encodeURIComponent(val), function(hr) { + dsResults(hr, obj); + }); +} + +function dsResults(hr, obj) { + var lst = hr.responseXML.getElementsByTagName('item'); + var box = byId('ds_box'); + if(lst.length < 1) { + setContent(box, tag('b', 'No results...')); + obj.selectedId = 0; + return; + } + + var tb = tag('tbody', null); + for(var i=0; i<lst.length; i++) { + var id = lst[i].getAttribute('id'); + var tr = tag('tr', {id: 'ds_box_'+id, ds_itemData: lst[i]} ); + setClass(tr, 'selected', obj.selectedId == id); + + tr.onmouseover = function() { + obj.ds_selectedId = this.id.substr(7); + var l = byName(box, 'tr'); + for(var j=0; j<l.length; j++) + setClass(l[j], 'selected', l[j].id == 'ds_box_'+obj.ds_selectedId); + }; + tr.onmousedown = function() { + obj.value = obj.ds_serFunc(this.ds_itemData, obj); + if(obj.ds_returnFunc) + obj.ds_returnFunc(); + box.style.top = '-500px'; + obj.ds_selectedId = 0; + }; + + obj.ds_trFunc(lst[i], tr); + tb.appendChild(tr); + } + setContent(box, tag('table', tb)); + + if(obj.ds_selectedId != 0 && !byId('ds_box_'+obj.ds_selectedId)) + obj.ds_selectedId = 0; +} + + + + /* M I S C S T U F F */ // search box @@ -716,6 +881,27 @@ if(byId('expandall')) { heads[i].onclick = singletoggle; } +// auto-complete tag search (/v/*) +if(byId('advselect') && byId('ti')) { + var trfunc = function(item, tr) { + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40), + item.getAttribute('meta') == 'yes' ? tag('b', {class: 'grayedout'}, ' meta') : null, + item.getAttribute('state') == 0 ? tag('b', {class: 'grayedout'}, ' awaiting moderation') : null + )); + }; + var serfunc = function(item, obj) { + var tags = obj.value.split(/ *, */); + tags[tags.length-1] = item.firstChild.nodeValue; + return tags.join(', '); + }; + var retfunc = function() { false; }; + var parfunc = function(val) { + return (val.split(/, */))[val.split(/, */).length-1]; + }; + dsInit(byId('ti'), '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc); + dsInit(byId('te'), '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc); +} + // spam protection on all forms setTimeout(function() { @@ -724,29 +910,3 @@ setTimeout(function() { }, 500); - - // auto-complete tag search - if(x('advselect') && x('ti')) { - var fields=['ti','te']; - for(var field=0;field<fields.length;field++) - dsInit(x(fields[field]), '/xml/tags.xml?q=', - function(item, tr) { - var td = document.createElement('td'); - td.innerHTML = shorten(item.firstChild.nodeValue, 40); - if(item.getAttribute('meta') == 'yes') - td.innerHTML += ' <b class="grayedout">meta</b>'; - else if(item.getAttribute('state') == 0) - td.innerHTML += ' <b class="grayedout">awaiting moderation</b>'; - tr.appendChild(td); - }, - function(item, obj) { - var tags = obj.value.split(/ *, */); - tags[tags.length-1] = item.firstChild.nodeValue; - return tags.join(', '); - }, - function() { false; }, - function(val) { return (val.split(/, */))[val.split(/, */).length-1]; } - ); - } - - -- cgit v1.2.3 From bad759e90cae690cc4ccb36aa388d8157f5aeb4a Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 4 Oct 2009 10:08:52 +0200 Subject: JS: Moved and rewrote VN relations editor + Some fixes and improvements in the dropdown search + Renamed 'relations' field to 'vnrelations', as other relations are going to be implemented as well New relation editor code is somewhat smaller than the old, mostly thanks to the tag() function. Also tried to make things less error-prone and easier to maintain by referencing things using self-explainable class names instead of the ordering of the HTML tags. --- data/style.css | 12 ++-- lib/VNDB/Handler/VNEdit.pm | 20 +++--- static/f/forms.js | 166 --------------------------------------------- static/f/script.js | 130 ++++++++++++++++++++++++++++++++++- 4 files changed, 144 insertions(+), 184 deletions(-) diff --git a/data/style.css b/data/style.css index 94a47a72..06b68833 100644 --- a/data/style.css +++ b/data/style.css @@ -729,12 +729,12 @@ a.addnew { #jt_box_vn_rel table { margin-bottom: 10px; } #jt_box_vn_rel h2 { margin: 0 0 3px 0px; } #jt_box_vn_rel td { padding: 1px 2px; vertical-align: middle; } -#jt_box_vn_rel td.tc1 { width: 300px; text-align: right } -#jt_box_vn_rel td.tc2 { width: 170px; white-space: nowrap } -#jt_box_vn_rel td.tc3 { width: 200px; } -#jt_box_vn_rel td.tc4 { width: 40px; text-align: right } -#jt_box_vn_rel td.tc1 input { width: 280px; } -#jt_box_vn_rel td.tc2 select { width: 130px; } +#jt_box_vn_rel td.tc_vn { width: 300px; text-align: right } +#jt_box_vn_rel td.tc_rel { width: 170px; white-space: nowrap } +#jt_box_vn_rel td.tc_title { width: 200px; } +#jt_box_vn_rel td.tc_add { width: 40px; text-align: right } +#jt_box_vn_rel td.tc_vn input { width: 280px; } +#jt_box_vn_rel td.tc_rel select { width: 130px; } #ds_box { border: 1px solid $border$; diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm index 591e24a6..e618b360 100644 --- a/lib/VNDB/Handler/VNEdit.pm +++ b/lib/VNDB/Handler/VNEdit.pm @@ -28,7 +28,7 @@ sub edit { my %b4 = !$vid ? () : ( (map { $_ => $v->{$_} } qw|title original desc alias length l_wp l_encubed l_renai l_vnn img_nsfw|), anime => join(' ', sort { $a <=> $b } map $_->{id}, @{$v->{anime}}), - relations => join('|||', map $_->{relation}.','.$_->{id}.','.$_->{title}, sort { $a->{id} <=> $b->{id} } @{$v->{relations}}), + vnrelations => join('|||', map $_->{relation}.','.$_->{id}.','.$_->{title}, sort { $a->{id} <=> $b->{id} } @{$v->{relations}}), screenshots => join(' ', map sprintf('%d,%d,%d', $_->{id}, $_->{nsfw}?1:0, $_->{rid}), @{$v->{screenshots}}), ); @@ -46,7 +46,7 @@ sub edit { { name => 'l_vnn', required => 0, default => $b4{l_vnn}||0, template => 'int' }, { name => 'anime', required => 0, default => '' }, { name => 'img_nsfw', required => 0, default => 0 }, - { name => 'relations', required => 0, default => '', maxlength => 5000 }, + { name => 'vnrelations', required => 0, default => '', maxlength => 5000 }, { name => 'screenshots', required => 0, default => '', maxlength => 1000 }, { name => 'editsum', maxlength => 5000 }, ); @@ -57,11 +57,11 @@ sub edit { if(!$frm->{_err}) { # parse and re-sort fields that have multiple representations of the same information my $anime = { map +($_=>1), grep /^[0-9]+$/, split /[ ,]+/, $frm->{anime} }; - my $relations = [ map { /^([a-z]+),([0-9]+),(.+)$/ && (!$vid || $2 != $vid) ? [ $1, $2, $3 ] : () } split /\|\|\|/, $frm->{relations} ]; + my $relations = [ map { /^([a-z]+),([0-9]+),(.+)$/ && (!$vid || $2 != $vid) ? [ $1, $2, $3 ] : () } split /\|\|\|/, $frm->{vnrelations} ]; my $screenshots = [ map /^[0-9]+,[01],[0-9]+$/ ? [split /,/] : (), split / +/, $frm->{screenshots} ]; $frm->{anime} = join ' ', sort { $a <=> $b } keys %$anime; - $frm->{relations} = join '|||', map $_->[0].','.$_->[1].','.$_->[2], sort { $a->[1] <=> $b->[1]} @{$relations}; + $frm->{vnrelations} = join '|||', map $_->[0].','.$_->[1].','.$_->[2], sort { $a->[1] <=> $b->[1]} @{$relations}; $frm->{img_nsfw} = $frm->{img_nsfw} ? 1 : 0; $frm->{screenshots} = join ' ', map sprintf('%d,%d,%d', $_->[0], $_->[1]?1:0, $_->[2]), sort { $a->[0] <=> $b->[0] } @$screenshots; @@ -83,7 +83,7 @@ sub edit { ($nvid, $cid) = $self->dbVNAdd(%args) if !$vid; # update reverse relations & relation graph - if(!$vid && $#$relations >= 0 || $vid && $frm->{relations} ne $b4{relations}) { + if(!$vid && $#$relations >= 0 || $vid && $frm->{vnrelations} ne $b4{vnrelations}) { my %old = $vid ? (map { $_->{id} => $_->{relation} } @{$v->{relations}}) : (); my %new = map { $_->[1] => $_->[0] } @$relations; _updreverse($self, \%old, \%new, $nvid, $cid, $nrev); @@ -183,7 +183,7 @@ sub _form { ], vn_rel => [ mt('_vnedit_rel'), - [ hidden => short => 'relations' ], + [ hidden => short => 'vnrelations' ], [ static => nolabel => 1, content => sub { h2 mt '_vnedit_rel_sel'; table; @@ -196,10 +196,10 @@ sub _form { # TODO: localize JS relartion selector table; Tr id => 'relation_new'; - td class => 'tc1'; + td class => 'tc_vn'; input type => 'text', class => 'text'; end; - td class => 'tc2'; + td class => 'tc_rel'; txt ' is a '; Select; option value => $_, mt "_vnrel_$_" @@ -207,8 +207,8 @@ sub _form { end; txt ' of'; end; - td class => 'tc3', $v ? $v->{title} : ''; - td class => 'tc4'; + td class => 'tc_title', $v ? $v->{title} : ''; + td class => 'tc_add'; a href => '#', 'add'; end; end; diff --git a/static/f/forms.js b/static/f/forms.js index 57513735..cf03ebc4 100644 --- a/static/f/forms.js +++ b/static/f/forms.js @@ -1,170 +1,6 @@ function qq(v) { return v.replace(/&/g,"&").replace(/</,"<").replace(/>/,">").replace(/"/g,'"'); } -function shorten(v, l) { - return qq(v.length > l ? v.substr(0, l-3)+'...' : v); -} - - - - - /*****************************\ - * V N R E L A T I O N S * - \*****************************/ - - -var relTypes = []; -function relLoad() { - var i;var l;var o; - - // fetch the relation types from the add new relation selectbox - l = x('relation_new').getElementsByTagName('select')[0].options; - for(i=0;i<l.length;i++) - relTypes[l[i].value] = l[i].text; - - // read the current relations - l = x('relations').value.split('|||'); - if(l[0]) { - for(i=0;i<l.length;i++) { - var rel = l[i].split(',', 3); - relAdd(rel[0], rel[1], rel[2]); - } - } - relEmpty(); - - // make sure the title is up-to-date - x('title').onchange = function() { - l = x('jt_box_vn_rel').getElementsByTagName('td'); - for(i=0;i<l.length;i++) - if(l[i].className == 'tc3') - l[i].innerHTML = shorten(this.value, 40); - }; - - // bind the add-link - x('relation_new').getElementsByTagName('a')[0].onclick = relFormAdd; - - // dropdown - dsInit(x('relation_new').getElementsByTagName('input')[0], '/xml/vn.xml?q=', function(item, tr) { - var td = document.createElement('td'); - td.innerHTML = 'v'+item.getAttribute('id'); - td.style.textAlign = 'right'; - td.style.paddingRight = '5px'; - tr.appendChild(td); - td = document.createElement('td'); - td.innerHTML = shorten(item.firstChild.nodeValue, 40); - tr.appendChild(td); - }, function(item) { - return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue; - }, relFormAdd); -} - -function relAdd(rel, vid, title) { - var o = document.createElement('tr'); - o.setAttribute('id', 'relation_tr_'+vid); - - var t = document.createElement('td'); - t.className = 'tc1'; - t.innerHTML = 'v'+vid+':<a href="/v'+vid+'">'+shorten(title, 40)+'</a>'; - o.appendChild(t); - - var options = ''; - for(var i in relTypes) - options += '<option value="'+i+'"'+(i == rel ? ' selected="selected"' : '')+'>'+qq(relTypes[i])+'</option>'; - t = document.createElement('td'); - t.className = 'tc2'; - t.innerHTML = 'is a <select onchange="relSerialize()">'+options+'</select> of'; - o.appendChild(t); - - t = document.createElement('td'); - t.className = 'tc3'; - t.innerHTML = shorten(x('title').value, 40); - o.appendChild(t); - - t = document.createElement('td'); - t.className = 'tc4'; - t.innerHTML = '<a href="#" onclick="return relDel('+vid+')">del</a>'; - o.appendChild(t); - - x('relation_tbl').appendChild(o); - relEmpty(); -} - -function relEmpty() { - if(x('relation_tbl').getElementsByTagName('tr').length > 0) { - if(x('relation_tr_none')) - x('relation_tbl').removeChild(x('relation_tr_none')); - return; - } - var o = document.createElement('tr'); - o.setAttribute('id', 'relation_tr_none'); - var t = document.createElement('td'); - t.colspan = 4; - t.innerHTML = 'No relations selected.'; - o.appendChild(t); - x('relation_tbl').appendChild(o); -} - -function relSerialize() { - var r=''; - var i; - var l = x('relation_tbl').getElementsByTagName('tr'); - for(i=0;i<l.length;i++) { - var title = l[i].getElementsByTagName('td')[0]; - var rel = l[i].getElementsByTagName('select')[0]; - title = title.innerText || title.textContent; - title = title.substr(title.indexOf(':')+1); - r += (r ? '|||' : '') - +rel.options[rel.selectedIndex].value - +','+l[i].id.substr(12)+','+title; - } - x('relations').value = r; -} - -function relDel(vid) { - x('relation_tbl').removeChild(x('relation_tr_'+vid)); - relSerialize(); - relEmpty(); - return false; -} - -function relFormAdd() { - var txt = x('relation_new').getElementsByTagName('input')[0]; - var sel = x('relation_new').getElementsByTagName('select')[0]; - var lnk = x('relation_new').getElementsByTagName('a')[0]; - var input = txt.value; - - if(!input.match(/^v[0-9]+/)) { - alert('Visual novel textbox must start with an ID (e.g. v17)'); - return false; - } - - txt.disabled = true; - txt.value = 'loading...'; - sel.disabled = true; - lnk.innerHTML = 'loading...'; - - ajax('/xml/vn.xml?q='+encodeURIComponent(input), function(hr) { - txt.disabled = false; - txt.value = ''; - sel.disabled = false; - lnk.innerHTML = 'add'; - - var items = hr.responseXML.getElementsByTagName('item'); - if(items.length < 1) - return alert('Visual novel not found!'); - - var id = items[0].getAttribute('id'); - if(x('relation_tr_'+id)) - return alert('This visual novel has already been selected!'); - - relAdd(sel.selectedIndex, id, items[0].firstChild.nodeValue); - sel.selectedIndex = 0; - relSerialize(); - }); - return false; -} - - @@ -779,8 +615,6 @@ function tglSerialize() { // load -if(x('relations')) - relLoad(); if(x('jt_box_vn_scr')) scrLoad(); if(x('media')) diff --git a/static/f/script.js b/static/f/script.js index 715e6240..47bce2c1 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -139,7 +139,7 @@ function setClass(obj, c, set) { } function shorten(v, l) { - return qq(v.length > l ? v.substr(0, l-3)+'...' : v); + return v.length > l ? v.substr(0, l-3)+'...' : v; } @@ -221,7 +221,7 @@ function ivView(what) { // update document view.style.display = 'block'; - setContent(x('ivimg'), tag('img', {src:u, onclick:ivClose, + setContent(byId('ivimg'), tag('img', {src:u, onclick:ivClose, onload: function() { byId('ivimgload').style.top='-400px'; }, style: 'width: '+w+'px; height: '+h+'px' })); @@ -547,8 +547,14 @@ function dsKeyDown(ev) { obj.value = obj.ds_serFunc(byId('ds_box_'+obj.ds_selectedId).ds_itemData, obj); if(obj.ds_returnFunc) obj.ds_returnFunc(); + byId('ds_box').style.top = '-500px'; + setContent(byId('ds_box'), tag('b', 'Loading...')); obj.ds_selectedId = 0; + if(obj.ds_dosearch) { + clearTimeout(obj.ds_dosearch); + obj.ds_dosearch = null; + } return false; } @@ -669,6 +675,126 @@ function dsResults(hr, obj) { +/* V I S U A L N O V E L R E L A T I O N S (/v+/edit) */ + +function vnrLoad() { + // read the current relations + var rels = byId('vnrelations').value.split('|||'); + for(var i=0; i<rels.length; i++) { + var rel = rels[i].split(',', 3); + vnrAdd(rel[0], rel[1], rel[2]); + } + vnrEmpty(); + + // make sure the title is up-to-date + byId('title').onchange = function() { + var l = byClass(byId('jt_box_vn_rel'), 'td', 'tc_title'); + for(i=0; i<l.length; i++) + setText(l[i], shorten(this.value, 40)); + }; + + // bind the add-link + byName(byClass(byId('relation_new'), 'td', 'tc_add')[0], 'a')[0].onclick = vnrFormAdd; + + // dropdown + dsInit(byName(byClass(byId('relation_new'), 'td', 'tc_vn')[0], 'input')[0], '/xml/vn.xml?q=', function(item, tr) { + tr.appendChild(tag('td', { style: 'text-align: right; padding-right: 5px'}, 'v'+item.getAttribute('id'))); + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); + }, function(item) { + return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue; + }, vnrFormAdd); +} + +function vnrAdd(rel, vid, title) { + var sel = tag('select', {onchange: vnrSerialize}); + var ops = byName(byClass(byId('relation_new'), 'td', 'tc_rel')[0], 'select')[0].options; + for(var i=0; i<ops.length; i++) + sel.appendChild(tag('option', {value: ops[i].value, selected: ops[i].value==rel}, getText(ops[i]))); + + byId('relation_tbl').appendChild(tag('tr', {id:'relation_tr_'+vid}, + tag('td', {class:'tc_vn' }, 'v'+vid+':', tag('a', {href:'/v'+vid}, shorten(title, 40))), + tag('td', {class:'tc_rel' }, 'is a ', sel, ' of'), + tag('td', {class:'tc_title'}, shorten(byId('title').value, 40)), + tag('td', {class:'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, 'del')) + )); + + vnrEmpty(); +} + +function vnrEmpty() { + var tbl = byId('relation_tbl'); + if(byName(tbl, 'tr').length < 1) + tbl.appendChild(tag('tr', {id:'relation_tr_none'}, tag('td', {colspan:4}, 'No relations selected.'))); + else if(byId('relation_tr_none')) + tbl.removeChild(byId('relation_tr_none')); +} + +function vnrSerialize() { + var r = []; + var trs = byName(byId('relation_tbl'), 'tr'); + for(var i=0; i<trs.length; i++) { + var rel = byName(byClass(trs[i], 'td', 'tc_rel')[0], 'select')[0]; + r[r.length] = [ + rel.options[rel.selectedIndex].value, // relation + trs[i].id.substr(12), // vid + getText(byName(byClass(trs[i], 'td', 'tc_vn')[0], 'a')[0]) // title + ].join(','); + } + byId('vnrelations').value = r.join('|||'); +} + +function vnrDel() { + var tr = this; + while(tr.nodeName.toLowerCase() != 'tr') + tr = tr.parentNode; + byId('relation_tbl').removeChild(tr); + vnrSerialize(); + vnrEmpty(); + return false; +} + +function vnrFormAdd() { + var relnew = byId('relation_new'); + var txt = byName(byClass(relnew, 'td', 'tc_vn')[0], 'input')[0]; + var sel = byName(byClass(relnew, 'td', 'tc_rel')[0], 'select')[0]; + var lnk = byName(byClass(relnew, 'td', 'tc_add')[0], 'a')[0]; + var input = txt.value; + + if(!input.match(/^v[0-9]+/)) { + alert('Visual novel textbox must start with an ID (e.g. v17)'); + return false; + } + + txt.disabled = sel.disabled = true; + txt.value = 'loading...'; + setText(lnk, 'loading...'); + + ajax('/xml/vn.xml?q='+encodeURIComponent(input), function(hr) { + txt.disabled = sel.disabled = false; + txt.value = ''; + setText(lnk, 'add'); + + var items = hr.responseXML.getElementsByTagName('item'); + if(items.length < 1) + return alert('Visual novel not found!'); + + var id = items[0].getAttribute('id'); + if(byId('relation_tr_'+id)) + return alert('This visual novel has already been selected!'); + + vnrAdd(sel.selectedIndex, id, items[0].firstChild.nodeValue); + sel.selectedIndex = 0; + vnrSerialize(); + }); + return false; +} + +if(byId('vnrelations')) + vnrLoad(); + + + + /* M I S C S T U F F */ // search box -- cgit v1.2.3 From 6c2b8498c9c9b828337e8adc6f1f873408b40d81 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 4 Oct 2009 11:31:58 +0200 Subject: JS: Moved and rewrote the release media selector It works slightly different from the previous, in that it enforces a proper selection instead of validating the selection on form submit, and it handles adding new media differently. Probably a bit less efficient, but less code and easier to maintain. --- static/f/forms.js | 109 ----------------------------------------------------- static/f/script.js | 83 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 110 deletions(-) diff --git a/static/f/forms.js b/static/f/forms.js index cf03ebc4..7fdcadf5 100644 --- a/static/f/forms.js +++ b/static/f/forms.js @@ -257,113 +257,6 @@ function scrSerialize() { - - - /***************\ - * M E D I A * - \***************/ - - -var medTypes = [ [ '', '- medium -', false ] ]; -function medLoad() { - // load the medTypes and clear the div - var l = x('media_div').getElementsByTagName('select')[0].options; - for(var i=0;i<l.length;i++) - medTypes[medTypes.length] = [ l[i].value, l[i].text, l[i].className.indexOf('noqty') ? false : true ]; - x('media_div').innerHTML = ''; - - // load the selected media - l = x('media').value.split(','); - for(var i=0;i<l.length;i++) - if(l[i].length > 2) - medAddNew(l[i].split(' ')[0], Math.floor(l[i].split(' ')[1])); - - medAddNew('', 0); - medSetSubmit(); -} - -function medSetSubmit() { - var o=x('media'); - while(o.nodeName.toLowerCase() != 'form') - o = o.parentNode; - oldfunc = o.onsubmit; - o.onsubmit = function() { - var l = x('media_div').getElementsByTagName('span'); - for(var i=0;i<l.length-1;i++) { - var s = l[i].getElementsByTagName('select'); - if(!medTypes[s[1].selectedIndex][2] && s[0].selectedIndex == 0) { - alert('Media '+medTypes[s[1].selectedIndex][1]+' requires a quantity to be specified!'); - return false; - } - } - return oldfunc ? oldfunc() : true; - }; -} - -function medAddNew(med, qty) { - var o = document.createElement('span'); - var r = '<select class="qty" onchange="medSerialize()"><option value="0">- quantity -</option>'; - for(var i=1;i<=20;i++) - r += '<option value="'+i+'"'+(qty == i ? ' selected="selected"' : '')+'>'+i+'</option>'; - r += '</select><select class="medium" onchange="return medCheckNew(this)">'; - for(i=0;i<medTypes.length;i++) - r += '<option value="'+medTypes[i][0]+'"'+(med == medTypes[i][0] ? ' selected="selected"' : '')+'>'+medTypes[i][1]+'</option>'; - r += '</select>'; - if(med != '') - r += '<input type="button" class="submit" onclick="return medDel(this)" value="remove" />'; - o.innerHTML = r; - x('media_div').appendChild(o); -} - -function medDel(what) { - what = what.nodeName ? what : this; - while(what.nodeName.toLowerCase() != 'span') - what = what.parentNode; - x('media_div').removeChild(what); - medSerialize(); - return false; -} - -function medCheckNew() { - // check for non-new items and add remove buttons - var l = x('media_div').getElementsByTagName('span'); - var createnew=1; - for(var i=0;i<l.length;i++) { - var sel = l[i].getElementsByTagName('select')[1].selectedIndex; - if(sel == 0) - createnew = 0; - else if(l[i].getElementsByTagName('input').length < 1) { - var a = document.createElement('input'); - a.type = 'button'; - a.className = 'submit'; - a.onclick = medDel; - a.value = 'remove'; - l[i].appendChild(a); - } - } - if(createnew) - medAddNew('', 0); - medSerialize(); - - return true; -} - -function medSerialize() { - var r = ''; - var l = x('media_div').getElementsByTagName('span'); - for(var i=0;i<l.length;i++) { - var sel = l[i].getElementsByTagName('select'); - if(sel[1].selectedIndex != 0) - r += (r ? ',' : '') + medTypes[sel[1].selectedIndex][0] + ' ' + (medTypes[sel[1].selectedIndex][2] ? 0 : sel[0].selectedIndex); - } - x('media').value = r; -} - - - - - - /****************************************************\ * V I S U A L N O V E L S / P R O D U C E R S * \****************************************************/ @@ -617,8 +510,6 @@ function tglSerialize() { if(x('jt_box_vn_scr')) scrLoad(); -if(x('media')) - medLoad(); if(x('jt_box_rel_vn')) vnpLoad('vn'); if(x('jt_box_rel_prod')) diff --git a/static/f/script.js b/static/f/script.js index 47bce2c1..31225a6c 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -680,7 +680,7 @@ function dsResults(hr, obj) { function vnrLoad() { // read the current relations var rels = byId('vnrelations').value.split('|||'); - for(var i=0; i<rels.length; i++) { + for(var i=0; i<rels.length && rels[0].length>1; i++) { var rel = rels[i].split(',', 3); vnrAdd(rel[0], rel[1], rel[2]); } @@ -795,6 +795,87 @@ if(byId('vnrelations')) +/* R E L E A S E M E D I A (/r+/edit) */ + +var medTypes = [ ]; +function medLoad() { + // load the medTypes and clear the div + var sel = byName(byId('media_div'), 'select')[0].options; + for(var i=0; i<sel.length; i++) + medTypes[medTypes.length] = [ sel[i].value, getText(sel[i]), !hasClass(sel[i], 'noqty') ]; + setText(byId('media_div'), ''); + + // load the selected media + var med = byId('media').value.split(','); + for(var i=0; i<med.length && med[i].length > 1; i++) + medAdd(med[i].split(' ')[0], Math.floor(med[i].split(' ')[1])); + + medAdd('', 0); +} + +function medAdd(med, qty) { + var qsel = tag('select', {class:'qty', onchange:medSerialize}, tag('option', {value:0}, '- quantity -')); + for(var i=1; i<=20; i++) + qsel.appendChild(tag('option', {value:i, selected: qty==i}, i)); + + var msel = tag('select', {class:'medium', onchange: med == '' ? medFormAdd : medSerialize}); + if(med == '') + msel.appendChild(tag('option', {value:''}, '- medium -')); + for(var i=0; i<medTypes.length; i++) + msel.appendChild(tag('option', {value:medTypes[i][0], selected: med==medTypes[i][0]}, medTypes[i][1])); + + byId('media_div').appendChild(tag('span', qsel, msel, + med != '' ? tag('input', {type: 'button', class:'submit', onclick:medDel, value:'remove'}) : null + )); +} + +function medDel() { + var span = this; + while(span.nodeName.toLowerCase() != 'span') + span = span.parentNode; + byId('media_div').removeChild(span); + medSerialize(); + return false; +} + +function medFormAdd() { + var span = this; + while(span.nodeName.toLowerCase() != 'span') + span = span.parentNode; + var med = byClass(span, 'select', 'medium')[0]; + var qty = byClass(span, 'select', 'qty')[0]; + if(!med.selectedIndex) + return; + medAdd(med.options[med.selectedIndex].value, qty.options[qty.selectedIndex].value); + byId('media_div').removeChild(span); + medAdd('', 0); + medSerialize(); +} + +function medSerialize() { + var r = []; + var meds = byName(byId('media_div'), 'span'); + for(var i=0; i<meds.length-1; i++) { + var med = byClass(meds[i], 'select', 'medium')[0]; + var qty = byClass(meds[i], 'select', 'qty')[0]; + + /* correct quantity if necessary */ + if(medTypes[med.selectedIndex][2] && !qty.selectedIndex) + qty.selectedIndex = 1; + if(!medTypes[med.selectedIndex][2] && qty.selectedIndex) + qty.selectedIndex = 0; + + r[r.length] = medTypes[med.selectedIndex][0] + ' ' + qty.selectedIndex; + } + byId('media').value = r.join(','); +} + +if(byId('jt_box_rel_format')) + medLoad(); + + + + /* M I S C S T U F F */ // search box -- cgit v1.2.3 From d703d1dd64ffcf6af82b2747388a1001228ec30f Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 4 Oct 2009 15:02:00 +0200 Subject: JS: Moved and rewrote VN screenshot uploader Works pretty much the same as the old version. --- data/style.css | 1 + static/f/forms.js | 254 ---------------------------------------------------- static/f/script.js | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 252 insertions(+), 259 deletions(-) diff --git a/data/style.css b/data/style.css index 06b68833..d09c7060 100644 --- a/data/style.css +++ b/data/style.css @@ -765,6 +765,7 @@ a.addnew { #scr_table td { height: 108px; border-top: 1px solid #258; padding: 0; padding-right: 5px } #scr_table td.thumb { width: 136px; vertical-align: middle } #scr_table select { width: 400px; } +div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px; position: absolute; left: -500px; top: -500px; } diff --git a/static/f/forms.js b/static/f/forms.js index 7fdcadf5..d490b0d8 100644 --- a/static/f/forms.js +++ b/static/f/forms.js @@ -5,258 +5,6 @@ function qq(v) { - /*********************************\ - * V N S C R E E N S H O T S * - \*********************************/ - - -var scrRel = [ [ 0, '-- select release --' ] ]; -var scrStaticURL; -function scrLoad() { - // load the releases - scrStaticURL = x('scr_rel').className; - var l = x('scr_rel').options; - for(var i=0;i<l.length;i++) - scrRel[i+1] = [ l[i].value, l[i].text ]; - x('scr_rel').parentNode.removeChild(x('scr_rel')); - - // load the current screenshots - l = x('screenshots').value.split(' '); - for(i=0;i<l.length;i++) - if(l[i].length > 2) { - var r = l[i].split(','); - scrAdd(r[0], r[1], r[2]); - } - scrLast(); - scrCheckStatus(); - - scrSetSubmit(); -} - -// give an error when submitting the form while still uploading an image -function scrSetSubmit() { - var o=x('screenshots'); - while(o.nodeName.toLowerCase() != 'form') - o = o.parentNode; - oldfunc = o.onsubmit; - o.onsubmit = function() { - var c=0;var r=0; - var l = x('scr_table').getElementsByTagName('tr'); - for(var i=0;i<l.length-1;i++) { - if(l[i].scrStatus > 0) - c=1; - else if(l[i].getElementsByTagName('select')[0].selectedIndex == 0) - r=1; - } - if(c) { - alert('Please wait for the screenshots to be uploaded before submitting the form.'); - return false; - } else if(r) { - alert('Please select the appropriate release for every screenshot'); - return false; - } else if(oldfunc) - return oldfunc(); - }; -} - - -function scrURL(id, t) { - return scrStaticURL+'/s'+t+'/'+(id%100<10?'0':'')+(id%100)+'/'+id+'.jpg'; -} - -function scrAdd(id, nsfw, rel) { - var tr = document.createElement('tr'); - tr.scrId = id; - tr.scrStatus = id ? 2 : 1; // 0: done, 1: uploading, 2: waiting for thumbnail - tr.scrRel = rel; - tr.scrNSFW = nsfw; - - var td = document.createElement('td'); - td.className = 'thumb'; - td.innerHTML = 'loading...'; - tr.appendChild(td); - - td = document.createElement('td'); - if(id) - td.innerHTML = '<b>Generating thumbnail...</b><br />' - +'Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side.' - +'Please try again later or report a bug if that is the case.'; - else - td.innerHTML = '<b>Uploading screenshot...</b><br />' - +'This can take a while, depending on the file size and your upload speed.<br />' - +'<a href="#" onclick="return scrDel(this)">cancel</a>'; - tr.appendChild(td); - - x('scr_table').appendChild(tr); - scrStripe(); - return tr; -} - -function scrLast() { - if(x('scr_last')) - x('scr_table').removeChild(x('scr_last')); - var full = x('scr_table').getElementsByTagName('tr').length >= 10; - - var tr = document.createElement('tr'); - tr.setAttribute('id', 'scr_last'); - - var td = document.createElement('td'); - td.className = 'thumb'; - tr.appendChild(td); - - var td = document.createElement('td'); - if(full) - td.innerHTML = '<b>Enough screenshots</b><br />' - +'The limit of 10 screenshots per visual novel has been reached. ' - +'If you want to add a new screenshot, please remove an existing one first.'; - else - td.innerHTML = '<b>Add screenshot</b><br />' - +'Image must be smaller than 5MB and in PNG or JPEG format.<br />' - +'<input name="scr_upload" id="scr_upload" type="file" class="text" /><br />' - +'<input type="button" value="Upload!" class="submit" onclick="scrUpload()" />'; - - tr.appendChild(td); - x('scr_table').appendChild(tr); - scrStripe(); -} - -function scrStripe() { - var l = x('scr_table').getElementsByTagName('tr'); - for(var i=0;i<l.length;i++) - l[i].className = i%2==0 ? 'odd' : ''; -} - -function scrCheckStatus() { - var ids = ''; - var l = x('scr_table').getElementsByTagName('tr'); - for(var i=0;i<l.length-1;i++) - if(l[i].scrStatus == 2) - ids += (ids ? ';' : '?')+'id='+l[i].scrId; - if(!ids) - return setTimeout(scrCheckStatus, 1000); - - var ti = setTimeout(scrCheckStatus, 10000); - ajax('/xml/screenshots.xml'+ids, function(hr) { - var ls = hr.responseXML.getElementsByTagName('item'); - var l = x('scr_table').getElementsByTagName('tr'); - var tr; - for(var s=0;s<ls.length;s++) { - for(i=0;i<l.length-1;i++) - if(l[i].scrId == ls[s].getAttribute('id') && ls[s].getAttribute('processed') == "1") - tr = l[i]; - if(!tr) - continue; - - tr.scrStatus = 0; - tr.getElementsByTagName('td')[0].innerHTML = - '<a href="'+scrURL(tr.scrId, 'f')+'" rel="iv:'+ls[s].getAttribute('width')+'x'+ls[s].getAttribute('height')+':edit">' - +'<img src="'+scrURL(tr.scrId, 't')+'" style="margin: 0; padding: 0; border: 0" /></a>'; - - var opt=''; - for(var o=0;o<scrRel.length;o++) - opt += '<option value="'+scrRel[o][0]+'"'+(tr.scrRel && tr.scrRel == scrRel[o][0] ? ' selected="selected"' : '')+'>'+scrRel[o][1]+'</option>'; - - tr.getElementsByTagName('td')[1].innerHTML = '<b>Screenshot #'+tr.scrId+'</b>' - +' (<a href="#" onclick="return scrDel(this)">remove</a>)<br />' - +'Full size: '+ls[s].getAttribute('width')+'x'+ls[s].getAttribute('height')+'<br /><br />' - +'<input type="checkbox" onclick="scrSerialize()" id="scr_ser_'+tr.scrId+'" name="scr_ser_'+tr.scrId+'"' - +' '+(tr.scrNSFW > 0 ? 'checked = "checked"' : '')+' />' - +'<label for="scr_ser_'+tr.scrId+'">This screenshot is NSFW</label><br />' - +'<select onchange="scrSerialize()">'+opt+'</select>'; - } - scrSerialize(); - ivInit(); - clearTimeout(ti); - setTimeout(scrCheckStatus, 1000); - }); -} - -function scrDel(what) { - while(what.nodeName.toLowerCase() != 'tr') - what = what.parentNode; - what.scrStatus = 3; - x('scr_table').removeChild(what); - scrSerialize(); - scrLast(); - return false; -} - -var scrUplNr=0; -function scrUpload() { - scrUplNr++; - - // create temporary form - var d = document.createElement('div'); - d.style.cssText = 'visibility: hidden; overflow: hidden; width: 1px; height: 1px; position: absolute; left: -500px; top: -500px'; - d.innerHTML = '<iframe id="scr_upl_'+scrUplNr+'" name="scr_upl_'+scrUplNr+'" style="height: 0px; width: 0px; visibility: hidden"' - +' src="about:blank" onload="scrUploadComplete(this)"></iframe>' - +'<form method="post" action="/xml/screenshots.xml" target="scr_upl_'+scrUplNr+'" enctype="multipart/form-data" id="scr_frm_'+scrUplNr+'"></form>'; - document.body.appendChild(d); - - // submit form and delete it - d = x('scr_frm_'+scrUplNr); - d.appendChild(x('scr_upload')); - d.submit(); - d.parentNode.removeChild(d); - - d = scrAdd(0, 0, 0); - x('scr_upl_'+scrUplNr).theTR = d; - scrLast(); - - return false; -} - -function scrUploadComplete(what) { - var f = window.frames[what.id]; - if(f.location.href.indexOf('screenshots') < 0) - return; - - var tr = what.theTR; - if(!tr || tr.scrStatus == 3) - return; - - try { - tr.scrId = f.window.document.getElementsByTagName('image')[0].getAttribute('id'); - } catch(e) { - tr.scrId = -10; - } - if(tr.scrId < 0) { - alert( - tr.scrId == -10 ? - 'Oops! Seems like something went wrong...\n' - +'Make sure the file you\'re uploading doesn\'t exceed 5MB in size.\n' - +'If that isn\'t the problem, then please report a bug.' : - tr.scrId == -1 ? - 'Upload failed!\nOnly JPEG or PNG images are accepted.' : - 'Upload failed!\nNo file selected, or an empty file?' - ); - return scrDel(tr); - } - - tr.scrStatus = 2; - tr.getElementsByTagName('td')[1].innerHTML = - '<b>Generating thumbnail...</b><br />' - +'Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side.' - +'Please try again later or report a bug if that is the case.'; - - // remove the <div> in a timeout, otherwise some browsers think the page is still loading - setTimeout(function() { document.body.removeChild(what.parentNode) }, 100); -} - -function scrSerialize() { - var r = ''; - var l = x('scr_table').getElementsByTagName('tr'); - for(var i=0;i<l.length-1;i++) - if(l[i].scrStatus == 0) - r += (r ? ' ' : '') + l[i].scrId + ',' - + (l[i].getElementsByTagName('input')[0].checked ? 1 : 0) + ',' - + scrRel[l[i].getElementsByTagName('select')[0].selectedIndex][0]; - x('screenshots').value = r; -} - - - - /****************************************************\ * V I S U A L N O V E L S / P R O D U C E R S * \****************************************************/ @@ -508,8 +256,6 @@ function tglSerialize() { // load -if(x('jt_box_vn_scr')) - scrLoad(); if(x('jt_box_rel_vn')) vnpLoad('vn'); if(x('jt_box_rel_prod')) diff --git a/static/f/script.js b/static/f/script.js index 31225a6c..a6c5499c 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -81,7 +81,7 @@ function tag() { if(attr == 'style') el.setAttribute(attr, arguments[i][attr]); else - el[ attr == 'class' ? 'className' : attr ] = arguments[i][attr]; + el[ attr == 'class' ? 'className' : attr == 'for' ? 'htmlFor' : attr ] = arguments[i][attr]; } } else el.appendChild(tag(arguments[i])); @@ -96,9 +96,10 @@ function addBody(el) { else if(document.appendChild) document.appendChild(el); } -function setContent(el, content) { - setText(el, ''); - el.appendChild(content); +function setContent() { + setText(arguments[0], ''); + for(var i=1; i<arguments.length; i++) + arguments[0].appendChild(tag(arguments[i])); } function getText(obj) { return obj.textContent || obj.innerText || ''; @@ -182,7 +183,7 @@ function ivView(what) { var ol = byName('a'); var l=[]; for(i=0;i<ol.length;i++) - if(ol[i].rel.substr(0,3) == 'iv:' && ol[i].rel.indexOf(':'+opt[2]) > 4 && !hasClass(l[i], 'hidden') && ol[i].id != 'ivprev' && ol[i].id != 'ivnext') + if(ol[i].rel.substr(0,3) == 'iv:' && ol[i].rel.indexOf(':'+opt[2]) > 4 && !hasClass(ol[i], 'hidden') && ol[i].id != 'ivprev' && ol[i].id != 'ivnext') l[l.length] = ol[i]; for(i=0;i<l.length;i++) if(l[i].href == u) { @@ -876,6 +877,251 @@ if(byId('jt_box_rel_format')) +/* V I S U A L N O V E L S C R E E N S H O T U P L O A D E R (/v+/edit) */ + +var scrRel = [ [ 0, '-- select release --' ] ]; +var scrStaticURL; +var scrUplNr = 0; + +function scrLoad() { + // get scrRel and scrStaticURL + var rel = byId('scr_rel'); + scrStaticURL = rel.className; + for(var i=0; i<rel.options.length; i++) + scrRel[scrRel.length] = [ rel.options[i].value, getText(rel.options[i]) ]; + rel.parentNode.removeChild(rel); + + // load the current screenshots + var scr = byId('screenshots').value.split(' '); + for(i=0; i<scr.length && scr[i].length>1; i++) { + var r = scr[i].split(','); + scrAdd(r[0], r[1], r[2]); + } + + scrLast(); + scrCheckStatus(); + scrSetSubmit(); +} + +function scrSetSubmit() { + var frm = byId('screenshots'); + while(frm.nodeName.toLowerCase() != 'form') + frm = frm.parentNode; + oldfunc = frm.onsubmit; + frm.onsubmit = function() { + var loading = 0; + var norelease = 0; + var l = byName(byId('scr_table'), 'tr'); + for(var i=0; i<l.length-1; i++) { + if(l[i].scr_status > 0) + loading = 1; + else if(byName(l[i], 'select')[0].selectedIndex == 0) + norelease = 1; + } + if(loading) { + alert('Please wait for the screenshots to be uploaded before submitting the form.'); + return false; + } else if(norelease) { + alert('Please select the appropriate release for every screenshot'); + return false; + } else if(oldfunc) + return oldfunc(); + }; +} + +function scrURL(id, t) { + return scrStaticURL+'/s'+t+'/'+(id%100<10?'0':'')+(id%100)+'/'+id+'.jpg'; +} + +function scrAdd(id, nsfw, rel) { + // tr.scr_status = 0: done, 1: uploading, 2: waiting for thumbnail, 3: deleted + + var tr = tag('tr', { id:'scr_tr_'+id, scr_id: id, scr_status: id?2:1, scr_rel: rel, scr_nsfw: nsfw}, + tag('td', { class: 'thumb'}, 'loading...'), + tag('td', + tag('b', id ? 'Fetching thumbnail...' : 'Uploading screenshot'), + tag('br', null), + id ? null : 'This can take a while, depending on the file size and your upload speed.', + tag('br', null), + id ? null : tag('a', {href:'#', onclick:scrDel}, 'cancel') + ) + ); + byId('scr_table').appendChild(tr); + scrStripe(); + return tr; +} + +function scrLast() { + if(byId('scr_last')) + byId('scr_table').removeChild(byId('scr_last')); + var full = byName(byId('scr_table'), 'tr').length >= 10; + + byId('scr_table').appendChild(tag('tr', {id:'scr_last'}, + tag('td', {class: 'thumb'}), + full ? tag('td', + tag('b', 'Enough screenshots'), + tag('br', null), + 'The limit of 10 screenshots per visual novel has been reached. ', + 'If you want to add a new screenshot, please remove an existing one first.' + ) : tag('td', + tag('b', 'Add screenshot'), + tag('br', null), + 'Image must be smaller than 5MB and in PNG or JPEG format.', + tag('br', null), + tag('input', {name:'scr_upload', id:'scr_upload', type:'file', class:'text'}), + tag('br', null), + tag('input', {type:'button', value:'Upload!', class:'submit', onclick:scrUpload}) + ) + )); + scrStripe(); +} + +function scrStripe() { + var l = byName(byId('scr_table'), 'tr'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'odd', i%2==0); +} + +function scrCheckStatus() { + var ids = []; + var trs = byName(byId('scr_table'), 'tr'); + for(var i=0; i<trs.length-1; i++) + if(trs[i].scr_status == 2) + ids[ids.length] = 'id='+trs[i].scr_id; + if(!ids.length) + return setTimeout(scrCheckStatus, 1000); + + var ti = setTimeout(scrCheckStatus, 10000); + ajax('/xml/screenshots.xml?'+ids.join(';'), function(hr) { + var ls = hr.responseXML.getElementsByTagName('item'); + for(var i=0; i<ls.length; i++) { + var tr = byId('scr_tr_'+ls[i].getAttribute('id')); + if(!tr || ls[i].getAttribute('processed') != '1') + continue; + tr.scr_status = 0; // ready + + // image + var dim = ls[i].getAttribute('width')+'x'+ls[i].getAttribute('height'); + setContent(byName(tr, 'td')[0], + tag('a', {href: scrURL(tr.scr_id, 'f'), rel:'iv:'+dim+':edit'}, + tag('img', {src: scrURL(tr.scr_id, 't')}) + ) + ); + + // content + var rel = tag('select', {onchange: scrSerialize, class:'scr_relsel'}); + for(var j=0; j<scrRel.length; j++) + rel.appendChild(tag('option', {value: scrRel[j][0], selected: tr.scr_rel == scrRel[j][0]}, scrRel[j][1])); + var nsfwid = 'scr_sfw_'+tr.scr_id; + setContent(byName(tr, 'td')[1], + tag('b', 'Screenshot #'+tr.scr_id), + ' (', tag('a', {href: '#', onclick:scrDel}, 'remove'), ')', + tag('br', null), + 'Full size: '+dim, + tag('br', null), + tag('br', null), + tag('input', {type:'checkbox', onclick:scrSerialize, id:nsfwid, name:nsfwid, checked: tr.scr_nsfw>0, class:'scr_nsfw'}), + tag('label', {for:nsfwid}, 'This screenshot is NSFW'), + tag('br', null), + rel + ); + } + scrSerialize(); + ivInit(); + clearTimeout(ti); + setTimeout(scrCheckStatus, 1000); + }); +} + +function scrDel(what) { + var tr = what && what.scr_status != null ? what : this; + while(tr.nodeName.toLowerCase() != 'tr') + tr = tr.parentNode; + tr.scr_status = 3; + byId('scr_table').removeChild(tr); + scrSerialize(); + scrLast(); + return false; +} + +function scrUpload() { + scrUplNr++; + + // create temporary form + var ifid = 'scr_upl_'+scrUplNr; + var frm = tag('form', {method: 'post', action:'/xml/screenshots.xml', target: ifid, enctype:'multipart/form-data'}); + var ifr = tag('iframe', {id:ifid, name:ifid, src:'about:blank', onload:scrUploadComplete}); + addBody(tag('div', {class:'scr_uploader'}, ifr, frm)); + + // submit form and delete it + frm.appendChild(byId('scr_upload')); + frm.submit(); + frm.parentNode.removeChild(frm); + ifr.scr_tr = scrAdd(0, 0, 0); + scrLast(); + return false; +} + +function scrUploadComplete() { + var ifr = this; + var fr = window.frames[ifr.id]; + if(fr.location.href.indexOf('screenshots') < 0) + return; + + var tr = ifr.scr_tr; + if(!tr || tr.scr_status == 3) + return; + + try { + tr.scr_id = fr.window.document.getElementsByTagName('image')[0].getAttribute('id'); + } catch(e) { + tr.scr_id = -10; + } + if(tr.scr_id < 0) { + alert( + tr.scr_id == -10 ? + 'Oops! Seems like something went wrong...\n' + +'Make sure the file you\'re uploading doesn\'t exceed 5MB in size.\n' + +'If that isn\'t the problem, then please report a bug.' : + tr.scr_id == -1 ? + 'Upload failed!\nOnly JPEG or PNG images are accepted.' : + 'Upload failed!\nNo file selected, or an empty file?' + ); + return scrDel(tr); + } + + tr.id = 'scr_tr_'+tr.scr_id; + tr.scr_status = 2; + setContent(byName(tr, 'td')[1], + tag('b', 'Generating thumbnail...'), + tag('br', null), + 'Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. ', + 'Please try again later or report a bug if that is the case.' + ); + + // remove the <div> in a timeout, otherwise some browsers think the page is still loading + setTimeout(function() { ifr.parentNode.parentNode.removeChild(ifr.parentNode) }, 100); +} + +function scrSerialize() { + var r = []; + var l = byName(byId('scr_table'), 'tr'); + for(var i=0; i<l.length-1; i++) + if(l[i].scr_status == 0) + r[r.length] = [ + l[i].scr_id, + byClass(l[i], 'input', 'scr_nsfw')[0].checked ? 1 : 0, + scrRel[byClass(l[i], 'select', 'scr_relsel')[0].selectedIndex][0] + ].join(','); + byId('screenshots').value = r.join(' '); +} + +if(x('jt_box_vn_scr')) + scrLoad(); + + + + /* M I S C S T U F F */ // search box -- cgit v1.2.3 From ad638b58f65285285adda787b79b9422ca43313b Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Mon, 5 Oct 2009 13:03:43 +0200 Subject: JS: Moved, rewrote and improved VN tag linking - You can now click the spoiler column to scroll through the options - Or mouse-over the spoiler column to see a JS dropdown with the options (no more select box, which introduces several more clicks to do the same) --- data/style.css | 21 ++--- lib/VNDB/Handler/Tags.pm | 33 ++++---- static/f/forms.js | 143 ------------------------------- static/f/script.js | 214 ++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 219 insertions(+), 192 deletions(-) diff --git a/data/style.css b/data/style.css index d09c7060..139551c9 100644 --- a/data/style.css +++ b/data/style.css @@ -974,15 +974,15 @@ div.browse.uposts td.tc1 { /***** VN tagmod *****/ #jt_box_tagmod .formtable table td { padding: 1px 5px } -#tagtable tfoot td { padding-top: 20px!important; } -#tagtable .tc2_1 { border-right: 1px solid $border$; border-left: 1px solid $border$; width: 150px; text-align: center } -#tagtable .tc3_1 { border-left: 1px solid $border$; width: 150px; text-align: center } -#tagtable .tc1 { min-width: 200px; border-right: 1px solid $border$ } -#tagtable .tc2 { padding-left: 30px!important } -#tagtable .tc3 { border-right: 1px solid $border$; padding-right: 30px!important; text-align: right; padding-left: 10px!important } -#tagtable .tc4 { padding-left: 30px!important; } -#tagtable .tc4 i { font-style: normal; font-size: 8px } -#tagtable .tc5 { text-align: right; padding-right: 30px!important; } +table.tgl tfoot td { padding-top: 20px!important; } +table.tgl .tc_you { border-right: 1px solid $border$; border-left: 1px solid $border$; width: 150px; text-align: center } +table.tgl .tc_others { border-left: 1px solid $border$; width: 150px; text-align: center } +table.tgl .tc_tagname { min-width: 200px; border-right: 1px solid $border$ } +table.tgl .tc_myvote { padding-left: 30px!important } +table.tgl .tc_myspoil { border-right: 1px solid $border$; padding-right: 30px!important; text-align: right; padding-left: 10px!important; cursor: pointer } +table.tgl .tc_allvote { padding-left: 30px!important; } +table.tgl .tc_allvote i { font-style: normal; font-size: 8px } +table.tgl .tc_allspoil { text-align: right; padding-right: 30px!important; } .taglvl { display: block; float: left; width: 8px; height: 12px; border: 1px solid $border$; font-size: 1px; color: $maintext$!important } .taglvl0 { width: 15px; border: none!important; font-size: 10px; text-align: center; } div.taglvl0 { font-size: 8px; width: 20px!important } @@ -994,9 +994,6 @@ a.taglvl:hover { border-bottom: 1px solid transparent!important } .taglvlsel.taglvl1 { background-color: #cf0; border-color: #cf0 } .taglvlsel.taglvl2 { background-color: #8f0; border-color: #8f0 } .taglvlsel.taglvl3 { background-color: #0f0; border-color: #0f0 } -#jt_box_tagmod #tagtable .tc3 { padding: 0 } -#tagtable .tc3 select { width: 90px; height: 15px; border: 0; margin: 0; font-size: 11px; background-color: $_blendbg$; text-align: right } -#tagtable .odd .tc3 select { background-color: $secbg$ } diff --git a/lib/VNDB/Handler/Tags.pm b/lib/VNDB/Handler/Tags.pm index 8484ad96..0f8b780a 100644 --- a/lib/VNDB/Handler/Tags.pm +++ b/lib/VNDB/Handler/Tags.pm @@ -438,43 +438,44 @@ sub vntagmod { $self->htmlForm({ frm => $frm, action => "/v$vid/tagmod", nosubmit => 1 }, tagmod => [ mt('_tagv_frm_title'), [ hidden => short => 'taglinks', value => '' ], [ static => nolabel => 1, content => sub { - table id => 'tagtable'; + table class => 'tgl'; thead; Tr; td ''; - td colspan => 2, class => 'tc2_1', mt '_tagv_col_you'; - td colspan => 2, class => 'tc3_1', mt '_tagv_col_others'; + td colspan => 2, class => 'tc_you', mt '_tagv_col_you'; + td colspan => 2, class => 'tc_others', mt '_tagv_col_others'; end; Tr; - my $i=0; - td class => 'tc'.++$i, mt '_tagv_col_'.$_ for(qw|tag rating spoiler rating spoiler|); + td class => 'tc_tagname', mt '_tagv_col_tag'; + td class => 'tc_myvote', mt '_tagv_col_rating'; + td class => 'tc_myspoil', mt '_tagv_col_spoiler'; + td class => 'tc_allvote', mt '_tagv_col_rating'; + td class => 'tc_allspoil', mt '_tagv_col_spoiler'; end; end; tfoot; Tr; td colspan => 5; input type => 'submit', class => 'submit', value => mt('_tagv_save'), style => 'float: right'; - input type => 'text', class => 'text', name => 'addtag', value => ''; - input type => 'button', class => 'submit', value => mt '_tagv_add'; + input id => 'tagmod_tag', type => 'text', class => 'text', value => ''; + input id => 'tagmod_add', type => 'button', class => 'submit', value => mt '_tagv_add'; br; p; lit mt '_tagv_addmsg'; end; end; end; end; - tbody; + tbody id => 'tagtable'; for my $t (sort { $a->{name} cmp $b->{name} } @$tags) { my $m = (grep $_->{tag} == $t->{id}, @$my)[0] || {}; - Tr; - td class => 'tc1'; - a href => "/g$t->{id}", $t->{name}; - end; - td class => 'tc2', $m->{vote}||0; - td class => 'tc3', defined $m->{spoiler} ? $m->{spoiler} : -1; - td class => 'tc4'; + Tr id => "tgl_$t->{id}"; + td class => 'tc_tagname'; a href => "/g$t->{id}", $t->{name}; end; + td class => 'tc_myvote', $m->{vote}||0; + td class => 'tc_myspoil', defined $m->{spoiler} ? $m->{spoiler} : -1; + td class => 'tc_allvote'; tagscore !$m->{vote} ? $t->{rating} : $t->{cnt} == 1 ? 0 : ($t->{rating}*$t->{cnt} - $m->{vote}) / ($t->{cnt}-1); i ' ('.($t->{cnt} - ($m->{vote} ? 1 : 0)).')'; end; - td class => 'tc5', sprintf '%.2f', $t->{spoiler}; + td class => 'tc_allspoil', sprintf '%.2f', $t->{spoiler}; end; } end; diff --git a/static/f/forms.js b/static/f/forms.js index d490b0d8..99b8bd13 100644 --- a/static/f/forms.js +++ b/static/f/forms.js @@ -114,153 +114,10 @@ function vnpSerialize(type) { - - - - /****************************************************\ - * V I S U A L N O V E L T A G L I N K I N G * - \****************************************************/ - - -function tglLoad() { - var n = x('tagtable').getElementsByTagName('tfoot')[0].getElementsByTagName('input'); - dsInit(n[1], '/xml/tags.xml?q=', function(item, tr) { - var td = document.createElement('td'); - td.innerHTML = shorten(item.firstChild.nodeValue, 40); - if(item.getAttribute('meta') == 'yes') - td.innerHTML += ' <b class="grayedout">meta</b>'; - else if(item.getAttribute('state') == 0) - td.innerHTML += ' <b class="grayedout">awaiting moderation</b>'; - tr.appendChild(td); - }, function(item) { - return item.firstChild.nodeValue; - }, tglAdd); - n[2].onclick = tglAdd; - - tglStripe(); - var l = x('tagtable').getElementsByTagName('tbody')[0].getElementsByTagName('tr'); - for(var i=0; i<l.length;i++) { - var o = l[i].getElementsByTagName('td'); - tglSpoiler(o[2], parseInt(o[2].innerHTML)); - tglVoteBar(o[1], parseInt(o[1].innerHTML)); - } -} - -function tglSpoiler(obj, spoil) { - var r = '<select onchange="tglSerialize()">'; - for(var i=-1; i<=2; i++) - r += '<option value="'+i+'"'+(spoil==i?' selected="selected"':'')+'>' - +(i == -1 ? 'neutral' : i == 0 ? 'no spoiler' : i == 1 ? 'minor spoiler' : 'major spoiler') - +' </option>'; - obj.innerHTML = r+'</select>'; -} - -function tglVoteBar(obj, vote) { - var r = ''; - for(var i=-3;i<=3;i++) - r += '<a href="#" class="taglvl taglvl'+i+'" onmouseover="tglVoteBarSel(this, '+i+')"' - + ' onmouseout="tglVoteBarSel(this, '+vote+')" onclick="return tglVoteBar(this.parentNode, '+i+')"> </a>'; - obj.innerHTML = r; - tglVoteBarSel(obj, vote); - tglSerialize(); - return false; -} - -function tglVoteBarSel(obj, vote) { - if(obj.className.indexOf('taglvl') >= 0) - obj = obj.parentNode; - var l = obj.getElementsByTagName('a'); - var num; - for(var i=0; i<l.length; i++) { - if((num = l[i].className.replace(/^.*taglvl(-?[0-3]).*$/, "$1")) == l[i].className) - continue; - if(num == 0) - l[i].innerHTML = vote == 0 ? '-' : vote; - else if(num<0&&vote<=num || num>0&&vote>=num) { - if(l[i].className.indexOf('taglvlsel') < 0) - l[i].className += ' taglvlsel'; - } else - if(l[i].className.indexOf('taglvlsel') >= 0) - l[i].className = l[i].className.replace(/taglvlsel/, ''); - } -} - -function tglAdd() { - var n = x('tagtable').getElementsByTagName('tfoot')[0].getElementsByTagName('input'); - n[1].disabled = n[2].disabled = true; - n[2].value = 'loading...'; - ajax('/xml/tags.xml?q=name:'+encodeURIComponent(n[1].value), function(hr) { - n[1].disabled = n[1].disabled = false; - n[2].value = 'Add tag'; - n[1].value = ''; - - var items = hr.responseXML.getElementsByTagName('item'); - if(items.length < 1) - return alert('Item not found!'); - if(items[0].getAttribute('meta') == 'yes') - return alert('Can\'t use meta tags here!'); - var name = items[0].firstChild.nodeValue; - var l = x('tagtable').getElementsByTagName('a'); - for(var i=0; i<l.length; i++) - if(l[i].innerHTML == qq(name)) - return alert('Tag is already present!'); - - var tr = document.createElement('tr'); - var td = document.createElement('td'); - td.innerHTML = '<a href="/g'+items[0].getAttribute('id')+'">'+qq(name)+'</a>'; - td.className = 'tc1'; - tr.appendChild(td); - td = document.createElement('td'); - tglVoteBar(td, 2); - td.className = 'tc2'; - tr.appendChild(td); - td = document.createElement('td'); - tglSpoiler(td, -1); - td.className = 'tc3'; - tr.appendChild(td); - td = document.createElement('td'); - td.className = 'tc4'; - td.innerHTML = '-'; - tr.appendChild(td); - td = document.createElement('td'); - td.innerHTML = '-'; - td.className = 'tc5'; - tr.appendChild(td); - x('tagtable').getElementsByTagName('tbody')[0].appendChild(tr); - tglStripe(); - tglSerialize(); - }); -} - -function tglStripe() { - var l = x('tagtable').getElementsByTagName('tbody')[0].getElementsByTagName('tr'); - for(var i=0;i<l.length;i++) - l[i].className = i%2 ? 'odd' : ''; -} - -function tglSerialize() { - var r = ''; - var l = x('tagtable').getElementsByTagName('tbody')[0].getElementsByTagName('tr'); - for(var i=0; i<l.length;i++) { - var lnk = l[i].getElementsByTagName('a')[0].href; - var vt = l[i].getElementsByTagName('td')[1].getElementsByTagName('a'); - var id; - if((id = lnk.replace(/^.*g([1-9][0-9]*)$/, "$1")) != lnk && vt.length > 3 && vt[3].innerHTML != '-') - r += (r?' ':'')+id+','+vt[3].innerHTML+','+(l[i].getElementsByTagName('select')[0].selectedIndex-1); - } - x('taglinks').value = r; -} - - - - // load if(x('jt_box_rel_vn')) vnpLoad('vn'); if(x('jt_box_rel_prod')) vnpLoad('producers'); -if(x('taglinks')) - tglLoad(); - diff --git a/static/f/script.js b/static/f/script.js index a6c5499c..de0b612d 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -251,9 +251,10 @@ ivInit(); /* D R O P D O W N */ function ddInit(obj, align, contents) { - obj.dd_align = align; // only 'left' and 'bottom' supported at the moment + obj.dd_align = align; // see ddRefresh for details obj.dd_contents = contents; document.onmousemove = ddMouseMove; + document.onscroll = ddHide; if(!byId('dd_box')) addBody(tag('div', {id:'dd_box', dd_used: false})); } @@ -263,6 +264,7 @@ function ddHide() { setText(box, ''); box.style.left = '-500px'; box.dd_used = false; + box.dd_lnk = null; } function ddMouseMove(e) { @@ -278,34 +280,44 @@ function ddMouseMove(e) { var mouseX = e.pageX || (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft); var mouseY = e.pageY || (e.clientY + document.body.scrollTop + document.documentElement.scrollTop); if((mouseX < ddx-10 || mouseX > ddx+box.offsetWidth+10 || mouseY < ddy-10 || mouseY > ddy+box.offsetHeight+10) - || (lnk && lnk.id == box.dd_id)) + || (lnk && lnk == box.dd_lnk)) ddHide(); } if(!box.dd_used && lnk) { - var content = lnk.dd_contents(lnk, box); - if(content == null) - return; - setContent(box, content); - box.dd_id = lnk.id; + box.dd_lnk = lnk; box.dd_used = true; - - var o = lnk; - ddx = ddy = 0; - do { - ddx += o.offsetLeft; - ddy += o.offsetTop; - } while(o = o.offsetParent); - - if(lnk.dd_align == 'left') - ddx -= box.offsetWidth; - if(lnk.dd_align == 'bottom') - ddy += lnk.offsetHeight; - box.style.left = ddx+'px'; - box.style.top = ddy+'px'; + if(!ddRefresh()) + ddHide(); } } +function ddRefresh() { + var box = byId('dd_box'); + if(!box.dd_used) + return false; + var lnk = box.dd_lnk; + var content = lnk.dd_contents(lnk, box); + if(content == null) + return false; + setContent(box, content); + + var o = lnk; + ddx = ddy = 0; + do { + ddx += o.offsetLeft; + ddy += o.offsetTop; + } while(o = o.offsetParent); + + if(lnk.dd_align == 'left') + ddx -= box.offsetWidth; + if(lnk.dd_align == 'tagmod') + ddx += lnk.offsetWidth-35; + box.style.left = ddx+'px'; + box.style.top = ddy+'px'; + return true; +} + // release list dropdown on VN pages @@ -1122,6 +1134,166 @@ if(x('jt_box_vn_scr')) +/* V I S U A L N O V E L T A G L I N K I N G (/v+/tagmod) */ + +var tglSpoilers = [ 'neutral', 'no spoiler', 'minor spoiler', 'major spoiler' ]; + +function tglLoad() { + // tag dropdown search + dsInit(byId('tagmod_tag'), '/xml/tags.xml?q=', function(item, tr) { + tr.appendChild(tag('td', + shorten(item.firstChild.nodeValue, 40), + item.getAttribute('meta') == 'yes' ? tag('b', {class:'grayedout'}, ' meta') : + item.getAttribute('state') == 0 ? tag('b', {class:'grayedout'}, ' awaiting moderation') : null + )); + }, function(item) { + return item.firstChild.nodeValue; + }, tglAdd); + byId('tagmod_add').onclick = tglAdd; + + // JS'ify the voting bar and spoiler setting + tglStripe(); + var trs = byName(byId('tagtable'), 'tr'); + for(var i=0; i<trs.length; i++) { + var vote = byClass(trs[i], 'td', 'tc_myvote')[0]; + vote.tgl_vote = getText(vote)*1; + tglVoteBar(vote); + + var spoil = byClass(trs[i], 'td', 'tc_myspoil')[0]; + spoil.tgl_spoil = getText(spoil)*1+1; + setText(spoil, tglSpoilers[spoil.tgl_spoil]); + ddInit(spoil, 'tagmod', tglSpoilDD); + spoil.onclick = tglSpoilNext; + } + tglSerialize(); +} + +function tglSpoilNext() { + if(++this.tgl_spoil >= tglSpoilers.length) + this.tgl_spoil = 0; + setText(this, tglSpoilers[this.tgl_spoil]); + tglSerialize(); + ddRefresh(); +} + +function tglSpoilDD(lnk) { + var lst = tag('ul', null); + for(var i=0; i<tglSpoilers.length; i++) + lst.appendChild(tag('li', i == lnk.tgl_spoil + ? tag('i', tglSpoilers[i]) + : tag('a', {href: '#', onclick:tglSpoilSet, tgl_td:lnk, tgl_sp:i}, tglSpoilers[i]) + )); + return lst; +} + +function tglSpoilSet() { + this.tgl_td.tgl_spoil = this.tgl_sp; + setText(this.tgl_td, tglSpoilers[this.tgl_sp]); + ddHide(); + tglSerialize(); + return false; +} + +function tglVoteBar(td, vote) { + setText(td, ''); + for(var i=-3; i<=3; i++) + td.appendChild(tag('a', { + class:'taglvl taglvl'+i, tgl_num: i, + onmouseover:tglVoteBarSel, onmouseout:tglVoteBarSel, onclick:tglVoteBarSel + }, ' ')); + tglVoteBarSel(td, td.tgl_vote); + return false; +} + +function tglVoteBarSel(td, vote) { + // nasty trick to make this function multifunctional + if(this && this.tgl_num != null) { + var e = td || window.event; + td = this.parentNode; + vote = this.tgl_num; + if(e.type.toLowerCase() == 'click') { + td.tgl_vote = vote; + tglSerialize(); + } + if(e.type.toLowerCase() == 'mouseout') + vote = td.tgl_vote; + } + var l = byName(td, 'a'); + var num; + for(var i=0; i<l.length; i++) { + num = l[i].tgl_num; + if(num == 0) + setText(l[i], vote || '-'); + else + setClass(l[i], 'taglvlsel', num<0&&vote<=num || num>0&&vote>=num); + } +} + +function tglAdd() { + var tg = byId('tagmod_tag'); + var add = byId('tagmod_add'); + tag.disabled = add.disabled = true; + add.value = 'loading...'; + + ajax('/xml/tags.xml?q=name:'+encodeURIComponent(tg.value), function(hr) { + tg.disabled = add.disabled = false; + tg.value = ''; + add.value = 'Add tag'; + + var items = hr.responseXML.getElementsByTagName('item'); + if(items.length < 1) + return alert('Item not found!'); + if(items[0].getAttribute('meta') == 'yes') + return alert('Can\'t use meta tags here!'); + + var name = items[0].firstChild.nodeValue; + var id = items[0].getAttribute('id'); + if(byId('tgl_'+id)) + return alert('Tag is already present!'); + + var vote = tag('td', {class:'tc_myvote', tgl_vote: 2}, ''); + tglVoteBar(vote); + var spoil = tag('td', {class:'tc_myspoil', tgl_spoil: 0}, tglSpoilers[0]); + ddInit(spoil, 'tagmod', tglSpoilDD); + + byId('tagtable').appendChild(tag('tr', {id:'tgl_'+id}, + tag('td', {class:'tc_tagname'}, tag('a', {href:'/g'+id}, name)), + vote, spoil, + tag('td', {class:'tc_allvote'}, '-'), + tag('td', {class:'tc_allspoil'}, '-') + )); + tglStripe(); + tglSerialize(); + }); +} + +function tglStripe() { + var l = byName(byId('tagtable'), 'tr'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'odd', i%2); +} + +function tglSerialize() { + var r = []; + var l = byName(byId('tagtable'), 'tr'); + for(var i=0; i<l.length; i++) { + var vote = byClass(l[i], 'td', 'tc_myvote')[0].tgl_vote; + if(vote != 0) + r[r.length] = [ + l[i].id.substr(4), + vote, + byClass(l[i], 'td', 'tc_myspoil')[0].tgl_spoil-1 + ].join(','); + } + byId('taglinks').value = r.join(' '); +} + +if(byId('taglinks')) + tglLoad(); + + + + /* M I S C S T U F F */ // search box -- cgit v1.2.3 From 877dd97e90c8eb16e65032a6f2c9c295fad7b9c2 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Mon, 5 Oct 2009 13:25:00 +0200 Subject: JS: Fixed syntax errors on Midori and some other minor problems I use Midori as a representative for all webkit-based browsers, not sure how reliable that is, but it definitely can't do harm to fix javascript problems in Midori. :-) --- static/f/script.js | 58 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/static/f/script.js b/static/f/script.js index de0b612d..7384427f 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -344,15 +344,15 @@ function rlDropDown(lnk) { vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+i, onclick:rlMod}, vstat[i]))); } - return tag('div', {class:'vrdd'}, rs, vs, st[0] == '--' ? null : - tag('ul', {class:'full'}, tag('li', tag('a', {href:'#', rl_rid: relid, rl_act:'del', onclick:rlMod}, 'Remove from VN List'))) + return tag('div', {'class':'vrdd'}, rs, vs, st[0] == '--' ? null : + tag('ul', {'class':'full'}, tag('li', tag('a', {href:'#', rl_rid: relid, rl_act:'del', onclick:rlMod}, 'Remove from VN List'))) ); } function rlMod() { var lnk = byId('rlsel_'+this.rl_rid); ddHide(); - setContent(lnk, tag('b', {class: 'patch'}, 'loading...')); + setContent(lnk, tag('b', {'class': 'patch'}, 'loading...')); ajax('/xml/rlist.xml?id='+this.rl_rid+';e='+this.rl_act, function(hr) { // TODO: get rid of innerHTML here... lnk.innerHTML = hr.responseXML.getElementsByTagName('rlist')[0].firstChild.nodeValue; @@ -509,7 +509,6 @@ function dateSerialize() { sel[2].options[sel[2].selectedIndex].value*1 ]; div.date_obj.value = val[0] == 0 ? 0 : val[0] == 9999 ? 99999999 : val[0]*10000+val[1]*100+(val[1]==99?99:val[2]); - alert(div.date_obj.value); } { @@ -725,10 +724,10 @@ function vnrAdd(rel, vid, title) { sel.appendChild(tag('option', {value: ops[i].value, selected: ops[i].value==rel}, getText(ops[i]))); byId('relation_tbl').appendChild(tag('tr', {id:'relation_tr_'+vid}, - tag('td', {class:'tc_vn' }, 'v'+vid+':', tag('a', {href:'/v'+vid}, shorten(title, 40))), - tag('td', {class:'tc_rel' }, 'is a ', sel, ' of'), - tag('td', {class:'tc_title'}, shorten(byId('title').value, 40)), - tag('td', {class:'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, 'del')) + tag('td', {'class':'tc_vn' }, 'v'+vid+':', tag('a', {href:'/v'+vid}, shorten(title, 40))), + tag('td', {'class':'tc_rel' }, 'is a ', sel, ' of'), + tag('td', {'class':'tc_title'}, shorten(byId('title').value, 40)), + tag('td', {'class':'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, 'del')) )); vnrEmpty(); @@ -827,18 +826,18 @@ function medLoad() { } function medAdd(med, qty) { - var qsel = tag('select', {class:'qty', onchange:medSerialize}, tag('option', {value:0}, '- quantity -')); + var qsel = tag('select', {'class':'qty', onchange:medSerialize}, tag('option', {value:0}, '- quantity -')); for(var i=1; i<=20; i++) qsel.appendChild(tag('option', {value:i, selected: qty==i}, i)); - var msel = tag('select', {class:'medium', onchange: med == '' ? medFormAdd : medSerialize}); + var msel = tag('select', {'class':'medium', onchange: med == '' ? medFormAdd : medSerialize}); if(med == '') msel.appendChild(tag('option', {value:''}, '- medium -')); for(var i=0; i<medTypes.length; i++) msel.appendChild(tag('option', {value:medTypes[i][0], selected: med==medTypes[i][0]}, medTypes[i][1])); byId('media_div').appendChild(tag('span', qsel, msel, - med != '' ? tag('input', {type: 'button', class:'submit', onclick:medDel, value:'remove'}) : null + med != '' ? tag('input', {type: 'button', 'class':'submit', onclick:medDel, value:'remove'}) : null )); } @@ -949,7 +948,7 @@ function scrAdd(id, nsfw, rel) { // tr.scr_status = 0: done, 1: uploading, 2: waiting for thumbnail, 3: deleted var tr = tag('tr', { id:'scr_tr_'+id, scr_id: id, scr_status: id?2:1, scr_rel: rel, scr_nsfw: nsfw}, - tag('td', { class: 'thumb'}, 'loading...'), + tag('td', { 'class': 'thumb'}, 'loading...'), tag('td', tag('b', id ? 'Fetching thumbnail...' : 'Uploading screenshot'), tag('br', null), @@ -969,7 +968,7 @@ function scrLast() { var full = byName(byId('scr_table'), 'tr').length >= 10; byId('scr_table').appendChild(tag('tr', {id:'scr_last'}, - tag('td', {class: 'thumb'}), + tag('td', {'class': 'thumb'}), full ? tag('td', tag('b', 'Enough screenshots'), tag('br', null), @@ -980,9 +979,9 @@ function scrLast() { tag('br', null), 'Image must be smaller than 5MB and in PNG or JPEG format.', tag('br', null), - tag('input', {name:'scr_upload', id:'scr_upload', type:'file', class:'text'}), + tag('input', {name:'scr_upload', id:'scr_upload', type:'file', 'class':'text'}), tag('br', null), - tag('input', {type:'button', value:'Upload!', class:'submit', onclick:scrUpload}) + tag('input', {type:'button', value:'Upload!', 'class':'submit', onclick:scrUpload}) ) )); scrStripe(); @@ -1021,7 +1020,7 @@ function scrCheckStatus() { ); // content - var rel = tag('select', {onchange: scrSerialize, class:'scr_relsel'}); + var rel = tag('select', {onchange: scrSerialize, 'class':'scr_relsel'}); for(var j=0; j<scrRel.length; j++) rel.appendChild(tag('option', {value: scrRel[j][0], selected: tr.scr_rel == scrRel[j][0]}, scrRel[j][1])); var nsfwid = 'scr_sfw_'+tr.scr_id; @@ -1032,8 +1031,8 @@ function scrCheckStatus() { 'Full size: '+dim, tag('br', null), tag('br', null), - tag('input', {type:'checkbox', onclick:scrSerialize, id:nsfwid, name:nsfwid, checked: tr.scr_nsfw>0, class:'scr_nsfw'}), - tag('label', {for:nsfwid}, 'This screenshot is NSFW'), + tag('input', {type:'checkbox', onclick:scrSerialize, id:nsfwid, name:nsfwid, checked: tr.scr_nsfw>0, 'class':'scr_nsfw'}), + tag('label', {'for':nsfwid}, 'This screenshot is NSFW'), tag('br', null), rel ); @@ -1063,7 +1062,7 @@ function scrUpload() { var ifid = 'scr_upl_'+scrUplNr; var frm = tag('form', {method: 'post', action:'/xml/screenshots.xml', target: ifid, enctype:'multipart/form-data'}); var ifr = tag('iframe', {id:ifid, name:ifid, src:'about:blank', onload:scrUploadComplete}); - addBody(tag('div', {class:'scr_uploader'}, ifr, frm)); + addBody(tag('div', {'class':'scr_uploader'}, ifr, frm)); // submit form and delete it frm.appendChild(byId('scr_upload')); @@ -1143,8 +1142,8 @@ function tglLoad() { dsInit(byId('tagmod_tag'), '/xml/tags.xml?q=', function(item, tr) { tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40), - item.getAttribute('meta') == 'yes' ? tag('b', {class:'grayedout'}, ' meta') : - item.getAttribute('state') == 0 ? tag('b', {class:'grayedout'}, ' awaiting moderation') : null + item.getAttribute('meta') == 'yes' ? tag('b', {'class':'grayedout'}, ' meta') : + item.getAttribute('state') == 0 ? tag('b', {'class':'grayedout'}, ' awaiting moderation') : null )); }, function(item) { return item.firstChild.nodeValue; @@ -1198,7 +1197,7 @@ function tglVoteBar(td, vote) { setText(td, ''); for(var i=-3; i<=3; i++) td.appendChild(tag('a', { - class:'taglvl taglvl'+i, tgl_num: i, + 'class':'taglvl taglvl'+i, tgl_num: i, onmouseover:tglVoteBarSel, onmouseout:tglVoteBarSel, onclick:tglVoteBarSel }, ' ')); tglVoteBarSel(td, td.tgl_vote); @@ -1251,16 +1250,17 @@ function tglAdd() { if(byId('tgl_'+id)) return alert('Tag is already present!'); - var vote = tag('td', {class:'tc_myvote', tgl_vote: 2}, ''); + var vote = tag('td', {'class':'tc_myvote', tgl_vote: 2}, ''); tglVoteBar(vote); - var spoil = tag('td', {class:'tc_myspoil', tgl_spoil: 0}, tglSpoilers[0]); + var spoil = tag('td', {'class':'tc_myspoil', tgl_spoil: 0}, tglSpoilers[0]); ddInit(spoil, 'tagmod', tglSpoilDD); + spoil.onclick = tglSpoilNext; byId('tagtable').appendChild(tag('tr', {id:'tgl_'+id}, - tag('td', {class:'tc_tagname'}, tag('a', {href:'/g'+id}, name)), + tag('td', {'class':'tc_tagname'}, tag('a', {href:'/g'+id}, name)), vote, spoil, - tag('td', {class:'tc_allvote'}, '-'), - tag('td', {class:'tc_allspoil'}, '-') + tag('td', {'class':'tc_allvote'}, '-'), + tag('td', {'class':'tc_allspoil'}, '-') )); tglStripe(); tglSerialize(); @@ -1510,8 +1510,8 @@ if(byId('expandall')) { if(byId('advselect') && byId('ti')) { var trfunc = function(item, tr) { tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40), - item.getAttribute('meta') == 'yes' ? tag('b', {class: 'grayedout'}, ' meta') : null, - item.getAttribute('state') == 0 ? tag('b', {class: 'grayedout'}, ' awaiting moderation') : null + item.getAttribute('meta') == 'yes' ? tag('b', {'class': 'grayedout'}, ' meta') : null, + item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' awaiting moderation') : null )); }; var serfunc = function(item, obj) { -- cgit v1.2.3 From fd24d5f1f95eb4285ddb938101275f66d1fdb544 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Mon, 5 Oct 2009 13:32:59 +0200 Subject: JS: Documented function/attribute prefixes Because I am bound to forget all those and add duplicates. --- static/f/script.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/static/f/script.js b/static/f/script.js index 7384427f..69f54fc9 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -1,3 +1,16 @@ +/* function/attribute prefixes: + * date -> Date selector + * dd -> dropdown + * ds -> dropdown search + * iv -> image viewer + * jt -> Javascript Tabs + * med -> Release media selector + * rl -> Release List dropdown + * scr -> VN screenshot uploader + * tgl -> VN tag linking + * tvs -> VN page tag spoilers + * vnr -> VN relation editor + */ var expanded_icon = '▾'; var collapsed_icon = '▸'; -- cgit v1.2.3 From 519b13787e33f1b8edb3d0f3b018339410b48371 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Mon, 5 Oct 2009 20:50:04 +0200 Subject: JS: Moved, split and rewrote release <-> VN & producer linking + removed last traces of forms.js + converted code to use tables, as that is easier to expand more accurate for this purpose. The reason I probably didn't use tables before was that the innerHTML property doesn't work on tr elements. The split was mainly because the producer linking is going to be expanded with an additional field later on. --- ChangeLog | 5 ++ data/style.css | 12 ++- lib/VNDB/Handler/Releases.pm | 16 ++-- lib/VNDB/Handler/Tags.pm | 2 +- lib/VNDB/Handler/VNBrowse.pm | 2 +- lib/VNDB/Handler/VNEdit.pm | 2 +- lib/VNDB/Util/LayoutHTML.pm | 4 +- static/f/forms.js | 123 ------------------------- static/f/script.js | 208 +++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 229 insertions(+), 145 deletions(-) delete mode 100644 static/f/forms.js diff --git a/ChangeLog b/ChangeLog index 5966c38d..9e12388f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,11 @@ git - ? - vn_relations.relation - anime.type - New language: Hungarian + - Complete rewrite of the Javascript code: + - Intended to be less error prone, more maintainable, and easier to make + 'XHTML compliant' in the future (currently still has some issues here). + - Improved spoiler selection on /v+/tagmod + - Everything merged into one file. 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/style.css b/data/style.css index 139551c9..192f909d 100644 --- a/data/style.css +++ b/data/style.css @@ -866,13 +866,11 @@ div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px #media_div { padding-left: 20px; } #media_div span { display: block } -#jt_box_rel_vn h2, #jt_box_rel_prod h2 { clear: left; padding-top: 10px; } -#jt_box_rel_vn div, #jt_box_rel_prod div { padding-left: 20px } -#jt_box_rel_vn input, #jt_box_rel_prod input { margin-right: 10px; width: 300px } -#jt_box_rel_vn span, #jt_box_rel_prod span { clear: left; display: block; padding: 2px; } -#jt_box_rel_vn span.odd, #jt_box_rel_prod span.odd { background: url($_boxbg$) repeat; } -#jt_box_rel_vn i, #jt_box_rel_prod i { font-style: normal; display: block; float: left; width: 310px } -#jt_box_rel_vn b, #jt_box_rel_prod b { font-weight: normal; } +#jt_box_rel_vn h2, #jt_box_rel_prod h2 { clear: left; padding-top: 10px; } +#jt_box_rel_vn div, #jt_box_rel_vn table, +#jt_box_rel_prod div, #jt_box_rel_prod table { margin-left: 20px } +#jt_box_rel_vn input, #jt_box_rel_prod input { margin-right: 10px; width: 300px } +#jt_box_rel_vn .tc_title, #jt_box_rel_prod .tc_name { width: 310px; padding: 2px } diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index f0daa4cb..e7442845 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -370,7 +370,7 @@ sub edit { $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}); - $self->htmlHeader(js => 'forms', title => $title, noindex => 1); + $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('r', $r, $copy ? 'copy' : 'edit') if $rid; $self->htmlMainTabs('v', $v, 'edit') if $vid; $self->htmlEditMessage('r', $r, $title, $copy); @@ -446,12 +446,11 @@ sub _form { [ hidden => short => 'producers' ], [ static => nolabel => 1, content => sub { h2 mt('_redit_form_prod_sel'); - div id => 'producerssel'; - end; + table; tbody id => 'producer_tbl'; end; end; h2 mt('_redit_form_prod_add'); div; - input type => 'text', class => 'text'; - a href => '#', 'add'; + input id => 'producer_input', type => 'text', class => 'text'; + a id => 'producer_add', href => '#', 'add'; end; }], ], @@ -460,12 +459,11 @@ sub _form { [ hidden => short => 'vn' ], [ static => nolabel => 1, content => sub { h2 mt('_redit_form_vn_sel'); - div id => 'vnsel'; - end; + table; tbody id => 'vn_tbl'; end; end; h2 mt('_redit_form_vn_add'); div; - input type => 'text', class => 'text'; - a href => '#', 'add'; + input id => 'vn_input', type => 'text', class => 'text'; + a href => '#', id => 'vn_add', 'add'; end; }], ], diff --git a/lib/VNDB/Handler/Tags.pm b/lib/VNDB/Handler/Tags.pm index 0f8b780a..6a13446b 100644 --- a/lib/VNDB/Handler/Tags.pm +++ b/lib/VNDB/Handler/Tags.pm @@ -422,7 +422,7 @@ sub vntagmod { my $frm; my $title = mt '_tagv_title', $v->{title}; - $self->htmlHeader(title => $title, noindex => 1, js => 'forms'); + $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('v', $v, 'tagmod'); div class => 'mainbox'; h1 $title; diff --git a/lib/VNDB/Handler/VNBrowse.pm b/lib/VNDB/Handler/VNBrowse.pm index 2a6d6cd7..b0c948cd 100644 --- a/lib/VNDB/Handler/VNBrowse.pm +++ b/lib/VNDB/Handler/VNBrowse.pm @@ -70,7 +70,7 @@ sub list { $self->resRedirect('/v'.$list->[0]{id}, 'temp') if $f->{q} && @$list == 1; - $self->htmlHeader(title => mt('_vnbrowse_title'), search => $f->{q}, js => 'forms'); + $self->htmlHeader(title => mt('_vnbrowse_title'), search => $f->{q}); _filters($self, $f, $char, \@ignored); my $url = "/v/$char?q=$f->{q};ti=$f->{ti};te=$f->{te}"; diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm index e618b360..8430156d 100644 --- a/lib/VNDB/Handler/VNEdit.pm +++ b/lib/VNDB/Handler/VNEdit.pm @@ -97,7 +97,7 @@ sub edit { $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'; - $self->htmlHeader(js => 'forms', title => $title, noindex => 1); + $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('v', $v, 'edit') if $vid; $self->htmlEditMessage('v', $v, $title); _form($self, $v, $frm); diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm index 99b615b5..524b6258 100644 --- a/lib/VNDB/Util/LayoutHTML.pm +++ b/lib/VNDB/Util/LayoutHTML.pm @@ -10,11 +10,10 @@ use VNDB::Func; our @EXPORT = qw|htmlHeader htmlFooter|; -sub htmlHeader { # %options->{ title, js, noindex, search } +sub htmlHeader { # %options->{ title, noindex, search } my($self, %o) = @_; my $skin = $self->reqParam('skin') || $self->authInfo->{skin} || $self->{skin_default}; $skin = $self->{skin_default} if !$self->{skins}{$skin} || !-d "$VNDB::ROOT/static/s/$skin"; - $self->{js} = $o{js}; # save for use in htmlFooter # heading html; @@ -159,7 +158,6 @@ sub htmlFooter { end; end; # /div maincontent script type => 'text/javascript', src => $self->{url_static}.'/f/script.js?'.$self->{version}, ''; - script type => 'text/javascript', src => $self->{url_static}.'/f/forms.js?'.$self->{version}, '' if $self->{js}; end; # /body end; # /html diff --git a/static/f/forms.js b/static/f/forms.js deleted file mode 100644 index 99b8bd13..00000000 --- a/static/f/forms.js +++ /dev/null @@ -1,123 +0,0 @@ -function qq(v) { - return v.replace(/&/g,"&").replace(/</,"<").replace(/>/,">").replace(/"/g,'"'); -} - - - - - /****************************************************\ - * V I S U A L N O V E L S / P R O D U C E R S * - \****************************************************/ - - -function vnpLoad(type) { - // load currently selected VNs - var l = x(type).value.split('|||'); - for(var i=0;i<l.length;i++) - if(l[i].length > 2) - vnpAdd(type, l[i].split(',',2)[0], l[i].split(',',2)[1]); - vnpCheckEmpty(type); - - // dropdown - var n = x('jt_box_'+(type == 'vn' ? 'rel_vn' : 'rel_prod')).getElementsByTagName('div')[1]; - dsInit(n.getElementsByTagName('input')[0], '/xml/'+type+'.xml?q=', function(item, tr) { - var td = document.createElement('td'); - td.innerHTML = type.substr(0,1)+item.getAttribute('id'); - td.style.textAlign = 'right'; - td.style.paddingRight = '5px'; - tr.appendChild(td); - td = document.createElement('td'); - td.innerHTML = shorten(item.firstChild.nodeValue, 40); - tr.appendChild(td); - }, function(item) { - return type.substr(0,1)+item.getAttribute('id')+':'+item.firstChild.nodeValue; - }, function() { vnpFormAdd(type) }); - n.getElementsByTagName('a')[0].onclick = function() { vnpFormAdd(type); return false }; -} - -function vnpAdd(type, id, title) { - var o = document.createElement('span'); - o.innerHTML = '<i>'+type.substr(0,1)+id+':<a href="/'+type.substr(0,1)+id+'">'+shorten(title, 40)+'</a></i>' - +'<a href="#" onclick="return vnpDel(this, \''+type+'\')">remove</a>'; - x(type+'sel').appendChild(o); - vnpStripe(type); - vnpCheckEmpty(type); -} - -function vnpDel(what, type) { - what = what.nodeName ? what : this; - while(what.nodeName.toLowerCase() != 'span') - what = what.parentNode; - x(type+'sel').removeChild(what); - vnpCheckEmpty(type); - vnpSerialize(type); - return false; -} - -function vnpCheckEmpty(type) { - var o = x(type+'sel'); - if(o.getElementsByTagName('span').length < 1) { - if(o.getElementsByTagName('b').length < 1) - o.innerHTML = '<b>Nothing selected...</b>'; - } else if(o.getElementsByTagName('b').length == 1) - o.removeChild(o.getElementsByTagName('b')[0]); -} - -function vnpStripe(type) { - var l = x(type+'sel').getElementsByTagName('span'); - for(var i=0;i<l.length;i++) - l[i].className = i%2 ? 'odd' : ''; -} - -function vnpFormAdd(type) { - var n = x('jt_box_'+(type == 'vn' ? 'rel_vn' : 'rel_prod')).getElementsByTagName('div')[1]; - var txt = n.getElementsByTagName('input')[0]; - var lnk = n.getElementsByTagName('a')[0]; - var input = txt.value; - - if(type == 'vn' && !input.match(/^v[0-9]+/)) { - alert('Visual novel textbox must start with an ID (e.g. v17)'); - return false; - } - if(type == 'producers' && !input.match(/^p[0-9]+/)) { - alert('Producer textbox must start with an ID (e.g. p5)'); - return false; - } - - txt.disabled = true; - txt.value = 'loading...'; - lnk.innerHTML = 'loading...'; - - ajax('/xml/'+type+'.xml?q='+encodeURIComponent(input), function(hr) { - txt.disabled = false; - txt.value = ''; - lnk.innerHTML = 'add'; - - var items = hr.responseXML.getElementsByTagName('item'); - if(items.length < 1) - return alert('Item not found!'); - - vnpAdd(type, items[0].getAttribute('id'), items[0].firstChild.nodeValue); - vnpSerialize(type); - }); - return false; -} - -function vnpSerialize(type) { - var r = ''; - var l = x(type+'sel').getElementsByTagName('span'); - for(var i=0;i<l.length;i++) - r += (r ? '|||' : '') + l[i].getElementsByTagName('i')[0].innerHTML.substr(1, l[i].getElementsByTagName('i')[0].innerHTML.indexOf(':')-1) - + ',' + l[i].getElementsByTagName('a')[0].innerHTML; - x(type).value = r; -} - - - -// load - -if(x('jt_box_rel_vn')) - vnpLoad('vn'); -if(x('jt_box_rel_prod')) - vnpLoad('producers'); - diff --git a/static/f/script.js b/static/f/script.js index 69f54fc9..07ad9866 100644 --- a/static/f/script.js +++ b/static/f/script.js @@ -6,6 +6,8 @@ * jt -> Javascript Tabs * med -> Release media selector * rl -> Release List dropdown + * rpr -> Release <-> producer linking + * rvn -> Release <-> visual novel linking * scr -> VN screenshot uploader * tgl -> VN tag linking * tvs -> VN page tag spoilers @@ -758,6 +760,8 @@ function vnrSerialize() { var r = []; var trs = byName(byId('relation_tbl'), 'tr'); for(var i=0; i<trs.length; i++) { + if(trs[i].id == 'relation_tr_none') + continue; var rel = byName(byClass(trs[i], 'td', 'tc_rel')[0], 'select')[0]; r[r.length] = [ rel.options[rel.selectedIndex].value, // relation @@ -1307,6 +1311,210 @@ if(byId('taglinks')) +/* R E L E A S E -> V I S U A L N O V E L L I N K I N G (/r+/edit) */ + +function rvnLoad() { + var vns = byId('vn').value.split('|||'); + for(var i=0; i<vns.length && vns[i].length>1; i++) + rvnAdd(vns[i].split(',',2)[0], vns[i].split(',',2)[1]); + rvnEmpty(); + + dsInit(byId('vn_input'), '/xml/vn.xml?q=', + function(item, tr) { + tr.appendChild(tag('td', {style:'text-align: right; padding-right: 5px'}, 'v'+item.getAttribute('id'))); + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); + }, function(item) { + return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue; + }, + rvnFormAdd + ); + byId('vn_add').onclick = rvnFormAdd; +} + +function rvnAdd(id, title) { + x('vn_tbl').appendChild(tag('tr', {id:'rvn_'+id, rvn_id:id}, + tag('td', {'class':'tc_title'}, 'v'+id+':', tag('a', {href:'/v'+id}, shorten(title, 40))), + tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rvnDel}, 'remove')) + )); + rvnStripe(); + rvnEmpty(); +} + +function rvnDel() { + var tr = this; + while(tr.nodeName.toLowerCase() != 'tr') + tr = tr.parentNode; + tr.parentNode.removeChild(tr); + rvnEmpty(); + rvnSerialize(); + rvnStripe(); + return false; +} + +function rvnEmpty() { + var tbl = byId('vn_tbl'); + if(byName(tbl, 'tr').length < 1) + tbl.appendChild(tag('tr', {id:'rvn_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.'))); + else if(byId('rvn_tr_none')) + tbl.removeChild(byId('rvn_tr_none')); +} + +function rvnStripe() { + var l = byName(byId('vn_tbl'), 'tr'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'odd', i%2); +} + +function rvnFormAdd() { + var txt = byId('vn_input'); + var lnk = byId('vn_add'); + var val = txt.value; + + if(!val.match(/^v[0-9]+/)) { + alert('Visual novel textbox must start with an ID (e.g. v17)'); + return false; + } + + txt.disabled = true; + txt.value = 'loading...'; + setText(lnk, 'loading...'); + + ajax('/xml/vn.xml?q='+encodeURIComponent(val), function(hr) { + txt.disabled = false; + txt.value = ''; + setText(lnk, 'add'); + + var items = hr.responseXML.getElementsByTagName('item'); + if(items.length < 1) + return alert('Visual novel not found!'); + + var id = items[0].getAttribute('id'); + if(byId('rvn_'+id)) + return alert('VN already selected!'); + + rvnAdd(id, items[0].firstChild.nodeValue); + rvnSerialize(); + }); + return false; +} + +function rvnSerialize() { + var r = []; + var l = byName(byId('vn_tbl'), 'tr'); + for(var i=0; i<l.length; i++) + if(l[i].rvn_id) + r[r.length] = l[i].rvn_id + ',' + getText(byName(byClass(l[i], 'td', 'tc_title')[0], 'a')[0]); + byId('vn').value = r.join('|||'); +} + +if(byId('jt_box_rel_vn')) + rvnLoad(); + + + + +/* R E L E A S E -> P R O D U C E R L I N K I N G (/r+/edit) */ + +function rprLoad() { + var ps = byId('producers').value.split('|||'); + for(var i=0; i<ps.length && ps[i].length>1; i++) + rprAdd(ps[i].split(',',2)[0], ps[i].split(',',2)[1]); + rprEmpty(); + + dsInit(byId('producer_input'), '/xml/producers.xml?q=', + function(item, tr) { + tr.appendChild(tag('td', {style:'text-align: right; padding-right: 5px'}, 'p'+item.getAttribute('id'))); + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); + }, function(item) { + return 'p'+item.getAttribute('id')+':'+item.firstChild.nodeValue; + }, + rprFormAdd + ); + byId('producer_add').onclick = rprFormAdd; +} + +function rprAdd(id, name) { + x('producer_tbl').appendChild(tag('tr', {id:'rpr_'+id, rpr_id:id}, + tag('td', {'class':'tc_name'}, 'p'+id+':', tag('a', {href:'/p'+id}, shorten(name, 40))), + tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rprDel}, 'remove')) + )); + rprStripe(); + rprEmpty(); +} + +function rprDel() { + var tr = this; + while(tr.nodeName.toLowerCase() != 'tr') + tr = tr.parentNode; + tr.parentNode.removeChild(tr); + rprEmpty(); + rprSerialize(); + rprStripe(); + return false; +} + +function rprEmpty() { + var tbl = byId('producer_tbl'); + if(byName(tbl, 'tr').length < 1) + tbl.appendChild(tag('tr', {id:'rpr_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.'))); + else if(byId('rpr_tr_none')) + tbl.removeChild(byId('rpr_tr_none')); +} + +function rprStripe() { + var l = byName(byId('producer_tbl'), 'tr'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'odd', i%2); +} + +function rprFormAdd() { + var txt = byId('producer_input'); + var lnk = byId('producer_add'); + var val = txt.value; + + if(!val.match(/^p[0-9]+/)) { + alert('Producer textbox must start with an ID (e.g. p17)'); + return false; + } + + txt.disabled = true; + txt.value = 'loading...'; + setText(lnk, 'loading...'); + + ajax('/xml/producers.xml?q='+encodeURIComponent(val), function(hr) { + txt.disabled = false; + txt.value = ''; + setText(lnk, 'add'); + + var items = hr.responseXML.getElementsByTagName('item'); + if(items.length < 1) + return alert('Producer not found!'); + + var id = items[0].getAttribute('id'); + if(byId('rpr_'+id)) + return alert('Producer already selected!'); + + rprAdd(id, items[0].firstChild.nodeValue); + rprSerialize(); + }); + return false; +} + +function rprSerialize() { + var r = []; + var l = byName(byId('producer_tbl'), 'tr'); + for(var i=0; i<l.length; i++) + if(l[i].rpr_id) + r[r.length] = l[i].rpr_id + ',' + getText(byName(byClass(l[i], 'td', 'tc_name')[0], 'a')[0]); + byId('producers').value = r.join('|||'); +} + +if(byId('jt_box_rel_prod')) + rprLoad(); + + + + /* M I S C S T U F F */ // search box -- cgit v1.2.3 From 9afed91c8196a8d35fc33ec23a214cabb58c45a7 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 09:13:15 +0200 Subject: L10N: Generalized age() for all languages by using maketext() internally This way the translators can TL/improve their own translation of the age display, instead of asking me to fix it. --- data/lang.txt | 31 +++++++++++++++++++++++++++++++ lib/VNDB/L10N.pm | 23 ++++------------------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index 306ff2d9..22f0073d 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -100,6 +100,37 @@ ends with ']'. The following options are supported: # data/global.pl - used in many places +# Age display + +:_age_years +en : [_1] [quant,_1,year,years] ago +ru : [_1] [quant,_1,год,года,лет] назад + +:_age_months +en : [_1] [quant,_1,month,months] ago +ru : [_1] [quant,_1,месяц,месяца,месяцев] назад + +:_age_weeks +en : [_1] [quant,_1,week,weeks] ago +ru : [_1] [quant,_1,неделя,недели,недель] назад + +:_age_days +en : [_1] [quant,_1,day,days] ago +ru : [_1] [quant,_1,день,дня,дней] назад + +:_age_hours +en : [_1] [quant,_1,hour,hours] ago +ru : [_1] [quant,_1,час,часа,часов] назад + +:_age_min +en : [_1] min ago +ru : [_1] [quant,_1,минута,минуты,минут] назад + +:_age_sec +en : [_1] sec ago +ru : [_1] [quant,_1,секунда,секунды,секунд] назад + + # user ranks :_urank_0 diff --git a/lib/VNDB/L10N.pm b/lib/VNDB/L10N.pm index c2423f53..e19302ed 100644 --- a/lib/VNDB/L10N.pm +++ b/lib/VNDB/L10N.pm @@ -58,8 +58,9 @@ use warnings; # Argument: unix timestamp # Returns: age sub age { - my $a = time-$_[1]; - return sprintf '%d %s ago', + my($self, $time) = @_; + my $a = time-$time; + my @f = $a > 60*60*24*365*2 ? ( $a/60/60/24/365, 'years' ) : $a > 60*60*24*(365/12)*2 ? ( $a/60/60/24/(365/12), 'months' ) : $a > 60*60*24*7*2 ? ( $a/60/60/24/7, 'weeks' ) : @@ -67,6 +68,7 @@ use warnings; $a > 60*60*2 ? ( $a/60/60, 'hours' ) : $a > 60*2 ? ( $a/60, 'min' ) : ( $a, 'sec' ); + return $self->maketext("_age_$f[1]", int $f[0]); } # argument: unix timestamp and optional format (compact/full) @@ -135,23 +137,6 @@ use warnings; return $couple if ($num % 10) >= 2 && ($num % 10) <= 4 && !(($num % 100) >= 12 && ($num % 100) <= 14); return $lots; } - - sub age { - my $self = shift; - my $a = time-shift; - use utf8; - my @l = ( - $a > 60*60*24*365*2 ? ( $a/60/60/24/365, 'год', 'года', 'лет' ) : - $a > 60*60*24*(365/12)*2 ? ( $a/60/60/24/(365/12), 'месяц', 'месяца', 'месяцев' ) : - $a > 60*60*24*7*2 ? ( $a/60/60/24/7, 'неделя', 'недели', 'недель' ) : - $a > 60*60*24*2 ? ( $a/60/60/24, 'день', 'дня', 'дней' ) : - $a > 60*60*2 ? ( $a/60/60, 'час', 'часа', 'часов' ) : - $a > 60*2 ? ( $a/60, 'минута', 'минуты', 'минут' ) : - ( $a, 'секунда', 'секунды', 'секунд' ) - ); - return sprintf '%d %s назад', $l[0], $self->quant(@l); - } - } -- cgit v1.2.3 From bafb8b134744cba74a3a019fefb36091b0e19d13 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 10:22:14 +0200 Subject: skingen: Used CSS::Minifier::XS instead of my crappy regexes The minified and gzipped CSS file is now 0.7kB smaller than the non-minified but gzipped CSS file. That's significant enough on ~5kB. --- README | 4 ++++ util/skingen.pl | 17 +++++------------ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/README b/README index 1060c544..0ea41d8c 100644 --- a/README +++ b/README @@ -48,6 +48,10 @@ Requirements XML::Writer PerlIO::gzip + util/skingen.pl + Image::Magick + CSS::Minifier::XS (optional, minimizes CSS output) + Contact diff --git a/util/skingen.pl b/util/skingen.pl index e27ea4a1..d18f5fde 100755 --- a/util/skingen.pl +++ b/util/skingen.pl @@ -5,8 +5,8 @@ package VNDB; use strict; use warnings; use Cwd 'abs_path'; -use Data::Dumper 'Dumper'; use Image::Magick; +eval { require CSS::Minifier::XS }; our($ROOT, %O); @@ -78,19 +78,12 @@ sub writeskin { # $obj # write the CSS open my $CSS, '<', "$ROOT/data/style.css" or die $!; + my $css = join '', <$CSS>; + close $CSS; + $css =~ s/\$$_\$/$o->{$_}/g for (keys %$o); open my $SKIN, '>', "$ROOT/static/s/$o->{_name}/style.css" or die $!; - while((my $d = <$CSS>)) { - if($O{debug}) { - chomp $d; - $d =~ s/^\s*/ /; - $d =~ s{/\*.+\*/}{}; # NOTE: multiline comments or multiple comments per line won't work - next if $d !~ /[^\s\t]/; - } - $d =~ s/\$$_\$/$o->{$_}/g for (keys %$o); - print $SKIN $d; - } + print $SKIN $CSS::Minifier::XS::VERSION ? CSS::Minifier::XS::minify($css) : $css; close $SKIN; - close $CSS; } -- cgit v1.2.3 From e0161bd219a3004a3affdecd04d54a85f5cf9e1d Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 11:03:59 +0200 Subject: JS: Moved script.js to data/ and added jsgen.pl to process it While this 'processing' is currently limited to minifying the file if JavaScript::Minifier::XS is available, this change would make it a lot easier to make the strings in the JS code translatable. --- .gitignore | 1 + README | 3 + data/script.js | 1758 ++++++++++++++++++++++++++++++++++++++++++++++++++++ static/f/script.js | 1758 ---------------------------------------------------- util/jsgen.pl | 24 + util/vndb.pl | 12 + 6 files changed, 1798 insertions(+), 1758 deletions(-) create mode 100644 data/script.js delete mode 100644 static/f/script.js create mode 100755 util/jsgen.pl diff --git a/.gitignore b/.gitignore index 2baf1a87..e2a730fd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /data/config.pl /data/log/ +/static/f/script.js /static/s/*/style.css /static/s/*/boxbg.png /static/cv/ diff --git a/README b/README index 0ea41d8c..e62f0e06 100644 --- a/README +++ b/README @@ -52,6 +52,9 @@ Requirements Image::Magick CSS::Minifier::XS (optional, minimizes CSS output) + util/jsgen.pl + JavaScript::Minifier::XS (optional, minimizes JS output) + Contact diff --git a/data/script.js b/data/script.js new file mode 100644 index 00000000..07ad9866 --- /dev/null +++ b/data/script.js @@ -0,0 +1,1758 @@ +/* function/attribute prefixes: + * date -> Date selector + * dd -> dropdown + * ds -> dropdown search + * iv -> image viewer + * jt -> Javascript Tabs + * med -> Release media selector + * rl -> Release List dropdown + * rpr -> Release <-> producer linking + * rvn -> Release <-> visual novel linking + * scr -> VN screenshot uploader + * tgl -> VN tag linking + * tvs -> VN page tag spoilers + * vnr -> VN relation editor + */ +var expanded_icon = '▾'; +var collapsed_icon = '▸'; + +/* M I N I M A L J A V A S C R I P T L I B R A R Y */ + +var http_request = false; +function ajax(url, func) { + if(http_request) + http_request.abort(); + http_request = (window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest(); + if(http_request == null) + return alert("Your browser does not support the functionality this website requires."); + http_request.onreadystatechange = function() { + if(!http_request || http_request.readyState != 4 || !http_request.responseText) + return; + if(http_request.status != 200) + return alert('Whoops, error! :('); + func(http_request); + }; + url += (url.indexOf('?')>=0 ? ';' : '?')+(Math.floor(Math.random()*999)+1); + http_request.open('GET', url, true); + http_request.send(null); +} + +function setCookie(n,v) { + var date = new Date(); + date.setTime(date.getTime()+(365*24*60*60*1000)); + document.cookie = n+'='+v+'; expires='+date.toGMTString()+'; path=/'; +} +function getCookie(n) { + var l = document.cookie.split(';'); + for(var i=0; i<l.length; i++) { + var c = l[i]; + while(c.charAt(0) == ' ') + c = c.substring(1,c.length); + if(c.indexOf(n+'=') == 0) + return c.substring(n.length+1,c.length); + } + return null; +} + +function x(y) { // deprecated + return document.getElementById(y) +} +function byId(n) { + return document.getElementById(n) +} +function byName(){ + var d = arguments.length > 1 ? arguments[0] : document; + var n = arguments.length > 1 ? arguments[1] : arguments[0]; + return d.getElementsByTagName(n); +} +function byClass() { // [class], [parent, class], [tagname, class], [parent, tagname, class] + var par = typeof arguments[0] == 'object' ? arguments[0] : document; + var tag = arguments.length == 2 && typeof arguments[0] == 'string' ? arguments[0] : arguments.length == 3 ? arguments[1] : '*'; + var c = arguments[arguments.length-1]; + var l = byName(par, tag); + var ret = []; + for(var i=0; i<l.length; i++) + if(hasClass(l[i], c)) + ret[ret.length] = l[i]; + return ret; +} + +/* wrapper around DOM element creation + * tag('string') -> createTextNode + * tag('tagname', tag(), 'string', ..) -> createElement(), appendChild(), .. + * tag('tagname', { class: 'meh', title: 'Title' }) -> createElement(), setAttribute().. + * tag('tagname', { <attributes> }, <elements>) -> create, setattr, append */ +function tag() { + if(arguments.length == 1) + return typeof arguments[0] != 'object' ? document.createTextNode(arguments[0]) : arguments[0]; + var el = typeof document.createElementNS != 'undefined' + ? document.createElementNS('http://www.w3.org/1999/xhtml', arguments[0]) + : document.createElement(arguments[0]); + for(var i=1; i<arguments.length; i++) { + if(arguments[i] == null) + continue; + if(typeof arguments[i] == 'object' && !arguments[i].appendChild) { + for(attr in arguments[i]) { + if(attr == 'style') + el.setAttribute(attr, arguments[i][attr]); + else + el[ attr == 'class' ? 'className' : attr == 'for' ? 'htmlFor' : attr ] = arguments[i][attr]; + } + } else + el.appendChild(tag(arguments[i])); + } + return el; +} +function addBody(el) { + if(document.body.appendChild) + document.body.appendChild(el); + else if(document.documentElement.appendChild) + document.documentElement.appendChild(el); + else if(document.appendChild) + document.appendChild(el); +} +function setContent() { + setText(arguments[0], ''); + for(var i=1; i<arguments.length; i++) + arguments[0].appendChild(tag(arguments[i])); +} +function getText(obj) { + return obj.textContent || obj.innerText || ''; +} +function setText(obj, txt) { + if(obj.textContent != null) + obj.textContent = txt; + else + obj.innerText = txt; +} + +function listClass(obj) { + var n = obj.className; + if(!n) + return []; + return n.split(/ /); +} +function hasClass(obj, c) { + var l = listClass(obj); + for(var i=0; i<l.length; i++) + if(l[i] == c) + return true; + return false; +} +function setClass(obj, c, set) { + var l = listClass(obj); + var n = []; + if(set) { + n = l; + if(!hasClass(obj, c)) + n[n.length] = c; + } else { + for(var i=0; i<l.length; i++) + if(l[i] != c) + n[n.length] = l[i]; + } + obj.className = n.join(' '); +} + +function shorten(v, l) { + return v.length > l ? v.substr(0, l-3)+'...' : v; +} + + + + +/* I M A G E V I E W E R */ + +function ivInit() { + var init = 0; + var l = byName('a'); + for(var i=0;i<l.length;i++) + if(l[i].rel.substr(0,3) == 'iv:') { + init++; + l[i].onclick = ivView; + } + if(init && !byId('iv_view')) { + addBody(tag('div', {id: 'iv_view'}, + tag('b', {id:'ivimg'}, ''), + tag('br', null), + tag('a', {href:'#', id:'ivfull'}, ''), + tag('a', {href:'#', onclick: ivClose, id:'ivclose'}, 'close'), + tag('a', {href:'#', onclick: ivView, id:'ivprev'}, '« previous'), + tag('a', {href:'#', onclick: ivView, id:'ivnext'}, 'next »') + )); + addBody(tag('b', {id:'ivimgload'}, 'Loading...')); + } +} + +function ivView(what) { + what = what && what.rel ? what : this; + var u = what.href; + var opt = what.rel.split(':'); + var view = byId('iv_view'); + var next = byId('ivnext'); + var prev = byId('ivprev'); + var full = byId('ivfull'); + + // fix prev/next links (if any) + if(opt[2]) { + var ol = byName('a'); + var l=[]; + for(i=0;i<ol.length;i++) + if(ol[i].rel.substr(0,3) == 'iv:' && ol[i].rel.indexOf(':'+opt[2]) > 4 && !hasClass(ol[i], 'hidden') && ol[i].id != 'ivprev' && ol[i].id != 'ivnext') + l[l.length] = ol[i]; + for(i=0;i<l.length;i++) + if(l[i].href == u) { + next.style.visibility = l[i+1] ? 'visible' : 'hidden'; + next.href = l[i+1] ? l[i+1].href : '#'; + next.rel = l[i+1] ? l[i+1].rel : ''; + prev.style.visibility = l[i-1] ? 'visible' : 'hidden'; + prev.href = l[i-1] ? l[i-1].href : '#'; + prev.rel = l[i-1] ? l[i-1].rel : ''; + } + } else + next.style.visibility = prev.style.visibility = 'hidden'; + + // calculate dimensions + var w = Math.floor(opt[1].split('x')[0]); + var h = Math.floor(opt[1].split('x')[1]); + var ww = typeof(window.innerWidth) == 'number' ? window.innerWidth : document.documentElement.clientWidth; + var wh = typeof(window.innerHeight) == 'number' ? window.innerHeight : document.documentElement.clientHeight; + var st = typeof(window.pageYOffset) == 'number' ? window.pageYOffset : document.body && document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop; + if(w+100 > ww || h+70 > wh) { + full.href = u; + setText(full, w+'x'+h); + full.style.visibility = 'visible'; + if(w/h > ww/wh) { // width++ + h *= (ww-100)/w; + w = ww-100; + } else { // height++ + w *= (wh-70)/h; + h = wh-70; + } + } else + full.style.visibility = 'hidden'; + var dw = w; + var dh = h+20; + dw = dw < 200 ? 200 : dw; + + // update document + view.style.display = 'block'; + setContent(byId('ivimg'), tag('img', {src:u, onclick:ivClose, + onload: function() { byId('ivimgload').style.top='-400px'; }, + style: 'width: '+w+'px; height: '+h+'px' + })); + view.style.width = dw+'px'; + view.style.height = dh+'px'; + view.style.left = ((ww - dw) / 2 - 10)+'px'; + view.style.top = ((wh - dh) / 2 + st - 20)+'px'; + byId('ivimgload').style.left = ((ww - 100) / 2 - 10)+'px'; + byId('ivimgload').style.top = ((wh - 20) / 2 + st)+'px'; + return false; +} + +function ivClose() { + byId('iv_view').style.display = 'none'; + byId('iv_view').style.top = '-5000px'; + byId('ivimgload').style.top = '-400px'; + setText(byId('ivimg'), ''); + return false; +} + +ivInit(); + + + + +/* D R O P D O W N */ + +function ddInit(obj, align, contents) { + obj.dd_align = align; // see ddRefresh for details + obj.dd_contents = contents; + document.onmousemove = ddMouseMove; + document.onscroll = ddHide; + if(!byId('dd_box')) + addBody(tag('div', {id:'dd_box', dd_used: false})); +} + +function ddHide() { + var box = byId('dd_box'); + setText(box, ''); + box.style.left = '-500px'; + box.dd_used = false; + box.dd_lnk = null; +} + +function ddMouseMove(e) { + e = e || window.event; + var lnk = e.target || e.srcElement; + while(lnk && (lnk.nodeType == 3 || !lnk.dd_align)) + lnk = lnk.parentNode; + var box = byId('dd_box'); + if(!box.dd_used && !lnk) + return; + + if(box.dd_used) { + var mouseX = e.pageX || (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft); + var mouseY = e.pageY || (e.clientY + document.body.scrollTop + document.documentElement.scrollTop); + if((mouseX < ddx-10 || mouseX > ddx+box.offsetWidth+10 || mouseY < ddy-10 || mouseY > ddy+box.offsetHeight+10) + || (lnk && lnk == box.dd_lnk)) + ddHide(); + } + + if(!box.dd_used && lnk) { + box.dd_lnk = lnk; + box.dd_used = true; + if(!ddRefresh()) + ddHide(); + } +} + +function ddRefresh() { + var box = byId('dd_box'); + if(!box.dd_used) + return false; + var lnk = box.dd_lnk; + var content = lnk.dd_contents(lnk, box); + if(content == null) + return false; + setContent(box, content); + + var o = lnk; + ddx = ddy = 0; + do { + ddx += o.offsetLeft; + ddy += o.offsetTop; + } while(o = o.offsetParent); + + if(lnk.dd_align == 'left') + ddx -= box.offsetWidth; + if(lnk.dd_align == 'tagmod') + ddx += lnk.offsetWidth-35; + box.style.left = ddx+'px'; + box.style.top = ddy+'px'; + return true; +} + + +// release list dropdown on VN pages + +var rstat = [ 'Unknown', 'Pending', 'Obtained', 'On loan', 'Deleted' ]; +var vstat = [ 'Unknown', 'Playing', 'Finished', 'Stalled', 'Dropped' ]; +function rlDropDown(lnk) { + var relid = lnk.id.substr(6); + var st = getText(lnk).split(' / '); + if(st[0].indexOf('loading') >= 0) + return null; + + var rs = tag('ul', tag('li', tag('b', 'Release status'))); + var vs = tag('ul', tag('li', tag('b', 'Play status'))); + for(var i=0;i<rstat.length;i++) { + if(st[0] && st[0].indexOf(rstat[i]) >= 0) + rs.appendChild(tag('li', tag('i', rstat[i]))); + else + rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+i, onclick:rlMod}, rstat[i]))); + } + for(var i=0;i<vstat.length;i++) { + if(st[0] && st[0].indexOf(vstat[i]) >= 0) + vs.appendChild(tag('li', tag('i', vstat[i]))); + else + vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+i, onclick:rlMod}, vstat[i]))); + } + + return tag('div', {'class':'vrdd'}, rs, vs, st[0] == '--' ? null : + tag('ul', {'class':'full'}, tag('li', tag('a', {href:'#', rl_rid: relid, rl_act:'del', onclick:rlMod}, 'Remove from VN List'))) + ); +} + +function rlMod() { + var lnk = byId('rlsel_'+this.rl_rid); + ddHide(); + setContent(lnk, tag('b', {'class': 'patch'}, 'loading...')); + ajax('/xml/rlist.xml?id='+this.rl_rid+';e='+this.rl_act, function(hr) { + // TODO: get rid of innerHTML here... + lnk.innerHTML = hr.responseXML.getElementsByTagName('rlist')[0].firstChild.nodeValue; + }); + return false; +} + +{ + var l = byClass('a', 'vnrlsel'); + for(var i=0;i<l.length;i++) + ddInit(l[i], 'left', rlDropDown); +} + + + + +/* J A V A S C R I P T T A B S */ + +function jtInit() { + if(!byId('jt_select')) + return; + var sel = ''; + var first = ''; + var l = byName(byId('jt_select'), 'a'); + if(l.length < 1) + return; + for(var i=0; i<l.length; i++) { + l[i].onclick = jtSel; + if(!first) + first = l[i].id; + if(location.hash && l[i].id == 'jt_sel_'+location.hash.substr(1)) + sel = l[i].id; + } + if(!sel) + sel = first; + jtSel(sel, 1); +} + +function jtSel(which, nolink) { + which = typeof(which) == 'string' ? which : which && which.id ? which.id : this.id; + which = which.substr(7); + + var l = byName(byId('jt_select'), 'a'); + for(var i=0;i<l.length;i++) { + var name = l[i].id.substr(7); + if(name != 'all') + byId('jt_box_'+name).style.display = name == which || which == 'all' ? 'block' : 'none'; + var tab = l[i].parentNode; + setClass(tab, 'tabselected', name == which); + } + + if(!nolink) + location.href = '#'+which; + return false; +} + +jtInit(); + + + + +/* V N P A G E T A G S P O I L E R S */ + +function tvsInit() { + if(!byId('tagops')) + return; + var l = byName(byId('tagops'), 'a'); + for(var i=0;i<l.length; i++) + l[i].onclick = tvsClick; + tvsSet(getCookie('tagspoil'), true); +} + +function tvsClick() { + var sel; + var l = byName(byId('tagops'), 'a'); + for(var i=0; i<l.length; i++) + if(l[i] == this) { + if(i < 3) { + tvsSet(i, null); + setCookie('tagspoil', i); + } else + tvsSet(null, i == 3 ? true : false); + } + return false; +} + +function tvsSet(lvl, lim) { + /* set/get level and limit to/from the links */ + var l = byName(byId('tagops'), 'a'); + for(var i=0; i<l.length; i++) { + if(i < 3) { /* spoiler level */ + if(lvl != null) + setClass(l[i], 'tsel', i == lvl); + if(lvl == null && hasClass(l[i], 'tsel')) + lvl = i; + } else { /* display limit (3 = summary) */ + if(lim != null) + setClass(l[i], 'tsel', lim == (i == 3)); + if(lim == null && hasClass(l[i], 'tsel')) + lim = i == 3; + } + } + + /* update tag visibility */ + l = byName(byId('vntags'), 'span'); + lim = lim ? 15 : 999; + var s=0; + for(i=0;i<l.length;i++) { + var thislvl = l[i].className.substr(6, 1); + if(thislvl <= lvl && s < lim) { + setClass(l[i], 'hidden', false); + s++; + } else + setClass(l[i], 'hidden', true); + } + return false; +} + +tvsInit(); + + + + +/* D A T E I N P U T */ + +var months = ['January','February','March','April','May','June','July','August','September','October','November','December']; + +function dateLoad(obj) { + var val = Math.floor(obj.value) || 0; + val = [ Math.floor(val/10000), Math.floor(val/100)%100, val%100 ]; + + var year = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:0}, '-year-')); + for(var i=1980; i<=(new Date()).getFullYear()+5; i++) + year.appendChild(tag('option', {value: i, selected: i==val[0]}, i)); + year.appendChild(tag('option', {value: 9999, selected: val[0]==9999}, 'TBA')); + + var month = tag('select', {style: 'width: 100px', onchange: dateSerialize}, tag('option', {value:99}, '-month-')); + for(var i=1; i<=12; i++) + month.appendChild(tag('option', {value: i, selected: i==val[1]}, months[i-1])); + + var day = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:99}, '-day-')); + for(var i=1; i<=31; i++) + day.appendChild(tag('option', {value: i, selected: i==val[2]}, i)); + + obj.parentNode.insertBefore(tag('div', {date_obj: obj}, year, month, day), obj); +} + +function dateSerialize() { + var div = this.parentNode; + var sel = byName(div, 'select'); + var val = [ + sel[0].options[sel[0].selectedIndex].value*1, + sel[1].options[sel[1].selectedIndex].value*1, + sel[2].options[sel[2].selectedIndex].value*1 + ]; + div.date_obj.value = val[0] == 0 ? 0 : val[0] == 9999 ? 99999999 : val[0]*10000+val[1]*100+(val[1]==99?99:val[2]); +} + +{ + var l = byClass('input', 'dateinput'); + for(i=0; i<l.length; i++) + dateLoad(l[i]); +} + + + + +/* D R O P D O W N S E A R C H */ + +function dsInit(obj, url, trfunc, serfunc, retfunc, parfunc) { + obj.setAttribute('autocomplete', 'off'); + obj.onkeydown = dsKeyDown; + obj.onblur = function() { setTimeout(function () { byId('ds_box').style.top = '-500px'; }, 500) }; + obj.ds_returnFunc = retfunc; + obj.ds_trFunc = trfunc; + obj.ds_serFunc = serfunc; + obj.ds_parFunc = parfunc; + obj.ds_searchURL = url; + obj.ds_selectedId = 0; + obj.ds_dosearch = null; + if(!byId('ds_box')) + addBody(tag('div', {id: 'ds_box', style: 'position: absolute; top: -500px'}, tag('b', 'Loading...'))); +} + +function dsKeyDown(ev) { + var c = document.layers ? ev.which : document.all ? event.keyCode : ev.keyCode; + var obj = this; + + if(c == 9) // tab + return true; + + // do some processing when the enter key has been pressed + if(c == 13) { + var frm = obj; + while(frm && frm.nodeName.toLowerCase() != 'form') + frm = frm.parentNode; + if(frm) { + var oldsubmit = frm.onsubmit; + frm.onsubmit = function() { return false }; + setTimeout(function() { frm.onsubmit = oldsubmit }, 100); + } + + if(obj.ds_selectedId != 0) + obj.value = obj.ds_serFunc(byId('ds_box_'+obj.ds_selectedId).ds_itemData, obj); + if(obj.ds_returnFunc) + obj.ds_returnFunc(); + + byId('ds_box').style.top = '-500px'; + setContent(byId('ds_box'), tag('b', 'Loading...')); + obj.ds_selectedId = 0; + if(obj.ds_dosearch) { + clearTimeout(obj.ds_dosearch); + obj.ds_dosearch = null; + } + + return false; + } + + // process up/down keys + if(c == 38 || c == 40) { + var l = byName(byId('ds_box'), 'tr'); + if(l.length < 1) + return true; + + // get new selected id + if(obj.ds_selectedId == 0) { + if(c == 38) // up + obj.ds_selectedId = l[l.length-1].id.substr(7); + else + obj.ds_selectedId = l[0].id.substr(7); + } else { + var sel = null; + for(var i=0; i<l.length; i++) + if(l[i].id == 'ds_box_'+obj.ds_selectedId) { + if(c == 38) // up + sel = i>0 ? l[i-1] : l[l.length-1]; + else + sel = l[i+1] ? l[i+1] : l[0]; + } + obj.ds_selectedId = sel.id.substr(7); + } + + // set selected class + for(var i=0; i<l.length; i++) + setClass(l[i], 'selected', l[i].id == 'ds_box_'+obj.ds_selectedId); + return true; + } + + // perform search after a timeout + if(obj.ds_dosearch) + clearTimeout(obj.ds_dosearch); + obj.ds_dosearch = setTimeout(function() { + dsSearch(obj); + }, 500); + + return true; +} + +function dsSearch(obj) { + var box = byId('ds_box'); + var val = obj.ds_parFunc ? obj.ds_parFunc(obj.value) : obj.value; + + clearTimeout(obj.ds_dosearch); + obj.ds_dosearch = null; + + // hide the ds_box div + if(val.length < 2) { + box.style.top = '-500px'; + setContent(box, tag('b', 'Loading...')); + obj.ds_selectedId = 0; + return; + } + + // position the div + var ddx=0; + var ddy=obj.offsetHeight; + var o = obj; + do { + ddx += o.offsetLeft; + ddy += o.offsetTop; + } while(o = o.offsetParent); + + box.style.position = 'absolute'; + box.style.left = ddx+'px'; + box.style.top = ddy+'px'; + box.style.width = obj.offsetWidth+'px'; + + // perform search + ajax(obj.ds_searchURL + encodeURIComponent(val), function(hr) { + dsResults(hr, obj); + }); +} + +function dsResults(hr, obj) { + var lst = hr.responseXML.getElementsByTagName('item'); + var box = byId('ds_box'); + if(lst.length < 1) { + setContent(box, tag('b', 'No results...')); + obj.selectedId = 0; + return; + } + + var tb = tag('tbody', null); + for(var i=0; i<lst.length; i++) { + var id = lst[i].getAttribute('id'); + var tr = tag('tr', {id: 'ds_box_'+id, ds_itemData: lst[i]} ); + setClass(tr, 'selected', obj.selectedId == id); + + tr.onmouseover = function() { + obj.ds_selectedId = this.id.substr(7); + var l = byName(box, 'tr'); + for(var j=0; j<l.length; j++) + setClass(l[j], 'selected', l[j].id == 'ds_box_'+obj.ds_selectedId); + }; + tr.onmousedown = function() { + obj.value = obj.ds_serFunc(this.ds_itemData, obj); + if(obj.ds_returnFunc) + obj.ds_returnFunc(); + box.style.top = '-500px'; + obj.ds_selectedId = 0; + }; + + obj.ds_trFunc(lst[i], tr); + tb.appendChild(tr); + } + setContent(box, tag('table', tb)); + + if(obj.ds_selectedId != 0 && !byId('ds_box_'+obj.ds_selectedId)) + obj.ds_selectedId = 0; +} + + + + +/* V I S U A L N O V E L R E L A T I O N S (/v+/edit) */ + +function vnrLoad() { + // read the current relations + var rels = byId('vnrelations').value.split('|||'); + for(var i=0; i<rels.length && rels[0].length>1; i++) { + var rel = rels[i].split(',', 3); + vnrAdd(rel[0], rel[1], rel[2]); + } + vnrEmpty(); + + // make sure the title is up-to-date + byId('title').onchange = function() { + var l = byClass(byId('jt_box_vn_rel'), 'td', 'tc_title'); + for(i=0; i<l.length; i++) + setText(l[i], shorten(this.value, 40)); + }; + + // bind the add-link + byName(byClass(byId('relation_new'), 'td', 'tc_add')[0], 'a')[0].onclick = vnrFormAdd; + + // dropdown + dsInit(byName(byClass(byId('relation_new'), 'td', 'tc_vn')[0], 'input')[0], '/xml/vn.xml?q=', function(item, tr) { + tr.appendChild(tag('td', { style: 'text-align: right; padding-right: 5px'}, 'v'+item.getAttribute('id'))); + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); + }, function(item) { + return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue; + }, vnrFormAdd); +} + +function vnrAdd(rel, vid, title) { + var sel = tag('select', {onchange: vnrSerialize}); + var ops = byName(byClass(byId('relation_new'), 'td', 'tc_rel')[0], 'select')[0].options; + for(var i=0; i<ops.length; i++) + sel.appendChild(tag('option', {value: ops[i].value, selected: ops[i].value==rel}, getText(ops[i]))); + + byId('relation_tbl').appendChild(tag('tr', {id:'relation_tr_'+vid}, + tag('td', {'class':'tc_vn' }, 'v'+vid+':', tag('a', {href:'/v'+vid}, shorten(title, 40))), + tag('td', {'class':'tc_rel' }, 'is a ', sel, ' of'), + tag('td', {'class':'tc_title'}, shorten(byId('title').value, 40)), + tag('td', {'class':'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, 'del')) + )); + + vnrEmpty(); +} + +function vnrEmpty() { + var tbl = byId('relation_tbl'); + if(byName(tbl, 'tr').length < 1) + tbl.appendChild(tag('tr', {id:'relation_tr_none'}, tag('td', {colspan:4}, 'No relations selected.'))); + else if(byId('relation_tr_none')) + tbl.removeChild(byId('relation_tr_none')); +} + +function vnrSerialize() { + var r = []; + var trs = byName(byId('relation_tbl'), 'tr'); + for(var i=0; i<trs.length; i++) { + if(trs[i].id == 'relation_tr_none') + continue; + var rel = byName(byClass(trs[i], 'td', 'tc_rel')[0], 'select')[0]; + r[r.length] = [ + rel.options[rel.selectedIndex].value, // relation + trs[i].id.substr(12), // vid + getText(byName(byClass(trs[i], 'td', 'tc_vn')[0], 'a')[0]) // title + ].join(','); + } + byId('vnrelations').value = r.join('|||'); +} + +function vnrDel() { + var tr = this; + while(tr.nodeName.toLowerCase() != 'tr') + tr = tr.parentNode; + byId('relation_tbl').removeChild(tr); + vnrSerialize(); + vnrEmpty(); + return false; +} + +function vnrFormAdd() { + var relnew = byId('relation_new'); + var txt = byName(byClass(relnew, 'td', 'tc_vn')[0], 'input')[0]; + var sel = byName(byClass(relnew, 'td', 'tc_rel')[0], 'select')[0]; + var lnk = byName(byClass(relnew, 'td', 'tc_add')[0], 'a')[0]; + var input = txt.value; + + if(!input.match(/^v[0-9]+/)) { + alert('Visual novel textbox must start with an ID (e.g. v17)'); + return false; + } + + txt.disabled = sel.disabled = true; + txt.value = 'loading...'; + setText(lnk, 'loading...'); + + ajax('/xml/vn.xml?q='+encodeURIComponent(input), function(hr) { + txt.disabled = sel.disabled = false; + txt.value = ''; + setText(lnk, 'add'); + + var items = hr.responseXML.getElementsByTagName('item'); + if(items.length < 1) + return alert('Visual novel not found!'); + + var id = items[0].getAttribute('id'); + if(byId('relation_tr_'+id)) + return alert('This visual novel has already been selected!'); + + vnrAdd(sel.selectedIndex, id, items[0].firstChild.nodeValue); + sel.selectedIndex = 0; + vnrSerialize(); + }); + return false; +} + +if(byId('vnrelations')) + vnrLoad(); + + + + +/* R E L E A S E M E D I A (/r+/edit) */ + +var medTypes = [ ]; +function medLoad() { + // load the medTypes and clear the div + var sel = byName(byId('media_div'), 'select')[0].options; + for(var i=0; i<sel.length; i++) + medTypes[medTypes.length] = [ sel[i].value, getText(sel[i]), !hasClass(sel[i], 'noqty') ]; + setText(byId('media_div'), ''); + + // load the selected media + var med = byId('media').value.split(','); + for(var i=0; i<med.length && med[i].length > 1; i++) + medAdd(med[i].split(' ')[0], Math.floor(med[i].split(' ')[1])); + + medAdd('', 0); +} + +function medAdd(med, qty) { + var qsel = tag('select', {'class':'qty', onchange:medSerialize}, tag('option', {value:0}, '- quantity -')); + for(var i=1; i<=20; i++) + qsel.appendChild(tag('option', {value:i, selected: qty==i}, i)); + + var msel = tag('select', {'class':'medium', onchange: med == '' ? medFormAdd : medSerialize}); + if(med == '') + msel.appendChild(tag('option', {value:''}, '- medium -')); + for(var i=0; i<medTypes.length; i++) + msel.appendChild(tag('option', {value:medTypes[i][0], selected: med==medTypes[i][0]}, medTypes[i][1])); + + byId('media_div').appendChild(tag('span', qsel, msel, + med != '' ? tag('input', {type: 'button', 'class':'submit', onclick:medDel, value:'remove'}) : null + )); +} + +function medDel() { + var span = this; + while(span.nodeName.toLowerCase() != 'span') + span = span.parentNode; + byId('media_div').removeChild(span); + medSerialize(); + return false; +} + +function medFormAdd() { + var span = this; + while(span.nodeName.toLowerCase() != 'span') + span = span.parentNode; + var med = byClass(span, 'select', 'medium')[0]; + var qty = byClass(span, 'select', 'qty')[0]; + if(!med.selectedIndex) + return; + medAdd(med.options[med.selectedIndex].value, qty.options[qty.selectedIndex].value); + byId('media_div').removeChild(span); + medAdd('', 0); + medSerialize(); +} + +function medSerialize() { + var r = []; + var meds = byName(byId('media_div'), 'span'); + for(var i=0; i<meds.length-1; i++) { + var med = byClass(meds[i], 'select', 'medium')[0]; + var qty = byClass(meds[i], 'select', 'qty')[0]; + + /* correct quantity if necessary */ + if(medTypes[med.selectedIndex][2] && !qty.selectedIndex) + qty.selectedIndex = 1; + if(!medTypes[med.selectedIndex][2] && qty.selectedIndex) + qty.selectedIndex = 0; + + r[r.length] = medTypes[med.selectedIndex][0] + ' ' + qty.selectedIndex; + } + byId('media').value = r.join(','); +} + +if(byId('jt_box_rel_format')) + medLoad(); + + + + +/* V I S U A L N O V E L S C R E E N S H O T U P L O A D E R (/v+/edit) */ + +var scrRel = [ [ 0, '-- select release --' ] ]; +var scrStaticURL; +var scrUplNr = 0; + +function scrLoad() { + // get scrRel and scrStaticURL + var rel = byId('scr_rel'); + scrStaticURL = rel.className; + for(var i=0; i<rel.options.length; i++) + scrRel[scrRel.length] = [ rel.options[i].value, getText(rel.options[i]) ]; + rel.parentNode.removeChild(rel); + + // load the current screenshots + var scr = byId('screenshots').value.split(' '); + for(i=0; i<scr.length && scr[i].length>1; i++) { + var r = scr[i].split(','); + scrAdd(r[0], r[1], r[2]); + } + + scrLast(); + scrCheckStatus(); + scrSetSubmit(); +} + +function scrSetSubmit() { + var frm = byId('screenshots'); + while(frm.nodeName.toLowerCase() != 'form') + frm = frm.parentNode; + oldfunc = frm.onsubmit; + frm.onsubmit = function() { + var loading = 0; + var norelease = 0; + var l = byName(byId('scr_table'), 'tr'); + for(var i=0; i<l.length-1; i++) { + if(l[i].scr_status > 0) + loading = 1; + else if(byName(l[i], 'select')[0].selectedIndex == 0) + norelease = 1; + } + if(loading) { + alert('Please wait for the screenshots to be uploaded before submitting the form.'); + return false; + } else if(norelease) { + alert('Please select the appropriate release for every screenshot'); + return false; + } else if(oldfunc) + return oldfunc(); + }; +} + +function scrURL(id, t) { + return scrStaticURL+'/s'+t+'/'+(id%100<10?'0':'')+(id%100)+'/'+id+'.jpg'; +} + +function scrAdd(id, nsfw, rel) { + // tr.scr_status = 0: done, 1: uploading, 2: waiting for thumbnail, 3: deleted + + var tr = tag('tr', { id:'scr_tr_'+id, scr_id: id, scr_status: id?2:1, scr_rel: rel, scr_nsfw: nsfw}, + tag('td', { 'class': 'thumb'}, 'loading...'), + tag('td', + tag('b', id ? 'Fetching thumbnail...' : 'Uploading screenshot'), + tag('br', null), + id ? null : 'This can take a while, depending on the file size and your upload speed.', + tag('br', null), + id ? null : tag('a', {href:'#', onclick:scrDel}, 'cancel') + ) + ); + byId('scr_table').appendChild(tr); + scrStripe(); + return tr; +} + +function scrLast() { + if(byId('scr_last')) + byId('scr_table').removeChild(byId('scr_last')); + var full = byName(byId('scr_table'), 'tr').length >= 10; + + byId('scr_table').appendChild(tag('tr', {id:'scr_last'}, + tag('td', {'class': 'thumb'}), + full ? tag('td', + tag('b', 'Enough screenshots'), + tag('br', null), + 'The limit of 10 screenshots per visual novel has been reached. ', + 'If you want to add a new screenshot, please remove an existing one first.' + ) : tag('td', + tag('b', 'Add screenshot'), + tag('br', null), + 'Image must be smaller than 5MB and in PNG or JPEG format.', + tag('br', null), + tag('input', {name:'scr_upload', id:'scr_upload', type:'file', 'class':'text'}), + tag('br', null), + tag('input', {type:'button', value:'Upload!', 'class':'submit', onclick:scrUpload}) + ) + )); + scrStripe(); +} + +function scrStripe() { + var l = byName(byId('scr_table'), 'tr'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'odd', i%2==0); +} + +function scrCheckStatus() { + var ids = []; + var trs = byName(byId('scr_table'), 'tr'); + for(var i=0; i<trs.length-1; i++) + if(trs[i].scr_status == 2) + ids[ids.length] = 'id='+trs[i].scr_id; + if(!ids.length) + return setTimeout(scrCheckStatus, 1000); + + var ti = setTimeout(scrCheckStatus, 10000); + ajax('/xml/screenshots.xml?'+ids.join(';'), function(hr) { + var ls = hr.responseXML.getElementsByTagName('item'); + for(var i=0; i<ls.length; i++) { + var tr = byId('scr_tr_'+ls[i].getAttribute('id')); + if(!tr || ls[i].getAttribute('processed') != '1') + continue; + tr.scr_status = 0; // ready + + // image + var dim = ls[i].getAttribute('width')+'x'+ls[i].getAttribute('height'); + setContent(byName(tr, 'td')[0], + tag('a', {href: scrURL(tr.scr_id, 'f'), rel:'iv:'+dim+':edit'}, + tag('img', {src: scrURL(tr.scr_id, 't')}) + ) + ); + + // content + var rel = tag('select', {onchange: scrSerialize, 'class':'scr_relsel'}); + for(var j=0; j<scrRel.length; j++) + rel.appendChild(tag('option', {value: scrRel[j][0], selected: tr.scr_rel == scrRel[j][0]}, scrRel[j][1])); + var nsfwid = 'scr_sfw_'+tr.scr_id; + setContent(byName(tr, 'td')[1], + tag('b', 'Screenshot #'+tr.scr_id), + ' (', tag('a', {href: '#', onclick:scrDel}, 'remove'), ')', + tag('br', null), + 'Full size: '+dim, + tag('br', null), + tag('br', null), + tag('input', {type:'checkbox', onclick:scrSerialize, id:nsfwid, name:nsfwid, checked: tr.scr_nsfw>0, 'class':'scr_nsfw'}), + tag('label', {'for':nsfwid}, 'This screenshot is NSFW'), + tag('br', null), + rel + ); + } + scrSerialize(); + ivInit(); + clearTimeout(ti); + setTimeout(scrCheckStatus, 1000); + }); +} + +function scrDel(what) { + var tr = what && what.scr_status != null ? what : this; + while(tr.nodeName.toLowerCase() != 'tr') + tr = tr.parentNode; + tr.scr_status = 3; + byId('scr_table').removeChild(tr); + scrSerialize(); + scrLast(); + return false; +} + +function scrUpload() { + scrUplNr++; + + // create temporary form + var ifid = 'scr_upl_'+scrUplNr; + var frm = tag('form', {method: 'post', action:'/xml/screenshots.xml', target: ifid, enctype:'multipart/form-data'}); + var ifr = tag('iframe', {id:ifid, name:ifid, src:'about:blank', onload:scrUploadComplete}); + addBody(tag('div', {'class':'scr_uploader'}, ifr, frm)); + + // submit form and delete it + frm.appendChild(byId('scr_upload')); + frm.submit(); + frm.parentNode.removeChild(frm); + ifr.scr_tr = scrAdd(0, 0, 0); + scrLast(); + return false; +} + +function scrUploadComplete() { + var ifr = this; + var fr = window.frames[ifr.id]; + if(fr.location.href.indexOf('screenshots') < 0) + return; + + var tr = ifr.scr_tr; + if(!tr || tr.scr_status == 3) + return; + + try { + tr.scr_id = fr.window.document.getElementsByTagName('image')[0].getAttribute('id'); + } catch(e) { + tr.scr_id = -10; + } + if(tr.scr_id < 0) { + alert( + tr.scr_id == -10 ? + 'Oops! Seems like something went wrong...\n' + +'Make sure the file you\'re uploading doesn\'t exceed 5MB in size.\n' + +'If that isn\'t the problem, then please report a bug.' : + tr.scr_id == -1 ? + 'Upload failed!\nOnly JPEG or PNG images are accepted.' : + 'Upload failed!\nNo file selected, or an empty file?' + ); + return scrDel(tr); + } + + tr.id = 'scr_tr_'+tr.scr_id; + tr.scr_status = 2; + setContent(byName(tr, 'td')[1], + tag('b', 'Generating thumbnail...'), + tag('br', null), + 'Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. ', + 'Please try again later or report a bug if that is the case.' + ); + + // remove the <div> in a timeout, otherwise some browsers think the page is still loading + setTimeout(function() { ifr.parentNode.parentNode.removeChild(ifr.parentNode) }, 100); +} + +function scrSerialize() { + var r = []; + var l = byName(byId('scr_table'), 'tr'); + for(var i=0; i<l.length-1; i++) + if(l[i].scr_status == 0) + r[r.length] = [ + l[i].scr_id, + byClass(l[i], 'input', 'scr_nsfw')[0].checked ? 1 : 0, + scrRel[byClass(l[i], 'select', 'scr_relsel')[0].selectedIndex][0] + ].join(','); + byId('screenshots').value = r.join(' '); +} + +if(x('jt_box_vn_scr')) + scrLoad(); + + + + +/* V I S U A L N O V E L T A G L I N K I N G (/v+/tagmod) */ + +var tglSpoilers = [ 'neutral', 'no spoiler', 'minor spoiler', 'major spoiler' ]; + +function tglLoad() { + // tag dropdown search + dsInit(byId('tagmod_tag'), '/xml/tags.xml?q=', function(item, tr) { + tr.appendChild(tag('td', + shorten(item.firstChild.nodeValue, 40), + item.getAttribute('meta') == 'yes' ? tag('b', {'class':'grayedout'}, ' meta') : + item.getAttribute('state') == 0 ? tag('b', {'class':'grayedout'}, ' awaiting moderation') : null + )); + }, function(item) { + return item.firstChild.nodeValue; + }, tglAdd); + byId('tagmod_add').onclick = tglAdd; + + // JS'ify the voting bar and spoiler setting + tglStripe(); + var trs = byName(byId('tagtable'), 'tr'); + for(var i=0; i<trs.length; i++) { + var vote = byClass(trs[i], 'td', 'tc_myvote')[0]; + vote.tgl_vote = getText(vote)*1; + tglVoteBar(vote); + + var spoil = byClass(trs[i], 'td', 'tc_myspoil')[0]; + spoil.tgl_spoil = getText(spoil)*1+1; + setText(spoil, tglSpoilers[spoil.tgl_spoil]); + ddInit(spoil, 'tagmod', tglSpoilDD); + spoil.onclick = tglSpoilNext; + } + tglSerialize(); +} + +function tglSpoilNext() { + if(++this.tgl_spoil >= tglSpoilers.length) + this.tgl_spoil = 0; + setText(this, tglSpoilers[this.tgl_spoil]); + tglSerialize(); + ddRefresh(); +} + +function tglSpoilDD(lnk) { + var lst = tag('ul', null); + for(var i=0; i<tglSpoilers.length; i++) + lst.appendChild(tag('li', i == lnk.tgl_spoil + ? tag('i', tglSpoilers[i]) + : tag('a', {href: '#', onclick:tglSpoilSet, tgl_td:lnk, tgl_sp:i}, tglSpoilers[i]) + )); + return lst; +} + +function tglSpoilSet() { + this.tgl_td.tgl_spoil = this.tgl_sp; + setText(this.tgl_td, tglSpoilers[this.tgl_sp]); + ddHide(); + tglSerialize(); + return false; +} + +function tglVoteBar(td, vote) { + setText(td, ''); + for(var i=-3; i<=3; i++) + td.appendChild(tag('a', { + 'class':'taglvl taglvl'+i, tgl_num: i, + onmouseover:tglVoteBarSel, onmouseout:tglVoteBarSel, onclick:tglVoteBarSel + }, ' ')); + tglVoteBarSel(td, td.tgl_vote); + return false; +} + +function tglVoteBarSel(td, vote) { + // nasty trick to make this function multifunctional + if(this && this.tgl_num != null) { + var e = td || window.event; + td = this.parentNode; + vote = this.tgl_num; + if(e.type.toLowerCase() == 'click') { + td.tgl_vote = vote; + tglSerialize(); + } + if(e.type.toLowerCase() == 'mouseout') + vote = td.tgl_vote; + } + var l = byName(td, 'a'); + var num; + for(var i=0; i<l.length; i++) { + num = l[i].tgl_num; + if(num == 0) + setText(l[i], vote || '-'); + else + setClass(l[i], 'taglvlsel', num<0&&vote<=num || num>0&&vote>=num); + } +} + +function tglAdd() { + var tg = byId('tagmod_tag'); + var add = byId('tagmod_add'); + tag.disabled = add.disabled = true; + add.value = 'loading...'; + + ajax('/xml/tags.xml?q=name:'+encodeURIComponent(tg.value), function(hr) { + tg.disabled = add.disabled = false; + tg.value = ''; + add.value = 'Add tag'; + + var items = hr.responseXML.getElementsByTagName('item'); + if(items.length < 1) + return alert('Item not found!'); + if(items[0].getAttribute('meta') == 'yes') + return alert('Can\'t use meta tags here!'); + + var name = items[0].firstChild.nodeValue; + var id = items[0].getAttribute('id'); + if(byId('tgl_'+id)) + return alert('Tag is already present!'); + + var vote = tag('td', {'class':'tc_myvote', tgl_vote: 2}, ''); + tglVoteBar(vote); + var spoil = tag('td', {'class':'tc_myspoil', tgl_spoil: 0}, tglSpoilers[0]); + ddInit(spoil, 'tagmod', tglSpoilDD); + spoil.onclick = tglSpoilNext; + + byId('tagtable').appendChild(tag('tr', {id:'tgl_'+id}, + tag('td', {'class':'tc_tagname'}, tag('a', {href:'/g'+id}, name)), + vote, spoil, + tag('td', {'class':'tc_allvote'}, '-'), + tag('td', {'class':'tc_allspoil'}, '-') + )); + tglStripe(); + tglSerialize(); + }); +} + +function tglStripe() { + var l = byName(byId('tagtable'), 'tr'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'odd', i%2); +} + +function tglSerialize() { + var r = []; + var l = byName(byId('tagtable'), 'tr'); + for(var i=0; i<l.length; i++) { + var vote = byClass(l[i], 'td', 'tc_myvote')[0].tgl_vote; + if(vote != 0) + r[r.length] = [ + l[i].id.substr(4), + vote, + byClass(l[i], 'td', 'tc_myspoil')[0].tgl_spoil-1 + ].join(','); + } + byId('taglinks').value = r.join(' '); +} + +if(byId('taglinks')) + tglLoad(); + + + + +/* R E L E A S E -> V I S U A L N O V E L L I N K I N G (/r+/edit) */ + +function rvnLoad() { + var vns = byId('vn').value.split('|||'); + for(var i=0; i<vns.length && vns[i].length>1; i++) + rvnAdd(vns[i].split(',',2)[0], vns[i].split(',',2)[1]); + rvnEmpty(); + + dsInit(byId('vn_input'), '/xml/vn.xml?q=', + function(item, tr) { + tr.appendChild(tag('td', {style:'text-align: right; padding-right: 5px'}, 'v'+item.getAttribute('id'))); + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); + }, function(item) { + return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue; + }, + rvnFormAdd + ); + byId('vn_add').onclick = rvnFormAdd; +} + +function rvnAdd(id, title) { + x('vn_tbl').appendChild(tag('tr', {id:'rvn_'+id, rvn_id:id}, + tag('td', {'class':'tc_title'}, 'v'+id+':', tag('a', {href:'/v'+id}, shorten(title, 40))), + tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rvnDel}, 'remove')) + )); + rvnStripe(); + rvnEmpty(); +} + +function rvnDel() { + var tr = this; + while(tr.nodeName.toLowerCase() != 'tr') + tr = tr.parentNode; + tr.parentNode.removeChild(tr); + rvnEmpty(); + rvnSerialize(); + rvnStripe(); + return false; +} + +function rvnEmpty() { + var tbl = byId('vn_tbl'); + if(byName(tbl, 'tr').length < 1) + tbl.appendChild(tag('tr', {id:'rvn_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.'))); + else if(byId('rvn_tr_none')) + tbl.removeChild(byId('rvn_tr_none')); +} + +function rvnStripe() { + var l = byName(byId('vn_tbl'), 'tr'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'odd', i%2); +} + +function rvnFormAdd() { + var txt = byId('vn_input'); + var lnk = byId('vn_add'); + var val = txt.value; + + if(!val.match(/^v[0-9]+/)) { + alert('Visual novel textbox must start with an ID (e.g. v17)'); + return false; + } + + txt.disabled = true; + txt.value = 'loading...'; + setText(lnk, 'loading...'); + + ajax('/xml/vn.xml?q='+encodeURIComponent(val), function(hr) { + txt.disabled = false; + txt.value = ''; + setText(lnk, 'add'); + + var items = hr.responseXML.getElementsByTagName('item'); + if(items.length < 1) + return alert('Visual novel not found!'); + + var id = items[0].getAttribute('id'); + if(byId('rvn_'+id)) + return alert('VN already selected!'); + + rvnAdd(id, items[0].firstChild.nodeValue); + rvnSerialize(); + }); + return false; +} + +function rvnSerialize() { + var r = []; + var l = byName(byId('vn_tbl'), 'tr'); + for(var i=0; i<l.length; i++) + if(l[i].rvn_id) + r[r.length] = l[i].rvn_id + ',' + getText(byName(byClass(l[i], 'td', 'tc_title')[0], 'a')[0]); + byId('vn').value = r.join('|||'); +} + +if(byId('jt_box_rel_vn')) + rvnLoad(); + + + + +/* R E L E A S E -> P R O D U C E R L I N K I N G (/r+/edit) */ + +function rprLoad() { + var ps = byId('producers').value.split('|||'); + for(var i=0; i<ps.length && ps[i].length>1; i++) + rprAdd(ps[i].split(',',2)[0], ps[i].split(',',2)[1]); + rprEmpty(); + + dsInit(byId('producer_input'), '/xml/producers.xml?q=', + function(item, tr) { + tr.appendChild(tag('td', {style:'text-align: right; padding-right: 5px'}, 'p'+item.getAttribute('id'))); + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); + }, function(item) { + return 'p'+item.getAttribute('id')+':'+item.firstChild.nodeValue; + }, + rprFormAdd + ); + byId('producer_add').onclick = rprFormAdd; +} + +function rprAdd(id, name) { + x('producer_tbl').appendChild(tag('tr', {id:'rpr_'+id, rpr_id:id}, + tag('td', {'class':'tc_name'}, 'p'+id+':', tag('a', {href:'/p'+id}, shorten(name, 40))), + tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rprDel}, 'remove')) + )); + rprStripe(); + rprEmpty(); +} + +function rprDel() { + var tr = this; + while(tr.nodeName.toLowerCase() != 'tr') + tr = tr.parentNode; + tr.parentNode.removeChild(tr); + rprEmpty(); + rprSerialize(); + rprStripe(); + return false; +} + +function rprEmpty() { + var tbl = byId('producer_tbl'); + if(byName(tbl, 'tr').length < 1) + tbl.appendChild(tag('tr', {id:'rpr_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.'))); + else if(byId('rpr_tr_none')) + tbl.removeChild(byId('rpr_tr_none')); +} + +function rprStripe() { + var l = byName(byId('producer_tbl'), 'tr'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'odd', i%2); +} + +function rprFormAdd() { + var txt = byId('producer_input'); + var lnk = byId('producer_add'); + var val = txt.value; + + if(!val.match(/^p[0-9]+/)) { + alert('Producer textbox must start with an ID (e.g. p17)'); + return false; + } + + txt.disabled = true; + txt.value = 'loading...'; + setText(lnk, 'loading...'); + + ajax('/xml/producers.xml?q='+encodeURIComponent(val), function(hr) { + txt.disabled = false; + txt.value = ''; + setText(lnk, 'add'); + + var items = hr.responseXML.getElementsByTagName('item'); + if(items.length < 1) + return alert('Producer not found!'); + + var id = items[0].getAttribute('id'); + if(byId('rpr_'+id)) + return alert('Producer already selected!'); + + rprAdd(id, items[0].firstChild.nodeValue); + rprSerialize(); + }); + return false; +} + +function rprSerialize() { + var r = []; + var l = byName(byId('producer_tbl'), 'tr'); + for(var i=0; i<l.length; i++) + if(l[i].rpr_id) + r[r.length] = l[i].rpr_id + ',' + getText(byName(byClass(l[i], 'td', 'tc_name')[0], 'a')[0]); + byId('producers').value = r.join('|||'); +} + +if(byId('jt_box_rel_prod')) + rprLoad(); + + + + +/* M I S C S T U F F */ + +// search box +{ + var i = byId('sq'); + i.onfocus = function () { + if(this.value == 'search') { + this.value = ''; + this.style.fontStyle = 'normal' + } + }; + i.onblur = function () { + if(this.value.length < 1) { + this.value = 'search'; + this.style.fontStyle = 'italic' + } + }; +} + +// VN Voting (/v+) +if(byId('votesel')) { + byId('votesel').onchange = function() { + var s = this.options[this.selectedIndex].value; + if(s == 1 && !confirm( + "You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, " + +"meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played.\n" + +"Are you really sure this visual novel matches that description?")) + return; + if(s == 10 && !confirm( + "You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, " + +"meaning this is one of the best visual novels you've ever played and it's unlikely " + +"that any other game could ever be better than this one.\n" + +"It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully!")) + return; + if(s) + location.href = location.href.replace(/\.[0-9]+/, '')+'/vote?v='+s; + }; +} + +// Advanced search (/v/*, /r) +if(byId('advselect')) { + byId('advselect').onclick = function() { + var box = byId('advoptions'); + var hidden = !hasClass(box, 'hidden'); + setClass(box, 'hidden', hidden); + setText(byName(this, 'i')[0], hidden ? collapsed_icon : expanded_icon); + return false; + }; +} + +// Spoiler filters -> cookie (/v/*) +if(byId('sp_0')) { + byId('sp_0').onclick = function() { setCookie('tagspoil', 0) }; + byId('sp_1').onclick = function() { setCookie('tagspoil', 1) }; + byId('sp_2').onclick = function() { setCookie('tagspoil', 2) }; + var spoil = getCookie('tagspoil'); + byId('sp_'+(spoil == null ? 1 : spoil)).checked = true; +} + +// NSFW VN image toggle (/v+) +if(byId('nsfw_show')) { + var msg = byId('nsfw_show'); + var img = byId('nsfw_hid'); + byName(msg, 'a')[0].onclick = function() { + msg.style.display = 'none'; + img.style.display = 'block'; + return false; + }; + img.onclick = function() { + msg.style.display = 'block'; + img.style.display = 'none'; + }; +} + +// NSFW toggle for screenshots (/v+) +if(byId('nsfwhide')) { + byId('nsfwhide').onclick = function() { + var shown = 0; + var l = byName(byId('screenshots'), 'div'); + for(var i=0; i<l.length; i++) { + if(hasClass(l[i], 'nsfw')) { + var hidden = !hasClass(l[i], 'hidden'); + setClass(l[i], 'hidden', hidden); + setClass(byName(l[i], 'a')[0], 'hidden', hidden); // for the image viewer + if(!hidden) + shown++; + } else + shown++; + } + setText(byId('nsfwshown'), shown); + return false; + }; +} + +// VN Wishlist dropdown box (/v+) +if(byId('wishsel')) { + byId('wishsel').onchange = function() { + if(this.selectedIndex != 0) + location.href = location.href.replace(/\.[0-9]+/, '') + +'/wish?s='+this.options[this.selectedIndex].value; + }; +} + +// Release list dropdown box (/r+) +if(byId('listsel')) { + byId('listsel').onchange = function() { + if(this.selectedIndex != 0) + location.href = location.href.replace(/\.[0-9]+/, '') + +'/list?e='+this.options[this.selectedIndex].value; + }; +} + +// BBCode spoiler tags +{ + var l = byClass('b', 'spoiler'); + for(var i=0; i<l.length; i++) { + l[i].onmouseover = function() { setClass(this, 'spoiler', false); setClass(this, 'spoiler_shown', true) }; + l[i].onmouseout = function() { setClass(this, 'spoiler', true); setClass(this, 'spoiler_shown', false) }; + } +} + +// vndb.org domain check +if(location.hostname != 'vndb.org') { + addBody(tag('div', {id:'debug'}, + tag('h2', 'This is not VNDB!'), + 'The real VNDB is ', + tag('a', {href:'http://vndb.org/'}, 'here'), + '.' + )); +} + +// make some fields readonly when patch flag is set (/r+/edit) +if(byId('jt_box_rel_geninfo')) { + var func = function() { + byId('doujin').disabled = + byId('resolution').disabled = + byId('voiced').disabled = + byId('ani_story').disabled = + byId('ani_ero').disabled = + byId('patch').checked; + }; + func(); + byId('patch').onclick = func; +} + +// Batch edit wishlist dropdown box (/u+/wish) +if(byId('batchedit')) { + byId('batchedit').onchange = function() { + if(this.selectedIndex == 0) + return true; + var frm = this; + while(frm.nodeName.toLowerCase() != 'form') + frm = frm.parentNode; + frm.submit(); + }; +} + +// expand/collapse listings (/*/hist, /u+/posts) +if(byId('expandlist')) { + var lnk = byId('expandlist'); + setexpand = function() { + var exp = getCookie('histexpand') == 1; + setText(lnk, exp ? 'collapse' : 'expand'); + var tbl = lnk; + while(tbl.nodeName.toLowerCase() != 'table') + tbl = tbl.parentNode; + var l = byClass(tbl, 'tr', 'collapse'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'hidden', !exp); + }; + setexpand(); + lnk.onclick = function () { + setCookie('histexpand', getCookie('histexpand') == 1 ? 0 : 1); + setexpand(); + return false; + }; +} + +// collapse/expand row groups (/u+/tags, /u+/list) (limited to one table on a page) +if(byId('expandall')) { + var table = byId('expandall'); + while(table.nodeName.toLowerCase() != 'table') + table = table.parentNode; + var heads = byClass(table, 'td', 'collapse_but'); + var allhid = false; + + var alltoggle = function() { + allhid = !allhid; + var l = byClass(table, 'tr', 'collapse'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'hidden', allhid); + setText(byName(byId('expandall'), 'i')[0], allhid ? collapsed_icon : expanded_icon); + for(var i=0; i<heads.length; i++) + setText(byName(heads[i], 'i')[0], allhid ? collapsed_icon : expanded_icon); + return false; + } + byId('expandall').onclick = alltoggle; + alltoggle(); + + var singletoggle = function() { + var l = byClass(table, 'tr', 'collapse_'+this.id); + if(l.length < 1) + return; + var hid = !hasClass(l[0], 'hidden'); + for(var i=0; i<l.length; i++) + setClass(l[i], 'hidden', hid); + setText(byName(this, 'i')[0], hid ? collapsed_icon : expanded_icon); + }; + for(var i=0; i<heads.length; i++) + heads[i].onclick = singletoggle; +} + +// auto-complete tag search (/v/*) +if(byId('advselect') && byId('ti')) { + var trfunc = function(item, tr) { + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40), + item.getAttribute('meta') == 'yes' ? tag('b', {'class': 'grayedout'}, ' meta') : null, + item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' awaiting moderation') : null + )); + }; + var serfunc = function(item, obj) { + var tags = obj.value.split(/ *, */); + tags[tags.length-1] = item.firstChild.nodeValue; + return tags.join(', '); + }; + var retfunc = function() { false; }; + var parfunc = function(val) { + return (val.split(/, */))[val.split(/, */).length-1]; + }; + dsInit(byId('ti'), '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc); + dsInit(byId('te'), '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc); +} + + +// spam protection on all forms +setTimeout(function() { + for(i=1; i<document.forms.length; i++) + document.forms[i].action = document.forms[i].action.replace(/\/nospam\?/,''); +}, 500); + + diff --git a/static/f/script.js b/static/f/script.js deleted file mode 100644 index 07ad9866..00000000 --- a/static/f/script.js +++ /dev/null @@ -1,1758 +0,0 @@ -/* function/attribute prefixes: - * date -> Date selector - * dd -> dropdown - * ds -> dropdown search - * iv -> image viewer - * jt -> Javascript Tabs - * med -> Release media selector - * rl -> Release List dropdown - * rpr -> Release <-> producer linking - * rvn -> Release <-> visual novel linking - * scr -> VN screenshot uploader - * tgl -> VN tag linking - * tvs -> VN page tag spoilers - * vnr -> VN relation editor - */ -var expanded_icon = '▾'; -var collapsed_icon = '▸'; - -/* M I N I M A L J A V A S C R I P T L I B R A R Y */ - -var http_request = false; -function ajax(url, func) { - if(http_request) - http_request.abort(); - http_request = (window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest(); - if(http_request == null) - return alert("Your browser does not support the functionality this website requires."); - http_request.onreadystatechange = function() { - if(!http_request || http_request.readyState != 4 || !http_request.responseText) - return; - if(http_request.status != 200) - return alert('Whoops, error! :('); - func(http_request); - }; - url += (url.indexOf('?')>=0 ? ';' : '?')+(Math.floor(Math.random()*999)+1); - http_request.open('GET', url, true); - http_request.send(null); -} - -function setCookie(n,v) { - var date = new Date(); - date.setTime(date.getTime()+(365*24*60*60*1000)); - document.cookie = n+'='+v+'; expires='+date.toGMTString()+'; path=/'; -} -function getCookie(n) { - var l = document.cookie.split(';'); - for(var i=0; i<l.length; i++) { - var c = l[i]; - while(c.charAt(0) == ' ') - c = c.substring(1,c.length); - if(c.indexOf(n+'=') == 0) - return c.substring(n.length+1,c.length); - } - return null; -} - -function x(y) { // deprecated - return document.getElementById(y) -} -function byId(n) { - return document.getElementById(n) -} -function byName(){ - var d = arguments.length > 1 ? arguments[0] : document; - var n = arguments.length > 1 ? arguments[1] : arguments[0]; - return d.getElementsByTagName(n); -} -function byClass() { // [class], [parent, class], [tagname, class], [parent, tagname, class] - var par = typeof arguments[0] == 'object' ? arguments[0] : document; - var tag = arguments.length == 2 && typeof arguments[0] == 'string' ? arguments[0] : arguments.length == 3 ? arguments[1] : '*'; - var c = arguments[arguments.length-1]; - var l = byName(par, tag); - var ret = []; - for(var i=0; i<l.length; i++) - if(hasClass(l[i], c)) - ret[ret.length] = l[i]; - return ret; -} - -/* wrapper around DOM element creation - * tag('string') -> createTextNode - * tag('tagname', tag(), 'string', ..) -> createElement(), appendChild(), .. - * tag('tagname', { class: 'meh', title: 'Title' }) -> createElement(), setAttribute().. - * tag('tagname', { <attributes> }, <elements>) -> create, setattr, append */ -function tag() { - if(arguments.length == 1) - return typeof arguments[0] != 'object' ? document.createTextNode(arguments[0]) : arguments[0]; - var el = typeof document.createElementNS != 'undefined' - ? document.createElementNS('http://www.w3.org/1999/xhtml', arguments[0]) - : document.createElement(arguments[0]); - for(var i=1; i<arguments.length; i++) { - if(arguments[i] == null) - continue; - if(typeof arguments[i] == 'object' && !arguments[i].appendChild) { - for(attr in arguments[i]) { - if(attr == 'style') - el.setAttribute(attr, arguments[i][attr]); - else - el[ attr == 'class' ? 'className' : attr == 'for' ? 'htmlFor' : attr ] = arguments[i][attr]; - } - } else - el.appendChild(tag(arguments[i])); - } - return el; -} -function addBody(el) { - if(document.body.appendChild) - document.body.appendChild(el); - else if(document.documentElement.appendChild) - document.documentElement.appendChild(el); - else if(document.appendChild) - document.appendChild(el); -} -function setContent() { - setText(arguments[0], ''); - for(var i=1; i<arguments.length; i++) - arguments[0].appendChild(tag(arguments[i])); -} -function getText(obj) { - return obj.textContent || obj.innerText || ''; -} -function setText(obj, txt) { - if(obj.textContent != null) - obj.textContent = txt; - else - obj.innerText = txt; -} - -function listClass(obj) { - var n = obj.className; - if(!n) - return []; - return n.split(/ /); -} -function hasClass(obj, c) { - var l = listClass(obj); - for(var i=0; i<l.length; i++) - if(l[i] == c) - return true; - return false; -} -function setClass(obj, c, set) { - var l = listClass(obj); - var n = []; - if(set) { - n = l; - if(!hasClass(obj, c)) - n[n.length] = c; - } else { - for(var i=0; i<l.length; i++) - if(l[i] != c) - n[n.length] = l[i]; - } - obj.className = n.join(' '); -} - -function shorten(v, l) { - return v.length > l ? v.substr(0, l-3)+'...' : v; -} - - - - -/* I M A G E V I E W E R */ - -function ivInit() { - var init = 0; - var l = byName('a'); - for(var i=0;i<l.length;i++) - if(l[i].rel.substr(0,3) == 'iv:') { - init++; - l[i].onclick = ivView; - } - if(init && !byId('iv_view')) { - addBody(tag('div', {id: 'iv_view'}, - tag('b', {id:'ivimg'}, ''), - tag('br', null), - tag('a', {href:'#', id:'ivfull'}, ''), - tag('a', {href:'#', onclick: ivClose, id:'ivclose'}, 'close'), - tag('a', {href:'#', onclick: ivView, id:'ivprev'}, '« previous'), - tag('a', {href:'#', onclick: ivView, id:'ivnext'}, 'next »') - )); - addBody(tag('b', {id:'ivimgload'}, 'Loading...')); - } -} - -function ivView(what) { - what = what && what.rel ? what : this; - var u = what.href; - var opt = what.rel.split(':'); - var view = byId('iv_view'); - var next = byId('ivnext'); - var prev = byId('ivprev'); - var full = byId('ivfull'); - - // fix prev/next links (if any) - if(opt[2]) { - var ol = byName('a'); - var l=[]; - for(i=0;i<ol.length;i++) - if(ol[i].rel.substr(0,3) == 'iv:' && ol[i].rel.indexOf(':'+opt[2]) > 4 && !hasClass(ol[i], 'hidden') && ol[i].id != 'ivprev' && ol[i].id != 'ivnext') - l[l.length] = ol[i]; - for(i=0;i<l.length;i++) - if(l[i].href == u) { - next.style.visibility = l[i+1] ? 'visible' : 'hidden'; - next.href = l[i+1] ? l[i+1].href : '#'; - next.rel = l[i+1] ? l[i+1].rel : ''; - prev.style.visibility = l[i-1] ? 'visible' : 'hidden'; - prev.href = l[i-1] ? l[i-1].href : '#'; - prev.rel = l[i-1] ? l[i-1].rel : ''; - } - } else - next.style.visibility = prev.style.visibility = 'hidden'; - - // calculate dimensions - var w = Math.floor(opt[1].split('x')[0]); - var h = Math.floor(opt[1].split('x')[1]); - var ww = typeof(window.innerWidth) == 'number' ? window.innerWidth : document.documentElement.clientWidth; - var wh = typeof(window.innerHeight) == 'number' ? window.innerHeight : document.documentElement.clientHeight; - var st = typeof(window.pageYOffset) == 'number' ? window.pageYOffset : document.body && document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop; - if(w+100 > ww || h+70 > wh) { - full.href = u; - setText(full, w+'x'+h); - full.style.visibility = 'visible'; - if(w/h > ww/wh) { // width++ - h *= (ww-100)/w; - w = ww-100; - } else { // height++ - w *= (wh-70)/h; - h = wh-70; - } - } else - full.style.visibility = 'hidden'; - var dw = w; - var dh = h+20; - dw = dw < 200 ? 200 : dw; - - // update document - view.style.display = 'block'; - setContent(byId('ivimg'), tag('img', {src:u, onclick:ivClose, - onload: function() { byId('ivimgload').style.top='-400px'; }, - style: 'width: '+w+'px; height: '+h+'px' - })); - view.style.width = dw+'px'; - view.style.height = dh+'px'; - view.style.left = ((ww - dw) / 2 - 10)+'px'; - view.style.top = ((wh - dh) / 2 + st - 20)+'px'; - byId('ivimgload').style.left = ((ww - 100) / 2 - 10)+'px'; - byId('ivimgload').style.top = ((wh - 20) / 2 + st)+'px'; - return false; -} - -function ivClose() { - byId('iv_view').style.display = 'none'; - byId('iv_view').style.top = '-5000px'; - byId('ivimgload').style.top = '-400px'; - setText(byId('ivimg'), ''); - return false; -} - -ivInit(); - - - - -/* D R O P D O W N */ - -function ddInit(obj, align, contents) { - obj.dd_align = align; // see ddRefresh for details - obj.dd_contents = contents; - document.onmousemove = ddMouseMove; - document.onscroll = ddHide; - if(!byId('dd_box')) - addBody(tag('div', {id:'dd_box', dd_used: false})); -} - -function ddHide() { - var box = byId('dd_box'); - setText(box, ''); - box.style.left = '-500px'; - box.dd_used = false; - box.dd_lnk = null; -} - -function ddMouseMove(e) { - e = e || window.event; - var lnk = e.target || e.srcElement; - while(lnk && (lnk.nodeType == 3 || !lnk.dd_align)) - lnk = lnk.parentNode; - var box = byId('dd_box'); - if(!box.dd_used && !lnk) - return; - - if(box.dd_used) { - var mouseX = e.pageX || (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft); - var mouseY = e.pageY || (e.clientY + document.body.scrollTop + document.documentElement.scrollTop); - if((mouseX < ddx-10 || mouseX > ddx+box.offsetWidth+10 || mouseY < ddy-10 || mouseY > ddy+box.offsetHeight+10) - || (lnk && lnk == box.dd_lnk)) - ddHide(); - } - - if(!box.dd_used && lnk) { - box.dd_lnk = lnk; - box.dd_used = true; - if(!ddRefresh()) - ddHide(); - } -} - -function ddRefresh() { - var box = byId('dd_box'); - if(!box.dd_used) - return false; - var lnk = box.dd_lnk; - var content = lnk.dd_contents(lnk, box); - if(content == null) - return false; - setContent(box, content); - - var o = lnk; - ddx = ddy = 0; - do { - ddx += o.offsetLeft; - ddy += o.offsetTop; - } while(o = o.offsetParent); - - if(lnk.dd_align == 'left') - ddx -= box.offsetWidth; - if(lnk.dd_align == 'tagmod') - ddx += lnk.offsetWidth-35; - box.style.left = ddx+'px'; - box.style.top = ddy+'px'; - return true; -} - - -// release list dropdown on VN pages - -var rstat = [ 'Unknown', 'Pending', 'Obtained', 'On loan', 'Deleted' ]; -var vstat = [ 'Unknown', 'Playing', 'Finished', 'Stalled', 'Dropped' ]; -function rlDropDown(lnk) { - var relid = lnk.id.substr(6); - var st = getText(lnk).split(' / '); - if(st[0].indexOf('loading') >= 0) - return null; - - var rs = tag('ul', tag('li', tag('b', 'Release status'))); - var vs = tag('ul', tag('li', tag('b', 'Play status'))); - for(var i=0;i<rstat.length;i++) { - if(st[0] && st[0].indexOf(rstat[i]) >= 0) - rs.appendChild(tag('li', tag('i', rstat[i]))); - else - rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+i, onclick:rlMod}, rstat[i]))); - } - for(var i=0;i<vstat.length;i++) { - if(st[0] && st[0].indexOf(vstat[i]) >= 0) - vs.appendChild(tag('li', tag('i', vstat[i]))); - else - vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+i, onclick:rlMod}, vstat[i]))); - } - - return tag('div', {'class':'vrdd'}, rs, vs, st[0] == '--' ? null : - tag('ul', {'class':'full'}, tag('li', tag('a', {href:'#', rl_rid: relid, rl_act:'del', onclick:rlMod}, 'Remove from VN List'))) - ); -} - -function rlMod() { - var lnk = byId('rlsel_'+this.rl_rid); - ddHide(); - setContent(lnk, tag('b', {'class': 'patch'}, 'loading...')); - ajax('/xml/rlist.xml?id='+this.rl_rid+';e='+this.rl_act, function(hr) { - // TODO: get rid of innerHTML here... - lnk.innerHTML = hr.responseXML.getElementsByTagName('rlist')[0].firstChild.nodeValue; - }); - return false; -} - -{ - var l = byClass('a', 'vnrlsel'); - for(var i=0;i<l.length;i++) - ddInit(l[i], 'left', rlDropDown); -} - - - - -/* J A V A S C R I P T T A B S */ - -function jtInit() { - if(!byId('jt_select')) - return; - var sel = ''; - var first = ''; - var l = byName(byId('jt_select'), 'a'); - if(l.length < 1) - return; - for(var i=0; i<l.length; i++) { - l[i].onclick = jtSel; - if(!first) - first = l[i].id; - if(location.hash && l[i].id == 'jt_sel_'+location.hash.substr(1)) - sel = l[i].id; - } - if(!sel) - sel = first; - jtSel(sel, 1); -} - -function jtSel(which, nolink) { - which = typeof(which) == 'string' ? which : which && which.id ? which.id : this.id; - which = which.substr(7); - - var l = byName(byId('jt_select'), 'a'); - for(var i=0;i<l.length;i++) { - var name = l[i].id.substr(7); - if(name != 'all') - byId('jt_box_'+name).style.display = name == which || which == 'all' ? 'block' : 'none'; - var tab = l[i].parentNode; - setClass(tab, 'tabselected', name == which); - } - - if(!nolink) - location.href = '#'+which; - return false; -} - -jtInit(); - - - - -/* V N P A G E T A G S P O I L E R S */ - -function tvsInit() { - if(!byId('tagops')) - return; - var l = byName(byId('tagops'), 'a'); - for(var i=0;i<l.length; i++) - l[i].onclick = tvsClick; - tvsSet(getCookie('tagspoil'), true); -} - -function tvsClick() { - var sel; - var l = byName(byId('tagops'), 'a'); - for(var i=0; i<l.length; i++) - if(l[i] == this) { - if(i < 3) { - tvsSet(i, null); - setCookie('tagspoil', i); - } else - tvsSet(null, i == 3 ? true : false); - } - return false; -} - -function tvsSet(lvl, lim) { - /* set/get level and limit to/from the links */ - var l = byName(byId('tagops'), 'a'); - for(var i=0; i<l.length; i++) { - if(i < 3) { /* spoiler level */ - if(lvl != null) - setClass(l[i], 'tsel', i == lvl); - if(lvl == null && hasClass(l[i], 'tsel')) - lvl = i; - } else { /* display limit (3 = summary) */ - if(lim != null) - setClass(l[i], 'tsel', lim == (i == 3)); - if(lim == null && hasClass(l[i], 'tsel')) - lim = i == 3; - } - } - - /* update tag visibility */ - l = byName(byId('vntags'), 'span'); - lim = lim ? 15 : 999; - var s=0; - for(i=0;i<l.length;i++) { - var thislvl = l[i].className.substr(6, 1); - if(thislvl <= lvl && s < lim) { - setClass(l[i], 'hidden', false); - s++; - } else - setClass(l[i], 'hidden', true); - } - return false; -} - -tvsInit(); - - - - -/* D A T E I N P U T */ - -var months = ['January','February','March','April','May','June','July','August','September','October','November','December']; - -function dateLoad(obj) { - var val = Math.floor(obj.value) || 0; - val = [ Math.floor(val/10000), Math.floor(val/100)%100, val%100 ]; - - var year = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:0}, '-year-')); - for(var i=1980; i<=(new Date()).getFullYear()+5; i++) - year.appendChild(tag('option', {value: i, selected: i==val[0]}, i)); - year.appendChild(tag('option', {value: 9999, selected: val[0]==9999}, 'TBA')); - - var month = tag('select', {style: 'width: 100px', onchange: dateSerialize}, tag('option', {value:99}, '-month-')); - for(var i=1; i<=12; i++) - month.appendChild(tag('option', {value: i, selected: i==val[1]}, months[i-1])); - - var day = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:99}, '-day-')); - for(var i=1; i<=31; i++) - day.appendChild(tag('option', {value: i, selected: i==val[2]}, i)); - - obj.parentNode.insertBefore(tag('div', {date_obj: obj}, year, month, day), obj); -} - -function dateSerialize() { - var div = this.parentNode; - var sel = byName(div, 'select'); - var val = [ - sel[0].options[sel[0].selectedIndex].value*1, - sel[1].options[sel[1].selectedIndex].value*1, - sel[2].options[sel[2].selectedIndex].value*1 - ]; - div.date_obj.value = val[0] == 0 ? 0 : val[0] == 9999 ? 99999999 : val[0]*10000+val[1]*100+(val[1]==99?99:val[2]); -} - -{ - var l = byClass('input', 'dateinput'); - for(i=0; i<l.length; i++) - dateLoad(l[i]); -} - - - - -/* D R O P D O W N S E A R C H */ - -function dsInit(obj, url, trfunc, serfunc, retfunc, parfunc) { - obj.setAttribute('autocomplete', 'off'); - obj.onkeydown = dsKeyDown; - obj.onblur = function() { setTimeout(function () { byId('ds_box').style.top = '-500px'; }, 500) }; - obj.ds_returnFunc = retfunc; - obj.ds_trFunc = trfunc; - obj.ds_serFunc = serfunc; - obj.ds_parFunc = parfunc; - obj.ds_searchURL = url; - obj.ds_selectedId = 0; - obj.ds_dosearch = null; - if(!byId('ds_box')) - addBody(tag('div', {id: 'ds_box', style: 'position: absolute; top: -500px'}, tag('b', 'Loading...'))); -} - -function dsKeyDown(ev) { - var c = document.layers ? ev.which : document.all ? event.keyCode : ev.keyCode; - var obj = this; - - if(c == 9) // tab - return true; - - // do some processing when the enter key has been pressed - if(c == 13) { - var frm = obj; - while(frm && frm.nodeName.toLowerCase() != 'form') - frm = frm.parentNode; - if(frm) { - var oldsubmit = frm.onsubmit; - frm.onsubmit = function() { return false }; - setTimeout(function() { frm.onsubmit = oldsubmit }, 100); - } - - if(obj.ds_selectedId != 0) - obj.value = obj.ds_serFunc(byId('ds_box_'+obj.ds_selectedId).ds_itemData, obj); - if(obj.ds_returnFunc) - obj.ds_returnFunc(); - - byId('ds_box').style.top = '-500px'; - setContent(byId('ds_box'), tag('b', 'Loading...')); - obj.ds_selectedId = 0; - if(obj.ds_dosearch) { - clearTimeout(obj.ds_dosearch); - obj.ds_dosearch = null; - } - - return false; - } - - // process up/down keys - if(c == 38 || c == 40) { - var l = byName(byId('ds_box'), 'tr'); - if(l.length < 1) - return true; - - // get new selected id - if(obj.ds_selectedId == 0) { - if(c == 38) // up - obj.ds_selectedId = l[l.length-1].id.substr(7); - else - obj.ds_selectedId = l[0].id.substr(7); - } else { - var sel = null; - for(var i=0; i<l.length; i++) - if(l[i].id == 'ds_box_'+obj.ds_selectedId) { - if(c == 38) // up - sel = i>0 ? l[i-1] : l[l.length-1]; - else - sel = l[i+1] ? l[i+1] : l[0]; - } - obj.ds_selectedId = sel.id.substr(7); - } - - // set selected class - for(var i=0; i<l.length; i++) - setClass(l[i], 'selected', l[i].id == 'ds_box_'+obj.ds_selectedId); - return true; - } - - // perform search after a timeout - if(obj.ds_dosearch) - clearTimeout(obj.ds_dosearch); - obj.ds_dosearch = setTimeout(function() { - dsSearch(obj); - }, 500); - - return true; -} - -function dsSearch(obj) { - var box = byId('ds_box'); - var val = obj.ds_parFunc ? obj.ds_parFunc(obj.value) : obj.value; - - clearTimeout(obj.ds_dosearch); - obj.ds_dosearch = null; - - // hide the ds_box div - if(val.length < 2) { - box.style.top = '-500px'; - setContent(box, tag('b', 'Loading...')); - obj.ds_selectedId = 0; - return; - } - - // position the div - var ddx=0; - var ddy=obj.offsetHeight; - var o = obj; - do { - ddx += o.offsetLeft; - ddy += o.offsetTop; - } while(o = o.offsetParent); - - box.style.position = 'absolute'; - box.style.left = ddx+'px'; - box.style.top = ddy+'px'; - box.style.width = obj.offsetWidth+'px'; - - // perform search - ajax(obj.ds_searchURL + encodeURIComponent(val), function(hr) { - dsResults(hr, obj); - }); -} - -function dsResults(hr, obj) { - var lst = hr.responseXML.getElementsByTagName('item'); - var box = byId('ds_box'); - if(lst.length < 1) { - setContent(box, tag('b', 'No results...')); - obj.selectedId = 0; - return; - } - - var tb = tag('tbody', null); - for(var i=0; i<lst.length; i++) { - var id = lst[i].getAttribute('id'); - var tr = tag('tr', {id: 'ds_box_'+id, ds_itemData: lst[i]} ); - setClass(tr, 'selected', obj.selectedId == id); - - tr.onmouseover = function() { - obj.ds_selectedId = this.id.substr(7); - var l = byName(box, 'tr'); - for(var j=0; j<l.length; j++) - setClass(l[j], 'selected', l[j].id == 'ds_box_'+obj.ds_selectedId); - }; - tr.onmousedown = function() { - obj.value = obj.ds_serFunc(this.ds_itemData, obj); - if(obj.ds_returnFunc) - obj.ds_returnFunc(); - box.style.top = '-500px'; - obj.ds_selectedId = 0; - }; - - obj.ds_trFunc(lst[i], tr); - tb.appendChild(tr); - } - setContent(box, tag('table', tb)); - - if(obj.ds_selectedId != 0 && !byId('ds_box_'+obj.ds_selectedId)) - obj.ds_selectedId = 0; -} - - - - -/* V I S U A L N O V E L R E L A T I O N S (/v+/edit) */ - -function vnrLoad() { - // read the current relations - var rels = byId('vnrelations').value.split('|||'); - for(var i=0; i<rels.length && rels[0].length>1; i++) { - var rel = rels[i].split(',', 3); - vnrAdd(rel[0], rel[1], rel[2]); - } - vnrEmpty(); - - // make sure the title is up-to-date - byId('title').onchange = function() { - var l = byClass(byId('jt_box_vn_rel'), 'td', 'tc_title'); - for(i=0; i<l.length; i++) - setText(l[i], shorten(this.value, 40)); - }; - - // bind the add-link - byName(byClass(byId('relation_new'), 'td', 'tc_add')[0], 'a')[0].onclick = vnrFormAdd; - - // dropdown - dsInit(byName(byClass(byId('relation_new'), 'td', 'tc_vn')[0], 'input')[0], '/xml/vn.xml?q=', function(item, tr) { - tr.appendChild(tag('td', { style: 'text-align: right; padding-right: 5px'}, 'v'+item.getAttribute('id'))); - tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); - }, function(item) { - return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue; - }, vnrFormAdd); -} - -function vnrAdd(rel, vid, title) { - var sel = tag('select', {onchange: vnrSerialize}); - var ops = byName(byClass(byId('relation_new'), 'td', 'tc_rel')[0], 'select')[0].options; - for(var i=0; i<ops.length; i++) - sel.appendChild(tag('option', {value: ops[i].value, selected: ops[i].value==rel}, getText(ops[i]))); - - byId('relation_tbl').appendChild(tag('tr', {id:'relation_tr_'+vid}, - tag('td', {'class':'tc_vn' }, 'v'+vid+':', tag('a', {href:'/v'+vid}, shorten(title, 40))), - tag('td', {'class':'tc_rel' }, 'is a ', sel, ' of'), - tag('td', {'class':'tc_title'}, shorten(byId('title').value, 40)), - tag('td', {'class':'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, 'del')) - )); - - vnrEmpty(); -} - -function vnrEmpty() { - var tbl = byId('relation_tbl'); - if(byName(tbl, 'tr').length < 1) - tbl.appendChild(tag('tr', {id:'relation_tr_none'}, tag('td', {colspan:4}, 'No relations selected.'))); - else if(byId('relation_tr_none')) - tbl.removeChild(byId('relation_tr_none')); -} - -function vnrSerialize() { - var r = []; - var trs = byName(byId('relation_tbl'), 'tr'); - for(var i=0; i<trs.length; i++) { - if(trs[i].id == 'relation_tr_none') - continue; - var rel = byName(byClass(trs[i], 'td', 'tc_rel')[0], 'select')[0]; - r[r.length] = [ - rel.options[rel.selectedIndex].value, // relation - trs[i].id.substr(12), // vid - getText(byName(byClass(trs[i], 'td', 'tc_vn')[0], 'a')[0]) // title - ].join(','); - } - byId('vnrelations').value = r.join('|||'); -} - -function vnrDel() { - var tr = this; - while(tr.nodeName.toLowerCase() != 'tr') - tr = tr.parentNode; - byId('relation_tbl').removeChild(tr); - vnrSerialize(); - vnrEmpty(); - return false; -} - -function vnrFormAdd() { - var relnew = byId('relation_new'); - var txt = byName(byClass(relnew, 'td', 'tc_vn')[0], 'input')[0]; - var sel = byName(byClass(relnew, 'td', 'tc_rel')[0], 'select')[0]; - var lnk = byName(byClass(relnew, 'td', 'tc_add')[0], 'a')[0]; - var input = txt.value; - - if(!input.match(/^v[0-9]+/)) { - alert('Visual novel textbox must start with an ID (e.g. v17)'); - return false; - } - - txt.disabled = sel.disabled = true; - txt.value = 'loading...'; - setText(lnk, 'loading...'); - - ajax('/xml/vn.xml?q='+encodeURIComponent(input), function(hr) { - txt.disabled = sel.disabled = false; - txt.value = ''; - setText(lnk, 'add'); - - var items = hr.responseXML.getElementsByTagName('item'); - if(items.length < 1) - return alert('Visual novel not found!'); - - var id = items[0].getAttribute('id'); - if(byId('relation_tr_'+id)) - return alert('This visual novel has already been selected!'); - - vnrAdd(sel.selectedIndex, id, items[0].firstChild.nodeValue); - sel.selectedIndex = 0; - vnrSerialize(); - }); - return false; -} - -if(byId('vnrelations')) - vnrLoad(); - - - - -/* R E L E A S E M E D I A (/r+/edit) */ - -var medTypes = [ ]; -function medLoad() { - // load the medTypes and clear the div - var sel = byName(byId('media_div'), 'select')[0].options; - for(var i=0; i<sel.length; i++) - medTypes[medTypes.length] = [ sel[i].value, getText(sel[i]), !hasClass(sel[i], 'noqty') ]; - setText(byId('media_div'), ''); - - // load the selected media - var med = byId('media').value.split(','); - for(var i=0; i<med.length && med[i].length > 1; i++) - medAdd(med[i].split(' ')[0], Math.floor(med[i].split(' ')[1])); - - medAdd('', 0); -} - -function medAdd(med, qty) { - var qsel = tag('select', {'class':'qty', onchange:medSerialize}, tag('option', {value:0}, '- quantity -')); - for(var i=1; i<=20; i++) - qsel.appendChild(tag('option', {value:i, selected: qty==i}, i)); - - var msel = tag('select', {'class':'medium', onchange: med == '' ? medFormAdd : medSerialize}); - if(med == '') - msel.appendChild(tag('option', {value:''}, '- medium -')); - for(var i=0; i<medTypes.length; i++) - msel.appendChild(tag('option', {value:medTypes[i][0], selected: med==medTypes[i][0]}, medTypes[i][1])); - - byId('media_div').appendChild(tag('span', qsel, msel, - med != '' ? tag('input', {type: 'button', 'class':'submit', onclick:medDel, value:'remove'}) : null - )); -} - -function medDel() { - var span = this; - while(span.nodeName.toLowerCase() != 'span') - span = span.parentNode; - byId('media_div').removeChild(span); - medSerialize(); - return false; -} - -function medFormAdd() { - var span = this; - while(span.nodeName.toLowerCase() != 'span') - span = span.parentNode; - var med = byClass(span, 'select', 'medium')[0]; - var qty = byClass(span, 'select', 'qty')[0]; - if(!med.selectedIndex) - return; - medAdd(med.options[med.selectedIndex].value, qty.options[qty.selectedIndex].value); - byId('media_div').removeChild(span); - medAdd('', 0); - medSerialize(); -} - -function medSerialize() { - var r = []; - var meds = byName(byId('media_div'), 'span'); - for(var i=0; i<meds.length-1; i++) { - var med = byClass(meds[i], 'select', 'medium')[0]; - var qty = byClass(meds[i], 'select', 'qty')[0]; - - /* correct quantity if necessary */ - if(medTypes[med.selectedIndex][2] && !qty.selectedIndex) - qty.selectedIndex = 1; - if(!medTypes[med.selectedIndex][2] && qty.selectedIndex) - qty.selectedIndex = 0; - - r[r.length] = medTypes[med.selectedIndex][0] + ' ' + qty.selectedIndex; - } - byId('media').value = r.join(','); -} - -if(byId('jt_box_rel_format')) - medLoad(); - - - - -/* V I S U A L N O V E L S C R E E N S H O T U P L O A D E R (/v+/edit) */ - -var scrRel = [ [ 0, '-- select release --' ] ]; -var scrStaticURL; -var scrUplNr = 0; - -function scrLoad() { - // get scrRel and scrStaticURL - var rel = byId('scr_rel'); - scrStaticURL = rel.className; - for(var i=0; i<rel.options.length; i++) - scrRel[scrRel.length] = [ rel.options[i].value, getText(rel.options[i]) ]; - rel.parentNode.removeChild(rel); - - // load the current screenshots - var scr = byId('screenshots').value.split(' '); - for(i=0; i<scr.length && scr[i].length>1; i++) { - var r = scr[i].split(','); - scrAdd(r[0], r[1], r[2]); - } - - scrLast(); - scrCheckStatus(); - scrSetSubmit(); -} - -function scrSetSubmit() { - var frm = byId('screenshots'); - while(frm.nodeName.toLowerCase() != 'form') - frm = frm.parentNode; - oldfunc = frm.onsubmit; - frm.onsubmit = function() { - var loading = 0; - var norelease = 0; - var l = byName(byId('scr_table'), 'tr'); - for(var i=0; i<l.length-1; i++) { - if(l[i].scr_status > 0) - loading = 1; - else if(byName(l[i], 'select')[0].selectedIndex == 0) - norelease = 1; - } - if(loading) { - alert('Please wait for the screenshots to be uploaded before submitting the form.'); - return false; - } else if(norelease) { - alert('Please select the appropriate release for every screenshot'); - return false; - } else if(oldfunc) - return oldfunc(); - }; -} - -function scrURL(id, t) { - return scrStaticURL+'/s'+t+'/'+(id%100<10?'0':'')+(id%100)+'/'+id+'.jpg'; -} - -function scrAdd(id, nsfw, rel) { - // tr.scr_status = 0: done, 1: uploading, 2: waiting for thumbnail, 3: deleted - - var tr = tag('tr', { id:'scr_tr_'+id, scr_id: id, scr_status: id?2:1, scr_rel: rel, scr_nsfw: nsfw}, - tag('td', { 'class': 'thumb'}, 'loading...'), - tag('td', - tag('b', id ? 'Fetching thumbnail...' : 'Uploading screenshot'), - tag('br', null), - id ? null : 'This can take a while, depending on the file size and your upload speed.', - tag('br', null), - id ? null : tag('a', {href:'#', onclick:scrDel}, 'cancel') - ) - ); - byId('scr_table').appendChild(tr); - scrStripe(); - return tr; -} - -function scrLast() { - if(byId('scr_last')) - byId('scr_table').removeChild(byId('scr_last')); - var full = byName(byId('scr_table'), 'tr').length >= 10; - - byId('scr_table').appendChild(tag('tr', {id:'scr_last'}, - tag('td', {'class': 'thumb'}), - full ? tag('td', - tag('b', 'Enough screenshots'), - tag('br', null), - 'The limit of 10 screenshots per visual novel has been reached. ', - 'If you want to add a new screenshot, please remove an existing one first.' - ) : tag('td', - tag('b', 'Add screenshot'), - tag('br', null), - 'Image must be smaller than 5MB and in PNG or JPEG format.', - tag('br', null), - tag('input', {name:'scr_upload', id:'scr_upload', type:'file', 'class':'text'}), - tag('br', null), - tag('input', {type:'button', value:'Upload!', 'class':'submit', onclick:scrUpload}) - ) - )); - scrStripe(); -} - -function scrStripe() { - var l = byName(byId('scr_table'), 'tr'); - for(var i=0; i<l.length; i++) - setClass(l[i], 'odd', i%2==0); -} - -function scrCheckStatus() { - var ids = []; - var trs = byName(byId('scr_table'), 'tr'); - for(var i=0; i<trs.length-1; i++) - if(trs[i].scr_status == 2) - ids[ids.length] = 'id='+trs[i].scr_id; - if(!ids.length) - return setTimeout(scrCheckStatus, 1000); - - var ti = setTimeout(scrCheckStatus, 10000); - ajax('/xml/screenshots.xml?'+ids.join(';'), function(hr) { - var ls = hr.responseXML.getElementsByTagName('item'); - for(var i=0; i<ls.length; i++) { - var tr = byId('scr_tr_'+ls[i].getAttribute('id')); - if(!tr || ls[i].getAttribute('processed') != '1') - continue; - tr.scr_status = 0; // ready - - // image - var dim = ls[i].getAttribute('width')+'x'+ls[i].getAttribute('height'); - setContent(byName(tr, 'td')[0], - tag('a', {href: scrURL(tr.scr_id, 'f'), rel:'iv:'+dim+':edit'}, - tag('img', {src: scrURL(tr.scr_id, 't')}) - ) - ); - - // content - var rel = tag('select', {onchange: scrSerialize, 'class':'scr_relsel'}); - for(var j=0; j<scrRel.length; j++) - rel.appendChild(tag('option', {value: scrRel[j][0], selected: tr.scr_rel == scrRel[j][0]}, scrRel[j][1])); - var nsfwid = 'scr_sfw_'+tr.scr_id; - setContent(byName(tr, 'td')[1], - tag('b', 'Screenshot #'+tr.scr_id), - ' (', tag('a', {href: '#', onclick:scrDel}, 'remove'), ')', - tag('br', null), - 'Full size: '+dim, - tag('br', null), - tag('br', null), - tag('input', {type:'checkbox', onclick:scrSerialize, id:nsfwid, name:nsfwid, checked: tr.scr_nsfw>0, 'class':'scr_nsfw'}), - tag('label', {'for':nsfwid}, 'This screenshot is NSFW'), - tag('br', null), - rel - ); - } - scrSerialize(); - ivInit(); - clearTimeout(ti); - setTimeout(scrCheckStatus, 1000); - }); -} - -function scrDel(what) { - var tr = what && what.scr_status != null ? what : this; - while(tr.nodeName.toLowerCase() != 'tr') - tr = tr.parentNode; - tr.scr_status = 3; - byId('scr_table').removeChild(tr); - scrSerialize(); - scrLast(); - return false; -} - -function scrUpload() { - scrUplNr++; - - // create temporary form - var ifid = 'scr_upl_'+scrUplNr; - var frm = tag('form', {method: 'post', action:'/xml/screenshots.xml', target: ifid, enctype:'multipart/form-data'}); - var ifr = tag('iframe', {id:ifid, name:ifid, src:'about:blank', onload:scrUploadComplete}); - addBody(tag('div', {'class':'scr_uploader'}, ifr, frm)); - - // submit form and delete it - frm.appendChild(byId('scr_upload')); - frm.submit(); - frm.parentNode.removeChild(frm); - ifr.scr_tr = scrAdd(0, 0, 0); - scrLast(); - return false; -} - -function scrUploadComplete() { - var ifr = this; - var fr = window.frames[ifr.id]; - if(fr.location.href.indexOf('screenshots') < 0) - return; - - var tr = ifr.scr_tr; - if(!tr || tr.scr_status == 3) - return; - - try { - tr.scr_id = fr.window.document.getElementsByTagName('image')[0].getAttribute('id'); - } catch(e) { - tr.scr_id = -10; - } - if(tr.scr_id < 0) { - alert( - tr.scr_id == -10 ? - 'Oops! Seems like something went wrong...\n' - +'Make sure the file you\'re uploading doesn\'t exceed 5MB in size.\n' - +'If that isn\'t the problem, then please report a bug.' : - tr.scr_id == -1 ? - 'Upload failed!\nOnly JPEG or PNG images are accepted.' : - 'Upload failed!\nNo file selected, or an empty file?' - ); - return scrDel(tr); - } - - tr.id = 'scr_tr_'+tr.scr_id; - tr.scr_status = 2; - setContent(byName(tr, 'td')[1], - tag('b', 'Generating thumbnail...'), - tag('br', null), - 'Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. ', - 'Please try again later or report a bug if that is the case.' - ); - - // remove the <div> in a timeout, otherwise some browsers think the page is still loading - setTimeout(function() { ifr.parentNode.parentNode.removeChild(ifr.parentNode) }, 100); -} - -function scrSerialize() { - var r = []; - var l = byName(byId('scr_table'), 'tr'); - for(var i=0; i<l.length-1; i++) - if(l[i].scr_status == 0) - r[r.length] = [ - l[i].scr_id, - byClass(l[i], 'input', 'scr_nsfw')[0].checked ? 1 : 0, - scrRel[byClass(l[i], 'select', 'scr_relsel')[0].selectedIndex][0] - ].join(','); - byId('screenshots').value = r.join(' '); -} - -if(x('jt_box_vn_scr')) - scrLoad(); - - - - -/* V I S U A L N O V E L T A G L I N K I N G (/v+/tagmod) */ - -var tglSpoilers = [ 'neutral', 'no spoiler', 'minor spoiler', 'major spoiler' ]; - -function tglLoad() { - // tag dropdown search - dsInit(byId('tagmod_tag'), '/xml/tags.xml?q=', function(item, tr) { - tr.appendChild(tag('td', - shorten(item.firstChild.nodeValue, 40), - item.getAttribute('meta') == 'yes' ? tag('b', {'class':'grayedout'}, ' meta') : - item.getAttribute('state') == 0 ? tag('b', {'class':'grayedout'}, ' awaiting moderation') : null - )); - }, function(item) { - return item.firstChild.nodeValue; - }, tglAdd); - byId('tagmod_add').onclick = tglAdd; - - // JS'ify the voting bar and spoiler setting - tglStripe(); - var trs = byName(byId('tagtable'), 'tr'); - for(var i=0; i<trs.length; i++) { - var vote = byClass(trs[i], 'td', 'tc_myvote')[0]; - vote.tgl_vote = getText(vote)*1; - tglVoteBar(vote); - - var spoil = byClass(trs[i], 'td', 'tc_myspoil')[0]; - spoil.tgl_spoil = getText(spoil)*1+1; - setText(spoil, tglSpoilers[spoil.tgl_spoil]); - ddInit(spoil, 'tagmod', tglSpoilDD); - spoil.onclick = tglSpoilNext; - } - tglSerialize(); -} - -function tglSpoilNext() { - if(++this.tgl_spoil >= tglSpoilers.length) - this.tgl_spoil = 0; - setText(this, tglSpoilers[this.tgl_spoil]); - tglSerialize(); - ddRefresh(); -} - -function tglSpoilDD(lnk) { - var lst = tag('ul', null); - for(var i=0; i<tglSpoilers.length; i++) - lst.appendChild(tag('li', i == lnk.tgl_spoil - ? tag('i', tglSpoilers[i]) - : tag('a', {href: '#', onclick:tglSpoilSet, tgl_td:lnk, tgl_sp:i}, tglSpoilers[i]) - )); - return lst; -} - -function tglSpoilSet() { - this.tgl_td.tgl_spoil = this.tgl_sp; - setText(this.tgl_td, tglSpoilers[this.tgl_sp]); - ddHide(); - tglSerialize(); - return false; -} - -function tglVoteBar(td, vote) { - setText(td, ''); - for(var i=-3; i<=3; i++) - td.appendChild(tag('a', { - 'class':'taglvl taglvl'+i, tgl_num: i, - onmouseover:tglVoteBarSel, onmouseout:tglVoteBarSel, onclick:tglVoteBarSel - }, ' ')); - tglVoteBarSel(td, td.tgl_vote); - return false; -} - -function tglVoteBarSel(td, vote) { - // nasty trick to make this function multifunctional - if(this && this.tgl_num != null) { - var e = td || window.event; - td = this.parentNode; - vote = this.tgl_num; - if(e.type.toLowerCase() == 'click') { - td.tgl_vote = vote; - tglSerialize(); - } - if(e.type.toLowerCase() == 'mouseout') - vote = td.tgl_vote; - } - var l = byName(td, 'a'); - var num; - for(var i=0; i<l.length; i++) { - num = l[i].tgl_num; - if(num == 0) - setText(l[i], vote || '-'); - else - setClass(l[i], 'taglvlsel', num<0&&vote<=num || num>0&&vote>=num); - } -} - -function tglAdd() { - var tg = byId('tagmod_tag'); - var add = byId('tagmod_add'); - tag.disabled = add.disabled = true; - add.value = 'loading...'; - - ajax('/xml/tags.xml?q=name:'+encodeURIComponent(tg.value), function(hr) { - tg.disabled = add.disabled = false; - tg.value = ''; - add.value = 'Add tag'; - - var items = hr.responseXML.getElementsByTagName('item'); - if(items.length < 1) - return alert('Item not found!'); - if(items[0].getAttribute('meta') == 'yes') - return alert('Can\'t use meta tags here!'); - - var name = items[0].firstChild.nodeValue; - var id = items[0].getAttribute('id'); - if(byId('tgl_'+id)) - return alert('Tag is already present!'); - - var vote = tag('td', {'class':'tc_myvote', tgl_vote: 2}, ''); - tglVoteBar(vote); - var spoil = tag('td', {'class':'tc_myspoil', tgl_spoil: 0}, tglSpoilers[0]); - ddInit(spoil, 'tagmod', tglSpoilDD); - spoil.onclick = tglSpoilNext; - - byId('tagtable').appendChild(tag('tr', {id:'tgl_'+id}, - tag('td', {'class':'tc_tagname'}, tag('a', {href:'/g'+id}, name)), - vote, spoil, - tag('td', {'class':'tc_allvote'}, '-'), - tag('td', {'class':'tc_allspoil'}, '-') - )); - tglStripe(); - tglSerialize(); - }); -} - -function tglStripe() { - var l = byName(byId('tagtable'), 'tr'); - for(var i=0; i<l.length; i++) - setClass(l[i], 'odd', i%2); -} - -function tglSerialize() { - var r = []; - var l = byName(byId('tagtable'), 'tr'); - for(var i=0; i<l.length; i++) { - var vote = byClass(l[i], 'td', 'tc_myvote')[0].tgl_vote; - if(vote != 0) - r[r.length] = [ - l[i].id.substr(4), - vote, - byClass(l[i], 'td', 'tc_myspoil')[0].tgl_spoil-1 - ].join(','); - } - byId('taglinks').value = r.join(' '); -} - -if(byId('taglinks')) - tglLoad(); - - - - -/* R E L E A S E -> V I S U A L N O V E L L I N K I N G (/r+/edit) */ - -function rvnLoad() { - var vns = byId('vn').value.split('|||'); - for(var i=0; i<vns.length && vns[i].length>1; i++) - rvnAdd(vns[i].split(',',2)[0], vns[i].split(',',2)[1]); - rvnEmpty(); - - dsInit(byId('vn_input'), '/xml/vn.xml?q=', - function(item, tr) { - tr.appendChild(tag('td', {style:'text-align: right; padding-right: 5px'}, 'v'+item.getAttribute('id'))); - tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); - }, function(item) { - return 'v'+item.getAttribute('id')+':'+item.firstChild.nodeValue; - }, - rvnFormAdd - ); - byId('vn_add').onclick = rvnFormAdd; -} - -function rvnAdd(id, title) { - x('vn_tbl').appendChild(tag('tr', {id:'rvn_'+id, rvn_id:id}, - tag('td', {'class':'tc_title'}, 'v'+id+':', tag('a', {href:'/v'+id}, shorten(title, 40))), - tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rvnDel}, 'remove')) - )); - rvnStripe(); - rvnEmpty(); -} - -function rvnDel() { - var tr = this; - while(tr.nodeName.toLowerCase() != 'tr') - tr = tr.parentNode; - tr.parentNode.removeChild(tr); - rvnEmpty(); - rvnSerialize(); - rvnStripe(); - return false; -} - -function rvnEmpty() { - var tbl = byId('vn_tbl'); - if(byName(tbl, 'tr').length < 1) - tbl.appendChild(tag('tr', {id:'rvn_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.'))); - else if(byId('rvn_tr_none')) - tbl.removeChild(byId('rvn_tr_none')); -} - -function rvnStripe() { - var l = byName(byId('vn_tbl'), 'tr'); - for(var i=0; i<l.length; i++) - setClass(l[i], 'odd', i%2); -} - -function rvnFormAdd() { - var txt = byId('vn_input'); - var lnk = byId('vn_add'); - var val = txt.value; - - if(!val.match(/^v[0-9]+/)) { - alert('Visual novel textbox must start with an ID (e.g. v17)'); - return false; - } - - txt.disabled = true; - txt.value = 'loading...'; - setText(lnk, 'loading...'); - - ajax('/xml/vn.xml?q='+encodeURIComponent(val), function(hr) { - txt.disabled = false; - txt.value = ''; - setText(lnk, 'add'); - - var items = hr.responseXML.getElementsByTagName('item'); - if(items.length < 1) - return alert('Visual novel not found!'); - - var id = items[0].getAttribute('id'); - if(byId('rvn_'+id)) - return alert('VN already selected!'); - - rvnAdd(id, items[0].firstChild.nodeValue); - rvnSerialize(); - }); - return false; -} - -function rvnSerialize() { - var r = []; - var l = byName(byId('vn_tbl'), 'tr'); - for(var i=0; i<l.length; i++) - if(l[i].rvn_id) - r[r.length] = l[i].rvn_id + ',' + getText(byName(byClass(l[i], 'td', 'tc_title')[0], 'a')[0]); - byId('vn').value = r.join('|||'); -} - -if(byId('jt_box_rel_vn')) - rvnLoad(); - - - - -/* R E L E A S E -> P R O D U C E R L I N K I N G (/r+/edit) */ - -function rprLoad() { - var ps = byId('producers').value.split('|||'); - for(var i=0; i<ps.length && ps[i].length>1; i++) - rprAdd(ps[i].split(',',2)[0], ps[i].split(',',2)[1]); - rprEmpty(); - - dsInit(byId('producer_input'), '/xml/producers.xml?q=', - function(item, tr) { - tr.appendChild(tag('td', {style:'text-align: right; padding-right: 5px'}, 'p'+item.getAttribute('id'))); - tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); - }, function(item) { - return 'p'+item.getAttribute('id')+':'+item.firstChild.nodeValue; - }, - rprFormAdd - ); - byId('producer_add').onclick = rprFormAdd; -} - -function rprAdd(id, name) { - x('producer_tbl').appendChild(tag('tr', {id:'rpr_'+id, rpr_id:id}, - tag('td', {'class':'tc_name'}, 'p'+id+':', tag('a', {href:'/p'+id}, shorten(name, 40))), - tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rprDel}, 'remove')) - )); - rprStripe(); - rprEmpty(); -} - -function rprDel() { - var tr = this; - while(tr.nodeName.toLowerCase() != 'tr') - tr = tr.parentNode; - tr.parentNode.removeChild(tr); - rprEmpty(); - rprSerialize(); - rprStripe(); - return false; -} - -function rprEmpty() { - var tbl = byId('producer_tbl'); - if(byName(tbl, 'tr').length < 1) - tbl.appendChild(tag('tr', {id:'rpr_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.'))); - else if(byId('rpr_tr_none')) - tbl.removeChild(byId('rpr_tr_none')); -} - -function rprStripe() { - var l = byName(byId('producer_tbl'), 'tr'); - for(var i=0; i<l.length; i++) - setClass(l[i], 'odd', i%2); -} - -function rprFormAdd() { - var txt = byId('producer_input'); - var lnk = byId('producer_add'); - var val = txt.value; - - if(!val.match(/^p[0-9]+/)) { - alert('Producer textbox must start with an ID (e.g. p17)'); - return false; - } - - txt.disabled = true; - txt.value = 'loading...'; - setText(lnk, 'loading...'); - - ajax('/xml/producers.xml?q='+encodeURIComponent(val), function(hr) { - txt.disabled = false; - txt.value = ''; - setText(lnk, 'add'); - - var items = hr.responseXML.getElementsByTagName('item'); - if(items.length < 1) - return alert('Producer not found!'); - - var id = items[0].getAttribute('id'); - if(byId('rpr_'+id)) - return alert('Producer already selected!'); - - rprAdd(id, items[0].firstChild.nodeValue); - rprSerialize(); - }); - return false; -} - -function rprSerialize() { - var r = []; - var l = byName(byId('producer_tbl'), 'tr'); - for(var i=0; i<l.length; i++) - if(l[i].rpr_id) - r[r.length] = l[i].rpr_id + ',' + getText(byName(byClass(l[i], 'td', 'tc_name')[0], 'a')[0]); - byId('producers').value = r.join('|||'); -} - -if(byId('jt_box_rel_prod')) - rprLoad(); - - - - -/* M I S C S T U F F */ - -// search box -{ - var i = byId('sq'); - i.onfocus = function () { - if(this.value == 'search') { - this.value = ''; - this.style.fontStyle = 'normal' - } - }; - i.onblur = function () { - if(this.value.length < 1) { - this.value = 'search'; - this.style.fontStyle = 'italic' - } - }; -} - -// VN Voting (/v+) -if(byId('votesel')) { - byId('votesel').onchange = function() { - var s = this.options[this.selectedIndex].value; - if(s == 1 && !confirm( - "You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, " - +"meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played.\n" - +"Are you really sure this visual novel matches that description?")) - return; - if(s == 10 && !confirm( - "You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, " - +"meaning this is one of the best visual novels you've ever played and it's unlikely " - +"that any other game could ever be better than this one.\n" - +"It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully!")) - return; - if(s) - location.href = location.href.replace(/\.[0-9]+/, '')+'/vote?v='+s; - }; -} - -// Advanced search (/v/*, /r) -if(byId('advselect')) { - byId('advselect').onclick = function() { - var box = byId('advoptions'); - var hidden = !hasClass(box, 'hidden'); - setClass(box, 'hidden', hidden); - setText(byName(this, 'i')[0], hidden ? collapsed_icon : expanded_icon); - return false; - }; -} - -// Spoiler filters -> cookie (/v/*) -if(byId('sp_0')) { - byId('sp_0').onclick = function() { setCookie('tagspoil', 0) }; - byId('sp_1').onclick = function() { setCookie('tagspoil', 1) }; - byId('sp_2').onclick = function() { setCookie('tagspoil', 2) }; - var spoil = getCookie('tagspoil'); - byId('sp_'+(spoil == null ? 1 : spoil)).checked = true; -} - -// NSFW VN image toggle (/v+) -if(byId('nsfw_show')) { - var msg = byId('nsfw_show'); - var img = byId('nsfw_hid'); - byName(msg, 'a')[0].onclick = function() { - msg.style.display = 'none'; - img.style.display = 'block'; - return false; - }; - img.onclick = function() { - msg.style.display = 'block'; - img.style.display = 'none'; - }; -} - -// NSFW toggle for screenshots (/v+) -if(byId('nsfwhide')) { - byId('nsfwhide').onclick = function() { - var shown = 0; - var l = byName(byId('screenshots'), 'div'); - for(var i=0; i<l.length; i++) { - if(hasClass(l[i], 'nsfw')) { - var hidden = !hasClass(l[i], 'hidden'); - setClass(l[i], 'hidden', hidden); - setClass(byName(l[i], 'a')[0], 'hidden', hidden); // for the image viewer - if(!hidden) - shown++; - } else - shown++; - } - setText(byId('nsfwshown'), shown); - return false; - }; -} - -// VN Wishlist dropdown box (/v+) -if(byId('wishsel')) { - byId('wishsel').onchange = function() { - if(this.selectedIndex != 0) - location.href = location.href.replace(/\.[0-9]+/, '') - +'/wish?s='+this.options[this.selectedIndex].value; - }; -} - -// Release list dropdown box (/r+) -if(byId('listsel')) { - byId('listsel').onchange = function() { - if(this.selectedIndex != 0) - location.href = location.href.replace(/\.[0-9]+/, '') - +'/list?e='+this.options[this.selectedIndex].value; - }; -} - -// BBCode spoiler tags -{ - var l = byClass('b', 'spoiler'); - for(var i=0; i<l.length; i++) { - l[i].onmouseover = function() { setClass(this, 'spoiler', false); setClass(this, 'spoiler_shown', true) }; - l[i].onmouseout = function() { setClass(this, 'spoiler', true); setClass(this, 'spoiler_shown', false) }; - } -} - -// vndb.org domain check -if(location.hostname != 'vndb.org') { - addBody(tag('div', {id:'debug'}, - tag('h2', 'This is not VNDB!'), - 'The real VNDB is ', - tag('a', {href:'http://vndb.org/'}, 'here'), - '.' - )); -} - -// make some fields readonly when patch flag is set (/r+/edit) -if(byId('jt_box_rel_geninfo')) { - var func = function() { - byId('doujin').disabled = - byId('resolution').disabled = - byId('voiced').disabled = - byId('ani_story').disabled = - byId('ani_ero').disabled = - byId('patch').checked; - }; - func(); - byId('patch').onclick = func; -} - -// Batch edit wishlist dropdown box (/u+/wish) -if(byId('batchedit')) { - byId('batchedit').onchange = function() { - if(this.selectedIndex == 0) - return true; - var frm = this; - while(frm.nodeName.toLowerCase() != 'form') - frm = frm.parentNode; - frm.submit(); - }; -} - -// expand/collapse listings (/*/hist, /u+/posts) -if(byId('expandlist')) { - var lnk = byId('expandlist'); - setexpand = function() { - var exp = getCookie('histexpand') == 1; - setText(lnk, exp ? 'collapse' : 'expand'); - var tbl = lnk; - while(tbl.nodeName.toLowerCase() != 'table') - tbl = tbl.parentNode; - var l = byClass(tbl, 'tr', 'collapse'); - for(var i=0; i<l.length; i++) - setClass(l[i], 'hidden', !exp); - }; - setexpand(); - lnk.onclick = function () { - setCookie('histexpand', getCookie('histexpand') == 1 ? 0 : 1); - setexpand(); - return false; - }; -} - -// collapse/expand row groups (/u+/tags, /u+/list) (limited to one table on a page) -if(byId('expandall')) { - var table = byId('expandall'); - while(table.nodeName.toLowerCase() != 'table') - table = table.parentNode; - var heads = byClass(table, 'td', 'collapse_but'); - var allhid = false; - - var alltoggle = function() { - allhid = !allhid; - var l = byClass(table, 'tr', 'collapse'); - for(var i=0; i<l.length; i++) - setClass(l[i], 'hidden', allhid); - setText(byName(byId('expandall'), 'i')[0], allhid ? collapsed_icon : expanded_icon); - for(var i=0; i<heads.length; i++) - setText(byName(heads[i], 'i')[0], allhid ? collapsed_icon : expanded_icon); - return false; - } - byId('expandall').onclick = alltoggle; - alltoggle(); - - var singletoggle = function() { - var l = byClass(table, 'tr', 'collapse_'+this.id); - if(l.length < 1) - return; - var hid = !hasClass(l[0], 'hidden'); - for(var i=0; i<l.length; i++) - setClass(l[i], 'hidden', hid); - setText(byName(this, 'i')[0], hid ? collapsed_icon : expanded_icon); - }; - for(var i=0; i<heads.length; i++) - heads[i].onclick = singletoggle; -} - -// auto-complete tag search (/v/*) -if(byId('advselect') && byId('ti')) { - var trfunc = function(item, tr) { - tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40), - item.getAttribute('meta') == 'yes' ? tag('b', {'class': 'grayedout'}, ' meta') : null, - item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' awaiting moderation') : null - )); - }; - var serfunc = function(item, obj) { - var tags = obj.value.split(/ *, */); - tags[tags.length-1] = item.firstChild.nodeValue; - return tags.join(', '); - }; - var retfunc = function() { false; }; - var parfunc = function(val) { - return (val.split(/, */))[val.split(/, */).length-1]; - }; - dsInit(byId('ti'), '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc); - dsInit(byId('te'), '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc); -} - - -// spam protection on all forms -setTimeout(function() { - for(i=1; i<document.forms.length; i++) - document.forms[i].action = document.forms[i].action.replace(/\/nospam\?/,''); -}, 500); - - diff --git a/util/jsgen.pl b/util/jsgen.pl new file mode 100755 index 00000000..d21f56c7 --- /dev/null +++ b/util/jsgen.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Cwd 'abs_path'; +eval { require JavaScript::Minifier::XS; }; + +our($ROOT, %O); +BEGIN { ($ROOT = abs_path $0) =~ s{/util/jsgen\.pl$}{}; } + + +sub jsgen { + # JavaScript::Minifier::XS doesn't correctly handle perl's unicode, + # so just do everything in raw bytes instead. + open my $JS, '<', "$ROOT/data/script.js" or die $!; + my $js = join '', <$JS>; + close $JS; + open my $NEWJS, '>', "$ROOT/static/f/script.js" or die $!; + print $NEWJS $JavaScript::Minifier::XS::VERSION ? JavaScript::Minifier::XS::minify($js) : $js; + close $NEWJS; +} + +jsgen; + diff --git a/util/vndb.pl b/util/vndb.pl index ed74a92f..609d47a8 100755 --- a/util/vndb.pl +++ b/util/vndb.pl @@ -28,6 +28,10 @@ our(%O, %S); $S{skins} = readskins(); +# automatically regenerate script.js when required and possible +checkjs(); + + # load lang.dat VNDB::L10N::loadfile(); @@ -113,3 +117,11 @@ sub readskins { return \%skins; } + +sub checkjs { + my $script = "$ROOT/static/f/script.js"; + system "$ROOT/util/jsgen.pl" if + (!-e $script && -x "$ROOT/static/f") + || (-e $script && -w $script && [stat $script]->[9] < [stat "$ROOT/data/script.js"]->[9]); +} + -- cgit v1.2.3 From 2c7b95fb3dc6bb25ac4b4171fb881f9f587bd62f Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 12:56:20 +0200 Subject: L10N/JS: Added small framework for translating the strings in JS --- data/script.js | 20 ++++++++++++++++++-- util/jsgen.pl | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/data/script.js b/data/script.js index 07ad9866..5882aaa3 100644 --- a/data/script.js +++ b/data/script.js @@ -158,6 +158,22 @@ function shorten(v, l) { return v.length > l ? v.substr(0, l-3)+'...' : v; } +/* maketext function, less powerful than the Perl equivalent (only supports [_n] and ~[~]) + * assumes that a TL structure called 'L10N_STR' is defined in the header of this file */ +var mt_curlang = getCookie('l10n') || 'en'; +function mt() { + var key = arguments[0]; + var val = L10N_STR[key][mt_curlang] || L10N_STR[key].en || key; + for(var i=1; i<arguments.length; i++) { + var expr = '[_'+i+']'; + while(val.substr(expr) >= 0) + val = val.replace(expr, arguments[i]); + } + while(val.substr('~[') >= 0 || val.substr('~]') >= 0) + val = val.replace('~[', '[').replace('~]', ']'); + return val; +} + @@ -1521,14 +1537,14 @@ if(byId('jt_box_rel_prod')) { var i = byId('sq'); i.onfocus = function () { - if(this.value == 'search') { + if(this.value == mt('_menu_emptysearch')) { this.value = ''; this.style.fontStyle = 'normal' } }; i.onblur = function () { if(this.value.length < 1) { - this.value = 'search'; + this.value = mt('_menu_emptysearch'); this.style.fontStyle = 'italic' } }; diff --git a/util/jsgen.pl b/util/jsgen.pl index d21f56c7..894fa1b9 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -2,18 +2,72 @@ use strict; use warnings; +use Encode 'encode_utf8'; use Cwd 'abs_path'; eval { require JavaScript::Minifier::XS; }; our($ROOT, %O); BEGIN { ($ROOT = abs_path $0) =~ s{/util/jsgen\.pl$}{}; } +use lib "$ROOT/lib"; +use lib "$ROOT/yawf/lib"; +use LangFile; + +# The VNDB::L10N module is not really suited to be used outside the VNDB::* +# framework, but it's the central location that defines which languages we have +# and in what order to display them. +use VNDB::L10N; + + +my $jskeys = qr{^_menu_emptysearch$}; + + +sub l10n { + # Using JSON::XS or something may be shorter and less error prone, + # although I would have less power over the output (mostly the quoting of the keys) + + my $lang = LangFile->new(read => "$ROOT/data/lang.txt"); + my @r; + push @r, 'L10N_STR = {'; + my $cur; # undef = none/excluded, 1 = awaiting first TL line, 2 = after first TL line + my %lang; + while((my $l = $lang->read())) { + my $type = shift @$l; + if($type eq 'key') { + my $key = shift @$l; + push @r, ' }' if $cur; + $cur = $key =~ $jskeys ? 1 : undef; + if($cur) { + $r[$#r] .= ',' if $r[$#r] =~ /}$/; + # let's assume key names don't trigger a reserved word in JS + $key = qq{"$key"} if $key !~ /^[a-z_][a-z0-9_]*$/i; + push @r, qq| $key: {|; + } + } + $lang{$l->[0]} = 1 if $type eq 'tl'; + if($type eq 'tl' && $cur) { + my($lang, $sync, $val) = @$l; + $val =~ s/"/\\"/g; + $val =~ s/\n/\\n/g; + $r[$#r] .= ',' if $cur == 2; + $lang = q{"$l->[0]"} if $lang =~ /^(?:as|do|if|in|is)$/; # reserved two-char words + push @r, qq| $lang: "$val"|; + $cur = 2; + } + } + push @r, ' }' if $cur; + push @r, '};'; + push @r, 'L10N_LANG = [ '.join(', ', map qq{"$_"}, VNDB::L10N::languages()).' ];'; + return join "\n", @r; +} + sub jsgen { # JavaScript::Minifier::XS doesn't correctly handle perl's unicode, # so just do everything in raw bytes instead. + my $js = encode_utf8(l10n()) . "\n\n"; open my $JS, '<', "$ROOT/data/script.js" or die $!; - my $js = join '', <$JS>; + $js .= join '', <$JS>; close $JS; open my $NEWJS, '>', "$ROOT/static/f/script.js" or die $!; print $NEWJS $JavaScript::Minifier::XS::VERSION ? JavaScript::Minifier::XS::minify($js) : $js; -- cgit v1.2.3 From de8d188a37b651a59a6460c0ead0e7aa4edab858 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 13:35:34 +0200 Subject: L10N: Extracted some common Javascript strings --- ChangeLog | 2 ++ data/lang.txt | 61 ++++++++++++++++++++++++++++++++++++++++ data/script.js | 68 ++++++++++++++++++++------------------------- lib/VNDB/Handler/Users.pm | 2 +- lib/VNDB/Util/CommonHTML.pm | 2 +- util/jsgen.pl | 8 ++++-- util/vndb.pl | 3 +- 7 files changed, 103 insertions(+), 43 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9e12388f..399a2110 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,8 @@ git - ? 'XHTML compliant' in the future (currently still has some issues here). - Improved spoiler selection on /v+/tagmod - Everything merged into one file. + - Optionally minified (using JavaScript::Minifier::XS) + - Language strings are translatable 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/lang.txt b/data/lang.txt index 22f0073d..7d4d2a67 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -695,6 +695,57 @@ en : Submit ru : Отправить +# Common javascript strings + +:_js_expand +en : expand +ru*: + +:_js_collapse +en : collapse +ru*: + +:_js_loading +en : Loading... +ru*: + +:_js_date_year +en : -year- +ru*: + +:_js_date_month +en : -month- +ru*: + +:_js_date_day +en : -day- +ru*: + +:_js_ds_noresults +en : No results... +ru*: + +:_js_iv_close +en : close +ru*: + +:_js_iv_prev +en : previous +ru*: + +:_js_iv_next +en : next +ru*: + +:_js_ds_tag_meta +en : meta +ru*: + +:_js_ds_tag_mod +en : awaiting moderation +ru*: + + ############################################################################# @@ -3213,6 +3264,16 @@ ru : Голосовать en : revoke ru : снять голос +:_vnpage_uopt_1vote +en : You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played. + Are you really sure this visual novel matches that description? +ru*: + +:_vnpage_uopt_10vote +en : You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, meaning this is one of the best visual novels you've ever played and it's unlikely that any other game could ever be better than this one. + It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully! +ru*: + :_vnpage_uopt_wishlisted en : wishlist: [_1] ru : список желаемого: [_1] diff --git a/data/script.js b/data/script.js index 5882aaa3..826b3bb2 100644 --- a/data/script.js +++ b/data/script.js @@ -163,7 +163,7 @@ function shorten(v, l) { var mt_curlang = getCookie('l10n') || 'en'; function mt() { var key = arguments[0]; - var val = L10N_STR[key][mt_curlang] || L10N_STR[key].en || key; + var val = L10N_STR[key] ? L10N_STR[key][mt_curlang] || L10N_STR[key].en : key; for(var i=1; i<arguments.length; i++) { var expr = '[_'+i+']'; while(val.substr(expr) >= 0) @@ -192,11 +192,11 @@ function ivInit() { tag('b', {id:'ivimg'}, ''), tag('br', null), tag('a', {href:'#', id:'ivfull'}, ''), - tag('a', {href:'#', onclick: ivClose, id:'ivclose'}, 'close'), - tag('a', {href:'#', onclick: ivView, id:'ivprev'}, '« previous'), - tag('a', {href:'#', onclick: ivView, id:'ivnext'}, 'next »') + tag('a', {href:'#', onclick: ivClose, id:'ivclose'}, mt('_js_iv_close')), + tag('a', {href:'#', onclick: ivView, id:'ivprev'}, '« '+mt('_js_iv_prev')), + tag('a', {href:'#', onclick: ivView, id:'ivnext'}, mt('_js_iv_next')+' »') )); - addBody(tag('b', {id:'ivimgload'}, 'Loading...')); + addBody(tag('b', {id:'ivimgload'}, mt('_js_loading'))); } } @@ -383,7 +383,7 @@ function rlDropDown(lnk) { function rlMod() { var lnk = byId('rlsel_'+this.rl_rid); ddHide(); - setContent(lnk, tag('b', {'class': 'patch'}, 'loading...')); + setContent(lnk, tag('b', {'class': 'patch'}, mt('js_loading'))); ajax('/xml/rlist.xml?id='+this.rl_rid+';e='+this.rl_act, function(hr) { // TODO: get rid of innerHTML here... lnk.innerHTML = hr.responseXML.getElementsByTagName('rlist')[0].firstChild.nodeValue; @@ -509,22 +509,20 @@ tvsInit(); /* D A T E I N P U T */ -var months = ['January','February','March','April','May','June','July','August','September','October','November','December']; - function dateLoad(obj) { var val = Math.floor(obj.value) || 0; val = [ Math.floor(val/10000), Math.floor(val/100)%100, val%100 ]; - var year = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:0}, '-year-')); + var year = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:0}, mt('_js_date_year'))); for(var i=1980; i<=(new Date()).getFullYear()+5; i++) year.appendChild(tag('option', {value: i, selected: i==val[0]}, i)); year.appendChild(tag('option', {value: 9999, selected: val[0]==9999}, 'TBA')); - var month = tag('select', {style: 'width: 100px', onchange: dateSerialize}, tag('option', {value:99}, '-month-')); + var month = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:99}, mt('_js_date_month'))); for(var i=1; i<=12; i++) - month.appendChild(tag('option', {value: i, selected: i==val[1]}, months[i-1])); + month.appendChild(tag('option', {value: i, selected: i==val[1]}, i)); - var day = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:99}, '-day-')); + var day = tag('select', {style: 'width: 70px', onchange: dateSerialize}, tag('option', {value:99}, mt('_js_date_day'))); for(var i=1; i<=31; i++) day.appendChild(tag('option', {value: i, selected: i==val[2]}, i)); @@ -565,7 +563,7 @@ function dsInit(obj, url, trfunc, serfunc, retfunc, parfunc) { obj.ds_selectedId = 0; obj.ds_dosearch = null; if(!byId('ds_box')) - addBody(tag('div', {id: 'ds_box', style: 'position: absolute; top: -500px'}, tag('b', 'Loading...'))); + addBody(tag('div', {id: 'ds_box', style: 'position: absolute; top: -500px'}, tag('b', mt('_js_loading')))); } function dsKeyDown(ev) { @@ -592,7 +590,7 @@ function dsKeyDown(ev) { obj.ds_returnFunc(); byId('ds_box').style.top = '-500px'; - setContent(byId('ds_box'), tag('b', 'Loading...')); + setContent(byId('ds_box'), tag('b', mt('_js_loading'))); obj.ds_selectedId = 0; if(obj.ds_dosearch) { clearTimeout(obj.ds_dosearch); @@ -652,7 +650,7 @@ function dsSearch(obj) { // hide the ds_box div if(val.length < 2) { box.style.top = '-500px'; - setContent(box, tag('b', 'Loading...')); + setContent(box, tag('b', mt('_js_loading'))); obj.ds_selectedId = 0; return; } @@ -681,7 +679,7 @@ function dsResults(hr, obj) { var lst = hr.responseXML.getElementsByTagName('item'); var box = byId('ds_box'); if(lst.length < 1) { - setContent(box, tag('b', 'No results...')); + setContent(box, tag('b', mt('_js_ds_noresults'))); obj.selectedId = 0; return; } @@ -811,8 +809,8 @@ function vnrFormAdd() { } txt.disabled = sel.disabled = true; - txt.value = 'loading...'; - setText(lnk, 'loading...'); + txt.value = mt('_js_loading'); + setText(lnk, mt('_js_loading')); ajax('/xml/vn.xml?q='+encodeURIComponent(input), function(hr) { txt.disabled = sel.disabled = false; @@ -981,7 +979,7 @@ function scrAdd(id, nsfw, rel) { // tr.scr_status = 0: done, 1: uploading, 2: waiting for thumbnail, 3: deleted var tr = tag('tr', { id:'scr_tr_'+id, scr_id: id, scr_status: id?2:1, scr_rel: rel, scr_nsfw: nsfw}, - tag('td', { 'class': 'thumb'}, 'loading...'), + tag('td', { 'class': 'thumb'}, mt('_js_loading')), tag('td', tag('b', id ? 'Fetching thumbnail...' : 'Uploading screenshot'), tag('br', null), @@ -1175,8 +1173,8 @@ function tglLoad() { dsInit(byId('tagmod_tag'), '/xml/tags.xml?q=', function(item, tr) { tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40), - item.getAttribute('meta') == 'yes' ? tag('b', {'class':'grayedout'}, ' meta') : - item.getAttribute('state') == 0 ? tag('b', {'class':'grayedout'}, ' awaiting moderation') : null + item.getAttribute('meta') == 'yes' ? tag('b', {'class':'grayedout'}, ' '+mt('_js_ds_tag_meta')) : + item.getAttribute('state') == 0 ? tag('b', {'class':'grayedout'}, ' '+mt('_js_ds_tag_mod')) : null )); }, function(item) { return item.firstChild.nodeValue; @@ -1265,7 +1263,7 @@ function tglAdd() { var tg = byId('tagmod_tag'); var add = byId('tagmod_add'); tag.disabled = add.disabled = true; - add.value = 'loading...'; + add.value = mt('_js_loading'); ajax('/xml/tags.xml?q=name:'+encodeURIComponent(tg.value), function(hr) { tg.disabled = add.disabled = false; @@ -1392,8 +1390,8 @@ function rvnFormAdd() { } txt.disabled = true; - txt.value = 'loading...'; - setText(lnk, 'loading...'); + txt.value = mt('_js_loading'); + setText(lnk, mt('_js_loading')); ajax('/xml/vn.xml?q='+encodeURIComponent(val), function(hr) { txt.disabled = false; @@ -1494,8 +1492,8 @@ function rprFormAdd() { } txt.disabled = true; - txt.value = 'loading...'; - setText(lnk, 'loading...'); + txt.value = mt('_js_loading'); + setText(lnk, mt('_js_loading')); ajax('/xml/producers.xml?q='+encodeURIComponent(val), function(hr) { txt.disabled = false; @@ -1554,16 +1552,9 @@ if(byId('jt_box_rel_prod')) if(byId('votesel')) { byId('votesel').onchange = function() { var s = this.options[this.selectedIndex].value; - if(s == 1 && !confirm( - "You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, " - +"meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played.\n" - +"Are you really sure this visual novel matches that description?")) + if(s == 1 && !confirm(mt('_vnpage_uopt_1vote'))) return; - if(s == 10 && !confirm( - "You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, " - +"meaning this is one of the best visual novels you've ever played and it's unlikely " - +"that any other game could ever be better than this one.\n" - +"It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully!")) + if(s == 10 && !confirm(mt('_vnpage_uopt_10vote'))) return; if(s) location.href = location.href.replace(/\.[0-9]+/, '')+'/vote?v='+s; @@ -1653,6 +1644,7 @@ if(byId('listsel')) { } // vndb.org domain check +// (let's just keep this untranslatable, nobody cares anyway ^^) if(location.hostname != 'vndb.org') { addBody(tag('div', {id:'debug'}, tag('h2', 'This is not VNDB!'), @@ -1693,7 +1685,7 @@ if(byId('expandlist')) { var lnk = byId('expandlist'); setexpand = function() { var exp = getCookie('histexpand') == 1; - setText(lnk, exp ? 'collapse' : 'expand'); + setText(lnk, mt(exp ? '_js_collapse' : '_js_expand')); var tbl = lnk; while(tbl.nodeName.toLowerCase() != 'table') tbl = tbl.parentNode; @@ -1747,8 +1739,8 @@ if(byId('expandall')) { if(byId('advselect') && byId('ti')) { var trfunc = function(item, tr) { tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40), - item.getAttribute('meta') == 'yes' ? tag('b', {'class': 'grayedout'}, ' meta') : null, - item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' awaiting moderation') : null + item.getAttribute('meta') == 'yes' ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_tag_meta')) : null, + item.getAttribute('state') == 0 ? tag('b', {'class': 'grayedout'}, ' '+mt('_js_ds_tag_mod')) : null )); }; var serfunc = function(item, obj) { diff --git a/lib/VNDB/Handler/Users.pm b/lib/VNDB/Handler/Users.pm index 2708f66e..1a4b993b 100644 --- a/lib/VNDB/Handler/Users.pm +++ b/lib/VNDB/Handler/Users.pm @@ -386,7 +386,7 @@ sub posts { [ '' ], [ '' ], [ mt '_uposts_col_date' ], - sub { td; a href => '#', id => 'expandlist', 'expand'; txt mt '_uposts_col_title'; end; } + sub { td; a href => '#', id => 'expandlist', mt '_js_expand'; txt mt '_uposts_col_title'; end; } ], row => sub { my($s, $n, $l) = @_; diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index e0fe65d2..7e98159a 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -501,7 +501,7 @@ sub htmlHistory { sub { td colspan => 2, class => 'tc1', mt '_hist_col_rev' }, [ mt '_hist_col_date' ], [ mt '_hist_col_user' ], - sub { td; a href => '#', id => 'expandlist', 'expand'; txt mt '_hist_col_page'; end; } + sub { td; a href => '#', id => 'expandlist', mt '_js_expand'; txt mt '_hist_col_page'; end; } ], row => sub { my($s, $n, $i) = @_; diff --git a/util/jsgen.pl b/util/jsgen.pl index 894fa1b9..3ae63157 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -19,8 +19,11 @@ use LangFile; use VNDB::L10N; -my $jskeys = qr{^_menu_emptysearch$}; - +my $jskeys = qr{^(?: + _js_.+| + _menu_emptysearch| + _vnpage_uopt_10?vote + )$}x; sub l10n { # Using JSON::XS or something may be shorter and less error prone, @@ -47,6 +50,7 @@ sub l10n { $lang{$l->[0]} = 1 if $type eq 'tl'; if($type eq 'tl' && $cur) { my($lang, $sync, $val) = @$l; + next if !$val; $val =~ s/"/\\"/g; $val =~ s/\n/\\n/g; $r[$#r] .= ',' if $cur == 2; diff --git a/util/vndb.pl b/util/vndb.pl index 609d47a8..f3c3036c 100755 --- a/util/vndb.pl +++ b/util/vndb.pl @@ -120,8 +120,9 @@ sub readskins { sub checkjs { my $script = "$ROOT/static/f/script.js"; + my $lastmod = [stat $script]->[9]; system "$ROOT/util/jsgen.pl" if (!-e $script && -x "$ROOT/static/f") - || (-e $script && -w $script && [stat $script]->[9] < [stat "$ROOT/data/script.js"]->[9]); + || (-e $script && -w $script && $lastmod < [stat "$ROOT/data/script.js"]->[9] || $lastmod < [stat "$ROOT/data/lang.txt"]->[9]); } -- cgit v1.2.3 From 246165b399856e207295773da2c03b135c1ca86a Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 14:16:36 +0200 Subject: L10N: Extracted release list statuses Should be converted to enums at some point... integers don't do the trick here. --- data/global.pl | 16 ++-------------- data/lang.txt | 43 +++++++++++++++++++++++++++++++++++++++++++ data/script.js | 26 ++++++++++++++------------ lib/VNDB/Func.pm | 4 ++-- lib/VNDB/Handler/Releases.pm | 10 +++++----- lib/VNDB/Handler/ULists.pm | 12 ++++++------ util/jsgen.pl | 3 ++- 7 files changed, 74 insertions(+), 40 deletions(-) diff --git a/data/global.pl b/data/global.pl index 22e18670..108f7332 100644 --- a/data/global.pl +++ b/data/global.pl @@ -99,20 +99,8 @@ our %S = (%S, animated => [ 0..4 ], wishlist_status => [ 0..3 ], # note: keep these synchronised in script.js - vn_rstat => [ - 'Unknown', - 'Pending', - 'Obtained', # hardcoded - 'On loan', - 'Deleted', - ], - vn_vstat => [ - 'Unknown', - 'Playing', - 'Finished', # hardcoded - 'Stalled', - 'Dropped', - ], + rlst_rstat => [ 0..4 ], # 2 = hardcoded 'OK', < 2 = hardcoded 'NOK' + rlst_vstat => [ 0..4 ], # 2 = hardcoded 'OK', 0 || 4 = hardcoded 'NOK' ); diff --git a/data/lang.txt b/data/lang.txt index 7d4d2a67..a5749fef 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -588,6 +588,49 @@ en : Very long[index,_1,, (> 50 hours), (Clannad)] ru : Очень длинная[index,_1,, (> 50 часов), (Clannad)] +# VN list statuses + +:_rlst_rstat_0 +en : Unknown +ru*: + +:_rlst_rstat_1 +en : Pending +ru*: + +:_rlst_rstat_2 +en : Obtained +ru*: + +:_rlst_rstat_3 +en : On loan +ru*: + +:_rlst_rstat_4 +en : Deleted +ru*: + +:_rlst_vstat_0 +en : Unknown +ru*: + +:_rlst_vstat_1 +en : Playing +ru*: + +:_rlst_vstat_2 +en : Finished +ru*: + +:_rlst_vstat_3 +en : Stalled +ru*: + +:_rlst_vstat_4 +en : Dropped +ru*: + + # Form messages :_formerr_e_login_failed diff --git a/data/script.js b/data/script.js index 826b3bb2..ec13e306 100644 --- a/data/script.js +++ b/data/script.js @@ -352,27 +352,29 @@ function ddRefresh() { // release list dropdown on VN pages -var rstat = [ 'Unknown', 'Pending', 'Obtained', 'On loan', 'Deleted' ]; -var vstat = [ 'Unknown', 'Playing', 'Finished', 'Stalled', 'Dropped' ]; +var rl_rstat = 4; +var rl_vstat = 4; function rlDropDown(lnk) { var relid = lnk.id.substr(6); var st = getText(lnk).split(' / '); - if(st[0].indexOf('loading') >= 0) + if(st[0].indexOf(mt('_js_loading')) >= 0) return null; var rs = tag('ul', tag('li', tag('b', 'Release status'))); var vs = tag('ul', tag('li', tag('b', 'Play status'))); - for(var i=0;i<rstat.length;i++) { - if(st[0] && st[0].indexOf(rstat[i]) >= 0) - rs.appendChild(tag('li', tag('i', rstat[i]))); + for(var i=0; i<=rl_rstat; i++) { + var val = mt('_rlst_rstat_'+i); + if(st[0] && st[0].indexOf(val) >= 0) + rs.appendChild(tag('li', tag('i', val))); else - rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+i, onclick:rlMod}, rstat[i]))); + rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+i, onclick:rlMod}, val))); } - for(var i=0;i<vstat.length;i++) { - if(st[0] && st[0].indexOf(vstat[i]) >= 0) - vs.appendChild(tag('li', tag('i', vstat[i]))); + for(var i=0; i<=rl_vstat; i++) { + var val = mt('_rlst_vstat_'+i); + if(st[1] && st[1].indexOf(val) >= 0) + vs.appendChild(tag('li', tag('i', val))); else - vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+i, onclick:rlMod}, vstat[i]))); + vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+i, onclick:rlMod}, val))); } return tag('div', {'class':'vrdd'}, rs, vs, st[0] == '--' ? null : @@ -383,7 +385,7 @@ function rlDropDown(lnk) { function rlMod() { var lnk = byId('rlsel_'+this.rl_rid); ddHide(); - setContent(lnk, tag('b', {'class': 'patch'}, mt('js_loading'))); + setContent(lnk, tag('b', {'class': 'patch'}, mt('_js_loading'))); ajax('/xml/rlist.xml?id='+this.rl_rid+';e='+this.rl_act, function(hr) { // TODO: get rid of innerHTML here... lnk.innerHTML = hr.responseXML.getElementsByTagName('rlist')[0].firstChild.nodeValue; diff --git a/lib/VNDB/Func.pm b/lib/VNDB/Func.pm index cd4c4b62..ad38215e 100644 --- a/lib/VNDB/Func.pm +++ b/lib/VNDB/Func.pm @@ -149,10 +149,10 @@ sub gtintype { sub liststat { my $l = shift; return '' if !$l; - my $rs = $YAWF::OBJ->{vn_rstat}[$l->{rstat}]; + my $rs = mt('_rlst_rstat_'.$l->{rstat}); $rs = qq|<b class="done">$rs</b>| if $l->{rstat} == 2; # Obtained $rs = qq|<b class="todo">$rs</b>| if $l->{rstat} < 2; # Unknown/pending - my $vs = $YAWF::OBJ->{vn_vstat}[$l->{vstat}]; + my $vs = mt('_rlst_vstat_'.$l->{vstat}); $vs = qq|<b class="done">$vs</b>| if $l->{vstat} == 2; # Finished $vs = qq|<b class="todo">$vs</b>| if $l->{vstat} == 0 || $l->{vstat} == 4; # Unknown/dropped return "$rs / $vs"; diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index e7442845..e3656cc3 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -241,14 +241,14 @@ sub _infotable { td; Select id => 'listsel', name => 'listsel'; option mt !$rl ? '_relinfo_user_notlist' : - ('_relinfo_user_inlist', $self->{vn_rstat}[$rl->{rstat}], $self->{vn_vstat}[$rl->{vstat}]); + ('_relinfo_user_inlist', mt('_rlst_rstat_'.$rl->{rstat}), mt('_rlst_vstat_'.$rl->{vstat})); optgroup label => mt '_relinfo_user_setr'; - option value => "r$_", $self->{vn_rstat}[$_] - for (0..$#{$self->{vn_rstat}}); + option value => "r$_", mt '_rlst_rstat_'.$_ + for (@{$self->{rlst_rstat}}); end; optgroup label => mt '_relinfo_user_setv'; - option value => "v$_", $self->{vn_vstat}[$_] - for (0..$#{$self->{vn_vstat}}); + option value => "v$_", mt '_rlst_vstat_'.$_ + for (@{$self->{rlst_vstat}}); end; option value => 'del', mt '_relinfo_user_del' if $rl; end; diff --git a/lib/VNDB/Handler/ULists.pm b/lib/VNDB/Handler/ULists.pm index 049ef48a..19db9f1e 100644 --- a/lib/VNDB/Handler/ULists.pm +++ b/lib/VNDB/Handler/ULists.pm @@ -69,7 +69,7 @@ sub rlist { return $self->htmlDenied() if !$uid; my $f = $self->formValidate( - { name => 'e', required => 1, enum => [ 'del', map("r$_", 0..$#{$self->{vn_rstat}}), map("v$_", 0..$#{$self->{vn_vstat}}) ] }, + { name => 'e', required => 1, enum => [ 'del', map("r$_", @{$self->{rlst_rstat}}), map("v$_", @{$self->{rlst_vstat}}) ] }, ); return 404 if $f->{_err}; @@ -212,7 +212,7 @@ sub vnlist { if($own && $self->reqMethod eq 'POST') { my $frm = $self->formValidate( { name => 'sel', required => 0, default => 0, multi => 1, template => 'int' }, - { name => 'batchedit', required => 1, enum => [ 'del', map("r$_", 0..$#{$self->{vn_rstat}}), map("v$_", 0..$#{$self->{vn_vstat}}) ] }, + { name => 'batchedit', required => 1, enum => [ 'del', map("r$_", @{$self->{rlst_rstat}}), map("v$_", @{$self->{rlst_vstat}}) ] }, ); if(!$frm->{_err} && @{$frm->{sel}} && $frm->{sel}[0]) { $self->dbVNListDel($uid, $frm->{sel}) if $frm->{batchedit} eq 'del'; @@ -333,12 +333,12 @@ sub _vnlist_browse { Select id => 'batchedit', name => 'batchedit'; option mt '_rlist_selection'; optgroup label => mt '_rlist_changerel'; - option value => "r$_", $self->{vn_rstat}[$_] - for (0..$#{$self->{vn_rstat}}); + option value => "r$_", mt "_rlst_rstat_$_" + for (@{$self->{rlst_rstat}}); end; optgroup label => mt '_rlist_changeplay'; - option value => "v$_", $self->{vn_vstat}[$_] - for (0..$#{$self->{vn_vstat}}); + option value => "v$_", mt "_rlst_vstat_$_" + for (@{$self->{rlst_vstat}}); end; option value => 'del', mt '_rlist_del'; end; diff --git a/util/jsgen.pl b/util/jsgen.pl index 3ae63157..eee52c2a 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -22,7 +22,8 @@ use VNDB::L10N; my $jskeys = qr{^(?: _js_.+| _menu_emptysearch| - _vnpage_uopt_10?vote + _vnpage_uopt_10?vote| + _rlst_[vr]stat_.+ )$}x; sub l10n { -- cgit v1.2.3 From de09cecb62a56a9dc017876d32c07e1a51f6378d Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 14:38:47 +0200 Subject: L10N: Extracted strings for and improved release list selector on VN pages --- ChangeLog | 1 + data/global.pl | 1 - data/lang.txt | 12 ++++++++++++ data/script.js | 22 ++++++++++------------ util/jsgen.pl | 11 ++++++++--- util/skingen.pl | 1 - 6 files changed, 31 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 399a2110..4babb39f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,7 @@ git - ? - Everything merged into one file. - Optionally minified (using JavaScript::Minifier::XS) - Language strings are translatable + - Information is automatically synchronised with data/global.pl 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/global.pl b/data/global.pl index 108f7332..1cbb9902 100644 --- a/data/global.pl +++ b/data/global.pl @@ -98,7 +98,6 @@ our %S = (%S, voiced => [ 0..4 ], animated => [ 0..4 ], wishlist_status => [ 0..3 ], - # note: keep these synchronised in script.js rlst_rstat => [ 0..4 ], # 2 = hardcoded 'OK', < 2 = hardcoded 'NOK' rlst_vstat => [ 0..4 ], # 2 = hardcoded 'OK', 0 || 4 = hardcoded 'NOK' ); diff --git a/data/lang.txt b/data/lang.txt index a5749fef..3437455c 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -3337,6 +3337,18 @@ ru : Добавить к списку en : remove from wishlist ru : убрать из списка +:_vnpage_uopt_relrstat +en : Release status +ru*: + +:_vnpage_uopt_relvstat +en : Play status +ru*: + +:_vnpage_uopt_reldel +en : Remove from VN list +ru*: + :_vnpage_rel en : Releases ru : Выпуски diff --git a/data/script.js b/data/script.js index ec13e306..2ddadb49 100644 --- a/data/script.js +++ b/data/script.js @@ -352,40 +352,38 @@ function ddRefresh() { // release list dropdown on VN pages -var rl_rstat = 4; -var rl_vstat = 4; function rlDropDown(lnk) { var relid = lnk.id.substr(6); var st = getText(lnk).split(' / '); if(st[0].indexOf(mt('_js_loading')) >= 0) return null; - var rs = tag('ul', tag('li', tag('b', 'Release status'))); - var vs = tag('ul', tag('li', tag('b', 'Play status'))); - for(var i=0; i<=rl_rstat; i++) { - var val = mt('_rlst_rstat_'+i); + var rs = tag('ul', tag('li', tag('b', mt('_vnpage_uopt_relrstat')))); + var vs = tag('ul', tag('li', tag('b', mt('_vnpage_uopt_relvstat')))); + for(var i=0; i<rlst_rstat.length; i++) { + var val = mt('_rlst_rstat_'+rlst_rstat[i]); if(st[0] && st[0].indexOf(val) >= 0) rs.appendChild(tag('li', tag('i', val))); else - rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+i, onclick:rlMod}, val))); + rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+rlst_rstat[i], onclick:rlMod}, val))); } - for(var i=0; i<=rl_vstat; i++) { - var val = mt('_rlst_vstat_'+i); + for(var i=0; i<rlst_vstat.length; i++) { + var val = mt('_rlst_vstat_'+rlst_vstat[i]); if(st[1] && st[1].indexOf(val) >= 0) vs.appendChild(tag('li', tag('i', val))); else - vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+i, onclick:rlMod}, val))); + vs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'v'+rlst_vstat[i], onclick:rlMod}, val))); } return tag('div', {'class':'vrdd'}, rs, vs, st[0] == '--' ? null : - tag('ul', {'class':'full'}, tag('li', tag('a', {href:'#', rl_rid: relid, rl_act:'del', onclick:rlMod}, 'Remove from VN List'))) + tag('ul', {'class':'full'}, tag('li', tag('a', {href:'#', rl_rid: relid, rl_act:'del', onclick:rlMod}, mt('_vnpage_uopt_reldel')))) ); } function rlMod() { var lnk = byId('rlsel_'+this.rl_rid); ddHide(); - setContent(lnk, tag('b', {'class': 'patch'}, mt('_js_loading'))); + setContent(lnk, tag('b', {'class': 'grayedout'}, mt('_js_loading'))); ajax('/xml/rlist.xml?id='+this.rl_rid+';e='+this.rl_act, function(hr) { // TODO: get rid of innerHTML here... lnk.innerHTML = hr.responseXML.getElementsByTagName('rlist')[0].firstChild.nodeValue; diff --git a/util/jsgen.pl b/util/jsgen.pl index eee52c2a..3afb371a 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -1,13 +1,16 @@ #!/usr/bin/perl +package VNDB; + use strict; use warnings; use Encode 'encode_utf8'; use Cwd 'abs_path'; eval { require JavaScript::Minifier::XS; }; -our($ROOT, %O); +our($ROOT, %S); BEGIN { ($ROOT = abs_path $0) =~ s{/util/jsgen\.pl$}{}; } +require $ROOT.'/data/global.pl'; use lib "$ROOT/lib"; use lib "$ROOT/yawf/lib"; @@ -22,7 +25,7 @@ use VNDB::L10N; my $jskeys = qr{^(?: _js_.+| _menu_emptysearch| - _vnpage_uopt_10?vote| + _vnpage_uopt_(?:10?vote|rel.+)| _rlst_[vr]stat_.+ )$}x; @@ -70,7 +73,9 @@ sub l10n { sub jsgen { # JavaScript::Minifier::XS doesn't correctly handle perl's unicode, # so just do everything in raw bytes instead. - my $js = encode_utf8(l10n()) . "\n\n"; + my $js = encode_utf8(l10n()) . "\n"; + $js .= sprintf "rlst_rstat = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{rlst_rstat}}; + $js .= sprintf "rlst_vstat = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{rlst_vstat}}; open my $JS, '<', "$ROOT/data/script.js" or die $!; $js .= join '', <$JS>; close $JS; diff --git a/util/skingen.pl b/util/skingen.pl index d18f5fde..73e4fdc7 100755 --- a/util/skingen.pl +++ b/util/skingen.pl @@ -11,7 +11,6 @@ eval { require CSS::Minifier::XS }; our($ROOT, %O); BEGIN { ($ROOT = abs_path $0) =~ s{/util/skingen\.pl$}{}; } -require $ROOT.'/data/global.pl'; if(@ARGV) { -- cgit v1.2.3 From b5d713427538b4f78d2527fb32dd58238a491025 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 14:52:59 +0200 Subject: L10N: Extracted VN relation editor --- data/lang.txt | 34 ++++++++++++++++++++++++++++++++++ data/script.js | 14 +++++++------- lib/VNDB/Handler/VNEdit.pm | 7 +++---- util/jsgen.pl | 3 ++- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index 3437455c..8c712a5a 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -3076,6 +3076,40 @@ ru : Выбранные связи en : Add relation ru : Добавить связь +# <title1> is a <relation> of <title2> +# this trick doesn't even work very well in English, so just an approximation is fine +:_vnedit_rel_isa +en : is a +ru*: + +:_vnedit_rel_of +en : of +ru*: + +:_vnedit_rel_addbut +en : add +ru*: + +:_vnedit_rel_del +en : del +ru*: + +:_vnedit_rel_none +en : No relations selected. +ru*: + +:_vnedit_rel_findformat +en : Visual novel textbox must start with an ID (e.g. v17) +ru*: + +:_vnedit_rel_novn +en : Visual novel not found! +ru*: + +:_vnedit_rel_double +en : This visual novel has already been selected! +ru*: + :_vnedit_scr en : Screenshots ru : Скриншоты diff --git a/data/script.js b/data/script.js index 2ddadb49..9bb3d84a 100644 --- a/data/script.js +++ b/data/script.js @@ -754,9 +754,9 @@ function vnrAdd(rel, vid, title) { byId('relation_tbl').appendChild(tag('tr', {id:'relation_tr_'+vid}, tag('td', {'class':'tc_vn' }, 'v'+vid+':', tag('a', {href:'/v'+vid}, shorten(title, 40))), - tag('td', {'class':'tc_rel' }, 'is a ', sel, ' of'), + tag('td', {'class':'tc_rel' }, mt('_vnedit_rel_isa')+' ', sel, ' '+mt('_vnedit_rel_of')), tag('td', {'class':'tc_title'}, shorten(byId('title').value, 40)), - tag('td', {'class':'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, 'del')) + tag('td', {'class':'tc_add' }, tag('a', {href:'#', onclick:vnrDel}, mt('_vnedit_rel_del'))) )); vnrEmpty(); @@ -765,7 +765,7 @@ function vnrAdd(rel, vid, title) { function vnrEmpty() { var tbl = byId('relation_tbl'); if(byName(tbl, 'tr').length < 1) - tbl.appendChild(tag('tr', {id:'relation_tr_none'}, tag('td', {colspan:4}, 'No relations selected.'))); + tbl.appendChild(tag('tr', {id:'relation_tr_none'}, tag('td', {colspan:4}, mt('_vnedit_rel_none')))); else if(byId('relation_tr_none')) tbl.removeChild(byId('relation_tr_none')); } @@ -804,7 +804,7 @@ function vnrFormAdd() { var input = txt.value; if(!input.match(/^v[0-9]+/)) { - alert('Visual novel textbox must start with an ID (e.g. v17)'); + alert('_vnedit_rel_findformat'); return false; } @@ -815,15 +815,15 @@ function vnrFormAdd() { ajax('/xml/vn.xml?q='+encodeURIComponent(input), function(hr) { txt.disabled = sel.disabled = false; txt.value = ''; - setText(lnk, 'add'); + setText(lnk, mt('_vnedit_rel_addbut')); var items = hr.responseXML.getElementsByTagName('item'); if(items.length < 1) - return alert('Visual novel not found!'); + return alert(mt('_vnedit_rel_novn')); var id = items[0].getAttribute('id'); if(byId('relation_tr_'+id)) - return alert('This visual novel has already been selected!'); + return alert(mt('_vnedit_rel_double')); vnrAdd(sel.selectedIndex, id, items[0].firstChild.nodeValue); sel.selectedIndex = 0; diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm index 8430156d..75cc9002 100644 --- a/lib/VNDB/Handler/VNEdit.pm +++ b/lib/VNDB/Handler/VNEdit.pm @@ -193,23 +193,22 @@ sub _form { end; h2 mt '_vnedit_rel_add'; - # TODO: localize JS relartion selector table; Tr id => 'relation_new'; td class => 'tc_vn'; input type => 'text', class => 'text'; end; td class => 'tc_rel'; - txt ' is a '; + txt mt('_vnedit_rel_isa').' '; Select; option value => $_, mt "_vnrel_$_" for (sort { $self->{vn_relations}{$a}[0] <=> $self->{vn_relations}{$b}[0] } keys %{$self->{vn_relations}}); end; - txt ' of'; + txt ' '.mt '_vnedit_rel_of'; end; td class => 'tc_title', $v ? $v->{title} : ''; td class => 'tc_add'; - a href => '#', 'add'; + a href => '#', mt '_vnedit_rel_addbut'; end; end; end; diff --git a/util/jsgen.pl b/util/jsgen.pl index 3afb371a..4ab856e5 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -26,7 +26,8 @@ my $jskeys = qr{^(?: _js_.+| _menu_emptysearch| _vnpage_uopt_(?:10?vote|rel.+)| - _rlst_[vr]stat_.+ + _rlst_[vr]stat_.+| + _vnedit_rel_(?:isa|of|addbut|del|none|findformat|novn|double) )$}x; sub l10n { -- cgit v1.2.3 From f5f25f314b106301c02855610ea2b466ee31d256 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 15:41:58 +0200 Subject: L10N: Extracted release media and the media selector --- data/global.pl | 24 +++++++++--------- data/lang.txt | 59 ++++++++++++++++++++++++++++++++++++++++++++ data/script.js | 11 ++++++--- lib/VNDB/Handler/Releases.pm | 18 +++++--------- util/jsgen.pl | 3 ++- 5 files changed, 86 insertions(+), 29 deletions(-) diff --git a/data/global.pl b/data/global.pl index 1cbb9902..9f176081 100644 --- a/data/global.pl +++ b/data/global.pl @@ -69,18 +69,18 @@ our %S = (%S, release_types => [0..2], platforms => [qw|win dos lin mac dvd gba msx nds nes p98 psp ps1 ps2 ps3 drc sat sfc wii xb3 oth|], media => { - #DB display qty - cd => [ 'CD', 1 ], - dvd => [ 'DVD', 1 ], - gdr => [ 'GD', 1 ], - blr => [ 'Blu-ray', 1 ], - flp => [ 'Floppy', 1 ], - mrt => [ 'Cartridge', 1 ], - mem => [ 'Memory card', 1 ], - umd => [ 'UMD', 1 ], - nod => [ 'Nintendo Optical Disk', 1 ], - in => [ 'Internet download', 0 ], - otc => [ 'Other', 0 ], + #DB qty? + cd => 1, + dvd => 1, + gdr => 1, + blr => 1, + flp => 1, + mrt => 1, + mem => 1, + umd => 1, + nod => 1, + in => 0, + otc => 0 }, resolutions => [ [ 'Unknown / console / handheld', '' ], diff --git a/data/lang.txt b/data/lang.txt index 8c712a5a..adf11b85 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -326,6 +326,53 @@ en : Other ru : Другая +# Release media + +:_med_cd +en : [quant,_1,CD,CDs] +ru*: + +:_med_dvd +en : [quant,_1,DVD,DVDs] +ru*: + +:_med_gdr +en : [quant,_1,GD-ROM,GD-ROMs] +ru*: + +:_med_blr +en : [quant,_1,Blu-ray disc,Blu-ray discs] +ru*: + +:_med_flp +en : [quant,_1,Floppy,Floppies] +ru*: + +:_med_mrt +en : [quant,_1,Cartridge,Cartridges] +ru*: + +:_med_mem +en : [quant,_1,Memory card,Memory cards] +ru*: + +:_med_umd +en : [quant,_1,UMD,UMDs] +ru*: + +:_med_nod +en : Nintendo Optical [quant,_1,Disk,Disks] +ru*: + +:_med_in +en : Internet download +ru*: + +:_med_otc +en : Other +ru*: + + # VN relations :_vnrel_seq @@ -1871,6 +1918,18 @@ ru : Платформы en : Media ru : Носители +:_redit_form_med_quantity +en : -quantity- +ru*: + +:_redit_form_med_medium +en : -medium- +ru*: + +:_redit_form_med_remove +en : remove +ru*: + :_redit_form_prod en : Producers ru : Компании diff --git a/data/script.js b/data/script.js index 9bb3d84a..2c6b776a 100644 --- a/data/script.js +++ b/data/script.js @@ -158,7 +158,9 @@ function shorten(v, l) { return v.length > l ? v.substr(0, l-3)+'...' : v; } -/* maketext function, less powerful than the Perl equivalent (only supports [_n] and ~[~]) +/* maketext function, less powerful than the Perl equivalent: + * - Only supports [_n], ~[, ~] + * - When it finds [quant,_n,..], it will only return the first argument (and doesn't support ~ in an argument) * assumes that a TL structure called 'L10N_STR' is defined in the header of this file */ var mt_curlang = getCookie('l10n') || 'en'; function mt() { @@ -169,6 +171,7 @@ function mt() { while(val.substr(expr) >= 0) val = val.replace(expr, arguments[i]); } + val = val.replace(/\[quant,_\d+\,([^,]+)[^\]]+\]/g, "$1"); while(val.substr('~[') >= 0 || val.substr('~]') >= 0) val = val.replace('~[', '[').replace('~]', ']'); return val; @@ -857,18 +860,18 @@ function medLoad() { } function medAdd(med, qty) { - var qsel = tag('select', {'class':'qty', onchange:medSerialize}, tag('option', {value:0}, '- quantity -')); + var qsel = tag('select', {'class':'qty', onchange:medSerialize}, tag('option', {value:0}, mt('_redit_form_med_quantity'))); for(var i=1; i<=20; i++) qsel.appendChild(tag('option', {value:i, selected: qty==i}, i)); var msel = tag('select', {'class':'medium', onchange: med == '' ? medFormAdd : medSerialize}); if(med == '') - msel.appendChild(tag('option', {value:''}, '- medium -')); + msel.appendChild(tag('option', {value:''}, mt('_redit_form_med_medium'))); for(var i=0; i<medTypes.length; i++) msel.appendChild(tag('option', {value:medTypes[i][0], selected: med==medTypes[i][0]}, medTypes[i][1])); byId('media_div').appendChild(tag('span', qsel, msel, - med != '' ? tag('input', {type: 'button', 'class':'submit', onclick:medDel, value:'remove'}) : null + med != '' ? tag('input', {type: 'button', 'class':'submit', onclick:medDel, value:mt('_redit_form_med_remove')}) : null )); } diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index e3656cc3..f022795a 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -54,10 +54,7 @@ sub page { [ notes => diff => 1 ], [ platforms => join => ', ', split => sub { map mt("_plat_$_"), @{$_[0]} } ], [ media => join => ', ', split => sub { - map { - my $med = $self->{media}{$_->{medium}}; - $med->[1] ? sprintf('%d %s%s', $_->{qty}, $med->[0], $_->{qty}>1?'s':'') : $med->[0] - } @{$_[0]}; + map $self->{media}{$_->{medium}} ? $_->{qty}.' '.mt("_med_$_->{medium}", $_->{qty}) : mt("_med_$_->{medium}",1), @{$_[0]} } ], [ resolution => serialize => sub { $self->{resolutions}[$_[0]][0] } ], [ voiced => serialize => sub { mt '_voiced_'.$_[0] } ], @@ -154,11 +151,9 @@ sub _infotable { if(@{$r->{media}}) { Tr ++$i % 2 ? (class => 'odd') : (); td mt '_relinfo_media', scalar @{$r->{media}}; - # TODO: TL the media - td join ', ', map { - my $med = $self->{media}{$_->{medium}}; - $med->[1] ? sprintf('%d %s%s', $_->{qty}, $med->[0], $_->{qty}>1?'s':'') : $med->[0] - } @{$r->{media}}; + td join ', ', map + $self->{media}{$_->{medium}} ? $_->{qty}.' '.mt("_med_$_->{medium}", $_->{qty}) : mt("_med_$_->{medium}",1), + @{$r->{media}}; end; } @@ -435,7 +430,7 @@ sub _form { h2 mt '_redit_form_media'; div id => 'media_div'; Select; - option value => $_, class => $self->{media}{$_}[1] ? 'qty' : 'noqty', $self->{media}{$_}[0] + option value => $_, class => $self->{media}{$_} ? 'qty' : 'noqty', mt "_med_$_", 1 for (sort keys %{$self->{media}}); end; end; @@ -657,10 +652,9 @@ sub _filters { b ' ('.mt('_rbrowse_boolor').')'; end; for my $i (sort keys %{$self->{media}}) { - next if $i eq 'otc'; span; input type => 'checkbox', name => 'me', value => $i, id => "med_$i", grep($_ eq $i, @{$f->{me}}) ? (checked => 'checked') : (); - label for => "med_$i", $self->{media}{$i}[0]; + label for => "med_$i", mt "_med_$i"; end; } diff --git a/util/jsgen.pl b/util/jsgen.pl index 4ab856e5..edc191b6 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -27,7 +27,8 @@ my $jskeys = qr{^(?: _menu_emptysearch| _vnpage_uopt_(?:10?vote|rel.+)| _rlst_[vr]stat_.+| - _vnedit_rel_(?:isa|of|addbut|del|none|findformat|novn|double) + _vnedit_rel_(?:isa|of|addbut|del|none|findformat|novn|double)| + _redit_form_med_.+ )$}x; sub l10n { -- cgit v1.2.3 From 908a5ee2185da46f1cc02a7d0c92b922fef99e77 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 16:16:48 +0200 Subject: L10N: Extracted VN screenshot uploader --- data/lang.txt | 92 +++++++++++++++++++++++++++++++++++++++++++++- data/script.js | 50 ++++++++++--------------- lib/VNDB/Handler/VNEdit.pm | 3 +- util/jsgen.pl | 3 +- 4 files changed, 114 insertions(+), 34 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index adf11b85..21ca3490 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -3173,7 +3173,7 @@ ru*: en : Screenshots ru : Скриншоты -:_vnedit_scr_msg +:_vnedit_scrmsg en : 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] @@ -3187,6 +3187,96 @@ ru : Когда загружаете скриншоты, пожалуйста п За подробностями обращайтесь к [url,/d2#6,рекомендациям].[br] Не забудьте сохранить изменения когда закончите загружать изображения! +:_vnedit_scr_selrel +en : -- select release -- +ru*: + +:_vnedit_scr_frmloading +en : Please wait for the screenshots to be uploaded before submitting the form. +ru*: + +:_vnedit_scr_frmnorel +en : Please select the appropriate release for every screenshot. +ru*: + +:_vnedit_scr_fetching +en : Fetching thumbnail... +ru*: + +:_vnedit_scr_uploading +en : Uploading screenshot +ru*: + +:_vnedit_scr_upl_msg +en : This can take a while, depending on the file size and your upload speed. +ru*: + +:_vnedit_scr_cancel +en : cancel +ru*: + +:_vnedit_scr_full +en : Enough screenshots +ru*: + +:_vnedit_scr_full_msg +en : The limit of 10 screenshots per visual novel has been reached. + If you want to add a new screenshot, please remove an existing one first. +ru*: + +:_vnedit_scr_add +en : Add screenshot +ru*: + +:_vnedit_scr_imgnote +en : Image must be smaller than 5MB and in PNG or JPEG format. +ru*: + +:_vnedit_scr_addbut +en : Upload! +ru*: + +:_vnedit_scr_id +en : Screenshot #[_1] +ru*: + +:_vnedit_scr_remove +en : remove +ru*: + +:_vnedit_scr_fullsize +en : Full size: [_1] +ru*: + +:_vnedit_scr_nsfw +en : This screenshot is NSFW +ru*: + +:_vnedit_scr_oops +en : Oops! Seems like something went wrong... + Make sure the file you're uploading doesn't exceed 5MB in size. + If that isn't the problem, then please report a bug. +ru*: + +:_vnedit_scr_errformat +en : Upload failed! + Only JPEG or PNG images are accepted. +ru*: + +:_vnedit_scr_errempty +en : Upload failed! + No file selected, or an empty file? +ru*: + +:_vnedit_scr_genthumb +en : Generating thumbnail... +ru*: + +:_vnedit_scr_genthumb_msg +en : Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. + Please try again later or report a bug if that is the case. +ru*: + # VN Relation graph page (/v+/rg) diff --git a/data/script.js b/data/script.js index 2c6b776a..f00d4d88 100644 --- a/data/script.js +++ b/data/script.js @@ -168,11 +168,11 @@ function mt() { var val = L10N_STR[key] ? L10N_STR[key][mt_curlang] || L10N_STR[key].en : key; for(var i=1; i<arguments.length; i++) { var expr = '[_'+i+']'; - while(val.substr(expr) >= 0) + while(val.indexOf(expr) >= 0) val = val.replace(expr, arguments[i]); } val = val.replace(/\[quant,_\d+\,([^,]+)[^\]]+\]/g, "$1"); - while(val.substr('~[') >= 0 || val.substr('~]') >= 0) + while(val.indexOf('~[') >= 0 || val.indexOf('~]') >= 0) val = val.replace('~[', '[').replace('~]', ']'); return val; } @@ -924,7 +924,7 @@ if(byId('jt_box_rel_format')) /* V I S U A L N O V E L S C R E E N S H O T U P L O A D E R (/v+/edit) */ -var scrRel = [ [ 0, '-- select release --' ] ]; +var scrRel = [ [ 0, mt('_vnedit_scr_selrel') ] ]; var scrStaticURL; var scrUplNr = 0; @@ -964,10 +964,10 @@ function scrSetSubmit() { norelease = 1; } if(loading) { - alert('Please wait for the screenshots to be uploaded before submitting the form.'); + alert(mt('_vnedit_scr_frmloading')); return false; } else if(norelease) { - alert('Please select the appropriate release for every screenshot'); + alert(mt('_vnedit_scr_frmnorel')); return false; } else if(oldfunc) return oldfunc(); @@ -984,11 +984,11 @@ function scrAdd(id, nsfw, rel) { var tr = tag('tr', { id:'scr_tr_'+id, scr_id: id, scr_status: id?2:1, scr_rel: rel, scr_nsfw: nsfw}, tag('td', { 'class': 'thumb'}, mt('_js_loading')), tag('td', - tag('b', id ? 'Fetching thumbnail...' : 'Uploading screenshot'), + tag('b', mt(id ? '_vnedit_scr_fetching' : '_vnedit_scr_uploading')), tag('br', null), - id ? null : 'This can take a while, depending on the file size and your upload speed.', + id ? null : mt('_vnedit_scr_upl_msg'), tag('br', null), - id ? null : tag('a', {href:'#', onclick:scrDel}, 'cancel') + id ? null : tag('a', {href:'#', onclick:scrDel}, mt('_vnedit_scr_cancel')) ) ); byId('scr_table').appendChild(tr); @@ -1004,18 +1004,17 @@ function scrLast() { byId('scr_table').appendChild(tag('tr', {id:'scr_last'}, tag('td', {'class': 'thumb'}), full ? tag('td', - tag('b', 'Enough screenshots'), + tag('b', mt('_vnedit_scr_full')), tag('br', null), - 'The limit of 10 screenshots per visual novel has been reached. ', - 'If you want to add a new screenshot, please remove an existing one first.' + mt('_vnedit_scr_full_msg') ) : tag('td', - tag('b', 'Add screenshot'), + tag('b', mt('_vnedit_scr_add')), tag('br', null), - 'Image must be smaller than 5MB and in PNG or JPEG format.', + mt('_vnedit_scr_imgnote'), tag('br', null), tag('input', {name:'scr_upload', id:'scr_upload', type:'file', 'class':'text'}), tag('br', null), - tag('input', {type:'button', value:'Upload!', 'class':'submit', onclick:scrUpload}) + tag('input', {type:'button', value:mt('_vnedit_scr_addbut'), 'class':'submit', onclick:scrUpload}) ) )); scrStripe(); @@ -1059,14 +1058,14 @@ function scrCheckStatus() { rel.appendChild(tag('option', {value: scrRel[j][0], selected: tr.scr_rel == scrRel[j][0]}, scrRel[j][1])); var nsfwid = 'scr_sfw_'+tr.scr_id; setContent(byName(tr, 'td')[1], - tag('b', 'Screenshot #'+tr.scr_id), - ' (', tag('a', {href: '#', onclick:scrDel}, 'remove'), ')', + tag('b', mt('_vnedit_scr_id', tr.scr_id)), + ' (', tag('a', {href: '#', onclick:scrDel}, mt('_vnedit_scr_remove')), ')', tag('br', null), - 'Full size: '+dim, + mt('_vnedit_scr_fullsize', dim), tag('br', null), tag('br', null), tag('input', {type:'checkbox', onclick:scrSerialize, id:nsfwid, name:nsfwid, checked: tr.scr_nsfw>0, 'class':'scr_nsfw'}), - tag('label', {'for':nsfwid}, 'This screenshot is NSFW'), + tag('label', {'for':nsfwid}, mt('_vnedit_scr_nsfw')), tag('br', null), rel ); @@ -1123,25 +1122,16 @@ function scrUploadComplete() { tr.scr_id = -10; } if(tr.scr_id < 0) { - alert( - tr.scr_id == -10 ? - 'Oops! Seems like something went wrong...\n' - +'Make sure the file you\'re uploading doesn\'t exceed 5MB in size.\n' - +'If that isn\'t the problem, then please report a bug.' : - tr.scr_id == -1 ? - 'Upload failed!\nOnly JPEG or PNG images are accepted.' : - 'Upload failed!\nNo file selected, or an empty file?' - ); + alert(mt(tr.scr_id == -10 ? '_vnedit_scr_oops' : tr.scr_id == -1 ? '_vnedit_scr_errformat' : '_vnedit_scr_errempty')); return scrDel(tr); } tr.id = 'scr_tr_'+tr.scr_id; tr.scr_status = 2; setContent(byName(tr, 'td')[1], - tag('b', 'Generating thumbnail...'), + tag('b', mt('_vnedit_scr_genthumb')), tag('br', null), - 'Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. ', - 'Please try again later or report a bug if that is the case.' + mt('_vnedit_scr_genthumb_msg') ); // remove the <div> in a timeout, otherwise some browsers think the page is still loading diff --git a/lib/VNDB/Handler/VNEdit.pm b/lib/VNDB/Handler/VNEdit.pm index 75cc9002..ed7068dc 100644 --- a/lib/VNDB/Handler/VNEdit.pm +++ b/lib/VNDB/Handler/VNEdit.pm @@ -219,10 +219,9 @@ sub _form { [ hidden => short => 'screenshots' ], [ static => nolabel => 1, content => sub { div class => 'warning'; - lit mt '_vnedit_scr_msg'; + lit mt '_vnedit_scrmsg'; end; br; - # TODO: localize screenshot uploader table; tbody id => 'scr_table', ''; end; diff --git a/util/jsgen.pl b/util/jsgen.pl index edc191b6..0e2bcf76 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -28,7 +28,8 @@ my $jskeys = qr{^(?: _vnpage_uopt_(?:10?vote|rel.+)| _rlst_[vr]stat_.+| _vnedit_rel_(?:isa|of|addbut|del|none|findformat|novn|double)| - _redit_form_med_.+ + _redit_form_med_.+| + _vnedit_scr_.+ )$}x; sub l10n { -- cgit v1.2.3 From 9271d61fd217d0848f37e85acc49df65d3f01772 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 17:04:28 +0200 Subject: L10N: Extracted last bits of Javascript --- data/lang.txt | 76 ++++++++++++++++++++++++++++++++++++++++++++ data/script.js | 37 +++++++++++---------- lib/VNDB/Handler/Releases.pm | 4 +-- util/jsgen.pl | 5 ++- 4 files changed, 102 insertions(+), 20 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index 21ca3490..0b00f7c5 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -1942,6 +1942,30 @@ ru : Выбранные компании en : Add producer ru : Добавить компанию +:_redit_form_prod_addbut +en : add +ru*: + +:_redit_form_prod_remove +en : remove +ru*: + +:_redit_form_prod_none +en : Nothing selected. +ru*: + +:_redit_form_prod_pformat +en : Producer textbox must start with an ID (e.g. p17) +ru*: + +:_redit_form_prod_notfound +en : Producer not found! +ru*: + +:_redit_form_prod_double +en : Producer already selected! +ru*: + :_redit_form_vn en : Visual novels ru : Новеллы @@ -1954,6 +1978,30 @@ ru : Выбранные новеллы en : Add visual novel ru : Добавить новеллу +:_redit_form_vn_addbut +en : add +ru*: + +:_redit_form_vn_remove +en : remove +ru*: + +:_redit_form_vn_none +en : Nothing selected. +ru*: + +:_redit_form_vn_vnformat +en : Visual novel textbox must start with an ID (e.g. v17) +ru*: + +:_redit_form_vn_notfound +en : Visual novel not found! +ru*: + +:_redit_form_vn_double +en : VN already selected! +ru*: + # Release browser @@ -2389,6 +2437,34 @@ en : Check the [url,/g,tag list] to browse all available tags.[br] ru : Откройте [url,/g,список тегов] чтобы увидеть все доступные теги.[br] Не нашли что искали? Вы можете [url,/g/new,запросить новый тег]. +:_tagv_spoil0 +en : neutral +ru*: + +:_tagv_spoil1 +en : no spoiler +ru*: + +:_tagv_spoil2 +en : minor spoiler +ru*: + +:_tagv_spoil3 +en : major spoiler +ru*: + +:_tagv_notfound +en : Item not found! +ru*: + +:_tagv_nometa +en : Can't use meta tags here! +ru*: + +:_tagv_double +en : Tag is already present! +ru*: + # User tag list (/u+/tags) diff --git a/data/script.js b/data/script.js index f00d4d88..544bd304 100644 --- a/data/script.js +++ b/data/script.js @@ -1159,9 +1159,12 @@ if(x('jt_box_vn_scr')) /* V I S U A L N O V E L T A G L I N K I N G (/v+/tagmod) */ -var tglSpoilers = [ 'neutral', 'no spoiler', 'minor spoiler', 'major spoiler' ]; +var tglSpoilers = []; function tglLoad() { + for(var i=0; i<=3; i++) + tglSpoilers[i] = mt('_tagv_spoil'+i); + // tag dropdown search dsInit(byId('tagmod_tag'), '/xml/tags.xml?q=', function(item, tr) { tr.appendChild(tag('td', @@ -1261,18 +1264,18 @@ function tglAdd() { ajax('/xml/tags.xml?q=name:'+encodeURIComponent(tg.value), function(hr) { tg.disabled = add.disabled = false; tg.value = ''; - add.value = 'Add tag'; + add.value = mt('_tagv_add'); var items = hr.responseXML.getElementsByTagName('item'); if(items.length < 1) - return alert('Item not found!'); + return alert(mt('_tagv_notfound')); if(items[0].getAttribute('meta') == 'yes') - return alert('Can\'t use meta tags here!'); + return alert(mt('_tagv_nometa')); var name = items[0].firstChild.nodeValue; var id = items[0].getAttribute('id'); if(byId('tgl_'+id)) - return alert('Tag is already present!'); + return alert(mt('_tagv_double')); var vote = tag('td', {'class':'tc_myvote', tgl_vote: 2}, ''); tglVoteBar(vote); @@ -1341,7 +1344,7 @@ function rvnLoad() { function rvnAdd(id, title) { x('vn_tbl').appendChild(tag('tr', {id:'rvn_'+id, rvn_id:id}, tag('td', {'class':'tc_title'}, 'v'+id+':', tag('a', {href:'/v'+id}, shorten(title, 40))), - tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rvnDel}, 'remove')) + tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rvnDel}, mt('_redit_form_vn_remove'))) )); rvnStripe(); rvnEmpty(); @@ -1361,7 +1364,7 @@ function rvnDel() { function rvnEmpty() { var tbl = byId('vn_tbl'); if(byName(tbl, 'tr').length < 1) - tbl.appendChild(tag('tr', {id:'rvn_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.'))); + tbl.appendChild(tag('tr', {id:'rvn_tr_none'}, tag('td', {colspan:2}, mt('_redit_form_vn_none')))); else if(byId('rvn_tr_none')) tbl.removeChild(byId('rvn_tr_none')); } @@ -1378,7 +1381,7 @@ function rvnFormAdd() { var val = txt.value; if(!val.match(/^v[0-9]+/)) { - alert('Visual novel textbox must start with an ID (e.g. v17)'); + alert(mt('_redit_form_vn_vnformat')); return false; } @@ -1389,15 +1392,15 @@ function rvnFormAdd() { ajax('/xml/vn.xml?q='+encodeURIComponent(val), function(hr) { txt.disabled = false; txt.value = ''; - setText(lnk, 'add'); + setText(lnk, mt('_redit_form_vn_addbut')); var items = hr.responseXML.getElementsByTagName('item'); if(items.length < 1) - return alert('Visual novel not found!'); + return alert(mt('_redit_form_vn_notfound')); var id = items[0].getAttribute('id'); if(byId('rvn_'+id)) - return alert('VN already selected!'); + return alert(mt('_redit_form_vn_double')); rvnAdd(id, items[0].firstChild.nodeValue); rvnSerialize(); @@ -1443,7 +1446,7 @@ function rprLoad() { function rprAdd(id, name) { x('producer_tbl').appendChild(tag('tr', {id:'rpr_'+id, rpr_id:id}, tag('td', {'class':'tc_name'}, 'p'+id+':', tag('a', {href:'/p'+id}, shorten(name, 40))), - tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rprDel}, 'remove')) + tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rprDel}, mt('_redit_form_prod_remove'))) )); rprStripe(); rprEmpty(); @@ -1463,7 +1466,7 @@ function rprDel() { function rprEmpty() { var tbl = byId('producer_tbl'); if(byName(tbl, 'tr').length < 1) - tbl.appendChild(tag('tr', {id:'rpr_tr_none'}, tag('td', {colspan:2}, 'Nothing selected.'))); + tbl.appendChild(tag('tr', {id:'rpr_tr_none'}, tag('td', {colspan:2}, mt('_redit_form_prod_none')))); else if(byId('rpr_tr_none')) tbl.removeChild(byId('rpr_tr_none')); } @@ -1480,7 +1483,7 @@ function rprFormAdd() { var val = txt.value; if(!val.match(/^p[0-9]+/)) { - alert('Producer textbox must start with an ID (e.g. p17)'); + alert(mt('_redit_form_prod_pformat')); return false; } @@ -1491,15 +1494,15 @@ function rprFormAdd() { ajax('/xml/producers.xml?q='+encodeURIComponent(val), function(hr) { txt.disabled = false; txt.value = ''; - setText(lnk, 'add'); + setText(lnk, mt('_redit_form_prod_addbut')); var items = hr.responseXML.getElementsByTagName('item'); if(items.length < 1) - return alert('Producer not found!'); + return alert(mt('_redit_form_prod_notfound')); var id = items[0].getAttribute('id'); if(byId('rpr_'+id)) - return alert('Producer already selected!'); + return alert(mt('_redit_form_prod_double')); rprAdd(id, items[0].firstChild.nodeValue); rprSerialize(); diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index f022795a..04ff716f 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -445,7 +445,7 @@ sub _form { h2 mt('_redit_form_prod_add'); div; input id => 'producer_input', type => 'text', class => 'text'; - a id => 'producer_add', href => '#', 'add'; + a id => 'producer_add', href => '#', mt '_redit_form_prod_addbut'; end; }], ], @@ -458,7 +458,7 @@ sub _form { h2 mt('_redit_form_vn_add'); div; input id => 'vn_input', type => 'text', class => 'text'; - a href => '#', id => 'vn_add', 'add'; + a href => '#', id => 'vn_add', mt '_redit_form_vn_addbut'; end; }], ], diff --git a/util/jsgen.pl b/util/jsgen.pl index 0e2bcf76..c7cca2c2 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -29,7 +29,10 @@ my $jskeys = qr{^(?: _rlst_[vr]stat_.+| _vnedit_rel_(?:isa|of|addbut|del|none|findformat|novn|double)| _redit_form_med_.+| - _vnedit_scr_.+ + _vnedit_scr_.+| + _tagv_(?:add|spoil\d|notfound|nometa|double)| + _redit_form_vn_(?:addbut|remove|none|vnformat|notfound|double)| + _redit_form_prod_(?:addbut|remove|none|pformat|notfound|double) )$}x; sub l10n { -- cgit v1.2.3 From 46a046e88c0059770fcffcf64d43ddbdbeb4fcc6 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 18:04:44 +0200 Subject: JS: Removed x() --- data/script.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/data/script.js b/data/script.js index 544bd304..27139c69 100644 --- a/data/script.js +++ b/data/script.js @@ -54,9 +54,6 @@ function getCookie(n) { return null; } -function x(y) { // deprecated - return document.getElementById(y) -} function byId(n) { return document.getElementById(n) } @@ -1151,7 +1148,7 @@ function scrSerialize() { byId('screenshots').value = r.join(' '); } -if(x('jt_box_vn_scr')) +if(byId('jt_box_vn_scr')) scrLoad(); @@ -1342,7 +1339,7 @@ function rvnLoad() { } function rvnAdd(id, title) { - x('vn_tbl').appendChild(tag('tr', {id:'rvn_'+id, rvn_id:id}, + byId('vn_tbl').appendChild(tag('tr', {id:'rvn_'+id, rvn_id:id}, tag('td', {'class':'tc_title'}, 'v'+id+':', tag('a', {href:'/v'+id}, shorten(title, 40))), tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rvnDel}, mt('_redit_form_vn_remove'))) )); @@ -1444,7 +1441,7 @@ function rprLoad() { } function rprAdd(id, name) { - x('producer_tbl').appendChild(tag('tr', {id:'rpr_'+id, rpr_id:id}, + byId('producer_tbl').appendChild(tag('tr', {id:'rpr_'+id, rpr_id:id}, tag('td', {'class':'tc_name'}, 'p'+id+':', tag('a', {href:'/p'+id}, shorten(name, 40))), tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rprDel}, mt('_redit_form_prod_remove'))) )); -- cgit v1.2.3 From bbc03376d61e2e557d473368611dbba5eead6338 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 7 Oct 2009 18:49:31 +0200 Subject: Changed language selector into a Javascript dropdown --- ChangeLog | 1 + data/script.js | 16 ++++++++++++++++ data/style.css | 7 ++++--- lib/VNDB/Util/LayoutHTML.pm | 8 ++------ util/jsgen.pl | 4 +++- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4babb39f..857c2ad4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ git - ? - Optionally minified (using JavaScript::Minifier::XS) - Language strings are translatable - Information is automatically synchronised with data/global.pl + - Changed language selector into a Javascript dropdown 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/script.js b/data/script.js index 27139c69..bd56f12e 100644 --- a/data/script.js +++ b/data/script.js @@ -344,6 +344,8 @@ function ddRefresh() { ddx -= box.offsetWidth; if(lnk.dd_align == 'tagmod') ddx += lnk.offsetWidth-35; + if(lnk.dd_align == 'bottom') + ddy += lnk.offsetHeight; box.style.left = ddx+'px'; box.style.top = ddy+'px'; return true; @@ -1749,6 +1751,20 @@ if(byId('advselect') && byId('ti')) { dsInit(byId('te'), '/xml/tags.xml?q=', trfunc, serfunc, retfunc, parfunc); } +// Language selector +if(byId('lang_select')) + ddInit(byId('lang_select'), 'bottom', function(lnk) { + var lst = tag('ul', null); + for(var i=0; i<L10N_LANG.length; i++) { + var ln = L10N_LANG[i]; + var icon = tag('acronym', {'class':'icons lang '+ln}, ' '); + lst.appendChild(tag('li', {'class':'lang_selector'}, mt_curlang == ln + ? tag('i', icon, mt('_lang_'+ln)) + : tag('a', {href:'?l10n='+ln}, icon, L10N_STR['_lang_'+ln][ln]) + )); + } + return lst; + }); // spam protection on all forms setTimeout(function() { diff --git a/data/style.css b/data/style.css index 192f909d..af9370e3 100644 --- a/data/style.css +++ b/data/style.css @@ -272,7 +272,7 @@ b.future, b.standout { font-size: 11px; color: $maintext$; } -#menulist h2 span { +#menulist h2 #lang_select { float: right; padding-top: 1px; } @@ -306,6 +306,7 @@ b.future, b.standout { #menulist #search input.submit { display: none; } +#dd_box acronym { margin: 2px 5px 2px 0!important; } @@ -697,8 +698,8 @@ a.addnew { #dd_box { position: absolute; left: -500px; border: 1px solid $border$; background-color: $secbg$; } #dd_box ul { list-style-type: none; margin: 0; padding: 0 } #dd_box li b { display: block; font-weight: normal; padding-left: 5px; } -#dd_box li i { display: block; font-style: normal; padding-left: 10px; } -#dd_box li a { display: block; padding-left: 10px; color: $link$; border: 0; } +#dd_box li i { display: block; font-style: normal; padding-left: 10px; padding-right: 5px } +#dd_box li a { display: block; padding-left: 10px; color: $link$; border: 0; padding-right: 5px } #dd_box li a:hover { background: url($_boxbg$) repeat } #dd_box .vrdd { width: 180px; } #dd_box .vrdd ul { float: left; width: 90px; } diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm index 524b6258..d9dad434 100644 --- a/lib/VNDB/Util/LayoutHTML.pm +++ b/lib/VNDB/Util/LayoutHTML.pm @@ -49,12 +49,8 @@ sub _menu { div class => 'menubox'; h2; - span; - for (grep $self->{l10n}->language_tag() ne $_, $self->{l10n}->languages()) { - a href => "?l10n=$_"; - cssicon "lang $_", mt "_lang_$_"; # NOTE: should actually be in the destination language... - end; - } + a href => "#", id => 'lang_select'; + cssicon "lang ".$self->{l10n}->language_tag(), mt "_lang_".$self->{l10n}->language_tag(); end; txt mt '_menu'; end; diff --git a/util/jsgen.pl b/util/jsgen.pl index c7cca2c2..56897679 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -22,7 +22,9 @@ use LangFile; use VNDB::L10N; +my $jskeys_lang = join '|', VNDB::L10N::languages(); my $jskeys = qr{^(?: + _lang_(?:$jskeys_lang)| _js_.+| _menu_emptysearch| _vnpage_uopt_(?:10?vote|rel.+)| @@ -64,7 +66,7 @@ sub l10n { $val =~ s/"/\\"/g; $val =~ s/\n/\\n/g; $r[$#r] .= ',' if $cur == 2; - $lang = q{"$l->[0]"} if $lang =~ /^(?:as|do|if|in|is)$/; # reserved two-char words + $lang = qq{"$l->[0]"} if $lang =~ /^(?:as|do|if|in|is)$/; # reserved two-char words push @r, qq| $lang: "$val"|; $cur = 2; } -- cgit v1.2.3 From 4304d30193646fdecbe2fcd081cfbce46ad82ed6 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Thu, 8 Oct 2009 22:19:35 +0200 Subject: Synchronised and updated dump.sql and dbgraph.pl Removed the 'SET default_with_oids', as the minimum required PostgreSQL version (8.3) has OIDS disables by default already. Also uncommented the CREATE LANGUAGE, plpgsql is a "trusted language" and as such doesn't need superuser priveleges to create anymore. --- util/dbgraph.pl | 6 +++--- util/dump.sql | 31 ++++++++++++++----------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/util/dbgraph.pl b/util/dbgraph.pl index 167680cd..51e7302e 100755 --- a/util/dbgraph.pl +++ b/util/dbgraph.pl @@ -18,11 +18,11 @@ use warnings; my %subgraphs = ( 'Producers' => [qw| FFFFCC producers producers_rev |], 'Releases' => [qw| C8FFC8 releases releases_rev releases_media releases_platforms releases_producers releases_lang releases_vn |], - 'Visual Novels' => [qw| FFE6BE vn vn_rev vn_relations vn_categories vn_anime vn_screenshots |], - 'Users' => [qw| CCFFFF users votes rlists wlists |], + 'Visual Novels' => [qw| FFE6BE vn vn_rev vn_relations vn_anime vn_screenshots vn_graphs |], + 'Users' => [qw| CCFFFF users votes rlists wlists sessions |], 'Discussion board' => [qw| FFDCDC threads threads_boards threads_posts |], 'Tags' => [qw| FFC8C8 tags tags_aliases tags_parents tags_vn |], - 'Misc' => [qw| F5F5F5 changes anime screenshots relgraph stats_cache quotes sessions |], + 'Misc' => [qw| F5F5F5 changes anime screenshots stats_cache quotes |], ); my %tables; # table_name => [ [ col1, pri ], ... ] diff --git a/util/dump.sql b/util/dump.sql index aaa1a5e9..7a621103 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -1,15 +1,12 @@ - --- we don't use PgSQL's OIDS -SET default_with_oids = false; - --- for the functions to work, the following query must --- be executed on the database by a superuser: --- CREATE PROCEDURAL LANGUAGE plpgsql - +-- plpgsql is required for our (trigger) functions +CREATE LANGUAGE plpgsql; +-- data types +CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); +CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); ----------------------------------------- @@ -23,7 +20,7 @@ CREATE TABLE anime ( year smallint, ann_id integer, nfo_id varchar(200), - type smallint, + type anime_type, title_romaji, title_kanji, lastfetch timestamptz @@ -137,12 +134,6 @@ CREATE TABLE releases_vn ( PRIMARY KEY(rid, vid) ); --- relgraph -CREATE TABLE relgraph ( - id SERIAL NOT NULL PRIMARY KEY, - cmap text NOT NULL DEFAULT '' -); - -- rlists CREATE TABLE rlists ( uid integer NOT NULL DEFAULT 0, @@ -288,11 +279,17 @@ CREATE TABLE vn_anime ( PRIMARY KEY(vid, aid) ); +-- vn_graphs +CREATE TABLE vn_graphs ( + id SERIAL PRIMARY KEY, + svg xml NOT NULL +); + -- vn_relations CREATE TABLE vn_relations ( vid1 integer NOT NULL DEFAULT 0, vid2 integer NOT NULL DEFAULT 0, - relation integer NOT NULL DEFAULT 0, + relation vn_relation NOT NULL, PRIMARY KEY(vid1, vid2) ); @@ -380,7 +377,7 @@ ALTER TABLE threads_posts ADD FOREIGN KEY (tid) REFERENCES threads ALTER TABLE threads_posts ADD FOREIGN KEY (uid) REFERENCES users (id); ALTER TABLE threads_boards ADD FOREIGN KEY (tid) REFERENCES threads (id); ALTER TABLE vn ADD FOREIGN KEY (latest) REFERENCES vn_rev (id) DEFERRABLE INITIALLY DEFERRED; -ALTER TABLE vn ADD FOREIGN KEY (rgraph) REFERENCES relgraph (id); +ALTER TABLE vn ADD FOREIGN KEY (rgraph) REFERENCES vn_graphs (id); ALTER TABLE vn_anime ADD FOREIGN KEY (aid) REFERENCES anime (id); ALTER TABLE vn_anime ADD FOREIGN KEY (vid) REFERENCES vn_rev (id); ALTER TABLE vn_relations ADD FOREIGN KEY (vid1) REFERENCES vn_rev (id); -- cgit v1.2.3 From d96c546f8beb1fdc79847b462f46ced9332e4c48 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 9 Oct 2009 08:52:32 +0200 Subject: SQL: Converted releases_media.medium to an ENUM type --- lib/VNDB/DB/Releases.pm | 2 +- util/dump.sql | 5 +++-- util/updates/update_2.8.sql | 7 +++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/VNDB/DB/Releases.pm b/lib/VNDB/DB/Releases.pm index 672596da..05f42ab8 100644 --- a/lib/VNDB/DB/Releases.pm +++ b/lib/VNDB/DB/Releases.pm @@ -137,7 +137,7 @@ sub dbReleaseGet { } if($o{what} =~ /media/) { - ($_->{medium}=~s/\s+//||1)&&push(@{$r->[$r{$_->{rid}}]{media}}, $_) for (@{$self->dbAll(q| + push(@{$r->[$r{$_->{rid}}]{media}}, $_) for (@{$self->dbAll(q| SELECT rid, medium, qty FROM releases_media WHERE rid IN(!l)|, diff --git a/util/dump.sql b/util/dump.sql index 7a621103..b43d8c62 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -5,8 +5,9 @@ CREATE LANGUAGE plpgsql; -- data types -CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); +CREATE TYPE medium AS ENUM ('cd', 'dvd', 'gdr', 'blr', 'flp', 'mrt', 'mem', 'umd', 'nod', 'in', 'otc'); +CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); ----------------------------------------- @@ -86,7 +87,7 @@ CREATE TABLE releases_lang ( -- releases_media CREATE TABLE releases_media ( rid integer NOT NULL DEFAULT 0, - medium character(3) NOT NULL DEFAULT '', + medium medium NOT NULL, qty smallint NOT NULL DEFAULT 1, PRIMARY KEY(rid, medium, qty) ); diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index e72af294..df5221ee 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -47,3 +47,10 @@ ALTER TABLE anime ALTER COLUMN type TYPE anime_type USING ELSE NULL END; + +-- Release media stored as enum +CREATE TYPE medium AS ENUM ('cd', 'dvd', 'gdr', 'blr', 'flp', 'mrt', 'mem', 'umd', 'nod', 'in', 'otc'); +ALTER TABLE releases_media ALTER COLUMN medium DROP DEFAULT; +ALTER TABLE releases_media ALTER COLUMN medium TYPE medium USING TRIM(both ' ' from medium)::medium; + + -- cgit v1.2.3 From 9b379e376cbafc8408d8ff3318a39ca2631f510a Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 9 Oct 2009 08:56:20 +0200 Subject: Handler::Releases: Fixed display of media in filters --- lib/VNDB/Handler/Releases.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index 04ff716f..586bb666 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -654,7 +654,7 @@ sub _filters { for my $i (sort keys %{$self->{media}}) { span; input type => 'checkbox', name => 'me', value => $i, id => "med_$i", grep($_ eq $i, @{$f->{me}}) ? (checked => 'checked') : (); - label for => "med_$i", mt "_med_$i"; + label for => "med_$i", mt "_med_$i", 1; end; } -- cgit v1.2.3 From d43ae33a587743fc0916930e0a39f561f3174a69 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 9 Oct 2009 11:45:32 +0200 Subject: Added producer role (developer/publisher) to DB and release editor They aren't displayed on the site yet, though. --- ChangeLog | 1 + data/lang.txt | 12 ++++++++++++ data/script.js | 37 +++++++++++++++++++++++-------------- data/style.css | 3 ++- lib/VNDB/DB/Releases.pm | 8 ++++---- lib/VNDB/Handler/Releases.pm | 22 +++++++++++++++------- util/dump.sql | 3 +++ util/updates/update_2.8.sql | 5 +++++ 8 files changed, 65 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 857c2ad4..6a62b020 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ git - ? - Language strings are translatable - Information is automatically synchronised with data/global.pl - Changed language selector into a Javascript dropdown + - Added producer role (developer/publisher) to releases 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/lang.txt b/data/lang.txt index 0b00f7c5..e78bf30b 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -1942,6 +1942,18 @@ ru : Выбранные компании en : Add producer ru : Добавить компанию +:_redit_form_prod_dev +en : Developer +ru*: + +:_redit_form_prod_pub +en : Publisher +ru*: + +:_redit_form_prod_both +en : Both +ru*: + :_redit_form_prod_addbut en : add ru*: diff --git a/data/script.js b/data/script.js index bd56f12e..cc984230 100644 --- a/data/script.js +++ b/data/script.js @@ -1426,8 +1426,10 @@ if(byId('jt_box_rel_vn')) function rprLoad() { var ps = byId('producers').value.split('|||'); - for(var i=0; i<ps.length && ps[i].length>1; i++) - rprAdd(ps[i].split(',',2)[0], ps[i].split(',',2)[1]); + for(var i=0; i<ps.length && ps[i].length>1; i++) { + var val = ps[i].split(',',3); + rprAdd(val[0], val[1], val[2]); + } rprEmpty(); dsInit(byId('producer_input'), '/xml/producers.xml?q=', @@ -1442,12 +1444,17 @@ function rprLoad() { byId('producer_add').onclick = rprFormAdd; } -function rprAdd(id, name) { +function rprAdd(id, role, name) { + var roles = byId('producer_role').options; + var rl = tag('select', {onchange:rprSerialize}); + for(var i=0; i<roles.length; i++) + rl.appendChild(tag('option', {value: roles[i].value, selected:role==roles[i].value}, getText(roles[i]))); + byId('producer_tbl').appendChild(tag('tr', {id:'rpr_'+id, rpr_id:id}, tag('td', {'class':'tc_name'}, 'p'+id+':', tag('a', {href:'/p'+id}, shorten(name, 40))), + tag('td', {'class':'tc_role'}, rl), tag('td', {'class':'tc_rm'}, tag('a', {href:'#', onclick:rprDel}, mt('_redit_form_prod_remove'))) )); - rprStripe(); rprEmpty(); } @@ -1458,7 +1465,6 @@ function rprDel() { tr.parentNode.removeChild(tr); rprEmpty(); rprSerialize(); - rprStripe(); return false; } @@ -1470,12 +1476,6 @@ function rprEmpty() { tbl.removeChild(byId('rpr_tr_none')); } -function rprStripe() { - var l = byName(byId('producer_tbl'), 'tr'); - for(var i=0; i<l.length; i++) - setClass(l[i], 'odd', i%2); -} - function rprFormAdd() { var txt = byId('producer_input'); var lnk = byId('producer_add'); @@ -1503,7 +1503,10 @@ function rprFormAdd() { if(byId('rpr_'+id)) return alert(mt('_redit_form_prod_double')); - rprAdd(id, items[0].firstChild.nodeValue); + var role = byId('producer_role'); + role = role[role.selectedIndex].value; + + rprAdd(id, role, items[0].firstChild.nodeValue); rprSerialize(); }); return false; @@ -1513,8 +1516,14 @@ function rprSerialize() { var r = []; var l = byName(byId('producer_tbl'), 'tr'); for(var i=0; i<l.length; i++) - if(l[i].rpr_id) - r[r.length] = l[i].rpr_id + ',' + getText(byName(byClass(l[i], 'td', 'tc_name')[0], 'a')[0]); + if(l[i].rpr_id) { + var role = byName(byClass(l[i], 'td', 'tc_role')[0], 'select')[0]; + r[r.length] = [ + l[i].rpr_id, + role.options[role.selectedIndex].value, + getText(byName(byClass(l[i], 'td', 'tc_name')[0], 'a')[0]) + ].join(','); + } byId('producers').value = r.join('|||'); } diff --git a/data/style.css b/data/style.css index af9370e3..56c68f3c 100644 --- a/data/style.css +++ b/data/style.css @@ -870,8 +870,9 @@ div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px #jt_box_rel_vn h2, #jt_box_rel_prod h2 { clear: left; padding-top: 10px; } #jt_box_rel_vn div, #jt_box_rel_vn table, #jt_box_rel_prod div, #jt_box_rel_prod table { margin-left: 20px } -#jt_box_rel_vn input, #jt_box_rel_prod input { margin-right: 10px; width: 300px } +#jt_box_rel_vn input, #jt_box_rel_prod input { margin-right: 10px; width: 295px } #jt_box_rel_vn .tc_title, #jt_box_rel_prod .tc_name { width: 310px; padding: 2px } +#jt_box_rel_prod .tc_role select { width: 100px; margin-right: 10px; } diff --git a/lib/VNDB/DB/Releases.pm b/lib/VNDB/DB/Releases.pm index 05f42ab8..551855e8 100644 --- a/lib/VNDB/DB/Releases.pm +++ b/lib/VNDB/DB/Releases.pm @@ -117,7 +117,7 @@ sub dbReleaseGet { if($o{what} =~ /producers/) { push(@{$r->[$r{$_->{rid}}]{producers}}, $_) for (@{$self->dbAll(q| - SELECT rp.rid, p.id, pr.name, pr.original, pr.type + SELECT rp.rid, rp.developer, rp.publisher, p.id, pr.name, pr.original, pr.type FROM releases_producers rp JOIN producers p ON rp.pid = p.id JOIN producers_rev pr ON pr.id = p.latest @@ -189,9 +189,9 @@ sub insert_rev { ) for (@{$o->{languages}}); $self->dbExec(q| - INSERT INTO releases_producers (rid, pid) - VALUES (?, ?)|, - $cid, $_ + INSERT INTO releases_producers (rid, pid, developer, publisher) + VALUES (?, ?, ?, ?)|, + $cid, $_->[0], $_->[1]?1:0, $_->[2]?1:0 ) for (@{$o->{producers}}); $self->dbExec(q| diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index 586bb666..763ff59c 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -284,7 +284,10 @@ sub edit { (map { $_ => $r->{$_} } qw|type title original gtin catalog languages website released notes minage platforms patch resolution voiced freeware doujin ani_story ani_ero|), media => join(',', sort map "$_->{medium} $_->{qty}", @{$r->{media}}), - producers => join('|||', map "$_->{id},$_->{name}", sort { $a->{id} <=> $b->{id} } @{$r->{producers}}), + producers => join('|||', map + sprintf('%d,%d,%s', $_->{id}, ($_->{developer}?1:0)+($_->{publisher}?2:0), $_->{name}), + sort { $a->{id} <=> $b->{id} } @{$r->{producers}} + ), ); $b4{vn} = join('|||', map "$_->{vid},$_->{title}", @$vn); my $frm; @@ -320,7 +323,7 @@ sub edit { if(!$frm->{_err}) { # de-serialize $media = [ map [ split / / ], split /,/, $frm->{media} ]; - $producers = [ map { /^([0-9]+)/ ? $1 : () } split /\|\|\|/, $frm->{producers} ]; + $producers = [ map { /^([0-9]+),([1-3])/ ? [ $1, $2&1?1:0, $2&2?1:0] : () } split /\|\|\|/, $frm->{producers} ]; $new_vn = [ map { /^([0-9]+)/ ? $1 : () } split /\|\|\|/, $frm->{vn} ]; $frm->{platforms} = [ grep $_, @{$frm->{platforms}} ]; $frm->{$_} = $frm->{$_} ? 1 : 0 for (qw|patch freeware doujin|); @@ -330,7 +333,7 @@ sub edit { my $same = $rid && (join(',', sort @{$b4{platforms}}) eq join(',', sort @{$frm->{platforms}})) && - (join(',', sort @$producers) eq join(',', sort map $_->{id}, @{$r->{producers}})) && + (join(',', map join(' ', @$_), sort { $a->[0] <=> $b->[0] } @$producers) eq join(',', sort map sprintf('%d %d %d',$_->{id}, $_->{developer}?1:0, $_->{publisher}?1:0), sort { $a->{id} <=> $b->{id} } @{$r->{producers}})) && (join(',', sort @$new_vn) eq join(',', sort map $_->{vid}, @$vn)) && (join(',', sort @{$b4{languages}}) eq join(',', sort @{$frm->{languages}})) && !grep !/^(platforms|producers|vn|languages)$/ && $frm->{$_} ne $b4{$_}, keys %b4; @@ -443,10 +446,15 @@ sub _form { h2 mt('_redit_form_prod_sel'); table; tbody id => 'producer_tbl'; end; end; h2 mt('_redit_form_prod_add'); - div; - input id => 'producer_input', type => 'text', class => 'text'; - a id => 'producer_add', href => '#', mt '_redit_form_prod_addbut'; - end; + 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'; + end; end; + td class => 'tc_add'; a id => 'producer_add', href => '#', mt '_redit_form_prod_addbut'; end; + end; end; }], ], diff --git a/util/dump.sql b/util/dump.sql index b43d8c62..10d13b9d 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -103,6 +103,9 @@ CREATE TABLE releases_platforms ( CREATE TABLE releases_producers ( rid integer NOT NULL, pid integer NOT NULL, + developer boolean NOT NULL DEFAULT FALSE, + publisher boolean NOT NULL DEFAULT TRUE, + CHECK(developer OR publisher), PRIMARY KEY(pid, rid) ); diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index df5221ee..2993467c 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -54,3 +54,8 @@ ALTER TABLE releases_media ALTER COLUMN medium DROP DEFAULT; ALTER TABLE releases_media ALTER COLUMN medium TYPE medium USING TRIM(both ' ' from medium)::medium; +-- Differentiate between publishers and developers +ALTER TABLE releases_producers ADD COLUMN developer boolean NOT NULL DEFAULT FALSE; +ALTER TABLE releases_producers ADD COLUMN publisher boolean NOT NULL DEFAULT TRUE; +ALTER TABLE releases_producers ADD CHECK(developer OR publisher); + -- cgit v1.2.3 From 4c4546ca2410844effb2edc72b80a3e1f8465f71 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 9 Oct 2009 17:41:41 +0200 Subject: Handler::Releases: Display producer role on release pages Still the VN & producer pages to go... --- data/lang.txt | 18 +++++++++++++++--- lib/VNDB/Handler/Releases.pm | 27 ++++++++++++++++----------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index e78bf30b..f6cd103e 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -1682,6 +1682,14 @@ ru : Анимация эросцен en : Producers ru : Компании +:_reldiff_developer +en : developer +ru*: + +:_reldiff_publisher +en : publisher +ru*: + # Information table (on every release page) @@ -1757,9 +1765,13 @@ ru : Дата выпуска en : Age rating ru : Возрастной рейтинг -:_relinfo_producer -en : [quant,_1,Producer,Producers] -ru : [quant,_1,Компания,Компании,Компаний] +:_relinfo_developer +en : [quant,_1,Developer,Developers] +ru*: + +:_relinfo_publisher +en : [quant,_1,Publisher,Publishers] +ru*: :_relinfo_catalog en : Catalog no. diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index 763ff59c..d771d4b1 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -61,7 +61,9 @@ sub page { [ ani_story => serialize => sub { mt '_animated_'.$_[0] } ], [ ani_ero => serialize => sub { mt '_animated_'.$_[0] } ], [ producers => join => '<br />', split => sub { - map sprintf('<a href="/p%d" title="%s">%s</a>', $_->{id}, $_->{original}||$_->{name}, shorten $_->{name}, 50), @{$_[0]}; + 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' :()) + ), @{$_[0]}; } ], ); } @@ -194,16 +196,19 @@ sub _infotable { end; } - if(@{$r->{producers}}) { - Tr ++$i % 2 ? (class => 'odd') : (); - td mt '_relinfo_producer', scalar @{$r->{producers}}; - td; - for (@{$r->{producers}}) { - a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 60; - br if $_ != $r->{producers}[$#{$r->{producers}}]; - } - end; - end; + for my $t (qw|developer publisher|) { + my @prod = grep $_->{$t}, @{$r->{producers}}; + if(@prod) { + Tr ++$i % 2 ? (class => 'odd') : (); + td mt "_relinfo_$t", scalar @prod; + td; + for (@prod) { + a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 60; + br if $_ != $prod[$#prod]; + } + end; + end; + } } if($r->{gtin}) { -- cgit v1.2.3 From 1e125f67ab50a5de477c538b3f7dd27a9ec3c62f Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 10 Oct 2009 12:46:43 +0200 Subject: Updated Producer and VN pages with developer/publisher information --- data/lang.txt | 18 ++++++++++++++--- lib/VNDB/DB/Producers.pm | 3 ++- lib/VNDB/Handler/Producers.pm | 2 ++ lib/VNDB/Handler/VNPage.pm | 45 ++++++++++++++++++++++++++++--------------- 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index f6cd103e..06b54cc7 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -1486,6 +1486,14 @@ ru : Связи новелл en : We have currently no visual novels by this producer. ru : У нас пока нет сведений о новеллах авторства этой компании. +:_prodpage_dev +en : developer +ru*: + +:_prodpage_pub +en : publisher +ru*: + # producer diff fields @@ -3550,9 +3558,13 @@ ru : суммарно en : all ru : все -:_vnpage_producers -en : Producers -ru : Компании +:_vnpage_developer +en : Developer +ru*: + +:_vnpage_publisher +en : Publishers +ru*: :_vnpage_relations en : Relations diff --git a/lib/VNDB/DB/Producers.pm b/lib/VNDB/DB/Producers.pm index 65d1fbca..18f372f9 100644 --- a/lib/VNDB/DB/Producers.pm +++ b/lib/VNDB/DB/Producers.pm @@ -61,7 +61,8 @@ sub dbProducerGet { } 0..$#$r; push @{$r->[$r{$_->{pid}}]{vn}}, $_ for (@{$self->dbAll(q| - SELECT MAX(vp.pid) AS pid, v.id, MAX(vr.title) AS title, MAX(vr.original) AS original, MIN(rr.released) AS date + SELECT MAX(vp.pid) AS pid, v.id, MAX(vr.title) AS title, MAX(vr.original) AS original, MIN(rr.released) AS date, + MAX(CASE WHEN vp.developer = true THEN 1 ELSE 0 END) AS developer, MAX(CASE WHEN vp.publisher = true THEN 1 ELSE 0 END) AS publisher FROM releases_producers vp JOIN releases_rev rr ON rr.id = vp.rid JOIN releases r ON r.latest = rr.id diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm index e6477567..241ff00c 100644 --- a/lib/VNDB/Handler/Producers.pm +++ b/lib/VNDB/Handler/Producers.pm @@ -75,6 +75,8 @@ sub page { lit $self->{l10n}->datestr($_->{date}); end; a href => "/v$_->{id}", title => $_->{original}, $_->{title}; + b class => 'grayedout', ' ('.join(', ', + $_->{developer} ? mt '_prodpage_dev' : (), $_->{publisher} ? mt '_prodpage_pub' : ()).')'; end; } end; diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 16f80ef1..248d1d43 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -261,27 +261,42 @@ sub _revision { sub _producers { my($self, $i, $r) = @_; - return if !grep @{$_->{producers}}, @$r; my %lang; my @lang = grep !$lang{$_}++, map @{$_->{languages}}, @$r; - Tr ++$$i % 2 ? (class => 'odd') : (); - td mt '_vnpage_producers'; - td; - for my $l (@lang) { - my %p = map { $_->{id} => $_ } map @{$_->{producers}}, grep grep($_ eq $l, @{$_->{languages}}), @$r; - my @p = values %p; - next if !@p; - cssicon "lang $l", mt "_lang_$l"; - for (@p) { + if(grep $_->{developer}, map @{$_->{producers}}, @$r) { + my %dev = map $_->{developer} ? ($_->{id} => $_) : (), map @{$_->{producers}}, @$r; + my @dev = values %dev; + Tr ++$$i % 2 ? (class => 'odd') : (); + td mt "_vnpage_developer"; + td; + for (@dev) { a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 30; - txt ' & ' if $_ != $p[$#p]; + txt ' & ' if $_ != $dev[$#dev]; } - txt "\n"; - } - end; - end; + end; + end; + } + + if(grep $_->{publisher}, map @{$_->{producers}}, @$r) { + Tr ++$$i % 2 ? (class => 'odd') : (); + td mt "_vnpage_publisher"; + td; + for my $l (@lang) { + my %p = map $_->{publisher} ? ($_->{id} => $_) : (), map @{$_->{producers}}, grep grep($_ eq $l, @{$_->{languages}}), @$r; + my @p = values %p; + next if !@p; + cssicon "lang $l", mt "_lang_$l"; + for (@p) { + a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 30; + txt ' & ' if $_ != $p[$#p]; + } + txt "\n"; + } + end; + end; + } } -- cgit v1.2.3 From 5ce2ce4c494feef5940c032549472a52b5282ad1 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 10 Oct 2009 15:51:57 +0200 Subject: Display number of unread posts in user menu Instead of displaying the total number of threads. Posts are marked as read when the thread is opened. --- ChangeLog | 1 + lib/VNDB/DB/Discussions.pm | 12 +++++++++++- lib/VNDB/DB/Users.pm | 8 +++++++- lib/VNDB/Handler/Discussions.pm | 5 +++++ util/dump.sql | 1 + util/updates/update_2.8.sql | 5 +++++ 6 files changed, 30 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6a62b020..f7022b15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,7 @@ git - ? - Information is automatically synchronised with data/global.pl - Changed language selector into a Javascript dropdown - Added producer role (developer/publisher) to releases + - Display number of unread posts in "My messages" (instead of total threads) 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/lib/VNDB/DB/Discussions.pm b/lib/VNDB/DB/Discussions.pm index 26beaaee..60487098 100644 --- a/lib/VNDB/DB/Discussions.pm +++ b/lib/VNDB/DB/Discussions.pm @@ -5,7 +5,7 @@ use strict; use warnings; use Exporter 'import'; -our @EXPORT = qw|dbThreadGet dbThreadEdit dbThreadAdd dbPostGet dbPostEdit dbPostAdd dbThreadCount|; +our @EXPORT = qw|dbThreadGet dbThreadEdit dbThreadAdd dbPostGet dbPostEdit dbPostAdd dbThreadCount dbPostRead|; # Options: id, type, iid, results, page, what, notusers @@ -243,5 +243,15 @@ sub dbPostAdd { } +sub dbPostRead { # thread id, user id, last post number + my($s, $tid, $uid, $num) = @_; + $s->dbExec(q| + UPDATE threads_boards + SET lastread = ? + WHERE tid = ? AND type = 'u' AND iid = ?|, + $num, $tid, $uid); +} + + 1; diff --git a/lib/VNDB/DB/Users.pm b/lib/VNDB/DB/Users.pm index b2cd1a31..cb25b9fe 100644 --- a/lib/VNDB/DB/Users.pm +++ b/lib/VNDB/DB/Users.pm @@ -54,7 +54,13 @@ sub dbUserGet { '(SELECT COUNT(DISTINCT vid) FROM tags_vn WHERE uid = u.id) AS tagvncount', ) : (), $o{what} =~ /mymessages/ ? - '(SELECT COUNT(*) FROM threads_boards tb JOIN threads t ON t.id = tb.tid WHERE tb.type = \'u\' AND tb.iid = u.id AND t.hidden = FALSE) AS mymessages' : (), + q{COALESCE((SELECT SUM(tbi.count) FROM ( + SELECT t.count-COALESCE(tb.lastread,0) + FROM threads_boards tb + JOIN threads t ON t.id = tb.tid AND NOT t.hidden + WHERE tb.type = 'u' AND tb.iid = u.id) AS tbi (count) + ), 0) AS mymessages + } : (), ); my($r, $np) = $s->dbPage(\%o, q| diff --git a/lib/VNDB/Handler/Discussions.pm b/lib/VNDB/Handler/Discussions.pm index 1d74ac6a..5fedaeed 100644 --- a/lib/VNDB/Handler/Discussions.pm +++ b/lib/VNDB/Handler/Discussions.pm @@ -29,6 +29,11 @@ sub thread { my $p = $self->dbPostGet(tid => $tid, results => 25, page => $page, what => 'user'); return 404 if !$p->[0]; + # mark as read when this thread is posted in the board of the currently logged in user + my $uid = $self->authInfo->{id}; + $self->dbPostRead($t->{id}, $uid, $p->[$#$p]{num}) + if $uid && grep $_->{type} eq 'u' && $_->{iid} == $uid, @{$t->{boards}}; + $self->htmlHeader(title => $t->{title}); div class => 'mainbox'; diff --git a/util/dump.sql b/util/dump.sql index 10d13b9d..c952c162 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -240,6 +240,7 @@ CREATE TABLE threads_boards ( tid integer NOT NULL DEFAULT 0, type character(2) NOT NULL DEFAULT 0, iid integer NOT NULL DEFAULT 0, + lastread smallint NOT NULL, PRIMARY KEY(tid, type, iid) ); diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index 2993467c..a90b3ac2 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -59,3 +59,8 @@ ALTER TABLE releases_producers ADD COLUMN developer boolean NOT NULL DEFAULT FAL ALTER TABLE releases_producers ADD COLUMN publisher boolean NOT NULL DEFAULT TRUE; ALTER TABLE releases_producers ADD CHECK(developer OR publisher); + +-- Keep track of last read post for PMs +ALTER TABLE threads_boards ADD COLUMN lastread smallint; + + -- cgit v1.2.3 From 5453223bf93a17d49d2717f8e0fbc70ed8477a94 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 10 Oct 2009 15:53:08 +0200 Subject: Make "My Messages (n)" stand out when n>0 Not very obstructive now that number will automatically reset itself after opening the threads. --- data/style.css | 2 +- lib/VNDB/Util/LayoutHTML.pm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/style.css b/data/style.css index 56c68f3c..483ef6d1 100644 --- a/data/style.css +++ b/data/style.css @@ -239,7 +239,7 @@ td.field label { p.center { text-align: center; } -b.future, b.standout { +b.future, b.standout, a.standout { font-weight: normal; color: $standout$; } diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm index d9dad434..34cbd30d 100644 --- a/lib/VNDB/Util/LayoutHTML.pm +++ b/lib/VNDB/Util/LayoutHTML.pm @@ -89,7 +89,7 @@ sub _menu { a href => "$uid/edit", mt '_menu_myprofile'; br; a href => "$uid/list", mt '_menu_myvnlist'; br; a href => "$uid/wish", mt '_menu_mywishlist'; br; - a href => "/t$uid", mt '_menu_mymessages', $self->authInfo->{mymessages}; br; + a href => "/t$uid", $self->authInfo->{mymessages} ? (class => 'standout') : (), mt '_menu_mymessages', $self->authInfo->{mymessages}; br; a href => "$uid/hist", mt '_menu_mychanges'; br; a href => "$uid/tags", mt '_menu_mytags'; br; br; -- cgit v1.2.3 From ecf82cabc44dcd333f0e46c037c7d9c1c4046a0d Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 10 Oct 2009 16:05:30 +0200 Subject: Get unread posts count in htmlHeader() instead of Util::Auth This way the counter resets itself immediately when opening the unread thread page, which is more intuitive. --- lib/VNDB/DB/Users.pm | 26 ++++++++++++++++---------- lib/VNDB/Util/Auth.pm | 4 ++-- lib/VNDB/Util/LayoutHTML.pm | 3 ++- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/VNDB/DB/Users.pm b/lib/VNDB/DB/Users.pm index cb25b9fe..ee4f2b14 100644 --- a/lib/VNDB/DB/Users.pm +++ b/lib/VNDB/DB/Users.pm @@ -5,11 +5,11 @@ use strict; use warnings; use Exporter 'import'; -our @EXPORT = qw|dbUserGet dbUserEdit dbUserAdd dbUserDel dbSessionAdd dbSessionDel dbSessionCheck|; +our @EXPORT = qw|dbUserGet dbUserEdit dbUserAdd dbUserDel dbUserMessageCount dbSessionAdd dbSessionDel dbSessionCheck|; # %options->{ username passwd mail order uid ip registered search results page what } -# what: stats mymessages +# what: stats sub dbUserGet { my $s = shift; my %o = ( @@ -53,14 +53,6 @@ sub dbUserGet { '(SELECT COUNT(DISTINCT tag) FROM tags_vn WHERE uid = u.id) AS tagcount', '(SELECT COUNT(DISTINCT vid) FROM tags_vn WHERE uid = u.id) AS tagvncount', ) : (), - $o{what} =~ /mymessages/ ? - q{COALESCE((SELECT SUM(tbi.count) FROM ( - SELECT t.count-COALESCE(tb.lastread,0) - FROM threads_boards tb - JOIN threads t ON t.id = tb.tid AND NOT t.hidden - WHERE tb.type = 'u' AND tb.iid = u.id) AS tbi (count) - ), 0) AS mymessages - } : (), ); my($r, $np) = $s->dbPage(\%o, q| @@ -116,6 +108,20 @@ sub dbUserDel { } +# Returns number of unread messages +sub dbUserMessageCount { # uid + my($s, $uid) = @_; + return $s->dbRow(q{ + SELECT SUM(tbi.count) AS cnt FROM ( + SELECT t.count-COALESCE(tb.lastread,0) + FROM threads_boards tb + JOIN threads t ON t.id = tb.tid AND NOT t.hidden + WHERE tb.type = 'u' AND tb.iid = ? + ) AS tbi (count) + }, $uid)->{cnt}||0; +} + + # Adds a session to the database # If no expiration is supplied the database default is used # uid, 40 character session token, expiration time (timestamp) diff --git a/lib/VNDB/Util/Auth.pm b/lib/VNDB/Util/Auth.pm index c4daffd9..2595ce5b 100644 --- a/lib/VNDB/Util/Auth.pm +++ b/lib/VNDB/Util/Auth.pm @@ -26,7 +26,7 @@ sub authInit { my $token = substr($cookie, 0, 40); my $uid = substr($cookie, 40); return _rmcookie($self) if $uid !~ /^\d+$/ || !$self->dbSessionCheck($uid, $token); - $self->{_auth} = $self->dbUserGet(uid => $uid, what => 'mymessages')->[0]; + $self->{_auth} = $self->dbUserGet(uid => $uid)->[0]; } @@ -95,7 +95,7 @@ sub _authCheck { return 0 if !$user || length($user) > 15 || length($user) < 2 || !$pass; - my $d = $self->dbUserGet(username => $user, what => 'mymessages')->[0]; + my $d = $self->dbUserGet(username => $user)->[0]; return 0 if !defined $d->{id} || !$d->{rank}; if(_authEncryptPass($self, $pass, $d->{salt}) eq $d->{passwd}) { diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm index 34cbd30d..084b9a4e 100644 --- a/lib/VNDB/Util/LayoutHTML.pm +++ b/lib/VNDB/Util/LayoutHTML.pm @@ -79,6 +79,7 @@ sub _menu { div class => 'menubox'; if($self->authInfo->{id}) { + my $msg = $self->dbUserMessageCount($self->authInfo->{id}); my $uid = sprintf '/u%d', $self->authInfo->{id}; h2; a href => $uid, ucfirst $self->authInfo->{username}; @@ -89,7 +90,7 @@ sub _menu { a href => "$uid/edit", mt '_menu_myprofile'; br; a href => "$uid/list", mt '_menu_myvnlist'; br; a href => "$uid/wish", mt '_menu_mywishlist'; br; - a href => "/t$uid", $self->authInfo->{mymessages} ? (class => 'standout') : (), mt '_menu_mymessages', $self->authInfo->{mymessages}; br; + a href => "/t$uid", $msg ? (class => 'standout') : (), mt '_menu_mymessages', $msg; br; a href => "$uid/hist", mt '_menu_mychanges'; br; a href => "$uid/tags", mt '_menu_mytags'; br; br; -- cgit v1.2.3 From 64007de03cba6c0acb8a2782bc5f86bcad946850 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 10 Oct 2009 16:33:56 +0200 Subject: Greatly reduced default number of columns returned by dbUserGet Most of the columns are only used in some rare situations, so fetching all that information is unecessary. To fetch this information, a what => 'extended' is now required. This change should be most noticable for the user list (now less than half of the previous data is fetched from the database). --- ChangeLog | 1 + lib/VNDB/DB/Users.pm | 10 +++++++--- lib/VNDB/Handler/Users.pm | 2 +- lib/VNDB/Util/Auth.pm | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index f7022b15..40fd4eb9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,7 @@ git - ? - Changed language selector into a Javascript dropdown - Added producer role (developer/publisher) to releases - Display number of unread posts in "My messages" (instead of total threads) + - Optimized dbUserGet (mostly for the user list) 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/lib/VNDB/DB/Users.pm b/lib/VNDB/DB/Users.pm index ee4f2b14..593c6415 100644 --- a/lib/VNDB/DB/Users.pm +++ b/lib/VNDB/DB/Users.pm @@ -9,7 +9,7 @@ our @EXPORT = qw|dbUserGet dbUserEdit dbUserAdd dbUserDel dbUserMessageCount dbS # %options->{ username passwd mail order uid ip registered search results page what } -# what: stats +# what: stats extended sub dbUserGet { my $s = shift; my %o = ( @@ -43,8 +43,12 @@ sub dbUserGet { ); my @select = ( - qw|id username mail rank salt c_votes c_changes show_nsfw show_list skin customcss ip c_tags ign_votes|, - q|encode(passwd, 'hex') AS passwd|, q|extract('epoch' from registered) as registered|, + qw|id username c_votes c_changes show_list c_tags|, + q|extract('epoch' from registered) as registered|, + $o{what} =~ /extended/ ? ( + qw|mail rank salt skin customcss show_nsfw ign_votes|, + q|encode(passwd, 'hex') AS passwd| + ) : (), $o{what} =~ /stats/ ? ( '(SELECT COUNT(*) FROM rlists WHERE uid = u.id) AS releasecount', '(SELECT COUNT(DISTINCT rv.vid) FROM rlists rl JOIN releases r ON rl.rid = r.id JOIN releases_vn rv ON rv.rid = r.latest WHERE uid = u.id) AS vncount', diff --git a/lib/VNDB/Handler/Users.pm b/lib/VNDB/Handler/Users.pm index 1a4b993b..39aecbfc 100644 --- a/lib/VNDB/Handler/Users.pm +++ b/lib/VNDB/Handler/Users.pm @@ -267,7 +267,7 @@ sub edit { return $self->htmlDenied if !$self->authInfo->{id} || $self->authInfo->{id} != $uid && !$self->authCan('usermod'); # fetch user info (cached if uid == loggedin uid) - my $u = $self->authInfo->{id} == $uid ? $self->authInfo : $self->dbUserGet(uid => $uid)->[0]; + my $u = $self->authInfo->{id} == $uid ? $self->authInfo : $self->dbUserGet(uid => $uid, what => 'extended')->[0]; return 404 if !$u->{id}; # check POST data diff --git a/lib/VNDB/Util/Auth.pm b/lib/VNDB/Util/Auth.pm index 2595ce5b..a3bf7c29 100644 --- a/lib/VNDB/Util/Auth.pm +++ b/lib/VNDB/Util/Auth.pm @@ -26,7 +26,7 @@ sub authInit { my $token = substr($cookie, 0, 40); my $uid = substr($cookie, 40); return _rmcookie($self) if $uid !~ /^\d+$/ || !$self->dbSessionCheck($uid, $token); - $self->{_auth} = $self->dbUserGet(uid => $uid)->[0]; + $self->{_auth} = $self->dbUserGet(uid => $uid, what => 'extended')->[0]; } @@ -95,7 +95,7 @@ sub _authCheck { return 0 if !$user || length($user) > 15 || length($user) < 2 || !$pass; - my $d = $self->dbUserGet(username => $user)->[0]; + my $d = $self->dbUserGet(username => $user, what => 'extended')->[0]; return 0 if !defined $d->{id} || !$d->{rank}; if(_authEncryptPass($self, $pass, $d->{salt}) eq $d->{passwd}) { -- cgit v1.2.3 From 0c5a9606dd9047522c4357e36e5fe9081943b947 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 10 Oct 2009 17:01:02 +0200 Subject: List all known languages on /r and /v/all instead of only those in use Performance improvement of ~15ms for all release and VN browse pages. There are in total 20 known languages in the DB, and 12 of them are actually used (i.e. a release in that language exists). Which means 8 of the listed language filters won't produce any results (yet), but I'd say that's an accaptable trade-off. --- ChangeLog | 1 + lib/VNDB/DB/Misc.pm | 16 +--------------- lib/VNDB/Handler/Releases.pm | 2 +- lib/VNDB/Handler/VNBrowse.pm | 2 +- 4 files changed, 4 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 40fd4eb9..b29cab16 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,7 @@ git - ? - Added producer role (developer/publisher) to releases - Display number of unread posts in "My messages" (instead of total threads) - Optimized dbUserGet (mostly for the user list) + - All languages are listed on /r and /v/all instead of only those in use 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/lib/VNDB/DB/Misc.pm b/lib/VNDB/DB/Misc.pm index eeb860b0..ed3730ee 100644 --- a/lib/VNDB/DB/Misc.pm +++ b/lib/VNDB/DB/Misc.pm @@ -6,7 +6,7 @@ use warnings; use Exporter 'import'; our @EXPORT = qw| - dbStats dbRevisionInsert dbItemInsert dbRevisionGet dbItemMod dbLanguages dbRandomQuote + dbStats dbRevisionInsert dbItemInsert dbRevisionGet dbItemMod dbRandomQuote |; @@ -160,20 +160,6 @@ sub dbItemMod { } -# Returns a list of languages actually in use -sub dbLanguages { - my $self = shift; - return [ - map $_->{lang}, @{$self->dbAll(q| - SELECT DISTINCT rl.lang - FROM releases r - JOIN releases_lang rl ON rl.rid = r.latest - WHERE r.hidden = FALSE| - )} - ]; -} - - # Returns a random quote (hashref with keys = vid, quote) sub dbRandomQuote { return $_[0]->dbRow(q| diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index d771d4b1..62776fd2 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -635,7 +635,7 @@ sub _filters { txt mt '_rbrowse_languages'; b ' ('.mt('_rbrowse_boolor').')'; end; - for my $i (sort @{$self->dbLanguages}) { + for my $i (@{$self->{languages}}) { span; input type => 'checkbox', name => 'ln', value => $i, id => "lang_$i", grep($_ eq $i, @{$f->{ln}}) ? (checked => 'checked') : (); label for => "lang_$i"; diff --git a/lib/VNDB/Handler/VNBrowse.pm b/lib/VNDB/Handler/VNBrowse.pm index b0c948cd..118a5ee2 100644 --- a/lib/VNDB/Handler/VNBrowse.pm +++ b/lib/VNDB/Handler/VNBrowse.pm @@ -162,7 +162,7 @@ sub _filters { txt mt '_vnbrowse_lang'; b ' ('.mt('_vnbrowse_boolor').')'; end; - for my $i (sort @{$self->dbLanguages}) { + for my $i (@{$self->{languages}}) { span; input type => 'checkbox', name => 'ln', value => $i, id => "lang_$i", (scalar grep $_ eq $i, @{$f->{ln}}) ? (checked => 'checked') : (); -- cgit v1.2.3 From 69d8738688ebb72707fe377b7ce7c717407aea96 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Mon, 12 Oct 2009 09:34:06 +0200 Subject: SQL: Converted changes.type to an ENUM This is a very important column in a very important table, I hope I didn't forget to update a piece of code somewhere... --- lib/Multi/IRC.pm | 8 ++++---- lib/VNDB/DB/Misc.pm | 24 ++++++++++++------------ lib/VNDB/DB/Producers.pm | 4 ++-- lib/VNDB/DB/Releases.pm | 4 ++-- lib/VNDB/DB/VN.pm | 4 ++-- lib/VNDB/Handler/Misc.pm | 5 ++--- lib/VNDB/Util/CommonHTML.pm | 5 ++--- util/dump.sql | 9 +++++---- util/updates/update_2.8.sql | 11 +++++++++++ 9 files changed, 42 insertions(+), 32 deletions(-) diff --git a/lib/Multi/IRC.pm b/lib/Multi/IRC.pm index 5018d2aa..4225e6b8 100644 --- a/lib/Multi/IRC.pm +++ b/lib/Multi/IRC.pm @@ -266,12 +266,12 @@ sub notify { # name, pid, payload return if !$_[HEAP]{$k}; my $q = $_[ARG0] eq 'newrevision' ? q|SELECT - CASE WHEN c.type = 0 THEN 'v' WHEN c.type = 1 THEN 'r' ELSE 'p' END AS type, c.rev, c.comments, c.id AS lastrev, + CASE WHEN c.type, c.rev, c.comments, c.id AS lastrev, COALESCE(vr.vid, rr.rid, pr.pid) AS id, COALESCE(vr.title, rr.title, pr.name) AS title, u.username FROM changes c - LEFT JOIN vn_rev vr ON c.type = 0 AND c.id = vr.id - LEFT JOIN releases_rev rr ON c.type = 1 AND c.id = rr.id - LEFT JOIN producers_rev pr ON c.type = 2 AND c.id = pr.id + LEFT JOIN vn_rev vr ON c.type = 'v' AND c.id = vr.id + LEFT JOIN releases_rev rr ON c.type = 'r' AND c.id = rr.id + LEFT JOIN producers_rev pr ON c.type = 'p' AND c.id = pr.id JOIN users u ON u.id = c.requester WHERE c.id > ? AND c.requester <> 1 ORDER BY c.added| diff --git a/lib/VNDB/DB/Misc.pm b/lib/VNDB/DB/Misc.pm index ed3730ee..b3522d72 100644 --- a/lib/VNDB/DB/Misc.pm +++ b/lib/VNDB/DB/Misc.pm @@ -24,12 +24,12 @@ sub dbStats { # This function leaves the DB in an inconsistent state, the actual revision # will have to be inserted directly after calling this function, otherwise # the commit will fail. -# Arguments: type [0..2], item ID, edit summary +# Arguments: type [vrp], item ID, edit summary # Returns: local revision, global revision sub dbRevisionInsert { my($self, $type, $iid, $editsum, $uid) = @_; - my $table = [qw|vn releases producers|]->[$type]; + my $table = {qw|v vn r releases p producers|}->{$type}; my $c = $self->dbRow(q| INSERT INTO changes (type, requester, ip, comments, rev) @@ -43,7 +43,7 @@ sub dbRevisionInsert { )) RETURNING id, rev|, $type, $uid||$self->authInfo->{id}, $self->reqIP, $editsum, - $table, [qw|v r p|]->[$type], $iid + $table, $type, $iid ); $self->dbExec(q|UPDATE !s SET latest = ? WHERE id = ?|, $table, $c->{id}, $iid); @@ -54,7 +54,7 @@ sub dbRevisionInsert { # Comparable to RevisionInsert, but creates a new item with a corresponding # change. Same things about inconsistent state, etc. -# Argumments: type [0..2], edit summary, [uid] +# Argumments: type [vrp], edit summary, [uid] # Returns: item id, global revision sub dbItemInsert { my($self, $type, $editsum, $uid) = @_; @@ -70,7 +70,7 @@ sub dbItemInsert { INSERT INTO !s (latest) VALUES (?) RETURNING id|, - [qw|vn releases producers|]->[$type], $cid + {qw|v vn r releases p producers|}->{$type}, $cid )->{id}; return ($iid, $cid); @@ -94,7 +94,7 @@ sub dbRevisionGet { '((c.type = ? AND vr.vid = ?) OR (c.type = ? AND rv.vid = ?))' => [0, $o{iid}, 1, $o{iid}], ) : ( $o{type} ? ( - 'c.type = ?' => { v=>0, r=>1, p=>2 }->{$o{type}} ) : (), + 'c.type = ?' => $o{type} ) : (), $o{iid} ? ( '!sr.!sid = ?' => [ $o{type}, $o{type}, $o{iid} ] ) : (), ), @@ -113,14 +113,14 @@ sub dbRevisionGet { my @join = ( $o{iid} || $o{what} =~ /item/ || $o{hidden} || $o{releases} ? ( - 'LEFT JOIN vn_rev vr ON c.type = 0 AND c.id = vr.id', - 'LEFT JOIN releases_rev rr ON c.type = 1 AND c.id = rr.id', - 'LEFT JOIN producers_rev pr ON c.type = 2 AND c.id = pr.id', + q{LEFT JOIN vn_rev vr ON c.type = 'v' AND c.id = vr.id}, + q{LEFT JOIN releases_rev rr ON c.type = 'r' AND c.id = rr.id}, + q{LEFT JOIN producers_rev pr ON c.type = 'p' AND c.id = pr.id}, ) : (), $o{hidden} || $o{releases} ? ( - 'LEFT JOIN vn v ON c.type = 0 AND vr.vid = v.id', - 'LEFT JOIN releases r ON c.type = 1 AND rr.rid = r.id', - 'LEFT JOIN producers p ON c.type = 2 AND pr.pid = p.id', + q{LEFT JOIN vn v ON c.type = 'v' AND vr.vid = v.id}, + q{LEFT JOIN releases r ON c.type = 'r' AND rr.rid = r.id}, + q{LEFT JOIN producers p ON c.type = 'p' AND pr.pid = p.id}, ) : (), $o{what} =~ /user/ ? 'JOIN users u ON c.requester = u.id' : (), $o{releases} ? 'LEFT JOIN releases_vn rv ON c.id = rv.rid' : (), diff --git a/lib/VNDB/DB/Producers.pm b/lib/VNDB/DB/Producers.pm index 18f372f9..afc21492 100644 --- a/lib/VNDB/DB/Producers.pm +++ b/lib/VNDB/DB/Producers.pm @@ -86,7 +86,7 @@ sub dbProducerGet { # returns: ( local revision, global revision ) sub dbProducerEdit { my($self, $pid, %o) = @_; - my($rev, $cid) = $self->dbRevisionInsert(2, $pid, $o{editsum}, $o{uid}); + my($rev, $cid) = $self->dbRevisionInsert('p', $pid, $o{editsum}, $o{uid}); insert_rev($self, $cid, $pid, \%o); return ($rev, $cid); } @@ -96,7 +96,7 @@ sub dbProducerEdit { # returns: ( item id, global revision ) sub dbProducerAdd { my($self, %o) = @_; - my($pid, $cid) = $self->dbItemInsert(2, $o{editsum}, $o{uid}); + my($pid, $cid) = $self->dbItemInsert('p', $o{editsum}, $o{uid}); insert_rev($self, $cid, $pid, \%o); return ($pid, $cid); } diff --git a/lib/VNDB/DB/Releases.pm b/lib/VNDB/DB/Releases.pm index 551855e8..9260b787 100644 --- a/lib/VNDB/DB/Releases.pm +++ b/lib/VNDB/DB/Releases.pm @@ -154,7 +154,7 @@ sub dbReleaseGet { # returns: ( local revision, global revision ) sub dbReleaseEdit { my($self, $rid, %o) = @_; - my($rev, $cid) = $self->dbRevisionInsert(1, $rid, $o{editsum}, $o{uid}); + my($rev, $cid) = $self->dbRevisionInsert('r', $rid, $o{editsum}, $o{uid}); insert_rev($self, $cid, $rid, \%o); return ($rev, $cid); } @@ -164,7 +164,7 @@ sub dbReleaseEdit { # returns: ( item id, global revision ) sub dbReleaseAdd { my($self, %o) = @_; - my($rid, $cid) = $self->dbItemInsert(1, $o{editsum}, $o{uid}); + my($rid, $cid) = $self->dbItemInsert('r', $o{editsum}, $o{uid}); insert_rev($self, $cid, $rid, \%o); return ($rid, $cid); } diff --git a/lib/VNDB/DB/VN.pm b/lib/VNDB/DB/VN.pm index 9c411794..662057d5 100644 --- a/lib/VNDB/DB/VN.pm +++ b/lib/VNDB/DB/VN.pm @@ -160,7 +160,7 @@ sub dbVNGet { # returns: ( local revision, global revision ) sub dbVNEdit { my($self, $id, %o) = @_; - my($rev, $cid) = $self->dbRevisionInsert(0, $id, $o{editsum}, $o{uid}); + my($rev, $cid) = $self->dbRevisionInsert('v', $id, $o{editsum}, $o{uid}); insert_rev($self, $cid, $id, \%o); return ($rev, $cid); } @@ -170,7 +170,7 @@ sub dbVNEdit { # returns: ( item id, global revision ) sub dbVNAdd { my($self, %o) = @_; - my($id, $cid) = $self->dbItemInsert(0, $o{editsum}, $o{uid}); + my($id, $cid) = $self->dbItemInsert('v', $o{editsum}, $o{uid}); insert_rev($self, $cid, $id, \%o); return ($id, $cid); } diff --git a/lib/VNDB/Handler/Misc.pm b/lib/VNDB/Handler/Misc.pm index 891a83f0..7896ad52 100644 --- a/lib/VNDB/Handler/Misc.pm +++ b/lib/VNDB/Handler/Misc.pm @@ -66,10 +66,9 @@ sub homepage { my $changes = $self->dbRevisionGet(what => 'item user', results => 10, auto => 1, hidden => 1); ul; for (@$changes) { - my $t = (qw|v r p|)[$_->{type}]; li; - lit mt '_home_recentchanges_item', $t, - sprintf('<a href="%s" title="%s">%s</a>', "/$t$_->{iid}.$_->{rev}", + lit mt '_home_recentchanges_item', $_->{type}, + sprintf('<a href="%s" title="%s">%s</a>', "/$_->{type}$_->{iid}.$_->{rev}", xml_escape($_->{ioriginal}||$_->{ititle}), xml_escape shorten $_->{ititle}, 33), $_; end; diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index 7e98159a..90c9db13 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -505,12 +505,11 @@ sub htmlHistory { ], row => sub { my($s, $n, $i) = @_; - my $tc = [qw|v r p|]->[$i->{type}]; - my $revurl = "/$tc$i->{iid}.$i->{rev}"; + my $revurl = "/$i->{type}$i->{iid}.$i->{rev}"; Tr $n % 2 ? ( class => 'odd' ) : (); td class => 'tc1_1'; - a href => $revurl, "$tc$i->{iid}"; + a href => $revurl, "$i->{type}$i->{iid}"; end; td class => 'tc1_2'; a href => $revurl, ".$i->{rev}"; diff --git a/util/dump.sql b/util/dump.sql index c952c162..8a8d2c61 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -5,9 +5,10 @@ CREATE LANGUAGE plpgsql; -- data types -CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); -CREATE TYPE medium AS ENUM ('cd', 'dvd', 'gdr', 'blr', 'flp', 'mrt', 'mem', 'umd', 'nod', 'in', 'otc'); -CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); +CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); +CREATE TYPE dbentry_type AS ENUM ('v', 'r', 'p'); +CREATE TYPE medium AS ENUM ('cd', 'dvd', 'gdr', 'blr', 'flp', 'mrt', 'mem', 'umd', 'nod', 'in', 'otc'); +CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); ----------------------------------------- @@ -30,7 +31,7 @@ CREATE TABLE anime ( -- changes CREATE TABLE changes ( id SERIAL NOT NULL PRIMARY KEY, - type smallint NOT NULL DEFAULT 0, + type dbentry_type NOT NULL, rev integer NOT NULL DEFAULT 1, added timestamptz NOT NULL DEFAULT NOW(), requester integer NOT NULL DEFAULT 0, diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index a90b3ac2..ff8fe9dd 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -64,3 +64,14 @@ ALTER TABLE releases_producers ADD CHECK(developer OR publisher); ALTER TABLE threads_boards ADD COLUMN lastread smallint; +-- changes.type stored as enum +CREATE TYPE dbentry_type AS ENUM ('v', 'r', 'p'); +ALTER TABLE changes ALTER COLUMN type DROP DEFAULT; +ALTER TABLE changes ALTER COLUMN type TYPE dbentry_type USING + CASE + WHEN type = 0 THEN 'v'::dbentry_type + WHEN type = 1 THEN 'r' + WHEN type = 2 THEN 'p' + ELSE NULL -- not allowed to happen, otherwise FIX YOUR DATABASE! + END; + -- cgit v1.2.3 From 4f687e4d1e81b665196251bb0cfa48c062357d20 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Mon, 12 Oct 2009 17:31:18 +0200 Subject: htmlSearchBox: Copy over search query when switching search type <@EchoMateria> for example I searched for 'Maika' in Visual Novels <@EchoMateria> then remembered that it was a producer not a game and clicked Producers instead <@EchoMateria> can you set it so that entry in the search field would stay and it would search for it in the producers instead? --- ChangeLog | 1 + lib/VNDB/Util/CommonHTML.pm | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index b29cab16..65a0a89a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,7 @@ git - ? - Display number of unread posts in "My messages" (instead of total threads) - Optimized dbUserGet (mostly for the user list) - All languages are listed on /r and /v/all instead of only those in use + - Copy over search query when switching search type (htmlSearchBox) 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index 90c9db13..3d032d37 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -537,13 +537,20 @@ sub htmlHistory { sub htmlSearchBox { my($self, $sel, $v) = @_; + # escape search query for use as a query string value + (my $q = $v||'') =~ s/&/%26/g; + $q =~ s/\?/%3F/g; + $q =~ s/;/%3B/g; + $q =~ s/ /%20/g; + $q = "?q=$q" if $q; + fieldset class => 'search'; p class => 'searchtabs'; - a href => '/v/all', $sel eq 'v' ? (class => 'sel') : (), mt '_searchbox_vn'; - a href => '/r', $sel eq 'r' ? (class => 'sel') : (), mt '_searchbox_releases'; - a href => '/p/all', $sel eq 'p' ? (class => 'sel') : (), mt '_searchbox_producers'; - a href => '/g', $sel eq 'g' ? (class => 'sel') : (), mt '_searchbox_tags'; - a href => '/u/all', $sel eq 'u' ? (class => 'sel') : (), mt '_searchbox_users'; + a href => "/v/all$q", $sel eq 'v' ? (class => 'sel') : (), mt '_searchbox_vn'; + a href => "/r$q", $sel eq 'r' ? (class => 'sel') : (), mt '_searchbox_releases'; + a href => "/p/all$q", $sel eq 'p' ? (class => 'sel') : (), mt '_searchbox_producers'; + a href => '/g'.($q?"/list$q":''), $sel eq 'g' ? (class => 'sel') : (), mt '_searchbox_tags'; + a href => "/u/all$q", $sel eq 'u' ? (class => 'sel') : (), mt '_searchbox_users'; end; input type => 'text', name => 'q', id => 'q', class => 'text', value => $v; input type => 'submit', class => 'submit', value => mt '_searchbox_submit'; -- cgit v1.2.3 From c816a8a462e925f8ef8133241c29d5d53afdce64 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 17 Oct 2009 11:07:45 +0200 Subject: L10N-EN: "Requested username" -> "Preferred username", more acurate --- data/lang.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/lang.txt b/data/lang.txt index 06b54cc7..dd5a59ad 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -2889,7 +2889,7 @@ en : Username ru : Имя пользователя :_register_username_msg -en : Requested username. Must be lowercase and can only consist of alphanumeric characters. +en : Preferred username. Must be lowercase and can only consist of alphanumeric characters. ru : Запрашиваемое имя пользователя. Должно состоять из буквенно-цифровых символов в нижнем регистре. :_register_mail -- cgit v1.2.3 From e7e53553cb42824b7360ebbc15bb86aaa015c677 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 17 Oct 2009 14:20:06 +0200 Subject: Handler::ULists: Add secundary order by title when ordered by vote This fixes a strange issue that the ordering changes when browsing to the next page, resulting in some VNs not showing up at all. --- ChangeLog | 1 + lib/VNDB/Handler/ULists.pm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 65a0a89a..b62057f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ git - ? - Optimized dbUserGet (mostly for the user list) - All languages are listed on /r and /v/all instead of only those in use - Copy over search query when switching search type (htmlSearchBox) + - Fixed obscure sorting bug on user VN list 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/lib/VNDB/Handler/ULists.pm b/lib/VNDB/Handler/ULists.pm index 19db9f1e..6a0d6c9e 100644 --- a/lib/VNDB/Handler/ULists.pm +++ b/lib/VNDB/Handler/ULists.pm @@ -229,7 +229,7 @@ sub vnlist { uid => $uid, results => 50, page => $f->{p}, - order => $f->{s}.' '.($f->{o} eq 'd' ? 'DESC' : 'ASC'), + order => $f->{s}.' '.($f->{o} eq 'd' ? 'DESC' : 'ASC').($f->{s} eq 'vote' ? ', title ASC' : ''), voted => $f->{v}, $f->{c} ne 'all' ? (char => $f->{c}) : (), ); -- cgit v1.2.3 From 668833467f8231ebdc622d42edcb49e8374b42b4 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 17 Oct 2009 16:21:38 +0200 Subject: SQL: Converted releases_rev.type to an ENUM data type --- ChangeLog | 3 +++ data/global.pl | 2 +- data/lang.txt | 6 ++--- data/style.css | 8 +++--- lib/VNDB/Handler/Releases.pm | 6 ++--- util/dump.sql | 9 ++++--- util/updates/update_2.8.sql | 62 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 81 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index b62057f9..1b46ad0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,9 @@ git - ? - Converted to ENUM data type: - vn_relations.relation - anime.type + - changes.type + - releases_rev.type + - releases_media.medium - New language: Hungarian - Complete rewrite of the Javascript code: - Intended to be less error prone, more maintainable, and easier to make diff --git a/data/global.pl b/data/global.pl index 9f176081..b1d4b031 100644 --- a/data/global.pl +++ b/data/global.pl @@ -66,7 +66,7 @@ our %S = (%S, 17 => [ '17+', 'CERO D' ], 18 => [ '18+', 'CERO Z' ], }, - release_types => [0..2], + release_types => [qw|complete partial trial|], platforms => [qw|win dos lin mac dvd gba msx nds nes p98 psp ps1 ps2 ps3 drc sat sfc wii xb3 oth|], media => { #DB qty? diff --git a/data/lang.txt b/data/lang.txt index dd5a59ad..d89f97d8 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -433,15 +433,15 @@ ru : Любительская группа # release types -:_rtype_0 +:_rtype_complete en : Complete ru : Полный -:_rtype_1 +:_rtype_partial en : Partial ru : Частичный -:_rtype_2 +:_rtype_trial en : Trial ru : Триальный diff --git a/data/style.css b/data/style.css index 483ef6d1..9aaceb59 100644 --- a/data/style.css +++ b/data/style.css @@ -1131,7 +1131,7 @@ div#iv_view { height: 11px; opacity: 0.5; } -.icons.rt0, .icons.rt1, .icons.rt2 { width: 11px; } +.icons.rtcomplete, .icons.rtpartial, .icons.rttrial { width: 11px; } acronym.icons, acronym.uicons { cursor: default; } a .icons { cursor: pointer } .icons.oth { background: none; } @@ -1153,9 +1153,9 @@ a .icons { cursor: pointer } .icons.xb3 { background-position: -16px -84px; } .icons.sat { background-position: -16px -98px; } -.icons.rt0 { background-position: -32px 0px; } -.icons.rt1 { background-position: -32px -14px; } -.icons.rt2 { background-position: -32px -28px; } +.icons.rtcomplete { background-position: -32px 0px; } +.icons.rtpartial { background-position: -32px -14px; } +.icons.rttrial { background-position: -32px -28px; } .icons.ext { background-position: -32px -42px; } .icons.msx { background-position: -32px -56px; } .icons.nes { background-position: -32px -70px; } diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm index 62776fd2..3cc5d1bb 100644 --- a/lib/VNDB/Handler/Releases.pm +++ b/lib/VNDB/Handler/Releases.pm @@ -490,7 +490,7 @@ sub browse { { name => 'ln', required => 0, multi => 1, default => '', enum => $self->{languages} }, { name => 'pl', required => 0, multi => 1, default => '', enum => $self->{platforms} }, { name => 'me', required => 0, multi => 1, default => '', enum => [ keys %{$self->{media}} ] }, - { name => 'tp', required => 0, default => -1, enum => [ -1, @{$self->{release_types}} ] }, + { name => 'tp', required => 0, default => '', enum => [ '', @{$self->{release_types}} ] }, { name => 'pa', required => 0, default => 0, enum => [ 0..2 ] }, { name => 'fw', required => 0, default => 0, enum => [ 0..2 ] }, { name => 'do', required => 0, default => 0, enum => [ 0..2 ] }, @@ -509,7 +509,7 @@ sub browse { $f->{ln}[0] ? (languages => $f->{ln}) : (), $f->{me}[0] ? (media => $f->{me}) : (), $f->{re}[0] ? (resolutions => $f->{re} ) : (), - $f->{tp} >= 0 ? (type => $f->{tp}) : (), + $f->{tp} ? (type => $f->{tp}) : (), $f->{ma_a} || $f->{ma_m} ? (minage => [$f->{ma_m}, $f->{ma_a}]) : (), $f->{pa} ? (patch => $f->{pa}) : (), $f->{fw} ? (freeware => $f->{fw}) : (), @@ -620,7 +620,7 @@ sub _filters { end; end; $self->htmlFormPart($f, [ select => short => 'tp', name => mt('_rbrowse_type'), - options => [ [-1, mt '_rbrowse_all'], map [ $_, mt "_rtype_$_" ], @{$self->{release_types}} ]]); + options => [ ['', mt '_rbrowse_all'], map [ $_, mt "_rtype_$_" ], @{$self->{release_types}} ]]); $self->htmlFormPart($f, [ select => short => 'pa', name => mt('_rbrowse_patch'), options => [ [0, mt '_rbrowse_all' ], [1, mt '_rbrowse_patchonly'], [2, mt '_rbrowse_patchnone']]]); $self->htmlFormPart($f, [ select => short => 'fw', name => mt('_rbrowse_freeware'), diff --git a/util/dump.sql b/util/dump.sql index 8a8d2c61..145c09e8 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -8,6 +8,7 @@ CREATE LANGUAGE plpgsql; CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); CREATE TYPE dbentry_type AS ENUM ('v', 'r', 'p'); CREATE TYPE medium AS ENUM ('cd', 'dvd', 'gdr', 'blr', 'flp', 'mrt', 'mem', 'umd', 'nod', 'in', 'otc'); +CREATE TYPE release_type AS ENUM ('complete', 'partial', 'trial'); CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); @@ -116,7 +117,7 @@ CREATE TABLE releases_rev ( rid integer NOT NULL DEFAULT 0, title varchar(250) NOT NULL DEFAULT '', original varchar(250) NOT NULL DEFAULT '', - type smallint NOT NULL DEFAULT 0, + type release_type NOT NULL DEFAULT 'complete', website varchar(250) NOT NULL DEFAULT '', released integer NOT NULL, notes text NOT NULL DEFAULT '', @@ -448,7 +449,7 @@ BEGIN JOIN releases r1 ON rr1.id = r1.latest JOIN releases_vn rv1 ON rr1.id = rv1.rid WHERE rv1.vid = vn.id - AND rr1.type <> 2 + AND rr1.type <> ''trial'' AND r1.hidden = FALSE AND rr1.released <> 0 GROUP BY rv1.vid @@ -460,7 +461,7 @@ BEGIN JOIN releases r2 ON rr2.id = r2.latest JOIN releases_vn rv2 ON rr2.id = rv2.rid WHERE rv2.vid = vn.id - AND rr2.type <> 2 + AND rr2.type <> ''trial'' AND rr2.released <= TO_CHAR(''today''::timestamp, ''YYYYMMDD'')::integer AND r2.hidden = FALSE GROUP BY rl2.lang @@ -473,7 +474,7 @@ BEGIN JOIN releases r3 ON rp3.rid = r3.latest JOIN releases_vn rv3 ON rp3.rid = rv3.rid WHERE rv3.vid = vn.id - AND rr3.type <> 2 + AND rr3.type <> ''trial'' AND rr3.released <= TO_CHAR(''today''::timestamp, ''YYYYMMDD'')::integer AND r3.hidden = FALSE GROUP BY rp3.platform diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index ff8fe9dd..c8bcda38 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -75,3 +75,65 @@ ALTER TABLE changes ALTER COLUMN type TYPE dbentry_type USING ELSE NULL -- not allowed to happen, otherwise FIX YOUR DATABASE! END; + +-- releases_rev.type stored as enum +CREATE TYPE release_type AS ENUM ('complete', 'partial', 'trial'); +ALTER TABLE releases_rev ALTER COLUMN type DROP DEFAULT; +ALTER TABLE releases_rev ALTER COLUMN type TYPE release_type USING + CASE + WHEN type = 0 THEN 'complete'::release_type + WHEN type = 1 THEN 'partial' + WHEN type = 2 THEN 'trial' + ELSE NULL + END; +ALTER TABLE releases_rev ALTER COLUMN type SET DEFAULT 'complete'; + +CREATE OR REPLACE FUNCTION update_vncache(id integer) RETURNS void AS $$ +DECLARE + w text := ''; +BEGIN + IF id > 0 THEN + w := ' WHERE id = '||id; + END IF; + EXECUTE 'UPDATE vn SET + c_released = COALESCE((SELECT + MIN(rr1.released) + FROM releases_rev rr1 + JOIN releases r1 ON rr1.id = r1.latest + JOIN releases_vn rv1 ON rr1.id = rv1.rid + WHERE rv1.vid = vn.id + AND rr1.type <> ''trial'' + AND r1.hidden = FALSE + AND rr1.released <> 0 + GROUP BY rv1.vid + ), 0), + c_languages = COALESCE(ARRAY_TO_STRING(ARRAY( + SELECT rl2.lang + FROM releases_rev rr2 + JOIN releases_lang rl2 ON rl2.rid = rr2.id + JOIN releases r2 ON rr2.id = r2.latest + JOIN releases_vn rv2 ON rr2.id = rv2.rid + WHERE rv2.vid = vn.id + AND rr2.type <> ''trial'' + AND rr2.released <= TO_CHAR(''today''::timestamp, ''YYYYMMDD'')::integer + AND r2.hidden = FALSE + GROUP BY rl2.lang + ORDER BY rl2.lang + ), ''/''), ''''), + c_platforms = COALESCE(ARRAY_TO_STRING(ARRAY( + SELECT rp3.platform + FROM releases_platforms rp3 + JOIN releases_rev rr3 ON rp3.rid = rr3.id + JOIN releases r3 ON rp3.rid = r3.latest + JOIN releases_vn rv3 ON rp3.rid = rv3.rid + WHERE rv3.vid = vn.id + AND rr3.type <> ''trial'' + AND rr3.released <= TO_CHAR(''today''::timestamp, ''YYYYMMDD'')::integer + AND r3.hidden = FALSE + GROUP BY rp3.platform + ORDER BY rp3.platform + ), ''/''), '''') + '||w; +END; +$$ LANGUAGE plpgsql; + -- cgit v1.2.3 From ee96a4381fa187eede8374601d0c06cd861eb66c Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 18 Oct 2009 09:15:08 +0200 Subject: Multi::Maintenance: Fixed bug with cron jobs running more than once --- lib/Multi/Maintenance.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm index 423def75..59d30ce6 100644 --- a/lib/Multi/Maintenance.pm +++ b/lib/Multi/Maintenance.pm @@ -50,7 +50,7 @@ sub set_daily { # (GMT because we're calculating on the UNIX timestamp, I can easily add an # offset if necessary, but it doesn't really matter what time this cron # runs, as long as it's run on a daily basis) - $_[KERNEL]->alarm(daily => int(time/86400+1)*86400); + $_[KERNEL]->alarm(daily => int((time+3)/86400+1)*86400); } @@ -70,7 +70,7 @@ sub set_monthly { # We do this by simply incrementing the timestamp with one day and checking gmtime() # for a month change. This might not be very reliable, but should be enough for # our purposes. - my $nextday = int(time/86400+1)*86400; + my $nextday = int((time+3)/86400+1)*86400; my $thismonth = (gmtime)[5]*100+(gmtime)[4]; # year*100 + month, for easy comparing $nextday += 86400 while (gmtime $nextday)[5]*100+(gmtime $nextday)[4] <= $thismonth; $_[KERNEL]->alarm(monthly => $nextday); -- cgit v1.2.3 From 62cb41c3b8780bffe5a8ea58a6a7b5053d9e1059 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 18 Oct 2009 18:06:14 +0200 Subject: SQL: Fixed calculation of tags_vn_bayesian.spoiler --- ChangeLog | 1 + util/dump.sql | 2 +- util/updates/update_2.8.sql | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1b46ad0c..d45d50f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,7 @@ git - ? - All languages are listed on /r and /v/all instead of only those in use - Copy over search query when switching search type (htmlSearchBox) - Fixed obscure sorting bug on user VN list + - Fixed calculation of tags_vn_bayesian.spoiler 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/util/dump.sql b/util/dump.sql index 145c09e8..9fbff0a2 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -589,7 +589,7 @@ BEGIN SELECT * FROM tags_vn UNION SELECT * FROM tag_vn_childs(); -- grouped by (tag, vid, uid), so only one user votes on one parent tag per VN entry CREATE OR REPLACE TEMPORARY VIEW tags_vn_grouped AS - SELECT tag, vid, uid, MAX(vote)::real AS vote, COALESCE(AVG(spoiler), 0)::real AS spoiler + SELECT tag, vid, uid, MAX(vote)::real AS vote, AVG(spoiler)::real AS spoiler FROM tags_vn_all GROUP BY tag, vid, uid; -- grouped by (tag, vid) and serialized into a table DROP INDEX IF EXISTS tags_vn_bayesian_tag; diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index c8bcda38..54367c9b 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -137,3 +137,37 @@ BEGIN END; $$ LANGUAGE plpgsql; + + +-- fix calculation of the tags_vn_bayesian.spoiler column + +CREATE OR REPLACE FUNCTION tag_vn_calc() RETURNS void AS $$ +BEGIN + -- all votes for all tags + CREATE OR REPLACE TEMPORARY VIEW tags_vn_all AS + SELECT * FROM tags_vn UNION SELECT * FROM tag_vn_childs(); + -- grouped by (tag, vid, uid), so only one user votes on one parent tag per VN entry + CREATE OR REPLACE TEMPORARY VIEW tags_vn_grouped AS + SELECT tag, vid, uid, MAX(vote)::real AS vote, AVG(spoiler)::real AS spoiler + FROM tags_vn_all GROUP BY tag, vid, uid; + -- grouped by (tag, vid) and serialized into a table + DROP INDEX IF EXISTS tags_vn_bayesian_tag; + TRUNCATE tags_vn_bayesian; + INSERT INTO tags_vn_bayesian + SELECT tag, vid, COUNT(uid) AS users, AVG(vote)::real AS rating, + (CASE WHEN AVG(spoiler) < 0.7 THEN 0 WHEN AVG(spoiler) > 1.3 THEN 2 ELSE 1 END)::smallint AS spoiler + FROM tags_vn_grouped + GROUP BY tag, vid + HAVING AVG(vote) > 0; + CREATE INDEX tags_vn_bayesian_tag ON tags_vn_bayesian (tag); + -- now perform the bayesian ranking calculation + UPDATE tags_vn_bayesian tvs SET rating = + ((SELECT AVG(users)::real * AVG(rating)::real FROM tags_vn_bayesian WHERE tag = tvs.tag) + users*rating) + / ((SELECT AVG(users)::real FROM tags_vn_bayesian WHERE tag = tvs.tag) + users)::real; + -- and update the VN count in the tags table as well + UPDATE tags SET c_vns = (SELECT COUNT(*) FROM tags_vn_bayesian WHERE tag = id); + RETURN; +END; +$$ LANGUAGE plpgsql; +SELECT tag_vn_calc(); + -- cgit v1.2.3 From fab6821be0cf1e7ad0f9c853475ec1d01482234a Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sun, 18 Oct 2009 18:46:22 +0200 Subject: Handler::Misc: Fixed bug with unhiding a producer entry I could swear I'd found and fixed a similar bug in the past... --- ChangeLog | 1 + lib/VNDB/Handler/Misc.pm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d45d50f8..f371d68b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,6 +26,7 @@ git - ? - Copy over search query when switching search type (htmlSearchBox) - Fixed obscure sorting bug on user VN list - Fixed calculation of tags_vn_bayesian.spoiler + - Fixed bug with unhiding a producer entry 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/lib/VNDB/Handler/Misc.pm b/lib/VNDB/Handler/Misc.pm index 7896ad52..72db2489 100644 --- a/lib/VNDB/Handler/Misc.pm +++ b/lib/VNDB/Handler/Misc.pm @@ -328,7 +328,7 @@ sub itemmod { my $obj = $type eq 'v' ? $self->dbVNGet(id => $iid)->[0] : $type eq 'r' ? $self->dbReleaseGet(id => $iid, what => 'vn extended')->[0] : - $self->dbProducerGet(id => $iid)->[0]; + $self->dbProducerGet(id => $iid, what => 'extended')->[0]; return 404 if !$obj->{id}; $self->dbItemMod($type, $iid, $act eq 'hide' ? (hidden => !$obj->{hidden}) : (locked => !$obj->{locked})); -- cgit v1.2.3 From 538000a678b4110394f1aaf413059bcdd43c5005 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Mon, 19 Oct 2009 09:32:12 +0200 Subject: Use 'no spoilers' as default spoiler level for tags --- ChangeLog | 1 + data/script.js | 2 +- lib/VNDB/Handler/Tags.pm | 2 +- lib/VNDB/Handler/VNBrowse.pm | 2 +- lib/VNDB/Handler/VNPage.pm | 6 +++--- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index f371d68b..9eba7ab8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -27,6 +27,7 @@ git - ? - Fixed obscure sorting bug on user VN list - Fixed calculation of tags_vn_bayesian.spoiler - Fixed bug with unhiding a producer entry + - Set 'no spoilers' as default spoiler level for tags 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/script.js b/data/script.js index cc984230..67ae8953 100644 --- a/data/script.js +++ b/data/script.js @@ -1582,7 +1582,7 @@ if(byId('sp_0')) { byId('sp_1').onclick = function() { setCookie('tagspoil', 1) }; byId('sp_2').onclick = function() { setCookie('tagspoil', 2) }; var spoil = getCookie('tagspoil'); - byId('sp_'+(spoil == null ? 1 : spoil)).checked = true; + byId('sp_'+(spoil == null ? 0 : spoil)).checked = true; } // NSFW VN image toggle (/v+) diff --git a/lib/VNDB/Handler/Tags.pm b/lib/VNDB/Handler/Tags.pm index 6a13446b..f75efdc6 100644 --- a/lib/VNDB/Handler/Tags.pm +++ b/lib/VNDB/Handler/Tags.pm @@ -36,7 +36,7 @@ sub tagpage { ); return 404 if $f->{_err}; my $tagspoil = $self->reqCookie('tagspoil'); - $f->{m} = $tagspoil =~ /^[0-2]$/ ? $tagspoil : 1 if $f->{m} == -1; + $f->{m} = $tagspoil =~ /^[0-2]$/ ? $tagspoil : 0 if $f->{m} == -1; my($list, $np) = $t->{meta} || $t->{state} != 2 ? ([],0) : $self->dbTagVNs( tag => $tag, diff --git a/lib/VNDB/Handler/VNBrowse.pm b/lib/VNDB/Handler/VNBrowse.pm index 118a5ee2..bca21151 100644 --- a/lib/VNDB/Handler/VNBrowse.pm +++ b/lib/VNDB/Handler/VNBrowse.pm @@ -25,7 +25,7 @@ sub list { { name => 'pl', required => 0, multi => 1, enum => $self->{platforms}, default => '' }, { name => 'ti', required => 0, default => '', maxlength => 200 }, { name => 'te', required => 0, default => '', maxlength => 200 }, - { name => 'sp', required => 0, default => $self->reqCookie('tagspoil') =~ /^([0-2])$/ ? $1 : 1, enum => [0..2] }, + { name => 'sp', required => 0, default => $self->reqCookie('tagspoil') =~ /^([0-2])$/ ? $1 : 0, enum => [0..2] }, ); return 404 if $f->{_err}; $f->{q} ||= $f->{sq}; diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 248d1d43..0205e77d 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -180,15 +180,15 @@ sub page { if(@$t) { div id => 'tagops'; # NOTE: order of these links is hardcoded in JS - a href => '#', mt '_vnpage_tags_spoil0'; - a href => '#', class => 'tsel', mt '_vnpage_tags_spoil1'; + a href => '#', class => 'tsel', mt '_vnpage_tags_spoil0'; + a href => '#', mt '_vnpage_tags_spoil1'; a href => '#', mt '_vnpage_tags_spoil2'; a href => '#', class => 'sec', mt '_vnpage_tags_summary'; a href => '#', mt '_vnpage_tags_all'; end; div id => 'vntags'; for (@$t) { - span class => sprintf 'tagspl%.0f %s', $_->{spoiler}, $_->{spoiler} > 1 ? 'hidden' : ''; + span class => sprintf 'tagspl%.0f %s', $_->{spoiler}, $_->{spoiler} > 0 ? 'hidden' : ''; a href => "/g$_->{id}", style => sprintf('font-size: %dpx', $_->{rating}*3.5+6), $_->{name}; b class => 'grayedout', sprintf ' %.1f', $_->{rating}; end; -- cgit v1.2.3 From 33c4f9d4cd7a14b4db347515ba3aa6b9f6cf99bb Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Fri, 2 Oct 2009 13:28:55 +0200 Subject: L10N-CS: Added Czech quant() --- ChangeLog | 1 + data/lang.txt | 4 ++++ lib/VNDB/L10N.pm | 19 ++++++++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9eba7ab8..421cdc88 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,6 +28,7 @@ git - ? - Fixed calculation of tags_vn_bayesian.spoiler - Fixed bug with unhiding a producer entry - Set 'no spoilers' as default spoiler level for tags + - Added Czech translation 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/lang.txt b/data/lang.txt index d89f97d8..f57a88a0 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -78,6 +78,10 @@ ends with ']'. The following options are supported: Same as the english [quant] as above, but has three forms for a word instead of two. + [quant,{num},{singular},{normative},{genetive}] (Czech) + Same as the english [quant] as above, but has three forms for a word + instead of two. + [url,{url},{title}] Formats a link to another page, where {url} is the location of the page and {title} the link title. {url} is usually an argument, e.g.: diff --git a/lib/VNDB/L10N.pm b/lib/VNDB/L10N.pm index e19302ed..279cbd31 100644 --- a/lib/VNDB/L10N.pm +++ b/lib/VNDB/L10N.pm @@ -11,7 +11,7 @@ use warnings; # used for the language switch interface, language tags must # be the same as in the languages hash in global.pl - sub languages { ('en', 'ru') } + sub languages { ('en', 'ru', 'cs') } sub maketext { my $r = eval { shift->SUPER::maketext(@_) }; @@ -25,6 +25,7 @@ use warnings; my %lang = ( en => \%VNDB::L10N::en::Lexicon, ru => \%VNDB::L10N::ru::Lexicon, + cs => \%VNDB::L10N::cs::Lexicon, ); my $r = LangFile->new(read => "$VNDB::ROOT/data/lang.txt"); my $key; @@ -140,5 +141,21 @@ use warnings; } + +{ + package VNDB::L10N::cs; + use base 'VNDB::L10N::en'; + our %Lexicon; + + sub quant { + my($self, $num, $single, $couple, $lots) = @_; + return $lots if ($num % 100) >= 11 && ($num % 100) <= 14; + return $single if ($num % 10) == 1; + return $couple if ($num % 10) >= 2 && ($num % 10) <= 4; + return $lots; + } +} + + 1; -- cgit v1.2.3 From 34826ef887252cab9a55be6cd7a3e3892a108b5b Mon Sep 17 00:00:00 2001 From: Nya-chan Production <nya.chan.production@gmail.com> Date: Mon, 19 Oct 2009 16:31:33 +0200 Subject: L10N-CS: Czech translation of lang.txt --- data/lang.txt | 880 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 880 insertions(+) diff --git a/data/lang.txt b/data/lang.txt index f57a88a0..af58d388 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -109,30 +109,37 @@ ends with ']'. The following options are supported: :_age_years en : [_1] [quant,_1,year,years] ago ru : [_1] [quant,_1,год,года,лет] назад +cs*: :_age_months en : [_1] [quant,_1,month,months] ago ru : [_1] [quant,_1,месяц,месяца,месяцев] назад +cs*: :_age_weeks en : [_1] [quant,_1,week,weeks] ago ru : [_1] [quant,_1,неделя,недели,недель] назад +cs*: :_age_days en : [_1] [quant,_1,day,days] ago ru : [_1] [quant,_1,день,дня,дней] назад +cs*: :_age_hours en : [_1] [quant,_1,hour,hours] ago ru : [_1] [quant,_1,час,часа,часов] назад +cs*: :_age_min en : [_1] min ago ru : [_1] [quant,_1,минута,минуты,минут] назад +cs*: :_age_sec en : [_1] sec ago ru : [_1] [quant,_1,секунда,секунды,секунд] назад +cs*: # user ranks @@ -140,26 +147,32 @@ ru : [_1] [quant,_1,секунда,секунды,секунд] назад :_urank_0 en : visitor ru : посетитель +cs : návštěvník :_urank_1 en : banned ru : забанен +cs : zabanovaný :_urank_2 en : loser ru : лузер +cs : loser :_urank_3 en : user ru : пользователь +cs : uživatel :_urank_4 en : mod ru : модератор +cs : moderátor :_urank_5 en : admin ru : администратор +cs : administrátor # languages @@ -167,82 +180,102 @@ ru : администратор :_lang_cs en : Czech ru : Чешский +cs : Česky :_lang_da en : Danish ru : Датский +cs : Dánsky :_lang_de en : German ru : Немецкий +cs : Německy :_lang_en en : English ru : Английский +cs : Anglicky :_lang_es en : Spanish ru : Испанский +cs : Španělsky :_lang_fi en : Finnish ru : Финский +cs : Finsky :_lang_fr en : French ru : Французский +cs : Francouzsky :_lang_hu en : Hungarian ru*: +cs*: :_lang_it en : Italian ru : Итальянский +cs : Italsky :_lang_ja en : Japanese ru : Японский +cs : Japonsky :_lang_ko en : Korean ru : Корейский +cs : Korejsky :_lang_nl en : Dutch ru : Голландский +cs : Nizozemsky :_lang_no en : Norwegian ru : Норвежский +cs : Norsky :_lang_pl en : Polish ru : Польский +cs : Polsky :_lang_pt en : Portuguese ru : Португальский +cs : Portugalsky :_lang_ru en : Russian ru : Русский +cs : Rusky :_lang_sv en : Swedish ru : Шведский +cs : Švédsky :_lang_tr en : Turkish ru : Турецкий +cs : Turecky :_lang_vi en : Vietnamese ru : Вьетнамский +cs : Vietnamsky :_lang_zh en : Chinese ru : Китайский +cs : Čínsky # platforms @@ -252,82 +285,102 @@ ru : Китайский :_plat_win en : Windows ru : Windows +cs : Windows :_plat_dos en : DOS ru : DOS +cs : DOS :_plat_lin en : Linux ru : Linux +cs : Linux :_plat_mac en : Mac OS ru : Mac OS +cs : Mac OS :_plat_dvd en : DVD Player ru : DVD Плеер +cs : DVD Přehrávač :_plat_gba en : Game Boy Advance ru : Game Boy Advance +cs : Game Boy Advance :_plat_msx en : MSX ru : MSX +cs : MSX :_plat_nds en : Nintendo DS ru : Nintendo DS +cs : Nintendo DS :_plat_nes en : Famicom ru : Famicom (Dendy) +cs : Famicom :_plat_p98 en : PC-98 ru : PC-98 +cs : PC-98 :_plat_psp en : Playstation Portable ru : Playstation Portable +cs : Playstation Portable :_plat_ps1 en : Playstation 1 ru : Playstation 1 +cs : Playstation 1 :_plat_ps2 en : Playstation 2 ru : Playstation 2 +cs : Playstation 2 :_plat_ps3 en : Playstation 3 ru : Playstation 3 +cs : Playstation 3 :_plat_drc en : Dreamcast ru : Dreamcast +cs : Dreamcast :_plat_sat en : Sega Saturn ru : Sega Saturn +cs : Sega Saturn :_plat_sfc en : Super Nintendo ru : Super Nintendo +cs : Super Nintendo :_plat_wii en : Nintendo Wii ru : Nintendo Wii +cs : Nintendo Wii :_plat_xb3 en : Xbox 360 ru : Xbox 360 +cs : Xbox 360 :_plat_oth en : Other ru : Другая +cs : Ostatní # Release media @@ -335,46 +388,57 @@ ru : Другая :_med_cd en : [quant,_1,CD,CDs] ru*: +cs*: :_med_dvd en : [quant,_1,DVD,DVDs] ru*: +cs*: :_med_gdr en : [quant,_1,GD-ROM,GD-ROMs] ru*: +cs*: :_med_blr en : [quant,_1,Blu-ray disc,Blu-ray discs] ru*: +cs*: :_med_flp en : [quant,_1,Floppy,Floppies] ru*: +cs*: :_med_mrt en : [quant,_1,Cartridge,Cartridges] ru*: +cs*: :_med_mem en : [quant,_1,Memory card,Memory cards] ru*: +cs*: :_med_umd en : [quant,_1,UMD,UMDs] ru*: +cs*: :_med_nod en : Nintendo Optical [quant,_1,Disk,Disks] ru*: +cs*: :_med_in en : Internet download ru*: +cs*: :_med_otc en : Other ru*: +cs*: # VN relations @@ -382,42 +446,52 @@ ru*: :_vnrel_seq en : Sequel ru*: +cs*: :_vnrel_preq en : Prequel ru*: +cs*: :_vnrel_set en : Same setting ru*: +cs*: :_vnrel_alt en : Alternative version ru*: +cs*: :_vnrel_char en : Shares characters ru*: +cs*: :_vnrel_side en : Side story ru*: +cs*: :_vnrel_par en : Parent story ru*: +cs*: :_vnrel_ser en : Same series ru*: +cs*: :_vnrel_fan en : Fandisc ru*: +cs*: :_vnrel_orig en : Original game ru*: +cs*: # producer types @@ -425,14 +499,17 @@ ru*: :_ptype_co en : Company ru : Компания +cs : Společnost :_ptype_in en : Individual ru : Частное лицо +cs : Jednotlivec :_ptype_ng en : Amateur group ru : Любительская группа +cs : Amatérská skupina # release types @@ -440,14 +517,17 @@ ru : Любительская группа :_rtype_complete en : Complete ru : Полный +cs : Kompletní :_rtype_partial en : Partial ru : Частичный +cs : Částečné :_rtype_trial en : Trial ru : Триальный +cs : Trial # Anime types @@ -455,30 +535,37 @@ ru : Триальный :_animetype_tv en : TV Series ru*: +cs*: :_animetype_ova en : OVA ru*: +cs*: :_animetype_mov en : Movie ru*: +cs*: :_animetype_oth en : Other ru*: +cs*: :_animetype_web en : Web ru*: +cs*: :_animetype_spe en : TV Special ru*: +cs*: :_animetype_mv en : Music Video ru*: +cs*: # Discussion board types @@ -486,22 +573,27 @@ ru*: :_dboard_an en : Announcements ru : Объявления +cs : Oznámení :_dboard_db en : VNDB Discussions ru : Форум VNDB +cs : Diskuse o VNDB :_dboard_v en : Visual novels ru : Новеллы +cs : Vizuální novely :_dboard_p en : Producers ru : Компании +cs : Producenti :_dboard_u en : Users ru : Пользователи +cs : Uživatelé # Wishlist statuses @@ -509,18 +601,22 @@ ru : Пользователи :_wish_0 en : high ru : высокий +cs : vysoká :_wish_1 en : medium ru : средний +cs : střední :_wish_2 en : low ru : низкий +cs : nízká :_wish_3 en : blacklist ru : в чёрном списке +cs : blacklist # 'Voiced' information for releases @@ -528,22 +624,27 @@ ru : в чёрном списке :_voiced_0 en : Unknown ru : Неизвестно +cs : Není známo :_voiced_1 en : Not voiced ru : Нет озвучки +cs : Bez hlasu :_voiced_2 en : Only ero scenes voiced ru : Озвучены лишь эросцены +cs : S hlasem pouze v ero scénách :_voiced_3 en : Partially voiced ru : Частичная озвучка +cs : Částečně s hlasem :_voiced_4 en : Fully voiced ru : Озвучено целиком +cs : Plně s hlasem # 'Animated' information for releases @@ -551,22 +652,27 @@ ru : Озвучено целиком :_animated_0 en : Unknown ru : Неизвестно +cs : Není známo :_animated_1 en : No animations ru : Без анимации +cs : Bez animací :_animated_2 en : Simple animations ru : Простая анимация +cs : Jednoduché animace :_animated_3 en : Some fully animated scenes ru : Некоторые сцены анимированы целиком +cs : Některé plně animované scény :_animated_4 en : All scenes fully animated ru : Все сцены полностью анимированы +cs : Všechny scény plně animovány # Rating indications @@ -574,42 +680,52 @@ ru : Все сцены полностью анимированы :_vote_1 en : worst ever ru : хуже некуда +cs : absolutně nejhorší :_vote_2 en : awful ru : ужасно +cs : hrozná :_vote_3 en : bad ru : плохо +cs : špatná :_vote_4 en : weak ru : слабо +cs : slabá :_vote_5 en : so-so ru : так себе +cs : taktak :_vote_6 en : decent ru : неплохо +cs : slušná :_vote_7 en : good ru : хорошо +cs : dobrá :_vote_8 en : very good ru : здорово +cs : velmi dobrá :_vote_9 en : excellent ru : отлично +cs : skvělá :_vote_10 en : masterpiece ru : шедевр +cs : mistrovský kus # VN lengths @@ -617,26 +733,32 @@ ru : шедевр :_vnlength_0 en : Unknown ru : Неизвестно +cs : Není známo :_vnlength_1 en : Very short[index,_1,, (< 2 hours), (OMGWTHOTL~, A Dream of Summer)] ru : Очень короткая[index,_1,, (< 2 часов), (OMGWTFOTL~, A Dream Of Summer)] +cs : Velmi krátká[index,_1,, (< 2 hours), (OMGWTHOTL~, A Dream of Summer)] :_vnlength_2 en : Short[index,_1,, (2 - 10 hours), (Narcissu~, Planetarian)] ru : Короткая[index,_1,, (2 - 10 часов), (Narcissu~, Planetarian)] +cs : Krátká[index,_1,, (2 - 10 hours), (Narcissu~, Planetarian)] :_vnlength_3 en : Medium[index,_1,, (10 - 30 hours), (Kana: Little Sister)] ru : Средняя[index,_1,, (10 - 30 часов), (Kana: Little Sister)] +cs : Střední[index,_1,, (10 - 30 hours), (Kana: Little Sister)] :_vnlength_4 en : Long[index,_1,, (30 - 50 hours), (Tsukihime)] ru : Длинная[index,_1,, (30 - 50 часов), (Tsukihime)] +cs : Dlouhá[index,_1,, (30 - 50 hours), (Tsukihime)] :_vnlength_5 en : Very long[index,_1,, (> 50 hours), (Clannad)] ru : Очень длинная[index,_1,, (> 50 часов), (Clannad)] +cs : Velmi dlouhá[index,_1,, (> 50 hours), (Clannad)] # VN list statuses @@ -644,42 +766,52 @@ ru : Очень длинная[index,_1,, (> 50 часов), (Clannad)] :_rlst_rstat_0 en : Unknown ru*: +cs*: :_rlst_rstat_1 en : Pending ru*: +cs*: :_rlst_rstat_2 en : Obtained ru*: +cs*: :_rlst_rstat_3 en : On loan ru*: +cs*: :_rlst_rstat_4 en : Deleted ru*: +cs*: :_rlst_vstat_0 en : Unknown ru*: +cs*: :_rlst_vstat_1 en : Playing ru*: +cs*: :_rlst_vstat_2 en : Finished ru*: +cs*: :_rlst_vstat_3 en : Stalled ru*: +cs*: :_rlst_vstat_4 en : Dropped ru*: +cs*: # Form messages @@ -687,106 +819,132 @@ ru*: :_formerr_e_login_failed en : Invalid username or password ru : Некорректное имя пользователя или пароль +cs : Neplatné uživatelské jméno nebo heslo :_formerr_e_nomail en : No user found with that email address ru : Пользователя с такой электронной почтой не существует +cs : Uživatel s touto e-mailovou adresou nebyl nalezen :_formerr_e_passmatch en : Passwords do not match ru : Пароли не совпадают +cs : Hesla nejsou stejná :_formerr_e_usrexists en : Someone already has this username, please choose something else ru : Кто-то уже зарегистрировал такой ник, пожалуйста выберите другой +cs : Toto uživatelské jméno už je v užívání, vyberte prosím jiné :_formerr_e_mailexists en : Someone already registered with that email address ru : Кто-то уже регистрировался с таким адресом электронной почты +cs : Tuto e-mailovou adresu již někdo k registraci použil :_formerr_e_noimage en : Image must be in JPEG or PNG format ru : Изображение должно быть в формате JPEG, либо в формате PNG +cs : Obrázek musí být v JPEG nebo PNG formátu :_formerr_e_toolarge en : Image is too large, only 500kB allowed ru : Изображение слишком большое, 500 кб - максимально допустимый предел +cs : Obrázek je moc velký, je povoleno pouze 500kB :_formerr_e_oneaday en : You can only register one account from the same IP within 24 hours ru : Вы можете зарегистрировать учётную запись с одного и того же IP лишь по прошествии 24 часов +cs : V rámci 24 hodin si lze z jedné IP adresy zaregistrovat pouze jeden účet :_formerr_e_nochanges en : No changes, please don't create an entry that is fully identical to another ru : Изменения отсутствуют, пожалуйста не создавайте идентичных копий записей +cs : Nenalezeny změny, netvořte prosím záznam, který je plně totožný s jiným :_formerr_e_doublepost en : Please wait 30 seconds before making another post ru : Прежде чем публиковать очередное сообщение, пожалуйста подождите 30 секунд +cs : Před posláním dalšího příspěvku počkejte prosím 30 sekund :_formerr_title en : Error ru : Ошибка +cs : Chyba :_formerr_subtitle en : Form could not be sent: ru : Невозможно отправить форму: +cs : Dokument nemohl být odeslán: :_formerr_required en : [_1] is a required field! ru : [_1] - обязательное поле! +cs : [_1] je pole, které musí být vyplněno! :_formerr_minlength en : [_1]: should have at least [_2] characters ru : [_1]: [quant,_2,необходим,необходимы,необходимо] хотя бы [_2] [quant,_2,символ,символа,символов] +cs : [_1]: musí mít minimálně [_2] znaků :_formerr_maxlength en : [_1]: only [_2] characters allowed ru : [_1]: [quant,_2,разрешён,разрешены,разрешено] лишь [_2] [quant,_2,символ,символа,символов] +cs : [_1]: je povoleno maximálně [_2] znaků :_formerr_enum en : [_1] must be one of the following: [_2] ru : Поле '[_1]' должно равняться одному из следующих значений: [_2] +cs : [_1] musí být z následujícího seznamu: [_2] :_formerr_wrongboard en : Wrong board: [_1] ru : Некорректная ветка: [_1] +cs : Špatný board: [_1] :_formerr_tagexists en : Tag [url,_1,_2] already exists! ru : Тег [url,_1,_2] уже существует! +cs : Tag [url,_1,_2] již existuje! :_formerr_tpl_mail en : Invalid email address ru : Некорректный адрес электронной почты +cs : Neplatná e-mailová adresa :_formerr_tpl_url en : [_1]: Invalid URL ru : [_1]: Некорректная ссылка +cs : [_1]: Neplatná URL :_formerr_tpl_asciiprint en : [_1] may only contain ASCII characters ru : Поле '[_1]' может содержать лишь символы диапазона ASCII +cs : [_1] smí obsahovat pouze znaky ASCII :_formerr_tpl_int en : [_1]: Not a valid number ru : [_1]: Не является правильным числом +cs : [_1]: Neplatné číslo :_formerr_tpl_pname en : [_1] can only contain lowercase alphanumeric characters and a hyphen, and must start with a character ru : Поле '[_1]' может содержать лишь символы буквенно-цифрового диапазона в нижнем регистре и чёрточку, а так же начинаться с буквы +cs : [_1] smí obsahovat pouze malá písmena, čísla a pomlčku, a musí začínat písmenem :_form_tab_all en : All items ru : Все поля +cs : Všechny položky :_form_editsum en : Edit summary ru : Суммарно о правке +cs : Shrnutí editace :_form_submit en : Submit ru : Отправить +cs : Potvrdit # Common javascript strings @@ -794,50 +952,62 @@ ru : Отправить :_js_expand en : expand ru*: +cs*: :_js_collapse en : collapse ru*: +cs*: :_js_loading en : Loading... ru*: +cs*: :_js_date_year en : -year- ru*: +cs*: :_js_date_month en : -month- ru*: +cs*: :_js_date_day en : -day- ru*: +cs*: :_js_ds_noresults en : No results... ru*: +cs*: :_js_iv_close en : close ru*: +cs*: :_js_iv_prev en : previous ru*: +cs*: :_js_iv_next en : next ru*: +cs*: :_js_ds_tag_meta en : meta ru*: +cs*: :_js_ds_tag_mod en : awaiting moderation ru*: +cs*: @@ -854,12 +1024,14 @@ ru*: :_site_title en : The Visual Novel Database ru : The Visual Novel Database +cs : Databáze Vizuálních Novel # the 'ALL' in "ALL A B C D .. #" :_char_all en : ALL ru : ВСЕ +cs : VŠE # Main menu @@ -867,54 +1039,67 @@ ru : ВСЕ :_menu en : Menu ru : Меню +cs : Menu :_menu_home en : Home ru : Главная +cs : Home :_menu_vn en : Visual novels ru : Новеллы +cs : Vizuální novely :_menu_releases en : Releases ru : Выпуски +cs : Vydání :_menu_producers en : Producers ru : Компании +cs : Producenti :_menu_tags en : Tags ru : Теги +cs : Tagy :_menu_users en : Users ru : Пользователи +cs : Uživatelé :_menu_recent_changes en : Recent changes ru : Свежие правки +cs : Poslední změny :_menu_discussion_board en : Discussion board ru : Форум +cs : Diskusní board :_menu_faq en : FAQ ru : ЧаВо +cs : FAQ :_menu_randvn en : Random visual novel ru : Случайная новелла +cs : Náhodná vizuální novela :_menu_webchat en : webchat ru : Веб-чат +cs : webchat :_menu_emptysearch en : search ru : поиск +cs : hledat # User menu @@ -922,80 +1107,99 @@ ru : поиск :_menu_myprofile en : My Profile ru : Мой профиль +cs : Můj profil :_menu_myvnlist en : My Visual Novel List ru : Мой список новелл +cs : Můj list vizuálních novel :_menu_mywishlist en : My Wishlist ru : Мой список желаемого +cs : Můj wishlist # [_1] = number of messages :_menu_mymessages en : My Messages ([_1]) ru : Мои сообщения +cs : Mé zprávy ([_1]) :_menu_mychanges en : My Recent Changes ru : Мои недавние правки +cs : Mé poslední změny :_menu_mytags en : My Tags ru : Мои теги +cs : Moje tagy :_menu_addvn en : Add Visual Novel ru : Добавить новеллу +cs : Přidat vizuální novelu :_menu_addproducer en : Add Producer ru : Добавить компанию +cs : Přidat producenta :_menu_logout en : Logout ru : Выйти +cs : Odhlásit # used for both the box title and submit button :_menu_login en : Login ru : Вход +cs : Přihlášení :_menu_loginmsg en : Need to [url,_1,register],[br] or [url,_2,forgot your password]? ru : Нужна [url,_1,регистрация],[br] или [url,_2,забыли свой пароль]? +cs : Potřebujete se [url,_1,přihlásit],[br] + nebo jste [url,_2,zapomněli heslo]? # database statistics :_menu_dbstats en : Database Statistics ru : Статистика базы данных +cs : Statistiky databáze :_menu_stat_vn en : Visual Novels ru : Новелл +cs : Vizuální novely :_menu_stat_releases en : Releases ru : Выпусков +cs : Vydání :_menu_stat_producers en : Producers ru : Компаний +cs : Producenti :_menu_stat_users en : Users ru : Пользователей +cs : Uživatelé :_menu_stat_threads en : Threads ru : Тем +cs : Thready :_menu_stat_posts en : Posts ru : Сообщений +cs : Příspevky # Footer @@ -1003,10 +1207,12 @@ ru : Сообщений :_footer_aboutus en : abous us ru : о нас +cs : o nás :_footer_source en : source ru : исходный код +cs : zdroj # Main tabs (those on the right top of the highest box) @@ -1014,70 +1220,85 @@ ru : исходный код :_mtabs_hist en : history ru : история +cs : historie :_mtabs_discuss en : discussions ([_1]) ru : обсуждения ([_1]) +cs : diskuse ([_1]) # the following 4 tabs are only present on user pages :_mtabs_posts en : posts ru : сообщения +cs : příspevky :_mtabs_wishlist en : wishlist ru : список желаемого +cs : wishlist :_mtabs_list en : list ru : список +cs : seznam :_mtabs_tags en : tags ru : теги +cs : tagy # modify tags on VN pages :_mtabs_tagmod en : modify tags ru : править теги +cs : změnit tagy # copy a release :_mtabs_copy en : copy ru : копировать +cs : kopírovat # following line is also used on revision pages (it's the same action, anyway) :_mtabs_edit en : edit ru : правка +cs : upravit # hide/unhide a DB item :_mtabs_hide en : hide ru : скрыть +cs : skrýt :_mtabs_unhide en : unhide ru : показать +cs : odkrýt # lock/unlock for editing :_mtabs_lock en : lock ru : заблокировать +cs : zamknout :_mtabs_unlock en : unlock ru : снять блокировку +cs : odemknout # delete :_mtabs_del en : del ru : удалить +cs : smazat # VN relations :_mtabs_relations en : relations ru : связи +cs : vztahy # Navigation buttons on the browse pages @@ -1085,10 +1306,12 @@ ru : связи :_browse_previous en : previous ru : назад +cs : předchozí :_browse_next en : next ru : далее +cs : další # Revision pages @@ -1096,31 +1319,38 @@ ru : далее :_revision_previous en : earlier revision ru : более ранняя редакция +cs : dřívější revize :_revision_next en : later revision ru : более поздняя редакция +cs : pozdější revize :_revision_title en : Revision [_1] ru : Редакция [_1] +cs : Revize [_1] # it's the summary of the edit, "edit" is not a verb here. :_revision_new_summary en : Edit summary ru : Суммарно +cs : Shrnutí editace :_revision_edit_summary en : Edit summary of revision [_1]: ru : Суммарно о редакции [_1]: +cs : Shrnutí editace revize[_1]: :_revision_user_date en : By [userstr,_1] on [date,_2,full] ru : [userstr,_1], [date,_2,full] +cs : Změnil [userstr,_1] [date,_2,full] :_revision_emptyfield en : ~[empty~] ru : ~[пусто~] +cs : ~[prázdná~] # tabs above the search boxes @@ -1128,27 +1358,33 @@ ru : ~[пусто~] :_searchbox_vn en : Visual novels ru : Новеллы +cs : Vizuální novely :_searchbox_releases en : Releases ru : Выпуски +cs : Vydání :_searchbox_producers en : Producers ru : Компании +cs : Producenti :_searchbox_tags en : Tags ru : Теги +cs : Tagy :_searchbox_users en : Users ru : Пользователи +cs : Uživatelé # text on the search button :_searchbox_submit en : Search! ru : Искать! +cs : Hledat! @@ -1176,39 +1412,55 @@ ru : VNDB.org стремится быть наиболее полной базо Если хотите, можете [url,/v/all,побродить по сайту], [url,/u/register,создать учётную запись] или поучаствовать в обсуждении новелл (либо самой VNDB) на нашем [url,/t,форуме] (убедительная просьба писать только на английском). +cs : VNDB.org se snaží být srozumitelnou databází informací o vizuálních novelách.[br] + Tato stránka funguje na principu wikipedie, tedy kdokoliv může volně přispívat informacemi + do databáze, což nám umožňuje tvořit největší, nejpřesnější a nejaktuálnější databázi + vizuálních novel na webu.[br] + Registrovaní uživatelé si také mohou vytvořit osobní list her, které chtějí hrát nebo dohráli + a mohou hodnotit všechny vizuální novely.[br][br] + Můžete jen tak [url,/v/all,brouzdat kolem], [url,/u/register,zaregistrovat si účet] + nebo se účastnit diskusí o vizuálních novelách nebo VNDB na našem [url,/t,diskusním boardu]. :_home_recentchanges en : Recent Changes ru : Свежие правки +cs : Poslední změny :_home_recentchanges_item en : [_1]:[_2] by [userstr,_3] ru : [_1]:[_2], [userstr,_3] +cs : [_1]:[_2], [userstr,_3] :_home_announcements en : Announcements ru : Объявления +cs : Oznámení :_home_recentposts en : Recent Posts ru : Недавние сообщения +cs : Poslední příspěvky :_home_recentposts_item en : [age,_1] [_2] by [userstr,_3] ru : [age,_1] [_2], [userstr,_3] +cs : [age,_1] [_2], [userstr,_3] :_home_randomvn en : Random vsual novels ru : Случайные новеллы +cs : Náhodné vizuální novely :_home_upcoming en : Upcoming releases ru : Грядущие выпуски +cs : Nadcházející vydání :_home_justreleased en : Just released ru : Только что вышли +cs : Právě vydáno @@ -1222,10 +1474,12 @@ ru : Только что вышли :_hist_title en : Recent changes ru : Свежие правки +cs : Poslední změny :_hist_title_item en : Edit history of [_1] ru : История изменений [_1] +cs : Editovat historii [_1] # the filter buttons @@ -1233,54 +1487,67 @@ ru : История изменений [_1] :_hist_filter_showauto en : Show automated edits ru : Показать автоматические правки +cs : Ukázat automatické editace :_hist_filter_hideauto en : Hide automated edits ru : Скрыть автоматические правки +cs : Skrýt automatické editace :_hist_filter_hidedel en : Hide deleted items ru : Скрыть удалённые страницы +cs : Skrýt smazané položky :_hist_filter_showdel en : Show deleted items ru : Показать удалённые страницы +cs : Ukázat smazané položky :_hist_filter_alltypes en : Show all items ru : Показать все страницы +cs : Ukázat všechny položky :_hist_filter_onlyvn en : Only visual novels ru : Только новеллы +cs : Pouze vizuální novely :_hist_filter_onlyreleases en : Only releases ru : Только выпуски +cs : Pouze vydání :_hist_filter_onlyproducers en : Only producers ru : Только компании +cs : Pouze producenti :_hist_filter_allactions en : Show all changes ru : Показать все изменения +cs : Ukázat všechny změny :_hist_filter_onlyedits en : Only edits ru : Только правки +cs : Pouze editace :_hist_filter_onlynew en : Only newly created pages ru : Только новые страницы +cs : Pouze nově stvořené stránky :_hist_filter_exrel en : Exclude edits of releases ru : Исключить правки выпусков +cs : Výjmout editace vydání :_hist_filter_increl en : Include edits of releases ru : Включить правки выпусков +cs : Zahrnout editace vydání # column headers @@ -1289,18 +1556,22 @@ ru : Включить правки выпусков :_hist_col_rev en : Rev. ru : Ревизия +cs : Rev. :_hist_col_date en : Date ru : Дата +cs : Datum :_hist_col_user en : User ru : Пользователь +cs : Uživatel :_hist_col_page en : Page ru : Страница +cs : Stránka @@ -1316,46 +1587,57 @@ ru : Страница :_thread_postedin en : Posted in ru : В теме +cs : Přispěno v :_thread_byuser en : by [userstr,_1] ru : [userstr,_1] +cs : , [userstr,_1] :_thread_editpost en : edit ru : правка +cs : editovat :_thread_deletedpost en : Post deleted. ru : Сообщение удалено. +cs : Příspěvek smazán. :_thread_lastmodified en : Last modified on [date,_1,full] ru : Последний раз редактировалось [date,_1,full] +cs : Naposledy změněno [date,_1,full] :_thread_noreply_title en : Reply ru : Ответить +cs : Odpovědět :_thread_noreply_locked en : This thread has been locked, you can't reply to it anymore ru : Данная тема заблокирована, вы больше не можете в неё ответить +cs : Tento thread byl zamčen, již se do něj nedá odpovědět :_thread_noreply_login en : You must be logged in to reply to this thread. ru : Вы должны быть авторизованы чтобы ответить в эту тему. +cs : Pro odpověď do tohoto threadu se musíte přihlásit. :_thread_quickreply_title en : Quick reply ru : Быстрый ответ +cs : Rychlá odpověď :_thread_quickreply_submit en : Reply ru : Ответить +cs : Odpovědět :_thread_quickreply_full en : Go advanced... ru : В расширенный режим... +cs : Rozšířený mód... # Post edit/reply/new thread form @@ -1363,54 +1645,67 @@ ru : В расширенный режим... :_postedit_newthread en : Start new thread ru : Начать новую тему +cs : Založit nový thread :_postedit_replyto en : Reply to [_1] ru : Ответить в [_1] +cs : Odpovědět na [_1] :_postedit_edit en : Edit post ru : Правка сообщения +cs : Editovat příspěvek :_postedit_form_username en : Username ru : Имя пользователя +cs : Uživatelské jméno :_postedit_form_title en : Thread title ru : Название темы +cs : Název threadu :_postedit_form_boards en : Board(s) ru : Форум(ы) +cs : Board(y) :_postedit_form_boards_info en : Read [url,/d9.2,d9.2] for information about how to specify boards. ru : О том как указывать форумы читайте в разделе [url,/d9.2,d9.2]. +cs : Přečtěte si [url,/d9.2,d9.2] pro informace jak určit správný board. :_postedit_form_locked en : Locked ru : Заблокировано +cs : Zamčený :_postedit_form_topic en : Topic ru : Тема +cs : Téma :_postedit_form_hidden en : Hidden ru : Скрыто +cs : Skrytý :_postedit_form_nolastmod en : Don't update last modified field ru : Не обновлять дату последнего изменения +cs : Neměnit poslední změněné pole :_postedit_form_msg en : Message ru : Сообщение +cs : Zpráva :_postedit_form_msg_format en : See [url,/d9.3,d9.3] for the allowed formatting codes ru : Список разрешённых кодов смотрите в разделе [url,/d9.3,d9.3] +cs : Přečtěte si [url,/d9.3,d9.3] pro povolené formátovací kódy # Browsing threads by board (/t/{board_id}) @@ -1418,22 +1713,27 @@ ru : Список разрешённых кодов смотрите в разд :_disboard_item_title en : Related discussions for [_1] ru : Темы, относящиеся к [_1] +cs : Diskuse pro [_1] :_disboard_rootlink en : Discussion board ru : Форум +cs : Diskusní board :_disboard_nothreads en : No related threads found ru : Связанных тем не найдено +cs : Nenalezeny žádné diskuse :_disboard_createyourown en : Why not create one yourself? ru : Почему бы не создать новую? +cs : Proč jednu nevytvořite sami? :_disboard_startnew en : Start a new thread ru : Начать новую тему +cs : Začít nový thread # The discussion board index (/t) @@ -1441,6 +1741,7 @@ ru : Начать новую тему :_disindex_title en : Discussion board index ru : Корневая директория форума +cs : Seznam diskusních boardů # Thread list (on discussion board index and board browser) @@ -1448,18 +1749,22 @@ ru : Корневая директория форума :_threadlist_col_topic en : Topic ru : Тема +cs : Téma :_threadlist_col_replies en : Replies ru : Ответов +cs : Odpovědi :_threadlist_col_starter en : Starter ru : Автор темы +cs : První příspěvek :_threadlist_col_lastpost en : Last post ru : Последнее сообщение +cs : Poslední příspěvek @@ -1477,26 +1782,32 @@ ru : Последнее сообщение :_prodpage_langtype en : [_1] [_2] ru : [_2], основной язык: [_1] +cs : [_2], [_1] :_prodpage_aliases en : a.k.a. [_1] ru : a.k.a. [_1] +cs : a.k.a. [_1] :_prodpage_vnrel en : Visual Novel Relations ru : Связи новелл +cs : Vztahy k vizuálním novelám :_prodpage_norel en : We have currently no visual novels by this producer. ru : У нас пока нет сведений о новеллах авторства этой компании. +cs : Nemáme žádné vizuální novely od tohoto producenta. :_prodpage_dev en : developer ru*: +cs*: :_prodpage_pub en : publisher ru*: +cs*: # producer diff fields @@ -1504,30 +1815,37 @@ ru*: :_revfield_p_type en : Type ru : Тип +cs : Typ :_revfield_p_name en : Name (romaji) ru : Название (ромадзи) +cs : Jméno (romaji) :_revfield_p_original en : Original name ru : Оригинальное название +cs : Originální jméno :_revfield_p_alias en : Aliases ru : Прочие названия +cs : Aliasy :_revfield_p_lang en : Language ru : Язык +cs : Jazyk :_revfield_p_website en : Website ru : Веб-сайт +cs : Internetová stránka :_revfield_p_desc en : Description ru : Описание +cs : Popis # Add/Edit producer @@ -1535,50 +1853,62 @@ ru : Описание :_pedit_title_edit en : Edit [_1] ru : Править [_1] +cs : Editovat [_1] :_pedit_title_add en : Add new producer ru : Добавление новой компании +cs : Přidat nového producenta :_pedit_form_generalinfo en : General info ru : Основная информация +cs : Obecné informace :_pedit_form_type en : Type ru : Тип +cs : Typ :_pedit_form_name en : Name (romaji) ru : Название (ромадзи) +cs : Jméno (romaji) :_pedit_form_original en : Original name ru : Оригинальное название +cs : Originální jméno :_pedit_form_original_note en : The original name of the producer, leave blank if it is already in the Latin alphabet. ru : Оригинальное название компании, оставьте пустым если уже в латинском алфавите. +cs : Originální jméno producenta, ponechte prázdné, pokud již je v latince. :_pedit_form_alias en : Aliases ru : Прочие названия +cs : Aliasy :_pedit_form_alias_note en : (Un)official aliases, separated by a comma. ru : (Не)официальные альтернативные названия, через запятую. +cs : Ne(oficiální) aliasy, oddělené čárkou. :_pedit_form_lang en : Primary language ru : Основной язык +cs : Hlavní jazyk :_pedit_form_website en : Website ru : Веб-сайт +cs : Internetová stránka :_pedit_form_desc en : Description ru : Описание +cs : Popis # Browse/search producers @@ -1586,18 +1916,22 @@ ru : Описание :_pbrowse_title en : Browse producers ru : Обзор компаний +cs : Procházet producenty :_pbrowse_searchres en : Search results ru : Результаты поиска +cs : Výsledky hledání :_pbrowse_list en : Producer list ru : Список компаний +cs : Seznam producentů :_pbrowse_noresults en : No results found ru : Ничего не найдено +cs : Nenalezeny žádné výsledky @@ -1613,94 +1947,117 @@ ru : Ничего не найдено :_revfield_r_vn en : Relations ru : Связи +cs : Vztahy :_revfield_r_type en : Type ru : Тип +cs : Typ :_revfield_r_patch en : Patch ru : Патч +cs : Patch :_revfield_r_freeware en : Freeware ru : Freeware +cs : Freeware :_revfield_r_doujin en : Doujin ru : Додзинси +cs : Doujin :_revfield_r_title en : Title (romaji) ru : Название (ромадзи) +cs : Název (romaji) :_revfield_r_original en : Original title ru : Оригинальное название +cs : Originální název :_revfield_r_gtin en : JAN/UPC/EAN ru : JAN/UPC/EAN +cs : JAN/UPC/EAN :_revfield_r_catalog en : Catalog number ru : Номер в каталоге +cs : Číslo v katalogu :_revfield_r_languages en : Language ru : Язык +cs : Jazyk :_revfield_r_website en : Website ru : Веб-сайт +cs : Internetová stránka :_revfield_r_released en : Release date ru : Дата выпуска +cs : Datum vydání :_revfield_r_minage en : Age rating ru : Возрастной рейтинг +cs : Věková přístupnost :_revfield_r_notes en : Notes ru : Заметки +cs : Poznámky :_revfield_r_platforms en : Platforms ru : Платформы +cs : Platformy :_revfield_r_media en : Media ru : Носители +cs : Média :_revfield_r_resolution en : Resolution ru : Разрешение +cs : Rozlišení :_revfield_r_voiced en : Voiced ru : Озвучка +cs : Hlas :_revfield_r_ani_story en : Story animation ru : Сюжетная анимация +cs : Animace příběhu :_revfield_r_ani_ero en : Ero animation ru : Анимация эросцен +cs : Ero animace :_revfield_r_producers en : Producers ru : Компании +cs : Producenti :_reldiff_developer en : developer ru*: +cs*: :_reldiff_publisher en : publisher ru*: +cs*: # Information table (on every release page) @@ -1708,118 +2065,147 @@ ru*: :_relinfo_vnrel en : Relation ru : Связи +cs : Vztah :_relinfo_title en : Title ru : Название +cs : Název :_relinfo_original en : Original title ru : Оригинальное название +cs : Originální název :_relinfo_type en : Type ru : Тип +cs : Typ :_relinfo_type_format en : [_1][index,_2,, patch] ru : [_1][index,_2,, патч] +cs : [_1][index,_2,, patch] :_relinfo_lang en : Language ru : Язык +cs : Jazyk :_relinfo_publication en : Publication ru : Публикация +cs : Publikováno :_relinfo_pub_nopatch en : [index,_1,Freeware,Non-free], [index,_2,doujin,commercial] ru : [index,_1,Freeware,Несвободная], [index,_2,додзинси,коммерческая] +cs : [index,_1,Freeware,Non-free], [index,_2,doujin,komerční] :_relinfo_pub_patch en : [index,_1,Freeware,Non-free] ru : [index,_1,Freeware,Несвободная] +cs : [index,_1,Freeware,Non-free] :_relinfo_platform en : [quant,_1,Platform,Platforms] ru : [quant,_1,Платформа,Платформы,Платформ] +cs : [quant,_1,Platforma,Platformy,Platforem] :_relinfo_media en : [quant,_1,Medium,Media] ru : [quant,_1,Носитель,Носители,Носителей] +cs : [quant,_1,Médium,Média,Médií] :_relinfo_resolution en : Resolution ru : Разрешение +cs : Rozlišení :_relinfo_voiced en : Voiced ru : Озвучка +cs : Hlas :_relinfo_ani en : Animation ru : Анимация +cs : Animace :_relinfo_ani_story en : Story: [_1] ru : Сюжет: [_1] +cs : Příběh: [_1] :_relinfo_ani_ero en : Ero scenes: [_1] ru : Эросцены: [_1] +cs : Ero scény: [_1] :_relinfo_released en : Released ru : Дата выпуска +cs : Vydáno :_relinfo_minage en : Age rating ru : Возрастной рейтинг +cs : Věková přístupnost :_relinfo_developer en : [quant,_1,Developer,Developers] ru*: +cs*: :_relinfo_publisher en : [quant,_1,Publisher,Publishers] ru*: +cs*: :_relinfo_catalog en : Catalog no. ru : № в каталоге +cs : Č. v katalogu :_relinfo_links en : Links ru : Ссылки +cs : Odkazy :_relinfo_website en : Official website ru : Официальный веб-сайт +cs : Oficiální stránky :_relinfo_user en : User options ru : Настройки пользователя +cs : Možnosti uživatele :_relinfo_user_notlist en : not in your list ru : не в вашем списке +cs : není ve vašem listu :_relinfo_user_inlist en : Status: [_1] / [_2] ru : Статус: [_1] / [_2] +cs : Status: [_1] / [_2] :_relinfo_user_setr en : Set release status ru : Установка статуса выпуска +cs : Změnit status vydání :_relinfo_user_setv en : Set play status ru : Установка статуса игры +cs : Změnit herní status :_relinfo_user_del en : remove from list ru : убрать из списка +cs : odstranit z listu # Editing a release @@ -1827,216 +2213,270 @@ ru : убрать из списка :_redit_title_edit en : Edit [_1] ru : Правка [_1] +cs : Editovat [_1] :_redit_title_copy en : Copy [_1] ru : Копирование [_1] +cs : Kopírovat [_1] :_redit_title_add en : Add release to [_1] ru : Добавление выпуска для [_1] +cs : Přidat vydání hry [_1] :_redit_form_geninfo en : General info ru : Основная информация +cs : Obecné informace :_redit_form_type en : Type ru : Тип +cs : Typ :_redit_form_patch en : This release is a patch to another release. ru : Данный выпуск является патчем для другого выпуска. +cs : Toto vydání je patch k jinému vydání. :_redit_form_freeware en : Freeware (i.e. available at no cost) ru : Freeware (т.е. распространяется бесплатно) +cs : Freeware (tj. dostupný zdarma) :_redit_form_doujin en : Doujin (self-published, not by a company) ru : Додзинси (выпущено самостоятельно, частным лицом) +cs : Doujin (publikováno samostatně, ne firmou) :_redit_form_title en : Title (romaji) ru : Название (ромадзи) +cs : Název (romaji) :_redit_form_original en : Original title ru : Оригинальное название +cs : Originální název :_redit_form_original_note en : The original title of this release, leave blank if it already is in the Latin alphabet. ru : Оригинальное название данного выпуска, осавьте пустым если уже в латинском алфавите. +cs : Originální název tohoto vydání, ponechte prázdné, pokud již je latinkou. :_redit_form_languages en : Language(s) ru : Язык(и) +cs : Jazyk(y) :_redit_form_gtin en : JAN/UPC/EAN ru : JAN/UPC/EAN +cs : JAN/UPC/EAN :_redit_form_catalog en : Catalog number ru : Номер в каталоге +cs : Číslo v katalogu :_redit_form_website en : Official website ru : Официальный веб-сайт +cs : Oficiální stránky :_redit_form_released en : Release date ru : Дата выпуска +cs : Datum vydání :_redit_form_released_note en : Leave month or day blank if they are unknown ru : Если месяц или день неизвестны, оставьте их пустыми +cs : Ponechte měsíc či den prázdné, pokud jsou neznámé :_redit_form_minage en : Age rating ru : Возрастной рейтинг +cs : Věková přístupnist :_redit_form_notes en : Notes ru : Заметки +cs : Poznámky :_redit_form_notes_note en : Miscellaneous notes/comments, information that does not fit in the above fields. E.g.: Censored/uncensored or for which releases this patch applies. ru : Дополнительные заметки/комментарии, информация для которой не нашлось приемлимых полей. Т.е.: присутствие/отсутствие цензуры, или для каких версий применим данный патч. +cs : Různé poznámky/komentáře a informace, které se nehodí do předchozích polí. + Např.: Cenzurovaná/necenzurovaná verze nebo pro které vydání je patch. :_redit_form_format en : Format ru : Формат +cs : Formát :_redit_form_resolution en : Resolution ru : Разрешение +cs : Rozlišení :_redit_form_voiced en : Voiced ru : Озвучка +cs : Hlas :_redit_form_ani_story en : Story animation ru : Сюжетная анимация +cs : Animace příběhu :_redit_form_ani_ero en : Ero animation ru : Анимация эросцен +cs : Ero animace :_redit_form_ani_ero_none en : Unknown / no ero scenes ru : Неизвестно / нет эросцен +cs : Není známo / bez ero scén :_redit_form_ani_ero_note en : Animation in erotic scenes, leave to unknown if there are no ero scenes. ru : Анимация в эротических сценах, не изменяйте поле если эросцены отсутствуют. +cs : Animace v ero scénách, ponechte na Není známo, pokud novela nemá ero scény. :_redit_form_platforms en : Platforms ru : Платформы +cs : Platformy :_redit_form_media en : Media ru : Носители +cs : Média :_redit_form_med_quantity en : -quantity- ru*: +cs*: :_redit_form_med_medium en : -medium- ru*: +cs*: :_redit_form_med_remove en : remove ru*: +cs*: :_redit_form_prod en : Producers ru : Компании +cs : Producenti :_redit_form_prod_sel en : Selected producers ru : Выбранные компании +cs : Vybraní producenti :_redit_form_prod_add en : Add producer ru : Добавить компанию +cs : Přidat producenta :_redit_form_prod_dev en : Developer ru*: +cs*: :_redit_form_prod_pub en : Publisher ru*: +cs*: :_redit_form_prod_both en : Both ru*: +cs*: :_redit_form_prod_addbut en : add ru*: +cs*: :_redit_form_prod_remove en : remove ru*: +cs*: :_redit_form_prod_none en : Nothing selected. ru*: +cs*: :_redit_form_prod_pformat en : Producer textbox must start with an ID (e.g. p17) ru*: +cs*: :_redit_form_prod_notfound en : Producer not found! ru*: +cs*: :_redit_form_prod_double en : Producer already selected! ru*: +cs*: :_redit_form_vn en : Visual novels ru : Новеллы +cs : Vizuální novely :_redit_form_vn_sel en : Selected visual novels ru : Выбранные новеллы +cs : Vybrané vizuální novely :_redit_form_vn_add en : Add visual novel ru : Добавить новеллу +cs : Přidat vizuální novelu :_redit_form_vn_addbut en : add ru*: +cs*: :_redit_form_vn_remove en : remove ru*: +cs*: :_redit_form_vn_none en : Nothing selected. ru*: +cs*: :_redit_form_vn_vnformat en : Visual novel textbox must start with an ID (e.g. v17) ru*: +cs*: :_redit_form_vn_notfound en : Visual novel not found! ru*: +cs*: :_redit_form_vn_double en : VN already selected! ru*: +cs*: # Release browser @@ -2044,22 +2484,27 @@ ru*: :_rbrowse_title en : Browse releases ru : Обзор выпусков +cs : Procházet vydání :_rbrowse_col_released en : Released ru : Выпущено +cs : Vydáno :_rbrowse_col_minage en : Rating ru : Рейтинг +cs : Hodnocení :_rbrowse_col_title en : Title ru : Название +cs : Název :_rbrowse_noresults_title en : No results found ru : Совпадений не найдено +cs : Nenalezeny žádné výsledky :_rbrowse_noresults_msg en : Sorry, couldn't find anything that comes through your filters. You might want to disable a few filters to get more results. @@ -2068,102 +2513,129 @@ en : Sorry, couldn't find anything that comes through your filters. You might wa ru : Простите, по вашему запросу ничего не найдено. Для получения результатов, попробуйте отключить пару-тройку фильтров. Также, не забывайте что у нас нет информации об абсолютно всех выпусках. Поэтому, если вы, например, поставили фильтр по разрешению экрана, он исключит все новеллы, не удовлетворяющие выбранному разрешению, даже если в действительности та которую вы ищите имеет искомое разрешение. +cs : Omlouváme se, nenalezli jsme nic, co by vyhovovalo vašemu nastavení filtrů. Možná najdete více výsledků, pokud nějaké z nich vypnete. + + Také nezapomeňte, že o všech vydáních nemáme všechny údaje. Takže pokud například vyfiltrujete rozlišení obrazovky, pak ve výsledcích nebudou všechna vydání, u kterých neznáme jejich rozlišení, i když by to mohla být právě vydání v rozlišení, o které se zajímáte. :_rbrowse_filters en : Filters ru : Фильтры +cs : Filtry :_rbrowse_minage en : Age rating ru : Возрастной рейтинг +cs : Věková přístupnost :_rbrowse_ge en : Greater than or equal to ru : Больше или равно +cs : Větší než nebo rovno :_rbrowse_le en : Less than or equal to ru : Меньше или равно +cs : Menší než nebo rovno :_rbrowse_resolution en : Screen resolution ru : Разрешение экрана +cs : Rozlišení obrazovky :_rbrowse_type en : Release type ru : Тип выпуска +cs : Typ vydání :_rbrowse_all en : All ru : Все +cs : Vše :_rbrowse_patch en : Patch status ru : Статус патча +cs : Status patche :_rbrowse_patchonly en : Only patches ru : Только патчи +cs : Pouze patche :_rbrowse_patchnone en : Only standalone releases ru : Только самостоятельные выпуски +cs : Pouze samostatná vydání :_rbrowse_freeware en : Freeware ru : Freeware +cs : Freeware :_rbrowse_freewareonly en : Freeware only ru : Только Freeware +cs : Pouze freeware :_rbrowse_freewarenone en : Only non-free releases ru : Только несвободные +cs : Pouze placená vydání :_rbrowse_doujin en : Doujin ru : Додзинси +cs : Doujin :_rbrowse_doujinonly en : Only doujin releases ru : Только додзинси +cs : Pouze doujin vydání :_rbrowse_doujinnone en : Only commercial releases ru : Только коммерческие +cs : Pouze komerční vydání :_rbrowse_dateafter en : Released after ru : Выпущены после +cs : Vydáno po :_rbrowse_datebefore en : Released before ru : Выпущены до +cs : Vydáno před :_rbrowse_languages en : Languages ru : Языки +cs : Jazyky :_rbrowse_boolor en : boolean or, selecting more gives more results ru : булевое 'или', чем больше выбрано, тем больше даёт результатов +cs : boolean nebo, výběr více dá více výsledků :_rbrowse_platforms en : Platforms ru : Платформы +cs : Platformy :_rbrowse_media en : Media ru : Носители +cs : Média :_rbrowse_apply en : Apply ru : Применить +cs : Použít :_rbrowse_clear en : Clear ru : Очистить +cs : Začít znovu @@ -2179,88 +2651,110 @@ ru : Очистить :_tagp_title en : [index,_1,Meta tag,Tag]: [_2] ru : [index,_1,Мета тег,Тег]: [_2] +cs : [index,_1,Meta tag,Tag]: [_2] :_tagp_del_title en : Tag deleted ru : Тег удалён +cs : Tag smazán :_tagp_del_msg en : This tag has been removed from the database, and cannot be used or re-added. File a request on the [url,/t/db,discussion board] if you disagree with this. ru : Данный тег удалён из базы данных, и не может быть использован. Напишите на [url,/t/db,форуме], если вы с этим не согласны. +cs : Tento tag byl smazán z databáze a nemůže být použit nebo znovu přidán. + Pokud s tímto nesouhlasíte, napište žádost na [url,/t/db,diskusní board]. :_tagp_pending_title en : Waiting for approval ru : Ждёт одобрения +cs : Čeká na schválení :_tagp_pending_msg en : 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. ru : Данный тег ожидает одобрения модератором. Однако, вы можете использовать его для пометки новелл, как и любой нормальный тег. +cs : Tento tag čeká na schválení moderátorem. Mezitím ho stále můžete používat jako normální tag. :_tagp_addchild en : Create child tag ru : Создать дочерний тег +cs : Vytvořit závislý tag :_tagp_indexlink en : Tags ru : Теги +cs : Tagy :_tagp_aliases en : Aliases ru : Прочие названия +cs : Aliasy :_tagp_childs en : Child tags ru : Дочерние теги +cs : Závislé tagy :_tagp_tree en : Tag tree ru : Древо тега +cs : Strom tagů :_tagp_moretags en : [_1] more [quant,_1,tag,tags] ru : ещё [_1] [quant,_1,тег,тега,тегов] +cs : [_1] [quant,_1,další tag,další tagy,dalších tagů] :_tagp_vnlist en : Visual novels ru : Новеллы +cs : Vizuální novely :_tagp_spoil0 en : Hide spoilers ru : Скрыть спойлеры +cs : Skrýt spoilery :_tagp_spoil1 en : Show minor spoilers ru : Показать лёгкие спойлеры +cs : Ukázat menší spoilery :_tagp_spoil2 en : Show major spoilers ru : Показать жёсткие спойлеры +cs : Ukázat všechny spoilery :_tagp_novn en : This tag has not been linked to any visual novels yet, or they were hidden because of the spoiler settings. ru : Этот тег пока не содержит ссылок ни на одну новеллу, либо они скрыты из-за настроек отображения спойлеров. +cs : Tento tag ještě nebyl použit v žádné vizuální novele nebo byly tyto skryty kvůli nastavení spoilerů. :_tagp_cached en : NOTE: 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. ru : ЗАМЕЧАНИЕ: Данный список кэшируется, поэтому может пройти вплоть до 24 часов, прежде чем новелла, помеченная тегом, отобразится на этой странице. +cs : POZNÁMKA: Tento list se ukládá do cache, takže může trvat až 24 hodin po otagování vizuální novely do objevení se na této stránce. :_tagp_vncol_score en : Score ru : Балл +cs : Skóre :_tagp_vncol_title en : Title ru : Название +cs : Název :_tagp_vncol_rel en : Released ru : Выпуск +cs : Vydáno :_tagp_vncol_pop en : Popularity ru : Популярность +cs : Popularita # Tag add/edit form (/g+/edit, /g+/add, /g/add) @@ -2268,26 +2762,32 @@ ru : Популярность :_tagedit_err_notfound en : Tag '[_1]' not found ru : Тег '[_1]' не найден +cs : Tag '[_1]' nenalezen :_tagedit_title_add en : Add child tag to [_1] ru : Добавление дочернего тега для '[_1]' +cs : Přidat závislý tag tagu [_1] :_tagedit_title_edit en : Edit tag: [_1] ru : Править тег: [_1] +cs : Editovat tag: [_1] :_tagedit_title_new en : Add new tag ru : Добавить новый тег +cs : Přidat nový tag :_tagedit_req_title en : Requesting new tag ru : Запросить новый тег +cs : Požaduje se nový tag :_tagedit_req_subtitle en : Your tag must be approved ru : Ваш тег должен быть одобрен +cs : Váš tag musí být schválen :_tagedit_req_msg en : Because all tags have to be approved by moderators, it can take a while before it will show up in the tag list @@ -2298,68 +2798,88 @@ ru : В связи с тем что все теги должны быть утв займёт некоторое время. Однако, вы всё равно можете голосовать за тег, даже если тот ещё не был утверждён. [br][br] Также, пожалуйста убедитесь что прочли [url,/d10,рекомендации], тогда вам не придётся гадать, утвердят ваш тег или нет. +cs : Protože všechny tagy musí být schválené moderátorem, může chvilku trvat, než se objeví na listu tagů + nebo na stránce vizuální novely. I před schválením ale můžete stále tag hodnotit. + [br][br] + Také se ujistěte, že jste přečetli [url,/d10,doporučení], abyste věděli, zda váš tag bude přidán nebo ne. :_tagedit_frm_name en : Primary name ru : Основное название +cs : Hlavní jméno :_tagedit_frm_by en : Added by ru : Добавлено +cs : Přidal :_tagedit_frm_state en : State ru : Состояние +cs : Stav :_tagedit_frm_state0 en : Awaiting moderation ru : Ждёт модерации +cs : Čeká na schválení :_tagedit_frm_state1 en : Deleted/hidden ru : Удалён/скрыт +cs : Smazán/skryt :_tagedit_frm_state2 en : Approved ru : Одобрен +cs : Schválen :_tagedit_frm_meta en : This is a meta-tag (only to be used as parent for other tags, not for linking to VN entries) ru : Это мета-тег (его нельзя добавлять к новеллам, он может использоваться лишь как родитель для других тегов) +cs : Toto je meta-tag (používá se pouze jako mateřský pro ostatní tagy, ne pro vlastní vizuální novely) :_tagedit_frm_meta_warn en : WARNING: Checking this option or selecting "Deleted" as state will permanently delete all existing VN relations! ru : ПРЕДУПРЕЖДЕНИЕ: Если выбрать данную опцию, либо выставить состояние "Удалён", произойдёт немедленное удаление всех существующих связей с новеллами! +cs : VAROVÁNÍ: Zaškrtnutí této volby nebo výběr položky "Smazáno" jako stavu smaže automaticky tag u všech vizuálních novel! :_tagedit_frm_alias en : Aliases (separated by newlines) ru : Прочие названия (каждое с новой строки) +cs : Aliasy + (odděleny novou řádkou) :_tagedit_frm_desc en : Description ru : Описание +cs : Popis :_tagedit_frm_desc_msg en : What should the tag be used for? Having a good description helps users choose which tags to link to a VN. ru : Для пометки чего будет использоваться тег? Хорошее описание поможет пользователям выбрать подходящий тег для подходящей новеллы. +cs : Pro co by měl být tag používán? Tagy s dobrým popisem usnadňují uživatelům jejich používání u vizuálních novel. :_tagedit_frm_parents en : Parent tags ru : Родительские теги +cs : Mateřské tagy :_tagedit_frm_parents_msg en : Comma separated list of tag names to be used as parent for this tag. ru : Теги, которые будут задействованы для этого в качестве родительских. Через запятую. +cs : Seznam tagů, oddělených čárkou, které mají být použity jako mateřské pro tento tag :_tagedit_frm_merge en : Merge tags ru : Объединение тегов +cs : Sjednotit tagy :_tagedit_frm_merge_tags en : Tags to merge ru : Теги для объединения +cs : Tagy ke sjednocení :_tagedit_frm_merge_msg en : Comma separated list of tag names to merge into this one. All votes and aliases/names will be moved over @@ -2368,6 +2888,9 @@ en : Comma separated list of tag names to merge into this one. All votes and ali ru : Список тегов для объединения в данный, через запятую. Все голоса и побочные названия будут перемещены в данный тег, а все старые теги удалены. Оставьте поле пустым, если вы не собираетесь проводить объединение. [br]ПРЕДУПРЕЖДЕНИЕ: данную операцию отменить невозможно! +cs : Seznam tagů, oddělených čárkou, ke sjednocení do tohoto. Všechny hlasy a aliasy/jména budou přesunuty do tohoto tagu + a staré tagy budou smazány. Nechte toto pole prázdné, pokud nehodláte nic sjednocovat. + [br]VAROVÁNÍ: tato akce nejde vrátit! # Plain tag browser (/g/list) @@ -2375,42 +2898,52 @@ ru : Список тегов для объединения в данный, че :_tagb_title en : Browse tags ru : Обзор тегов +cs : Procházet tagy :_tagb_state-1 en : All ru : Все +cs : Všechny :_tagb_state0 en : Awaiting moderation ru : Ожидающие модерации +cs : Čekající na schválení :_tagb_state1 en : Deleted ru : Удалённые +cs : Smazané :_tagb_state2 en : Accepted ru : Одобренные +cs : Přijaté :_tagb_noresults en : No results found ru : Совпадений не найдено +cs : Nenalezeny žádné výsledky :_tagb_col_added en : Created ru : Созданы +cs : Vytvořené :_tagb_col_name en : Tag ru : Тег +cs : Tag :_tagb_note_awaiting en : awaiting moderation ru : ждёт модерации +cs : čeká na schválení :_tagb_note_del en : deleted ru : удалён +cs : smazán # VN<->Tag voting (/v+/tagmod) @@ -2418,88 +2951,110 @@ ru : удалён :_tagv_title en : Add/remove tags for [_1] ru : Добавление/удаление тегов для [_1] +cs : Přidat/odebrat tag pro novelu [_1] :_tagv_msg_title en : Tagging ru : Пометка тегами +cs : Tagování :_tagv_msg_guidelines en : Make sure you have read the [url,/d10,guidelines]! ru : Пожалуйста, убедитесь что прочли [url,/d10,рекомендации]! +cs : Ujistěte se, že jste přečetli [url,/d10,doporučení]! :_tagv_msg_submit en : Don't forget to hit the submit button on the bottom of the page to make your changes permanent. ru : Не забудьте сохранить изменения, нажав соответствующую кнопку в низу страницы, иначе они не вступят в силу. +cs : Nezapomeňte potvrdit tlačítko na spodku stránky, abyste uložili změny trvale. :_tagv_msg_cache en : Some tag information on the site is cached, it can take up to an hour for your changes to be visible everywhere. ru : Информация о некоторых тегах на данном сайте кэшируется, поэтому ваши изменения станут видны везде в течение часа. +cs : Některé informace o tazích na této stránce jsou v cache a může zabrat až hodinu než budou změny vidět. :_tagv_frm_title en : Tags ru : Теги +cs : Tagy :_tagv_col_you en : You ru : Вы +cs : Vy :_tagv_col_others en : Others ru : Остальные +cs : Ostatní :_tagv_col_tag en : Tag ru : Тег +cs : Tag :_tagv_col_rating en : Rating ru : Рейтинг +cs : Hodnocení :_tagv_col_spoiler en : Spoiler ru : Спойлер +cs : Spoiler :_tagv_save en : Save changes ru : Сохранить изменения +cs : Uložit změny :_tagv_add en : Add tag ru : Добавить тег +cs : Přidat tag :_tagv_addmsg en : Check the [url,/g,tag list] to browse all available tags.[br] Can't find what you're looking for? [url,/g/new,Request a new tag]. ru : Откройте [url,/g,список тегов] чтобы увидеть все доступные теги.[br] Не нашли что искали? Вы можете [url,/g/new,запросить новый тег]. +cs : Zkontrolujte [url,/g,list tagů] pro seznam všech dostupných tagů.[br] + Nenašli jste, co jste hledali? [url,/g/new,Vyžádejte si nový tag]. :_tagv_spoil0 en : neutral ru*: +cs*: :_tagv_spoil1 en : no spoiler ru*: +cs*: :_tagv_spoil2 en : minor spoiler ru*: +cs*: :_tagv_spoil3 en : major spoiler ru*: +cs*: :_tagv_notfound en : Item not found! ru*: +cs*: :_tagv_nometa en : Can't use meta tags here! ru*: +cs*: :_tagv_double en : Tag is already present! ru*: +cs*: # User tag list (/u+/tags) @@ -2507,34 +3062,42 @@ ru*: :_tagu_title en : Tags by [_1] ru : Теги [_1] +cs : Tagy podle [_1] :_tagu_spoilerwarn en : Warning: spoilery tags are not hidden in this list! ru : Предупреждение: в этом списке отображаются теги-спойлеры! +cs : Varování: spoilerové tagy nejsou v tomto seznamu skryté! :_tagu_notags en : [_1] doesn't seem to have used the tagging system yet... ru : Похоже, что [_1] пока не использует систему тегов... +cs : Nezdá se, že by [_1] zatím použil tagovací systém... :_tagu_col_num en : #VNs ru : #Новеллы +cs : #VN :_tagu_col_name en : Tag ru : Тег +cs : Tag :_tagu_spoil0 en : No spoiler ru : Нет спойлера +cs : Bez spoilerů :_tagu_spoil1 en : Minor spoiler ru : Лёгкий спойлер +cs : Menší spoilery :_tagu_spoil2 en : Major spoiler ru : Жёсткий спойлер +cs : Všechny spoilery # Tag index (/g) @@ -2542,42 +3105,52 @@ ru : Жёсткий спойлер :_tagidx_title en : Tag index ru : Индекс тега +cs : Seznam tagů :_tagidx_create en : Create new tag ru : Создать новый тег +cs : Vytvořit nový tag :_tagidx_search en : Search tags ru : Поиск тегов +cs : Hledat tag :_tagidx_browseall en : Browse all tags ru : Обзор всех тегов +cs : Procházet všechny tagy :_tagidx_recent en : Recently added ru : Недавно добавлены +cs : Poslední přidané :_tagidx_popular en : Popular tags ru : Популярные теги +cs : Populární tagy :_tagidx_queue en : Awaiting moderation ru : Ожидают модерации +cs : Čekající na schválení :_tagidx_queue_empty en : Moderation queue empty! yay! ru : В очереди модерации пусто! Няа! +cs : Fronta ke schválení prázdná! Jej! :_tagidx_queue_link en : Moderation queue ru : Очередь модерации +cs : Fronta ke schválení :_tagidx_denied en : Denied tags ru : Отклонённые теги +cs : Zamítnuté tagy @@ -2593,42 +3166,52 @@ ru : Отклонённые теги :_wishlist_title_my en : My wishlist ru : Мой список желаемого +cs : Můj wishlist :_wishlist_title_other en : [_1]'s wishlist ru : Список желаемого [_1] +cs : Wishlist uživatele [_1] :_wishlist_noresults en : Wishlist empty... ru : Список пуст... +cs : Wishlist je prázdný... :_wishlist_prio_all en : All priorities ru : Все приоритеты +cs : Všechny priority :_wishlist_col_title en : Title ru : Название +cs : Název :_wishlist_col_prio en : Priority ru : Приоритет +cs : Priorita :_wishlist_col_added en : Added ru : Добавлено +cs : Přidáno :_wishlist_select en : -- with selected -- ru : -- с выбранными -- +cs : -- s vybranými -- :_wishlist_changeprio en : Change priority ru : Изменить приоритет +cs : Změnit prioritu :_wishlist_remove en : remove from wishlist ru : убрать из списка желаемого +cs : odstranit z wishlistu # VN list (/u+/list) @@ -2636,54 +3219,67 @@ ru : убрать из списка желаемого :_rlist_title_my en : My visual novel list ru : Мой список новелл +cs : Můj list vizuálních novel :_rlist_title_other en : [_1]'s visual novel list ru : Список новелл [_1] +cs : List vizuálních novel uživatele [_1] :_rlist_voted_all en : All ru : Все +cs : Všechny :_rlist_voted_only en : Only voted ru : Проголосованные +cs : Pouze hodnocené :_rlist_voted_none en : Hide voted ru : Скрыть проголосованные +cs : Skrýt hodnocené :_rlist_col_title en : Title ru : Название +cs : Název :_rlist_col_releases en : Releases ru : Выпуски +cs : Vydání :_rlist_col_vote en : Vote ru : Голос +cs : Hodnocení :_rlist_selection en : -- with selected -- ru : -- с выбранными -- +cs : -- s vybranými -- :_rlist_changerel en : Change release status ru : Смена статуса выпуска +cs : Změnit stav vydání :_rlist_changeplay en : Change play status ru : Смена статуса игры +cs : Změnit stav hraní :_rlist_del en : remove from list ru : убрать из списка +cs : odstranit z listu :_rlist_releasenote en : * Obtained/finished/total ru : * Приобретено/прочитано/всего +cs : * Sehnáno/dohráno/celkem @@ -2699,66 +3295,82 @@ ru : * Приобретено/прочитано/всего :_userpage_title en : [_1]'s profile ru : Учётная запись [_1] +cs : Profil uživatele [_1] :_userpage_username en : Username ru : Имя пользователя +cs : Uživatelské jméno :_userpage_registered en : Registered ru : Регистрация +cs : Registrován :_userpage_edits en : Edits ru : Правки +cs : Editace :_userpage_votes en : Votes ru : Отдано голосов +cs : Hlasování :_userpage_votes_item en : [url,_1,_2] ([_3] average) ru : [url,_1,_2] ([_3] в среднем) +cs : [url,_1,_2] (průměr [_3]) :_userpage_hidden en : hidden ru : скрыто +cs : skryto :_userpage_tags en : Tags ru : Теги +cs : Tagy :_userpage_tags_item en : [_1] [quant,_1,vote,votes] on [_2] distinct [quant,_2,tag,tags] and [_3] visual [quant,_3,novel,novels] ru : [_1] [quant,_1,голос,голоса,голосов] по [_2][quant,_2,-у тегу,-м различным тегам,-и различным тегам] и [_3][quant,_3,-й новелле,-м новеллам,-и новеллам] +cs : [_1] [quant,_1,hlasy,hlasy,hlasů] pro [_2] [quant,_2,tag,různé tagy,různých tagů] a [_3] [quant,_3,vizuální novelu,vizuální novely,vizuálních novel] :_userpage_list en : List stats ru : Статистика по спискам +cs : Statistiky listu :_userpage_list_item en : [_1] [quant,_1,release,releases] of [_2] visual [quant,_2,novel,novels] ru : [_1] [quant,_1,выпуск,выпуска,выпусков] [_2][quant,_2,-й новеллы,-х новелл,-и новелл] +cs : [_1] [quant,_1,vydání,vydání,vydání] [_2] [quant,_2,vizuální novely,vizuálních novel,vizuálních novel] :_userpage_forum en : Forum stats ru : Статистика по форуму +cs : Statistiky fóra :_userpage_forum_item en : [_1] [quant,_1,post,posts], [_2] new [quant,_2,thead,threads]. ru : [_1] [quant,_1,сообщение,сообщения,сообщений], [_2] [quant,_2,новая тема,новые темы,новых тем] +cs : [_1] [quant,_1,příspěvek, příspěvky, příspěvků], [_2] [quant,_2,nový thread, nové thready, nových threadů]. :_userpage_forum_browse en : Browse posts ru : Обзор сообщений +cs : Procházet příspěvky :_userpage_votestats en : Vote statistics ru : Статистика по голосованиям +cs : Statistiky hlasování :_userpage_changes en : Recent changes ru : Свежие правки +cs : Poslední změny # Login form (/u/login) @@ -2766,22 +3378,27 @@ ru : Свежие правки :_login_title en : Login ru : Вход +cs : Přihlásit :_login_username en : Username ru : Имя пользователя +cs : Uživatelské jméno :_login_register en : No account yet? ru : Нет учётной записи? +cs : Ještě nemáte účet? :_login_password en : Password ru : Пароль +cs : Heslo :_login_forgotpass en : Forgot your password? ru : Забыли пароль? +cs : Zapomněli jste své heslo? # Reset password (/u/newpass) @@ -2808,14 +3425,27 @@ ru : Привет, [_1] Постарайтесь больше не забывать свой пароль! :-) + vndb.org +cs : Zdravíme, [_1] + + Vaše heslo bylo změněno, nyní se můžete přihlásit na http://vndb.org + s následujícími informacemi: + + Uživatelské jmno: [_1] + Heslo: [_2] + + A snažte se už heslo znovu nezapomenout! :-) + vndb.org :_newpass_mail_subject en : New password for [_1] ru : Новый пароль для [_1] +cs : Nové heslo pro uživatele [_1] :_newpass_title en : Forgot password ru : Забытый пароль +cs : Zapomenuté heslo :_newpass_msg en : Forgot your password and can't login to VNDB anymore? @@ -2825,22 +3455,29 @@ ru : Забыли пароль и больше не можете авториз Без паники! Всё что вам нужно - указать адрес электронной почты, который вы использовали для регистрации в VNDB, и мы вышлем вам новый пароль за считанные минуты! +cs : Zapomněli jste své heslo a nemůžete se přihlásit na VNDB? + Nebojte! Stačí zadat e-mailovou adresu, se kterou jste se na VNDB registrovali, + a my vám do několika minut pošleme heslo nové! :_newpass_reset_title en : Reset password ru : Сброс пароля +cs : Změnit heslo :_newpass_mail en : Email ru : E-mail +cs : E-mail :_newpass_sent_title en : New password ru : Новый пароль +cs : Nové heslo :_newpass_sent_subtitle en : Password reset ru : Сбросить пароль +cs : Změnit heslo :_newpass_sent_msg en : Your password has been reset and your new password should reach your mailbox in a few minutes.[br] @@ -2851,16 +3488,22 @@ ru : Ваш пароль был сброшен. Через несколько м Вы всегда можете изменить пароль после того как прошли авторизацию.[br] [br] [url,/u/login,Вход] - [url,/,Главная] +cs : Vaše heslo bylo změněno a vaše nové heslo by mělo být za několik minut doručeno do vaší schránky.[br] + Vždy můžete změnit vaše heslo po přihlášení.[br] + [br] + [url,/u/login,Přihlásit] - [url,/,Home] # Register new account (/u/register) :_register_title en : Create an account ru : Создание учётной записи +cs : Vytvořit účet :_register_why en : Why should I register? ru : Для чего нужна регистрация? +cs : Proč bych se měl registrovat? :_register_why_msg en : Creating an account is completely painless, the only thing we need to know is your prefered username @@ -2883,36 +3526,53 @@ ru : Создание учётной записи совершенно безо - Следить за всеми новеллами и выпусками, которые у вас есть, в которые вы бы хотели сыграть, в которые играете, либо уже доиграли[br] - Голосовать за понравившиеся или, наоборот, не понравившиеся новеллы[br] - Вступать в обсуждения на ветках форума +cs : Tvorba účtu je zcela bezbolestná, jediné údaje, které potřebujeme znát jsou uživatelské jméno, které chcete, a vaše heslo. + Můžete i použít e-mail, který není váš, jelikož ani neověřujeme, že jste nám zadali opravdu váš e-mail. + Pamatujte ale, že pokud jste zadali neplatnou e-mailovou adresu, pak byste si měli dobře zapamatovat vaše heslo...[br] + [br] + V každém případě, založení účtu vám přináší několik výhod oproti běžným návštěvníkům[br] + - Můžete přispívat do databáze editací všech dat a přidáváním dat nových[br] + - Mějte přehled o všech vizuálních novelách, které máte, chtěli byste hrát, hrajete, nebo jste dohráli[br] + - Hlasujte pro vizuální novely, které se vám líbily nebo nelíbily[br] + - Přispívejte do diskusí na boardech :_register_form_title en : New account ru : Новая учётная запись +cs : Nový účet :_register_username en : Username ru : Имя пользователя +cs : Uživatelské jméno :_register_username_msg en : Preferred username. Must be lowercase and can only consist of alphanumeric characters. ru : Запрашиваемое имя пользователя. Должно состоять из буквенно-цифровых символов в нижнем регистре. +cs : Požadováné uživatelské jméno. Musí být malými písmeny a smí obsahovat pouze písmena a číslice. :_register_mail en : Email ru : E-mail +cs : E-mail :_register_mail_msg en : 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. ru : Адрес вашей электронной почты будет использоваться лишь в случае утери пароля. Мы никогда не пришлём вам спама или новостных рассылок, пока вы недвусмысленно не попросите об обратном. +cs : Vaše e-mailová adresa bude použita pouze v případě ztráty vašeho hesla. Nikdy vám nezašleme spam nebo newslettery, + pokud o to explicitně nezažádáte. :_register_password en : Password ru : Пароль +cs : Heslo :_register_confirm en : Confirm password ru : Подтверждение пароля +cs : Potvrdit heslo # User edit (/u+/edit) @@ -2920,70 +3580,87 @@ ru : Подтверждение пароля :_usere_title en : My account ru : Моя учётная запись +cs : Můj účet :_usere_saved_title en : Settings saved ru : Параметры сохранены +cs : Nastavení uloženo :_usere_saved_msg en : Settings successfully saved. ru : Параметры успешно сохранены. +cs : Nastavení úspěšně uloženo. :_usere_geninfo en : General info ru : Основная информация +cs : Obecné informace :_usere_username en : Username ru : Имя пользователя +cs : Uživatelské jméno :_usere_rank en : Rank ru : Ранг +cs : Postavení :_usere_ignvotes en : Ignore votes in VN statistics ru : Игнорировать голосования в статистике новелл +cs : Ignorovat hlasy ve statistikách vizuálních novel :_usere_mail en : Email ru : E-mail +cs : E-mail :_usere_changepass en : Change password ru : Смена пароля +cs : Změnit heslo :_usere_changepass_msg en : Leave blank to keep your current password ru : Оставьте пустым чтобы сохранить текущий пароль +cs : Zanechte prázdné pro zachování současného hesla :_usere_password en : Password ru : Пароль +cs : Heslo :_usere_confirm en : Confirm password ru : Подтверждение пароля +cs : Potvrdit heslo :_usere_options en : Options ru : Настройки +cs : Nastavení :_usere_flist en : Allow other people to see my visual novel list ([url,_1,_1]) and wishlist ([url,_2,_2]) ru : Разрешить остальным видеть мой список новелл ([url,_1,_1]) и список желаемого ([url,_2,_2]) +cs : Povolit ostatním zobrazit můj list vizuálních novel ([url,_1,_1]) a wishlist ([url,_2,_2]) :_usere_fnsfw en : Disable warnings for images that are not safe for work. ru : Отключить предупреждения для небезопасных изображений. +cs : Vypnout varování pro obrázky, které jsou "Not Safe For Work". :_usere_skin en : Prefered skin ru : Предпочитаемая шкурка +cs : Preferovaný skin :_usere_css en : Additional [url,http://en.wikipedia.org/wiki/Cascading_Style_Sheets,CSS] ru : Дополнительный [url,http://en.wikipedia.org/wiki/Cascading_Style_Sheets,CSS] +cs : Další [url,http://en.wikipedia.org/wiki/Cascading_Style_Sheets,CSS] # Users posts (/u+/posts) @@ -2991,18 +3668,22 @@ ru : Дополнительный [url,http://en.wikipedia.org/wiki/Cascading_St :_uposts_title en : Posts made by [_1] ru : Сообщения [_1] +cs : Příspěvek od uživatele [_1] :_uposts_noresults en : [_1] hasn't made any posts yet. ru : [_1] пока не имеет сообщений. +cs : [_1] ještě nenapsal žádný příspěvek. :_uposts_col_date en : Date ru : Дата +cs : Datum :_uposts_col_title en : Title ru : Название +cs : Název # User list (/u/all) @@ -3010,26 +3691,32 @@ ru : Название :_ulist_title en : Browse users ru : Обзор пользователей +cs : Procházet uživatele :_ulist_col_username en : Username ru : Имя пользователя +cs : Uživatelské jméno :_ulist_col_registered en : Registered ru : Регистрация +cs : Registrován :_ulist_col_votes en : Votes ru : Отдано голосов +cs : Hlasy :_ulist_col_edits en : Edits ru : Правок +cs : Editace :_ulist_col_tags en : Tags ru : Тегов +cs : Tagy @@ -3048,86 +3735,107 @@ ru : Тегов :_vnbrowse_title en : Browse visual novels ru : Обзор новелл +cs : Procházet vizuální novely :_vnbrowse_col_score en : Score ru : Рейтинг +cs : Skóre :_vnbrowse_col_title en : Title ru : Название +cs : Název :_vnbrowse_col_released en : Released ru : Выпуск +cs : Vydáno :_vnbrowse_col_popularity en : Popularity ru : Популярность +cs : Popularita :_vnbrowse_tagign_title en : The following tags were ignored: ru : Следующие теги были пропущены: +cs : Následující tagy byly ignorovány: :_vnbrowse_tagign_meta en : can't filter on meta tags ru : фильтрация мета-тегов невозможна +cs : nedají se filtrovat meta tagy :_vnbrowse_tagign_notfound en : no such tag found ru : тег не найден +cs : nenalezeny takové tagy :_vnbrowse_advsearch en : advanced search ru : расширенный поиск +cs : pokročilé hledání :_vnbrowse_tags en : Tag filters ru : Фильтры тегов +cs : Filtry tagů :_vnbrowse_booland en : boolean and, selecting more gives less results ru : булевое 'и', чем больше выбрано, тем меньше даёт результатов +cs : boolean a, výběr více dá méně výsledků :_vnbrowse_taginc en : Tags to include ru : Включить теги +cs : Tagy k zahrnutí :_vnbrowse_tagexc en : Tags to exclude ru : Исключить теги +cs : Tagy k vyjmutí :_vnbrowse_spoil0 en : Hide spoilers ru : Скрыть спойлеры +cs : Skrýt spoilery :_vnbrowse_spoil1 en : Show minor spoilers ru : Показать лёгкие спойлеры +cs : Ukázat menší spoilery :_vnbrowse_spoil2 en : Show major spoilers ru : Показать жёсткие спойлеры +cs : Ukázat všechny spoilery :_vnbrowse_lang en : Languages ru : Языки +cs : Jazyky :_vnbrowse_boolor en : boolean or, selecting more gives more results ru : булевое 'или', чем больше выбрано, тем больше даёт результатов +cs : boolean nebo, výběr více dá více výsledků :_vnbrowse_plat en : Platforms ru : Платформы +cs : Platformy :_vnbrowse_apply en : Apply ru : Применить +cs : Použít :_vnbrowse_clear en : Clear ru : Очистить +cs : Začít znovu # VN add/edit form (/v+/edit) @@ -3135,30 +3843,37 @@ ru : Очистить :_vnedit_title_edit en : Edit [_1] ru : Правка [_1] +cs : Editovat vizuální novelu [_1] :_vnedit_title_add en : Add a new visual novel ru : Добавление новой новеллы +cs : Přidat novou vizuální novelu :_vnedit_geninfo en : General info ru : Основная информация +cs : Obecné informace :_vnedit_frm_title en : Title (romaji) ru : Название (ромадзи) +cs : Název (romaji) :_vnedit_original en : Original title ru : Оригинальное название +cs : Originální název :_vnedit_original_msg en : The original title of this visual novel, leave blank if it already is in the Latin alphabet. ru : Оригинальное название данной новеллы, оставьте пустым если уже набрано в латинском алфавите. +cs : Originální název této vizuální novely, ponechte prázdné, pokud již je latinkou. :_vnedit_alias en : Aliases ru : Прочие названия +cs : Aliasy :_vnedit_alias_msg en : Comma seperated list of alternative titles or abbreviations. Can include both official @@ -3167,28 +3882,37 @@ en : Comma seperated list of alternative titles or abbreviations. Can include bo ru : Список альтернативных названий или аббревиатур, перечисленных через запятую. Может включать как официальные (японские/английские/русские) названия, так и неофициальные, имеющие хождение в сети.[br] Не следует добавлять сюда названия, указанные в выпусках! +cs : Seznam alternativních názvů nebo zkratek, oddělených čárkou. Může zahrnovat oba + (japonský/anglický) názvy a neoficiální názvy používané na internetu.[br] + Názvy, vypsané ve vydáních by se sem přidávat neměly! :_vnedit_desc en : Description ru : Описание +cs : Popis :_vnedit_desc_msg en : 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) ru : Краткое описание главной сюжетной линии. Пожалуйста, не вносите сюда спойлеры, а так же не забывайте указать источник описания, если не являетесь его автором. (коды форматирования разрешены) +cs : Krátký popis hlavního příběhu. Prosím nepište spoilery a nezapomeňte uvést zdroj, + pokud jste popis nenapsali sami. (formátovací kódy jsou povoleny) :_vnedit_length en : Length ru : Продолжительность +cs : Délka :_vnedit_links en : External links ru : Внешние ссылки +cs : Externí odkazy :_vnedit_anime en : Anime ru : Аниме +cs : Anime :_vnedit_anime_msg en : Whitespace seperated list of [url,http://anidb.net/,AniDB] anime IDs. @@ -3199,22 +3923,30 @@ ru : Список идентификаторов аниме по [url,http://ani Например, "1015 3348" добавит связь с аниме [url,http://anidb.net/a1015,Shingetsutan Tsukihime] и [url,http://anidb.net/a3348,Fate/stay night].[br] Замечание: появление названия аниме на странице новеллы может занять несколько минут. +cs : Seznam AnimeID z [url,http://anidb.net/,AniDB], oddělených mezerou. + Např. "1015 3348" přidá [url,http://anidb.net/a1015,Shingetsutan Tsukihime] + a [url,http://anidb.net/a3348,Fate/stay night] jako příbuzná anime.[br] + Poznámka: Může trvat několik minut, než se názvy anime objeví na stránce vizuální novely. :_vnedit_image en : Image ru : Изображение +cs : Obrázek :_vnedit_image_none en : No image uploaded yet ru : Изображения пока нет +cs : Obrázek ještě nebyl nahrán :_vnedit_image_processing en : ~[processing image, please return in a few minutes~] ru : ~[обработка изображения, пожалуйста подождите несколько минут~] +cs : ~[obrázek se zpracovává, vraťte se prosím za několik minut~] :_vnedit_image_upload en : Upload new image ru : Загрузить новое изображение +cs : Nahrát nový obrázek :_vnedit_image_upload_msg en : Preferably the cover of the CD/DVD/package. Image must be in JPEG or PNG format @@ -3222,68 +3954,85 @@ en : Preferably the cover of the CD/DVD/package. Image must be in JPEG or PNG fo ru : Желательно, обложка CD/DVD/коробки. Изображение должно быть в формате JPEG, либо в формате PNG, и весить не более 500 Кб. Изображения размером более 256 на 400 точек будут автоматически уменьшены. +cs : Pokud možno obálka CD/DVD/balení. Obrázek musí být ve formátu JPEG nebo PNG + a ne větší 500kB. Obrázek větší než 256x400 pixelů bude automaticky zmenšen. :_vnedit_image_nsfw en : NSFW ru : НБДР (NSFW) +cs : NSFW :_vnedit_image_nsfw_check en : Not Safe For Work ru : Не безопасно для работы +cs : Not Safe For Work :_vnedit_image_nsfw_msg en : Please check this option if the image contains nudity, gore, or is otherwise not safe in a work-friendly environment. ru : Пожалуйста, поставьте эту галочку если изображение содержит наготу, кровищу, либо тем или иным образом не безопасно для рабочего окружения. +cs : Prosíme, zaškrtněte tuto možnost, pokud obrázek obsahuje nahotu, gore nebo je jinak nevhodný pro pracovní prostředí. :_vnedit_rel en : Relations ru : Связи +cs : Vztahy :_vnedit_rel_sel en : Selected relations ru : Выбранные связи +cs : Vybrané vztahy :_vnedit_rel_add en : Add relation ru : Добавить связь +cs : Přidat vztah # <title1> is a <relation> of <title2> # this trick doesn't even work very well in English, so just an approximation is fine :_vnedit_rel_isa en : is a ru*: +cs*: :_vnedit_rel_of en : of ru*: +cs*: :_vnedit_rel_addbut en : add ru*: +cs*: :_vnedit_rel_del en : del ru*: +cs*: :_vnedit_rel_none en : No relations selected. ru*: +cs*: :_vnedit_rel_findformat en : Visual novel textbox must start with an ID (e.g. v17) ru*: +cs*: :_vnedit_rel_novn en : Visual novel not found! ru*: +cs*: :_vnedit_rel_double en : This visual novel has already been selected! ru*: +cs*: :_vnedit_scr en : Screenshots ru : Скриншоты +cs : Screenshoty :_vnedit_scrmsg en : Please keep the following in mind when uploading screenshots:[br] @@ -3298,96 +4047,123 @@ ru : Когда загружаете скриншоты, пожалуйста п - Старайтесь загружать не только одни сюжетные картинки.[br] За подробностями обращайтесь к [url,/d2#6,рекомендациям].[br] Не забудьте сохранить изменения когда закончите загружать изображения! +cs : Prosíme, pamatujte na následující věci, pokud nahráváte screenshoty:[br] + - Screenshots musí být v původním rozlišení hry,[br] + - Odstraňte všechna okna kolem a ujistěte se, že na obrázku není nic navíc,[br] + - Nenahrávejte pouze CG.[br] + Prosíme, přečtěte si [url,/d2#6,doporučení] pro více informací.[br] + Ujistěte se, že jste potvrdili odeslání informací poté, co nahrajete obrázky! :_vnedit_scr_selrel en : -- select release -- ru*: +cs*: :_vnedit_scr_frmloading en : Please wait for the screenshots to be uploaded before submitting the form. ru*: +cs*: :_vnedit_scr_frmnorel en : Please select the appropriate release for every screenshot. ru*: +cs*: :_vnedit_scr_fetching en : Fetching thumbnail... ru*: +cs*: :_vnedit_scr_uploading en : Uploading screenshot ru*: +cs*: :_vnedit_scr_upl_msg en : This can take a while, depending on the file size and your upload speed. ru*: +cs*: :_vnedit_scr_cancel en : cancel ru*: +cs*: :_vnedit_scr_full en : Enough screenshots ru*: +cs*: :_vnedit_scr_full_msg en : The limit of 10 screenshots per visual novel has been reached. If you want to add a new screenshot, please remove an existing one first. ru*: +cs*: :_vnedit_scr_add en : Add screenshot ru*: +cs*: :_vnedit_scr_imgnote en : Image must be smaller than 5MB and in PNG or JPEG format. ru*: +cs*: :_vnedit_scr_addbut en : Upload! ru*: +cs*: :_vnedit_scr_id en : Screenshot #[_1] ru*: +cs*: :_vnedit_scr_remove en : remove ru*: +cs*: :_vnedit_scr_fullsize en : Full size: [_1] ru*: +cs*: :_vnedit_scr_nsfw en : This screenshot is NSFW ru*: +cs*: :_vnedit_scr_oops en : Oops! Seems like something went wrong... Make sure the file you're uploading doesn't exceed 5MB in size. If that isn't the problem, then please report a bug. ru*: +cs*: :_vnedit_scr_errformat en : Upload failed! Only JPEG or PNG images are accepted. ru*: +cs*: :_vnedit_scr_errempty en : Upload failed! No file selected, or an empty file? ru*: +cs*: :_vnedit_scr_genthumb en : Generating thumbnail... ru*: +cs*: :_vnedit_scr_genthumb_msg en : Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. Please try again later or report a bug if that is the case. ru*: +cs*: # VN Relation graph page (/v+/rg) @@ -3395,14 +4171,17 @@ ru*: :_vnrg_title en : Relation graph for [_1] ru : Схема связей для [_1] +cs : Graf vztahů pro vizuální novelu [_1] :_vnrg_notsupp en : Not supported ru*: +cs*: :_vnrg_notsupp_msg en : Your browser sucks, it doesn't have the functionality to render our nice relation graphs. ru*: +cs*: # VN Diff viewer (/v+.+) @@ -3410,86 +4189,107 @@ ru*: :_revfield_v_title en : Title (romaji) ru : Название (ромадзи) +cs : Název (romaji) :_revfield_v_original en : Original title ru : Оригинальное название +cs : Originální název :_revfield_v_alias en : Alias ru : Прочие названия +cs : Alias :_revfield_v_desc en : Description ru : Описание +cs : Popis :_revfield_v_length en : Length ru : Продолжительность +cs : Délka :_vndiff_nolink en : ~[no link~] ru : ~[нет ссылки~] +cs : ~[žádný odkaz~] :_vndiff_none en : ~[none~] ru : ~[пусто~] +cs : ~[nic~] :_revfield_v_l_wp en : Wikipedia link ru : Ссылка Википедии +cs : Link na Wikipedii :_revfield_v_l_encubed en : Encubed tag ru : Тег Encubed'а +cs : Tag na Encubed :_revfield_v_l_renai en : Renai.us link ru : Ссылка Renai.us +cs : Odkaz na Renai.us :_revfield_v_l_vnn en : V-N.net link ru : Ссылка V-N.net +cs : Odkaz na V-N.net :_revfield_v_relations en : Relations ru : Связи +cs : Vztahy :_revfield_v_anime en : Anime ru : Аниме +cs : Anime :_revfield_v_screenshots en : Screenshots ru : Скриншоты +cs : Screenshoty :_revfield_v_image en : Image ru : Изображение +cs : Obrázek :_vndiff_image_nsfw en : (NSFW) ru : (НБДР|NSFW) +cs : (NSFW) :_vndiff_image_proc en : ~[processing~] ru : ~[обработка~] +cs : ~[zpracovává se~] :_vndiff_image_none en : No image ru : Нет изображения +cs : Obrázek není :_revfield_v_img_nsfw en : Image NSFW ru : Изображение НБДР (NSFW) +cs : Vhodnost obrázku :_vndiff_nsfw_safe en : Safe ru : Безопасно +cs : SFW :_vndiff_nsfw_notsafe en : Not safe ru : Не безопасно +cs : NSFW # VN page (/v+) @@ -3497,220 +4297,274 @@ ru : Не безопасно :_vnpage_noimg en : No image uploaded yet ru : Нет загруженного изображения +cs : Ještě nebyl nahrán žádný obrázek :_vnpage_imgproc en : ~[processing image, please return in a few minutes~] ru : ~[идёт обработка изображения, подождите несколько минут~] +cs : ~[obrázek se zpracovává, prosíme, vraťte se za několik minut~] :_vnpage_imgnsfw_msg en : This image has been flagged as Not Safe For Work. ru : Данное изображение помечено как не безопасное для работы. +cs : Tento obrázek byl označen jako "Not Safe For Work" :_vnpage_imgnsfw_show en : Show me anyway ru : Всё равно показать +cs : Ukázat i přes to :_vnpage_imgnsfw_note en : (This warning can be disabled in your account) ru : (Это предупреждение можно отключить в настройках вашей учётной записи) +cs : (Toto varování může být vypnuto ve vašem nastavení) :_vnpage_imgnsfw_foot en : Flagged as NSFW ru : Помечено как НБДР (NSFW) +cs : Označeno jako NSFW :_vnpage_vntitle en : Title ru : Название +cs : Název :_vnpage_original en : Original title ru : Оригинальное название +cs : Originální název :_vnpage_alias en : Aliases ru : Прочие названия +cs : Aliasy :_vnpage_length en : Length ru : Продолжительность +cs : Délka :_vnpage_links en : Links ru : Ссылки +cs : Odkazy :_vnpage_description en : Description ru : Описание +cs : Popis :_vnpage_tags_spoil0 en : hide spoilers ru : скрыть спойлеры +cs : skrýt spoilery :_vnpage_tags_spoil1 en : show minor spoilers ru : показать лёгкие спойлеры +cs : ukázat menší spoilery :_vnpage_tags_spoil2 en : spoil me! ru : показать все! +cs : prozraď mi vše! :_vnpage_tags_summary en : summary ru : суммарно +cs : shrnutí :_vnpage_tags_all en : all ru : все +cs : vše :_vnpage_developer en : Developer ru*: +cs*: :_vnpage_publisher en : Publishers ru*: +cs*: :_vnpage_relations en : Relations ru : Связи +cs : Vztahy :_vnpage_anime en : Related anime ru : Связанное аниме +cs : Příbuzná anime :_vnpage_anime_noinfo en : ~[no information available at this time: [url,_2,_1]~] ru : ~[к сожалению, пока никакой информации: [url,_2,_1]~] +cs : ~[nyní nejsou dostupné žádné informace: [url,_2,_1]~] :_vnpage_uopt en : User options ru : Настройки пользователя +cs : Možnosti uživatele :_vnpage_uopt_voted en : your vote: [_1] ru : ваш голос: [_1] +cs : váš hlas: [_1] :_vnpage_uopt_novote en : not voted yet ru : пока без голоса +cs : ještě nehlasováno :_vnpage_uopt_changevote en : Change vote ru : Переголосовать +cs : Změnit hlas :_vnpage_uopt_dovote en : Vote ru : Голосовать +cs : Hlasovat :_vnpage_uopt_delvote en : revoke ru : снять голос +cs : zdržet se :_vnpage_uopt_1vote en : You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played. Are you really sure this visual novel matches that description? ru*: +cs*: :_vnpage_uopt_10vote en : You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, meaning this is one of the best visual novels you've ever played and it's unlikely that any other game could ever be better than this one. It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully! ru*: +cs*: :_vnpage_uopt_wishlisted en : wishlist: [_1] ru : список желаемого: [_1] +cs : wishlist: [_1] :_vnpage_uopt_nowish en : not on your wishlist ru : не в вашем списке +cs : není na vašem wishlistu :_vnpage_uopt_changewish en : Change status ru : Сменить статус +cs : Změnit status :_vnpage_uopt_addwish en : Add to wishlist ru : Добавить к списку +cs : Přidat na wishlist :_vnpage_uopt_delwish en : remove from wishlist ru : убрать из списка +cs : odstranit z wishlistu :_vnpage_uopt_relrstat en : Release status ru*: +cs*: :_vnpage_uopt_relvstat en : Play status ru*: +cs*: :_vnpage_uopt_reldel en : Remove from VN list ru*: +cs*: :_vnpage_rel en : Releases ru : Выпуски +cs : Vydání :_vnpage_rel_none en : We don't have any information about releases of this visual novel yet... ru : У нас пока нет информации о выпусках этой новеллы... +cs : K této vizuální novele zatím nemáme informace o žádném vydání... :_vnpage_rel_add en : add release ru : добавить выпуск +cs : přidat vydání :_vnpage_rel_patch en : (patch) ru : (патч) +cs : (patch) :_vnpage_rel_extlink en : External link ru : Внешняя ссылка +cs : Externí odkaz :_vnpage_scr en : Screenshots ru : Скриншоты +cs : Screenshoty :_vnpage_scr_showing en : Showing [_1] out of [_2] [quant,_2,screenshot,screenshots]. ru : [_1] из [_2] [quant,_2,скриншота,скриншотов,скриншотов] отображено. +cs : Ukazuji screenshot [_1] z celkém [_2] [quant,_2,screenshotu,screenshotů,screenshotů]. :_vnpage_scr_nsfwhide en : show/hide NSFW ru : показать/скрыть НБДР (NSFW) +cs : skrýt/zobrazit NSFW :_vnpage_scr_num en : Screenshot #[_1] ru : Скриншот #[_1] +cs : Screenshot #[_1] :_vnpage_stats en : User stats ru : Статистика пользователей +cs : Statistiky uživatelů :_vnpage_stats_none en : Nobody has voted on this visual novel yet... ru : Никто пока не голосовал за эту новеллу... +cs : Pro tuto vizuální novelu ještě nikdo nehlasoval... :_votestats_title en : Vote stats ru : Статистика голосования +cs : Statistika hlasování :_votestats_sum en : [_1] [quant,_1,vote,votes] total, average [_2] ru : Всего [_1] [quant,_1,голос,голоса,голосов], в среднем [_2] +cs : Celkem [_1] [quant,_1,hlas,hlasy,hlasů], průměr [_2] :_votestats_recent en : Recent votes ru : Недавно проголосовали +cs : Poslední hlasy :_votestats_pop_title en : Popularity ru : Популярность +cs : Popularita :_votestats_pop_sum en : Ranked #[_1] out of [_2] with a score of [_3]. ru : Рейтинг - #[_1] из [_2], средний балл - [_3]. +cs : Hodnoceno na [_1]. místě z celkem [_2] se skóre [_3]. @@ -3727,24 +4581,29 @@ ru : Рейтинг - #[_1] из [_2], средний балл - [_3]. :_denied_title en : Access Denied ru : В доступе отказано +cs : Přístup odepřen # not logged in :_denied_needlogin_title en : You need to be logged in to perform this action. ru : Для выполнения этого действия требуется авторизация. +cs : Pro vykonání této akce se musíte přihlásit. :_denied_needlogin_msg en : Please [url,/u/login,login], or [url,/u/register,create an account] if you don't have one yet. ru : Пожалуйста [url,/u/login,авторизуйтесь], либо [url,/u/register,создайте учётную запись], если таковой у вас нет. +cs : Prosíme, [url,/u/login,přihlašte se], nebo si [url,/u/register,vytvořte účet], pokud ještě žádný nemáte. # logged in, but simply no access :_denied_noaccess_title en : You are not allowed to perform this action. ru : Вам запрещено выполнять это действие. +cs : Nemáte oprávnění provést tuto akci. :_denied_noaccess_msg en : It seems you don't have the proper rights to perform the action you wanted to perform... ru : Похоже, у вас нет прав на выполнение того, чего вы хотите... +cs : Zdá se, že nemáte potřebná práva pro vykonání akce, kterou chcete provést... # "DB Item has been deleted" page @@ -3752,12 +4611,15 @@ ru : Похоже, у вас нет прав на выполнение того, :_hiddenmsg_title en : Item deleted ru : Запись удалена +cs : Položka smazána :_hiddenmsg_msg en : This item has been deleted from the database, File a request on the [url,_1,discussion board] to undelete this page. ru : Данная запись удалена из базы данных. Пожалуйста, подайте заявку на [url,_1,форуме] для восстановления этой страницы. +cs : Tato položka byla smazána z databáze. Pro obnovení této stránky napište žádost na + [url,_1,diskusní board]. # The warning/notice messages on edit pages @@ -3765,42 +4627,53 @@ ru : Данная запись удалена из базы данных. Пож :_editmsg_copy_title en : You're not editing a release! ru : Вы не редактируете выпуск, а копируете его! +cs : Needitujete vydání! :_editmsg_copy_msg en : You're about to insert a new release into the database with information based on [_1].[br] Hit the 'edit' tab on the right-top if you intended to edit the release instead of creating a new one. ru : Вы собираетесь вставить новый выпуск, основанный на информации из [_1].[br] Щёлкните вкладку 'правка' в правом верхнем углу, если собирались редактировать выпуск, а не создавать новый. +cs : Chystáte se vložit nové vydání do databáze s informacemi založenými na vydání [_1].[br] + Pokud chcete editovat vydání místo toho, abyste vložili další vydání, přejděte na záložku 'editovat' v pravém horním rohu. :_editmsg_msg_title en : Before editing: ru : Прежде чем приступить к редактированию: +cs : Před editací: :_editmsg_msg_guidelines en : Read the [url,_1,guidelines]! ru : Прочтите [url,_1,рекомендации]! +cs : Přečtěte si [url,_1,doporučení]! :_editmsg_msg_discuss en : Check for any existing discussions on the [url,_1,discussion board] ru : Проверьте все существующие темы на [url,_1,форуме] +cs : Podívejte se do existujících diskusí na [url,_1,diskusním boardu] :_editmsg_msg_history en : Browse the [url,_1,edit history] for any recent changes related to what you want to change. ru : Просмотрите [url,_1,историю правок] на предмет недавних изменений данных, которые вы хотите изменить. +cs : Projděte [url,_1,historii editací] pro nedávné změny týkající se změn, které se chystáte provést. :_editmsg_msg_search en : [url,_1,Search the database] to see if we already have information about this [index,_2,visual novel,release,producer]. ru : [url,_1,Воспользуйтесь поиском], ведь вполне возможно что у нас уже есть информация об [index,_2,этой новелле,этом выпуске,этой компании]. +cs : [url,_1,Prohledejte databázi], zda již nemáme informaci o [index,_2,této vizuální novele,tomto vydání,tomto producentovi]. :_editmsg_revert_title en : Reverting ru : Восстановление +cs : Vracení :_editmsg_revert_msg en : You are editing an old revision of this [index,_1,visual novel,release,producer]. If you save it, all changes made after this revision will be reverted! ru : Вы правите старую редакцию страницы [index,_1,новеллы,выпуска,компании]. Если вы сохраните её, все изменения сделанные после этой правки будут утеряны! +cs : Editujete starší verzi [index,_1,této vizuální novely,tohoto vydání,tohoto producenta]. + Pokud ji uložíte, všechny změny provedené po této revizi budou vráceny! # Messages about editing on the VN/Release/Producer pages (right beneath the tabs) @@ -3808,14 +4681,17 @@ ru : Вы правите старую редакцию страницы [index,_ :_itemmsg_locked en : Locked for editing ru : Правка заблокирована +cs : Zamčeno pro editaci :_itemmsg_login en : You need to be [url,_1,logged in] to edit this page ru : Чтобы редактировать эту страницу, вы должны быть [url,_1,авторизованы] +cs : Pro editaci této stránky musíte být [url,_1,přihlášen] :_itemmsg_denied en : You are not allowed to edit this page ru : Вам запрещено редактировать эту страницу +cs : Nemáte oprávnění editovat tuto stránku # User didn't pass the spam protection @@ -3823,14 +4699,17 @@ ru : Вам запрещено редактировать эту страниц :_nospam_title en : Could not send form ru : Невозможно отправить форму +cs : Formulář nemohl být odeslán :_nospam_subtitle en : Error ru : Ошибка +cs : Chyba :_nospam_msg en : The form could not be sent, please make sure you have Javascript enabled in your browser. ru : Не удалось отправить форму, пожалуйста убедитесь что в вашем браузере включён Javascript. +cs : Formulář nemohl být odeslán, ujistěte se, že máte ve svém prohlížeči povolen Javascript. # Short message reminding the user to post in ENGLISH (Used at about every message/description input field) @@ -3838,5 +4717,6 @@ ru : Не удалось отправить форму, пожалуйста у :_inenglish en : English please! ru : Пожалуйста, пишите на английском! +cs : Prosíme, anglicky! -- cgit v1.2.3 From d0df330fc1a0e56253f6ad30cb206603622eb05e Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Mon, 19 Oct 2009 16:38:30 +0200 Subject: CSS: Widened login button Czech and Hungarian translations didn't quite fit. --- data/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/style.css b/data/style.css index 9aaceb59..bec0686a 100644 --- a/data/style.css +++ b/data/style.css @@ -295,7 +295,7 @@ b.future, b.standout, a.standout { margin-left: 15px; } #menulist input.submit { - width: 40px; + width: 70px; margin-left: 45px; } #menulist #search input.text { -- cgit v1.2.3 From e88144fa2d8fb95e35ed3f34714063b11ef9dea7 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Mon, 19 Oct 2009 17:58:27 +0200 Subject: L10N-EN: Typo fix: "seperated" -> "separated" --- data/lang.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index af58d388..4c63bcce 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -3876,7 +3876,7 @@ ru : Прочие названия cs : Aliasy :_vnedit_alias_msg -en : Comma seperated list of alternative titles or abbreviations. Can include both official +en : Comma separated list of alternative titles or abbreviations. 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! ru : Список альтернативных названий или аббревиатур, перечисленных через запятую. Может включать как @@ -3915,7 +3915,7 @@ ru : Аниме cs : Anime :_vnedit_anime_msg -en : Whitespace seperated list of [url,http://anidb.net/,AniDB] anime IDs. +en : Whitespace separated list of [url,http://anidb.net/,AniDB] anime IDs. E.g. "1015 3348" will add [url,http://anidb.net/a1015,Shingetsutan Tsukihime] and [url,http://anidb.net/a3348,Fate/stay night] as related anime.[br] Note: It can take a few minutes for the anime titles to appear on the VN page. -- cgit v1.2.3 From d4a7430b0cb058c111c0f3ca36a8cbf32104f787 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 09:20:56 +0200 Subject: L10N-HU: Added code for Hungarian TL and minor code cleanup --- ChangeLog | 2 +- lib/VNDB/L10N.pm | 35 ++++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 421cdc88..4593180a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,7 +28,7 @@ git - ? - Fixed calculation of tags_vn_bayesian.spoiler - Fixed bug with unhiding a producer entry - Set 'no spoilers' as default spoiler level for tags - - Added Czech translation + - Added Czech and Hungarian interface translation 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/lib/VNDB/L10N.pm b/lib/VNDB/L10N.pm index 279cbd31..8698cb74 100644 --- a/lib/VNDB/L10N.pm +++ b/lib/VNDB/L10N.pm @@ -11,7 +11,7 @@ use warnings; # used for the language switch interface, language tags must # be the same as in the languages hash in global.pl - sub languages { ('en', 'ru', 'cs') } + sub languages { qw{ cs en hu ru } } sub maketext { my $r = eval { shift->SUPER::maketext(@_) }; @@ -22,11 +22,10 @@ use warnings; # can be called as either a subroutine or a method sub loadfile { - my %lang = ( - en => \%VNDB::L10N::en::Lexicon, - ru => \%VNDB::L10N::ru::Lexicon, - cs => \%VNDB::L10N::cs::Lexicon, - ); + my %lang = do { + no strict 'refs'; + map +($_, \%{"VNDB::L10N::${_}::Lexicon"}), languages + }; my $r = LangFile->new(read => "$VNDB::ROOT/data/lang.txt"); my $key; while(my $l = $r->read) { @@ -45,6 +44,7 @@ use warnings; } + { package VNDB::L10N::en; use base 'VNDB::L10N'; @@ -128,14 +128,15 @@ use warnings; { - package VNDB::L10N::ru; + package VNDB::L10N::cs; use base 'VNDB::L10N::en'; our %Lexicon; sub quant { my($self, $num, $single, $couple, $lots) = @_; - return $single if ($num % 10) == 1 && ($num % 100) != 11; - return $couple if ($num % 10) >= 2 && ($num % 10) <= 4 && !(($num % 100) >= 12 && ($num % 100) <= 14); + return $lots if ($num % 100) >= 11 && ($num % 100) <= 14; + return $single if ($num % 10) == 1; + return $couple if ($num % 10) >= 2 && ($num % 10) <= 4; return $lots; } } @@ -143,19 +144,27 @@ use warnings; { - package VNDB::L10N::cs; + package VNDB::L10N::hu; + use base 'VNDB::L10N::en'; + our %Lexicon; +} + + + +{ + package VNDB::L10N::ru; use base 'VNDB::L10N::en'; our %Lexicon; sub quant { my($self, $num, $single, $couple, $lots) = @_; - return $lots if ($num % 100) >= 11 && ($num % 100) <= 14; - return $single if ($num % 10) == 1; - return $couple if ($num % 10) >= 2 && ($num % 10) <= 4; + return $single if ($num % 10) == 1 && ($num % 100) != 11; + return $couple if ($num % 10) >= 2 && ($num % 10) <= 4 && !(($num % 100) >= 12 && ($num % 100) <= 14); return $lots; } } + 1; -- cgit v1.2.3 From a739a8112bc4be854bcd3c19aafce828491e3ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bikfalvi=20M=C3=A1t=C3=A9?= <bikmate@gmail.com> Date: Wed, 21 Oct 2009 10:08:52 +0200 Subject: L10N-HU: Added Hungarian interface translation --- data/lang.txt | 881 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 880 insertions(+), 1 deletion(-) diff --git a/data/lang.txt b/data/lang.txt index 4c63bcce..a6ce7082 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -110,36 +110,43 @@ ends with ']'. The following options are supported: en : [_1] [quant,_1,year,years] ago ru : [_1] [quant,_1,год,года,лет] назад cs*: +hu*: :_age_months en : [_1] [quant,_1,month,months] ago ru : [_1] [quant,_1,месяц,месяца,месяцев] назад cs*: +hu*: :_age_weeks en : [_1] [quant,_1,week,weeks] ago ru : [_1] [quant,_1,неделя,недели,недель] назад cs*: +hu*: :_age_days en : [_1] [quant,_1,day,days] ago ru : [_1] [quant,_1,день,дня,дней] назад cs*: +hu*: :_age_hours en : [_1] [quant,_1,hour,hours] ago ru : [_1] [quant,_1,час,часа,часов] назад cs*: +hu*: :_age_min en : [_1] min ago ru : [_1] [quant,_1,минута,минуты,минут] назад cs*: +hu*: :_age_sec en : [_1] sec ago ru : [_1] [quant,_1,секунда,секунды,секунд] назад cs*: +hu*: # user ranks @@ -148,31 +155,37 @@ cs*: en : visitor ru : посетитель cs : návštěvník +hu : vendég :_urank_1 en : banned ru : забанен cs : zabanovaný +hu : kicsapva :_urank_2 en : loser ru : лузер cs : loser +hu : vesztes :_urank_3 en : user ru : пользователь cs : uživatel +hu : felhasználó :_urank_4 en : mod ru : модератор cs : moderátor +hu : mod :_urank_5 en : admin ru : администратор cs : administrátor +hu : admin # languages @@ -181,101 +194,121 @@ cs : administrátor en : Czech ru : Чешский cs : Česky +hu : Cseh :_lang_da en : Danish ru : Датский cs : Dánsky +hu : Dán :_lang_de en : German ru : Немецкий cs : Německy +hu : Német :_lang_en en : English ru : Английский cs : Anglicky +hu : Angol :_lang_es en : Spanish ru : Испанский cs : Španělsky +hu : Spanyol :_lang_fi en : Finnish ru : Финский cs : Finsky +hu : Finn :_lang_fr en : French ru : Французский cs : Francouzsky +hu : Francia :_lang_hu en : Hungarian ru*: cs*: +hu*: :_lang_it en : Italian ru : Итальянский cs : Italsky +hu : Olasz :_lang_ja en : Japanese ru : Японский cs : Japonsky +hu : Japán :_lang_ko en : Korean ru : Корейский cs : Korejsky +hu : Koreai :_lang_nl en : Dutch ru : Голландский cs : Nizozemsky +hu : Holland :_lang_no en : Norwegian ru : Норвежский cs : Norsky +hu : Norvég :_lang_pl en : Polish ru : Польский cs : Polsky +hu : Lengyel :_lang_pt en : Portuguese ru : Португальский cs : Portugalsky +hu : Portugál :_lang_ru en : Russian ru : Русский cs : Rusky +hu : Orosz :_lang_sv en : Swedish ru : Шведский cs : Švédsky +hu : Svéd :_lang_tr en : Turkish ru : Турецкий cs : Turecky +hu : Török :_lang_vi en : Vietnamese ru : Вьетнамский cs : Vietnamsky +hu : Vietnámi :_lang_zh en : Chinese ru : Китайский cs : Čínsky +hu : Kínai # platforms @@ -286,101 +319,121 @@ cs : Čínsky en : Windows ru : Windows cs : Windows +hu : :_plat_dos en : DOS ru : DOS cs : DOS +hu : :_plat_lin en : Linux ru : Linux cs : Linux +hu : :_plat_mac en : Mac OS ru : Mac OS cs : Mac OS +hu : :_plat_dvd en : DVD Player ru : DVD Плеер cs : DVD Přehrávač +hu : DVD Lejátszó :_plat_gba en : Game Boy Advance ru : Game Boy Advance cs : Game Boy Advance +hu : :_plat_msx en : MSX ru : MSX cs : MSX +hu : :_plat_nds en : Nintendo DS ru : Nintendo DS cs : Nintendo DS +hu : :_plat_nes en : Famicom ru : Famicom (Dendy) cs : Famicom +hu : :_plat_p98 en : PC-98 ru : PC-98 cs : PC-98 +hu : :_plat_psp en : Playstation Portable ru : Playstation Portable cs : Playstation Portable +hu : :_plat_ps1 en : Playstation 1 ru : Playstation 1 cs : Playstation 1 +hu : :_plat_ps2 en : Playstation 2 ru : Playstation 2 cs : Playstation 2 +hu : :_plat_ps3 en : Playstation 3 ru : Playstation 3 cs : Playstation 3 +hu : :_plat_drc en : Dreamcast ru : Dreamcast cs : Dreamcast +hu : :_plat_sat en : Sega Saturn ru : Sega Saturn cs : Sega Saturn +hu : :_plat_sfc en : Super Nintendo ru : Super Nintendo cs : Super Nintendo +hu : :_plat_wii en : Nintendo Wii ru : Nintendo Wii cs : Nintendo Wii +hu : :_plat_xb3 en : Xbox 360 ru : Xbox 360 cs : Xbox 360 +hu : :_plat_oth en : Other ru : Другая cs : Ostatní +hu : Egyéb # Release media @@ -389,56 +442,67 @@ cs : Ostatní en : [quant,_1,CD,CDs] ru*: cs*: +hu*: :_med_dvd en : [quant,_1,DVD,DVDs] ru*: cs*: +hu*: :_med_gdr en : [quant,_1,GD-ROM,GD-ROMs] ru*: cs*: +hu*: :_med_blr en : [quant,_1,Blu-ray disc,Blu-ray discs] ru*: cs*: +hu*: :_med_flp en : [quant,_1,Floppy,Floppies] ru*: cs*: +hu*: :_med_mrt en : [quant,_1,Cartridge,Cartridges] ru*: cs*: +hu*: :_med_mem en : [quant,_1,Memory card,Memory cards] ru*: cs*: +hu*: :_med_umd en : [quant,_1,UMD,UMDs] ru*: cs*: +hu*: :_med_nod en : Nintendo Optical [quant,_1,Disk,Disks] ru*: cs*: +hu*: :_med_in en : Internet download ru*: cs*: +hu*: :_med_otc en : Other ru*: cs*: +hu*: # VN relations @@ -447,51 +511,61 @@ cs*: en : Sequel ru*: cs*: +hu*: :_vnrel_preq en : Prequel ru*: cs*: +hu*: :_vnrel_set en : Same setting ru*: cs*: +hu*: :_vnrel_alt en : Alternative version ru*: cs*: +hu*: :_vnrel_char en : Shares characters ru*: cs*: +hu*: :_vnrel_side en : Side story ru*: cs*: +hu*: :_vnrel_par en : Parent story ru*: cs*: +hu*: :_vnrel_ser en : Same series ru*: cs*: +hu*: :_vnrel_fan en : Fandisc ru*: cs*: +hu*: :_vnrel_orig en : Original game ru*: cs*: +hu*: # producer types @@ -500,16 +574,19 @@ cs*: en : Company ru : Компания cs : Společnost +hu : Cég :_ptype_in en : Individual ru : Частное лицо cs : Jednotlivec +hu : Magánszemély :_ptype_ng en : Amateur group ru : Любительская группа cs : Amatérská skupina +hu : Amatör csoport # release types @@ -518,16 +595,19 @@ cs : Amatérská skupina en : Complete ru : Полный cs : Kompletní +hu : Teljes :_rtype_partial en : Partial ru : Частичный cs : Částečné +hu : Részleges :_rtype_trial en : Trial ru : Триальный cs : Trial +hu : Próba # Anime types @@ -536,36 +616,43 @@ cs : Trial en : TV Series ru*: cs*: +hu*: :_animetype_ova en : OVA ru*: cs*: +hu*: :_animetype_mov en : Movie ru*: cs*: +hu*: :_animetype_oth en : Other ru*: cs*: +hu*: :_animetype_web en : Web ru*: cs*: +hu*: :_animetype_spe en : TV Special ru*: cs*: +hu*: :_animetype_mv en : Music Video ru*: cs*: +hu*: # Discussion board types @@ -574,26 +661,31 @@ cs*: en : Announcements ru : Объявления cs : Oznámení +hu : Hirdetések :_dboard_db en : VNDB Discussions ru : Форум VNDB cs : Diskuse o VNDB +hu : VNDB Eszmecsere :_dboard_v en : Visual novels ru : Новеллы cs : Vizuální novely +hu : Visual novellek :_dboard_p en : Producers ru : Компании cs : Producenti +hu : Készítők :_dboard_u en : Users ru : Пользователи cs : Uživatelé +hu : Felhasználók # Wishlist statuses @@ -602,21 +694,25 @@ cs : Uživatelé en : high ru : высокий cs : vysoká +hu : magas :_wish_1 en : medium ru : средний cs : střední +hu : közepes :_wish_2 en : low ru : низкий cs : nízká +hu : alacsony :_wish_3 en : blacklist ru : в чёрном списке cs : blacklist +hu : fekete lista # 'Voiced' information for releases @@ -625,26 +721,31 @@ cs : blacklist en : Unknown ru : Неизвестно cs : Není známo +hu : Ismeretlen :_voiced_1 en : Not voiced ru : Нет озвучки cs : Bez hlasu +hu : Néma :_voiced_2 en : Only ero scenes voiced ru : Озвучены лишь эросцены cs : S hlasem pouze v ero scénách +hu : Csak ero jelenetek szinkronossak :_voiced_3 en : Partially voiced ru : Частичная озвучка cs : Částečně s hlasem +hu : Részlegesen szinkronos :_voiced_4 en : Fully voiced ru : Озвучено целиком cs : Plně s hlasem +hu : Szinkronizált # 'Animated' information for releases @@ -653,26 +754,31 @@ cs : Plně s hlasem en : Unknown ru : Неизвестно cs : Není známo +hu : Ismeretlen :_animated_1 en : No animations ru : Без анимации cs : Bez animací +hu : Nem animált :_animated_2 en : Simple animations ru : Простая анимация cs : Jednoduché animace +hu : Egyszerű animációk :_animated_3 en : Some fully animated scenes ru : Некоторые сцены анимированы целиком cs : Některé plně animované scény +hu : Pár teljesen animált jelenet :_animated_4 en : All scenes fully animated ru : Все сцены полностью анимированы cs : Všechny scény plně animovány +hu : Minden jelenet animált # Rating indications @@ -681,51 +787,61 @@ cs : Všechny scény plně animovány en : worst ever ru : хуже некуда cs : absolutně nejhorší +hu : iszonyú :_vote_2 en : awful ru : ужасно cs : hrozná +hu : szörnyű :_vote_3 en : bad ru : плохо cs : špatná +hu : rossz :_vote_4 en : weak ru : слабо cs : slabá +hu : gyenge :_vote_5 en : so-so ru : так себе cs : taktak +hu : elmegy :_vote_6 en : decent ru : неплохо cs : slušná +hu : átlagos :_vote_7 en : good ru : хорошо cs : dobrá +hu : jó :_vote_8 en : very good ru : здорово cs : velmi dobrá +hu : nagyon jó :_vote_9 en : excellent ru : отлично cs : skvělá +hu : nagyszerű :_vote_10 en : masterpiece ru : шедевр cs : mistrovský kus +hu : mestermű # VN lengths @@ -734,31 +850,37 @@ cs : mistrovský kus en : Unknown ru : Неизвестно cs : Není známo +hu : Ismeretlen :_vnlength_1 en : Very short[index,_1,, (< 2 hours), (OMGWTHOTL~, A Dream of Summer)] ru : Очень короткая[index,_1,, (< 2 часов), (OMGWTFOTL~, A Dream Of Summer)] cs : Velmi krátká[index,_1,, (< 2 hours), (OMGWTHOTL~, A Dream of Summer)] +hu : Nagyon rövid[index,_1,, (< 2 óra), (OMGWTHOTL~, A Dream of Summer)] :_vnlength_2 en : Short[index,_1,, (2 - 10 hours), (Narcissu~, Planetarian)] ru : Короткая[index,_1,, (2 - 10 часов), (Narcissu~, Planetarian)] cs : Krátká[index,_1,, (2 - 10 hours), (Narcissu~, Planetarian)] +hu : Rövid[index,_1,, (2 - 10 óra), (Narcissu~, Planetarian)] :_vnlength_3 en : Medium[index,_1,, (10 - 30 hours), (Kana: Little Sister)] ru : Средняя[index,_1,, (10 - 30 часов), (Kana: Little Sister)] cs : Střední[index,_1,, (10 - 30 hours), (Kana: Little Sister)] +hu : Közepes[index,_1,, (10 - 30 óra), (Kana: Little Sister)] :_vnlength_4 en : Long[index,_1,, (30 - 50 hours), (Tsukihime)] ru : Длинная[index,_1,, (30 - 50 часов), (Tsukihime)] cs : Dlouhá[index,_1,, (30 - 50 hours), (Tsukihime)] +hu : Hosszú[index,_1,, (30 - 50 óra), (Tsukihime)] :_vnlength_5 en : Very long[index,_1,, (> 50 hours), (Clannad)] ru : Очень длинная[index,_1,, (> 50 часов), (Clannad)] cs : Velmi dlouhá[index,_1,, (> 50 hours), (Clannad)] +hu : Nagyon hosszú[index,_1,, (> 50 óra), (Clannad)] # VN list statuses @@ -767,51 +889,61 @@ cs : Velmi dlouhá[index,_1,, (> 50 hours), (Clannad)] en : Unknown ru*: cs*: +hu*: :_rlst_rstat_1 en : Pending ru*: cs*: +hu*: :_rlst_rstat_2 en : Obtained ru*: cs*: +hu*: :_rlst_rstat_3 en : On loan ru*: cs*: +hu*: :_rlst_rstat_4 en : Deleted ru*: cs*: +hu*: :_rlst_vstat_0 en : Unknown ru*: cs*: +hu*: :_rlst_vstat_1 en : Playing ru*: cs*: +hu*: :_rlst_vstat_2 en : Finished ru*: cs*: +hu*: :_rlst_vstat_3 en : Stalled ru*: cs*: +hu*: :_rlst_vstat_4 en : Dropped ru*: cs*: +hu*: # Form messages @@ -820,131 +952,157 @@ cs*: en : Invalid username or password ru : Некорректное имя пользователя или пароль cs : Neplatné uživatelské jméno nebo heslo +hu : Hibás felhasználónév vagy jelszó :_formerr_e_nomail en : No user found with that email address ru : Пользователя с такой электронной почтой не существует cs : Uživatel s touto e-mailovou adresou nebyl nalezen +hu : Nem található felhasználó ezzel az email címmel :_formerr_e_passmatch en : Passwords do not match ru : Пароли не совпадают cs : Hesla nejsou stejná +hu : A jelszavak nem egyeznek meg :_formerr_e_usrexists en : Someone already has this username, please choose something else ru : Кто-то уже зарегистрировал такой ник, пожалуйста выберите другой cs : Toto uživatelské jméno už je v užívání, vyberte prosím jiné +hu : Már foglalt ez a felhasználónév, kérlek válassz másikat :_formerr_e_mailexists en : Someone already registered with that email address ru : Кто-то уже регистрировался с таким адресом электронной почты cs : Tuto e-mailovou adresu již někdo k registraci použil +hu : Valaki már regisztrált ezzel az email címmel :_formerr_e_noimage en : Image must be in JPEG or PNG format ru : Изображение должно быть в формате JPEG, либо в формате PNG cs : Obrázek musí být v JPEG nebo PNG formátu +hu : A kép múszáj JPEG vagy PNG formátúmba legyen :_formerr_e_toolarge en : Image is too large, only 500kB allowed ru : Изображение слишком большое, 500 кб - максимально допустимый предел cs : Obrázek je moc velký, je povoleno pouze 500kB +hu : A kép túl nagy, 500kb a megengedett :_formerr_e_oneaday en : You can only register one account from the same IP within 24 hours ru : Вы можете зарегистрировать учётную запись с одного и того же IP лишь по прошествии 24 часов cs : V rámci 24 hodin si lze z jedné IP adresy zaregistrovat pouze jeden účet +hu : 24 óra alatt csak egy fiókot hozzhatsz létre úgyanazzal az IP-vel :_formerr_e_nochanges en : No changes, please don't create an entry that is fully identical to another ru : Изменения отсутствуют, пожалуйста не создавайте идентичных копий записей cs : Nenalezeny změny, netvořte prosím záznam, který je plně totožný s jiným +hu : Nem történt változtatás, kérlek ne készíts egy bejegyzést ami teljesen megegyezzik egy másikkal :_formerr_e_doublepost en : Please wait 30 seconds before making another post ru : Прежде чем публиковать очередное сообщение, пожалуйста подождите 30 секунд cs : Před posláním dalšího příspěvku počkejte prosím 30 sekund +hu : Kérlek várj 30 másodpercet mielőtt új hozzászólást küldesz :_formerr_title en : Error ru : Ошибка cs : Chyba +hu : Hiba :_formerr_subtitle en : Form could not be sent: ru : Невозможно отправить форму: cs : Dokument nemohl být odeslán: +hu : Az űrlappot nem sikerült elküldeni: :_formerr_required en : [_1] is a required field! ru : [_1] - обязательное поле! cs : [_1] je pole, které musí být vyplněno! +hu : [_1] kitöltésse kötelező! :_formerr_minlength en : [_1]: should have at least [_2] characters ru : [_1]: [quant,_2,необходим,необходимы,необходимо] хотя бы [_2] [quant,_2,символ,символа,символов] cs : [_1]: musí mít minimálně [_2] znaků +hu : [_1]: legalább [_2] karaktert kell tartalmazzon :_formerr_maxlength en : [_1]: only [_2] characters allowed ru : [_1]: [quant,_2,разрешён,разрешены,разрешено] лишь [_2] [quant,_2,символ,символа,символов] cs : [_1]: je povoleno maximálně [_2] znaků +hu : [_1]: csakis [_2] karakterek megengedetek :_formerr_enum en : [_1] must be one of the following: [_2] ru : Поле '[_1]' должно равняться одному из следующих значений: [_2] cs : [_1] musí být z následujícího seznamu: [_2] +hu : [_1] muszáj az alábbiak közül valamelyik legyen: [_2] :_formerr_wrongboard en : Wrong board: [_1] ru : Некорректная ветка: [_1] cs : Špatný board: [_1] +hu : Rossz alfórum: [_1] :_formerr_tagexists en : Tag [url,_1,_2] already exists! ru : Тег [url,_1,_2] уже существует! cs : Tag [url,_1,_2] již existuje! +hu : A(z) [url,_1,_2] cimke már létezik! :_formerr_tpl_mail en : Invalid email address ru : Некорректный адрес электронной почты cs : Neplatná e-mailová adresa +hu : Érvénytelen email cím :_formerr_tpl_url en : [_1]: Invalid URL ru : [_1]: Некорректная ссылка cs : [_1]: Neplatná URL +hu : [_1]: Érvénytelen hivatkozás :_formerr_tpl_asciiprint en : [_1] may only contain ASCII characters ru : Поле '[_1]' может содержать лишь символы диапазона ASCII cs : [_1] smí obsahovat pouze znaky ASCII +hu : [_1] kizárólag ASCII karaktereket tartalmazhat :_formerr_tpl_int en : [_1]: Not a valid number ru : [_1]: Не является правильным числом cs : [_1]: Neplatné číslo +hu : [_1]: Nem egy érvényes szám :_formerr_tpl_pname en : [_1] can only contain lowercase alphanumeric characters and a hyphen, and must start with a character ru : Поле '[_1]' может содержать лишь символы буквенно-цифрового диапазона в нижнем регистре и чёрточку, а так же начинаться с буквы cs : [_1] smí obsahovat pouze malá písmena, čísla a pomlčku, a musí začínat písmenem +hu : [_1] egy karakterrel kell kezdődjön és csak kisbetűs alfanumerikus karaktereket és egy kötőjelet tartalmazhat :_form_tab_all en : All items ru : Все поля cs : Všechny položky +hu : Minden :_form_editsum en : Edit summary ru : Суммарно о правке cs : Shrnutí editace +hu : Összegzés :_form_submit en : Submit ru : Отправить cs : Potvrdit +hu : Beküldés # Common javascript strings @@ -953,61 +1111,73 @@ cs : Potvrdit en : expand ru*: cs*: +hu*: :_js_collapse en : collapse ru*: cs*: +hu*: :_js_loading en : Loading... ru*: cs*: +hu*: :_js_date_year en : -year- ru*: cs*: +hu*: :_js_date_month en : -month- ru*: cs*: +hu*: :_js_date_day en : -day- ru*: cs*: +hu*: :_js_ds_noresults en : No results... ru*: cs*: +hu*: :_js_iv_close en : close ru*: cs*: +hu*: :_js_iv_prev en : previous ru*: cs*: +hu*: :_js_iv_next en : next ru*: cs*: +hu*: :_js_ds_tag_meta en : meta ru*: cs*: +hu*: :_js_ds_tag_mod en : awaiting moderation ru*: cs*: +hu*: @@ -1025,6 +1195,7 @@ cs*: en : The Visual Novel Database ru : The Visual Novel Database cs : Databáze Vizuálních Novel +hu : A Visual Novel Adatbázis # the 'ALL' in "ALL A B C D .. #" @@ -1032,6 +1203,7 @@ cs : Databáze Vizuálních Novel en : ALL ru : ВСЕ cs : VŠE +hu : Minden # Main menu @@ -1040,66 +1212,79 @@ cs : VŠE en : Menu ru : Меню cs : Menu +hu : Menü :_menu_home en : Home ru : Главная cs : Home +hu : Kezdőlap :_menu_vn en : Visual novels ru : Новеллы cs : Vizuální novely +hu : Visual novellek :_menu_releases en : Releases ru : Выпуски cs : Vydání +hu : Kiadások :_menu_producers en : Producers ru : Компании cs : Producenti +hu : Készítők :_menu_tags en : Tags ru : Теги cs : Tagy +hu : Cimkék :_menu_users en : Users ru : Пользователи cs : Uživatelé +hu : Felhasználók :_menu_recent_changes en : Recent changes ru : Свежие правки cs : Poslední změny +hu : Legútóbbi változtatások :_menu_discussion_board en : Discussion board ru : Форум cs : Diskusní board +hu : Fórum :_menu_faq en : FAQ ru : ЧаВо cs : FAQ +hu : GYIK :_menu_randvn en : Random visual novel ru : Случайная новелла cs : Náhodná vizuální novela +hu : Véletlenszerű novel :_menu_webchat en : webchat ru : Веб-чат cs : webchat +hu : :_menu_emptysearch en : search ru : поиск cs : hledat +hu : kereső # User menu @@ -1108,53 +1293,63 @@ cs : hledat en : My Profile ru : Мой профиль cs : Můj profil +hu : Profilom :_menu_myvnlist en : My Visual Novel List ru : Мой список новелл cs : Můj list vizuálních novel +hu : Visual Novel listám :_menu_mywishlist en : My Wishlist ru : Мой список желаемого cs : Můj wishlist +hu : Kivánságlistám # [_1] = number of messages :_menu_mymessages en : My Messages ([_1]) ru : Мои сообщения cs : Mé zprávy ([_1]) +hu : Üzenenteim ([_1]) :_menu_mychanges en : My Recent Changes ru : Мои недавние правки cs : Mé poslední změny +hu : Legútóbbi változtatásaim :_menu_mytags en : My Tags ru : Мои теги cs : Moje tagy +hu : Cimkéim :_menu_addvn en : Add Visual Novel ru : Добавить новеллу cs : Přidat vizuální novelu +hu : Visual Novel hozzáadássa :_menu_addproducer en : Add Producer ru : Добавить компанию cs : Přidat producenta +hu : Készítő hozzáadássa :_menu_logout en : Logout ru : Выйти cs : Odhlásit +hu : Kijelentkezés # used for both the box title and submit button :_menu_login en : Login ru : Вход cs : Přihlášení +hu : Bejelentkezés :_menu_loginmsg en : Need to [url,_1,register],[br] @@ -1163,6 +1358,8 @@ ru : Нужна [url,_1,регистрация],[br] или [url,_2,забыли свой пароль]? cs : Potřebujete se [url,_1,přihlásit],[br] nebo jste [url,_2,zapomněli heslo]? +hu : Ha még nem [url,_1,regisztráltál], akkor most megteheted,[br] + vagy netán [url,_2,elfelejtetted a jelszavad]? # database statistics @@ -1170,36 +1367,43 @@ cs : Potřebujete se [url,_1,přihlásit],[br] en : Database Statistics ru : Статистика базы данных cs : Statistiky databáze +hu : Adatbázis Statisztikák :_menu_stat_vn en : Visual Novels ru : Новелл cs : Vizuální novely +hu : Visual Novellek :_menu_stat_releases en : Releases ru : Выпусков cs : Vydání +hu : Kiadások :_menu_stat_producers en : Producers ru : Компаний cs : Producenti +hu : Készítők :_menu_stat_users en : Users ru : Пользователей cs : Uživatelé +hu : Felhasználók :_menu_stat_threads en : Threads ru : Тем cs : Thready +hu : Témák :_menu_stat_posts en : Posts ru : Сообщений cs : Příspevky +hu : Hozzászólások # Footer @@ -1208,11 +1412,13 @@ cs : Příspevky en : abous us ru : о нас cs : o nás +hu : rólunk :_footer_source en : source ru : исходный код cs : zdroj +hu : forráskód # Main tabs (those on the right top of the highest box) @@ -1221,84 +1427,99 @@ cs : zdroj en : history ru : история cs : historie +hu : előzmények :_mtabs_discuss en : discussions ([_1]) ru : обсуждения ([_1]) cs : diskuse ([_1]) +hu : beszélgetések ([_1]) # the following 4 tabs are only present on user pages :_mtabs_posts en : posts ru : сообщения cs : příspevky +hu : hozzászólások :_mtabs_wishlist en : wishlist ru : список желаемого cs : wishlist +hu : kivánságlista :_mtabs_list en : list ru : список cs : seznam +hu : lista :_mtabs_tags en : tags ru : теги cs : tagy +hu : cimkék # modify tags on VN pages :_mtabs_tagmod en : modify tags ru : править теги cs : změnit tagy +hu : cimkék módosítása # copy a release :_mtabs_copy en : copy ru : копировать cs : kopírovat +hu : másolás # following line is also used on revision pages (it's the same action, anyway) :_mtabs_edit en : edit ru : правка cs : upravit +hu : szerkesztés # hide/unhide a DB item :_mtabs_hide en : hide ru : скрыть cs : skrýt +hu : elrejtés :_mtabs_unhide en : unhide ru : показать cs : odkrýt +hu : megjelenítés # lock/unlock for editing :_mtabs_lock en : lock ru : заблокировать cs : zamknout +hu : bezárás :_mtabs_unlock en : unlock ru : снять блокировку cs : odemknout +hu : kinyitás # delete :_mtabs_del en : del ru : удалить cs : smazat +hu : törlés # VN relations :_mtabs_relations en : relations ru : связи cs : vztahy +hu : kapcsolatok # Navigation buttons on the browse pages @@ -1307,11 +1528,13 @@ cs : vztahy en : previous ru : назад cs : předchozí +hu : előző :_browse_next en : next ru : далее cs : další +hu : következő # Revision pages @@ -1320,37 +1543,44 @@ cs : další en : earlier revision ru : более ранняя редакция cs : dřívější revize +hu : korábbi javítás :_revision_next en : later revision ru : более поздняя редакция cs : pozdější revize +hu : későbbi javítás :_revision_title en : Revision [_1] ru : Редакция [_1] cs : Revize [_1] +hu : Javítás - #[_1] # it's the summary of the edit, "edit" is not a verb here. :_revision_new_summary en : Edit summary ru : Суммарно cs : Shrnutí editace +hu : Szerkesztés összefoglalása :_revision_edit_summary en : Edit summary of revision [_1]: ru : Суммарно о редакции [_1]: cs : Shrnutí editace revize[_1]: +hu : [_1] javítás szerkesztésének az összefoglalása :_revision_user_date en : By [userstr,_1] on [date,_2,full] ru : [userstr,_1], [date,_2,full] cs : Změnil [userstr,_1] [date,_2,full] +hu : [userstr,_1] által, [date,_2,full] :_revision_emptyfield en : ~[empty~] ru : ~[пусто~] cs : ~[prázdná~] +hu : ~[üres~] # tabs above the search boxes @@ -1359,32 +1589,38 @@ cs : ~[prázdná~] en : Visual novels ru : Новеллы cs : Vizuální novely +hu : Visual novellek :_searchbox_releases en : Releases ru : Выпуски cs : Vydání +hu : Kiadások :_searchbox_producers en : Producers ru : Компании cs : Producenti +hu : Keszítők :_searchbox_tags en : Tags ru : Теги cs : Tagy +hu : Cimkék :_searchbox_users en : Users ru : Пользователи cs : Uživatelé +hu : Felhasználok # text on the search button :_searchbox_submit en : Search! ru : Искать! cs : Hledat! +hu : Keress! @@ -1420,47 +1656,62 @@ cs : VNDB.org se snaží být srozumitelnou databází informací o vizuálních a mohou hodnotit všechny vizuální novely.[br][br] Můžete jen tak [url,/v/all,brouzdat kolem], [url,/u/register,zaregistrovat si účet] nebo se účastnit diskusí o vizuálních novelách nebo VNDB na našem [url,/t,diskusním boardu]. +hu : A VNDB.org arra törekszik, hogy egy átfogó és információdús adatbázist hozzon létre visual novellekről.[br] + Ez az oldal úgy van felépítve mint egy wiki, s annak érdekében, hogy ez legyen a legnagyobb, legpontosabb + és napra kész visual novel adatbázis a weben, mindenki szabadon hozzájárulhat a tartalom bővítéséhez.[br] + Regisztrált felhasználók úgyanakkor listát vezethetnek azokról a játékokról amelyeket már játszottak,játszanak + vagy épp játszani szeretnének, valamint szavazhatnak is az oldalon tálalható bármely novelre.[br][br] + Bátran, [url,/v/all,nézz körül], [url,/u/register,regisztrálj az oldalra] vagy vegyél részt a visual + novellek és a VNDB-ről szóló eszmecserékbe a [url,/t,fórumon]. :_home_recentchanges en : Recent Changes ru : Свежие правки cs : Poslední změny +hu : Legútóbbi változtatások :_home_recentchanges_item en : [_1]:[_2] by [userstr,_3] ru : [_1]:[_2], [userstr,_3] cs : [_1]:[_2], [userstr,_3] +hu : [_1]:[_2] - [userstr,_3] által :_home_announcements en : Announcements ru : Объявления cs : Oznámení +hu : Hirdetések :_home_recentposts en : Recent Posts ru : Недавние сообщения cs : Poslední příspěvky +hu : Legfrissebb hozzászólások :_home_recentposts_item en : [age,_1] [_2] by [userstr,_3] ru : [age,_1] [_2], [userstr,_3] cs : [age,_1] [_2], [userstr,_3] +hu : [age,_1] [_2] - [userstr,_3] által :_home_randomvn -en : Random vsual novels +en : Random visual novels ru : Случайные новеллы cs : Náhodné vizuální novely +hu : Véletlenszerű visual novel :_home_upcoming en : Upcoming releases ru : Грядущие выпуски cs : Nadcházející vydání +hu : Hamarosan megjelenő kiadások :_home_justreleased en : Just released ru : Только что вышли cs : Právě vydáno +hu : Épp most jelentek meg @@ -1475,11 +1726,13 @@ cs : Právě vydáno en : Recent changes ru : Свежие правки cs : Poslední změny +hu : Legútóbbi változtatások :_hist_title_item en : Edit history of [_1] ru : История изменений [_1] cs : Editovat historii [_1] +hu : [_1] előzményeinek szerkesztése # the filter buttons @@ -1488,66 +1741,79 @@ cs : Editovat historii [_1] en : Show automated edits ru : Показать автоматические правки cs : Ukázat automatické editace +hu : Autómata szerkesztések megjelenítése :_hist_filter_hideauto en : Hide automated edits ru : Скрыть автоматические правки cs : Skrýt automatické editace +hu : Autómata szerkesztések elrejtése :_hist_filter_hidedel en : Hide deleted items ru : Скрыть удалённые страницы cs : Skrýt smazané položky +hu : Törölt elemek elrejtése :_hist_filter_showdel en : Show deleted items ru : Показать удалённые страницы cs : Ukázat smazané položky +hu : Törölt elemek megjelenítése :_hist_filter_alltypes en : Show all items ru : Показать все страницы cs : Ukázat všechny položky +hu : Minden elem megjelenítése :_hist_filter_onlyvn en : Only visual novels ru : Только новеллы cs : Pouze vizuální novely +hu : Csak visual novellek :_hist_filter_onlyreleases en : Only releases ru : Только выпуски cs : Pouze vydání +hu : Csak kiadások :_hist_filter_onlyproducers en : Only producers ru : Только компании cs : Pouze producenti +hu : Csak készítők :_hist_filter_allactions en : Show all changes ru : Показать все изменения cs : Ukázat všechny změny +hu : Minden változtatás megjelenitése :_hist_filter_onlyedits en : Only edits ru : Только правки cs : Pouze editace +hu : Csak a szerkesztések :_hist_filter_onlynew en : Only newly created pages ru : Только новые страницы cs : Pouze nově stvořené stránky +hu : Csak újjonan létrehozott oldalakat :_hist_filter_exrel en : Exclude edits of releases ru : Исключить правки выпусков cs : Výjmout editace vydání +hu : Ezen kiadások szerkesztésének a kihagyása :_hist_filter_increl en : Include edits of releases ru : Включить правки выпусков cs : Zahrnout editace vydání +hu : Ezen kiadások szerkesztésének a mellékelése # column headers @@ -1557,21 +1823,25 @@ cs : Zahrnout editace vydání en : Rev. ru : Ревизия cs : Rev. +hu : Javitás :_hist_col_date en : Date ru : Дата cs : Datum +hu : Dátúm :_hist_col_user en : User ru : Пользователь cs : Uživatel +hu : Felhasználó :_hist_col_page en : Page ru : Страница cs : Stránka +hu : Oldal @@ -1588,56 +1858,67 @@ cs : Stránka en : Posted in ru : В теме cs : Přispěno v +hu : Válaszolva :_thread_byuser en : by [userstr,_1] ru : [userstr,_1] cs : , [userstr,_1] +hu : - [userstr,_1] :_thread_editpost en : edit ru : правка cs : editovat +hu : szerkesztés :_thread_deletedpost en : Post deleted. ru : Сообщение удалено. cs : Příspěvek smazán. +hu : Hozzászólás törölve. :_thread_lastmodified en : Last modified on [date,_1,full] ru : Последний раз редактировалось [date,_1,full] cs : Naposledy změněno [date,_1,full] +hu : Utolsó szerkesztés [date,_1,full] :_thread_noreply_title en : Reply ru : Ответить cs : Odpovědět +hu : Válasz :_thread_noreply_locked en : This thread has been locked, you can't reply to it anymore ru : Данная тема заблокирована, вы больше не можете в неё ответить cs : Tento thread byl zamčen, již se do něj nedá odpovědět +hu : A téma le van zárva, nem lehet rá válaszolni :_thread_noreply_login en : You must be logged in to reply to this thread. ru : Вы должны быть авторизованы чтобы ответить в эту тему. cs : Pro odpověď do tohoto threadu se musíte přihlásit. +hu : Be kell legyél jelentkezve, hogy hozzászolhas a témához. :_thread_quickreply_title en : Quick reply ru : Быстрый ответ cs : Rychlá odpověď +hu : Gyors válasz :_thread_quickreply_submit en : Reply ru : Ответить cs : Odpovědět +hu : Válasz :_thread_quickreply_full en : Go advanced... ru : В расширенный режим... cs : Rozšířený mód... +hu : Haladó mód... # Post edit/reply/new thread form @@ -1646,66 +1927,79 @@ cs : Rozšířený mód... en : Start new thread ru : Начать новую тему cs : Založit nový thread +hu : Új téma létrehozása :_postedit_replyto en : Reply to [_1] ru : Ответить в [_1] cs : Odpovědět na [_1] +hu : Válasz [_1]-ra :_postedit_edit en : Edit post ru : Правка сообщения cs : Editovat příspěvek +hu : Hozzászólás szerkesztése :_postedit_form_username en : Username ru : Имя пользователя cs : Uživatelské jméno +hu : Felhasználónév :_postedit_form_title en : Thread title ru : Название темы cs : Název threadu +hu : Téma cím :_postedit_form_boards en : Board(s) ru : Форум(ы) cs : Board(y) +hu : Fórum(ok) :_postedit_form_boards_info en : Read [url,/d9.2,d9.2] for information about how to specify boards. ru : О том как указывать форумы читайте в разделе [url,/d9.2,d9.2]. cs : Přečtěte si [url,/d9.2,d9.2] pro informace jak určit správný board. +hu : Lásd [url,/d9.2,d9.2], hogy hogy kell meghatározni a fórumokat. :_postedit_form_locked en : Locked ru : Заблокировано cs : Zamčený +hu : Lezárva :_postedit_form_topic en : Topic ru : Тема cs : Téma +hu : Téma :_postedit_form_hidden en : Hidden ru : Скрыто cs : Skrytý +hu : Rejtett :_postedit_form_nolastmod en : Don't update last modified field ru : Не обновлять дату последнего изменения cs : Neměnit poslední změněné pole +hu : Ne frissítse az utolsó változtatot mezőt :_postedit_form_msg en : Message ru : Сообщение cs : Zpráva +hu : Üzenet :_postedit_form_msg_format en : See [url,/d9.3,d9.3] for the allowed formatting codes ru : Список разрешённых кодов смотрите в разделе [url,/d9.3,d9.3] cs : Přečtěte si [url,/d9.3,d9.3] pro povolené formátovací kódy +hu : A formázó kódokat itt [url,/d9.3,d9.3] találod meg # Browsing threads by board (/t/{board_id}) @@ -1714,26 +2008,31 @@ cs : Přečtěte si [url,/d9.3,d9.3] pro povolené formátovací kódy en : Related discussions for [_1] ru : Темы, относящиеся к [_1] cs : Diskuse pro [_1] +hu : [_1]-hoz kapcsolódó beszélgetések :_disboard_rootlink en : Discussion board ru : Форум cs : Diskusní board +hu : Fórum :_disboard_nothreads en : No related threads found ru : Связанных тем не найдено cs : Nenalezeny žádné diskuse +hu : Nincs hozzá kapcsolódó téma :_disboard_createyourown en : Why not create one yourself? ru : Почему бы не создать новую? cs : Proč jednu nevytvořite sami? +hu : Miért ne kezdenél te egyet? :_disboard_startnew en : Start a new thread ru : Начать новую тему cs : Začít nový thread +hu : Új téma megnyitása # The discussion board index (/t) @@ -1742,6 +2041,7 @@ cs : Začít nový thread en : Discussion board index ru : Корневая директория форума cs : Seznam diskusních boardů +hu : Fórum kezdőoldal # Thread list (on discussion board index and board browser) @@ -1750,21 +2050,25 @@ cs : Seznam diskusních boardů en : Topic ru : Тема cs : Téma +hu : Téma :_threadlist_col_replies en : Replies ru : Ответов cs : Odpovědi +hu : Válaszok :_threadlist_col_starter en : Starter ru : Автор темы cs : První příspěvek +hu : Készítő :_threadlist_col_lastpost en : Last post ru : Последнее сообщение cs : Poslední příspěvek +hu : Utolsó hozzászólás @@ -1783,31 +2087,37 @@ cs : Poslední příspěvek en : [_1] [_2] ru : [_2], основной язык: [_1] cs : [_2], [_1] +hu : :_prodpage_aliases en : a.k.a. [_1] ru : a.k.a. [_1] cs : a.k.a. [_1] +hu : :_prodpage_vnrel en : Visual Novel Relations ru : Связи новелл cs : Vztahy k vizuálním novelám +hu : Visual Novel Összefüggések :_prodpage_norel en : We have currently no visual novels by this producer. ru : У нас пока нет сведений о новеллах авторства этой компании. cs : Nemáme žádné vizuální novely od tohoto producenta. +hu : Jelenleg nincsen visual novel bejegyzésünk ettől a készítőtől. :_prodpage_dev en : developer ru*: cs*: +hu*: :_prodpage_pub en : publisher ru*: cs*: +hu*: # producer diff fields @@ -1816,36 +2126,43 @@ cs*: en : Type ru : Тип cs : Typ +hu : Típus :_revfield_p_name en : Name (romaji) ru : Название (ромадзи) cs : Jméno (romaji) +hu : Név (romaji) :_revfield_p_original en : Original name ru : Оригинальное название cs : Originální jméno +hu : Eredeti név :_revfield_p_alias en : Aliases ru : Прочие названия cs : Aliasy +hu : Más nevezések :_revfield_p_lang en : Language ru : Язык cs : Jazyk +hu : Nyelv :_revfield_p_website en : Website ru : Веб-сайт cs : Internetová stránka +hu : Weboldal :_revfield_p_desc en : Description ru : Описание cs : Popis +hu : Leírás # Add/Edit producer @@ -1854,61 +2171,73 @@ cs : Popis en : Edit [_1] ru : Править [_1] cs : Editovat [_1] +hu : [_1] szerkesztése :_pedit_title_add en : Add new producer ru : Добавление новой компании cs : Přidat nového producenta +hu : Új készítő hozzáadása :_pedit_form_generalinfo en : General info ru : Основная информация cs : Obecné informace +hu : Általános info :_pedit_form_type en : Type ru : Тип cs : Typ +hu : Típus :_pedit_form_name en : Name (romaji) ru : Название (ромадзи) cs : Jméno (romaji) +hu : Név (romaji) :_pedit_form_original en : Original name ru : Оригинальное название cs : Originální jméno +hu : Eredeti név :_pedit_form_original_note en : The original name of the producer, leave blank if it is already in the Latin alphabet. ru : Оригинальное название компании, оставьте пустым если уже в латинском алфавите. cs : Originální jméno producenta, ponechte prázdné, pokud již je v latince. +hu : A készítő eredeti neve, hagyd üresen ha latin betűkből áll s már beírtad a "Név" mezőbe. :_pedit_form_alias en : Aliases ru : Прочие названия cs : Aliasy +hu : Más nevek :_pedit_form_alias_note en : (Un)official aliases, separated by a comma. ru : (Не)официальные альтернативные названия, через запятую. cs : Ne(oficiální) aliasy, oddělené čárkou. +hu : (Nem)hivatalos nevek, vesszővel elválasztva :_pedit_form_lang en : Primary language ru : Основной язык cs : Hlavní jazyk +hu : Elsődleges nyelv :_pedit_form_website en : Website ru : Веб-сайт cs : Internetová stránka +hu : Weboldal :_pedit_form_desc en : Description ru : Описание cs : Popis +hu : Leírás # Browse/search producers @@ -1917,21 +2246,25 @@ cs : Popis en : Browse producers ru : Обзор компаний cs : Procházet producenty +hu : Készítők böngészése :_pbrowse_searchres en : Search results ru : Результаты поиска cs : Výsledky hledání +hu : Keresés eredménye :_pbrowse_list en : Producer list ru : Список компаний cs : Seznam producentů +hu : Készítők listája :_pbrowse_noresults en : No results found ru : Ничего не найдено cs : Nenalezeny žádné výsledky +hu : Nem található semmi @@ -1948,116 +2281,139 @@ cs : Nenalezeny žádné výsledky en : Relations ru : Связи cs : Vztahy +hu : Összefüggések :_revfield_r_type en : Type ru : Тип cs : Typ +hu : Típus :_revfield_r_patch en : Patch ru : Патч cs : Patch +hu : :_revfield_r_freeware en : Freeware ru : Freeware cs : Freeware +hu : :_revfield_r_doujin en : Doujin ru : Додзинси cs : Doujin +hu : :_revfield_r_title en : Title (romaji) ru : Название (ромадзи) cs : Název (romaji) +hu : Cím (romaji) :_revfield_r_original en : Original title ru : Оригинальное название cs : Originální název +hu : Eredeti cím :_revfield_r_gtin en : JAN/UPC/EAN ru : JAN/UPC/EAN cs : JAN/UPC/EAN +hu : :_revfield_r_catalog en : Catalog number ru : Номер в каталоге cs : Číslo v katalogu +hu : Katalógus szám :_revfield_r_languages en : Language ru : Язык cs : Jazyk +hu : Nyelv :_revfield_r_website en : Website ru : Веб-сайт cs : Internetová stránka +hu : Weboldal :_revfield_r_released en : Release date ru : Дата выпуска cs : Datum vydání +hu : Kiadás ideje :_revfield_r_minage en : Age rating ru : Возрастной рейтинг cs : Věková přístupnost +hu : Korhatár :_revfield_r_notes en : Notes ru : Заметки cs : Poznámky +hu : Megjegyzések :_revfield_r_platforms en : Platforms ru : Платформы cs : Platformy +hu : Platformok :_revfield_r_media en : Media ru : Носители cs : Média +hu : Médium :_revfield_r_resolution en : Resolution ru : Разрешение cs : Rozlišení +hu : Felbontás :_revfield_r_voiced en : Voiced ru : Озвучка cs : Hlas +hu : Szinkronos :_revfield_r_ani_story en : Story animation ru : Сюжетная анимация cs : Animace příběhu +hu : Animált történet :_revfield_r_ani_ero en : Ero animation ru : Анимация эросцен cs : Ero animace +hu : Animált ero jelenetek :_revfield_r_producers en : Producers ru : Компании cs : Producenti +hu : Készítők :_reldiff_developer en : developer ru*: cs*: +hu*: :_reldiff_publisher en : publisher ru*: cs*: +hu*: # Information table (on every release page) @@ -2066,146 +2422,175 @@ cs*: en : Relation ru : Связи cs : Vztah +hu : Összefüggés :_relinfo_title en : Title ru : Название cs : Název +hu : Cím :_relinfo_original en : Original title ru : Оригинальное название cs : Originální název +hu : Eredeti cím :_relinfo_type en : Type ru : Тип cs : Typ +hu : Típus :_relinfo_type_format en : [_1][index,_2,, patch] ru : [_1][index,_2,, патч] cs : [_1][index,_2,, patch] +hu : :_relinfo_lang en : Language ru : Язык cs : Jazyk +hu : Nyelv :_relinfo_publication en : Publication ru : Публикация cs : Publikováno +hu : Kiadás :_relinfo_pub_nopatch en : [index,_1,Freeware,Non-free], [index,_2,doujin,commercial] ru : [index,_1,Freeware,Несвободная], [index,_2,додзинси,коммерческая] cs : [index,_1,Freeware,Non-free], [index,_2,doujin,komerční] +hu : [index,_1,Freeware,Nem Freeware], [index,_2,doujin,kereskedelmi] :_relinfo_pub_patch en : [index,_1,Freeware,Non-free] ru : [index,_1,Freeware,Несвободная] cs : [index,_1,Freeware,Non-free] +hu : [index,_1,Freeware,Nem Freeware] :_relinfo_platform en : [quant,_1,Platform,Platforms] ru : [quant,_1,Платформа,Платформы,Платформ] cs : [quant,_1,Platforma,Platformy,Platforem] +hu : [quant,_1,Platform,Platformok] :_relinfo_media en : [quant,_1,Medium,Media] ru : [quant,_1,Носитель,Носители,Носителей] cs : [quant,_1,Médium,Média,Médií] +hu : [quant,_1,Medium,Mediumok] :_relinfo_resolution en : Resolution ru : Разрешение cs : Rozlišení +hu : Felbontás :_relinfo_voiced en : Voiced ru : Озвучка cs : Hlas +hu : Szinkronos :_relinfo_ani en : Animation ru : Анимация cs : Animace +hu : Animáció :_relinfo_ani_story en : Story: [_1] ru : Сюжет: [_1] cs : Příběh: [_1] +hu : Történet: [_1] :_relinfo_ani_ero en : Ero scenes: [_1] ru : Эросцены: [_1] cs : Ero scény: [_1] +hu : Ero jelenetek: [_1] :_relinfo_released en : Released ru : Дата выпуска cs : Vydáno +hu : Kiadva :_relinfo_minage en : Age rating ru : Возрастной рейтинг cs : Věková přístupnost +hu : Korhatár :_relinfo_developer en : [quant,_1,Developer,Developers] ru*: cs*: +hu*: :_relinfo_publisher en : [quant,_1,Publisher,Publishers] ru*: cs*: +hu*: :_relinfo_catalog en : Catalog no. ru : № в каталоге cs : Č. v katalogu +hu : Katalógus szám :_relinfo_links en : Links ru : Ссылки cs : Odkazy +hu : Linkek :_relinfo_website en : Official website ru : Официальный веб-сайт cs : Oficiální stránky +hu : Hivatalos weboldal :_relinfo_user en : User options ru : Настройки пользователя cs : Možnosti uživatele +hu : Beállítások :_relinfo_user_notlist en : not in your list ru : не в вашем списке cs : není ve vašem listu +hu : nincs a listádba :_relinfo_user_inlist en : Status: [_1] / [_2] ru : Статус: [_1] / [_2] cs : Status: [_1] / [_2] +hu : Állapot: [_1] / [_2] :_relinfo_user_setr en : Set release status ru : Установка статуса выпуска cs : Změnit status vydání +hu : Kiadás állapotának módosítása :_relinfo_user_setv en : Set play status ru : Установка статуса игры cs : Změnit herní status +hu : Játszás állapotának módosítása :_relinfo_user_del en : remove from list ru : убрать из списка cs : odstranit z listu +hu : eltávolítás a listából # Editing a release @@ -2214,96 +2599,115 @@ cs : odstranit z listu en : Edit [_1] ru : Правка [_1] cs : Editovat [_1] +hu : [_1] szerkesztése :_redit_title_copy en : Copy [_1] ru : Копирование [_1] cs : Kopírovat [_1] +hu : [_1] másolása :_redit_title_add en : Add release to [_1] ru : Добавление выпуска для [_1] cs : Přidat vydání hry [_1] +hu : Kiadás hozzáadása [_1]-hoz :_redit_form_geninfo en : General info ru : Основная информация cs : Obecné informace +hu : Általános info :_redit_form_type en : Type ru : Тип cs : Typ +hu : Típus :_redit_form_patch en : This release is a patch to another release. ru : Данный выпуск является патчем для другого выпуска. cs : Toto vydání je patch k jinému vydání. +hu : Ez a kiadás egy patch egy másik kiadáshoz. :_redit_form_freeware en : Freeware (i.e. available at no cost) ru : Freeware (т.е. распространяется бесплатно) cs : Freeware (tj. dostupný zdarma) +hu : Freeware (vagyis ingyenes) :_redit_form_doujin en : Doujin (self-published, not by a company) ru : Додзинси (выпущено самостоятельно, частным лицом) cs : Doujin (publikováno samostatně, ne firmou) +hu : Doujin (magán kiadás, nem egy cég által) :_redit_form_title en : Title (romaji) ru : Название (ромадзи) cs : Název (romaji) +hu : Cím (romaji) :_redit_form_original en : Original title ru : Оригинальное название cs : Originální název +hu : Eredeti cím :_redit_form_original_note en : The original title of this release, leave blank if it already is in the Latin alphabet. ru : Оригинальное название данного выпуска, осавьте пустым если уже в латинском алфавите. cs : Originální název tohoto vydání, ponechte prázdné, pokud již je latinkou. +hu : A kiadás eredeti neve, hagyd üresen ha latin betűkből áll s már beírtad a "Cím" mezőbe. :_redit_form_languages en : Language(s) ru : Язык(и) cs : Jazyk(y) +hu : Nyelv(ek) :_redit_form_gtin en : JAN/UPC/EAN ru : JAN/UPC/EAN cs : JAN/UPC/EAN +hu : :_redit_form_catalog en : Catalog number ru : Номер в каталоге cs : Číslo v katalogu +hu : Katalógus szám :_redit_form_website en : Official website ru : Официальный веб-сайт cs : Oficiální stránky +hu : Hivatalos weboldal :_redit_form_released en : Release date ru : Дата выпуска cs : Datum vydání +hu : Kiadás ideje :_redit_form_released_note en : Leave month or day blank if they are unknown ru : Если месяц или день неизвестны, оставьте их пустыми cs : Ponechte měsíc či den prázdné, pokud jsou neznámé +hu : Ha a hónap és nap ismeretlen akkor hagyd üresen a mezőt. :_redit_form_minage en : Age rating ru : Возрастной рейтинг cs : Věková přístupnist +hu : Korhatár :_redit_form_notes en : Notes ru : Заметки cs : Poznámky +hu : Megjegyzések :_redit_form_notes_note en : Miscellaneous notes/comments, information that does not fit in the above fields. @@ -2312,171 +2716,206 @@ ru : Дополнительные заметки/комментарии, инф Т.е.: присутствие/отсутствие цензуры, или для каких версий применим данный патч. cs : Různé poznámky/komentáře a informace, které se nehodí do předchozích polí. Např.: Cenzurovaná/necenzurovaná verze nebo pro které vydání je patch. +hu : Különböző észrevételek/megjegyzések, olyan infók amelyek nem illenek a fenti mezőbe. + Pl. : Cenzurált/Cenzurálatlan, vagy, hogy melyik kiadásra vonatkozik a patch, stb. :_redit_form_format en : Format ru : Формат cs : Formát +hu : Formátúm :_redit_form_resolution en : Resolution ru : Разрешение cs : Rozlišení +hu : Felbontás :_redit_form_voiced en : Voiced ru : Озвучка cs : Hlas +hu : Szinkronos :_redit_form_ani_story en : Story animation ru : Сюжетная анимация cs : Animace příběhu +hu : Animált történet :_redit_form_ani_ero en : Ero animation ru : Анимация эросцен cs : Ero animace +hu : Animált ero jelenetek :_redit_form_ani_ero_none en : Unknown / no ero scenes ru : Неизвестно / нет эросцен cs : Není známo / bez ero scén +hu : Ismeretlen / nincs ero jelenet :_redit_form_ani_ero_note en : Animation in erotic scenes, leave to unknown if there are no ero scenes. ru : Анимация в эротических сценах, не изменяйте поле если эросцены отсутствуют. cs : Animace v ero scénách, ponechte na Není známo, pokud novela nemá ero scény. +hu : Animált erotikus jelenetek, hagyd 'Ismeretlen'-en ha nem tartalmaz erotikus jelenetek. :_redit_form_platforms en : Platforms ru : Платформы cs : Platformy +hu : Platformok :_redit_form_media en : Media ru : Носители cs : Média +hu : Médium :_redit_form_med_quantity en : -quantity- ru*: cs*: +hu*: :_redit_form_med_medium en : -medium- ru*: cs*: +hu*: :_redit_form_med_remove en : remove ru*: cs*: +hu*: :_redit_form_prod en : Producers ru : Компании cs : Producenti +hu : Készítők :_redit_form_prod_sel en : Selected producers ru : Выбранные компании cs : Vybraní producenti +hu : Kiválasztot készítők :_redit_form_prod_add en : Add producer ru : Добавить компанию cs : Přidat producenta +hu : Készitő hozzáadása :_redit_form_prod_dev en : Developer ru*: cs*: +hu*: :_redit_form_prod_pub en : Publisher ru*: cs*: +hu*: :_redit_form_prod_both en : Both ru*: cs*: +hu*: :_redit_form_prod_addbut en : add ru*: cs*: +hu*: :_redit_form_prod_remove en : remove ru*: cs*: +hu*: :_redit_form_prod_none en : Nothing selected. ru*: cs*: +hu*: :_redit_form_prod_pformat en : Producer textbox must start with an ID (e.g. p17) ru*: cs*: +hu*: :_redit_form_prod_notfound en : Producer not found! ru*: cs*: +hu*: :_redit_form_prod_double en : Producer already selected! ru*: cs*: +hu*: :_redit_form_vn en : Visual novels ru : Новеллы cs : Vizuální novely +hu : Visual novellek :_redit_form_vn_sel en : Selected visual novels ru : Выбранные новеллы cs : Vybrané vizuální novely +hu : Kiválasztot visual novellek :_redit_form_vn_add en : Add visual novel ru : Добавить новеллу cs : Přidat vizuální novelu +hu : Visual novel hozzáadása :_redit_form_vn_addbut en : add ru*: cs*: +hu*: :_redit_form_vn_remove en : remove ru*: cs*: +hu*: :_redit_form_vn_none en : Nothing selected. ru*: cs*: +hu*: :_redit_form_vn_vnformat en : Visual novel textbox must start with an ID (e.g. v17) ru*: cs*: +hu*: :_redit_form_vn_notfound en : Visual novel not found! ru*: cs*: +hu*: :_redit_form_vn_double en : VN already selected! ru*: cs*: +hu*: # Release browser @@ -2485,26 +2924,31 @@ cs*: en : Browse releases ru : Обзор выпусков cs : Procházet vydání +hu : Kiadások böngészése :_rbrowse_col_released en : Released ru : Выпущено cs : Vydáno +hu : Kiadva :_rbrowse_col_minage en : Rating ru : Рейтинг cs : Hodnocení +hu : Szavazat :_rbrowse_col_title en : Title ru : Название cs : Název +hu : Cím :_rbrowse_noresults_title en : No results found ru : Совпадений не найдено cs : Nenalezeny žádné výsledky +hu : Nem található semmi :_rbrowse_noresults_msg en : Sorry, couldn't find anything that comes through your filters. You might want to disable a few filters to get more results. @@ -2516,126 +2960,153 @@ ru : Простите, по вашему запросу ничего не най cs : Omlouváme se, nenalezli jsme nic, co by vyhovovalo vašemu nastavení filtrů. Možná najdete více výsledků, pokud nějaké z nich vypnete. Také nezapomeňte, že o všech vydáních nemáme všechny údaje. Takže pokud například vyfiltrujete rozlišení obrazovky, pak ve výsledcích nebudou všechna vydání, u kterých neznáme jejich rozlišení, i když by to mohla být právě vydání v rozlišení, o které se zajímáte. +hu : Bocs, de ezzekel a szűrőkkel nem található semmi. Talán ki kéne kapcsolj egy párat, hogy több eredmény jöjjön ki. + + Valamint, ne felejtsd el, hogy nincsen minden kiadásról elégséges információnk. Szóval ha bekapcsolod a felbontásra vonatkozó szűrőt, azokat nem mutatja amelyeknek nincs megadva a felbontásuk, még akkor is ha valójabban annyi, mint amennyit te keresel. :_rbrowse_filters en : Filters ru : Фильтры cs : Filtry +hu : Szűrők :_rbrowse_minage en : Age rating ru : Возрастной рейтинг cs : Věková přístupnost +hu : Korhatár :_rbrowse_ge en : Greater than or equal to ru : Больше или равно cs : Větší než nebo rovno +hu : Nagyobb vagy egyenlő :_rbrowse_le en : Less than or equal to ru : Меньше или равно cs : Menší než nebo rovno +hu : Kisebb vagy egyenlő :_rbrowse_resolution en : Screen resolution ru : Разрешение экрана cs : Rozlišení obrazovky +hu : Felbontás :_rbrowse_type en : Release type ru : Тип выпуска cs : Typ vydání +hu : Kiadás típus :_rbrowse_all en : All ru : Все cs : Vše +hu : Minden :_rbrowse_patch en : Patch status ru : Статус патча cs : Status patche +hu : Patch állapot :_rbrowse_patchonly en : Only patches ru : Только патчи cs : Pouze patche +hu : Csak patchek :_rbrowse_patchnone en : Only standalone releases ru : Только самостоятельные выпуски cs : Pouze samostatná vydání +hu : Csak különálló kiadások :_rbrowse_freeware en : Freeware ru : Freeware cs : Freeware +hu : :_rbrowse_freewareonly en : Freeware only ru : Только Freeware cs : Pouze freeware +hu : Csak Freeware :_rbrowse_freewarenone en : Only non-free releases ru : Только несвободные cs : Pouze placená vydání +hu : Minden nem ingyenes kiadás :_rbrowse_doujin en : Doujin ru : Додзинси cs : Doujin +hu : :_rbrowse_doujinonly en : Only doujin releases ru : Только додзинси cs : Pouze doujin vydání +hu : Csak doujin kiadások :_rbrowse_doujinnone en : Only commercial releases ru : Только коммерческие cs : Pouze komerční vydání +hu : Csak kereskedelmi kiadások :_rbrowse_dateafter en : Released after ru : Выпущены после cs : Vydáno po +hu : Kiadva útán :_rbrowse_datebefore en : Released before ru : Выпущены до cs : Vydáno před +hu : Kiadva előtt :_rbrowse_languages en : Languages ru : Языки cs : Jazyky +hu : Nyelvek :_rbrowse_boolor en : boolean or, selecting more gives more results ru : булевое 'или', чем больше выбрано, тем больше даёт результатов cs : boolean nebo, výběr více dá více výsledků +hu : Boole féle értékhalmaz(igaz/hamis), ha többet jelölsz be, több eredményt ad ki :_rbrowse_platforms en : Platforms ru : Платформы cs : Platformy +hu : Platformok :_rbrowse_media en : Media ru : Носители cs : Média +hu : Médium :_rbrowse_apply en : Apply ru : Применить cs : Použít +hu : Alkalmaz :_rbrowse_clear en : Clear ru : Очистить cs : Začít znovu +hu : Törlés @@ -2652,11 +3123,13 @@ cs : Začít znovu en : [index,_1,Meta tag,Tag]: [_2] ru : [index,_1,Мета тег,Тег]: [_2] cs : [index,_1,Meta tag,Tag]: [_2] +hu : [index,_1,Meta Cimke,Cimke]: [_2] :_tagp_del_title en : Tag deleted ru : Тег удалён cs : Tag smazán +hu : Cimke törölve :_tagp_del_msg en : This tag has been removed from the database, and cannot be used or re-added. @@ -2665,96 +3138,116 @@ ru : Данный тег удалён из базы данных, и не мож Напишите на [url,/t/db,форуме], если вы с этим не согласны. cs : Tento tag byl smazán z databáze a nemůže být použit nebo znovu přidán. Pokud s tímto nesouhlasíte, napište žádost na [url,/t/db,diskusní board]. +hu : Ez a cimke törölve lett az adatbázisból, s nem lehetséges visszaállitani vagy használni. + Tegyél panaszt a [url,/t/db,fórumon] ha nem értesz egyet. :_tagp_pending_title en : Waiting for approval ru : Ждёт одобрения cs : Čeká na schválení +hu : Megerősítésre vár :_tagp_pending_msg en : 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. ru : Данный тег ожидает одобрения модератором. Однако, вы можете использовать его для пометки новелл, как и любой нормальный тег. cs : Tento tag čeká na schválení moderátorem. Mezitím ho stále můžete používat jako normální tag. +hu : Ez a cimke arra vár, hogy egy moderátor elfogadja. Azonban használhatod bármely VN-nél nyugodtan akárcsak egy normális cimkét. :_tagp_addchild en : Create child tag ru : Создать дочерний тег cs : Vytvořit závislý tag +hu : Gyerek cimke létrehozássa :_tagp_indexlink en : Tags ru : Теги cs : Tagy +hu : Cimkék :_tagp_aliases en : Aliases ru : Прочие названия cs : Aliasy +hu : Más nevek :_tagp_childs en : Child tags ru : Дочерние теги cs : Závislé tagy +hu : Gyerek cimkék :_tagp_tree en : Tag tree ru : Древо тега cs : Strom tagů +hu : Cimke fa :_tagp_moretags en : [_1] more [quant,_1,tag,tags] ru : ещё [_1] [quant,_1,тег,тега,тегов] cs : [_1] [quant,_1,další tag,další tagy,dalších tagů] +hu : [_1] több [quant,_1,cimke,cimkék] :_tagp_vnlist en : Visual novels ru : Новеллы cs : Vizuální novely +hu : Visual novellek :_tagp_spoil0 en : Hide spoilers ru : Скрыть спойлеры cs : Skrýt spoilery +hu : Spoilerek elrejtése :_tagp_spoil1 en : Show minor spoilers ru : Показать лёгкие спойлеры cs : Ukázat menší spoilery +hu : Kisebb spoilerek megjelenítése :_tagp_spoil2 en : Show major spoilers ru : Показать жёсткие спойлеры cs : Ukázat všechny spoilery +hu : Nagyobb spoilerek megjelenítése :_tagp_novn en : This tag has not been linked to any visual novels yet, or they were hidden because of the spoiler settings. ru : Этот тег пока не содержит ссылок ни на одну новеллу, либо они скрыты из-за настроек отображения спойлеров. cs : Tento tag ještě nebyl použit v žádné vizuální novele nebo byly tyto skryty kvůli nastavení spoilerů. +hu : Ez a cimke eddig egy visual novelhez sincs hozzárendelve, vagy el lettek rejtve a spoiler-ek beállítása során. :_tagp_cached en : NOTE: 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. ru : ЗАМЕЧАНИЕ: Данный список кэшируется, поэтому может пройти вплоть до 24 часов, прежде чем новелла, помеченная тегом, отобразится на этой странице. cs : POZNÁMKA: Tento list se ukládá do cache, takže může trvat až 24 hodin po otagování vizuální novely do objevení se na této stránce. +hu : FIGYELEM: Ez a lista le van mentve a gyorsítótárba, beletelhet 24 órába míg a visual novelhez újjonan hozzárendelt cimke megjelenik ezzen az oldalon. :_tagp_vncol_score en : Score ru : Балл cs : Skóre +hu : Pontozás :_tagp_vncol_title en : Title ru : Название cs : Název +hu : Cím :_tagp_vncol_rel en : Released ru : Выпуск cs : Vydáno +hu : Kiadva :_tagp_vncol_pop en : Popularity ru : Популярность cs : Popularita +hu : Népszerűség # Tag add/edit form (/g+/edit, /g+/add, /g/add) @@ -2763,31 +3256,37 @@ cs : Popularita en : Tag '[_1]' not found ru : Тег '[_1]' не найден cs : Tag '[_1]' nenalezen +hu : A(z) '[_1]' cimke nem található :_tagedit_title_add en : Add child tag to [_1] ru : Добавление дочернего тега для '[_1]' cs : Přidat závislý tag tagu [_1] +hu : Gyerek cimke hozzárendelése a(z) [_1] - hez :_tagedit_title_edit en : Edit tag: [_1] ru : Править тег: [_1] cs : Editovat tag: [_1] +hu : Cimke szerkesztése: [_1] :_tagedit_title_new en : Add new tag ru : Добавить новый тег cs : Přidat nový tag +hu : Új cimke készítése :_tagedit_req_title en : Requesting new tag ru : Запросить новый тег cs : Požaduje se nový tag +hu : Új cimke kérése :_tagedit_req_subtitle en : Your tag must be approved ru : Ваш тег должен быть одобрен cs : Váš tag musí být schválen +hu : A cimkédet előbb el kell fogadják :_tagedit_req_msg en : Because all tags have to be approved by moderators, it can take a while before it will show up in the tag list @@ -2802,46 +3301,58 @@ cs : Protože všechny tagy musí být schválené moderátorem, může chvilku nebo na stránce vizuální novely. I před schválením ale můžete stále tag hodnotit. [br][br] Také se ujistěte, že jste přečetli [url,/d10,doporučení], abyste věděli, zda váš tag bude přidán nebo ne. +hu : Mivel minden cimkét külön el kell fogadjanak a moderátorok, beletarthat egy kis időbe míg azok megjelennek a listába + vagy a visual novellek oldalain. Viszont, akkor is tudsz egy cimkére szavazni, ha még nincsen elfogadva. + [br][br] + Valamint, olvasd el az [url,/d10,útmutatót], ha biztosra akarsz menni, hogy a cimkédet el fogják fogadni vagy nem. :_tagedit_frm_name en : Primary name ru : Основное название cs : Hlavní jméno +hu : Elsődleges név :_tagedit_frm_by en : Added by ru : Добавлено cs : Přidal +hu : Hozzáadta :_tagedit_frm_state en : State ru : Состояние cs : Stav +hu : Állapot :_tagedit_frm_state0 en : Awaiting moderation ru : Ждёт модерации cs : Čeká na schválení +hu : Moderálásra vár :_tagedit_frm_state1 en : Deleted/hidden ru : Удалён/скрыт cs : Smazán/skryt +hu : Rejtett/törölve :_tagedit_frm_state2 en : Approved ru : Одобрен cs : Schválen +hu : Elfogadva :_tagedit_frm_meta en : This is a meta-tag (only to be used as parent for other tags, not for linking to VN entries) ru : Это мета-тег (его нельзя добавлять к новеллам, он может использоваться лишь как родитель для других тегов) cs : Toto je meta-tag (používá se pouze jako mateřský pro ostatní tagy, ne pro vlastní vizuální novely) +hu : Ez itt egy meta-cimke (csakis más cimkék szűlője ként használandó, nem pedig VN bejegyzésekhez) :_tagedit_frm_meta_warn en : WARNING: Checking this option or selecting "Deleted" as state will permanently delete all existing VN relations! ru : ПРЕДУПРЕЖДЕНИЕ: Если выбрать данную опцию, либо выставить состояние "Удалён", произойдёт немедленное удаление всех существующих связей с новеллами! cs : VAROVÁNÍ: Zaškrtnutí této volby nebo výběr položky "Smazáno" jako stavu smaže automaticky tag u všech vizuálních novel! +hu : FIGYELEM: Ezzen opció bejelölése vagy a "Törölve" állapot kiválasztása véglegesen megsemmísit minden összefüggést a VN-ekel! :_tagedit_frm_alias en : Aliases @@ -2850,36 +3361,44 @@ ru : Прочие названия (каждое с новой строки) cs : Aliasy (odděleny novou řádkou) +hu : Más nevek + (új sorokkal elválasztva) :_tagedit_frm_desc en : Description ru : Описание cs : Popis +hu : Leírás :_tagedit_frm_desc_msg en : What should the tag be used for? Having a good description helps users choose which tags to link to a VN. ru : Для пометки чего будет использоваться тег? Хорошее описание поможет пользователям выбрать подходящий тег для подходящей новеллы. cs : Pro co by měl být tag používán? Tagy s dobrým popisem usnadňují uživatelům jejich používání u vizuálních novel. +hu : Mire és mikor használja valaki a cimkét? Egy jó leírás megkönyíti a felhasználók dolgát mikor hozzá akarják rendelni egy VN-hez. :_tagedit_frm_parents en : Parent tags ru : Родительские теги cs : Mateřské tagy +hu : Szűlő cimkék :_tagedit_frm_parents_msg en : Comma separated list of tag names to be used as parent for this tag. ru : Теги, которые будут задействованы для этого в качестве родительских. Через запятую. cs : Seznam tagů, oddělených čárkou, které mají být použity jako mateřské pro tento tag +hu : Vesszővel elválasztot cimke nevek amelyek szűlő ként szolgálnak ennek a cimkének. :_tagedit_frm_merge en : Merge tags ru : Объединение тегов cs : Sjednotit tagy +hu : Cimkék egyesítése :_tagedit_frm_merge_tags en : Tags to merge ru : Теги для объединения cs : Tagy ke sjednocení +hu : Egyesítésre váró cimkék :_tagedit_frm_merge_msg en : Comma separated list of tag names to merge into this one. All votes and aliases/names will be moved over @@ -2891,6 +3410,9 @@ ru : Список тегов для объединения в данный, че cs : Seznam tagů, oddělených čárkou, ke sjednocení do tohoto. Všechny hlasy a aliasy/jména budou přesunuty do tohoto tagu a staré tagy budou smazány. Nechte toto pole prázdné, pokud nehodláte nic sjednocovat. [br]VAROVÁNÍ: tato akce nejde vrátit! +hu : Egy lista, veszővel elválasztot cimke nevekkel amelyeket egyesíteni akarsz ebbe az egybe. Minden szavazat és aliasz/nevek át lesznek + helyezve ehhez az új cimkéhez és a régi cimkék pedig törölve lesznek. Ha nem akarsz cimkéket egyesíteni akkor ezt a mezőt hagyd űresen. + [br]FIGYELEM: ez a művelet végleges, nem lehet visszavonni! # Plain tag browser (/g/list) @@ -2899,51 +3421,61 @@ cs : Seznam tagů, oddělených čárkou, ke sjednocení do tohoto. Všechny hla en : Browse tags ru : Обзор тегов cs : Procházet tagy +hu : Cimkék böngészése :_tagb_state-1 en : All ru : Все cs : Všechny +hu : Mind :_tagb_state0 en : Awaiting moderation ru : Ожидающие модерации cs : Čekající na schválení +hu : Moderálásra vár :_tagb_state1 en : Deleted ru : Удалённые cs : Smazané +hu : Törölve :_tagb_state2 en : Accepted ru : Одобренные cs : Přijaté +hu : Elfogadva :_tagb_noresults en : No results found ru : Совпадений не найдено cs : Nenalezeny žádné výsledky +hu : Keresés sikertelen :_tagb_col_added en : Created ru : Созданы cs : Vytvořené +hu : Létrehozva :_tagb_col_name en : Tag ru : Тег cs : Tag +hu : Cimke :_tagb_note_awaiting en : awaiting moderation ru : ждёт модерации cs : čeká na schválení +hu : moderálásra vár :_tagb_note_del en : deleted ru : удалён cs : smazán +hu : törölve # VN<->Tag voting (/v+/tagmod) @@ -2952,66 +3484,79 @@ cs : smazán en : Add/remove tags for [_1] ru : Добавление/удаление тегов для [_1] cs : Přidat/odebrat tag pro novelu [_1] +hu : Cimke hozzáadása/törlése [_1]-hez :_tagv_msg_title en : Tagging ru : Пометка тегами cs : Tagování +hu : Cimkézés :_tagv_msg_guidelines en : Make sure you have read the [url,/d10,guidelines]! ru : Пожалуйста, убедитесь что прочли [url,/d10,рекомендации]! cs : Ujistěte se, že jste přečetli [url,/d10,doporučení]! +hu : Olvasdd el az [url,/d10,utmutatókat]! :_tagv_msg_submit en : Don't forget to hit the submit button on the bottom of the page to make your changes permanent. ru : Не забудьте сохранить изменения, нажав соответствующую кнопку в низу страницы, иначе они не вступят в силу. cs : Nezapomeňte potvrdit tlačítko na spodku stránky, abyste uložili změny trvale. +hu : Ne felejtsd el megnyomni a beküldés gombot a lap alján, hogy véglegesítsd a változtatásokat. :_tagv_msg_cache en : Some tag information on the site is cached, it can take up to an hour for your changes to be visible everywhere. ru : Информация о некоторых тегах на данном сайте кэшируется, поэтому ваши изменения станут видны везде в течение часа. cs : Některé informace o tazích na této stránce jsou v cache a může zabrat až hodinu než budou změny vidět. +hu : Valamely cimkékkel kapcsolatos információ le van mentve a gyorsítótárba, beletelhet egy órába is mire mindenhol láthatóvá válnak a változtatások. :_tagv_frm_title en : Tags ru : Теги cs : Tagy +hu : Cimkék :_tagv_col_you en : You ru : Вы cs : Vy +hu : Te :_tagv_col_others en : Others ru : Остальные cs : Ostatní +hu : Egyebek :_tagv_col_tag en : Tag ru : Тег cs : Tag +hu : Cimke :_tagv_col_rating en : Rating ru : Рейтинг cs : Hodnocení +hu : Osztályozás :_tagv_col_spoiler en : Spoiler ru : Спойлер cs : Spoiler +hu : Spoiler :_tagv_save en : Save changes ru : Сохранить изменения cs : Uložit změny +hu : Változtatások mentése :_tagv_add en : Add tag ru : Добавить тег cs : Přidat tag +hu : Cimke hozzáadása :_tagv_addmsg en : Check the [url,/g,tag list] to browse all available tags.[br] @@ -3020,41 +3565,50 @@ ru : Откройте [url,/g,список тегов] чтобы увидеть Не нашли что искали? Вы можете [url,/g/new,запросить новый тег]. cs : Zkontrolujte [url,/g,list tagů] pro seznam všech dostupných tagů.[br] Nenašli jste, co jste hledali? [url,/g/new,Vyžádejte si nový tag]. +hu : Menj a [url,/g,cimke listára] ha szeretnél böngészni az összes rendelkezésre álló cimke közt.[br] + Nem találod azt amelyiket keresed? [url,/g/new,Itt kérhetsz egy új cimkét]. :_tagv_spoil0 en : neutral ru*: cs*: +hu*: :_tagv_spoil1 en : no spoiler ru*: cs*: +hu*: :_tagv_spoil2 en : minor spoiler ru*: cs*: +hu*: :_tagv_spoil3 en : major spoiler ru*: cs*: +hu*: :_tagv_notfound en : Item not found! ru*: cs*: +hu*: :_tagv_nometa en : Can't use meta tags here! ru*: cs*: +hu*: :_tagv_double en : Tag is already present! ru*: cs*: +hu*: # User tag list (/u+/tags) @@ -3063,41 +3617,49 @@ cs*: en : Tags by [_1] ru : Теги [_1] cs : Tagy podle [_1] +hu : [_1] által létrehozott cimkék :_tagu_spoilerwarn en : Warning: spoilery tags are not hidden in this list! ru : Предупреждение: в этом списке отображаются теги-спойлеры! cs : Varování: spoilerové tagy nejsou v tomto seznamu skryté! +hu : Figyelem: ebbe a listába a spoiler-t tartalmazó cimkek nincsenek elrejtve! :_tagu_notags en : [_1] doesn't seem to have used the tagging system yet... ru : Похоже, что [_1] пока не использует систему тегов... cs : Nezdá se, že by [_1] zatím použil tagovací systém... +hu : Úgy tűnik, hogy [_1] még nem használta a cimkéző rendszert... :_tagu_col_num en : #VNs ru : #Новеллы cs : #VN +hu : #VN-nek :_tagu_col_name en : Tag ru : Тег cs : Tag +hu : Cimke :_tagu_spoil0 en : No spoiler ru : Нет спойлера cs : Bez spoilerů +hu : Nem spoiler :_tagu_spoil1 en : Minor spoiler ru : Лёгкий спойлер cs : Menší spoilery +hu : Enyhe spoiler :_tagu_spoil2 en : Major spoiler ru : Жёсткий спойлер cs : Všechny spoilery +hu : Nagy spoiler # Tag index (/g) @@ -3106,51 +3668,61 @@ cs : Všechny spoilery en : Tag index ru : Индекс тега cs : Seznam tagů +hu : Cimke index :_tagidx_create en : Create new tag ru : Создать новый тег cs : Vytvořit nový tag +hu : Új cimke létrehozássa :_tagidx_search en : Search tags ru : Поиск тегов cs : Hledat tag +hu : Cimkék keresése :_tagidx_browseall en : Browse all tags ru : Обзор всех тегов cs : Procházet všechny tagy +hu : Összes cimke böngészése :_tagidx_recent en : Recently added ru : Недавно добавлены cs : Poslední přidané +hu : Nemrég hozzáadva :_tagidx_popular en : Popular tags ru : Популярные теги cs : Populární tagy +hu : Népszerű cimkék :_tagidx_queue en : Awaiting moderation ru : Ожидают модерации cs : Čekající na schválení +hu : Moderálásra vár :_tagidx_queue_empty en : Moderation queue empty! yay! ru : В очереди модерации пусто! Няа! cs : Fronta ke schválení prázdná! Jej! +hu : Moderálásra váró lista üres! Hurrá! :_tagidx_queue_link en : Moderation queue ru : Очередь модерации cs : Fronta ke schválení +hu : Moderálásra váró lista :_tagidx_denied en : Denied tags ru : Отклонённые теги cs : Zamítnuté tagy +hu : Megtagadot cimkék @@ -3167,51 +3739,61 @@ cs : Zamítnuté tagy en : My wishlist ru : Мой список желаемого cs : Můj wishlist +hu : Kivánságlistám :_wishlist_title_other en : [_1]'s wishlist ru : Список желаемого [_1] cs : Wishlist uživatele [_1] +hu : [_1] kivánság listája :_wishlist_noresults en : Wishlist empty... ru : Список пуст... cs : Wishlist je prázdný... +hu : Kivánságlista üres... :_wishlist_prio_all en : All priorities ru : Все приоритеты cs : Všechny priority +hu : Minden prioritás :_wishlist_col_title en : Title ru : Название cs : Název +hu : Cím :_wishlist_col_prio en : Priority ru : Приоритет cs : Priorita +hu : Prioritás :_wishlist_col_added en : Added ru : Добавлено cs : Přidáno +hu : Hozzáadva :_wishlist_select en : -- with selected -- ru : -- с выбранными -- cs : -- s vybranými -- +hu : -- kiválasztva -- :_wishlist_changeprio en : Change priority ru : Изменить приоритет cs : Změnit prioritu +hu : Prioritás megváltoztatása :_wishlist_remove en : remove from wishlist ru : убрать из списка желаемого cs : odstranit z wishlistu +hu : eltávolítás a kivánságlistából # VN list (/u+/list) @@ -3220,66 +3802,79 @@ cs : odstranit z wishlistu en : My visual novel list ru : Мой список новелл cs : Můj list vizuálních novel +hu : Visual novel listám :_rlist_title_other en : [_1]'s visual novel list ru : Список новелл [_1] cs : List vizuálních novel uživatele [_1] +hu : [_1] visual novel listája :_rlist_voted_all en : All ru : Все cs : Všechny +hu : Mind :_rlist_voted_only en : Only voted ru : Проголосованные cs : Pouze hodnocené +hu : Csak a szavazottak :_rlist_voted_none en : Hide voted ru : Скрыть проголосованные cs : Skrýt hodnocené +hu : Szavazottak elrejtése :_rlist_col_title en : Title ru : Название cs : Název +hu : Cím :_rlist_col_releases en : Releases ru : Выпуски cs : Vydání +hu : Kiadások :_rlist_col_vote en : Vote ru : Голос cs : Hodnocení +hu : Szavazat :_rlist_selection en : -- with selected -- ru : -- с выбранными -- cs : -- s vybranými -- +hu : -- kiválasztva -- :_rlist_changerel en : Change release status ru : Смена статуса выпуска cs : Změnit stav vydání +hu : Kiadás állapotának megváltoztatása :_rlist_changeplay en : Change play status ru : Смена статуса игры cs : Změnit stav hraní +hu : Játszás állapot megváltoztatása :_rlist_del en : remove from list ru : убрать из списка cs : odstranit z listu +hu : eltávolítás a listából :_rlist_releasenote en : * Obtained/finished/total ru : * Приобретено/прочитано/всего cs : * Sehnáno/dohráno/celkem +hu : * Megszerezve/befejezve/összesen @@ -3296,81 +3891,97 @@ cs : * Sehnáno/dohráno/celkem en : [_1]'s profile ru : Учётная запись [_1] cs : Profil uživatele [_1] +hu : [_1] profilja :_userpage_username en : Username ru : Имя пользователя cs : Uživatelské jméno +hu : Felhasználónév :_userpage_registered en : Registered ru : Регистрация cs : Registrován +hu : Regisztrálva :_userpage_edits en : Edits ru : Правки cs : Editace +hu : Szerkesztések :_userpage_votes en : Votes ru : Отдано голосов cs : Hlasování +hu : Szavazatok :_userpage_votes_item en : [url,_1,_2] ([_3] average) ru : [url,_1,_2] ([_3] в среднем) cs : [url,_1,_2] (průměr [_3]) +hu : [url,_1,_2] ([_3] átlag) :_userpage_hidden en : hidden ru : скрыто cs : skryto +hu : elrejtve :_userpage_tags en : Tags ru : Теги cs : Tagy +hu : Cimkék :_userpage_tags_item en : [_1] [quant,_1,vote,votes] on [_2] distinct [quant,_2,tag,tags] and [_3] visual [quant,_3,novel,novels] ru : [_1] [quant,_1,голос,голоса,голосов] по [_2][quant,_2,-у тегу,-м различным тегам,-и различным тегам] и [_3][quant,_3,-й новелле,-м новеллам,-и новеллам] cs : [_1] [quant,_1,hlasy,hlasy,hlasů] pro [_2] [quant,_2,tag,různé tagy,různých tagů] a [_3] [quant,_3,vizuální novelu,vizuální novely,vizuálních novel] +hu : [_1] [quant,_1,szavazat,szavazat] [_2] egyedi [quant,_2,cimkére,cimkére] és [_3] visual [quant,_3,novelre,novelre] :_userpage_list en : List stats ru : Статистика по спискам cs : Statistiky listu +hu : Lista adatok :_userpage_list_item en : [_1] [quant,_1,release,releases] of [_2] visual [quant,_2,novel,novels] ru : [_1] [quant,_1,выпуск,выпуска,выпусков] [_2][quant,_2,-й новеллы,-х новелл,-и новелл] cs : [_1] [quant,_1,vydání,vydání,vydání] [_2] [quant,_2,vizuální novely,vizuálních novel,vizuálních novel] +hu : [_1] [quant,_1,kiadás,kiadás] és [_2] visual [quant,_2,novel,novel] :_userpage_forum en : Forum stats ru : Статистика по форуму cs : Statistiky fóra +hu : Fórum adatok :_userpage_forum_item en : [_1] [quant,_1,post,posts], [_2] new [quant,_2,thead,threads]. ru : [_1] [quant,_1,сообщение,сообщения,сообщений], [_2] [quant,_2,новая тема,новые темы,новых тем] cs : [_1] [quant,_1,příspěvek, příspěvky, příspěvků], [_2] [quant,_2,nový thread, nové thready, nových threadů]. +hu : [_1] [quant,_1,válasz,válaszok], [_2] új [quant,_2,téma,témá]. :_userpage_forum_browse en : Browse posts ru : Обзор сообщений cs : Procházet příspěvky +hu : Hozzászólások böngészése :_userpage_votestats en : Vote statistics ru : Статистика по голосованиям cs : Statistiky hlasování +hu : Szavazási statisztikák :_userpage_changes en : Recent changes ru : Свежие правки cs : Poslední změny +hu : Legutóbbi változtatások # Login form (/u/login) @@ -3379,26 +3990,31 @@ cs : Poslední změny en : Login ru : Вход cs : Přihlásit +hu : Bejelentkezés :_login_username en : Username ru : Имя пользователя cs : Uživatelské jméno +hu : Felhasználónév :_login_register en : No account yet? ru : Нет учётной записи? cs : Ještě nemáte účet? +hu : Nincs még fiókod? :_login_password en : Password ru : Пароль cs : Heslo +hu : Jelszó :_login_forgotpass en : Forgot your password? ru : Забыли пароль? cs : Zapomněli jste své heslo? +hu : Elfelejtetted a jelszavad? # Reset password (/u/newpass) @@ -3435,17 +4051,29 @@ cs : Zdravíme, [_1] Heslo: [_2] A snažte se už heslo znovu nezapomenout! :-) +hu : Üdv [_1] + + A jelszavad vissza lett állítva, mostmár bejelentkezhetsz a http://vndb.org/ címmen az + új adataidal: + + Felhasználónév: [_1] + Jelszó: [_2] + + Legközelebb próbáld meg nem elfelejteni a jelszavad! :-) vndb.org + :_newpass_mail_subject en : New password for [_1] ru : Новый пароль для [_1] cs : Nové heslo pro uživatele [_1] +hu : Új jelszó [_1]-nak :_newpass_title en : Forgot password ru : Забытый пароль cs : Zapomenuté heslo +hu : Elfelejtetted a jelszavad? :_newpass_msg en : Forgot your password and can't login to VNDB anymore? @@ -3458,26 +4086,33 @@ ru : Забыли пароль и больше не можете авториз cs : Zapomněli jste své heslo a nemůžete se přihlásit na VNDB? Nebojte! Stačí zadat e-mailovou adresu, se kterou jste se na VNDB registrovali, a my vám do několika minut pošleme heslo nové! +hu : Elfelejtetted a jelszavad és nem tudsz bejelentkezni a VNBD-be? + Ne aggódj! Csak add meg nekünk az email címmet amivel regisztráltál, + s egy pár percen belűl kapsz tőlünk egy új jelszót! :_newpass_reset_title en : Reset password ru : Сброс пароля cs : Změnit heslo +hu : Jelszó visszaállitása :_newpass_mail en : Email ru : E-mail cs : E-mail +hu : :_newpass_sent_title en : New password ru : Новый пароль cs : Nové heslo +hu : Új jelszó :_newpass_sent_subtitle en : Password reset ru : Сбросить пароль cs : Změnit heslo +hu : Jelszó visszaállitás :_newpass_sent_msg en : Your password has been reset and your new password should reach your mailbox in a few minutes.[br] @@ -3492,6 +4127,10 @@ cs : Vaše heslo bylo změněno a vaše nové heslo by mělo být za několik mi Vždy můžete změnit vaše heslo po přihlášení.[br] [br] [url,/u/login,Přihlásit] - [url,/,Home] +hu : A jelszavad vissza lett állítva s pár percen belül kapsz egy újjat a postafiókodba.[br] + Miútán bejelentkezel, nyugodtan megváltoztathatod a jelszavad amire akarod.[br] + [br] + [url,/u/login,Bejelentkezés] - [url,/,Kezdőlap] # Register new account (/u/register) @@ -3499,11 +4138,13 @@ cs : Vaše heslo bylo změněno a vaše nové heslo by mělo být za několik mi en : Create an account ru : Создание учётной записи cs : Vytvořit účet +hu : Új fiók létrehozzása :_register_why en : Why should I register? ru : Для чего нужна регистрация? cs : Proč bych se měl registrovat? +hu : Miért kéne regisztráljak? :_register_why_msg en : Creating an account is completely painless, the only thing we need to know is your prefered username @@ -3535,26 +4176,39 @@ cs : Tvorba účtu je zcela bezbolestná, jediné údaje, které potřebujeme zn - Mějte přehled o všech vizuálních novelách, které máte, chtěli byste hrát, hrajete, nebo jste dohráli[br] - Hlasujte pro vizuální novely, které se vám líbily nebo nelíbily[br] - Přispívejte do diskusí na boardech +hu : Egy fiókot nagyon egyszerű készíteni, minden ami kell egy felhasználónév és egy jelszó. Bármilyen email címmet használhatsz, + minket nem érdekel, hogy a tied vagy nem, mivel nincs külön aktiválás. Viszont ha nem jó emailt adsz meg nekünk + akkor jól vésd az eszedbe a jelszavad, különben nem tudunk neked segíteni ha elfelejted.[br] + [br] + Nos, a saját fiókkal rendelkezők több előnybe is részesűlnek mint az egyszerű látogatók[br] + - Hozzájárúlhatsz az adatbázis fejlődéséhez, hiszen szerkeszthetsz, vagy létrehozhatsz új bejegyzéseket[br] + - Nyomon követheted a tulajdonodban levő visual novellek, helyzetét, állapotát...mit játszol, melyiket fejezted már be stb.[br] + - Szavazhatsz a visual novellekre, melyek tetszettek, vagy ép meggyülölteték magukat[br] + - Bekapcsolódhatsz a fórumba levő beszélgetésekbe :_register_form_title en : New account ru : Новая учётная запись cs : Nový účet +hu : Új fiók :_register_username en : Username ru : Имя пользователя cs : Uživatelské jméno +hu : Felhasználónév :_register_username_msg en : Preferred username. Must be lowercase and can only consist of alphanumeric characters. ru : Запрашиваемое имя пользователя. Должно состоять из буквенно-цифровых символов в нижнем регистре. cs : Požadováné uživatelské jméno. Musí být malými písmeny a smí obsahovat pouze písmena a číslice. +hu : A kivánt felhasználónév. Múszáj kisbetűkkel legyen s csakis alfanumerikus karaktereket tartalmazhat. :_register_mail en : Email ru : E-mail cs : E-mail +hu : :_register_mail_msg en : Your email address will only be used in case you lose your password. We will never send @@ -3563,16 +4217,20 @@ ru : Адрес вашей электронной почты будет испо пришлём вам спама или новостных рассылок, пока вы недвусмысленно не попросите об обратном. cs : Vaše e-mailová adresa bude použita pouze v případě ztráty vašeho hesla. Nikdy vám nezašleme spam nebo newslettery, pokud o to explicitně nezažádáte. +hu : Az email címmed csakis akkor kerül használatba ha elveszted a jelszavad. Soha nem fogunk + spam vagy hírleveleket küldeni, csakis ha te azt kifejezeten kéred tőlünk. :_register_password en : Password ru : Пароль cs : Heslo +hu : Jelszó :_register_confirm en : Confirm password ru : Подтверждение пароля cs : Potvrdit heslo +hu : Jelszó megerősitése # User edit (/u+/edit) @@ -3581,86 +4239,103 @@ cs : Potvrdit heslo en : My account ru : Моя учётная запись cs : Můj účet +hu : Fiókom :_usere_saved_title en : Settings saved ru : Параметры сохранены cs : Nastavení uloženo +hu : Beállitások mentve :_usere_saved_msg en : Settings successfully saved. ru : Параметры успешно сохранены. cs : Nastavení úspěšně uloženo. +hu : Beállitások sikeresen mentve. :_usere_geninfo en : General info ru : Основная информация cs : Obecné informace +hu : Általános info :_usere_username en : Username ru : Имя пользователя cs : Uživatelské jméno +hu : Felhasználónév :_usere_rank en : Rank ru : Ранг cs : Postavení +hu : Rang :_usere_ignvotes en : Ignore votes in VN statistics ru : Игнорировать голосования в статистике новелл cs : Ignorovat hlasy ve statistikách vizuálních novel +hu : VN szavazatok figyelmen kivűl hagyása a statisztikákban :_usere_mail en : Email ru : E-mail cs : E-mail +hu : :_usere_changepass en : Change password ru : Смена пароля cs : Změnit heslo +hu : Jelszó megváltoztatása :_usere_changepass_msg en : Leave blank to keep your current password ru : Оставьте пустым чтобы сохранить текущий пароль cs : Zanechte prázdné pro zachování současného hesla +hu : Hagyd üresen ha a jelenlegi jelszavad meg akarod tartani :_usere_password en : Password ru : Пароль cs : Heslo +hu : Jelszó :_usere_confirm en : Confirm password ru : Подтверждение пароля cs : Potvrdit heslo +hu : Jelszó megerősitése :_usere_options en : Options ru : Настройки cs : Nastavení +hu : Beállitások :_usere_flist en : Allow other people to see my visual novel list ([url,_1,_1]) and wishlist ([url,_2,_2]) ru : Разрешить остальным видеть мой список новелл ([url,_1,_1]) и список желаемого ([url,_2,_2]) cs : Povolit ostatním zobrazit můj list vizuálních novel ([url,_1,_1]) a wishlist ([url,_2,_2]) +hu : Más embereknek megengedni, hogy lássák a visual novel listám ([url,_1,_1]) és a kivánságlistám ([url,_2,_2]) :_usere_fnsfw en : Disable warnings for images that are not safe for work. ru : Отключить предупреждения для небезопасных изображений. cs : Vypnout varování pro obrázky, které jsou "Not Safe For Work". +hu : Nem biztonságos képek előtti figyelmeztetés kikapcsolása. :_usere_skin en : Prefered skin ru : Предпочитаемая шкурка cs : Preferovaný skin +hu : Előnybe részesített stílus :_usere_css en : Additional [url,http://en.wikipedia.org/wiki/Cascading_Style_Sheets,CSS] ru : Дополнительный [url,http://en.wikipedia.org/wiki/Cascading_Style_Sheets,CSS] cs : Další [url,http://en.wikipedia.org/wiki/Cascading_Style_Sheets,CSS] +hu : Továbbiak [url,http://en.wikipedia.org/wiki/Cascading_Style_Sheets,CSS] # Users posts (/u+/posts) @@ -3669,21 +4344,25 @@ cs : Další [url,http://en.wikipedia.org/wiki/Cascading_Style_Sheets,CSS] en : Posts made by [_1] ru : Сообщения [_1] cs : Příspěvek od uživatele [_1] +hu : Hozzászólás [_1] által :_uposts_noresults en : [_1] hasn't made any posts yet. ru : [_1] пока не имеет сообщений. cs : [_1] ještě nenapsal žádný příspěvek. +hu : [_1] még nem szólt hozzá semmihez :_uposts_col_date en : Date ru : Дата cs : Datum +hu : Dátum :_uposts_col_title en : Title ru : Название cs : Název +hu : Cím # User list (/u/all) @@ -3692,31 +4371,37 @@ cs : Název en : Browse users ru : Обзор пользователей cs : Procházet uživatele +hu : Felhasználók böngészése :_ulist_col_username en : Username ru : Имя пользователя cs : Uživatelské jméno +hu : Felhasználónév :_ulist_col_registered en : Registered ru : Регистрация cs : Registrován +hu : Regisztrált :_ulist_col_votes en : Votes ru : Отдано голосов cs : Hlasy +hu : Szavazatok :_ulist_col_edits en : Edits ru : Правок cs : Editace +hu : Szerkesztések :_ulist_col_tags en : Tags ru : Тегов cs : Tagy +hu : Cimkék @@ -3736,106 +4421,127 @@ cs : Tagy en : Browse visual novels ru : Обзор новелл cs : Procházet vizuální novely +hu : Visual novellek böngészése :_vnbrowse_col_score en : Score ru : Рейтинг cs : Skóre +hu : Pontozás :_vnbrowse_col_title en : Title ru : Название cs : Název +hu : Cím :_vnbrowse_col_released en : Released ru : Выпуск cs : Vydáno +hu : Kiadva :_vnbrowse_col_popularity en : Popularity ru : Популярность cs : Popularita +hu : Népszerűség :_vnbrowse_tagign_title en : The following tags were ignored: ru : Следующие теги были пропущены: cs : Následující tagy byly ignorovány: +hu : Az allábi cimkék nem lettek figyelembe véve: :_vnbrowse_tagign_meta en : can't filter on meta tags ru : фильтрация мета-тегов невозможна cs : nedají se filtrovat meta tagy +hu : meta cimkéken nem működik a szűrő :_vnbrowse_tagign_notfound en : no such tag found ru : тег не найден cs : nenalezeny takové tagy +hu : nem található ilyen cimke :_vnbrowse_advsearch en : advanced search ru : расширенный поиск cs : pokročilé hledání +hu : bővített keresés :_vnbrowse_tags en : Tag filters ru : Фильтры тегов cs : Filtry tagů +hu : cimke szűrők :_vnbrowse_booland en : boolean and, selecting more gives less results ru : булевое 'и', чем больше выбрано, тем меньше даёт результатов cs : boolean a, výběr více dá méně výsledků +hu : Boole féle értékhalmaz(igaz/hamis), s ha többet választasz ki akkor kevesebb találatot ad :_vnbrowse_taginc en : Tags to include ru : Включить теги cs : Tagy k zahrnutí +hu : Cimkék beleszámítása :_vnbrowse_tagexc en : Tags to exclude ru : Исключить теги cs : Tagy k vyjmutí +hu : Cimkék kihagyása :_vnbrowse_spoil0 en : Hide spoilers ru : Скрыть спойлеры cs : Skrýt spoilery +hu : Spoilerek elrejtése :_vnbrowse_spoil1 en : Show minor spoilers ru : Показать лёгкие спойлеры cs : Ukázat menší spoilery +hu : Kisebb spoilerek megjelenítése :_vnbrowse_spoil2 en : Show major spoilers ru : Показать жёсткие спойлеры cs : Ukázat všechny spoilery +hu : Nagyobb spoilerek megjelenítése :_vnbrowse_lang en : Languages ru : Языки cs : Jazyky +hu : Nyelvek :_vnbrowse_boolor en : boolean or, selecting more gives more results ru : булевое 'или', чем больше выбрано, тем больше даёт результатов cs : boolean nebo, výběr více dá více výsledků +hu : Boole féle értékhalmaz(igaz/hamis), ha többet választasz ki akkor több találatot ad ki :_vnbrowse_plat en : Platforms ru : Платформы cs : Platformy +hu : Platformok :_vnbrowse_apply en : Apply ru : Применить cs : Použít +hu : Alkalmazás :_vnbrowse_clear en : Clear ru : Очистить cs : Začít znovu +hu : Törlés # VN add/edit form (/v+/edit) @@ -3844,36 +4550,43 @@ cs : Začít znovu en : Edit [_1] ru : Правка [_1] cs : Editovat vizuální novelu [_1] +hu : [_1] szerkesztése :_vnedit_title_add en : Add a new visual novel ru : Добавление новой новеллы cs : Přidat novou vizuální novelu +hu : Új visual novel hozzáadása :_vnedit_geninfo en : General info ru : Основная информация cs : Obecné informace +hu : Általános info :_vnedit_frm_title en : Title (romaji) ru : Название (ромадзи) cs : Název (romaji) +hu : Cím (romaji) :_vnedit_original en : Original title ru : Оригинальное название cs : Originální název +hu : Eredeti cím :_vnedit_original_msg en : The original title of this visual novel, leave blank if it already is in the Latin alphabet. ru : Оригинальное название данной новеллы, оставьте пустым если уже набрано в латинском алфавите. cs : Originální název této vizuální novely, ponechte prázdné, pokud již je latinkou. +hu : A visual novel eredeti címe, ha latin betűkkel van akkor ne írd be mégegyszer ide. :_vnedit_alias en : Aliases ru : Прочие названия cs : Aliasy +hu : Más nevek :_vnedit_alias_msg en : Comma separated list of alternative titles or abbreviations. Can include both official @@ -3885,11 +4598,15 @@ ru : Список альтернативных названий или аббр cs : Seznam alternativních názvů nebo zkratek, oddělených čárkou. Může zahrnovat oba (japonský/anglický) názvy a neoficiální názvy používané na internetu.[br] Názvy, vypsané ve vydáních by se sem přidávat neměly! +hu : Vesszővel elválasztott lista, más címmekel vagy röviditésekel. Tartalmazhat hivatalos + (japán/angol) címmeket vagy nem hivatalosokat amelyet a netten használnak.[br] + Azok a címmek amelyek a kiadásokba vannak ne tegyétek bele! :_vnedit_desc en : Description ru : Описание cs : Popis +hu : Leírás :_vnedit_desc_msg en : Short description of the main story. Please do not include spoilers, and don't forget to list @@ -3898,21 +4615,26 @@ ru : Краткое описание главной сюжетной линии. забывайте указать источник описания, если не являетесь его автором. (коды форматирования разрешены) cs : Krátký popis hlavního příběhu. Prosím nepište spoilery a nezapomeňte uvést zdroj, pokud jste popis nenapsali sami. (formátovací kódy jsou povoleny) +hu : A fő történet rövid leírása. Ne tartalmazzon spoilert és ha nem te írtad akkor ne felejtsd el + megemlítetni a forrást amit felhasználtál. (formázó kódok megengedettek) :_vnedit_length en : Length ru : Продолжительность cs : Délka +hu : Hossz :_vnedit_links en : External links ru : Внешние ссылки cs : Externí odkazy +hu : Külső linkek :_vnedit_anime en : Anime ru : Аниме cs : Anime +hu : :_vnedit_anime_msg en : Whitespace separated list of [url,http://anidb.net/,AniDB] anime IDs. @@ -3927,26 +4649,34 @@ cs : Seznam AnimeID z [url,http://anidb.net/,AniDB], oddělených mezerou. Např. "1015 3348" přidá [url,http://anidb.net/a1015,Shingetsutan Tsukihime] a [url,http://anidb.net/a3348,Fate/stay night] jako příbuzná anime.[br] Poznámka: Může trvat několik minut, než se názvy anime objeví na stránce vizuální novely. +hu : Szókőzzel elválasztot lista [url,http://anidb.net/,AniDB] anime ID-kal. + Pl. "1015 3348" belinkeli [url,http://anidb.net/a1015,Shingetsutan Tsukihime] + és [url,http://anidb.net/a3348,Fate/stay night] mint kapcsolodó animék.[br] + Figyelem: Beletelhet pár percbe míg az anime címmek megjelennek a VN oldalán. :_vnedit_image en : Image ru : Изображение cs : Obrázek +hu : Kép :_vnedit_image_none en : No image uploaded yet ru : Изображения пока нет cs : Obrázek ještě nebyl nahrán +hu : Még nincs kép feltöltve :_vnedit_image_processing en : ~[processing image, please return in a few minutes~] ru : ~[обработка изображения, пожалуйста подождите несколько минут~] cs : ~[obrázek se zpracovává, vraťte se prosím za několik minut~] +hu : ~[a kép feldolgozás alatt van, gyere vissza pár perc múlva~] :_vnedit_image_upload en : Upload new image ru : Загрузить новое изображение cs : Nahrát nový obrázek +hu : Tötls fel egy új képet :_vnedit_image_upload_msg en : Preferably the cover of the CD/DVD/package. Image must be in JPEG or PNG format @@ -3956,36 +4686,45 @@ ru : Желательно, обложка CD/DVD/коробки. Изображ будут автоматически уменьшены. cs : Pokud možno obálka CD/DVD/balení. Obrázek musí být ve formátu JPEG nebo PNG a ne větší 500kB. Obrázek větší než 256x400 pixelů bude automaticky zmenšen. +hu : Lehetőleg a CD/DVD/csomagolás borítóját. A képek muszáj JPEG vagy PNG formátúmba + legyenek és maximum 500kb nagyok. 254x400-nál nagyobb képek automatikusan át lesznek + méretezve. :_vnedit_image_nsfw en : NSFW ru : НБДР (NSFW) cs : NSFW +hu : Nem Biztonságos :_vnedit_image_nsfw_check en : Not Safe For Work ru : Не безопасно для работы cs : Not Safe For Work +hu : Nem biztonságos :_vnedit_image_nsfw_msg en : Please check this option if the image contains nudity, gore, or is otherwise not safe in a work-friendly environment. ru : Пожалуйста, поставьте эту галочку если изображение содержит наготу, кровищу, либо тем или иным образом не безопасно для рабочего окружения. cs : Prosíme, zaškrtněte tuto možnost, pokud obrázek obsahuje nahotu, gore nebo je jinak nevhodný pro pracovní prostředí. +hu : Kérlek pipáld ezt be ha a kép tartalmaz meztelenséget, vért vagy más módon nem szalon képes dolgokat. :_vnedit_rel en : Relations ru : Связи cs : Vztahy +hu : Összefüggések :_vnedit_rel_sel en : Selected relations ru : Выбранные связи cs : Vybrané vztahy +hu : Kiválasztot összefüggések :_vnedit_rel_add en : Add relation ru : Добавить связь cs : Přidat vztah +hu : Összefüggés hozzáadása # <title1> is a <relation> of <title2> # this trick doesn't even work very well in English, so just an approximation is fine @@ -3993,46 +4732,55 @@ cs : Přidat vztah en : is a ru*: cs*: +hu*: :_vnedit_rel_of en : of ru*: cs*: +hu*: :_vnedit_rel_addbut en : add ru*: cs*: +hu*: :_vnedit_rel_del en : del ru*: cs*: +hu*: :_vnedit_rel_none en : No relations selected. ru*: cs*: +hu*: :_vnedit_rel_findformat en : Visual novel textbox must start with an ID (e.g. v17) ru*: cs*: +hu*: :_vnedit_rel_novn en : Visual novel not found! ru*: cs*: +hu*: :_vnedit_rel_double en : This visual novel has already been selected! ru*: cs*: +hu*: :_vnedit_scr en : Screenshots ru : Скриншоты cs : Screenshoty +hu : Pillanatképek :_vnedit_scrmsg en : Please keep the following in mind when uploading screenshots:[br] @@ -4053,87 +4801,109 @@ cs : Prosíme, pamatujte na následující věci, pokud nahráváte screenshoty: - Nenahrávejte pouze CG.[br] Prosíme, přečtěte si [url,/d2#6,doporučení] pro více informací.[br] Ujistěte se, že jste potvrdili odeslání informací poté, co nahrajete obrázky! +hu : Mielőtt pillanatképeket töltesz fel, tarts néhány dolgot figyelembe:[br] + - A pillanatképek a játék eredeti felbontásába kell legyenek,[br] + - Távolits el bármilyen ablak szélet és vigyázz, hogy a képen ne legyenek jelölések,[br] + - Ne csak esemény CG-ket tölts fel.[br] + Legyél szives és olvasd el az [url,/d2#6,útmutatókat] több információért.[br] + A feltöltés útán ne felejtsd beküldeni a formulát! :_vnedit_scr_selrel en : -- select release -- ru*: cs*: +hu*: :_vnedit_scr_frmloading en : Please wait for the screenshots to be uploaded before submitting the form. ru*: cs*: +hu*: :_vnedit_scr_frmnorel en : Please select the appropriate release for every screenshot. ru*: cs*: +hu*: :_vnedit_scr_fetching en : Fetching thumbnail... ru*: cs*: +hu*: :_vnedit_scr_uploading en : Uploading screenshot ru*: cs*: +hu*: :_vnedit_scr_upl_msg en : This can take a while, depending on the file size and your upload speed. ru*: cs*: +hu*: :_vnedit_scr_cancel en : cancel ru*: cs*: +hu*: :_vnedit_scr_full en : Enough screenshots ru*: cs*: +hu*: :_vnedit_scr_full_msg en : The limit of 10 screenshots per visual novel has been reached. If you want to add a new screenshot, please remove an existing one first. ru*: cs*: +hu*: :_vnedit_scr_add en : Add screenshot ru*: cs*: +hu*: :_vnedit_scr_imgnote en : Image must be smaller than 5MB and in PNG or JPEG format. ru*: cs*: +hu*: :_vnedit_scr_addbut en : Upload! ru*: cs*: +hu*: :_vnedit_scr_id en : Screenshot #[_1] ru*: cs*: +hu*: :_vnedit_scr_remove en : remove ru*: cs*: +hu*: :_vnedit_scr_fullsize en : Full size: [_1] ru*: cs*: +hu*: :_vnedit_scr_nsfw en : This screenshot is NSFW ru*: cs*: +hu*: :_vnedit_scr_oops en : Oops! Seems like something went wrong... @@ -4141,29 +4911,34 @@ en : Oops! Seems like something went wrong... If that isn't the problem, then please report a bug. ru*: cs*: +hu*: :_vnedit_scr_errformat en : Upload failed! Only JPEG or PNG images are accepted. ru*: cs*: +hu*: :_vnedit_scr_errempty en : Upload failed! No file selected, or an empty file? ru*: cs*: +hu*: :_vnedit_scr_genthumb en : Generating thumbnail... ru*: cs*: +hu*: :_vnedit_scr_genthumb_msg en : Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. Please try again later or report a bug if that is the case. ru*: cs*: +hu*: # VN Relation graph page (/v+/rg) @@ -4172,16 +4947,19 @@ cs*: en : Relation graph for [_1] ru : Схема связей для [_1] cs : Graf vztahů pro vizuální novelu [_1] +hu : Összefüggés gráf [_1]-hoz :_vnrg_notsupp en : Not supported ru*: cs*: +hu*: :_vnrg_notsupp_msg en : Your browser sucks, it doesn't have the functionality to render our nice relation graphs. ru*: cs*: +hu*: # VN Diff viewer (/v+.+) @@ -4190,106 +4968,127 @@ cs*: en : Title (romaji) ru : Название (ромадзи) cs : Název (romaji) +hu : Cím (romaji) :_revfield_v_original en : Original title ru : Оригинальное название cs : Originální název +hu : Eredeti cím :_revfield_v_alias en : Alias ru : Прочие названия cs : Alias +hu : Más nevek :_revfield_v_desc en : Description ru : Описание cs : Popis +hu : Leírás :_revfield_v_length en : Length ru : Продолжительность cs : Délka +hu : Hossz :_vndiff_nolink en : ~[no link~] ru : ~[нет ссылки~] cs : ~[žádný odkaz~] +hu : ~[nincs link~] :_vndiff_none en : ~[none~] ru : ~[пусто~] cs : ~[nic~] +hu : ~[nincs~] :_revfield_v_l_wp en : Wikipedia link ru : Ссылка Википедии cs : Link na Wikipedii +hu : :_revfield_v_l_encubed en : Encubed tag ru : Тег Encubed'а cs : Tag na Encubed +hu : Encubed cimke :_revfield_v_l_renai en : Renai.us link ru : Ссылка Renai.us cs : Odkaz na Renai.us +hu : :_revfield_v_l_vnn en : V-N.net link ru : Ссылка V-N.net cs : Odkaz na V-N.net +hu : :_revfield_v_relations en : Relations ru : Связи cs : Vztahy +hu : Kapcsolatok :_revfield_v_anime en : Anime ru : Аниме cs : Anime +hu : :_revfield_v_screenshots en : Screenshots ru : Скриншоты cs : Screenshoty +hu : Pillanatképek :_revfield_v_image en : Image ru : Изображение cs : Obrázek +hu : Kép :_vndiff_image_nsfw en : (NSFW) ru : (НБДР|NSFW) cs : (NSFW) +hu : (NB) :_vndiff_image_proc en : ~[processing~] ru : ~[обработка~] cs : ~[zpracovává se~] +hu : ~[feldolgozás~] :_vndiff_image_none en : No image ru : Нет изображения cs : Obrázek není +hu : Nincs kép :_revfield_v_img_nsfw en : Image NSFW ru : Изображение НБДР (NSFW) cs : Vhodnost obrázku +hu : A kép nem biztonságos :_vndiff_nsfw_safe en : Safe ru : Безопасно cs : SFW +hu : Biztonságos :_vndiff_nsfw_notsafe en : Not safe ru : Не безопасно cs : NSFW +hu : Nem biztonságos # VN page (/v+) @@ -4298,273 +5097,327 @@ cs : NSFW en : No image uploaded yet ru : Нет загруженного изображения cs : Ještě nebyl nahrán žádný obrázek +hu : Még nincs kép feltöltve :_vnpage_imgproc en : ~[processing image, please return in a few minutes~] ru : ~[идёт обработка изображения, подождите несколько минут~] cs : ~[obrázek se zpracovává, prosíme, vraťte se za několik minut~] +hu : ~[a kép feldolgozás alatt van, gyere vissza pár perc múlva~] :_vnpage_imgnsfw_msg en : This image has been flagged as Not Safe For Work. ru : Данное изображение помечено как не безопасное для работы. cs : Tento obrázek byl označen jako "Not Safe For Work" +hu : Ezt a képet Nem Biztonságosnak nyilvánitották. :_vnpage_imgnsfw_show en : Show me anyway ru : Всё равно показать cs : Ukázat i přes to +hu : Mutasd meg akkor is :_vnpage_imgnsfw_note en : (This warning can be disabled in your account) ru : (Это предупреждение можно отключить в настройках вашей учётной записи) cs : (Toto varování může být vypnuto ve vašem nastavení) +hu : (Ezt a figyelmeztetést ki lehet kapcsolni a profilodba) :_vnpage_imgnsfw_foot en : Flagged as NSFW ru : Помечено как НБДР (NSFW) cs : Označeno jako NSFW +hu : Nem biztonságosnak van bejelölve :_vnpage_vntitle en : Title ru : Название cs : Název +hu : Cím :_vnpage_original en : Original title ru : Оригинальное название cs : Originální název +hu : Eredeti cím :_vnpage_alias en : Aliases ru : Прочие названия cs : Aliasy +hu : Más nevek :_vnpage_length en : Length ru : Продолжительность cs : Délka +hu : Hossz :_vnpage_links en : Links ru : Ссылки cs : Odkazy +hu : Linkek :_vnpage_description en : Description ru : Описание cs : Popis +hu : Leírás :_vnpage_tags_spoil0 en : hide spoilers ru : скрыть спойлеры cs : skrýt spoilery +hu : spoilerek elrejtése :_vnpage_tags_spoil1 en : show minor spoilers ru : показать лёгкие спойлеры cs : ukázat menší spoilery +hu : kisebb spoilerek megjelenítése :_vnpage_tags_spoil2 en : spoil me! ru : показать все! cs : prozraď mi vše! +hu : rontsd el nekem! :_vnpage_tags_summary en : summary ru : суммарно cs : shrnutí +hu : összefoglalás :_vnpage_tags_all en : all ru : все cs : vše +hu : mind :_vnpage_developer en : Developer ru*: cs*: +hu*: :_vnpage_publisher en : Publishers ru*: cs*: +hu*: :_vnpage_relations en : Relations ru : Связи cs : Vztahy +hu : Összefüggések :_vnpage_anime en : Related anime ru : Связанное аниме cs : Příbuzná anime +hu : Kapcsolódó animék :_vnpage_anime_noinfo en : ~[no information available at this time: [url,_2,_1]~] ru : ~[к сожалению, пока никакой информации: [url,_2,_1]~] cs : ~[nyní nejsou dostupné žádné informace: [url,_2,_1]~] +hu : ~[jelenleg nincs semmilyen információÉ [url,_2,_1]~] :_vnpage_uopt en : User options ru : Настройки пользователя cs : Možnosti uživatele +hu : Felhasználó beállítások :_vnpage_uopt_voted en : your vote: [_1] ru : ваш голос: [_1] cs : váš hlas: [_1] +hu : szavazatod: [_1] :_vnpage_uopt_novote en : not voted yet ru : пока без голоса cs : ještě nehlasováno +hu : még nem kapott szavazatot :_vnpage_uopt_changevote en : Change vote ru : Переголосовать cs : Změnit hlas +hu : Szavazat megváltoztatássa :_vnpage_uopt_dovote en : Vote ru : Голосовать cs : Hlasovat +hu : Szavazás :_vnpage_uopt_delvote en : revoke ru : снять голос cs : zdržet se +hu : visszavonás :_vnpage_uopt_1vote en : You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played. Are you really sure this visual novel matches that description? ru*: cs*: +hu*: :_vnpage_uopt_10vote en : You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, meaning this is one of the best visual novels you've ever played and it's unlikely that any other game could ever be better than this one. It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully! ru*: cs*: +hu*: :_vnpage_uopt_wishlisted en : wishlist: [_1] ru : список желаемого: [_1] cs : wishlist: [_1] +hu : Kivánságlista: [_1] :_vnpage_uopt_nowish en : not on your wishlist ru : не в вашем списке cs : není na vašem wishlistu +hu : nincs benne a kivánságlistádba :_vnpage_uopt_changewish en : Change status ru : Сменить статус cs : Změnit status +hu : Állapot megváltoztatássa :_vnpage_uopt_addwish en : Add to wishlist ru : Добавить к списку cs : Přidat na wishlist +hu : Hozzáadás a kivánságlistdhoz :_vnpage_uopt_delwish en : remove from wishlist ru : убрать из списка cs : odstranit z wishlistu +hu : eltávolitás a kivánságlistából :_vnpage_uopt_relrstat en : Release status ru*: cs*: +hu*: :_vnpage_uopt_relvstat en : Play status ru*: cs*: +hu*: :_vnpage_uopt_reldel en : Remove from VN list ru*: cs*: +hu*: :_vnpage_rel en : Releases ru : Выпуски cs : Vydání +hu : Kiadások :_vnpage_rel_none en : We don't have any information about releases of this visual novel yet... ru : У нас пока нет информации о выпусках этой новеллы... cs : K této vizuální novele zatím nemáme informace o žádném vydání... +hu : Még nincs információnk ennek a visual novelnek a kiadásairól... :_vnpage_rel_add en : add release ru : добавить выпуск cs : přidat vydání +hu : kiadás hozzáadása :_vnpage_rel_patch en : (patch) ru : (патч) cs : (patch) +hu : :_vnpage_rel_extlink en : External link ru : Внешняя ссылка cs : Externí odkaz +hu : Külső link :_vnpage_scr en : Screenshots ru : Скриншоты cs : Screenshoty +hu : Pillanatképek :_vnpage_scr_showing en : Showing [_1] out of [_2] [quant,_2,screenshot,screenshots]. ru : [_1] из [_2] [quant,_2,скриншота,скриншотов,скриншотов] отображено. cs : Ukazuji screenshot [_1] z celkém [_2] [quant,_2,screenshotu,screenshotů,screenshotů]. +hu : [_1] megjelenitve a [_2] [quant,_2,pillanatkép,pillanatképekből]. :_vnpage_scr_nsfwhide en : show/hide NSFW ru : показать/скрыть НБДР (NSFW) cs : skrýt/zobrazit NSFW +hu : megjelenít/elrejt NB :_vnpage_scr_num en : Screenshot #[_1] ru : Скриншот #[_1] cs : Screenshot #[_1] +hu : Pillanatkép #[_1] :_vnpage_stats en : User stats ru : Статистика пользователей cs : Statistiky uživatelů +hu : Felhasználó adatok :_vnpage_stats_none en : Nobody has voted on this visual novel yet... ru : Никто пока не голосовал за эту новеллу... cs : Pro tuto vizuální novelu ještě nikdo nehlasoval... +hu : Még senki nem szavazot erre a visual novelre... :_votestats_title en : Vote stats ru : Статистика голосования cs : Statistika hlasování +hu : Szavazási adatok :_votestats_sum en : [_1] [quant,_1,vote,votes] total, average [_2] ru : Всего [_1] [quant,_1,голос,голоса,голосов], в среднем [_2] cs : Celkem [_1] [quant,_1,hlas,hlasy,hlasů], průměr [_2] +hu : [_1] [quant,_1,szavazat,szavazatok] összesen, átlagba [_2] :_votestats_recent en : Recent votes ru : Недавно проголосовали cs : Poslední hlasy +hu : Legútóbbi szavazatok :_votestats_pop_title en : Popularity ru : Популярность cs : Popularita +hu : Népszerűsség :_votestats_pop_sum en : Ranked #[_1] out of [_2] with a score of [_3]. ru : Рейтинг - #[_1] из [_2], средний балл - [_3]. cs : Hodnoceno na [_1]. místě z celkem [_2] se skóre [_3]. +hu : [_1]. helyezet a [_2] bejegyzésből [_3] pontszámmal. @@ -4582,28 +5435,33 @@ cs : Hodnoceno na [_1]. místě z celkem [_2] se skóre [_3]. en : Access Denied ru : В доступе отказано cs : Přístup odepřen +hu : Belépés megtagadva # not logged in :_denied_needlogin_title en : You need to be logged in to perform this action. ru : Для выполнения этого действия требуется авторизация. cs : Pro vykonání této akce se musíte přihlásit. +hu : Be kell legyél jelentkezve ha ezt akarod csinálni. :_denied_needlogin_msg en : Please [url,/u/login,login], or [url,/u/register,create an account] if you don't have one yet. ru : Пожалуйста [url,/u/login,авторизуйтесь], либо [url,/u/register,создайте учётную запись], если таковой у вас нет. cs : Prosíme, [url,/u/login,přihlašte se], nebo si [url,/u/register,vytvořte účet], pokud ještě žádný nemáte. +hu : Kérlek [url,/u/login,lépj be] vagy [url,/u/register,készíts egy fiókot] ha még nem volna. # logged in, but simply no access :_denied_noaccess_title en : You are not allowed to perform this action. ru : Вам запрещено выполнять это действие. cs : Nemáte oprávnění provést tuto akci. +hu : Ezt a műveletet nem hajthatod végre. :_denied_noaccess_msg en : It seems you don't have the proper rights to perform the action you wanted to perform... ru : Похоже, у вас нет прав на выполнение того, чего вы хотите... cs : Zdá se, že nemáte potřebná práva pro vykonání akce, kterou chcete provést... +hu : Úgy tűnik, hogy nem rendelkezzel megfelelő jogokkal, hogy elvégezd azt a műveletet amit szerettél volna... # "DB Item has been deleted" page @@ -4612,6 +5470,7 @@ cs : Zdá se, že nemáte potřebná práva pro vykonání akce, kterou chcete p en : Item deleted ru : Запись удалена cs : Položka smazána +hu : Tárgy törölve :_hiddenmsg_msg en : This item has been deleted from the database, File a request on the @@ -4620,6 +5479,8 @@ ru : Данная запись удалена из базы данных. Пож [url,_1,форуме] для восстановления этой страницы. cs : Tato položka byla smazána z databáze. Pro obnovení této stránky napište žádost na [url,_1,diskusní board]. +hu : Ez a bejegyzés ki lett törölve az adatbázisból. Nyújtsd be egy kérvényt a + [url,_1,forumon], hogy állítsák vissza ezt az oldalt. # The warning/notice messages on edit pages @@ -4628,6 +5489,7 @@ cs : Tato položka byla smazána z databáze. Pro obnovení této stránky napi en : You're not editing a release! ru : Вы не редактируете выпуск, а копируете его! cs : Needitujete vydání! +hu : Te most nem szerkesztesz egy kiadást! :_editmsg_copy_msg en : You're about to insert a new release into the database with information based on [_1].[br] @@ -4636,36 +5498,44 @@ ru : Вы собираетесь вставить новый выпуск, ос Щёлкните вкладку 'правка' в правом верхнем углу, если собирались редактировать выпуск, а не создавать новый. cs : Chystáte se vložit nové vydání do databáze s informacemi založenými na vydání [_1].[br] Pokud chcete editovat vydání místo toho, abyste vložili další vydání, přejděte na záložku 'editovat' v pravém horním rohu. +hu : Te most ép arra készülsz, hogy egy új kiadást hozzál létre az adatbázisban, [_1]-ra alapozva az információkat.[br] + Klikelj a 'szerkesztés' fűlre a jobb felső sarokba ha egy új kiadás helyet, csak szerkeszteni akartad a meglévőt. :_editmsg_msg_title en : Before editing: ru : Прежде чем приступить к редактированию: cs : Před editací: +hu : Szerkesztés előtt: :_editmsg_msg_guidelines en : Read the [url,_1,guidelines]! ru : Прочтите [url,_1,рекомендации]! cs : Přečtěte si [url,_1,doporučení]! +hu : Olvasdd el az [url,_1,útmutatokat]! :_editmsg_msg_discuss en : Check for any existing discussions on the [url,_1,discussion board] ru : Проверьте все существующие темы на [url,_1,форуме] cs : Podívejte se do existujících diskusí na [url,_1,diskusním boardu] +hu : Keress bármilyen meglévő beszélgetésre a [url,_1,fórumon] :_editmsg_msg_history en : Browse the [url,_1,edit history] for any recent changes related to what you want to change. ru : Просмотрите [url,_1,историю правок] на предмет недавних изменений данных, которые вы хотите изменить. cs : Projděte [url,_1,historii editací] pro nedávné změny týkající se změn, které se chystáte provést. +hu : Nézz bele a [url,_1,szerkesztési előzményekbe], hogy lásd milyen változtatások voltak mielőtt te is megváltoztatnál valamit. :_editmsg_msg_search en : [url,_1,Search the database] to see if we already have information about this [index,_2,visual novel,release,producer]. ru : [url,_1,Воспользуйтесь поиском], ведь вполне возможно что у нас уже есть информация об [index,_2,этой новелле,этом выпуске,этой компании]. cs : [url,_1,Prohledejte databázi], zda již nemáme informaci o [index,_2,této vizuální novele,tomto vydání,tomto producentovi]. +hu : [url,_1,Nézd át az adatbázist], hogy van-e már információ erről a [index,_2,visual novelről, kiadásról, készítőről]. :_editmsg_revert_title en : Reverting ru : Восстановление cs : Vracení +hu : Visszaállítás :_editmsg_revert_msg en : You are editing an old revision of this [index,_1,visual novel,release,producer]. @@ -4674,6 +5544,8 @@ ru : Вы правите старую редакцию страницы [index,_ Если вы сохраните её, все изменения сделанные после этой правки будут утеряны! cs : Editujete starší verzi [index,_1,této vizuální novely,tohoto vydání,tohoto producenta]. Pokud ji uložíte, všechny změny provedené po této revizi budou vráceny! +hu : Te egy régi átjavítását szerkeszted ennek a [index,_1,visual novelnek, kiadásnak, készítőnek]. + Ha lemented, akkor minden szerkesztés amit ezután a javítás után végeztek megsemmisül! # Messages about editing on the VN/Release/Producer pages (right beneath the tabs) @@ -4682,16 +5554,19 @@ cs : Editujete starší verzi [index,_1,této vizuální novely,tohoto vydání, en : Locked for editing ru : Правка заблокирована cs : Zamčeno pro editaci +hu : Lezárva :_itemmsg_login en : You need to be [url,_1,logged in] to edit this page ru : Чтобы редактировать эту страницу, вы должны быть [url,_1,авторизованы] cs : Pro editaci této stránky musíte být [url,_1,přihlášen] +hu : Be kell legyél [url,_1, jelentkezve], hogy szerkeszthesd ezt az oldalt :_itemmsg_denied en : You are not allowed to edit this page ru : Вам запрещено редактировать эту страницу cs : Nemáte oprávnění editovat tuto stránku +hu : Nincs engedélyed, hogy szerkesd ezt az oldalt # User didn't pass the spam protection @@ -4700,16 +5575,19 @@ cs : Nemáte oprávnění editovat tuto stránku en : Could not send form ru : Невозможно отправить форму cs : Formulář nemohl být odeslán +hu : Nem lehetet elküldeni a formulát :_nospam_subtitle en : Error ru : Ошибка cs : Chyba +hu : Hiba :_nospam_msg en : The form could not be sent, please make sure you have Javascript enabled in your browser. ru : Не удалось отправить форму, пожалуйста убедитесь что в вашем браузере включён Javascript. cs : Formulář nemohl být odeslán, ujistěte se, že máte ve svém prohlížeči povolen Javascript. +hu : A formulát nem lehetet elküldeni, kérlek ellenőrizd, hogy engedélyezve van a Javascript a böngésződbe. # Short message reminding the user to post in ENGLISH (Used at about every message/description input field) @@ -4718,5 +5596,6 @@ cs : Formulář nemohl být odeslán, ujistěte se, že máte ve svém prohlíž en : English please! ru : Пожалуйста, пишите на английском! cs : Prosíme, anglicky! +hu : Kérlek angolul válaszolj! -- cgit v1.2.3 From f1c2df3d3e8761f6095ad7612a3d7b87354a7a44 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 10:56:56 +0200 Subject: JS: Ignore language flag onclick, and fixed bug when lang TL is unavailable --- data/script.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/data/script.js b/data/script.js index 67ae8953..a6600f9f 100644 --- a/data/script.js +++ b/data/script.js @@ -1761,19 +1761,22 @@ if(byId('advselect') && byId('ti')) { } // Language selector -if(byId('lang_select')) - ddInit(byId('lang_select'), 'bottom', function(lnk) { +if(byId('lang_select')) { + var d = byId('lang_select'); + ddInit(d, 'bottom', function(lnk) { var lst = tag('ul', null); for(var i=0; i<L10N_LANG.length; i++) { var ln = L10N_LANG[i]; var icon = tag('acronym', {'class':'icons lang '+ln}, ' '); lst.appendChild(tag('li', {'class':'lang_selector'}, mt_curlang == ln ? tag('i', icon, mt('_lang_'+ln)) - : tag('a', {href:'?l10n='+ln}, icon, L10N_STR['_lang_'+ln][ln]) + : tag('a', {href:'?l10n='+ln}, icon, L10N_STR['_lang_'+ln][ln]||mt('_lang_'+ln)) )); } return lst; }); + d.onclick = function() {return false}; +} // spam protection on all forms setTimeout(function() { -- cgit v1.2.3 From 815ed4023dea8c3a4168bc6826a7e9515631dab8 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 10:58:04 +0200 Subject: JS: Improved dependency checking when determining whether to run jsgen.pl --- util/vndb.pl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/util/vndb.pl b/util/vndb.pl index f3c3036c..4752c274 100755 --- a/util/vndb.pl +++ b/util/vndb.pl @@ -123,6 +123,12 @@ sub checkjs { my $lastmod = [stat $script]->[9]; system "$ROOT/util/jsgen.pl" if (!-e $script && -x "$ROOT/static/f") - || (-e $script && -w $script && $lastmod < [stat "$ROOT/data/script.js"]->[9] || $lastmod < [stat "$ROOT/data/lang.txt"]->[9]); + || (-e $script && -w $script && ( + $lastmod < [stat "$ROOT/data/script.js"]->[9] + || $lastmod < [stat "$ROOT/data/lang.txt"]->[9] + || (-e "$ROOT/data/config.pl" && $lastmod < [stat "$ROOT/data/config.pl"]->[9]) + || $lastmod < [stat "$ROOT/data/global.pl"]->[9] + || $lastmod < [stat "$ROOT/util/jsgen.pl"]->[9] + )); } -- cgit v1.2.3 From 06a2e823c738a622625dce599fa19580714834a5 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 11:30:24 +0200 Subject: Started on the producer relations The current list of relations isn't final yet, may be changed later on. Quite a bit of this code has been copied from the VN relations... need to find a way to use prober code reuse here. TODO: - Nice relation editor interface - Display relations in revision browser - Display relations on producer pages - Generate relation graphs - Sync update_2.8.sql into dump.sql --- ChangeLog | 1 + data/global.pl | 8 +++++ data/lang.txt | 6 ++++ lib/VNDB/DB/Producers.pm | 28 +++++++++++++-- lib/VNDB/Handler/Producers.pm | 80 ++++++++++++++++++++++++++++++++++++------- util/updates/update_2.8.sql | 16 +++++++++ 6 files changed, 123 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4593180a..444f710c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,7 @@ git - ? - Fixed bug with unhiding a producer entry - Set 'no spoilers' as default spoiler level for tags - Added Czech and Hungarian interface translation + - Producer relations 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/data/global.pl b/data/global.pl index b1d4b031..a807c9ca 100644 --- a/data/global.pl +++ b/data/global.pl @@ -49,6 +49,14 @@ our %S = (%S, fan => [ 8, 'orig' ], orig => [ 9, 'fan' ], }, + prod_relations => { + 'old' => [ 0, 'new' ], + 'new' => [ 1, 'old' ], + 'par' => [ 2, 'sub' ], + 'sub' => [ 3, 'par' ], + 'imp' => [ 4, 'ipa' ], + 'ipa' => [ 5, 'imp' ], + }, age_ratings => { -1 => [ 'Unknown' ], 0 => [ 'All ages' ,'CERO A' ], diff --git a/data/lang.txt b/data/lang.txt index a6ce7082..ef5f641e 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -2239,6 +2239,12 @@ ru : Описание cs : Popis hu : Leírás +:_pedit_form_rel +en : Relations +ru*: +cs*: +hu*: + # Browse/search producers diff --git a/lib/VNDB/DB/Producers.pm b/lib/VNDB/DB/Producers.pm index afc21492..c28d12d7 100644 --- a/lib/VNDB/DB/Producers.pm +++ b/lib/VNDB/DB/Producers.pm @@ -9,7 +9,7 @@ our @EXPORT = qw|dbProducerGet dbProducerEdit dbProducerAdd|; # options: results, page, id, search, char, rev -# what: extended, changes, vn +# what: extended, changes, vn, relations sub dbProducerGet { my $self = shift; my %o = ( @@ -41,7 +41,7 @@ sub dbProducerGet { push @join, 'JOIN changes c ON c.id = pr.id' if $o{what} =~ /changes/ || $o{rev}; push @join, 'JOIN users u ON u.id = c.requester' if $o{what} =~ /changes/; - my $select = 'p.id, pr.type, pr.name, pr.original, pr.lang'; + my $select = 'p.id, pr.type, pr.name, pr.original, pr.lang, pr.id AS cid'; $select .= ', pr.desc, pr.alias, pr.website, p.hidden, p.locked' if $o{what} =~ /extended/; $select .= q|, extract('epoch' from c.added) as added, c.requester, c.comments, p.latest, pr.id AS cid, u.username, c.rev| if $o{what} =~ /changes/; @@ -78,6 +78,22 @@ sub dbProducerGet { )}); } + if(@$r && $o{what} =~ /relations/) { + my %r = map { + $r->[$_]{relations} = []; + ($r->[$_]{cid}, $_) + } 0..$#$r; + + push @{$r->[$r{$_->{pid1}}]{relations}}, $_ for(@{$self->dbAll(q| + SELECT rel.pid1, rel.pid2 AS id, rel.relation, pr.name, pr.original + FROM producers_relations rel + JOIN producers p ON rel.pid2 = p.id + JOIN producers_rev pr ON p.latest = pr.id + WHERE rel.pid1 IN(!l)|, + [ keys %r ] + )}); + } + return wantarray ? ($r, $np) : $r; } @@ -103,7 +119,7 @@ sub dbProducerAdd { # helper function, inserts a producer revision -# Arguments: global revision, item id, { columns in producers_rev } +# Arguments: global revision, item id, { columns in producers_rev }, relations sub insert_rev { my($self, $cid, $pid, $o) = @_; $self->dbExec(q| @@ -111,6 +127,12 @@ sub insert_rev { VALUES (!l)|, [ $cid, $pid, @$o{qw| name original website type lang desc alias|} ] ); + + $self->dbExec(q| + INSERT INTO producers_relations (pid1, pid2, relation) + VALUES (?, ?, ?)|, + $cid, $_->[1], $_->[0] + ) for (@{$o->{relations}}); } diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm index 241ff00c..2a3991ba 100644 --- a/lib/VNDB/Handler/Producers.pm +++ b/lib/VNDB/Handler/Producers.pm @@ -91,36 +91,55 @@ sub page { sub edit { my($self, $pid, $rev) = @_; - my $p = $pid && $self->dbProducerGet(id => $pid, what => 'changes extended', $rev ? (rev => $rev) : ())->[0]; + my $p = $pid && $self->dbProducerGet(id => $pid, what => 'changes extended relations', $rev ? (rev => $rev) : ())->[0]; return 404 if $pid && !$p->{id}; $rev = undef if !$p || $p->{cid} == $p->{latest}; return $self->htmlDenied if !$self->authCan('edit') || $pid && ($p->{locked} && !$self->authCan('lock') || $p->{hidden} && !$self->authCan('del')); - my %b4 = !$pid ? () : map { $_ => $p->{$_} } qw|type name original lang website desc alias|; + my %b4 = !$pid ? () : ( + (map { $_ => $p->{$_} } qw|type name original lang website desc alias|), + prodrelations => join('|||', map $_->{relation}.','.$_->{id}.','.$_->{name}, sort { $a->{id} <=> $b->{id} } @{$p->{relations}}), + ); my $frm; if($self->reqMethod eq 'POST') { $frm = $self->formValidate( - { name => 'type', enum => $self->{producer_types} }, - { name => 'name', maxlength => 200 }, - { name => 'original', required => 0, maxlength => 200, default => '' }, - { name => 'alias', required => 0, maxlength => 500, default => '' }, - { name => 'lang', enum => $self->{languages} }, - { name => 'website', required => 0, template => 'url', default => '' }, - { name => 'desc', required => 0, maxlength => 5000, default => '' }, - { name => 'editsum', maxlength => 5000 }, + { name => 'type', enum => $self->{producer_types} }, + { name => 'name', maxlength => 200 }, + { name => 'original', required => 0, maxlength => 200, default => '' }, + { name => 'alias', required => 0, maxlength => 500, default => '' }, + { name => 'lang', enum => $self->{languages} }, + { name => 'website', required => 0, template => 'url', default => '' }, + { name => 'desc', required => 0, maxlength => 5000, default => '' }, + { name => 'prodrelations', required => 0, maxlength => 5000, default => '' }, + { name => 'editsum', maxlength => 5000 }, ); if(!$frm->{_err}) { + # parse + my $relations = [ map { /^([a-z]+),([0-9]+),(.+)$/ && (!$pid || $2 != $pid) ? [ $1, $2, $3 ] : () } split /\|\|\|/, $frm->{prodrelations} ]; + + # normalize + $frm->{prodrelations} = join '|||', map $_->[0].','.$_->[1].','.$_->[2], sort { $a->[1] <=> $b->[1]} @{$relations}; + return $self->resRedirect("/p$pid", 'post') if $pid && !grep $frm->{$_} ne $b4{$_}, keys %b4; + $frm->{relations} = $relations; $rev = 1; + my $cid; if($pid) { - ($rev) = $self->dbProducerEdit($pid, %$frm); + ($rev, $cid) = $self->dbProducerEdit($pid, %$frm); } else { - ($pid) = $self->dbProducerAdd(%$frm); + ($pid, $cid) = $self->dbProducerAdd(%$frm); + } + + # update reverse relations + if(!$pid && $#$relations >= 0 || $pid && $frm->{prodrelations} ne $b4{prodrelations}) { + my %old = $pid ? (map { $_->{id} => $_->{relation} } @{$p->{relations}}) : (); + my %new = map { $_->[1] => $_->[0] } @$relations; + _updreverse($self, \%old, \%new, $pid, $cid, $rev); } return $self->resRedirect("/p$pid.$rev", 'post'); @@ -135,7 +154,8 @@ sub edit { $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'), + $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', options => [ map [ $_, mt "_ptype_$_" ], sort @{$self->{producer_types}} ] ], [ input => name => mt('_pedit_form_name'), short => 'name' ], @@ -147,10 +167,44 @@ sub edit { options => [ map [ $_, "$_ (".mt("_lang_$_").')' ], sort @{$self->{languages}} ] ], [ input => name => mt('_pedit_form_website'), short => 'website' ], [ text => name => mt('_pedit_form_desc').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'desc', rows => 6 ], + ], 'pedit_rel' => [ mt('_pedit_form_rel'), + [ textarea => short => 'prodrelations' ], ]); $self->htmlFooter; } +# !IMPORTANT!: Don't forget to update this function when +# adding/removing fields to/from producer entries! +sub _updreverse { + my($self, $old, $new, $pid, $cid, $rev) = @_; + my %upd; + + # compare %old and %new + for (keys %$old, keys %$new) { + if(exists $$old{$_} and !exists $$new{$_}) { + $upd{$_} = undef; + } elsif((!exists $$old{$_} and exists $$new{$_}) || ($$old{$_} ne $$new{$_})) { + $upd{$_} = $self->{prod_relations}{$$new{$_}}[1]; + } + } + + return if !keys %upd; + + # edit all related producers + for my $i (keys %upd) { + my $r = $self->dbProducerGet(id => $i, what => 'extended relations')->[0]; + my @newrel = map $_->{id} != $pid ? [ $_->{relation}, $_->{id} ] : (), @{$r->{relations}}; + push @newrel, [ $upd{$i}, $pid ] if $upd{$i}; + $self->dbProducerEdit($i, + relations => \@newrel, + editsum => "Reverse relation update caused by revision p$pid.$rev", + causedby => $cid, + uid => 1, # Multi - hardcoded + ( map { $_ => $r->{$_} } qw|type name original lang website desc alias| ) + ); + } +} + sub list { my($self, $char) = @_; diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index 54367c9b..1775958c 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -33,6 +33,22 @@ ALTER TABLE vn_relations ALTER COLUMN relation TYPE vn_relation USING END; +-- producer relations +-- old -> Formerly +-- new -> Succeeded by +-- par -> Parent producer +-- sub -> Subsidairy +-- imp -> Imprint +-- ipa -> Parent brand +CREATE TYPE producer_relation AS ENUM ('old', 'new', 'par', 'sub', 'imp', 'ipa'); +CREATE TABLE producers_relations ( + pid1 integer NOT NULL REFERENCES producers_rev (id), + pid2 integer NOT NULL REFERENCES producers (id), + relation producer_relation NOT NULL, + PRIMARY KEY(pid1, pid2) +); + + -- Anime types stored as enum CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); ALTER TABLE anime ALTER COLUMN type TYPE anime_type USING -- cgit v1.2.3 From 25bbbe2d974ea83fc01c2053354b05b62c5d6167 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 11:40:53 +0200 Subject: Display producer relations in revision browser And again copied something from the VN relation code... meh. --- data/lang.txt | 51 +++++++++++++++++++++++++++++++++++++++++++ lib/VNDB/Handler/Producers.pm | 12 +++++++--- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index ef5f641e..9d7bf027 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -589,6 +589,45 @@ cs : Amatérská skupina hu : Amatör csoport +# producer relations + +:_prodrel_old +en : Formerly +ru*: +cs*: +hu*: + +:_prodrel_new +en : Succeeded by +ru*: +cs*: +hu*: + +:_prodrel_par +en : Parent producer +ru*: +cs*: +hu*: + +:_prodrel_sub +en : Subsidairy +ru*: +cs*: +hu*: + +:_prodrel_imp +en : Imprint +ru*: +cs*: +hu*: + +:_prodrel_ipa +en : Parent brand +ru*: +cs*: +hu*: + + # release types :_rtype_complete @@ -2164,6 +2203,18 @@ ru : Описание cs : Popis hu : Leírás +:_revfield_p_relations +en : Relations +ru*: +cs*: +hu*: + +:_proddiff_none +en : none +ru*: +cs*: +hu*: + # Add/Edit producer diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm index 2a3991ba..97260dde 100644 --- a/lib/VNDB/Handler/Producers.pm +++ b/lib/VNDB/Handler/Producers.pm @@ -3,7 +3,7 @@ package VNDB::Handler::Producers; use strict; use warnings; -use YAWF ':html', ':xml'; +use YAWF ':html', ':xml', 'xml_escape'; use VNDB::Func; @@ -21,7 +21,7 @@ sub page { my $p = $self->dbProducerGet( id => $pid, - what => 'vn extended'.($rev ? ' changes' : ''), + what => 'vn extended relations'.($rev ? ' changes' : ''), $rev ? ( rev => $rev ) : () )->[0]; return 404 if !$p->{id}; @@ -31,7 +31,7 @@ sub page { return if $self->htmlHiddenMessage('p', $p); if($rev) { - my $prev = $rev && $rev > 1 && $self->dbProducerGet(id => $pid, rev => $rev-1, what => 'changes extended')->[0]; + my $prev = $rev && $rev > 1 && $self->dbProducerGet(id => $pid, rev => $rev-1, what => 'changes extended relations')->[0]; $self->htmlRevision('p', $prev, $p, [ type => serialize => sub { mt "_ptype_$_[0]" } ], [ name => diff => 1 ], @@ -40,6 +40,12 @@ sub page { [ lang => serialize => sub { "$_[0] (".mt("_lang_$_[0]").')' } ], [ website => diff => 1 ], [ desc => diff => 1 ], + [ relations => join => '<br />', split => sub { + my @r = map sprintf('%s: <a href="/p%d" title="%s">%s</a>', + mt("_prodrel_$_->{relation}"), $_->{id}, xml_escape($_->{original}||$_->{name}), xml_escape shorten $_->{name}, 40 + ), sort { $a->{id} <=> $b->{id} } @{$_[0]}; + return @r ? @r : (mt '_proddiff_none'); + }], ); } -- cgit v1.2.3 From bd2251939c7e4c9903aa3a6eb838f489b0328bcd Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 12:36:49 +0200 Subject: Display producer relations on producer pages --- lib/VNDB/Handler/Producers.pm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm index 97260dde..f662ba3e 100644 --- a/lib/VNDB/Handler/Producers.pm +++ b/lib/VNDB/Handler/Producers.pm @@ -62,6 +62,23 @@ sub page { } end; + if(@{$p->{relations}}) { + my %rel; + push @{$rel{$_->{relation}}}, $_ + for (sort { $a->{name} cmp $b->{name} } @{$p->{relations}}); + p class => 'center'; + txt "\n"; + for my $r (sort keys %rel) { + txt mt("_prodrel_$r").' '; + for (@{$rel{$r}}) { + a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 40; + txt ', ' if $_ ne $rel{$r}[$#{$rel{$r}}]; + } + txt "\n"; + } + end; + } + if($p->{desc}) { p class => 'description'; lit bb2html $p->{desc}; -- cgit v1.2.3 From 2301f0d2c726a1352494ad0f3bba8c5138b4fedd Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 13:37:42 +0200 Subject: Wrote producer relation editor interface Again, mostly copied from the VN relation editor... --- data/lang.txt | 48 ++++++++++++++++++ data/script.js | 115 ++++++++++++++++++++++++++++++++++++++++++ data/style.css | 10 ++++ lib/VNDB/Handler/Producers.pm | 30 ++++++++++- util/jsgen.pl | 3 +- 5 files changed, 203 insertions(+), 3 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index 9d7bf027..df894718 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -2296,6 +2296,54 @@ ru*: cs*: hu*: +:_pedit_rel_sel +en : Selected producers +ru*: +cs*: +hu*: + +:_pedit_rel_add +en : Add producer +ru*: +cs*: +hu*: + +:_pedit_rel_addbut +en : add +ru*: +cs*: +hu*: + +:_pedit_rel_del +en : remove +ru*: +cs*: +hu*: + +:_pedit_rel_none +en : Nothing selected. +ru*: +cs*: +hu*: + +:_pedit_rel_findformat +en : Producer textbox should start with an ID (e.g. "p7:") +ru*: +cs*: +hu*: + +:_pedit_rel_notfound +en : Producer not found +ru*: +cs*: +hu*: + +:_pedit_rel_double +en : Producer already selected! +ru*: +cs*: +hu*: + # Browse/search producers diff --git a/data/script.js b/data/script.js index a6600f9f..8ab9b003 100644 --- a/data/script.js +++ b/data/script.js @@ -5,6 +5,7 @@ * iv -> image viewer * jt -> Javascript Tabs * med -> Release media selector + * prr -> Producer relation editor * rl -> Release List dropdown * rpr -> Release <-> producer linking * rvn -> Release <-> visual novel linking @@ -1533,6 +1534,120 @@ if(byId('jt_box_rel_prod')) +/* P R O D U C E R R E L A T I O N S (/p+/edit) */ + +function prrLoad() { + // read the current relations + var rels = byId('prodrelations').value.split('|||'); + for(var i=0; i<rels.length && rels[0].length>1; i++) { + var rel = rels[i].split(',', 3); + prrAdd(rel[0], rel[1], rel[2]); + } + prrEmpty(); + + // bind the add-link + byName(byClass(byId('relation_new'), 'td', 'tc_add')[0], 'a')[0].onclick = prrFormAdd; + + // dropdown + dsInit(byName(byClass(byId('relation_new'), 'td', 'tc_prod')[0], 'input')[0], '/xml/producers.xml?q=', function(item, tr) { + tr.appendChild(tag('td', { style: 'text-align: right; padding-right: 5px'}, 'p'+item.getAttribute('id'))); + tr.appendChild(tag('td', shorten(item.firstChild.nodeValue, 40))); + }, function(item) { + return 'p'+item.getAttribute('id')+':'+item.firstChild.nodeValue; + }, prrFormAdd); +} + +function prrAdd(rel, pid, title) { + var sel = tag('select', {onchange: prrSerialize}); + var ops = byName(byClass(byId('relation_new'), 'td', 'tc_rel')[0], 'select')[0].options; + for(var i=0; i<ops.length; i++) + sel.appendChild(tag('option', {value: ops[i].value, selected: ops[i].value==rel}, getText(ops[i]))); + + byId('relation_tbl').appendChild(tag('tr', {id:'relation_tr_'+pid}, + tag('td', {'class':'tc_prod' }, 'p'+pid+':', tag('a', {href:'/p'+pid}, shorten(title, 40))), + tag('td', {'class':'tc_rel' }, sel), + tag('td', {'class':'tc_add' }, tag('a', {href:'#', onclick:prrDel}, mt('_pedit_rel_del'))) + )); + + prrEmpty(); +} + +function prrEmpty() { + var tbl = byId('relation_tbl'); + if(byName(tbl, 'tr').length < 1) + tbl.appendChild(tag('tr', {id:'relation_tr_none'}, tag('td', {colspan:4}, mt('_pedit_rel_none')))); + else if(byId('relation_tr_none')) + tbl.removeChild(byId('relation_tr_none')); +} + +function prrSerialize() { + var r = []; + var trs = byName(byId('relation_tbl'), 'tr'); + for(var i=0; i<trs.length; i++) { + if(trs[i].id == 'relation_tr_none') + continue; + var rel = byName(byClass(trs[i], 'td', 'tc_rel')[0], 'select')[0]; + r[r.length] = [ + rel.options[rel.selectedIndex].value, + trs[i].id.substr(12), + getText(byName(byClass(trs[i], 'td', 'tc_prod')[0], 'a')[0]) + ].join(','); + } + byId('prodrelations').value = r.join('|||'); +} + +function prrDel() { + var tr = this; + while(tr.nodeName.toLowerCase() != 'tr') + tr = tr.parentNode; + byId('relation_tbl').removeChild(tr); + prrSerialize(); + prrEmpty(); + return false; +} + +function prrFormAdd() { + var relnew = byId('relation_new'); + var txt = byName(byClass(relnew, 'td', 'tc_prod')[0], 'input')[0]; + var sel = byName(byClass(relnew, 'td', 'tc_rel')[0], 'select')[0]; + var lnk = byName(byClass(relnew, 'td', 'tc_add')[0], 'a')[0]; + var input = txt.value; + + if(!input.match(/^p[0-9]+/)) { + alert('_pedit_rel_findformat'); + return false; + } + + txt.disabled = sel.disabled = true; + txt.value = mt('_js_loading'); + setText(lnk, mt('_js_loading')); + + ajax('/xml/producers.xml?q='+encodeURIComponent(input), function(hr) { + txt.disabled = sel.disabled = false; + txt.value = ''; + setText(lnk, mt('_pedit_rel_addbut')); + + var items = hr.responseXML.getElementsByTagName('item'); + if(items.length < 1) + return alert(mt('_pedit_rel_notfound')); + + var id = items[0].getAttribute('id'); + if(byId('relation_tr_'+id)) + return alert(mt('_pedit_rel_double')); + + prrAdd(sel.selectedIndex, id, items[0].firstChild.nodeValue); + sel.selectedIndex = 0; + prrSerialize(); + }); + return false; +} + +if(byId('prodrelations')) + prrLoad(); + + + + /* M I S C S T U F F */ // search box diff --git a/data/style.css b/data/style.css index bec0686a..ea793578 100644 --- a/data/style.css +++ b/data/style.css @@ -844,6 +844,16 @@ div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px padding-bottom: 10px!important } +/***** Producer edit *****/ + +#jt_box_pedit_rel table { margin-bottom: 10px; } +#jt_box_pedit_rel h2 { margin: 0 0 3px 0px; } +#jt_box_pedit_rel td { padding: 1px 2px; vertical-align: middle; } +#jt_box_pedit_rel td.tc_prod { width: 290px; padding-left: 10px } +#jt_box_pedit_rel td.tc_add { width: 40px; text-align: left } +#jt_box_pedit_rel td.tc_prod input { width: 280px; } +#jt_box_pedit_rel td.tc_rel select { width: 130px; } + diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm index f662ba3e..41465b18 100644 --- a/lib/VNDB/Handler/Producers.pm +++ b/lib/VNDB/Handler/Producers.pm @@ -69,7 +69,7 @@ sub page { p class => 'center'; txt "\n"; for my $r (sort keys %rel) { - txt mt("_prodrel_$r").' '; + txt mt("_prodrel_$r").': '; for (@{$rel{$r}}) { a href => "/p$_->{id}", title => $_->{original}||$_->{name}, shorten $_->{name}, 40; txt ', ' if $_ ne $rel{$r}[$#{$rel{$r}}]; @@ -191,7 +191,33 @@ sub edit { [ input => name => mt('_pedit_form_website'), short => 'website' ], [ text => name => mt('_pedit_form_desc').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'desc', rows => 6 ], ], 'pedit_rel' => [ mt('_pedit_form_rel'), - [ textarea => short => 'prodrelations' ], + [ hidden => short => 'prodrelations' ], + [ static => nolabel => 1, content => sub { + h2 mt '_pedit_rel_sel'; + table; + tbody id => 'relation_tbl'; + # to be filled using javascript + end; + end; + + h2 mt '_pedit_rel_add'; + table; + Tr id => 'relation_new'; + td class => 'tc_prod'; + input type => 'text', class => 'text'; + end; + td class => 'tc_rel'; + Select; + option value => $_, mt "_prodrel_$_" + for (sort { $self->{prod_relations}{$a}[0] <=> $self->{prod_relations}{$b}[0] } keys %{$self->{prod_relations}}); + end; + end; + td class => 'tc_add'; + a href => '#', mt '_pedit_rel_addbut'; + end; + end; + end; + }], ]); $self->htmlFooter; } diff --git a/util/jsgen.pl b/util/jsgen.pl index 56897679..1ad8fb53 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -34,7 +34,8 @@ my $jskeys = qr{^(?: _vnedit_scr_.+| _tagv_(?:add|spoil\d|notfound|nometa|double)| _redit_form_vn_(?:addbut|remove|none|vnformat|notfound|double)| - _redit_form_prod_(?:addbut|remove|none|pformat|notfound|double) + _redit_form_prod_(?:addbut|remove|none|pformat|notfound|double)| + _pedit_rel_(?:addbut|del|none|findformat|notfound|double) )$}x; sub l10n { -- cgit v1.2.3 From 91b6578e17f1ce6d0ff7974d06ae55ad2e39bf1d Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 13:47:59 +0200 Subject: SQL: Synced update_2.8.sql into dump.sql This doesn't mean the relations are final, though... --- util/dump.sql | 23 ++++++++++++++++++----- util/updates/update_2.8.sql | 6 ------ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/util/dump.sql b/util/dump.sql index 9fbff0a2..f5ce2614 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -5,11 +5,12 @@ CREATE LANGUAGE plpgsql; -- data types -CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); -CREATE TYPE dbentry_type AS ENUM ('v', 'r', 'p'); -CREATE TYPE medium AS ENUM ('cd', 'dvd', 'gdr', 'blr', 'flp', 'mrt', 'mem', 'umd', 'nod', 'in', 'otc'); -CREATE TYPE release_type AS ENUM ('complete', 'partial', 'trial'); -CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); +CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); +CREATE TYPE dbentry_type AS ENUM ('v', 'r', 'p'); +CREATE TYPE medium AS ENUM ('cd', 'dvd', 'gdr', 'blr', 'flp', 'mrt', 'mem', 'umd', 'nod', 'in', 'otc'); +CREATE TYPE producer_relation AS ENUM ('old', 'new', 'par', 'sub', 'imp', 'ipa'); +CREATE TYPE release_type AS ENUM ('complete', 'partial', 'trial'); +CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); ----------------------------------------- @@ -49,6 +50,16 @@ CREATE TABLE producers ( hidden boolean NOT NULL DEFAULT FALSE ); + +-- producers_relations +CREATE TABLE producers_relations ( + pid1 integer NOT NULL, + pid2 integer NOT NULL, + relation producer_relation NOT NULL, + PRIMARY KEY(pid1, pid2) +); + + -- producers_rev CREATE TABLE producers_rev ( id integer NOT NULL PRIMARY KEY, @@ -356,6 +367,8 @@ CREATE TABLE wlists ( ALTER TABLE changes ADD FOREIGN KEY (requester) REFERENCES users (id); ALTER TABLE changes ADD FOREIGN KEY (causedby) REFERENCES changes (id); ALTER TABLE producers ADD FOREIGN KEY (latest) REFERENCES producers_rev (id) DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE producers_relations ADD FOREIGN KEY (pid1) REFERENCES producers_rev (id); +ALTER TABLE producers_relations ADD FOREIGN KEY (pid2) REFERENCES producers (id); ALTER TABLE producers_rev ADD FOREIGN KEY (id) REFERENCES changes (id); ALTER TABLE producers_rev ADD FOREIGN KEY (pid) REFERENCES producers (id); ALTER TABLE quotes ADD FOREIGN KEY (vid) REFERENCES vn (id); diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index 1775958c..9d79500a 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -34,12 +34,6 @@ ALTER TABLE vn_relations ALTER COLUMN relation TYPE vn_relation USING -- producer relations --- old -> Formerly --- new -> Succeeded by --- par -> Parent producer --- sub -> Subsidairy --- imp -> Imprint --- ipa -> Parent brand CREATE TYPE producer_relation AS ENUM ('old', 'new', 'par', 'sub', 'imp', 'ipa'); CREATE TABLE producers_relations ( pid1 integer NOT NULL REFERENCES producers_rev (id), -- cgit v1.2.3 From 0325073d1eb045628f6090c7be4ee9685d7ec159 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 14:09:48 +0200 Subject: Handler::Tags: Increased tag dropdown search results to 15 --- ChangeLog | 1 + lib/VNDB/Handler/Tags.pm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 444f710c..71ff2069 100644 --- a/ChangeLog +++ b/ChangeLog @@ -30,6 +30,7 @@ git - ? - Set 'no spoilers' as default spoiler level for tags - Added Czech and Hungarian interface translation - Producer relations + - Increased tag dropdown search results to 15 2.7 - 2009-09-24 - Improved styling of the threeboxes layout diff --git a/lib/VNDB/Handler/Tags.pm b/lib/VNDB/Handler/Tags.pm index f75efdc6..4c969436 100644 --- a/lib/VNDB/Handler/Tags.pm +++ b/lib/VNDB/Handler/Tags.pm @@ -653,7 +653,7 @@ sub tagxml { my($list, $np) = $self->dbTagGet( $q =~ /^g([1-9]\d*)/ ? (id => $1) : $q =~ /^name:(.+)$/ ? (name => $1) : (search => $q), - results => 10, + results => 15, page => 1, ); -- cgit v1.2.3 From 96e77619793fbe8351e023d17e257e96cdb37509 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 14:21:38 +0200 Subject: SQL: Renamed vn_graphs to relgraphs and synced dbgraph.pl As the same table can easily be used to store producer relation graphs as well. --- lib/Multi/Maintenance.pm | 2 +- lib/Multi/RG.pm | 2 +- lib/VNDB/DB/VN.pm | 2 +- util/dbgraph.pl | 6 +++--- util/dump.sql | 18 +++++++----------- util/updates/update_2.8.sql | 4 ++-- 6 files changed, 15 insertions(+), 19 deletions(-) diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm index 59d30ce6..ecc80486 100644 --- a/lib/Multi/Maintenance.pm +++ b/lib/Multi/Maintenance.pm @@ -119,7 +119,7 @@ sub vnpopularity { sub cleangraphs { # should be pretty fast - $_[KERNEL]->post(pg => do => 'DELETE FROM vn_graphs vg WHERE NOT EXISTS(SELECT 1 FROM vn WHERE rgraph = vg.id)', + $_[KERNEL]->post(pg => do => 'DELETE FROM relgraphs vg WHERE NOT EXISTS(SELECT 1 FROM vn WHERE rgraph = vg.id)', undef, 'log_stats', 'cleangraphs'); } diff --git a/lib/Multi/RG.pm b/lib/Multi/RG.pm index 1ee69911..5cb03ed4 100644 --- a/lib/Multi/RG.pm +++ b/lib/Multi/RG.pm @@ -220,7 +220,7 @@ sub savegraph { $w->end(); # save the processed SVG in the database and fetch graph ID - $_[KERNEL]->post(pg => query => 'INSERT INTO vn_graphs (svg) VALUES (?) RETURNING id', [ $svg ], 'finish'); + $_[KERNEL]->post(pg => query => 'INSERT INTO relgraphs (svg) VALUES (?) RETURNING id', [ $svg ], 'finish'); } diff --git a/lib/VNDB/DB/VN.pm b/lib/VNDB/DB/VN.pm index 662057d5..bb2c1275 100644 --- a/lib/VNDB/DB/VN.pm +++ b/lib/VNDB/DB/VN.pm @@ -77,7 +77,7 @@ sub dbVNGet { $o{what} =~ /changes/ ? 'JOIN users u ON u.id = c.requester' : (), $o{what} =~ /relgraph/ ? - 'JOIN vn_graphs vg ON vg.id = v.rgraph' : (), + 'JOIN relgraphs vg ON vg.id = v.rgraph' : (), ); my $tag_ids = $o{tags_include} && join ',', @{$o{tags_include}[1]}; diff --git a/util/dbgraph.pl b/util/dbgraph.pl index 51e7302e..0b72ceba 100755 --- a/util/dbgraph.pl +++ b/util/dbgraph.pl @@ -16,13 +16,13 @@ use warnings; my %subgraphs = ( - 'Producers' => [qw| FFFFCC producers producers_rev |], + 'Producers' => [qw| FFFFCC producers producers_rev producers_relations |], 'Releases' => [qw| C8FFC8 releases releases_rev releases_media releases_platforms releases_producers releases_lang releases_vn |], - 'Visual Novels' => [qw| FFE6BE vn vn_rev vn_relations vn_anime vn_screenshots vn_graphs |], + 'Visual Novels' => [qw| FFE6BE vn vn_rev vn_relations vn_anime vn_screenshots |], 'Users' => [qw| CCFFFF users votes rlists wlists sessions |], 'Discussion board' => [qw| FFDCDC threads threads_boards threads_posts |], 'Tags' => [qw| FFC8C8 tags tags_aliases tags_parents tags_vn |], - 'Misc' => [qw| F5F5F5 changes anime screenshots stats_cache quotes |], + 'Misc' => [qw| F5F5F5 changes anime screenshots stats_cache quotes relgraphs |], ); my %tables; # table_name => [ [ col1, pri ], ... ] diff --git a/util/dump.sql b/util/dump.sql index f5ce2614..97d317e0 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -50,7 +50,6 @@ CREATE TABLE producers ( hidden boolean NOT NULL DEFAULT FALSE ); - -- producers_relations CREATE TABLE producers_relations ( pid1 integer NOT NULL, @@ -59,7 +58,6 @@ CREATE TABLE producers_relations ( PRIMARY KEY(pid1, pid2) ); - -- producers_rev CREATE TABLE producers_rev ( id integer NOT NULL PRIMARY KEY, @@ -73,7 +71,6 @@ CREATE TABLE producers_rev ( alias varchar(500) NOT NULL DEFAULT '' ); - -- quotes CREATE TABLE quotes ( vid integer NOT NULL, @@ -81,7 +78,6 @@ CREATE TABLE quotes ( PRIMARY KEY(vid, quote) ); - -- releases CREATE TABLE releases ( id SERIAL NOT NULL PRIMARY KEY, @@ -151,6 +147,12 @@ CREATE TABLE releases_vn ( PRIMARY KEY(rid, vid) ); +-- relgraphs +CREATE TABLE relgraphs ( + id SERIAL PRIMARY KEY, + svg xml NOT NULL +); + -- rlists CREATE TABLE rlists ( uid integer NOT NULL DEFAULT 0, @@ -297,12 +299,6 @@ CREATE TABLE vn_anime ( PRIMARY KEY(vid, aid) ); --- vn_graphs -CREATE TABLE vn_graphs ( - id SERIAL PRIMARY KEY, - svg xml NOT NULL -); - -- vn_relations CREATE TABLE vn_relations ( vid1 integer NOT NULL DEFAULT 0, @@ -397,7 +393,7 @@ ALTER TABLE threads_posts ADD FOREIGN KEY (tid) REFERENCES threads ALTER TABLE threads_posts ADD FOREIGN KEY (uid) REFERENCES users (id); ALTER TABLE threads_boards ADD FOREIGN KEY (tid) REFERENCES threads (id); ALTER TABLE vn ADD FOREIGN KEY (latest) REFERENCES vn_rev (id) DEFERRABLE INITIALLY DEFERRED; -ALTER TABLE vn ADD FOREIGN KEY (rgraph) REFERENCES vn_graphs (id); +ALTER TABLE vn ADD FOREIGN KEY (rgraph) REFERENCES relgraphs (id); ALTER TABLE vn_anime ADD FOREIGN KEY (aid) REFERENCES anime (id); ALTER TABLE vn_anime ADD FOREIGN KEY (vid) REFERENCES vn_rev (id); ALTER TABLE vn_relations ADD FOREIGN KEY (vid1) REFERENCES vn_rev (id); diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index 9d79500a..aef84791 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -8,11 +8,11 @@ UPDATE vn SET rgraph = NULL; ALTER TABLE vn DROP CONSTRAINT vn_rgraph_fkey; DROP TABLE relgraph; -CREATE TABLE vn_graphs ( +CREATE TABLE relgraphs ( id SERIAL PRIMARY KEY, svg xml NOT NULL ); -ALTER TABLE vn ADD FOREIGN KEY (rgraph) REFERENCES vn_graphs (id); +ALTER TABLE vn ADD FOREIGN KEY (rgraph) REFERENCES relgraphs (id); -- VN relations stored as enum -- cgit v1.2.3 From 6900668e8dad97762e4a4c493c21dec1391998cb Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 16:01:08 +0200 Subject: Added relation graphs for producers TODO: - document the relations - emit a relgraph notify when needed --- data/lang.txt | 35 ++++--- lib/Multi/Maintenance.pm | 7 +- lib/Multi/RG.pm | 217 +++++++++++++++++++++++++++--------------- lib/VNDB/DB/Producers.pm | 6 +- lib/VNDB/Handler/Producers.pm | 23 +++++ lib/VNDB/Handler/VNPage.pm | 32 +------ lib/VNDB/Util/CommonHTML.pm | 40 +++++++- util/dump.sql | 4 +- util/updates/update_2.8.sql | 1 + 9 files changed, 239 insertions(+), 126 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index df894718..84ac35a0 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -2216,6 +2216,15 @@ cs*: hu*: +# Producer relation graph page (/p+/rg) + +:_prodrg_title +en : Relation graph for [_1] +ru*: +cs*: +hu*: + + # Add/Edit producer :_pedit_title_edit @@ -5054,18 +5063,6 @@ ru : Схема связей для [_1] cs : Graf vztahů pro vizuální novelu [_1] hu : Összefüggés gráf [_1]-hoz -:_vnrg_notsupp -en : Not supported -ru*: -cs*: -hu*: - -:_vnrg_notsupp_msg -en : Your browser sucks, it doesn't have the functionality to render our nice relation graphs. -ru*: -cs*: -hu*: - # VN Diff viewer (/v+.+) @@ -5704,3 +5701,17 @@ cs : Prosíme, anglicky! hu : Kérlek angolul válaszolj! +# No browser support to display the relation graphs + +:_rg_notsupp +en : Not supported +ru*: +cs*: +hu*: + +:_rg_notsupp_msg +en : Your browser sucks, it doesn't have the functionality to render our nice relation graphs. +ru*: +cs*: +hu*: + diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm index ecc80486..0bd5eb91 100644 --- a/lib/Multi/Maintenance.pm +++ b/lib/Multi/Maintenance.pm @@ -119,8 +119,11 @@ sub vnpopularity { sub cleangraphs { # should be pretty fast - $_[KERNEL]->post(pg => do => 'DELETE FROM relgraphs vg WHERE NOT EXISTS(SELECT 1 FROM vn WHERE rgraph = vg.id)', - undef, 'log_stats', 'cleangraphs'); + $_[KERNEL]->post(pg => do => q| + DELETE FROM relgraphs vg + WHERE NOT EXISTS(SELECT 1 FROM vn WHERE rgraph = vg.id) + AND NOT EXISTS(SELECT 1 FROM producers WHERE rgraph = vg.id) + |, undef, 'log_stats', 'cleangraphs'); } diff --git a/lib/Multi/RG.pm b/lib/Multi/RG.pm index 5cb03ed4..de3e89bf 100644 --- a/lib/Multi/RG.pm +++ b/lib/Multi/RG.pm @@ -51,10 +51,12 @@ sub shutdown { sub check_rg { - return if $_[HEAP]{vid}; - $_[KERNEL]->call(pg => query => - 'SELECT v.id FROM vn v JOIN vn_relations vr ON vr.vid1 = v.latest WHERE rgraph IS NULL AND hidden = FALSE LIMIT 1', - undef, 'creategraph'); + return if $_[HEAP]{id}; + $_[KERNEL]->call(pg => query => q| + SELECT 'v' AS type, v.id FROM vn v JOIN vn_relations vr ON vr.vid1 = v.latest WHERE rgraph IS NULL AND hidden = FALSE + UNION + SELECT 'p', p.id FROM producers p JOIN producers_relations pr ON pr.pid1 = p.latest WHERE rgraph IS NULL AND hidden = FALSE + LIMIT 1|, undef, 'creategraph'); } @@ -62,45 +64,48 @@ sub creategraph { # num, res return $_[KERNEL]->delay('check_rg', $_[HEAP]{check_delay}) if $_[ARG0] == 0; $_[HEAP]{start} = time; - $_[HEAP]{vid} = $_[ARG1][0]{id}; - $_[HEAP]{rels} = {}; # relations (key=vid1-vid2, value=relation) - $_[HEAP]{nodes} = {}; # nodes (key=vid, value= 0:found, 1:processed) - - $_[KERNEL]->post(pg => query => - 'SELECT vid2 AS id, relation FROM vn v JOIN vn_relations vr ON vr.vid1 = v.latest WHERE v.id = ?', - [ $_[HEAP]{vid} ], 'getrel', $_[HEAP]{vid}); + $_[HEAP]{id} = $_[ARG1][0]{id}; + $_[HEAP]{type} = $_[ARG1][0]{type}; + $_[HEAP]{rels} = {}; # relations (key=id1-id2, value=relation) + $_[HEAP]{nodes} = {}; # nodes (key=id, value= 0:found, 1:processed) + + $_[KERNEL]->post(pg => query => $_[HEAP]{type} eq 'v' + ? 'SELECT vid2 AS id, relation FROM vn v JOIN vn_relations vr ON vr.vid1 = v.latest WHERE v.id = ?' + : 'SELECT pid2 AS id, relation FROM producers p JOIN producers_relations pr ON pr.pid1 = p.latest WHERE p.id = ?', + [ $_[HEAP]{id} ], 'getrel', $_[HEAP]{id}); } -sub getrel { # num, res, vid +sub getrel { # num, res, id my $id = $_[ARG2]; $_[HEAP]{nodes}{$id} = 1; for($_[ARG0] > 0 ? @{$_[ARG1]} : ()) { - $_[HEAP]{rels}{$id.'-'.$_->{id}} = $VNDB::S{vn_relations}{$_->{relation}}[1] if $id < $_->{id}; + $_[HEAP]{rels}{$id.'-'.$_->{id}} = $VNDB::S{ $_[HEAP]{type} eq 'v' ? 'vn_relations' : 'prod_relations' }{$_->{relation}}[1] if $id < $_->{id}; $_[HEAP]{rels}{$_->{id}.'-'.$id} = $_->{relation} if $id > $_->{id}; if(!exists $_[HEAP]{nodes}{$_->{id}}) { $_[HEAP]{nodes}{$_->{id}} = 0; - $_[KERNEL]->post(pg => query => - 'SELECT vid2 AS id, relation FROM vn v JOIN vn_relations vr ON vr.vid1 = v.latest WHERE v.id = ?', + $_[KERNEL]->post(pg => query => $_[HEAP]{type} eq 'v' + ? 'SELECT vid2 AS id, relation FROM vn v JOIN vn_relations vr ON vr.vid1 = v.latest WHERE v.id = ?' + : 'SELECT pid2 AS id, relation FROM producers p JOIN producers_relations pr ON pr.pid1 = p.latest WHERE p.id = ?', [ $_->{id} ], 'getrel', $_->{id}); } } - # do we have all relations now? get VN info + # do we have all relations now? get node info if(!grep !$_, values %{$_[HEAP]{nodes}}) { - $_[KERNEL]->post(pg => query => - 'SELECT v.id, vr.title, v.c_released AS date, v.c_languages AS lang - FROM vn v JOIN vn_rev vr ON vr.id = v.latest - WHERE v.id IN('.join(', ', map '?', keys %{$_[HEAP]{nodes}}).')', + my $ids = join(', ', map '?', keys %{$_[HEAP]{nodes}}); + $_[KERNEL]->post(pg => query => $_[HEAP]{type} eq 'v' + ? "SELECT v.id, vr.title, v.c_released AS date, v.c_languages AS lang FROM vn v JOIN vn_rev vr ON vr.id = v.latest WHERE v.id IN($ids) ORDER BY v.c_released" + : "SELECT p.id, pr.name, pr.lang, pr.type FROM producers p JOIN producers_rev pr ON pr.id = p.latest WHERE p.id IN($ids) ORDER BY pr.name", [ keys %{$_[HEAP]{nodes}} ], 'builddot'); } } sub builddot { # num, res - my $vns = $_[ARG1]; + my $nodes = $_[ARG1]; my $gv = qq|graph rgraph {\n|. @@ -109,57 +114,11 @@ sub builddot { # num, res qq|\tedge [ labeldistance = 2.5, labelangle = -20, labeljust = 1, minlen = 2, dir = "both",|. qq| fontname = $_[HEAP]{font}, fontsize = $_[HEAP]{fsize}[1], arrowsize = 0.7, color = "#111111", fontcolor = "#333333" ]\n|; - # insert all nodes, ordered by release date - for (sort { $a->{date} <=> $b->{date} } @$vns) { - my $date = sprintf '%08d', $_->{date}; - $date =~ s{^([0-9]{4})([0-9]{2})([0-9]{2})$}{ - $1 == 0 ? 'unknown' - : $1 == 9999 ? 'TBA' - : $2 == 99 ? $1 - : $3 == 99 ? "$1-$2" : "$1-$2-$3" - }e; - - my $title = $_->{title}; - $title = substr($title, 0, 27).'...' if length($title) > 30; - $title =~ s/&/&/g; - $title =~ s/>/>/g; - $title =~ s/</</g; - - my $tooltip = $_->{title}; - $tooltip =~ s/\\/\\\\/g; - $tooltip =~ s/"/\\"/g; - - $gv .= sprintf - qq|\tv%d [ URL = "/v%d", tooltip = "%s" label=<|. - q|<TABLE CELLSPACING="0" CELLPADDING="1" BORDER="0" CELLBORDER="1" BGCOLOR="#222222">|. - q|<TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="2"><FONT POINT-SIZE="%d"> %s </FONT></TD></TR>|. - q|<TR><TD> %s </TD><TD> %s </TD></TR>|. - qq|</TABLE>> ]\n|, - $_->{id}, $_->{id}, encode_utf8($tooltip), $_[HEAP]{fsize}[2], encode_utf8($title), $date, $_->{lang}||'N/A'; - } + # insert all nodes + $gv .= $_[HEAP]{type} eq 'v' ? _vnnode($_, $_[HEAP]) : _prodnode($_, $_[HEAP]) for @$nodes; - # @rels = ([ vid1, vid2, relation, date1, date2 ], ..), for easier processing - my @rels = map { - /^([0-9]+)-([0-9]+)$/; - my $vn1 = (grep $1 == $_->{id}, @$vns)[0]; - my $vn2 = (grep $2 == $_->{id}, @$vns)[0]; - [ $1, $2, $_[HEAP]{rels}{$_}, $vn1->{date}, $vn2->{date} ] - } keys %{$_[HEAP]{rels}}; - - # insert all edges, ordered by release date again - for (sort { ($a->[3]>$a->[4]?$a->[4]:$a->[3]) <=> ($b->[3]>$b->[4]?$b->[4]:$b->[3]) } @rels) { - # [older game] -> [newer game] - if($_->[4] > $_->[3]) { - ($_->[0], $_->[1]) = ($_->[1], $_->[0]); - $_->[2] = $VNDB::S{vn_relations}{$_->[2]}[1]; - } - my $rev = $VNDB::S{vn_relations}{$_->[2]}[1]; - my $label = - $rev ne $_->[2] - ? qq|headlabel = "\$____vnrel_$_->[2]____\$", taillabel = "\$____vnrel_${rev}____\$"| - : qq|label = "\$____vnrel_$_->[2]____\$"|; - $gv .= qq|\tv$$_[1] -- v$$_[0] [ $label ]\n|; - } + # ...and relations + $gv .= $_[HEAP]{type} eq 'v' ? _vnrels($_[HEAP]{rels}, $nodes) : _prodrels($_[HEAP]{rels}, $nodes); $gv .= "}\n"; @@ -226,16 +185,17 @@ sub savegraph { sub finish { # num, res my $id = $_[ARG1][0]{id}; - my $vids = join ',', sort map int, keys %{$_[HEAP]{nodes}}; + my $ids = join ',', sort map int, keys %{$_[HEAP]{nodes}}; + my $table = $_[HEAP]{type} eq 'v' ? 'vn' : 'producers'; - # update the VN table - $_[KERNEL]->post(pg => do => "UPDATE vn SET rgraph = ? WHERE id IN($vids)", [ $id ]); + # update the table + $_[KERNEL]->post(pg => do => "UPDATE $table SET rgraph = ? WHERE id IN($ids)", [ $id ]); # log - $_[KERNEL]->call(core => log => 'Generated VN relation graph #%d in %.2fs, V: %s', $id, time-$_[HEAP]{start}, $vids); + $_[KERNEL]->call(core => log => 'Generated %s relation graph #%d in %.2fs, V: %s', $table, $id, time-$_[HEAP]{start}, $ids); # clean up - delete @{$_[HEAP]}{qw| start vid nodes rels svg proc |}; + delete @{$_[HEAP]}{qw| start id type nodes rels svg proc |}; # check for more things to do $_[KERNEL]->yield('check_rg'); @@ -261,5 +221,110 @@ sub proc_child { } + +# non-POE helper functions + +sub _vnnode { + my($n, $heap) = @_; + + my $date = sprintf '%08d', $n->{date}; + $date =~ s{^([0-9]{4})([0-9]{2})([0-9]{2})$}{ + $1 == 0 ? 'unknown' + : $1 == 9999 ? 'TBA' + : $2 == 99 ? $1 + : $3 == 99 ? "$1-$2" : "$1-$2-$3" + }e; + + my $title = $n->{title}; + $title = substr($title, 0, 27).'...' if length($title) > 30; + $title =~ s/&/&/g; + $title =~ s/>/>/g; + $title =~ s/</</g; + + my $tooltip = $n->{title}; + $tooltip =~ s/\\/\\\\/g; + $tooltip =~ s/"/\\"/g; + + return sprintf + qq|\tv%d [ URL = "/v%d", tooltip = "%s", label=<|. + q|<TABLE CELLSPACING="0" CELLPADDING="1" BORDER="0" CELLBORDER="1" BGCOLOR="#222222">|. + q|<TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="2"><FONT POINT-SIZE="%d"> %s </FONT></TD></TR>|. + q|<TR><TD> %s </TD><TD> %s </TD></TR>|. + qq|</TABLE>> ]\n|, + $_->{id}, $_->{id}, encode_utf8($tooltip), $heap->{fsize}[2], encode_utf8($title), $date, $n->{lang}||'N/A'; +} + + +sub _vnrels { + my($rels, $vns) = @_; + my $r = ''; + + # @rels = ([ vid1, vid2, relation, date1, date2 ], ..), for easier processing + my @rels = map { + /^([0-9]+)-([0-9]+)$/; + my $vn1 = (grep $1 == $_->{id}, @$vns)[0]; + my $vn2 = (grep $2 == $_->{id}, @$vns)[0]; + [ $1, $2, $rels->{$_}, $vn1->{date}, $vn2->{date} ] + } keys %$rels; + + # insert all edges, ordered by release date again + for (sort { ($a->[3]>$a->[4]?$a->[4]:$a->[3]) <=> ($b->[3]>$b->[4]?$b->[4]:$b->[3]) } @rels) { + # [older game] -> [newer game] + if($_->[4] > $_->[3]) { + ($_->[0], $_->[1]) = ($_->[1], $_->[0]); + $_->[2] = $VNDB::S{vn_relations}{$_->[2]}[1]; + } + my $rev = $VNDB::S{vn_relations}{$_->[2]}[1]; + my $label = $rev ne $_->[2] + ? qq|headlabel = "\$____vnrel_$_->[2]____\$", taillabel = "\$____vnrel_${rev}____\$"| + : qq|label = "\$____vnrel_$_->[2]____\$"|; + $r .= qq|\tv$$_[1] -- v$$_[0] [ $label ]\n|; + } + return $r; +} + + +sub _prodnode { + my($n, $heap) = @_; + + my $name = $n->{name}; + $name = substr($name, 0, 27).'...' if length($name) > 30; + $name =~ s/&/&/g; + $name =~ s/>/>/g; + $name =~ s/</</g; + + my $tooltip = $n->{name}; + $tooltip =~ s/\\/\\\\/g; + $tooltip =~ s/"/\\"/g; + + return sprintf + qq|\tp%d [ URL = "/p%d", tooltip = "%s", label=<|. + q|<TABLE CELLSPACING="0" CELLPADDING="1" BORDER="0" CELLBORDER="1" BGCOLOR="#222222">|. + q|<TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="2"><FONT POINT-SIZE="%d"> %s </FONT></TD></TR>|. + q|<TR><TD ALIGN="CENTER"> $_lang_%s_$ </TD><TD ALIGN="CENTER"> $_ptype_%s_$ </TD></TR>|. + qq|</TABLE>> ]\n|, + $_->{id}, $_->{id}, encode_utf8($tooltip), $heap->{fsize}[2], encode_utf8($name), $n->{lang}, $n->{type}; +} + + +sub _prodrels { + my($rels, $prods) = @_; + my $r = ''; + + for (keys %$rels) { + /^([0-9]+)-([0-9]+)$/; + my $p1 = (grep $1 == $_->{id}, @$prods)[0]; + my $p2 = (grep $2 == $_->{id}, @$prods)[0]; + + my $rev = $VNDB::S{prod_relations}{$rels->{$_}}[1]; + my $label = $rev ne $rels->{$_} + ? qq|headlabel = "\$____prodrel_${rev}____\$", taillabel = "\$____prodrel_$rels->{$_}____\$"| + : qq|label = "\$____prodrel_$rels->{$_}____\$"|; + $r .= qq|\tp$p1->{id} -- p$p2->{id} [ $label ]\n|; + } + return $r; +} + + 1; diff --git a/lib/VNDB/DB/Producers.pm b/lib/VNDB/DB/Producers.pm index c28d12d7..7c7da3ba 100644 --- a/lib/VNDB/DB/Producers.pm +++ b/lib/VNDB/DB/Producers.pm @@ -9,7 +9,7 @@ our @EXPORT = qw|dbProducerGet dbProducerEdit dbProducerAdd|; # options: results, page, id, search, char, rev -# what: extended, changes, vn, relations +# what: extended changes vn relations relgraph sub dbProducerGet { my $self = shift; my %o = ( @@ -40,10 +40,12 @@ sub dbProducerGet { push @join, $o{rev} ? 'JOIN producers p ON p.id = pr.pid' : 'JOIN producers p ON pr.id = p.latest'; push @join, 'JOIN changes c ON c.id = pr.id' if $o{what} =~ /changes/ || $o{rev}; push @join, 'JOIN users u ON u.id = c.requester' if $o{what} =~ /changes/; + push @join, 'JOIN relgraphs pg ON pg.id = p.rgraph' if $o{what} =~ /relgraph/; - my $select = 'p.id, pr.type, pr.name, pr.original, pr.lang, pr.id AS cid'; + my $select = 'p.id, pr.type, pr.name, pr.original, pr.lang, pr.id AS cid, p.rgraph'; $select .= ', pr.desc, pr.alias, pr.website, p.hidden, p.locked' if $o{what} =~ /extended/; $select .= q|, extract('epoch' from c.added) as added, c.requester, c.comments, p.latest, pr.id AS cid, u.username, c.rev| if $o{what} =~ /changes/; + $select .= ', pg.svg' if $o{what} =~ /relgraph/; my($r, $np) = $self->dbPage(\%o, q| SELECT !s diff --git a/lib/VNDB/Handler/Producers.pm b/lib/VNDB/Handler/Producers.pm index 41465b18..4e75962b 100644 --- a/lib/VNDB/Handler/Producers.pm +++ b/lib/VNDB/Handler/Producers.pm @@ -8,6 +8,7 @@ use VNDB::Func; YAWF::register( + qr{p([1-9]\d*)/rg} => \&rg, qr{p([1-9]\d*)(?:\.([1-9]\d*))?} => \&page, qr{p(?:([1-9]\d*)(?:\.([1-9]\d*))?/edit|/new)} => \&edit, @@ -16,6 +17,28 @@ YAWF::register( ); +sub rg { + my($self, $pid) = @_; + + my $p = $self->dbProducerGet(id => $pid, what => 'relgraph')->[0]; + return 404 if !$p->{id} || !$p->{rgraph}; + + my $title = mt '_prodrg_title', $p->{name}; + return if $self->htmlRGHeader($title, 'p', $p); + + $p->{svg} =~ s/\$___(_prodrel_[a-z]+)____\$/mt $1/eg; + $p->{svg} =~ s/\$(_lang_[a-z]+)_\$/mt $1/eg; + $p->{svg} =~ s/\$(_ptype_[a-z]+)_\$/mt $1/eg; + + div class => 'mainbox'; + h1 $title; + p class => 'center'; + lit $p->{svg}; + end; + end; + $self->htmlFooter; +} + sub page { my($self, $pid, $rev) = @_; diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm index 0205e77d..ec5f4afc 100644 --- a/lib/VNDB/Handler/VNPage.pm +++ b/lib/VNDB/Handler/VNPage.pm @@ -27,40 +27,10 @@ sub rg { return 404 if !$v->{id} || !$v->{rgraph}; my $title = mt '_vnrg_title', $v->{title}; - - if(($self->reqHeader('Accept')||'') !~ /application\/xhtml\+xml/) { - $self->htmlHeader(title => $title); - $self->htmlMainTabs('v', $v, 'rg'); - div class => 'mainbox'; - h1 $title; - div class => 'warning'; - h2 mt '_vnrg_notsupp'; - p mt '_vnrg_notsupp_msg'; - end; - end; - $self->htmlFooter; - return; - } - $self->resHeader('Content-Type' => 'application/xhtml+xml; charset=UTF-8'); - - # This is a REALLY ugly hack, need find a proper solution in YAWF - no warnings 'redefine'; - my $sub = \&YAWF::XML::html; - *YAWF::XML::html = sub () { - lit q|<!DOCTYPE html PUBLIC - "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" - "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">|; - tag 'html', - xmlns => "http://www.w3.org/1999/xhtml", - 'xmlns:svg' => 'http://www.w3.org/2000/svg', - 'xmlns:xlink' => 'http://www.w3.org/1999/xlink'; - }; - $self->htmlHeader(title => $title); - *YAWF::XML::html = $sub; + return if $self->htmlRGHeader($title, 'v', $v); $v->{svg} =~ s/\$___(_vnrel_[a-z]+)____\$/mt $1/eg; - $self->htmlMainTabs('v', $v, 'rg'); div class => 'mainbox'; h1 $title; p class => 'center'; diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index 3d032d37..ad99d32d 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -12,7 +12,7 @@ use POSIX 'ceil'; our @EXPORT = qw| htmlMainTabs htmlDenied htmlHiddenMessage htmlBrowse htmlBrowseNavigate - htmlRevision htmlEditMessage htmlItemMessage htmlVoteStats htmlHistory htmlSearchBox + htmlRevision htmlEditMessage htmlItemMessage htmlVoteStats htmlHistory htmlSearchBox htmlRGHeader |; @@ -101,7 +101,7 @@ sub htmlMainTabs { end; } - if($type eq 'v' && $obj->{rgraph}) { + if($type =~ /[vp]/ && $obj->{rgraph}) { li $sel eq 'rg' ? (class => 'tabselected') : (); a href => "/$id/rg", mt '_mtabs_relations'; end; @@ -558,5 +558,41 @@ sub htmlSearchBox { } +sub htmlRGHeader { + my($self, $title, $type, $obj) = @_; + + if(($self->reqHeader('Accept')||'') !~ /application\/xhtml\+xml/) { + $self->htmlHeader(title => $title); + $self->htmlMainTabs($type, $obj, 'rg'); + div class => 'mainbox'; + h1 $title; + div class => 'warning'; + h2 mt '_rg_notsupp'; + p mt '_rg_notsupp_msg'; + end; + end; + $self->htmlFooter; + return 1; + } + $self->resHeader('Content-Type' => 'application/xhtml+xml; charset=UTF-8'); + + # This is a REALLY ugly hack, need find a proper solution in YAWF + no warnings 'redefine'; + my $sub = \&YAWF::XML::html; + *YAWF::XML::html = sub () { + lit q|<!DOCTYPE html PUBLIC + "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" + "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">|; + tag 'html', + xmlns => "http://www.w3.org/1999/xhtml", + 'xmlns:svg' => 'http://www.w3.org/2000/svg', + 'xmlns:xlink' => 'http://www.w3.org/1999/xlink'; + }; + $self->htmlHeader(title => $title); + *YAWF::XML::html = $sub; + $self->htmlMainTabs($type, $obj, 'rg'); + return 0; +} + 1; diff --git a/util/dump.sql b/util/dump.sql index 97d317e0..84d862fd 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -47,7 +47,8 @@ CREATE TABLE producers ( id SERIAL NOT NULL PRIMARY KEY, latest integer NOT NULL DEFAULT 0, locked boolean NOT NULL DEFAULT FALSE, - hidden boolean NOT NULL DEFAULT FALSE + hidden boolean NOT NULL DEFAULT FALSE, + rgraph integer ); -- producers_relations @@ -363,6 +364,7 @@ CREATE TABLE wlists ( ALTER TABLE changes ADD FOREIGN KEY (requester) REFERENCES users (id); ALTER TABLE changes ADD FOREIGN KEY (causedby) REFERENCES changes (id); ALTER TABLE producers ADD FOREIGN KEY (latest) REFERENCES producers_rev (id) DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE producers ADD FOREIGN KEY (rgraph) REFERENCES relgraphs (id); ALTER TABLE producers_relations ADD FOREIGN KEY (pid1) REFERENCES producers_rev (id); ALTER TABLE producers_relations ADD FOREIGN KEY (pid2) REFERENCES producers (id); ALTER TABLE producers_rev ADD FOREIGN KEY (id) REFERENCES changes (id); diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index aef84791..637c61c1 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -41,6 +41,7 @@ CREATE TABLE producers_relations ( relation producer_relation NOT NULL, PRIMARY KEY(pid1, pid2) ); +ALTER TABLE producers ADD COLUMN rgraph integer REFERENCES relgraphs (id); -- Anime types stored as enum -- cgit v1.2.3 From a580210dc8e1d9e66b31ad68de9cf2492aba4d4f Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 16:06:51 +0200 Subject: CSS: Center the login button --- data/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/style.css b/data/style.css index ea793578..6bd0c547 100644 --- a/data/style.css +++ b/data/style.css @@ -296,7 +296,7 @@ b.future, b.standout, a.standout { } #menulist input.submit { width: 70px; - margin-left: 45px; + margin-left: 30px; } #menulist #search input.text { width: 133px; -- cgit v1.2.3 From 76154a765f9b69af92495462a5e880d5c2e608ce Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 16:21:31 +0200 Subject: SQL: Send relgraph notify when needed for producer entries --- util/dump.sql | 30 ++++++++++++++++++++++++++++++ util/updates/update_2.8.sql | 25 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/util/dump.sql b/util/dump.sql index 84d862fd..c04273b6 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -796,6 +796,36 @@ $$ LANGUAGE plpgsql; CREATE CONSTRAINT TRIGGER vn_relgraph_notify AFTER INSERT OR UPDATE ON vn DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE vn_relgraph_notify(); +-- Same as above for producers, with slight differences in the steps: +-- There is no 2, and +-- 3 = New producer revision of which the name, language or type differs from the previous revision (deferred) +CREATE OR REPLACE FUNCTION producer_relgraph_notify() RETURNS trigger AS $$ +BEGIN + -- 1. + IF TG_TABLE_NAME = 'producers' THEN + IF NEW.rgraph IS NULL AND EXISTS(SELECT 1 FROM producers_relations WHERE pid1 = NEW.latest) THEN + NOTIFY relgraph; + END IF; + END IF; + IF TG_TABLE_NAME = 'producers' AND TG_OP = 'UPDATE' THEN + IF NEW.rgraph IS NOT NULL AND OLD.latest > 0 THEN + -- 3 & 4 + IF OLD.latest <> NEW.latest AND ( + EXISTS(SELECT 1 FROM producers_rev p1, producers_rev p2 WHERE (p2.name <> p1.name OR p2.type <> p1.type OR p2.lang <> p1.lang) AND p1.id = OLD.latest AND p2.id = NEW.latest) + OR EXISTS(SELECT p1.pid2, p1.relation FROM producers_relations p1 WHERE p1.pid1 = OLD.latest EXCEPT SELECT p2.pid2, p2.relation FROM producers_relations p2 WHERE p2.pid1 = NEW.latest) + OR EXISTS(SELECT p1.pid2, p1.relation FROM producers_relations p1 WHERE p1.pid1 = NEW.latest EXCEPT SELECT p2.pid2, p2.relation FROM producers_relations p2 WHERE p2.pid1 = OLD.latest) + ) THEN + UPDATE producers SET rgraph = NULL WHERE id = NEW.id; + END IF; + END IF; + END IF; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; + +CREATE CONSTRAINT TRIGGER vn_relgraph_notify AFTER INSERT OR UPDATE ON producers DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE producer_relgraph_notify(); + + -- NOTIFY on insert into changes/posts/tags CREATE OR REPLACE FUNCTION insert_notify() RETURNS trigger AS $$ BEGIN diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index 637c61c1..e299e608 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -43,6 +43,31 @@ CREATE TABLE producers_relations ( ); ALTER TABLE producers ADD COLUMN rgraph integer REFERENCES relgraphs (id); +CREATE OR REPLACE FUNCTION producer_relgraph_notify() RETURNS trigger AS $$ +BEGIN + -- 1. + IF TG_TABLE_NAME = 'producers' THEN + IF NEW.rgraph IS NULL AND EXISTS(SELECT 1 FROM producers_relations WHERE pid1 = NEW.latest) THEN + NOTIFY relgraph; + END IF; + END IF; + IF TG_TABLE_NAME = 'producers' AND TG_OP = 'UPDATE' THEN + IF NEW.rgraph IS NOT NULL AND OLD.latest > 0 THEN + -- 3 & 4 + IF OLD.latest <> NEW.latest AND ( + EXISTS(SELECT 1 FROM producers_rev p1, producers_rev p2 WHERE (p2.name <> p1.name OR p2.type <> p1.type OR p2.lang <> p1.lang) AND p1.id = OLD.latest AND p2.id = NEW.latest) + OR EXISTS(SELECT p1.pid2, p1.relation FROM producers_relations p1 WHERE p1.pid1 = OLD.latest EXCEPT SELECT p2.pid2, p2.relation FROM producers_relations p2 WHERE p2.pid1 = NEW.latest) + OR EXISTS(SELECT p1.pid2, p1.relation FROM producers_relations p1 WHERE p1.pid1 = NEW.latest EXCEPT SELECT p2.pid2, p2.relation FROM producers_relations p2 WHERE p2.pid1 = OLD.latest) + ) THEN + UPDATE producers SET rgraph = NULL WHERE id = NEW.id; + END IF; + END IF; + END IF; + RETURN NULL; +END; +$$ LANGUAGE plpgsql; +CREATE CONSTRAINT TRIGGER vn_relgraph_notify AFTER INSERT OR UPDATE ON producers DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE producer_relgraph_notify(); + -- Anime types stored as enum CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); -- cgit v1.2.3 From 28e027452a548e67e631593481b8396254b8d39c Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 21 Oct 2009 16:27:18 +0200 Subject: JS: Copy over selection when adding new VN or producer relation Small but annoying bug... --- data/script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/script.js b/data/script.js index 8ab9b003..78169c1b 100644 --- a/data/script.js +++ b/data/script.js @@ -828,7 +828,7 @@ function vnrFormAdd() { if(byId('relation_tr_'+id)) return alert(mt('_vnedit_rel_double')); - vnrAdd(sel.selectedIndex, id, items[0].firstChild.nodeValue); + vnrAdd(sel.options[sel.selectedIndex].value, id, items[0].firstChild.nodeValue); sel.selectedIndex = 0; vnrSerialize(); }); @@ -1635,7 +1635,7 @@ function prrFormAdd() { if(byId('relation_tr_'+id)) return alert(mt('_pedit_rel_double')); - prrAdd(sel.selectedIndex, id, items[0].firstChild.nodeValue); + prrAdd(sel.options[sel.selectedIndex].value, id, items[0].firstChild.nodeValue); sel.selectedIndex = 0; prrSerialize(); }); -- cgit v1.2.3 From 126acb28340ddb4831b7e398cacba7f6957721b6 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Thu, 22 Oct 2009 13:45:08 +0200 Subject: Wrote a quick and dirty translation editor plugin See Plugin::TransAdmin for details. I wrote it as a plugin so that it can make use of the framework and functions of the main VNDB website code, but that it doesn't have to confirm to the rest of the code or have to be loaded into memory when unused. --- lib/VNDB/Plugin/TransAdmin.pm | 239 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 lib/VNDB/Plugin/TransAdmin.pm diff --git a/lib/VNDB/Plugin/TransAdmin.pm b/lib/VNDB/Plugin/TransAdmin.pm new file mode 100644 index 00000000..5e9f8b1c --- /dev/null +++ b/lib/VNDB/Plugin/TransAdmin.pm @@ -0,0 +1,239 @@ +# This plugin provides a quick and dirty user interface to editing lang.txt, +# to use it, add the following to your data/config.pl: +# +# use VNDB::Plugin::TransAdmin; +# $VNDB::S{transadmin} = { +# <userid> => 'all' || <language> || <arrayref with languages> +# }; +# +# And then open /tladmin in your browser. +# Also make sure data/lang.txt is writable by the httpd process. +# English is considered the 'main' language, and cannot be edited using this interface. + +package VNDB::Plugin::TransAdmin; + +use strict; +use warnings; +use YAWF ':html'; +use LangFile; +use VNDB::Func; + + +my $langfile = "$VNDB::ROOT/data/lang.txt"; + + +YAWF::register( + qr{tladmin(?:/([a-z]+))?} => \&tladmin +); + + +sub uri_escape { + local $_ = shift; + s/ /%20/g; + s/\?/%3F/g; + s/;/%3B/g; + s/&/%26/g; + return $_; +} + + +sub _allowed { + my($self, $lang) = @_; + my $a = $self->{transadmin}{ $self->authInfo->{id} }; + return $a eq 'all' || $a eq $lang || ref($a) eq 'ARRAY' && grep $_ eq $lang, @$a; +} + + +sub tladmin { + my($self, $lang) = @_; + + $lang ||= ''; + return 404 if $lang && ($lang eq 'en' || !grep $_ eq $lang, $self->{l10n}->languages); + my $sect = $self->reqParam('sect')||''; + + my $uid = $self->authInfo->{id}; + return $self->htmlDenied if !$uid || !$self->{transadmin}{$uid}; + + if(!-w $langfile) { + $self->htmlHeader(title => 'Language file not writable', noindex => 1); + div class => 'mainbox'; + h1 'Language file not writable'; + div class => 'warning', 'Sorry, I do not have enough permission to write to the language file.'; + end; + $self->htmlFooter; + return; + } + + _savelang($self, $lang) if $lang && $self->reqMethod eq 'POST' && _allowed($self, $lang); + my($sects, $page) = _readlang($lang, $sect) if $lang; + + $self->htmlHeader(title => 'Quick-and-dirty Translation Editor', noindex => 1); + div class => 'mainbox'; + h1 'Quick-and-dirty Translation Editor'; + h2 class => 'alttitle', 'Step #1: Choose a language'; + p class => 'browseopts'; + a $lang eq $_ ? (class => 'optselected') : (), href => "/tladmin/$_", mt "_lang_$_" + for grep !/en/, $self->{l10n}->languages; + end; + _sections($self, $lang, $sect, $sects) if $lang; + end; + + _page($self, $lang, $sect, $page) if $lang && $sect; + + $self->htmlFooter; +} + + +sub _savelang { + my($self, $lang) = @_; + + # do everything in-memory, so we don't need write access to a temporary file + # (this has the downside that in the event something goes wrong, everything will be wiped) + my $f = LangFile->new(read => $langfile); + my @read; + push @read, $_ while (local $_ = $f->read); + $f->close; + + my @keys = $self->reqParam; + $f = LangFile->new(write => $langfile); + my $key; + for my $l (@read) { + $key = $l->[1] if $l->[0] eq 'key'; + if($l->[0] eq 'tl' && $l->[1] eq $lang && grep $key eq $_, @keys) { + $l->[2] = !$self->reqParam("check$key"); + $l->[3] = $self->reqParam($key); + $l->[3] =~ s/\r?\n/\n/g; + $l->[3] =~ s/\s+$//g; + } + $f->write(@$l); + } + $f->close; + + # re-read the file and regenerate the JS in case we're not running as CGI + if($INC{"FCGI.pm"}) { + VNDB::L10N::loadfile(); + VNDB::checkjs(); + } +} + + +sub _readlang { + my($lang, $sect) = @_; + my @sect; # [ title, count, unsync ] + my @page; # [ 'comment'||'line', <comment>|| ( <key>, <en>, <sync>, <tl> ) ] + + my $f = LangFile->new(read => $langfile); + my($key, $insect); + while(my $l = $f->read) { + my $t = shift @$l; + + if($t eq 'space') { + if(join("\n", @$l) =~ /((#{30,90}\n)## +(.+) +##\n\2.+)^/ms) { + my $header = $1; + (my $title = $3) =~ s/\s+$//; + $title =~ s/\s+\([^)]+\)$//; + push @sect, [ $title, 0, 0 ]; + $insect = $title eq $sect; + push @page, [ 'comment', $header ] if $insect; + } elsif($insect) { + push @page, [ 'comment', join "\n", @$l ]; + } + } + + $sect[$#sect][1]++ if $t eq 'key'; + $sect[$#sect][2]++ if $t eq 'tl' && $l->[0] eq $lang && !$l->[1]; + + next if !$insect; + push @page, [ 'line', $l->[0] ] if $t eq 'key'; + $page[$#page][2] = $l->[2] if $t eq 'tl' && $l->[0] eq 'en'; + if($t eq 'tl' && $l->[0] eq $lang) { + $page[$#page][3] = $l->[1]; + $page[$#page][4] = $l->[2]; + } + } + $f->close; + return (\@sect, \@page); +} + + +sub _sections { + my($self, $lang, $sect, $list) = @_; + + br; + h2 class => 'alttitle', 'Step #2: Choose a section'; + div style => 'margin: 0 40px'; + for (@$list) { + div style => 'float: left; width: 200px;'; + a href => "/tladmin/$lang?sect=".uri_escape($_->[0]), $_->[0] if $sect ne $_->[0]; + txt $sect if $sect eq $_->[0]; + txt " "; + txt "0/$_->[1]" if !$_->[2]; + b class => 'standout', "$_->[2]/$_->[1]" if $_->[2]; + end; + } + clearfloat; + end; + br; +} + + +sub _page { + my($self, $lang, $sect, $page) = @_; + + form action => "/tladmin/$lang?sect=".uri_escape($sect), method => 'POST', 'accept-charset' => 'utf-8'; + div class => 'mainbox'; + h1 $sect; + + if(_allowed($self, $lang)) { + h2 class => 'alttitle', "Don't forget to hit the 'save' button to make your changes permament!"; + } else { + div class => 'warning'; + h2 'Read-only'; + p "You can't edit this language."; + end; + } + + for my $l (@$page) { + if($l->[0] eq 'comment') { + pre; + b class => 'grayedout', $l->[1]."\n"; + end; + next; + } + + my(undef, $key, $en, $sync, $tl) = @$l; + b class => $sync ? 'grayedout' : 'standout', ":$key"; + br; + div style => 'margin-left: 25px; font: 12px Tahoma; width: 700px; overflow-x: auto; white-space: nowrap', $en; + my $multi = $en =~ y/\n//; + + div style => 'width: 23px; float: left; text-align: right'; + input type => 'checkbox', name => "check$key", id => "check$key", !$sync ? (checked => 'checked') : (); + end; + div style => 'float: left'; + if($multi) { + $tl =~ s/&/&/; + $tl =~ s/</</; + $tl =~ s/>/>/; + textarea name => $key, id => $key, rows => $multi+2, style => 'width: 700px; height: auto; white-space: nowrap; border: none', wrap => 'off'; + lit $tl; + end; + } else { + input type => 'text', class => 'text', name => $key, id => $key, value => $tl, style => 'width: 700px; border: none'; + } + end; + clearfloat; + } + if(_allowed($self, $lang)) { + br;br; + fieldset class => 'submit'; + input type => 'submit', value => 'Save', class => 'submit'; + end; + } + end; + end; +} + + +1; + -- cgit v1.2.3 From 40d71fd459c223fafd4b976c9a4b9628ccc80f25 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Thu, 22 Oct 2009 14:00:44 +0200 Subject: TransAdmin: Fixed comment about how to use it So that it will only be loaded in the scripts where it is used. This is still a rather ugly solution, though. --- lib/VNDB/Plugin/TransAdmin.pm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/VNDB/Plugin/TransAdmin.pm b/lib/VNDB/Plugin/TransAdmin.pm index 5e9f8b1c..742d2ff2 100644 --- a/lib/VNDB/Plugin/TransAdmin.pm +++ b/lib/VNDB/Plugin/TransAdmin.pm @@ -1,10 +1,12 @@ # This plugin provides a quick and dirty user interface to editing lang.txt, # to use it, add the following to your data/config.pl: # -# use VNDB::Plugin::TransAdmin; -# $VNDB::S{transadmin} = { -# <userid> => 'all' || <language> || <arrayref with languages> -# }; +# if($INC{"YAWF.pm"}) { +# require VNDB::Plugin::TransAdmin; +# $VNDB::S{transadmin} = { +# <userid> => 'all' || <language> || <arrayref with languages> +# }; +# } # # And then open /tladmin in your browser. # Also make sure data/lang.txt is writable by the httpd process. -- cgit v1.2.3 From 4170cec21986540ffe0f9025840971ccea682268 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Thu, 22 Oct 2009 15:05:40 +0200 Subject: TransAdmin: Added intro page --- lib/VNDB/Plugin/TransAdmin.pm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/VNDB/Plugin/TransAdmin.pm b/lib/VNDB/Plugin/TransAdmin.pm index 742d2ff2..ebb173f6 100644 --- a/lib/VNDB/Plugin/TransAdmin.pm +++ b/lib/VNDB/Plugin/TransAdmin.pm @@ -50,6 +50,7 @@ sub tladmin { my($self, $lang) = @_; $lang ||= ''; + my $intro = $lang =~ s/intro//; return 404 if $lang && ($lang eq 'en' || !grep $_ eq $lang, $self->{l10n}->languages); my $sect = $self->reqParam('sect')||''; @@ -71,6 +72,7 @@ sub tladmin { $self->htmlHeader(title => 'Quick-and-dirty Translation Editor', noindex => 1); div class => 'mainbox'; + a class => 'addnew', href => '/tladmin/intro', 'README'; h1 'Quick-and-dirty Translation Editor'; h2 class => 'alttitle', 'Step #1: Choose a language'; p class => 'browseopts'; @@ -80,6 +82,7 @@ sub tladmin { _sections($self, $lang, $sect, $sects) if $lang; end; + _intro() if $intro; _page($self, $lang, $sect, $page) if $lang && $sect; $self->htmlFooter; @@ -179,6 +182,18 @@ sub _sections { } +sub _intro { + my $f = LangFile->new(read => $langfile); + my $intro = $f->read; + $intro = join "\n", @$intro[1..$#$intro]; + $f->close; + div class => 'mainbox'; + h1 'Introduction to the language file'; + pre $intro; + end; +} + + sub _page { my($self, $lang, $sect, $page) = @_; -- cgit v1.2.3 From f585ec6696b23565c210e46aa06da4a62f7d5e04 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Thu, 22 Oct 2009 15:21:54 +0200 Subject: LangFile: Use flock()ing Doesn't guarantee that all issues related to multiple processes accessing the same file at the same time, but prevents some of them. --- lib/LangFile.pm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/LangFile.pm b/lib/LangFile.pm index 3c5ab1e2..e81f7f7a 100644 --- a/lib/LangFile.pm +++ b/lib/LangFile.pm @@ -2,10 +2,16 @@ package LangFile; +use strict; +use warnings; +use Fcntl qw(LOCK_SH LOCK_EX SEEK_SET); + sub new { my($class, $action, $file) = @_; open my $F, $action eq 'read' ? '<:utf8' : '>:utf8', $file or die "Opening $file: $!"; + flock($F, $action eq 'read' ? LOCK_SH : LOCK_EX) or die "Locking $file: $!"; + seek($F, 0, SEEK_SET) or die "Seeking $file: $!"; return bless { act => $action, FH => $F, -- cgit v1.2.3 From ae4b696c48a5fd1d7b5548d0697507d2440fa980 Mon Sep 17 00:00:00 2001 From: Dmitri Poguliayev <winkillerstudio@gmail.com> Date: Thu, 22 Oct 2009 15:25:40 +0200 Subject: L10N-RU: Synchronised Russian TL with new lang.txt --- data/lang.txt | 288 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 148 insertions(+), 140 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index 84ac35a0..5cb3d81a 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -234,7 +234,7 @@ hu : Francia :_lang_hu en : Hungarian -ru*: +ru : Венгерский cs*: hu*: @@ -440,67 +440,67 @@ hu : Egyéb :_med_cd en : [quant,_1,CD,CDs] -ru*: +ru : [quant,_1,CD,CD,CD] cs*: hu*: :_med_dvd en : [quant,_1,DVD,DVDs] -ru*: +ru : [quant,_1,DVD,DVD,DVD] cs*: hu*: :_med_gdr en : [quant,_1,GD-ROM,GD-ROMs] -ru*: +ru : [quant,_1,GD-ROM,GD-ROM,GD-ROM] cs*: hu*: :_med_blr en : [quant,_1,Blu-ray disc,Blu-ray discs] -ru*: +ru : [quant,_1,BD-ROM,BD-ROM,BD-ROM] cs*: hu*: :_med_flp en : [quant,_1,Floppy,Floppies] -ru*: +ru : [quant,_1,Дискета,Дискеты,Дискетт] cs*: hu*: :_med_mrt en : [quant,_1,Cartridge,Cartridges] -ru*: +ru : [quant,_1,Картридж,Картриджа,Картриджей] cs*: hu*: :_med_mem en : [quant,_1,Memory card,Memory cards] -ru*: +ru : [quant,_1,Карта памяти,Карты памяти,Карт памяти] cs*: hu*: :_med_umd en : [quant,_1,UMD,UMDs] -ru*: +ru : [quant,_1,UMD,UMD,UMD] cs*: hu*: :_med_nod en : Nintendo Optical [quant,_1,Disk,Disks] -ru*: +ru : [quant,_1,Оптический диск,Оптические диски,Оптических дисков] Nintendo cs*: hu*: :_med_in en : Internet download -ru*: +ru : Распространение через Интернет cs*: hu*: :_med_otc en : Other -ru*: +ru : Другое cs*: hu*: @@ -509,61 +509,61 @@ hu*: :_vnrel_seq en : Sequel -ru*: +ru : Продолжение cs*: hu*: :_vnrel_preq en : Prequel -ru*: +ru : Предыстория cs*: hu*: :_vnrel_set en : Same setting -ru*: +ru : Тот же мир cs*: hu*: :_vnrel_alt en : Alternative version -ru*: +ru : Альтернативная версия cs*: hu*: :_vnrel_char en : Shares characters -ru*: +ru : Те же персонажи cs*: hu*: :_vnrel_side en : Side story -ru*: +ru : Побочный сюжет cs*: hu*: :_vnrel_par en : Parent story -ru*: +ru : Исходный сюжет cs*: hu*: :_vnrel_ser en : Same series -ru*: +ru : Из той же серии cs*: hu*: :_vnrel_fan en : Fandisc -ru*: +ru : Фандиск cs*: hu*: :_vnrel_orig en : Original game -ru*: +ru : Оригинальная игра cs*: hu*: @@ -593,37 +593,37 @@ hu : Amatör csoport :_prodrel_old en : Formerly -ru*: +ru : Изначально cs*: hu*: :_prodrel_new en : Succeeded by -ru*: +ru : Унаследована cs*: hu*: :_prodrel_par en : Parent producer -ru*: +ru : Исходная компания cs*: hu*: :_prodrel_sub en : Subsidairy -ru*: +ru : Второстепенная cs*: hu*: :_prodrel_imp en : Imprint -ru*: +ru : Марка cs*: hu*: :_prodrel_ipa en : Parent brand -ru*: +ru : Исходный бренд cs*: hu*: @@ -653,43 +653,43 @@ hu : Próba :_animetype_tv en : TV Series -ru*: +ru : ТВ Сериал cs*: hu*: :_animetype_ova en : OVA -ru*: +ru : ОВА cs*: hu*: :_animetype_mov en : Movie -ru*: +ru : Фильм cs*: hu*: :_animetype_oth en : Other -ru*: +ru : Другое cs*: hu*: :_animetype_web en : Web -ru*: +ru : Веб-трансляция cs*: hu*: :_animetype_spe en : TV Special -ru*: +ru : ТВ-спешл cs*: hu*: :_animetype_mv en : Music Video -ru*: +ru : Музыкальное видео cs*: hu*: @@ -911,13 +911,13 @@ hu : Közepes[index,_1,, (10 - 30 óra), (Kana: Little Sister)] :_vnlength_4 en : Long[index,_1,, (30 - 50 hours), (Tsukihime)] -ru : Длинная[index,_1,, (30 - 50 часов), (Tsukihime)] +ru : Большая[index,_1,, (30 - 50 часов), (Tsukihime)] cs : Dlouhá[index,_1,, (30 - 50 hours), (Tsukihime)] hu : Hosszú[index,_1,, (30 - 50 óra), (Tsukihime)] :_vnlength_5 en : Very long[index,_1,, (> 50 hours), (Clannad)] -ru : Очень длинная[index,_1,, (> 50 часов), (Clannad)] +ru : Очень большая[index,_1,, (> 50 часов), (Clannad)] cs : Velmi dlouhá[index,_1,, (> 50 hours), (Clannad)] hu : Nagyon hosszú[index,_1,, (> 50 óra), (Clannad)] @@ -926,61 +926,61 @@ hu : Nagyon hosszú[index,_1,, (> 50 óra), (Clannad)] :_rlst_rstat_0 en : Unknown -ru*: +ru : Неизвестно cs*: hu*: :_rlst_rstat_1 en : Pending -ru*: +ru : Ожидает cs*: hu*: :_rlst_rstat_2 en : Obtained -ru*: +ru : Приобретено cs*: hu*: :_rlst_rstat_3 en : On loan -ru*: +ru : Взято напрокат cs*: hu*: :_rlst_rstat_4 en : Deleted -ru*: +ru : Удалено cs*: hu*: :_rlst_vstat_0 en : Unknown -ru*: +ru : Неизвестно cs*: hu*: :_rlst_vstat_1 en : Playing -ru*: +ru : Играю cs*: hu*: :_rlst_vstat_2 en : Finished -ru*: +ru : Завершено cs*: hu*: :_rlst_vstat_3 en : Stalled -ru*: +ru : Застряло cs*: hu*: :_rlst_vstat_4 en : Dropped -ru*: +ru : Заброшено cs*: hu*: @@ -1148,73 +1148,73 @@ hu : Beküldés :_js_expand en : expand -ru*: +ru : развернуть cs*: hu*: :_js_collapse en : collapse -ru*: +ru : свернуть cs*: hu*: :_js_loading en : Loading... -ru*: +ru : Загрузка... cs*: hu*: :_js_date_year en : -year- -ru*: +ru : -год- cs*: hu*: :_js_date_month en : -month- -ru*: +ru : -месяц- cs*: hu*: :_js_date_day en : -day- -ru*: +ru : -день- cs*: hu*: :_js_ds_noresults en : No results... -ru*: +ru : Совпадений не найдено... cs*: hu*: :_js_iv_close en : close -ru*: +ru : закрыть cs*: hu*: :_js_iv_prev en : previous -ru*: +ru : назад cs*: hu*: :_js_iv_next en : next -ru*: +ru : далее cs*: hu*: :_js_ds_tag_meta en : meta -ru*: +ru : мета cs*: hu*: :_js_ds_tag_mod en : awaiting moderation -ru*: +ru : ждёт модерирования cs*: hu*: @@ -2148,13 +2148,13 @@ hu : Jelenleg nincsen visual novel bejegyzésünk ettől a készítőtől. :_prodpage_dev en : developer -ru*: +ru : разработчик cs*: hu*: :_prodpage_pub en : publisher -ru*: +ru : издатель cs*: hu*: @@ -2205,13 +2205,13 @@ hu : Leírás :_revfield_p_relations en : Relations -ru*: +ru : Отношения cs*: hu*: :_proddiff_none en : none -ru*: +ru : нет cs*: hu*: @@ -2220,7 +2220,7 @@ hu*: :_prodrg_title en : Relation graph for [_1] -ru*: +ru : Схема отношений для [_1] cs*: hu*: @@ -2301,55 +2301,55 @@ hu : Leírás :_pedit_form_rel en : Relations -ru*: +ru : Отношения cs*: hu*: :_pedit_rel_sel en : Selected producers -ru*: +ru : Выбранные компании cs*: hu*: :_pedit_rel_add en : Add producer -ru*: +ru : Добавить компанию cs*: hu*: :_pedit_rel_addbut en : add -ru*: +ru : добавить cs*: hu*: :_pedit_rel_del en : remove -ru*: +ru : убрать cs*: hu*: :_pedit_rel_none en : Nothing selected. -ru*: +ru : Ничего не выбрано. cs*: hu*: :_pedit_rel_findformat en : Producer textbox should start with an ID (e.g. "p7:") -ru*: +ru : Строка компании должна начинаться с идентификатора (например, "p7:") cs*: hu*: :_pedit_rel_notfound en : Producer not found -ru*: +ru : Компания не найдена cs*: hu*: :_pedit_rel_double en : Producer already selected! -ru*: +ru : Компания уже выбрана! cs*: hu*: @@ -2519,13 +2519,13 @@ hu : Készítők :_reldiff_developer en : developer -ru*: +ru : разработчик cs*: hu*: :_reldiff_publisher en : publisher -ru*: +ru : издатель cs*: hu*: @@ -2642,13 +2642,13 @@ hu : Korhatár :_relinfo_developer en : [quant,_1,Developer,Developers] -ru*: +ru : [quant,_1,Разработчик,Разработчика,Разработчиков] cs*: hu*: :_relinfo_publisher en : [quant,_1,Publisher,Publishers] -ru*: +ru : [quant,_1,Издатель,Издателя,Издателей] cs*: hu*: @@ -2889,19 +2889,19 @@ hu : Médium :_redit_form_med_quantity en : -quantity- -ru*: +ru : -количество- cs*: hu*: :_redit_form_med_medium en : -medium- -ru*: +ru : -носитель- cs*: hu*: :_redit_form_med_remove en : remove -ru*: +ru : убрать cs*: hu*: @@ -2925,55 +2925,55 @@ hu : Készitő hozzáadása :_redit_form_prod_dev en : Developer -ru*: +ru : Разработчик cs*: hu*: :_redit_form_prod_pub en : Publisher -ru*: +ru : Издатель cs*: hu*: :_redit_form_prod_both en : Both -ru*: +ru : Оба cs*: hu*: :_redit_form_prod_addbut en : add -ru*: +ru : добавить cs*: hu*: :_redit_form_prod_remove en : remove -ru*: +ru : убрать cs*: hu*: :_redit_form_prod_none en : Nothing selected. -ru*: +ru : Ничего не выбрано. cs*: hu*: :_redit_form_prod_pformat en : Producer textbox must start with an ID (e.g. p17) -ru*: +ru : Строка компании должна начинаться с идентификатора (например, p17) cs*: hu*: :_redit_form_prod_notfound en : Producer not found! -ru*: +ru : Компания не найдена! cs*: hu*: :_redit_form_prod_double en : Producer already selected! -ru*: +ru : Компания уже выбрана! cs*: hu*: @@ -2997,37 +2997,37 @@ hu : Visual novel hozzáadása :_redit_form_vn_addbut en : add -ru*: +ru : добавить cs*: hu*: :_redit_form_vn_remove en : remove -ru*: +ru : убрать cs*: hu*: :_redit_form_vn_none en : Nothing selected. -ru*: +ru : Ничего не выбрано. cs*: hu*: :_redit_form_vn_vnformat en : Visual novel textbox must start with an ID (e.g. v17) -ru*: +ru : Строка новеллы должна начинаться с идентификатора (например, v17) cs*: hu*: :_redit_form_vn_notfound en : Visual novel not found! -ru*: +ru : Новелла не найдена! cs*: hu*: :_redit_form_vn_double en : VN already selected! -ru*: +ru : Новелла уже выбрана! cs*: hu*: @@ -3684,43 +3684,43 @@ hu : Menj a [url,/g,cimke listára] ha szeretnél böngészni az összes rendelk :_tagv_spoil0 en : neutral -ru*: +ru : нейтральный cs*: hu*: :_tagv_spoil1 en : no spoiler -ru*: +ru : без спойлеров cs*: hu*: :_tagv_spoil2 en : minor spoiler -ru*: +ru : лёгкий спойлер cs*: hu*: :_tagv_spoil3 en : major spoiler -ru*: +ru : тяжёлый спойлер cs*: hu*: :_tagv_notfound en : Item not found! -ru*: +ru : Элемент не найден! cs*: hu*: :_tagv_nometa en : Can't use meta tags here! -ru*: +ru : Использование мета-тегов здесь запрещено! cs*: hu*: :_tagv_double en : Tag is already present! -ru*: +ru : Тег уже указан! cs*: hu*: @@ -4844,49 +4844,49 @@ hu : Összefüggés hozzáadása # this trick doesn't even work very well in English, so just an approximation is fine :_vnedit_rel_isa en : is a -ru*: +ru : это cs*: hu*: :_vnedit_rel_of en : of -ru*: +ru : для cs*: hu*: :_vnedit_rel_addbut en : add -ru*: +ru : добавить cs*: hu*: :_vnedit_rel_del en : del -ru*: +ru : убрать cs*: hu*: :_vnedit_rel_none en : No relations selected. -ru*: +ru : Отношений не выбрано. cs*: hu*: :_vnedit_rel_findformat en : Visual novel textbox must start with an ID (e.g. v17) -ru*: +ru : Строка новеллы должна начинаться с идентификатора (например, v17) cs*: hu*: :_vnedit_rel_novn en : Visual novel not found! -ru*: +ru : Новелла не найдена! cs*: hu*: :_vnedit_rel_double en : This visual novel has already been selected! -ru*: +ru : Эта новелла уже была выбрана! cs*: hu*: @@ -4924,98 +4924,99 @@ hu : Mielőtt pillanatképeket töltesz fel, tarts néhány dolgot figyelembe:[b :_vnedit_scr_selrel en : -- select release -- -ru*: +ru : -- выбор выпуска -- cs*: hu*: :_vnedit_scr_frmloading en : Please wait for the screenshots to be uploaded before submitting the form. -ru*: +ru : Прежде чем сохранить изменения, дождитесь загрузки скриншотов на сервер. cs*: hu*: :_vnedit_scr_frmnorel en : Please select the appropriate release for every screenshot. -ru*: +ru : Пожалуйста, укажите подходящий выпуск для каждого скриншота. cs*: hu*: :_vnedit_scr_fetching en : Fetching thumbnail... -ru*: +ru : Обработка превьюшки... cs*: hu*: :_vnedit_scr_uploading en : Uploading screenshot -ru*: +ru : Загрузка скриншота cs*: hu*: :_vnedit_scr_upl_msg en : This can take a while, depending on the file size and your upload speed. -ru*: +ru : Это может занять некоторое время, в зависимости от размера файла и скорости вашего соединения. cs*: hu*: :_vnedit_scr_cancel en : cancel -ru*: +ru : отменить cs*: hu*: :_vnedit_scr_full en : Enough screenshots -ru*: +ru : Больше нет места cs*: hu*: :_vnedit_scr_full_msg en : The limit of 10 screenshots per visual novel has been reached. If you want to add a new screenshot, please remove an existing one first. -ru*: +ru : Достигнуто ограничение в 10 скриншотов. + Если вы хотите добавить новый скриншот, пожалуйста удалите один из существующих. cs*: hu*: :_vnedit_scr_add en : Add screenshot -ru*: +ru : Добавить скриншот cs*: hu*: :_vnedit_scr_imgnote en : Image must be smaller than 5MB and in PNG or JPEG format. -ru*: +ru : Изображение должно быть не более 5 Мегабайт и в формате PNG, либо JPEG. cs*: hu*: :_vnedit_scr_addbut en : Upload! -ru*: +ru : Загрузить! cs*: hu*: :_vnedit_scr_id en : Screenshot #[_1] -ru*: +ru : Скриншот #[_1] cs*: hu*: :_vnedit_scr_remove en : remove -ru*: +ru : убрать cs*: hu*: :_vnedit_scr_fullsize en : Full size: [_1] -ru*: +ru : Полный размер: [_1] cs*: hu*: :_vnedit_scr_nsfw en : This screenshot is NSFW -ru*: +ru : Этот скриншот НБДР (NSFW) cs*: hu*: @@ -5023,34 +5024,39 @@ hu*: en : Oops! Seems like something went wrong... Make sure the file you're uploading doesn't exceed 5MB in size. If that isn't the problem, then please report a bug. -ru*: +ru : Э-кхм! Похоже, возникла проблема... + Пожалуйста, убедитесь что ваш файл не превышает размер в 5 Мегабайт. + Если дело не в размере, тогда пожалуйста сообщите администрации сайта об ошибке. cs*: hu*: :_vnedit_scr_errformat en : Upload failed! Only JPEG or PNG images are accepted. -ru*: +ru : Ошибка при загрузке! + Допускаются только JPEG или PNG. cs*: hu*: :_vnedit_scr_errempty en : Upload failed! No file selected, or an empty file? -ru*: +ru : Ошибка при загрузке! + Файл не выбран или имеет нулевой размер. cs*: hu*: :_vnedit_scr_genthumb en : Generating thumbnail... -ru*: +ru : Генерация превьюшки... cs*: hu*: :_vnedit_scr_genthumb_msg en : Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. Please try again later or report a bug if that is the case. -ru*: +ru : Замечание: если эта операция длится более 30 секунд, значит у нас на сервере неполадки. + В таком случае попытайтесь снова или сообщите администрации об ошибках. cs*: hu*: @@ -5299,13 +5305,13 @@ hu : mind :_vnpage_developer en : Developer -ru*: +ru : Разработчик cs*: hu*: :_vnpage_publisher en : Publishers -ru*: +ru : Издатели cs*: hu*: @@ -5366,14 +5372,16 @@ hu : visszavonás :_vnpage_uopt_1vote en : You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played. Are you really sure this visual novel matches that description? -ru*: +ru : Вы собираетесь дать этой новелле оценку 1 из 10. Это весьма сильная оценка, означающая что это совершенно бездарная работа и худшее из всего во что вы играли. + Вы уверены, что эта новелла соответствует такому критерию? cs*: hu*: :_vnpage_uopt_10vote en : You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, meaning this is one of the best visual novels you've ever played and it's unlikely that any other game could ever be better than this one. It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully! -ru*: +ru : Вы собираетесь дать этой новелле оценку 10 из 10. Это весьма сильная оценка, означающая что это одна из лучших когда либо выпущенных новелл, которую вы когда-либо читали. + Вы уверены, что эта новелла соответствует такому критерию? cs*: hu*: @@ -5409,19 +5417,19 @@ hu : eltávolitás a kivánságlistából :_vnpage_uopt_relrstat en : Release status -ru*: +ru : Статус выпуска cs*: hu*: :_vnpage_uopt_relvstat en : Play status -ru*: +ru : Статус играбельности cs*: hu*: :_vnpage_uopt_reldel en : Remove from VN list -ru*: +ru : Убрать из списка новелл cs*: hu*: @@ -5705,13 +5713,13 @@ hu : Kérlek angolul válaszolj! :_rg_notsupp en : Not supported -ru*: +ru : Не поддерживается cs*: hu*: :_rg_notsupp_msg en : Your browser sucks, it doesn't have the functionality to render our nice relation graphs. -ru*: +ru : Ваш браузер настолько отстоен, что даже не может отрендерить наши графики. cs*: hu*: -- cgit v1.2.3 From 296c94e820e0664d5a1efb154ce8505e8eac0c57 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Thu, 22 Oct 2009 15:30:01 +0200 Subject: L10N-EN: Fixed typo with Subsidiary --- data/lang.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/lang.txt b/data/lang.txt index 5cb3d81a..61a3dbfb 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -610,7 +610,7 @@ cs*: hu*: :_prodrel_sub -en : Subsidairy +en : Subsidiary ru : Второстепенная cs*: hu*: -- cgit v1.2.3 From c5ba0795a08d4c1be02331db9ea3867d86fc2119 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Thu, 22 Oct 2009 17:49:51 +0200 Subject: d+: Wrote more extensive credits page and moved link icons to the FAQ --- data/docs/6 | 16 ++++++++++++ data/docs/7 | 63 +++++++++++++++++++++++++++++++++--------------- lib/VNDB/Handler/Misc.pm | 6 +++++ 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/data/docs/6 b/data/docs/6 index 8bbf20a5..c9ab4375 100644 --- a/data/docs/6 +++ b/data/docs/6 @@ -72,3 +72,19 @@ the illegal spreading of visual novels. </p> + +:SUB:Can I link to VNDB? +<p> + Of course you can! We even have some icons you could use to link to and promote + VNDB. Direct linking is, unlike with all other images on this site, allowed.<br /> + <img src="http://static.yorhel.nl/2008/vndb_88x31.gif" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb1.gif" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb2.jpg" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb3.jpg" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb4.jpg" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb5.jpg" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb6.jpg" style="margin: 5px"><br /> + If you feel these banners don't suit your needs, please don't hesitate to make + one yourself. +<p> + diff --git a/data/docs/7 b/data/docs/7 index b20b8e7c..9590cbd0 100644 --- a/data/docs/7 +++ b/data/docs/7 @@ -47,25 +47,50 @@ :SUB:Credits <p> - Due to the sites nature as a wiki, all information in the database is added and - kept up-to-date by active users. VNDB would not have been as large and comprehensive - as it is now without the support of the many contributers. For a complete list of - active contributors, check out the <a href="/u/all?o=d;s=changes">user list</a>. -</p> + <b>Code development</b><br /> + <dl> + <dt>Yorhel</dt><dd>Main developer.</dd> + <dt>3dB</dt><dd>Wrote the current user authentication code and implemented post throttling on the discussion board.</dd> + </dl> + <br /> + <b>Translations</b><br /> + <dl> + <dt>Czech</dt><dd><a href="mailto:nya.chan.production@gmail.com">Nya-chan Production</a></dd> + <dt>Hungarian</dt><dd><a href="mailto:bikmate@gmail.com">Bikfalvi Máté</a></dd> + <dt>Russian</dt><dd><a href="mailto:winkillerstudio@gmail.com">Dmitri Poguliayev</a></dd> + </dl> -:SUB:Link to us -<p> - Due to popular demand, here are some icons you could use to link to and promote - VNDB. Direct linking is, unlike with all other images on this site, allowed.<br /> - <img src="http://static.yorhel.nl/2008/vndb_88x31.gif" style="margin: 5px"> - <img src="http://static.yorhel.nl/2009/vndb1.gif" style="margin: 5px"> - <img src="http://static.yorhel.nl/2009/vndb2.jpg" style="margin: 5px"> - <img src="http://static.yorhel.nl/2009/vndb3.jpg" style="margin: 5px"> - <img src="http://static.yorhel.nl/2009/vndb4.jpg" style="margin: 5px"> - <img src="http://static.yorhel.nl/2009/vndb5.jpg" style="margin: 5px"> - <img src="http://static.yorhel.nl/2009/vndb6.jpg" style="margin: 5px"><br /> - If you feel these banners don't suit your needs, please don't hesitate to make - one yourself. -<p> + <br /> + <b>Skins</b> + <dl> + <dt>applehq</dt><dd> + <a href="?skin=lb">Little Busters! (pink)</a>, + <a href="?skin=term">Neon (black)</a> + </dd><dt>EchoMateria</dt><dd> + <a href="?skin=aselia_01">Aselia (sunset)</a>, + <a href="?skin=carnevale">Gekkou no Carnevale (black)</a>, + <a href="?skin=eiel">EIeL (sand)</a>, + <a href="?skin=ever17_01">Ever17 (light blue)</a>, + <a href="?skin=fate_01">Fate/stay night (rust)</a>, + <a href="?skin=fate_02">Fate/stay night (red)</a>, + <a href="?skin=higu">Higurashi no Naku Koro ni (orange)</a>, + <a href="?skin=lb_02">Little Busters! (sand)</a>, + <a href="?skin=haze">Primitive Link (haze)</a>, + <a href="?skin=saya">Saya no Uta (maroon)</a>, + <a href="?skin=seinarukana">Seinarukana (white)</a>, + <a href="?skin=taka">Sora no Iro, Mizu no Iro (turquoise)</a>, + <a href="?skin=tsukihime">Tsukihime (purple)</a>, + <a href="?skin=tsukihime_02">Tsukihime (black)</a> + </dd><dt>Yorhel</dt><dd> + <a href="?skin=angel">Angelic Serenade (dark blue)</a>, + <a href="?skin=grey">Touhou (grey)</a> + </dd> + </dl> + <br /> + + <b>Top 5 Contributors</b> +:TOP5CONTRIB: + ...and <a href="/u/all?o=d;s=changes">many more</a>. +</p> diff --git a/lib/VNDB/Handler/Misc.pm b/lib/VNDB/Handler/Misc.pm index 72db2489..b2cadbda 100644 --- a/lib/VNDB/Handler/Misc.pm +++ b/lib/VNDB/Handler/Misc.pm @@ -292,6 +292,12 @@ sub docpage { close $F; $ii; }eg; + s{^:TOP5CONTRIB:$}{ + my $l = $self->dbUserGet(results => 6, order => 'c_changes DESC'); + '<dl>'.join('', map $_->{id} == 1 ? () : + sprintf('<dt><a href="/u%d">%s</a></dt><dd>%d</dd>', $_->{id}, $_->{username}, $_->{c_changes}), + @$l).'</dl>'; + }eg; } $self->htmlHeader(title => $title); -- cgit v1.2.3 From 7d99e7d4f5060cc320fa2c4c81bc7c3b0f145b57 Mon Sep 17 00:00:00 2001 From: Nya-chan Production <nya.chan.production@gmail.com> Date: Thu, 22 Oct 2009 17:53:48 +0200 Subject: L10N-CS: Synchronised Czech TL of lang.txt --- data/lang.txt | 298 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 153 insertions(+), 145 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index 61a3dbfb..ee34497a 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -109,43 +109,43 @@ ends with ']'. The following options are supported: :_age_years en : [_1] [quant,_1,year,years] ago ru : [_1] [quant,_1,год,года,лет] назад -cs*: +cs : před [_1] [quant,_1,rokem,roky,roky] hu*: :_age_months en : [_1] [quant,_1,month,months] ago ru : [_1] [quant,_1,месяц,месяца,месяцев] назад -cs*: +cs : před [_1] [quant,_1,měsícem,měsíci,měsíci] hu*: :_age_weeks en : [_1] [quant,_1,week,weeks] ago ru : [_1] [quant,_1,неделя,недели,недель] назад -cs*: +cs : před [_1] [quant,_1,týdnem,týdny,týdny] hu*: :_age_days en : [_1] [quant,_1,day,days] ago ru : [_1] [quant,_1,день,дня,дней] назад -cs*: +cs : před [_1] [quant,_1,dnem,dny,dny] hu*: :_age_hours en : [_1] [quant,_1,hour,hours] ago ru : [_1] [quant,_1,час,часа,часов] назад -cs*: +cs : před [_1] [quant,_1,hodinou,hodinami,hodinami] hu*: :_age_min en : [_1] min ago ru : [_1] [quant,_1,минута,минуты,минут] назад -cs*: +cs : před [_1] min hu*: :_age_sec en : [_1] sec ago ru : [_1] [quant,_1,секунда,секунды,секунд] назад -cs*: +cs : před [_1] s hu*: @@ -235,7 +235,7 @@ hu : Francia :_lang_hu en : Hungarian ru : Венгерский -cs*: +cs : Maďarsky hu*: :_lang_it @@ -441,67 +441,67 @@ hu : Egyéb :_med_cd en : [quant,_1,CD,CDs] ru : [quant,_1,CD,CD,CD] -cs*: +cs : [quant,_1,CD,CD,CD] hu*: :_med_dvd en : [quant,_1,DVD,DVDs] ru : [quant,_1,DVD,DVD,DVD] -cs*: +cs : [quant,_1,DVD,DVD,DVD] hu*: :_med_gdr en : [quant,_1,GD-ROM,GD-ROMs] ru : [quant,_1,GD-ROM,GD-ROM,GD-ROM] -cs*: +cs : [quant,_1,GD-ROM,GD-ROMy,GD-ROMů] hu*: :_med_blr en : [quant,_1,Blu-ray disc,Blu-ray discs] ru : [quant,_1,BD-ROM,BD-ROM,BD-ROM] -cs*: +cs : [quant,_1,disk Blu-ray,disky Blu-ray,disků Blu-ray] hu*: :_med_flp en : [quant,_1,Floppy,Floppies] ru : [quant,_1,Дискета,Дискеты,Дискетт] -cs*: +cs : [quant,_1,disketa,diskety,disket] hu*: :_med_mrt en : [quant,_1,Cartridge,Cartridges] ru : [quant,_1,Картридж,Картриджа,Картриджей] -cs*: +cs : [quant,_1,Cartridge,Cartridge,Cartridgí] hu*: :_med_mem en : [quant,_1,Memory card,Memory cards] ru : [quant,_1,Карта памяти,Карты памяти,Карт памяти] -cs*: +cs : [quant,_1,Paměťová karta,Paměťové karty,Paměťových karet] hu*: :_med_umd en : [quant,_1,UMD,UMDs] ru : [quant,_1,UMD,UMD,UMD] -cs*: +cs : [quant,_1,UMD,UMD,UMD] hu*: :_med_nod en : Nintendo Optical [quant,_1,Disk,Disks] ru : [quant,_1,Оптический диск,Оптические диски,Оптических дисков] Nintendo -cs*: +cs : [quant,_1,Nintendo Optical Disk,Nintendo Optical Disky,Nintendo Optical Disků] hu*: :_med_in en : Internet download ru : Распространение через Интернет -cs*: +cs : Stažení z internetu hu*: :_med_otc en : Other ru : Другое -cs*: +cs : Ostatní hu*: @@ -510,61 +510,61 @@ hu*: :_vnrel_seq en : Sequel ru : Продолжение -cs*: +cs : Pokračování hu*: :_vnrel_preq en : Prequel ru : Предыстория -cs*: +cs : Prequel hu*: :_vnrel_set en : Same setting ru : Тот же мир -cs*: +cs : Stejné zasazení hu*: :_vnrel_alt en : Alternative version ru : Альтернативная версия -cs*: +cs : Alternativní verze hu*: :_vnrel_char en : Shares characters ru : Те же персонажи -cs*: +cs : Sdílí postavy hu*: :_vnrel_side en : Side story ru : Побочный сюжет -cs*: +cs : Vedlejší příběh hu*: :_vnrel_par en : Parent story ru : Исходный сюжет -cs*: +cs : Mateřský příběh hu*: :_vnrel_ser en : Same series ru : Из той же серии -cs*: +cs : Stejná série hu*: :_vnrel_fan en : Fandisc ru : Фандиск -cs*: +cs : Fandisk hu*: :_vnrel_orig en : Original game ru : Оригинальная игра -cs*: +cs : Originální hra hu*: @@ -594,37 +594,37 @@ hu : Amatör csoport :_prodrel_old en : Formerly ru : Изначально -cs*: +cs : Dříve hu*: :_prodrel_new en : Succeeded by ru : Унаследована -cs*: +cs : Nahrazeno hu*: :_prodrel_par en : Parent producer ru : Исходная компания -cs*: +cs : Mateřský producent hu*: :_prodrel_sub en : Subsidiary ru : Второстепенная -cs*: +cs : Vedlejší hu*: :_prodrel_imp en : Imprint ru : Марка -cs*: +cs : Otisk hu*: :_prodrel_ipa en : Parent brand ru : Исходный бренд -cs*: +cs : mateřská značka hu*: @@ -654,43 +654,43 @@ hu : Próba :_animetype_tv en : TV Series ru : ТВ Сериал -cs*: +cs : TV série hu*: :_animetype_ova en : OVA ru : ОВА -cs*: +cs : OVA hu*: :_animetype_mov en : Movie ru : Фильм -cs*: +cs : Film hu*: :_animetype_oth en : Other ru : Другое -cs*: +cs : Ostatní hu*: :_animetype_web en : Web ru : Веб-трансляция -cs*: +cs : Internet hu*: :_animetype_spe en : TV Special ru : ТВ-спешл -cs*: +cs : TV Speciál hu*: :_animetype_mv en : Music Video ru : Музыкальное видео -cs*: +cs : Hudební video hu*: @@ -927,61 +927,61 @@ hu : Nagyon hosszú[index,_1,, (> 50 óra), (Clannad)] :_rlst_rstat_0 en : Unknown ru : Неизвестно -cs*: +cs : Není známo hu*: :_rlst_rstat_1 en : Pending ru : Ожидает -cs*: +cs : V čekání hu*: :_rlst_rstat_2 en : Obtained ru : Приобретено -cs*: +cs : Obdrženo hu*: :_rlst_rstat_3 en : On loan ru : Взято напрокат -cs*: +cs : Vypůjčeno hu*: :_rlst_rstat_4 en : Deleted ru : Удалено -cs*: +cs : Smazáno hu*: :_rlst_vstat_0 en : Unknown ru : Неизвестно -cs*: +cs : Není známo hu*: :_rlst_vstat_1 en : Playing ru : Играю -cs*: +cs : Ve hraní hu*: :_rlst_vstat_2 en : Finished ru : Завершено -cs*: +cs : Dohráno hu*: :_rlst_vstat_3 en : Stalled ru : Застряло -cs*: +cs : Pozastaveno hu*: :_rlst_vstat_4 en : Dropped ru : Заброшено -cs*: +cs : Vyřazeno hu*: @@ -1149,73 +1149,73 @@ hu : Beküldés :_js_expand en : expand ru : развернуть -cs*: +cs : rozbalit hu*: :_js_collapse en : collapse ru : свернуть -cs*: +cs : složit hu*: :_js_loading en : Loading... ru : Загрузка... -cs*: +cs : Nahrává se... hu*: :_js_date_year en : -year- ru : -год- -cs*: +cs : -rok- hu*: :_js_date_month en : -month- ru : -месяц- -cs*: +cs : -měsíc- hu*: :_js_date_day en : -day- ru : -день- -cs*: +cs : -dne- hu*: :_js_ds_noresults en : No results... ru : Совпадений не найдено... -cs*: +cs : Žádné výsledky... hu*: :_js_iv_close en : close ru : закрыть -cs*: +cs : zavřít hu*: :_js_iv_prev en : previous ru : назад -cs*: +cs : předchozí hu*: :_js_iv_next en : next ru : далее -cs*: +cs : další hu*: :_js_ds_tag_meta en : meta ru : мета -cs*: +cs : meta hu*: :_js_ds_tag_mod en : awaiting moderation ru : ждёт модерирования -cs*: +cs : čeká na schválení hu*: @@ -2149,13 +2149,13 @@ hu : Jelenleg nincsen visual novel bejegyzésünk ettől a készítőtől. :_prodpage_dev en : developer ru : разработчик -cs*: +cs : vývojář hu*: :_prodpage_pub en : publisher ru : издатель -cs*: +cs : vydavatel hu*: @@ -2206,13 +2206,13 @@ hu : Leírás :_revfield_p_relations en : Relations ru : Отношения -cs*: +cs : Vztahy hu*: :_proddiff_none en : none ru : нет -cs*: +cs : žádné hu*: @@ -2221,7 +2221,7 @@ hu*: :_prodrg_title en : Relation graph for [_1] ru : Схема отношений для [_1] -cs*: +cs : Graf vztahů pro producenta [_1] hu*: @@ -2302,55 +2302,55 @@ hu : Leírás :_pedit_form_rel en : Relations ru : Отношения -cs*: +cs : Vztahy hu*: :_pedit_rel_sel en : Selected producers ru : Выбранные компании -cs*: +cs : Vybraní producenti hu*: :_pedit_rel_add en : Add producer ru : Добавить компанию -cs*: +cs : Přidat producenta hu*: :_pedit_rel_addbut en : add ru : добавить -cs*: +cs : přidat hu*: :_pedit_rel_del en : remove ru : убрать -cs*: +cs : odebrat hu*: :_pedit_rel_none en : Nothing selected. ru : Ничего не выбрано. -cs*: +cs : Není nic vybráno. hu*: :_pedit_rel_findformat en : Producer textbox should start with an ID (e.g. "p7:") ru : Строка компании должна начинаться с идентификатора (например, "p7:") -cs*: +cs : Textové pole producenta by mělo začínat ID (např. "p7:") hu*: :_pedit_rel_notfound en : Producer not found ru : Компания не найдена -cs*: +cs : Producent nenalezen hu*: :_pedit_rel_double en : Producer already selected! ru : Компания уже выбрана! -cs*: +cs : Producent byl již vybrán! hu*: @@ -2520,13 +2520,13 @@ hu : Készítők :_reldiff_developer en : developer ru : разработчик -cs*: +cs : vývojář hu*: :_reldiff_publisher en : publisher ru : издатель -cs*: +cs : vydavatel hu*: @@ -2643,13 +2643,13 @@ hu : Korhatár :_relinfo_developer en : [quant,_1,Developer,Developers] ru : [quant,_1,Разработчик,Разработчика,Разработчиков] -cs*: +cs : [quant,_1,Vývojář,Vývojáři,Vývojářů] hu*: :_relinfo_publisher en : [quant,_1,Publisher,Publishers] ru : [quant,_1,Издатель,Издателя,Издателей] -cs*: +cs : [quant,_1,Vydavatel,Vydavatelé,Vydavatelů] hu*: :_relinfo_catalog @@ -2890,19 +2890,19 @@ hu : Médium :_redit_form_med_quantity en : -quantity- ru : -количество- -cs*: +cs : -množství- hu*: :_redit_form_med_medium en : -medium- ru : -носитель- -cs*: +cs : -médium- hu*: :_redit_form_med_remove en : remove ru : убрать -cs*: +cs : odebrat hu*: :_redit_form_prod @@ -2926,55 +2926,55 @@ hu : Készitő hozzáadása :_redit_form_prod_dev en : Developer ru : Разработчик -cs*: +cs : Vývojář hu*: :_redit_form_prod_pub en : Publisher ru : Издатель -cs*: +cs : Vydavatel hu*: :_redit_form_prod_both en : Both ru : Оба -cs*: +cs : Obojí hu*: :_redit_form_prod_addbut en : add ru : добавить -cs*: +cs : přidat hu*: :_redit_form_prod_remove en : remove ru : убрать -cs*: +cs : odebrat hu*: :_redit_form_prod_none en : Nothing selected. ru : Ничего не выбрано. -cs*: +cs : Není nic vybráno. hu*: :_redit_form_prod_pformat en : Producer textbox must start with an ID (e.g. p17) ru : Строка компании должна начинаться с идентификатора (например, p17) -cs*: +cs : Textové pole producenta musí začínat ID (např. p17) hu*: :_redit_form_prod_notfound en : Producer not found! ru : Компания не найдена! -cs*: +cs : Producent nenalezen! hu*: :_redit_form_prod_double en : Producer already selected! ru : Компания уже выбрана! -cs*: +cs : Producent byl již vybrán! hu*: :_redit_form_vn @@ -2998,37 +2998,37 @@ hu : Visual novel hozzáadása :_redit_form_vn_addbut en : add ru : добавить -cs*: +cs : přidat hu*: :_redit_form_vn_remove en : remove ru : убрать -cs*: +cs : odebrat hu*: :_redit_form_vn_none en : Nothing selected. ru : Ничего не выбрано. -cs*: +cs : Není nic vybráno. hu*: :_redit_form_vn_vnformat en : Visual novel textbox must start with an ID (e.g. v17) ru : Строка новеллы должна начинаться с идентификатора (например, v17) -cs*: +cs : Vizuální novela musí začínat ID (např. v17) hu*: :_redit_form_vn_notfound en : Visual novel not found! ru : Новелла не найдена! -cs*: +cs : Vizuální novela nenalezena! hu*: :_redit_form_vn_double en : VN already selected! ru : Новелла уже выбрана! -cs*: +cs : VN již byla vybrána! hu*: @@ -3685,43 +3685,43 @@ hu : Menj a [url,/g,cimke listára] ha szeretnél böngészni az összes rendelk :_tagv_spoil0 en : neutral ru : нейтральный -cs*: +cs : neutrální hu*: :_tagv_spoil1 en : no spoiler ru : без спойлеров -cs*: +cs : bez spoilerů hu*: :_tagv_spoil2 en : minor spoiler ru : лёгкий спойлер -cs*: +cs : menší spoilery hu*: :_tagv_spoil3 en : major spoiler ru : тяжёлый спойлер -cs*: +cs : všechny spoilery hu*: :_tagv_notfound en : Item not found! ru : Элемент не найден! -cs*: +cs : Předmět nenalezen! hu*: :_tagv_nometa en : Can't use meta tags here! ru : Использование мета-тегов здесь запрещено! -cs*: +cs : Zde se nedají použít meta-tagy! hu*: :_tagv_double en : Tag is already present! ru : Тег уже указан! -cs*: +cs : Tag už je přiřazen! hu*: @@ -4845,49 +4845,49 @@ hu : Összefüggés hozzáadása :_vnedit_rel_isa en : is a ru : это -cs*: +cs : je hu*: :_vnedit_rel_of en : of ru : для -cs*: +cs : titulu hu*: :_vnedit_rel_addbut en : add ru : добавить -cs*: +cs : přidat hu*: :_vnedit_rel_del en : del ru : убрать -cs*: +cs : smazat hu*: :_vnedit_rel_none en : No relations selected. ru : Отношений не выбрано. -cs*: +cs : Nejsou vybrány žádné vztahy. hu*: :_vnedit_rel_findformat en : Visual novel textbox must start with an ID (e.g. v17) ru : Строка новеллы должна начинаться с идентификатора (например, v17) -cs*: +cs : textové pole vizuální novely musí začínat ID (např. v17) hu*: :_vnedit_rel_novn en : Visual novel not found! ru : Новелла не найдена! -cs*: +cs : Vizuální novela nenalezena! hu*: :_vnedit_rel_double en : This visual novel has already been selected! ru : Эта новелла уже была выбрана! -cs*: +cs : Tato vizuální novela již byla vybrána! hu*: :_vnedit_scr @@ -4925,49 +4925,49 @@ hu : Mielőtt pillanatképeket töltesz fel, tarts néhány dolgot figyelembe:[b :_vnedit_scr_selrel en : -- select release -- ru : -- выбор выпуска -- -cs*: +cs : -- vybrat vydání -- hu*: :_vnedit_scr_frmloading en : Please wait for the screenshots to be uploaded before submitting the form. ru : Прежде чем сохранить изменения, дождитесь загрузки скриншотов на сервер. -cs*: +cs : Prosíme, počkejte na nahrání screenshotů před potvrzením změn. hu*: :_vnedit_scr_frmnorel en : Please select the appropriate release for every screenshot. ru : Пожалуйста, укажите подходящий выпуск для каждого скриншота. -cs*: +cs : Prosíme, vyberte příslušné vydání pro každý screenshot. hu*: :_vnedit_scr_fetching en : Fetching thumbnail... ru : Обработка превьюшки... -cs*: +cs : Načítám náhled... hu*: :_vnedit_scr_uploading en : Uploading screenshot ru : Загрузка скриншота -cs*: +cs : Nahrávám screenshot hu*: :_vnedit_scr_upl_msg en : This can take a while, depending on the file size and your upload speed. ru : Это может занять некоторое время, в зависимости от размера файла и скорости вашего соединения. -cs*: +cs : Toto může chvíli trvat, v závislosti na velikosti souboru a vaší rychlosti uploadu. hu*: :_vnedit_scr_cancel en : cancel ru : отменить -cs*: +cs : zrušit hu*: :_vnedit_scr_full en : Enough screenshots ru : Больше нет места -cs*: +cs : Již máme dostatek screenshotů hu*: :_vnedit_scr_full_msg @@ -4975,49 +4975,50 @@ en : The limit of 10 screenshots per visual novel has been reached. If you want to add a new screenshot, please remove an existing one first. ru : Достигнуто ограничение в 10 скриншотов. Если вы хотите добавить новый скриншот, пожалуйста удалите один из существующих. -cs*: +cs : Limit deseti screenshotů na vizuální novelu byl dosažen. + Pokud chcete přidat další screenshot, prosíme odstraňte nejdříve nějaký již existující. hu*: :_vnedit_scr_add en : Add screenshot ru : Добавить скриншот -cs*: +cs : Přidat screenshot hu*: :_vnedit_scr_imgnote en : Image must be smaller than 5MB and in PNG or JPEG format. ru : Изображение должно быть не более 5 Мегабайт и в формате PNG, либо JPEG. -cs*: +cs : Obrázek musí být menší 5MB a ve formátu PNG nebo JPEG. hu*: :_vnedit_scr_addbut en : Upload! ru : Загрузить! -cs*: +cs : Nahrát! hu*: :_vnedit_scr_id en : Screenshot #[_1] ru : Скриншот #[_1] -cs*: +cs : Screenshot #[_1] hu*: :_vnedit_scr_remove en : remove ru : убрать -cs*: +cs : odebrat hu*: :_vnedit_scr_fullsize en : Full size: [_1] ru : Полный размер: [_1] -cs*: +cs : Plná velikost: [_1] hu*: :_vnedit_scr_nsfw en : This screenshot is NSFW ru : Этот скриншот НБДР (NSFW) -cs*: +cs : Tento screenshot je NSFW hu*: :_vnedit_scr_oops @@ -5027,7 +5028,9 @@ en : Oops! Seems like something went wrong... ru : Э-кхм! Похоже, возникла проблема... Пожалуйста, убедитесь что ваш файл не превышает размер в 5 Мегабайт. Если дело не в размере, тогда пожалуйста сообщите администрации сайта об ошибке. -cs*: +cs : Hups! Zdá se, že se něco pokazilo... + Ujistěte se, že soubor, který nahráváte nemá více jak 5MB. + Pokud v tom problém neleží, nahlaste systémovou chybu. hu*: :_vnedit_scr_errformat @@ -5035,7 +5038,8 @@ en : Upload failed! Only JPEG or PNG images are accepted. ru : Ошибка при загрузке! Допускаются только JPEG или PNG. -cs*: +cs : Nahrání se nezdařilo! + Přijímány jsou pouze obrázky formátu JPEG nebo PNG. hu*: :_vnedit_scr_errempty @@ -5043,13 +5047,14 @@ en : Upload failed! No file selected, or an empty file? ru : Ошибка при загрузке! Файл не выбран или имеет нулевой размер. -cs*: +cs : Nahrání se nezdařilo! + Buď jste nevybrali soubor, nebo byl tento soubor prázdný. hu*: :_vnedit_scr_genthumb en : Generating thumbnail... ru : Генерация превьюшки... -cs*: +cs : Tvořím náhled... hu*: :_vnedit_scr_genthumb_msg @@ -5057,7 +5062,8 @@ en : Note: if this takes longer than 30 seconds, there\'s probably something wro Please try again later or report a bug if that is the case. ru : Замечание: если эта операция длится более 30 секунд, значит у нас на сервере неполадки. В таком случае попытайтесь снова или сообщите администрации об ошибках. -cs*: +cs : Poznámka: Pokud toto zabere více jak 30 sekund, je pravděpodobně chyba někde na naší straně. + Prosíme, zkuste to znovu později nebo nahlaste systémovou chybu, pokud tomu tak je. hu*: @@ -5306,13 +5312,13 @@ hu : mind :_vnpage_developer en : Developer ru : Разработчик -cs*: +cs : Vývojář hu*: :_vnpage_publisher en : Publishers ru : Издатели -cs*: +cs : Vydavatel hu*: :_vnpage_relations @@ -5374,7 +5380,8 @@ en : You are about to give this visual novel a 1 out of 10. This is a rather ext Are you really sure this visual novel matches that description? ru : Вы собираетесь дать этой новелле оценку 1 из 10. Это весьма сильная оценка, означающая что это совершенно бездарная работа и худшее из всего во что вы играли. Вы уверены, что эта новелла соответствует такому критерию? -cs*: +cs : Chystáte se této vizuální novele dát hodnocení 1 z 10. To je celkem extrémní hodnocení, znamenající, že tato hra nemá absolutně nic co nabídnout, a že je to ta nejhorší hra, kterou jste kdy hráli. + Jste si opravdu jisti, že tato vizuální novela odpovídá tomuto popisu? hu*: :_vnpage_uopt_10vote @@ -5382,7 +5389,8 @@ en : You are about to give this visual novel a 10 out of 10. This is a rather ex It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully! ru : Вы собираетесь дать этой новелле оценку 10 из 10. Это весьма сильная оценка, означающая что это одна из лучших когда либо выпущенных новелл, которую вы когда-либо читали. Вы уверены, что эта новелла соответствует такому критерию? -cs*: +cs : Chystáte se této vizuální novele dát hodnocení 10 z 10. To je celkem extrémní hodnocení, znamenající, že to je jedna z nejlepších vizuálních novel, které jste kdy hráli a je nepravděpodobné, že by nějaká další hra mohla být lepší než tato. + Obecně vztao je špatný nápad mít víc jak tři hry s tímto hodnocením ve vašem listu hlasování, vybírejte pečlivě! hu*: :_vnpage_uopt_wishlisted @@ -5418,19 +5426,19 @@ hu : eltávolitás a kivánságlistából :_vnpage_uopt_relrstat en : Release status ru : Статус выпуска -cs*: +cs : Status vydání hu*: :_vnpage_uopt_relvstat en : Play status ru : Статус играбельности -cs*: +cs : Herní status hu*: :_vnpage_uopt_reldel en : Remove from VN list ru : Убрать из списка новелл -cs*: +cs : Odstranit z listu VN hu*: :_vnpage_rel @@ -5714,12 +5722,12 @@ hu : Kérlek angolul válaszolj! :_rg_notsupp en : Not supported ru : Не поддерживается -cs*: +cs : Nepodporováno hu*: :_rg_notsupp_msg en : Your browser sucks, it doesn't have the functionality to render our nice relation graphs. ru : Ваш браузер настолько отстоен, что даже не может отрендерить наши графики. -cs*: +cs : Váš prohlížeč je na nic, nepodporuje vykreslování našich krásných vztahových grafů. hu*: -- cgit v1.2.3 From 6ee4964e7f628042ce351080099dbddb5aa2d8c9 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Thu, 22 Oct 2009 19:43:31 +0200 Subject: TransAdmin: Added simple doc page translation interface --- lib/VNDB/Plugin/TransAdmin.pm | 141 +++++++++++++++++++++++++++++++++++------- 1 file changed, 117 insertions(+), 24 deletions(-) diff --git a/lib/VNDB/Plugin/TransAdmin.pm b/lib/VNDB/Plugin/TransAdmin.pm index ebb173f6..ed5ebb36 100644 --- a/lib/VNDB/Plugin/TransAdmin.pm +++ b/lib/VNDB/Plugin/TransAdmin.pm @@ -1,6 +1,6 @@ # This plugin provides a quick and dirty user interface to editing lang.txt, # to use it, add the following to your data/config.pl: -# +# # if($INC{"YAWF.pm"}) { # require VNDB::Plugin::TransAdmin; # $VNDB::S{transadmin} = { @@ -9,7 +9,7 @@ # } # # And then open /tladmin in your browser. -# Also make sure data/lang.txt is writable by the httpd process. +# Also make sure data/lang.txt and data/docs/* are writable by the httpd process. # English is considered the 'main' language, and cannot be edited using this interface. package VNDB::Plugin::TransAdmin; @@ -53,21 +53,23 @@ sub tladmin { my $intro = $lang =~ s/intro//; return 404 if $lang && ($lang eq 'en' || !grep $_ eq $lang, $self->{l10n}->languages); my $sect = $self->reqParam('sect')||''; + my $doc = $self->reqParam('doc')||''; my $uid = $self->authInfo->{id}; return $self->htmlDenied if !$uid || !$self->{transadmin}{$uid}; - if(!-w $langfile) { + if(!-w $langfile || !-w "$VNDB::ROOT/data/docs" || grep /\.[a-z]{2}$/ && !-w $_, glob "$VNDB::ROOT/data/docs/*") { $self->htmlHeader(title => 'Language file not writable', noindex => 1); div class => 'mainbox'; h1 'Language file not writable'; - div class => 'warning', 'Sorry, I do not have enough permission to write to the language file.'; + div class => 'warning', 'Sorry, I do not have enough permission to write to the language files.'; end; $self->htmlFooter; return; } - _savelang($self, $lang) if $lang && $self->reqMethod eq 'POST' && _allowed($self, $lang); + _savelang($self, $lang) if $lang && $sect && $self->reqMethod eq 'POST' && _allowed($self, $lang); + _savedoc($self, $lang, $doc) if $lang && $doc && $self->reqMethod eq 'POST' && _allowed($self, $lang); my($sects, $page) = _readlang($lang, $sect) if $lang; $self->htmlHeader(title => 'Quick-and-dirty Translation Editor', noindex => 1); @@ -80,10 +82,12 @@ sub tladmin { for grep !/en/, $self->{l10n}->languages; end; _sections($self, $lang, $sect, $sects) if $lang; + _docs($lang, $doc) if $lang; end; _intro() if $intro; - _page($self, $lang, $sect, $page) if $lang && $sect; + _section($self, $lang, $sect, $page) if $lang && $sect; + _doc($self, $lang, $doc) if $lang && $doc; $self->htmlFooter; } @@ -161,12 +165,24 @@ sub _readlang { } +sub _intro { + my $f = LangFile->new(read => $langfile); + my $intro = $f->read; + $intro = join "\n", @$intro[1..$#$intro]; + $f->close; + div class => 'mainbox'; + h1 'Introduction to the language file'; + pre $intro; + end; +} + + sub _sections { my($self, $lang, $sect, $list) = @_; - + br; h2 class => 'alttitle', 'Step #2: Choose a section'; - div style => 'margin: 0 40px'; + div style => 'margin: 0 40px'; for (@$list) { div style => 'float: left; width: 200px;'; a href => "/tladmin/$lang?sect=".uri_escape($_->[0]), $_->[0] if $sect ne $_->[0]; @@ -179,22 +195,11 @@ sub _sections { clearfloat; end; br; + br; } -sub _intro { - my $f = LangFile->new(read => $langfile); - my $intro = $f->read; - $intro = join "\n", @$intro[1..$#$intro]; - $f->close; - div class => 'mainbox'; - h1 'Introduction to the language file'; - pre $intro; - end; -} - - -sub _page { +sub _section { my($self, $lang, $sect, $page) = @_; form action => "/tladmin/$lang?sect=".uri_escape($sect), method => 'POST', 'accept-charset' => 'utf-8'; @@ -229,9 +234,9 @@ sub _page { end; div style => 'float: left'; if($multi) { - $tl =~ s/&/&/; - $tl =~ s/</</; - $tl =~ s/>/>/; + $tl =~ s/&/&/g; + $tl =~ s/</</g; + $tl =~ s/>/>/g; textarea name => $key, id => $key, rows => $multi+2, style => 'width: 700px; height: auto; white-space: nowrap; border: none', wrap => 'off'; lit $tl; end; @@ -252,5 +257,93 @@ sub _page { } +sub _savedoc { + my($self, $lang, $doc) = @_; + + my $file = "$VNDB::ROOT/data/docs/$doc.$lang"; + + open my $f, '<:utf8', "$VNDB::ROOT/data/docs/$doc" or die $!; + my $en = join '', <$f>; + close $f; + + my $tl = $self->reqParam('tl'); + $tl =~ s/\r?\n/\n/g; + + return -e $file && unlink $file if $tl eq $en; + + open $f, '>:utf8', $file or die $!; + print $f $tl; + close $f; + chmod 0666, $file; +} + + +sub _docs { + my($lang, $doc) = @_; + + my @d = map /\.[a-z]{2}$/ || /\/8$/ ? () : s{^.+\/([^/]+)$}{$1} && $_, glob "$VNDB::ROOT/data/docs/*"; + + h2 class => 'alttitle', '...or a doc page'; + div style => 'margin: 0 40px'; + for (sort { $a =~ /^\d+$/ && $b =~ /^\d+$/ ? $a <=> $b : $a cmp $b } @d) { + div style => 'float: left; width: 60px;'; + a href => "/tladmin/$lang?doc=$_", $_ if $_ ne $doc; + txt $_ if $_ eq $doc; + end; + } + clearfloat; + end; +} + + +sub _doc { + my($self, $lang, $doc) = @_; + + open my $f, '<:utf8', "$VNDB::ROOT/data/docs/$doc" or die $!; + my $en = join '', <$f>; + close $f; + + my $tl = $en; + if(open $f, '<:utf8', "$VNDB::ROOT/data/docs/$doc.$lang") { + $tl = join '', <$f>; + close $f; + } + $tl =~ s/&/&/g; + $tl =~ s/</</g; + $tl =~ s/>/>/g; + + + form action => "/tladmin/$lang?doc=$doc", method => 'POST', 'accept-charset' => 'utf-8'; + div class => 'mainbox'; + a class => 'addnew', href => "/d$doc", "View current page" if $doc =~ /^\d+$/; + h1 "Translating page $doc"; + h2 class => 'alttitle', 'Left = English, Right = translation'; + + if(!_allowed($self, $lang)) { + div class => 'warning'; + h2 'Read-only'; + p "You can't edit this language."; + end; + } + + div style => 'width: 48%; margin-right: 10px; overflow-y: auto; float: left'; + pre style => 'font: 12px Tahoma', $en; + end; + textarea name => 'tl', id => 'tl', rows => ($en =~ y/\n//), + style => 'border: none; float: left; width: 49%; white-space: nowrap', wrap => 'off'; + lit $tl; + end; + clearfloat; + if(_allowed($self, $lang)) { + br; + fieldset class => 'submit'; + input type => 'submit', value => 'Save', class => 'submit'; + end; + } + end; + end; +} + + 1; -- cgit v1.2.3 From 45e3b46f3caf53d8e152240104b820f83317047f Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 24 Oct 2009 10:34:31 +0200 Subject: Discussions: Don't allow bots to index user discussion indexes --- lib/VNDB/Handler/Discussions.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/VNDB/Handler/Discussions.pm b/lib/VNDB/Handler/Discussions.pm index 5fedaeed..12b55029 100644 --- a/lib/VNDB/Handler/Discussions.pm +++ b/lib/VNDB/Handler/Discussions.pm @@ -298,7 +298,7 @@ sub board { order => $type eq 'an' ? 't.id DESC' : 'tpl.date DESC', ); - $self->htmlHeader(title => $title, noindex => !@$list); + $self->htmlHeader(title => $title, noindex => !@$list || $type eq 'u'); $self->htmlMainTabs($type, $obj, 'disc') if $iid; div class => 'mainbox'; -- cgit v1.2.3 From 59404b4fd5c54fc924605323eaddf4f172dc1e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bikfalvi=20M=C3=A1t=C3=A9?= <bikmate@gmail.com> Date: Sat, 24 Oct 2009 10:55:19 +0200 Subject: L10N-HU: Synchronised Hungarian TL of lang.txt --- data/lang.txt | 578 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 293 insertions(+), 285 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index ee34497a..a14050c3 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -110,43 +110,43 @@ ends with ']'. The following options are supported: en : [_1] [quant,_1,year,years] ago ru : [_1] [quant,_1,год,года,лет] назад cs : před [_1] [quant,_1,rokem,roky,roky] -hu*: +hu : [_1] [quant,_1,éve,éve] :_age_months en : [_1] [quant,_1,month,months] ago ru : [_1] [quant,_1,месяц,месяца,месяцев] назад cs : před [_1] [quant,_1,měsícem,měsíci,měsíci] -hu*: +hu : [_1] [quant,_1,hónapja,hónapja] :_age_weeks en : [_1] [quant,_1,week,weeks] ago ru : [_1] [quant,_1,неделя,недели,недель] назад cs : před [_1] [quant,_1,týdnem,týdny,týdny] -hu*: +hu : [_1] [quant,_1,hete,hete] :_age_days en : [_1] [quant,_1,day,days] ago ru : [_1] [quant,_1,день,дня,дней] назад cs : před [_1] [quant,_1,dnem,dny,dny] -hu*: +hu : [_1] [quant,_1,napja,napja] :_age_hours en : [_1] [quant,_1,hour,hours] ago ru : [_1] [quant,_1,час,часа,часов] назад cs : před [_1] [quant,_1,hodinou,hodinami,hodinami] -hu*: +hu : [_1] [quant,_1,órája,órája] :_age_min en : [_1] min ago ru : [_1] [quant,_1,минута,минуты,минут] назад cs : před [_1] min -hu*: +hu : [_1] perce :_age_sec en : [_1] sec ago ru : [_1] [quant,_1,секунда,секунды,секунд] назад cs : před [_1] s -hu*: +hu : [_1] másodperce # user ranks @@ -236,7 +236,7 @@ hu : Francia en : Hungarian ru : Венгерский cs : Maďarsky -hu*: +hu : Magyar :_lang_it en : Italian @@ -442,67 +442,67 @@ hu : Egyéb en : [quant,_1,CD,CDs] ru : [quant,_1,CD,CD,CD] cs : [quant,_1,CD,CD,CD] -hu*: +hu : [quant,_1,CD,CD] :_med_dvd en : [quant,_1,DVD,DVDs] ru : [quant,_1,DVD,DVD,DVD] cs : [quant,_1,DVD,DVD,DVD] -hu*: +hu : [quant,_1,DVD,DVD] :_med_gdr en : [quant,_1,GD-ROM,GD-ROMs] ru : [quant,_1,GD-ROM,GD-ROM,GD-ROM] cs : [quant,_1,GD-ROM,GD-ROMy,GD-ROMů] -hu*: +hu : [quant,_1,GD-ROM,GD-ROM] :_med_blr en : [quant,_1,Blu-ray disc,Blu-ray discs] ru : [quant,_1,BD-ROM,BD-ROM,BD-ROM] cs : [quant,_1,disk Blu-ray,disky Blu-ray,disků Blu-ray] -hu*: +hu : [quant,_1,Blu-ray lemez,Blu-ray lemez] :_med_flp en : [quant,_1,Floppy,Floppies] ru : [quant,_1,Дискета,Дискеты,Дискетт] cs : [quant,_1,disketa,diskety,disket] -hu*: +hu : [quant,_1,Floppy,Floppy] :_med_mrt en : [quant,_1,Cartridge,Cartridges] ru : [quant,_1,Картридж,Картриджа,Картриджей] cs : [quant,_1,Cartridge,Cartridge,Cartridgí] -hu*: +hu : [quant,_1,Kazetta,Kazetta] :_med_mem en : [quant,_1,Memory card,Memory cards] ru : [quant,_1,Карта памяти,Карты памяти,Карт памяти] cs : [quant,_1,Paměťová karta,Paměťové karty,Paměťových karet] -hu*: +hu : [quant,_1,Memória kártya,Memória kártya] :_med_umd en : [quant,_1,UMD,UMDs] ru : [quant,_1,UMD,UMD,UMD] cs : [quant,_1,UMD,UMD,UMD] -hu*: +hu : [quant,_1,UMD,UMD] :_med_nod en : Nintendo Optical [quant,_1,Disk,Disks] ru : [quant,_1,Оптический диск,Оптические диски,Оптических дисков] Nintendo cs : [quant,_1,Nintendo Optical Disk,Nintendo Optical Disky,Nintendo Optical Disků] -hu*: +hu : Nintendo Optical [quant,_1,Lemez,Lemezek] :_med_in en : Internet download ru : Распространение через Интернет cs : Stažení z internetu -hu*: +hu : Internetes letöltés :_med_otc en : Other ru : Другое cs : Ostatní -hu*: +hu : Egyéb # VN relations @@ -511,61 +511,61 @@ hu*: en : Sequel ru : Продолжение cs : Pokračování -hu*: +hu : Folytatás :_vnrel_preq en : Prequel ru : Предыстория cs : Prequel -hu*: +hu : Előzmény :_vnrel_set en : Same setting ru : Тот же мир cs : Stejné zasazení -hu*: +hu : Egyforma környezet :_vnrel_alt en : Alternative version ru : Альтернативная версия cs : Alternativní verze -hu*: +hu : Alternatív változat :_vnrel_char en : Shares characters ru : Те же персонажи cs : Sdílí postavy -hu*: +hu : Megosztott szereplők :_vnrel_side en : Side story ru : Побочный сюжет cs : Vedlejší příběh -hu*: +hu : Mellék történet :_vnrel_par en : Parent story ru : Исходный сюжет cs : Mateřský příběh -hu*: +hu : Szüllő történet :_vnrel_ser en : Same series ru : Из той же серии cs : Stejná série -hu*: +hu : Ugyanaz a sorozat :_vnrel_fan en : Fandisc ru : Фандиск cs : Fandisk -hu*: +hu : Rajongó lemez :_vnrel_orig en : Original game ru : Оригинальная игра cs : Originální hra -hu*: +hu : Eredeti játék # producer types @@ -586,7 +586,7 @@ hu : Magánszemély en : Amateur group ru : Любительская группа cs : Amatérská skupina -hu : Amatör csoport +hu : Amatőr csoport # producer relations @@ -595,37 +595,37 @@ hu : Amatör csoport en : Formerly ru : Изначально cs : Dříve -hu*: +hu : Előzőleg :_prodrel_new en : Succeeded by ru : Унаследована cs : Nahrazeno -hu*: +hu : Utódja :_prodrel_par en : Parent producer ru : Исходная компания cs : Mateřský producent -hu*: +hu : Szüllő készítő :_prodrel_sub en : Subsidiary ru : Второстепенная cs : Vedlejší -hu*: +hu : Alválalat :_prodrel_imp en : Imprint ru : Марка cs : Otisk -hu*: +hu : Megjelenési adatok :_prodrel_ipa en : Parent brand ru : Исходный бренд cs : mateřská značka -hu*: +hu : Szüllő márka # release types @@ -655,43 +655,43 @@ hu : Próba en : TV Series ru : ТВ Сериал cs : TV série -hu*: +hu : TV Sorozat :_animetype_ova en : OVA ru : ОВА cs : OVA -hu*: +hu : :_animetype_mov en : Movie ru : Фильм cs : Film -hu*: +hu : Film :_animetype_oth en : Other ru : Другое cs : Ostatní -hu*: +hu : Egyéb :_animetype_web en : Web ru : Веб-трансляция cs : Internet -hu*: +hu : :_animetype_spe en : TV Special ru : ТВ-спешл cs : TV Speciál -hu*: +hu : TV Különkiadás :_animetype_mv en : Music Video ru : Музыкальное видео cs : Hudební video -hu*: +hu : Videoklip # Discussion board types @@ -772,7 +772,7 @@ hu : Néma en : Only ero scenes voiced ru : Озвучены лишь эросцены cs : S hlasem pouze v ero scénách -hu : Csak ero jelenetek szinkronossak +hu : Csak ero jelenetek szinkronosak :_voiced_3 en : Partially voiced @@ -928,61 +928,61 @@ hu : Nagyon hosszú[index,_1,, (> 50 óra), (Clannad)] en : Unknown ru : Неизвестно cs : Není známo -hu*: +hu : Ismeretlen :_rlst_rstat_1 en : Pending ru : Ожидает cs : V čekání -hu*: +hu : Függő :_rlst_rstat_2 en : Obtained ru : Приобретено cs : Obdrženo -hu*: +hu : Megszerezve :_rlst_rstat_3 en : On loan ru : Взято напрокат cs : Vypůjčeno -hu*: +hu : Kölcsönadva :_rlst_rstat_4 en : Deleted ru : Удалено cs : Smazáno -hu*: +hu : Törölve :_rlst_vstat_0 en : Unknown ru : Неизвестно cs : Není známo -hu*: +hu : Ismeretlen :_rlst_vstat_1 en : Playing ru : Играю cs : Ve hraní -hu*: +hu : Játszás :_rlst_vstat_2 en : Finished ru : Завершено cs : Dohráno -hu*: +hu : Befejezve :_rlst_vstat_3 en : Stalled ru : Застряло cs : Pozastaveno -hu*: +hu : Leragadva :_rlst_vstat_4 en : Dropped ru : Заброшено cs : Vyřazeno -hu*: +hu : Lemondva # Form messages @@ -1021,7 +1021,7 @@ hu : Valaki már regisztrált ezzel az email címmel en : Image must be in JPEG or PNG format ru : Изображение должно быть в формате JPEG, либо в формате PNG cs : Obrázek musí být v JPEG nebo PNG formátu -hu : A kép múszáj JPEG vagy PNG formátúmba legyen +hu : A kép muszáj JPEG vagy PNG formátumba legyen :_formerr_e_toolarge en : Image is too large, only 500kB allowed @@ -1033,13 +1033,13 @@ hu : A kép túl nagy, 500kb a megengedett en : You can only register one account from the same IP within 24 hours ru : Вы можете зарегистрировать учётную запись с одного и того же IP лишь по прошествии 24 часов cs : V rámci 24 hodin si lze z jedné IP adresy zaregistrovat pouze jeden účet -hu : 24 óra alatt csak egy fiókot hozzhatsz létre úgyanazzal az IP-vel +hu : 24 óra alatt csak egy fiókot hozhatsz létre ugyanazzal az IP-vel :_formerr_e_nochanges en : No changes, please don't create an entry that is fully identical to another ru : Изменения отсутствуют, пожалуйста не создавайте идентичных копий записей cs : Nenalezeny změny, netvořte prosím záznam, který je plně totožný s jiným -hu : Nem történt változtatás, kérlek ne készíts egy bejegyzést ami teljesen megegyezzik egy másikkal +hu : Nem történt változtatás, kérlek ne készíts egy bejegyzést ami teljesen megegyezik egy másikkal :_formerr_e_doublepost en : Please wait 30 seconds before making another post @@ -1057,13 +1057,13 @@ hu : Hiba en : Form could not be sent: ru : Невозможно отправить форму: cs : Dokument nemohl být odeslán: -hu : Az űrlappot nem sikerült elküldeni: +hu : Az űrlapot nem sikerült elküldeni: :_formerr_required en : [_1] is a required field! ru : [_1] - обязательное поле! cs : [_1] je pole, které musí být vyplněno! -hu : [_1] kitöltésse kötelező! +hu : [_1] kitöltése kötelező! :_formerr_minlength en : [_1]: should have at least [_2] characters @@ -1075,7 +1075,7 @@ hu : [_1]: legalább [_2] karaktert kell tartalmazzon en : [_1]: only [_2] characters allowed ru : [_1]: [quant,_2,разрешён,разрешены,разрешено] лишь [_2] [quant,_2,символ,символа,символов] cs : [_1]: je povoleno maximálně [_2] znaků -hu : [_1]: csakis [_2] karakterek megengedetek +hu : [_1]: csakis [_2] karakterek megengedettek :_formerr_enum en : [_1] must be one of the following: [_2] @@ -1093,7 +1093,7 @@ hu : Rossz alfórum: [_1] en : Tag [url,_1,_2] already exists! ru : Тег [url,_1,_2] уже существует! cs : Tag [url,_1,_2] již existuje! -hu : A(z) [url,_1,_2] cimke már létezik! +hu : A(z) [url,_1,_2] címke már létezik! :_formerr_tpl_mail en : Invalid email address @@ -1150,73 +1150,73 @@ hu : Beküldés en : expand ru : развернуть cs : rozbalit -hu*: +hu : kiterjeszt :_js_collapse en : collapse ru : свернуть cs : složit -hu*: +hu : összevonás :_js_loading en : Loading... ru : Загрузка... cs : Nahrává se... -hu*: +hu : Betöltés... :_js_date_year en : -year- ru : -год- cs : -rok- -hu*: +hu : -év- :_js_date_month en : -month- ru : -месяц- cs : -měsíc- -hu*: +hu : -hónap- :_js_date_day en : -day- ru : -день- cs : -dne- -hu*: +hu : -nap- :_js_ds_noresults en : No results... ru : Совпадений не найдено... cs : Žádné výsledky... -hu*: +hu : Nincs eredmény... :_js_iv_close en : close ru : закрыть cs : zavřít -hu*: +hu : bezárás :_js_iv_prev en : previous ru : назад cs : předchozí -hu*: +hu : előző :_js_iv_next en : next ru : далее cs : další -hu*: +hu : következő :_js_ds_tag_meta en : meta ru : мета cs : meta -hu*: +hu : :_js_ds_tag_mod en : awaiting moderation ru : ждёт модерирования cs : čeká na schválení -hu*: +hu : moderálásra vár @@ -1281,7 +1281,7 @@ hu : Készítők en : Tags ru : Теги cs : Tagy -hu : Cimkék +hu : Címkék :_menu_users en : Users @@ -1357,13 +1357,13 @@ hu : Üzenenteim ([_1]) en : My Recent Changes ru : Мои недавние правки cs : Mé poslední změny -hu : Legútóbbi változtatásaim +hu : Legutóbbi változtatásaim :_menu_mytags en : My Tags ru : Мои теги cs : Moje tagy -hu : Cimkéim +hu : Címkéim :_menu_addvn en : Add Visual Novel @@ -1497,14 +1497,14 @@ hu : lista en : tags ru : теги cs : tagy -hu : cimkék +hu : címkék # modify tags on VN pages :_mtabs_tagmod en : modify tags ru : править теги cs : změnit tagy -hu : cimkék módosítása +hu : címkék módosítása # copy a release :_mtabs_copy @@ -1558,7 +1558,7 @@ hu : törlés en : relations ru : связи cs : vztahy -hu : kapcsolatok +hu : összefüggések # Navigation buttons on the browse pages @@ -1646,7 +1646,7 @@ hu : Keszítők en : Tags ru : Теги cs : Tagy -hu : Cimkék +hu : Címkék :_searchbox_users en : Users @@ -1695,10 +1695,10 @@ cs : VNDB.org se snaží být srozumitelnou databází informací o vizuálních a mohou hodnotit všechny vizuální novely.[br][br] Můžete jen tak [url,/v/all,brouzdat kolem], [url,/u/register,zaregistrovat si účet] nebo se účastnit diskusí o vizuálních novelách nebo VNDB na našem [url,/t,diskusním boardu]. -hu : A VNDB.org arra törekszik, hogy egy átfogó és információdús adatbázist hozzon létre visual novellekről.[br] +hu : A VNDB.org arra törekszik, hogy egy átfogó és információ dús adatbázist hozzon létre visual novellekről.[br] Ez az oldal úgy van felépítve mint egy wiki, s annak érdekében, hogy ez legyen a legnagyobb, legpontosabb és napra kész visual novel adatbázis a weben, mindenki szabadon hozzájárulhat a tartalom bővítéséhez.[br] - Regisztrált felhasználók úgyanakkor listát vezethetnek azokról a játékokról amelyeket már játszottak,játszanak + Regisztrált felhasználók ugyanakkor listát vezethetnek azokról a játékokról amelyeket már játszottak,játszanak vagy épp játszani szeretnének, valamint szavazhatnak is az oldalon tálalható bármely novelre.[br][br] Bátran, [url,/v/all,nézz körül], [url,/u/register,regisztrálj az oldalra] vagy vegyél részt a visual novellek és a VNDB-ről szóló eszmecserékbe a [url,/t,fórumon]. @@ -1765,7 +1765,7 @@ hu : Épp most jelentek meg en : Recent changes ru : Свежие правки cs : Poslední změny -hu : Legútóbbi változtatások +hu : Legutóbbi változtatások :_hist_title_item en : Edit history of [_1] @@ -1780,13 +1780,13 @@ hu : [_1] előzményeinek szerkesztése en : Show automated edits ru : Показать автоматические правки cs : Ukázat automatické editace -hu : Autómata szerkesztések megjelenítése +hu : Automata szerkesztések megjelenítése :_hist_filter_hideauto en : Hide automated edits ru : Скрыть автоматические правки cs : Skrýt automatické editace -hu : Autómata szerkesztések elrejtése +hu : Automata szerkesztések elrejtése :_hist_filter_hidedel en : Hide deleted items @@ -1840,7 +1840,7 @@ hu : Csak a szerkesztések en : Only newly created pages ru : Только новые страницы cs : Pouze nově stvořené stránky -hu : Csak újjonan létrehozott oldalakat +hu : Csak újonnan létrehozott oldalakat :_hist_filter_exrel en : Exclude edits of releases @@ -1862,7 +1862,7 @@ hu : Ezen kiadások szerkesztésének a mellékelése en : Rev. ru : Ревизия cs : Rev. -hu : Javitás +hu : Javítás :_hist_col_date en : Date @@ -1939,7 +1939,7 @@ hu : A téma le van zárva, nem lehet rá válaszolni en : You must be logged in to reply to this thread. ru : Вы должны быть авторизованы чтобы ответить в эту тему. cs : Pro odpověď do tohoto threadu se musíte přihlásit. -hu : Be kell legyél jelentkezve, hogy hozzászolhas a témához. +hu : Be kell legyél jelentkezve, hogy hozzászólhass a témához. :_thread_quickreply_title en : Quick reply @@ -2026,7 +2026,7 @@ hu : Rejtett en : Don't update last modified field ru : Не обновлять дату последнего изменения cs : Neměnit poslední změněné pole -hu : Ne frissítse az utolsó változtatot mezőt +hu : Ne frissítse az utolsó változtatott mezőt :_postedit_form_msg en : Message @@ -2150,13 +2150,13 @@ hu : Jelenleg nincsen visual novel bejegyzésünk ettől a készítőtől. en : developer ru : разработчик cs : vývojář -hu*: +hu : fejlesztő :_prodpage_pub en : publisher ru : издатель cs : vydavatel -hu*: +hu : kiadó # producer diff fields @@ -2207,13 +2207,13 @@ hu : Leírás en : Relations ru : Отношения cs : Vztahy -hu*: +hu : Összefüggések :_proddiff_none en : none ru : нет cs : žádné -hu*: +hu : semmi # Producer relation graph page (/p+/rg) @@ -2222,7 +2222,7 @@ hu*: en : Relation graph for [_1] ru : Схема отношений для [_1] cs : Graf vztahů pro producenta [_1] -hu*: +hu : [_1] összefüggés gráfja # Add/Edit producer @@ -2303,55 +2303,55 @@ hu : Leírás en : Relations ru : Отношения cs : Vztahy -hu*: +hu : Összefüggések :_pedit_rel_sel en : Selected producers ru : Выбранные компании cs : Vybraní producenti -hu*: +hu : Kiválasztott készítők :_pedit_rel_add en : Add producer ru : Добавить компанию cs : Přidat producenta -hu*: +hu : Készítő hozzáadása :_pedit_rel_addbut en : add ru : добавить cs : přidat -hu*: +hu : hozzáad :_pedit_rel_del en : remove ru : убрать cs : odebrat -hu*: +hu : eltávolít :_pedit_rel_none en : Nothing selected. ru : Ничего не выбрано. cs : Není nic vybráno. -hu*: +hu : Nincs semmi kiválasztva. :_pedit_rel_findformat en : Producer textbox should start with an ID (e.g. "p7:") ru : Строка компании должна начинаться с идентификатора (например, "p7:") cs : Textové pole producenta by mělo začínat ID (např. "p7:") -hu*: +hu : A Készítő szövegdoboz egy ID-val kell kezdődjön (pl. "p7:") :_pedit_rel_notfound en : Producer not found ru : Компания не найдена cs : Producent nenalezen -hu*: +hu : A készítő nem található :_pedit_rel_double en : Producer already selected! ru : Компания уже выбрана! cs : Producent byl již vybrán! -hu*: +hu : A készítő már ki van választva! # Browse/search producers @@ -2521,13 +2521,13 @@ hu : Készítők en : developer ru : разработчик cs : vývojář -hu*: +hu : fejlesztő :_reldiff_publisher en : publisher ru : издатель cs : vydavatel -hu*: +hu : kiadó # Information table (on every release page) @@ -2644,13 +2644,13 @@ hu : Korhatár en : [quant,_1,Developer,Developers] ru : [quant,_1,Разработчик,Разработчика,Разработчиков] cs : [quant,_1,Vývojář,Vývojáři,Vývojářů] -hu*: +hu : [quant,_1,Fejlesztő,Fejlesztők] :_relinfo_publisher en : [quant,_1,Publisher,Publishers] ru : [quant,_1,Издатель,Издателя,Издателей] cs : [quant,_1,Vydavatel,Vydavatelé,Vydavatelů] -hu*: +hu : [quant,_1,Kiadó,Kiadók] :_relinfo_catalog en : Catalog no. @@ -2831,7 +2831,7 @@ ru : Дополнительные заметки/комментарии, инф cs : Různé poznámky/komentáře a informace, které se nehodí do předchozích polí. Např.: Cenzurovaná/necenzurovaná verze nebo pro které vydání je patch. hu : Különböző észrevételek/megjegyzések, olyan infók amelyek nem illenek a fenti mezőbe. - Pl. : Cenzurált/Cenzurálatlan, vagy, hogy melyik kiadásra vonatkozik a patch, stb. + Pl. : Cenzúrázott/Cenzúrázatlan, vagy, hogy melyik kiadásra vonatkozik a patch, stb. :_redit_form_format en : Format @@ -2891,19 +2891,19 @@ hu : Médium en : -quantity- ru : -количество- cs : -množství- -hu*: +hu : -mennyiség- :_redit_form_med_medium en : -medium- ru : -носитель- cs : -médium- -hu*: +hu : -medium- :_redit_form_med_remove en : remove ru : убрать cs : odebrat -hu*: +hu : eltávolítás :_redit_form_prod en : Producers @@ -2927,55 +2927,55 @@ hu : Készitő hozzáadása en : Developer ru : Разработчик cs : Vývojář -hu*: +hu : Fejlesztő :_redit_form_prod_pub en : Publisher ru : Издатель cs : Vydavatel -hu*: +hu : Kiadó :_redit_form_prod_both en : Both ru : Оба cs : Obojí -hu*: +hu : Mindkettő :_redit_form_prod_addbut en : add ru : добавить cs : přidat -hu*: +hu : hozzáadd :_redit_form_prod_remove en : remove ru : убрать cs : odebrat -hu*: +hu : eltávolít :_redit_form_prod_none en : Nothing selected. ru : Ничего не выбрано. cs : Není nic vybráno. -hu*: +hu : Nincsen semmi kiválasztva. :_redit_form_prod_pformat en : Producer textbox must start with an ID (e.g. p17) ru : Строка компании должна начинаться с идентификатора (например, p17) cs : Textové pole producenta musí začínat ID (např. p17) -hu*: +hu : A Készítő szövegdoboz muszáj egy ID-val kezdődjön (pl. p17) :_redit_form_prod_notfound en : Producer not found! ru : Компания не найдена! cs : Producent nenalezen! -hu*: +hu : A készítő nem található! :_redit_form_prod_double en : Producer already selected! ru : Компания уже выбрана! cs : Producent byl již vybrán! -hu*: +hu : A készítő már ki van választva! :_redit_form_vn en : Visual novels @@ -2999,37 +2999,37 @@ hu : Visual novel hozzáadása en : add ru : добавить cs : přidat -hu*: +hu : hozzáadd :_redit_form_vn_remove en : remove ru : убрать cs : odebrat -hu*: +hu : eltávolít :_redit_form_vn_none en : Nothing selected. ru : Ничего не выбрано. cs : Není nic vybráno. -hu*: +hu : Nincsen semmi kiválasztva :_redit_form_vn_vnformat en : Visual novel textbox must start with an ID (e.g. v17) ru : Строка новеллы должна начинаться с идентификатора (например, v17) cs : Vizuální novela musí začínat ID (např. v17) -hu*: +hu : A Visual novel szövegdoboz muszáj egy ID-val kezdődjön (pl. v17) :_redit_form_vn_notfound en : Visual novel not found! ru : Новелла не найдена! cs : Vizuální novela nenalezena! -hu*: +hu : A visual novel nem található! :_redit_form_vn_double en : VN already selected! ru : Новелла уже выбрана! cs : VN již byla vybrána! -hu*: +hu : A visual novel már ki van választva! # Release browser @@ -3074,9 +3074,9 @@ ru : Простите, по вашему запросу ничего не най cs : Omlouváme se, nenalezli jsme nic, co by vyhovovalo vašemu nastavení filtrů. Možná najdete více výsledků, pokud nějaké z nich vypnete. Také nezapomeňte, že o všech vydáních nemáme všechny údaje. Takže pokud například vyfiltrujete rozlišení obrazovky, pak ve výsledcích nebudou všechna vydání, u kterých neznáme jejich rozlišení, i když by to mohla být právě vydání v rozlišení, o které se zajímáte. -hu : Bocs, de ezzekel a szűrőkkel nem található semmi. Talán ki kéne kapcsolj egy párat, hogy több eredmény jöjjön ki. +hu : Bocs, de ezekkel a szűrőkkel nem található semmi. Talán ki kéne kapcsolj egy párat, hogy több eredmény jöjjön ki. - Valamint, ne felejtsd el, hogy nincsen minden kiadásról elégséges információnk. Szóval ha bekapcsolod a felbontásra vonatkozó szűrőt, azokat nem mutatja amelyeknek nincs megadva a felbontásuk, még akkor is ha valójabban annyi, mint amennyit te keresel. + Valamint, ne felejtsd el, hogy nincsen minden kiadásról elégséges információnk. Szóval ha bekapcsolod a felbontásra vonatkozó szűrőt, azokat nem mutatja amelyeknek nincs megadva a felbontásuk, még akkor is ha valójában annyi, mint amennyit te keresel. :_rbrowse_filters en : Filters @@ -3237,13 +3237,13 @@ hu : Törlés en : [index,_1,Meta tag,Tag]: [_2] ru : [index,_1,Мета тег,Тег]: [_2] cs : [index,_1,Meta tag,Tag]: [_2] -hu : [index,_1,Meta Cimke,Cimke]: [_2] +hu : [index,_1,Meta Címke,Címke]: [_2] :_tagp_del_title en : Tag deleted ru : Тег удалён cs : Tag smazán -hu : Cimke törölve +hu : Címke törölve :_tagp_del_msg en : This tag has been removed from the database, and cannot be used or re-added. @@ -3252,7 +3252,7 @@ ru : Данный тег удалён из базы данных, и не мож Напишите на [url,/t/db,форуме], если вы с этим не согласны. cs : Tento tag byl smazán z databáze a nemůže být použit nebo znovu přidán. Pokud s tímto nesouhlasíte, napište žádost na [url,/t/db,diskusní board]. -hu : Ez a cimke törölve lett az adatbázisból, s nem lehetséges visszaállitani vagy használni. +hu : Ez a címke törölve lett az adatbázisból, s nem lehetséges visszaállítani vagy használni. Tegyél panaszt a [url,/t/db,fórumon] ha nem értesz egyet. :_tagp_pending_title @@ -3265,19 +3265,19 @@ hu : Megerősítésre vár en : 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. ru : Данный тег ожидает одобрения модератором. Однако, вы можете использовать его для пометки новелл, как и любой нормальный тег. cs : Tento tag čeká na schválení moderátorem. Mezitím ho stále můžete používat jako normální tag. -hu : Ez a cimke arra vár, hogy egy moderátor elfogadja. Azonban használhatod bármely VN-nél nyugodtan akárcsak egy normális cimkét. +hu : Ez a címke arra vár, hogy egy moderátor elfogadja. Azonban használhatod bármely VN-nél nyugodtan akárcsak egy normális címkét. :_tagp_addchild en : Create child tag ru : Создать дочерний тег cs : Vytvořit závislý tag -hu : Gyerek cimke létrehozássa +hu : Gyerek címke létrehozása :_tagp_indexlink en : Tags ru : Теги cs : Tagy -hu : Cimkék +hu : Címkék :_tagp_aliases en : Aliases @@ -3289,19 +3289,19 @@ hu : Más nevek en : Child tags ru : Дочерние теги cs : Závislé tagy -hu : Gyerek cimkék +hu : Gyerek címkék :_tagp_tree en : Tag tree ru : Древо тега cs : Strom tagů -hu : Cimke fa +hu : Címke fa :_tagp_moretags en : [_1] more [quant,_1,tag,tags] ru : ещё [_1] [quant,_1,тег,тега,тегов] cs : [_1] [quant,_1,další tag,další tagy,dalších tagů] -hu : [_1] több [quant,_1,cimke,cimkék] +hu : [_1] több [quant,_1,címke,címkék] :_tagp_vnlist en : Visual novels @@ -3331,13 +3331,13 @@ hu : Nagyobb spoilerek megjelenítése en : This tag has not been linked to any visual novels yet, or they were hidden because of the spoiler settings. ru : Этот тег пока не содержит ссылок ни на одну новеллу, либо они скрыты из-за настроек отображения спойлеров. cs : Tento tag ještě nebyl použit v žádné vizuální novele nebo byly tyto skryty kvůli nastavení spoilerů. -hu : Ez a cimke eddig egy visual novelhez sincs hozzárendelve, vagy el lettek rejtve a spoiler-ek beállítása során. +hu : Ez a címke eddig egy visual novelhez sincs hozzárendelve, vagy el lettek rejtve a spoiler-ek beállítása során. :_tagp_cached en : NOTE: 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. ru : ЗАМЕЧАНИЕ: Данный список кэшируется, поэтому может пройти вплоть до 24 часов, прежде чем новелла, помеченная тегом, отобразится на этой странице. cs : POZNÁMKA: Tento list se ukládá do cache, takže může trvat až 24 hodin po otagování vizuální novely do objevení se na této stránce. -hu : FIGYELEM: Ez a lista le van mentve a gyorsítótárba, beletelhet 24 órába míg a visual novelhez újjonan hozzárendelt cimke megjelenik ezzen az oldalon. +hu : FIGYELEM: Ez a lista le van mentve a gyorsítótárba, beletelhet 24 órába míg a visual novelhez újonnan hozzárendelt címke megjelenik ezen az oldalon. :_tagp_vncol_score en : Score @@ -3370,37 +3370,37 @@ hu : Népszerűség en : Tag '[_1]' not found ru : Тег '[_1]' не найден cs : Tag '[_1]' nenalezen -hu : A(z) '[_1]' cimke nem található +hu : A(z) '[_1]' címke nem található :_tagedit_title_add en : Add child tag to [_1] ru : Добавление дочернего тега для '[_1]' cs : Přidat závislý tag tagu [_1] -hu : Gyerek cimke hozzárendelése a(z) [_1] - hez +hu : Gyerek címke hozzárendelése a(z) [_1] - hez :_tagedit_title_edit en : Edit tag: [_1] ru : Править тег: [_1] cs : Editovat tag: [_1] -hu : Cimke szerkesztése: [_1] +hu : Címke szerkesztése: [_1] :_tagedit_title_new en : Add new tag ru : Добавить новый тег cs : Přidat nový tag -hu : Új cimke készítése +hu : Új címke készítése :_tagedit_req_title en : Requesting new tag ru : Запросить новый тег cs : Požaduje se nový tag -hu : Új cimke kérése +hu : Új címke kérése :_tagedit_req_subtitle en : Your tag must be approved ru : Ваш тег должен быть одобрен cs : Váš tag musí být schválen -hu : A cimkédet előbb el kell fogadják +hu : A címkédet előbb el kell fogadják :_tagedit_req_msg en : Because all tags have to be approved by moderators, it can take a while before it will show up in the tag list @@ -3415,10 +3415,10 @@ cs : Protože všechny tagy musí být schválené moderátorem, může chvilku nebo na stránce vizuální novely. I před schválením ale můžete stále tag hodnotit. [br][br] Také se ujistěte, že jste přečetli [url,/d10,doporučení], abyste věděli, zda váš tag bude přidán nebo ne. -hu : Mivel minden cimkét külön el kell fogadjanak a moderátorok, beletarthat egy kis időbe míg azok megjelennek a listába - vagy a visual novellek oldalain. Viszont, akkor is tudsz egy cimkére szavazni, ha még nincsen elfogadva. +hu : Mivel minden címkét külön el kell fogadjanak a moderátorok, beletarthat egy kis időbe míg azok megjelennek a listába + vagy a visual novellek oldalain. Viszont, akkor is tudsz egy címkére szavazni, ha még nincsen elfogadva. [br][br] - Valamint, olvasd el az [url,/d10,útmutatót], ha biztosra akarsz menni, hogy a cimkédet el fogják fogadni vagy nem. + Valamint, olvasd el az [url,/d10,útmutatót], ha biztosra akarsz menni, hogy a címkédet el fogják fogadni vagy nem. :_tagedit_frm_name en : Primary name @@ -3460,13 +3460,13 @@ hu : Elfogadva en : This is a meta-tag (only to be used as parent for other tags, not for linking to VN entries) ru : Это мета-тег (его нельзя добавлять к новеллам, он может использоваться лишь как родитель для других тегов) cs : Toto je meta-tag (používá se pouze jako mateřský pro ostatní tagy, ne pro vlastní vizuální novely) -hu : Ez itt egy meta-cimke (csakis más cimkék szűlője ként használandó, nem pedig VN bejegyzésekhez) +hu : Ez itt egy meta-címke (csakis más címkék szülője ként használandó, nem pedig VN bejegyzésekhez) :_tagedit_frm_meta_warn en : WARNING: Checking this option or selecting "Deleted" as state will permanently delete all existing VN relations! ru : ПРЕДУПРЕЖДЕНИЕ: Если выбрать данную опцию, либо выставить состояние "Удалён", произойдёт немедленное удаление всех существующих связей с новеллами! cs : VAROVÁNÍ: Zaškrtnutí této volby nebo výběr položky "Smazáno" jako stavu smaže automaticky tag u všech vizuálních novel! -hu : FIGYELEM: Ezzen opció bejelölése vagy a "Törölve" állapot kiválasztása véglegesen megsemmísit minden összefüggést a VN-ekel! +hu : FIGYELEM: Ezen opció bejelölése vagy a "Törölve" állapot kiválasztása véglegesen megsemmisít minden összefüggést a VN-ekel! :_tagedit_frm_alias en : Aliases @@ -3488,31 +3488,31 @@ hu : Leírás en : What should the tag be used for? Having a good description helps users choose which tags to link to a VN. ru : Для пометки чего будет использоваться тег? Хорошее описание поможет пользователям выбрать подходящий тег для подходящей новеллы. cs : Pro co by měl být tag používán? Tagy s dobrým popisem usnadňují uživatelům jejich používání u vizuálních novel. -hu : Mire és mikor használja valaki a cimkét? Egy jó leírás megkönyíti a felhasználók dolgát mikor hozzá akarják rendelni egy VN-hez. +hu : Mire és mikor használja valaki a címkét? Egy jó leírás megkönnyíti a felhasználók dolgát mikor hozzá akarják rendelni egy VN-hez. :_tagedit_frm_parents en : Parent tags ru : Родительские теги cs : Mateřské tagy -hu : Szűlő cimkék +hu : Szülő címkék :_tagedit_frm_parents_msg en : Comma separated list of tag names to be used as parent for this tag. ru : Теги, которые будут задействованы для этого в качестве родительских. Через запятую. cs : Seznam tagů, oddělených čárkou, které mají být použity jako mateřské pro tento tag -hu : Vesszővel elválasztot cimke nevek amelyek szűlő ként szolgálnak ennek a cimkének. +hu : Vesszővel elválasztott címke nevek amelyek szülő ként szolgálnak ennek a címkének. :_tagedit_frm_merge en : Merge tags ru : Объединение тегов cs : Sjednotit tagy -hu : Cimkék egyesítése +hu : Címkék egyesítése :_tagedit_frm_merge_tags en : Tags to merge ru : Теги для объединения cs : Tagy ke sjednocení -hu : Egyesítésre váró cimkék +hu : Egyesítésre váró címkék :_tagedit_frm_merge_msg en : Comma separated list of tag names to merge into this one. All votes and aliases/names will be moved over @@ -3524,8 +3524,8 @@ ru : Список тегов для объединения в данный, че cs : Seznam tagů, oddělených čárkou, ke sjednocení do tohoto. Všechny hlasy a aliasy/jména budou přesunuty do tohoto tagu a staré tagy budou smazány. Nechte toto pole prázdné, pokud nehodláte nic sjednocovat. [br]VAROVÁNÍ: tato akce nejde vrátit! -hu : Egy lista, veszővel elválasztot cimke nevekkel amelyeket egyesíteni akarsz ebbe az egybe. Minden szavazat és aliasz/nevek át lesznek - helyezve ehhez az új cimkéhez és a régi cimkék pedig törölve lesznek. Ha nem akarsz cimkéket egyesíteni akkor ezt a mezőt hagyd űresen. +hu : Egy lista, veszővel elválasztott címke nevekkel amelyeket egyesíteni akarsz ebbe az egybe. Minden szavazat és alias/nevek át lesznek + helyezve ehhez az új címkéhez és a régi címkék pedig törölve lesznek. Ha nem akarsz címkéket egyesíteni akkor ezt a mezőt hagyd üresen. [br]FIGYELEM: ez a művelet végleges, nem lehet visszavonni! @@ -3535,7 +3535,7 @@ hu : Egy lista, veszővel elválasztot cimke nevekkel amelyeket egyesíteni akar en : Browse tags ru : Обзор тегов cs : Procházet tagy -hu : Cimkék böngészése +hu : Címkék böngészése :_tagb_state-1 en : All @@ -3577,7 +3577,7 @@ hu : Létrehozva en : Tag ru : Тег cs : Tag -hu : Cimke +hu : Címke :_tagb_note_awaiting en : awaiting moderation @@ -3598,19 +3598,19 @@ hu : törölve en : Add/remove tags for [_1] ru : Добавление/удаление тегов для [_1] cs : Přidat/odebrat tag pro novelu [_1] -hu : Cimke hozzáadása/törlése [_1]-hez +hu : Címke hozzáadása/törlése [_1]-hez :_tagv_msg_title en : Tagging ru : Пометка тегами cs : Tagování -hu : Cimkézés +hu : Címkézés :_tagv_msg_guidelines en : Make sure you have read the [url,/d10,guidelines]! ru : Пожалуйста, убедитесь что прочли [url,/d10,рекомендации]! cs : Ujistěte se, že jste přečetli [url,/d10,doporučení]! -hu : Olvasdd el az [url,/d10,utmutatókat]! +hu : Olvasd el az [url,/d10,útmutatókat]! :_tagv_msg_submit en : Don't forget to hit the submit button on the bottom of the page to make your changes permanent. @@ -3622,13 +3622,13 @@ hu : Ne felejtsd el megnyomni a beküldés gombot a lap alján, hogy véglegesí en : Some tag information on the site is cached, it can take up to an hour for your changes to be visible everywhere. ru : Информация о некоторых тегах на данном сайте кэшируется, поэтому ваши изменения станут видны везде в течение часа. cs : Některé informace o tazích na této stránce jsou v cache a může zabrat až hodinu než budou změny vidět. -hu : Valamely cimkékkel kapcsolatos információ le van mentve a gyorsítótárba, beletelhet egy órába is mire mindenhol láthatóvá válnak a változtatások. +hu : Valamely címkékkel kapcsolatos információ le van mentve a gyorsítótárba, beletelhet egy órába is mire mindenhol láthatóvá válnak a változtatások. :_tagv_frm_title en : Tags ru : Теги cs : Tagy -hu : Cimkék +hu : Címkék :_tagv_col_you en : You @@ -3646,7 +3646,7 @@ hu : Egyebek en : Tag ru : Тег cs : Tag -hu : Cimke +hu : Címke :_tagv_col_rating en : Rating @@ -3670,7 +3670,7 @@ hu : Változtatások mentése en : Add tag ru : Добавить тег cs : Přidat tag -hu : Cimke hozzáadása +hu : Címke hozzáadása :_tagv_addmsg en : Check the [url,/g,tag list] to browse all available tags.[br] @@ -3679,50 +3679,50 @@ ru : Откройте [url,/g,список тегов] чтобы увидеть Не нашли что искали? Вы можете [url,/g/new,запросить новый тег]. cs : Zkontrolujte [url,/g,list tagů] pro seznam všech dostupných tagů.[br] Nenašli jste, co jste hledali? [url,/g/new,Vyžádejte si nový tag]. -hu : Menj a [url,/g,cimke listára] ha szeretnél böngészni az összes rendelkezésre álló cimke közt.[br] - Nem találod azt amelyiket keresed? [url,/g/new,Itt kérhetsz egy új cimkét]. +hu : Menj a [url,/g,cimke listára] ha szeretnél böngészni az összes rendelkezésre álló címke közt.[br] + Nem találod azt amelyiket keresed? [url,/g/new,Itt kérhetsz egy új címkét]. :_tagv_spoil0 en : neutral ru : нейтральный cs : neutrální -hu*: +hu : semleges :_tagv_spoil1 en : no spoiler ru : без спойлеров cs : bez spoilerů -hu*: +hu : nem spoiler :_tagv_spoil2 en : minor spoiler ru : лёгкий спойлер cs : menší spoilery -hu*: +hu : kisebb spoiler :_tagv_spoil3 en : major spoiler ru : тяжёлый спойлер cs : všechny spoilery -hu*: +hu : nagyobb spoiler :_tagv_notfound en : Item not found! ru : Элемент не найден! cs : Předmět nenalezen! -hu*: +hu : A tárgy nem található! :_tagv_nometa en : Can't use meta tags here! ru : Использование мета-тегов здесь запрещено! cs : Zde se nedají použít meta-tagy! -hu*: +hu : Itt nem használhatsz meta címkéket! :_tagv_double en : Tag is already present! ru : Тег уже указан! cs : Tag už je přiřazen! -hu*: +hu : A címke már jelen van! # User tag list (/u+/tags) @@ -3731,19 +3731,19 @@ hu*: en : Tags by [_1] ru : Теги [_1] cs : Tagy podle [_1] -hu : [_1] által létrehozott cimkék +hu : [_1] által létrehozott címkék :_tagu_spoilerwarn en : Warning: spoilery tags are not hidden in this list! ru : Предупреждение: в этом списке отображаются теги-спойлеры! cs : Varování: spoilerové tagy nejsou v tomto seznamu skryté! -hu : Figyelem: ebbe a listába a spoiler-t tartalmazó cimkek nincsenek elrejtve! +hu : Figyelem: ebbe a listába a spoiler-t tartalmazó címkék nincsenek elrejtve! :_tagu_notags en : [_1] doesn't seem to have used the tagging system yet... ru : Похоже, что [_1] пока не использует систему тегов... cs : Nezdá se, že by [_1] zatím použil tagovací systém... -hu : Úgy tűnik, hogy [_1] még nem használta a cimkéző rendszert... +hu : Úgy tűnik, hogy [_1] még nem használta a címkéző rendszert... :_tagu_col_num en : #VNs @@ -3755,7 +3755,7 @@ hu : #VN-nek en : Tag ru : Тег cs : Tag -hu : Cimke +hu : Címke :_tagu_spoil0 en : No spoiler @@ -3767,13 +3767,13 @@ hu : Nem spoiler en : Minor spoiler ru : Лёгкий спойлер cs : Menší spoilery -hu : Enyhe spoiler +hu : Kisebb spoiler :_tagu_spoil2 en : Major spoiler ru : Жёсткий спойлер cs : Všechny spoilery -hu : Nagy spoiler +hu : Nagyobb spoiler # Tag index (/g) @@ -3782,25 +3782,25 @@ hu : Nagy spoiler en : Tag index ru : Индекс тега cs : Seznam tagů -hu : Cimke index +hu : Címke index :_tagidx_create en : Create new tag ru : Создать новый тег cs : Vytvořit nový tag -hu : Új cimke létrehozássa +hu : Új címke létrehozása :_tagidx_search en : Search tags ru : Поиск тегов cs : Hledat tag -hu : Cimkék keresése +hu : Címkék keresése :_tagidx_browseall en : Browse all tags ru : Обзор всех тегов cs : Procházet všechny tagy -hu : Összes cimke böngészése +hu : Összes címke böngészése :_tagidx_recent en : Recently added @@ -3812,7 +3812,7 @@ hu : Nemrég hozzáadva en : Popular tags ru : Популярные теги cs : Populární tagy -hu : Népszerű cimkék +hu : Népszerű címkék :_tagidx_queue en : Awaiting moderation @@ -3836,7 +3836,7 @@ hu : Moderálásra váró lista en : Denied tags ru : Отклонённые теги cs : Zamítnuté tagy -hu : Megtagadot cimkék +hu : Megtagadott címkék @@ -3853,19 +3853,19 @@ hu : Megtagadot cimkék en : My wishlist ru : Мой список желаемого cs : Můj wishlist -hu : Kivánságlistám +hu : Kívánságlistám :_wishlist_title_other en : [_1]'s wishlist ru : Список желаемого [_1] cs : Wishlist uživatele [_1] -hu : [_1] kivánság listája +hu : [_1] kívánság listája :_wishlist_noresults en : Wishlist empty... ru : Список пуст... cs : Wishlist je prázdný... -hu : Kivánságlista üres... +hu : Kívánságlista üres... :_wishlist_prio_all en : All priorities @@ -3907,7 +3907,7 @@ hu : Prioritás megváltoztatása en : remove from wishlist ru : убрать из списка желаемого cs : odstranit z wishlistu -hu : eltávolítás a kivánságlistából +hu : eltávolítás a kívánságlistából # VN list (/u+/list) @@ -4047,13 +4047,13 @@ hu : elrejtve en : Tags ru : Теги cs : Tagy -hu : Cimkék +hu : Címkék :_userpage_tags_item en : [_1] [quant,_1,vote,votes] on [_2] distinct [quant,_2,tag,tags] and [_3] visual [quant,_3,novel,novels] ru : [_1] [quant,_1,голос,голоса,голосов] по [_2][quant,_2,-у тегу,-м различным тегам,-и различным тегам] и [_3][quant,_3,-й новелле,-м новеллам,-и новеллам] cs : [_1] [quant,_1,hlasy,hlasy,hlasů] pro [_2] [quant,_2,tag,různé tagy,různých tagů] a [_3] [quant,_3,vizuální novelu,vizuální novely,vizuálních novel] -hu : [_1] [quant,_1,szavazat,szavazat] [_2] egyedi [quant,_2,cimkére,cimkére] és [_3] visual [quant,_3,novelre,novelre] +hu : [_1] [quant,_1,szavazat,szavazat] [_2] egyedi [quant,_2,címkére,címkére] és [_3] visual [quant,_3,novelre,novelre] :_userpage_list en : List stats @@ -4077,7 +4077,7 @@ hu : Fórum adatok en : [_1] [quant,_1,post,posts], [_2] new [quant,_2,thead,threads]. ru : [_1] [quant,_1,сообщение,сообщения,сообщений], [_2] [quant,_2,новая тема,новые темы,новых тем] cs : [_1] [quant,_1,příspěvek, příspěvky, příspěvků], [_2] [quant,_2,nový thread, nové thready, nových threadů]. -hu : [_1] [quant,_1,válasz,válaszok], [_2] új [quant,_2,téma,témá]. +hu : [_1] [quant,_1,válasz,válaszok], [_2] új [quant,_2,téma,téma]. :_userpage_forum_browse en : Browse posts @@ -4167,8 +4167,8 @@ cs : Zdravíme, [_1] A snažte se už heslo znovu nezapomenout! :-) hu : Üdv [_1] - A jelszavad vissza lett állítva, mostmár bejelentkezhetsz a http://vndb.org/ címmen az - új adataidal: + A jelszavad vissza lett állítva, most már bejelentkezhetsz a http://vndb.org/ címen az + új adataiddal: Felhasználónév: [_1] Jelszó: [_2] @@ -4201,8 +4201,8 @@ cs : Zapomněli jste své heslo a nemůžete se přihlásit na VNDB? Nebojte! Stačí zadat e-mailovou adresu, se kterou jste se na VNDB registrovali, a my vám do několika minut pošleme heslo nové! hu : Elfelejtetted a jelszavad és nem tudsz bejelentkezni a VNBD-be? - Ne aggódj! Csak add meg nekünk az email címmet amivel regisztráltál, - s egy pár percen belűl kapsz tőlünk egy új jelszót! + Ne aggódj! Csak add meg nekünk az email címet amivel regisztráltál, + s egy pár percen belül kapsz tőlünk egy új jelszót! :_newpass_reset_title en : Reset password @@ -4241,8 +4241,8 @@ cs : Vaše heslo bylo změněno a vaše nové heslo by mělo být za několik mi Vždy můžete změnit vaše heslo po přihlášení.[br] [br] [url,/u/login,Přihlásit] - [url,/,Home] -hu : A jelszavad vissza lett állítva s pár percen belül kapsz egy újjat a postafiókodba.[br] - Miútán bejelentkezel, nyugodtan megváltoztathatod a jelszavad amire akarod.[br] +hu : A jelszavad vissza lett állítva s pár percen belül kapsz egy ujjat a postafiókodba.[br] + Miután bejelentkezel, nyugodtan megváltoztathatod a jelszavad amire akarod.[br] [br] [url,/u/login,Bejelentkezés] - [url,/,Kezdőlap] @@ -4252,7 +4252,7 @@ hu : A jelszavad vissza lett állítva s pár percen belül kapsz egy újjat a p en : Create an account ru : Создание учётной записи cs : Vytvořit účet -hu : Új fiók létrehozzása +hu : Új fiók létrehozása :_register_why en : Why should I register? @@ -4290,14 +4290,14 @@ cs : Tvorba účtu je zcela bezbolestná, jediné údaje, které potřebujeme zn - Mějte přehled o všech vizuálních novelách, které máte, chtěli byste hrát, hrajete, nebo jste dohráli[br] - Hlasujte pro vizuální novely, které se vám líbily nebo nelíbily[br] - Přispívejte do diskusí na boardech -hu : Egy fiókot nagyon egyszerű készíteni, minden ami kell egy felhasználónév és egy jelszó. Bármilyen email címmet használhatsz, +hu : Egy fiókot nagyon egyszerű készíteni, minden ami kell egy felhasználónév és egy jelszó. Bármilyen email címet használhatsz, minket nem érdekel, hogy a tied vagy nem, mivel nincs külön aktiválás. Viszont ha nem jó emailt adsz meg nekünk akkor jól vésd az eszedbe a jelszavad, különben nem tudunk neked segíteni ha elfelejted.[br] [br] - Nos, a saját fiókkal rendelkezők több előnybe is részesűlnek mint az egyszerű látogatók[br] - - Hozzájárúlhatsz az adatbázis fejlődéséhez, hiszen szerkeszthetsz, vagy létrehozhatsz új bejegyzéseket[br] + Nos, a saját fiókkal rendelkezők több előnybe is részesülnek mint az egyszerű látogatók[br] + - Hozzájárulhatsz az adatbázis fejlődéséhez, hiszen szerkeszthetsz, vagy létrehozhatsz új bejegyzéseket[br] - Nyomon követheted a tulajdonodban levő visual novellek, helyzetét, állapotát...mit játszol, melyiket fejezted már be stb.[br] - - Szavazhatsz a visual novellekre, melyek tetszettek, vagy ép meggyülölteték magukat[br] + - Szavazhatsz a visual novellekre, melyek tetszettek, vagy ép meggyűlöltették magukat[br] - Bekapcsolódhatsz a fórumba levő beszélgetésekbe :_register_form_title @@ -4316,7 +4316,7 @@ hu : Felhasználónév en : Preferred username. Must be lowercase and can only consist of alphanumeric characters. ru : Запрашиваемое имя пользователя. Должно состоять из буквенно-цифровых символов в нижнем регистре. cs : Požadováné uživatelské jméno. Musí být malými písmeny a smí obsahovat pouze písmena a číslice. -hu : A kivánt felhasználónév. Múszáj kisbetűkkel legyen s csakis alfanumerikus karaktereket tartalmazhat. +hu : A kívánt felhasználónév. Muszáj kisbetűkkel legyen s csakis alfanumerikus karaktereket tartalmazhat. :_register_mail en : Email @@ -4331,8 +4331,8 @@ ru : Адрес вашей электронной почты будет испо пришлём вам спама или новостных рассылок, пока вы недвусмысленно не попросите об обратном. cs : Vaše e-mailová adresa bude použita pouze v případě ztráty vašeho hesla. Nikdy vám nezašleme spam nebo newslettery, pokud o to explicitně nezažádáte. -hu : Az email címmed csakis akkor kerül használatba ha elveszted a jelszavad. Soha nem fogunk - spam vagy hírleveleket küldeni, csakis ha te azt kifejezeten kéred tőlünk. +hu : Az email címed csakis akkor kerül használatba ha elveszted a jelszavad. Soha nem fogunk + spam vagy hírleveleket küldeni, csakis ha te azt kifejezetten kéred tőlünk. :_register_password en : Password @@ -4344,7 +4344,7 @@ hu : Jelszó en : Confirm password ru : Подтверждение пароля cs : Potvrdit heslo -hu : Jelszó megerősitése +hu : Jelszó megerősítése # User edit (/u+/edit) @@ -4359,13 +4359,13 @@ hu : Fiókom en : Settings saved ru : Параметры сохранены cs : Nastavení uloženo -hu : Beállitások mentve +hu : Beállítások mentve :_usere_saved_msg en : Settings successfully saved. ru : Параметры успешно сохранены. cs : Nastavení úspěšně uloženo. -hu : Beállitások sikeresen mentve. +hu : Beállítások sikeresen mentve. :_usere_geninfo en : General info @@ -4389,7 +4389,7 @@ hu : Rang en : Ignore votes in VN statistics ru : Игнорировать голосования в статистике новелл cs : Ignorovat hlasy ve statistikách vizuálních novel -hu : VN szavazatok figyelmen kivűl hagyása a statisztikákban +hu : VN szavazatok figyelmen kívül hagyása a statisztikákban :_usere_mail en : Email @@ -4419,19 +4419,19 @@ hu : Jelszó en : Confirm password ru : Подтверждение пароля cs : Potvrdit heslo -hu : Jelszó megerősitése +hu : Jelszó megerősítése :_usere_options en : Options ru : Настройки cs : Nastavení -hu : Beállitások +hu : Beállítások :_usere_flist en : Allow other people to see my visual novel list ([url,_1,_1]) and wishlist ([url,_2,_2]) ru : Разрешить остальным видеть мой список новелл ([url,_1,_1]) и список желаемого ([url,_2,_2]) cs : Povolit ostatním zobrazit můj list vizuálních novel ([url,_1,_1]) a wishlist ([url,_2,_2]) -hu : Más embereknek megengedni, hogy lássák a visual novel listám ([url,_1,_1]) és a kivánságlistám ([url,_2,_2]) +hu : Más embereknek megengedni, hogy lássák a visual novel listám ([url,_1,_1]) és a kívánságlistám ([url,_2,_2]) :_usere_fnsfw en : Disable warnings for images that are not safe for work. @@ -4515,7 +4515,7 @@ hu : Szerkesztések en : Tags ru : Тегов cs : Tagy -hu : Cimkék +hu : Címkék @@ -4565,19 +4565,19 @@ hu : Népszerűség en : The following tags were ignored: ru : Следующие теги были пропущены: cs : Následující tagy byly ignorovány: -hu : Az allábi cimkék nem lettek figyelembe véve: +hu : Az allábi címkék nem lettek figyelembe véve: :_vnbrowse_tagign_meta en : can't filter on meta tags ru : фильтрация мета-тегов невозможна cs : nedají se filtrovat meta tagy -hu : meta cimkéken nem működik a szűrő +hu : meta címkéken nem működik a szűrő :_vnbrowse_tagign_notfound en : no such tag found ru : тег не найден cs : nenalezeny takové tagy -hu : nem található ilyen cimke +hu : nem található ilyen címke :_vnbrowse_advsearch en : advanced search @@ -4589,7 +4589,7 @@ hu : bővített keresés en : Tag filters ru : Фильтры тегов cs : Filtry tagů -hu : cimke szűrők +hu : címke szűrők :_vnbrowse_booland en : boolean and, selecting more gives less results @@ -4601,13 +4601,13 @@ hu : Boole féle értékhalmaz(igaz/hamis), s ha többet választasz ki akkor ke en : Tags to include ru : Включить теги cs : Tagy k zahrnutí -hu : Cimkék beleszámítása +hu : Címkék beleszámítása :_vnbrowse_tagexc en : Tags to exclude ru : Исключить теги cs : Tagy k vyjmutí -hu : Cimkék kihagyása +hu : Címkék kihagyása :_vnbrowse_spoil0 en : Hide spoilers @@ -4712,9 +4712,9 @@ ru : Список альтернативных названий или аббр cs : Seznam alternativních názvů nebo zkratek, oddělených čárkou. Může zahrnovat oba (japonský/anglický) názvy a neoficiální názvy používané na internetu.[br] Názvy, vypsané ve vydáních by se sem přidávat neměly! -hu : Vesszővel elválasztott lista, más címmekel vagy röviditésekel. Tartalmazhat hivatalos - (japán/angol) címmeket vagy nem hivatalosokat amelyet a netten használnak.[br] - Azok a címmek amelyek a kiadásokba vannak ne tegyétek bele! +hu : Vesszővel elválasztott lista, más címekkel vagy rövidítésekkel. Tartalmazhat hivatalos + (japán/angol) címeket vagy nem hivatalosokat amelyet a netten használnak.[br] + Azok a címek amelyek a kiadásokba vannak ne tegyétek bele! :_vnedit_desc en : Description @@ -4730,7 +4730,7 @@ ru : Краткое описание главной сюжетной линии. cs : Krátký popis hlavního příběhu. Prosím nepište spoilery a nezapomeňte uvést zdroj, pokud jste popis nenapsali sami. (formátovací kódy jsou povoleny) hu : A fő történet rövid leírása. Ne tartalmazzon spoilert és ha nem te írtad akkor ne felejtsd el - megemlítetni a forrást amit felhasználtál. (formázó kódok megengedettek) + megemlíteni a forrást amit felhasználtál. (formázó kódok megengedettek) :_vnedit_length en : Length @@ -4763,10 +4763,10 @@ cs : Seznam AnimeID z [url,http://anidb.net/,AniDB], oddělených mezerou. Např. "1015 3348" přidá [url,http://anidb.net/a1015,Shingetsutan Tsukihime] a [url,http://anidb.net/a3348,Fate/stay night] jako příbuzná anime.[br] Poznámka: Může trvat několik minut, než se názvy anime objeví na stránce vizuální novely. -hu : Szókőzzel elválasztot lista [url,http://anidb.net/,AniDB] anime ID-kal. +hu : Szóközzel elválasztott lista [url,http://anidb.net/,AniDB] anime ID-kal. Pl. "1015 3348" belinkeli [url,http://anidb.net/a1015,Shingetsutan Tsukihime] - és [url,http://anidb.net/a3348,Fate/stay night] mint kapcsolodó animék.[br] - Figyelem: Beletelhet pár percbe míg az anime címmek megjelennek a VN oldalán. + és [url,http://anidb.net/a3348,Fate/stay night] mint kapcsolódó animék.[br] + Figyelem: Beletelhet pár percbe míg az anime címek megjelennek a VN oldalán. :_vnedit_image en : Image @@ -4790,7 +4790,7 @@ hu : ~[a kép feldolgozás alatt van, gyere vissza pár perc múlva~] en : Upload new image ru : Загрузить новое изображение cs : Nahrát nový obrázek -hu : Tötls fel egy új képet +hu : Tölts fel egy új képet :_vnedit_image_upload_msg en : Preferably the cover of the CD/DVD/package. Image must be in JPEG or PNG format @@ -4800,7 +4800,7 @@ ru : Желательно, обложка CD/DVD/коробки. Изображ будут автоматически уменьшены. cs : Pokud možno obálka CD/DVD/balení. Obrázek musí být ve formátu JPEG nebo PNG a ne větší 500kB. Obrázek větší než 256x400 pixelů bude automaticky zmenšen. -hu : Lehetőleg a CD/DVD/csomagolás borítóját. A képek muszáj JPEG vagy PNG formátúmba +hu : Lehetőleg a CD/DVD/csomagolás borítóját. A képek muszáj JPEG vagy PNG formátumba legyenek és maximum 500kb nagyok. 254x400-nál nagyobb képek automatikusan át lesznek méretezve. @@ -4832,7 +4832,7 @@ hu : Összefüggések en : Selected relations ru : Выбранные связи cs : Vybrané vztahy -hu : Kiválasztot összefüggések +hu : Kiválasztott összefüggések :_vnedit_rel_add en : Add relation @@ -4846,49 +4846,49 @@ hu : Összefüggés hozzáadása en : is a ru : это cs : je -hu*: +hu*: - :_vnedit_rel_of en : of ru : для cs : titulu -hu*: +hu*: - :_vnedit_rel_addbut en : add ru : добавить cs : přidat -hu*: +hu : hozzáadd :_vnedit_rel_del en : del ru : убрать cs : smazat -hu*: +hu : töröl :_vnedit_rel_none en : No relations selected. ru : Отношений не выбрано. cs : Nejsou vybrány žádné vztahy. -hu*: +hu : Semmilyen összefüggés nincs kiválasztva. :_vnedit_rel_findformat en : Visual novel textbox must start with an ID (e.g. v17) ru : Строка новеллы должна начинаться с идентификатора (например, v17) cs : textové pole vizuální novely musí začínat ID (např. v17) -hu*: +hu : A visual novel szövegdoboz muszáj egy ID-val kezdődjön (pl. v17) :_vnedit_rel_novn en : Visual novel not found! ru : Новелла не найдена! cs : Vizuální novela nenalezena! -hu*: +hu : A visual novel nem található! :_vnedit_rel_double en : This visual novel has already been selected! ru : Эта новелла уже была выбрана! cs : Tato vizuální novela již byla vybrána! -hu*: +hu : Ez a visual novel már ki van választva! :_vnedit_scr en : Screenshots @@ -4917,58 +4917,58 @@ cs : Prosíme, pamatujte na následující věci, pokud nahráváte screenshoty: Ujistěte se, že jste potvrdili odeslání informací poté, co nahrajete obrázky! hu : Mielőtt pillanatképeket töltesz fel, tarts néhány dolgot figyelembe:[br] - A pillanatképek a játék eredeti felbontásába kell legyenek,[br] - - Távolits el bármilyen ablak szélet és vigyázz, hogy a képen ne legyenek jelölések,[br] + - Távolíts el bármilyen ablak szélet és vigyázz, hogy a képen ne legyenek jelölések,[br] - Ne csak esemény CG-ket tölts fel.[br] - Legyél szives és olvasd el az [url,/d2#6,útmutatókat] több információért.[br] - A feltöltés útán ne felejtsd beküldeni a formulát! + Legyél szíves és olvasd el az [url,/d2#6,útmutatókat] több információért.[br] + A feltöltés után ne felejtsd beküldeni a formulát! :_vnedit_scr_selrel en : -- select release -- ru : -- выбор выпуска -- cs : -- vybrat vydání -- -hu*: +hu : -- kiadás kiválasztása -- :_vnedit_scr_frmloading en : Please wait for the screenshots to be uploaded before submitting the form. ru : Прежде чем сохранить изменения, дождитесь загрузки скриншотов на сервер. cs : Prosíme, počkejte na nahrání screenshotů před potvrzením změn. -hu*: +hu : Kérlek várj míg a pillanatképek feltöltődnek, mielőtt beküldenéd a forma lapot. :_vnedit_scr_frmnorel en : Please select the appropriate release for every screenshot. ru : Пожалуйста, укажите подходящий выпуск для каждого скриншота. cs : Prosíme, vyberte příslušné vydání pro každý screenshot. -hu*: +hu : Kérlek válaszd ki a megfelelő kiadást mindegyik pillanatképhez. :_vnedit_scr_fetching en : Fetching thumbnail... ru : Обработка превьюшки... cs : Načítám náhled... -hu*: +hu : Indexképek előkészítése... :_vnedit_scr_uploading en : Uploading screenshot ru : Загрузка скриншота cs : Nahrávám screenshot -hu*: +hu : Pillanatkép feltöltése :_vnedit_scr_upl_msg en : This can take a while, depending on the file size and your upload speed. ru : Это может занять некоторое время, в зависимости от размера файла и скорости вашего соединения. cs : Toto může chvíli trvat, v závislosti na velikosti souboru a vaší rychlosti uploadu. -hu*: +hu : Ez eltarthat egy ideig, attól függ milyen nagy a fájl mérete és mennyivel tudsz feltölteni. :_vnedit_scr_cancel en : cancel ru : отменить cs : zrušit -hu*: +hu : mégse :_vnedit_scr_full en : Enough screenshots ru : Больше нет места cs : Již máme dostatek screenshotů -hu*: +hu : Elég ennyi pillanatkép :_vnedit_scr_full_msg en : The limit of 10 screenshots per visual novel has been reached. @@ -4977,49 +4977,50 @@ ru : Достигнуто ограничение в 10 скриншотов. Если вы хотите добавить новый скриншот, пожалуйста удалите один из существующих. cs : Limit deseti screenshotů na vizuální novelu byl dosažen. Pokud chcete přidat další screenshot, prosíme odstraňte nejdříve nějaký již existující. -hu*: +hu : A megengedett 10 pillanatkép/visual novel megtelt. + Ha szeretnél egy új pillanatképet feltölteni, akkor el kell távolíts egy már létezőt. :_vnedit_scr_add en : Add screenshot ru : Добавить скриншот cs : Přidat screenshot -hu*: +hu : Pillanatkép hozzáadása :_vnedit_scr_imgnote en : Image must be smaller than 5MB and in PNG or JPEG format. ru : Изображение должно быть не более 5 Мегабайт и в формате PNG, либо JPEG. cs : Obrázek musí být menší 5MB a ve formátu PNG nebo JPEG. -hu*: +hu : A kép kisebb kell legyen mint 5MB és PNG vagy JPEG formátumba kell legyen. :_vnedit_scr_addbut en : Upload! ru : Загрузить! cs : Nahrát! -hu*: +hu : Feltöltés! :_vnedit_scr_id en : Screenshot #[_1] ru : Скриншот #[_1] cs : Screenshot #[_1] -hu*: +hu : #[_1]-dik pillanatkép :_vnedit_scr_remove en : remove ru : убрать cs : odebrat -hu*: +hu : eltávolítás :_vnedit_scr_fullsize en : Full size: [_1] ru : Полный размер: [_1] cs : Plná velikost: [_1] -hu*: +hu : Teljes méret: [_1] :_vnedit_scr_nsfw en : This screenshot is NSFW ru : Этот скриншот НБДР (NSFW) cs : Tento screenshot je NSFW -hu*: +hu : Ez a pillanatkép nem biztonságos :_vnedit_scr_oops en : Oops! Seems like something went wrong... @@ -5031,7 +5032,9 @@ ru : Э-кхм! Похоже, возникла проблема... cs : Hups! Zdá se, že se něco pokazilo... Ujistěte se, že soubor, který nahráváte nemá více jak 5MB. Pokud v tom problém neleží, nahlaste systémovou chybu. -hu*: +hu : Hoppá! Úgy tűnik valami rosszul sült el... + Ellenőrizd, hogy a fájl amit fel akarsz tölteni nem haladja meg az 5MB-os méretet. + Ha nem az a baj, akkor kérlek jelentsd a hibát. :_vnedit_scr_errformat en : Upload failed! @@ -5040,7 +5043,8 @@ ru : Ошибка при загрузке! Допускаются только JPEG или PNG. cs : Nahrání se nezdařilo! Přijímány jsou pouze obrázky formátu JPEG nebo PNG. -hu*: +hu : Feltöltés sikertelen! + Csakis JPEG vagy PNG képek az elfogadhatóak. :_vnedit_scr_errempty en : Upload failed! @@ -5049,13 +5053,14 @@ ru : Ошибка при загрузке! Файл не выбран или имеет нулевой размер. cs : Nahrání se nezdařilo! Buď jste nevybrali soubor, nebo byl tento soubor prázdný. -hu*: +hu : Feltöltés sikertelen! + Nincs fájl kiválasztva, vagy üres volna a fájl? :_vnedit_scr_genthumb en : Generating thumbnail... ru : Генерация превьюшки... cs : Tvořím náhled... -hu*: +hu : Indexkép készítése :_vnedit_scr_genthumb_msg en : Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side. @@ -5064,7 +5069,8 @@ ru : Замечание: если эта операция длится боле В таком случае попытайтесь снова или сообщите администрации об ошибках. cs : Poznámka: Pokud toto zabere více jak 30 sekund, je pravděpodobně chyba někde na naší straně. Prosíme, zkuste to znovu později nebo nahlaste systémovou chybu, pokud tomu tak je. -hu*: +hu : Figyelem: ha ez tovább tart mint 30 másodperc, akkor a mivelünk van a gond. + Kérlek próbáld meg később és ha adott az eset, akkor jelentsd a hibát. # VN Relation graph page (/v+/rg) @@ -5130,7 +5136,7 @@ hu : en : Encubed tag ru : Тег Encubed'а cs : Tag na Encubed -hu : Encubed cimke +hu : Encubed címke :_revfield_v_l_renai en : Renai.us link @@ -5148,7 +5154,7 @@ hu : en : Relations ru : Связи cs : Vztahy -hu : Kapcsolatok +hu : Összefüggések :_revfield_v_anime en : Anime @@ -5172,7 +5178,7 @@ hu : Kép en : (NSFW) ru : (НБДР|NSFW) cs : (NSFW) -hu : (NB) +hu : (Nem Biztonságos) :_vndiff_image_proc en : ~[processing~] @@ -5223,7 +5229,7 @@ hu : ~[a kép feldolgozás alatt van, gyere vissza pár perc múlva~] en : This image has been flagged as Not Safe For Work. ru : Данное изображение помечено как не безопасное для работы. cs : Tento obrázek byl označen jako "Not Safe For Work" -hu : Ezt a képet Nem Biztonságosnak nyilvánitották. +hu : Ezt a képet Nem Biztonságosnak nyilvánították. :_vnpage_imgnsfw_show en : Show me anyway @@ -5313,13 +5319,13 @@ hu : mind en : Developer ru : Разработчик cs : Vývojář -hu*: +hu : Fejlesztő :_vnpage_publisher en : Publishers ru : Издатели cs : Vydavatel -hu*: +hu : Kiadó :_vnpage_relations en : Relations @@ -5337,7 +5343,7 @@ hu : Kapcsolódó animék en : ~[no information available at this time: [url,_2,_1]~] ru : ~[к сожалению, пока никакой информации: [url,_2,_1]~] cs : ~[nyní nejsou dostupné žádné informace: [url,_2,_1]~] -hu : ~[jelenleg nincs semmilyen információÉ [url,_2,_1]~] +hu : ~[jelenleg nincs semmilyen információ: [url,_2,_1]~] :_vnpage_uopt en : User options @@ -5382,7 +5388,8 @@ ru : Вы собираетесь дать этой новелле оценку 1 Вы уверены, что эта новелла соответствует такому критерию? cs : Chystáte se této vizuální novele dát hodnocení 1 z 10. To je celkem extrémní hodnocení, znamenající, že tato hra nemá absolutně nic co nabídnout, a že je to ta nejhorší hra, kterou jste kdy hráli. Jste si opravdu jisti, že tato vizuální novela odpovídá tomuto popisu? -hu*: +hu : Te most épp a 10-ből, 1-et adsz ennek a visual novelnek. Ez egy elég extrém osztályozás, ez azt jelenti, hogy ez a játék egyáltalán semmit nem tud nyújtani és, hogy ez a legrosszabb amit valaha játszottál. + Biztos vagy benne, hogy ezt a visual novel azok közzé lehet sorolni? :_vnpage_uopt_10vote en : You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, meaning this is one of the best visual novels you've ever played and it's unlikely that any other game could ever be better than this one. @@ -5391,7 +5398,8 @@ ru : Вы собираетесь дать этой новелле оценку 1 Вы уверены, что эта новелла соответствует такому критерию? cs : Chystáte se této vizuální novele dát hodnocení 10 z 10. To je celkem extrémní hodnocení, znamenající, že to je jedna z nejlepších vizuálních novel, které jste kdy hráli a je nepravděpodobné, že by nějaká další hra mohla být lepší než tato. Obecně vztao je špatný nápad mít víc jak tři hry s tímto hodnocením ve vašem listu hlasování, vybírejte pečlivě! -hu*: +hu : Te most épp a 10-ből, 10-et adsz ennek a visual novelnek. Ez egy elég extrém osztályozás, ami annyit jelent, hogy ez a legjobb visual novel amit valaha játszottál és elég valószínűtlen, hogy találkozol ettől jobb játékkal. + Általában rossz ötlet ha 3-nál több ilyen játékot tartasz a szavazási listádba, válasz óvatosan! :_vnpage_uopt_wishlisted en : wishlist: [_1] @@ -5427,19 +5435,19 @@ hu : eltávolitás a kivánságlistából en : Release status ru : Статус выпуска cs : Status vydání -hu*: +hu : Kiadás állapota :_vnpage_uopt_relvstat en : Play status ru : Статус играбельности cs : Herní status -hu*: +hu : Játszás állapota :_vnpage_uopt_reldel en : Remove from VN list ru : Убрать из списка новелл cs : Odstranit z listu VN -hu*: +hu : Eltávolítás a VN listából :_vnpage_rel en : Releases @@ -5579,7 +5587,7 @@ hu : Ezt a műveletet nem hajthatod végre. en : It seems you don't have the proper rights to perform the action you wanted to perform... ru : Похоже, у вас нет прав на выполнение того, чего вы хотите... cs : Zdá se, že nemáte potřebná práva pro vykonání akce, kterou chcete provést... -hu : Úgy tűnik, hogy nem rendelkezzel megfelelő jogokkal, hogy elvégezd azt a műveletet amit szerettél volna... +hu : Úgy tűnik, hogy nem rendelkezel megfelelő jogokkal, hogy elvégezd azt a műveletet amit szerettél volna... # "DB Item has been deleted" page @@ -5598,7 +5606,7 @@ ru : Данная запись удалена из базы данных. Пож cs : Tato položka byla smazána z databáze. Pro obnovení této stránky napište žádost na [url,_1,diskusní board]. hu : Ez a bejegyzés ki lett törölve az adatbázisból. Nyújtsd be egy kérvényt a - [url,_1,forumon], hogy állítsák vissza ezt az oldalt. + [url,_1,fórumon], hogy állítsák vissza ezt az oldalt. # The warning/notice messages on edit pages @@ -5617,7 +5625,7 @@ ru : Вы собираетесь вставить новый выпуск, ос cs : Chystáte se vložit nové vydání do databáze s informacemi založenými na vydání [_1].[br] Pokud chcete editovat vydání místo toho, abyste vložili další vydání, přejděte na záložku 'editovat' v pravém horním rohu. hu : Te most ép arra készülsz, hogy egy új kiadást hozzál létre az adatbázisban, [_1]-ra alapozva az információkat.[br] - Klikelj a 'szerkesztés' fűlre a jobb felső sarokba ha egy új kiadás helyet, csak szerkeszteni akartad a meglévőt. + Klikkelj a 'szerkesztés' fülre a jobb felső sarokba ha egy új kiadás helyet, csak szerkeszteni akartad a meglévőt. :_editmsg_msg_title en : Before editing: @@ -5629,7 +5637,7 @@ hu : Szerkesztés előtt: en : Read the [url,_1,guidelines]! ru : Прочтите [url,_1,рекомендации]! cs : Přečtěte si [url,_1,doporučení]! -hu : Olvasdd el az [url,_1,útmutatokat]! +hu : Olvasd el az [url,_1,útmutatókat]! :_editmsg_msg_discuss en : Check for any existing discussions on the [url,_1,discussion board] @@ -5684,7 +5692,7 @@ hu : Be kell legyél [url,_1, jelentkezve], hogy szerkeszthesd ezt az oldalt en : You are not allowed to edit this page ru : Вам запрещено редактировать эту страницу cs : Nemáte oprávnění editovat tuto stránku -hu : Nincs engedélyed, hogy szerkesd ezt az oldalt +hu : Nincs engedélyed, hogy szerkeszd ezt az oldalt # User didn't pass the spam protection @@ -5693,7 +5701,7 @@ hu : Nincs engedélyed, hogy szerkesd ezt az oldalt en : Could not send form ru : Невозможно отправить форму cs : Formulář nemohl být odeslán -hu : Nem lehetet elküldeni a formulát +hu : Nem lehetett elküldeni a formulát :_nospam_subtitle en : Error @@ -5705,7 +5713,7 @@ hu : Hiba en : The form could not be sent, please make sure you have Javascript enabled in your browser. ru : Не удалось отправить форму, пожалуйста убедитесь что в вашем браузере включён Javascript. cs : Formulář nemohl být odeslán, ujistěte se, že máte ve svém prohlížeči povolen Javascript. -hu : A formulát nem lehetet elküldeni, kérlek ellenőrizd, hogy engedélyezve van a Javascript a böngésződbe. +hu : A formulát nem lehetett elküldeni, kérlek ellenőrizd, hogy engedélyezve van a JavaScript a böngésződbe. # Short message reminding the user to post in ENGLISH (Used at about every message/description input field) @@ -5723,11 +5731,11 @@ hu : Kérlek angolul válaszolj! en : Not supported ru : Не поддерживается cs : Nepodporováno -hu*: +hu : Nem támogatott :_rg_notsupp_msg en : Your browser sucks, it doesn't have the functionality to render our nice relation graphs. ru : Ваш браузер настолько отстоен, что даже не может отрендерить наши графики. cs : Váš prohlížeč je na nic, nepodporuje vykreslování našich krásných vztahových grafů. -hu*: +hu : A böngésződ szar, nem képes megjeleníteni a szép összefüggés gráfunkat. -- cgit v1.2.3 From 246dbbdad9aab4d59c2a1d70e0936452d1df9bca Mon Sep 17 00:00:00 2001 From: Nya-chan Production <nya.chan.production@gmail.com> Date: Sat, 24 Oct 2009 10:56:01 +0200 Subject: L10N-CS: Translated all doc pages --- data/docs/10.cs | 49 +++++++++++++ data/docs/2.cs | 184 +++++++++++++++++++++++++++++++++++++++++++++++ data/docs/3.cs | 138 +++++++++++++++++++++++++++++++++++ data/docs/4.cs | 36 ++++++++++ data/docs/5.cs | 82 +++++++++++++++++++++ data/docs/6.cs | 89 +++++++++++++++++++++++ data/docs/7.cs | 92 ++++++++++++++++++++++++ data/docs/9.cs | 74 +++++++++++++++++++ data/docs/index.cs | 14 ++++ data/docs/notfinished.cs | 4 ++ 10 files changed, 762 insertions(+) create mode 100644 data/docs/10.cs create mode 100644 data/docs/2.cs create mode 100644 data/docs/3.cs create mode 100644 data/docs/4.cs create mode 100644 data/docs/5.cs create mode 100644 data/docs/6.cs create mode 100644 data/docs/7.cs create mode 100644 data/docs/9.cs create mode 100644 data/docs/index.cs create mode 100644 data/docs/notfinished.cs diff --git a/data/docs/10.cs b/data/docs/10.cs new file mode 100644 index 00000000..d8eebb52 --- /dev/null +++ b/data/docs/10.cs @@ -0,0 +1,49 @@ +:TITLE:Tagovací systém +:INC:notfinished +:INC:index + + +:SUB:Úvod +<i>TODO</i> + + +:SUB:Hodnocení tagů +<p> + I když celkem vzato může kdokoliv uvést jakýkoliv tag k jakékoliv vizuální novele, pamatujte prosím na následující věci, + pokud tagy hodnotíte: +</p> +<ul> + <li>Před přidáním tagu k nějaké vizuální novele si přečtěte jeho popis, některé tagy nemusí znamenat to, + co si myslíte, že znamenají.</li> + <li>Buďte tak přesní, jak jen můžete být. Kupříkladu, pokud má hra dramatické prvky, zkuste spíše najít + více specifické odvozené tagy, které popisují jaký typ dramatických událostí může hráč očekávat, + než přidat tag "Drama".</li> + <li>Tagu může být přiděleno hodnocení v rozsahu -3 až 3. Negativní hodnocení znamená, že s tagem + nesouhlasíte, kde -1 bude "Nemyslím si, že tento tag je opravdu ve hře" a -3 bude znamenat, že plně + nesouhlasíte a tag by neměl být použit vůbec. Pozitivní hodnocení tagu funguje naopak a znamená, že + s tagem pro danou vizuální novelu souhlasíte.</li> + <li>Některé tagy se mohou chovat jako spoiler co se děje VN týká, to může být označeno ohodnocením spoiler + statusu. Je vysoce doporučeno nenechávat tento jako "Neutral", a opravdu se snažit poskytnout nějaké vodítko + ohledně toho, zda tasg vůbec není spoiler nebo zda vizuální novelu malinko prozrazuje.</li> +</ul> + + +:SUB:Doporučení k tagům +<p> + Nové tagy si může vyžádat kdokoliv, ale než se dají procházet musí být schváleny moderátorem. + Platí následující pravidla: +</p> +<ul> + <li>Jména tagů musí mluvit za sebe. I když význam tagu může být zřejmý v okamžiku, kdy se podíváte + na jeho umístění ve stromu tagů, v okamžiku, kdy je zobrazen na stránce VN, je vidět pouze jeho jméno + a ne mateřské tagy. Jméno by tedy mělo plně popisovat co tag znamená a pro co by měl být použit. + Například: Tag k popisu mužského hlavního hrdiny by měl být pojmenován plně "Male protagonist" (Muž protagonista), + i když jeho mateřský tag je "Characters > Protagonist" (Postavy > Protagonista).</li> + <li>Tagy by měly být užívány k popisování objektivních informací o VN. Subjektivní tagy jako + "Awesome protagonist" (Úžasný protagonista), které by pro každého znamenaly něco jiného, nejsou povoleny.</li> + <li>Tagy by měly popisovat pouze informace, které VNDB ještě nezahrnuje. Tudíž tagy ohledně informací o vydání či + o délce VN nejsou povoleny.</li> + <li>Výše uvedené pravidlo platí i pro jakékoliv další informace o VN, které ještě nejsou na VNDB zahrnuty, + jako lidé v produkčním týmu nebo stav licence v jakékoliv zemi.</li> +</ul> + diff --git a/data/docs/2.cs b/data/docs/2.cs new file mode 100644 index 00000000..b7d3c7eb --- /dev/null +++ b/data/docs/2.cs @@ -0,0 +1,184 @@ +:TITLE:Přidání/editace vizuální novely +:INC:index + +:SUB:Kdy přidat vizuální novelu +<p> + Aby hra byla zahrnuta v této databázi, musí pro vyprávění příběhu konzistentně + používat vyprávěcí styl. Příklady zahrnují popisy <a + href="http://s.vndb.org/sf/58/258.jpg">vizuální</a>, <a + href="http://s.vndb.org/sf/63/2663.jpg">událostí</a>, <a + href="http://s.vndb.org/sf/74/274.jpg">akcí postav</a> nebo <a + href="http://s.vndb.org/sf/49/449.jpg">myšlenek</a>. Toto vyprávění musí být + jednou ze známých metod prezentace vizuálních novel, jako jsou <a + href="http://s.vndb.org/sf/40/3440.jpg">ADV</a>, <a + href="http://s.vndb.org/sf/52/3152.jpg">NVL</a> a jejich <a + href="http://s.vndb.org/sf/39/339.jpg">obdoby</a>.<br /> + <br /> + Hra, která 'působí' jako VN, i když plní jinou funkci než striktně vyprávění + příběhu (jako například vysoce interaktivní simulace) se může jako VN kvalifikovat + pokud je buď celá vyprávěna v ADV/NVL stylu nebo jsou její další herní prvky + jasně podřízeny prvkům textovým (prezentovaným v ADV/NVL stylu) (např. akční scény + v 3D hrách nemohou být podřízeny jejich textovým prvkům, jelikož vizuální prvky + jsou jasně 'účelem' hry; 'podzemí' ve hrách Princess Maker, která mají jednoduchou + grafiku a dají se všechna přeskočit, by podřízena byla). +</p> + +:SUB:Obecné informace +<dl> + <dt>Název (romaji)</dt><dd> + Název by měl korespondovat s názvem původního vydání.<br /> + Pokud název užívá latinky použijte našich <a href="/d5.2">doporučení ke kapitalizaci</a>.<br /> + Jinak <a href="/d5.1">romanizujte</a> podle našich doporučení. + </dd><dt>Originální název</dt><dd> + Pokud je název oficiálně odlišný od názvu v romaji (obvykle kvůli odlišným znakovým sadám), + umístěte sem originální název. + </dd><dt>Aliasy</dt><dd> + Vizuální novely mohou být známy pod různými názvy, použijte tedy toto pole pro přidání jakýchkoliv + aliasů a akronymů užívaných na internetu. Oficiální názvy vydání by se sem přidávat neměla, protože + jsou již zapsána ve vydáních. + </dd><dt>Popis</dt><dd> + Krátký popis hlavního příběhu. + </dd><dt>Délka</dt><dd> + Velmi hrubý odhad času potřebného k dohrání všech konců vizuální novely. + K určení délky hry je často lepší ignorovat délku branou v čase jako takovém a místo toho + ji porovnat s jinými hrami, které jste hráli. Všechno je to přeci jen relativní. + </dd><dt>Externí odkazy</dt><dd> + Odkazy k externím zdrojům o této vizuální novele. Abyste získali URL, navštivte tyto stránky + (<a href="http://en.wikipedia.org/">Wikipedia</a>, <a href="http://novelnews.net/"> + Novelnews.net</a>, <a href="http://renai.us/">Renai.us</a> a + <a href="http://visual-novels.net/">Visual-novels.net</a>), + najděte stránku o hře a určete ID nebo jméno této stránky, které je třeba vyplnit + do textových polí. Nepište celá URL, potřebujeme jen jejich malou část! + </dd><dt>Vztahy k anime</dt><dd> + Některé vizuální novely (jako <a href="/v4">Clannad</a> a <a href="/v3">Utawarerumono</a>) + mají anime adaptace a některé vizuální novely byly adaptovány z anime sérií. Použijte + toto pole pro upřesnění těchto anime se vztahy k vizuálním novelám.<br /> + Anime by mělo být specifikováno za užití <a href="http://anidb.net/">AniDB</a> ID. + Pro přidání anime ho najděte na AniDB a vložte číselné ID anime (dá se najít v + <i>aid=xxx</i> části URL) do editovatelného pole. Několik ID by mělo být odděleno mezerou.<br /> + Pokud má vizuální novela vztah k jiné vizuální novele a obě hry mají anime adaptaci, + to samé anime nemusí být přidáno k oběma hrám. Například <a href="/v264">Da Capo</a> má dvě + anime adaptace (<a href="http://anidb.net/a837">837</a>, <a href="http://anidb.net/a2832">2832</a>), + stejně jako <a href="/v266">Da Capo II</a>. (<a href="http://anidb.net/a5419">5419</a>, + <a href="http://anidb.net/a5652">5652</a>) Ale vztahy pro Da Capo II se nemusí přidávat + k Da Capu a vice versa - o to se postarají vnitřní vztahy vizuálních novel.<br /> + VNDB po potvrzení nového AniDB ID automaticky zanese informace o anime a bude je prezentovat + na stránce. Tato akce zabere několik minut až - přinejhorším - několik hodin. Po tento čas + uvidíte ID anime, ale ne jeho název a odkazy na AnimeNFO a Anime News Network. Není možné + tyto informace přidat ručně, budou zaneseny automaticky! + </dd> +</dl> + + +:SUB:Kategorie +<i> + Systém kategorií byl nahrazen tagy. Tato sekce je zde kvůli místu, aby se zachovala posloupnost + číslování. +</i> + + +:SUB:Obrázek +<p> + Každá vizuální novela by měla mít obrázek, preferován je oficiální art z obalu + některého vydání. V některých případech, hlavně u doujin her, pokud není žádný + oficiální art z obalu dostupný, může být použitý obecný obrázek ze stránek hry + nebo screenshot ze hry samotné.<br /> + Obrázky mohou být nahrány v JPEG nebo PNG formátu a neměly by být větší 500kB. + Všechny obrázky větší 256x400 pixelů budou automaticky zmenšeny, aby na stránku + pasovaly. Pamatujte, že zmenšení se děje odděleně, takže obrázek neuvidíte + hned po nahrání. Tento proces obvykle zabere jen pár vteřin a obrázek by měl být + dostupný krátce po potvrzení formuláře. + <br /><br /> + NSFW varování by mělo být použito v případě, kdy obrázek z obalu není vhodný pro + prostředí přátelských pracovišť. K určení toho, co je "safe for work" a co ne + použijte následující doporučení: +</p><ul> + <li>Nahota je "safe" pouze pokud jsou sexuální znaky zakryty nebo schovány</li> + <li>Bikini, pantsu aa ostatní spodní prádlo jsou "safe" jen pokud neobsahují žádné + implicitní naznačení pohlavní anatomie</li> + <li>Pokud je póza postavy přehnaně sexuálně provokativní, pak je to NSFW</li> + <li>Pokud je zobrazeno několik postav a jsou zobrazeny ve fyzickém kontaktu, který + by se dal považovat za sexuální kontakt (či předehru k němu), pak je obrázek také NSFW. + </li> +</ul><p> + I s těmito doporučeními nemusí být občas jednoduché určit zda je obrázek "safe" nebo ne. + Pokud jste v pochybách, je často nejlepší zvolit NSFW. +</p> + + +:SUB:Vztahy +<p> + Vztahy mezi vizuálními novelami se dají použít k určení toho, jak jsou mezi sebou hry + provázány.<br /> + Když přidáváte vztah, k druhé vizuální novele bude automaticky přidán vztah opačný. + Např. pokud označíte hru x jako pokračování ke hře y, pak hra y bude automaticky + označena jako prequel ke hře x. Nemusíte editovat obě hry.<br /> + Specifikujte pouze <b>přímé</b> vztahy. Pokud má hra 1 zapsán nějaký vztah ke hře 2 + a hra 2 má vztah ke hře 3, pak hra 3 nemusí nutně mít vztah ke hře 1. Toto se může + na první pohled zdát matoucí, ale dá se to pochopit z grafu vztahů. Když editujete + vydání, vždy se snažte myslet na vztahy mezi všemi hrami, které je mají - jak je + ukázáno v grafu - místo toho, abyste se dívali jen na tu jedinou vizuální novelu, + kterou editujete. + <br /> + Máme pevný seznam vztahů, ze kterých se dá vybrat (jak je popsán níže). Jako s mnoha + vztahy, i ty mezi hrami mohou být ve skutečnosti mnohem složitější, než jak je tyto + možnosti mohou popsat. Pokud si nejste jisti, kterou možnost vybrat, pak jedoduše + vyberte tu, o které si myslíte, že je nejblíže vyjádření skutečného vztahu. +</p> +<dl> + <dt>Pokračování</dt><dd> + Pokračování příběhu. <=><i>Prequel</i>. + </dd><dt>Prequel</dt><dd> + Příběh se odehrává před příběhem originálním.<=><i>Pokračování</i>. + </dd><dt>Stejný setting</dt><dd> + Stejný vesmír, svět, realita a časová linie, ale kompletně odlišné postavy. + Definici "settingu" není vždy jednoduché definovat, ale obvykle to znamená, že + pokud místa či předměty, neexistující v reálném světě, popsané v jedné hře, + existují také ve hře druhé, pak se dá použít tento vztah. + </dd><dt>Alternativní verze</dt><dd> + Stejný setting, stejné postavy, ale příběh je odvyprávěn odlišně. + </dd><dt>Sdílí postavy</dt><dd> + Odlišný příběh, který ale sdílí některé postavy. + </dd><dt>Vedlejší příběh</dt><dd> + Příběh se odehrává někdy během příběhu hlavního. <=><i>Parent story</i> + </dd><dt>Hlavní příběh</dt><dd> + Opak <i>vedlejšího příběhu</i>. + </dd><dt>Stejná série</dt><dd> + Hry jsou součástí jedné herní série. + </dd><dt>Fandisk</dt><dd> + <a href="http://en.wikipedia.org/wiki/Fan_disc">Fandisk</a>. + </dd><dt>Originální hra</dt><dd> + Opak fandisku. + </dd> +</dl> + + +:SUB:Screenshoty +Každá jedna vizuální novela může mít až 10 screenshotů. Screenshoty mohou být nahrány v JPEG a PNG +formátu a měly by vždy být v souladu s těmito doporučeními: +<ul> + <li>Všechny obrázky musí být v nejvyšším původním rozlišení VN. Původní rozlišení je takové rozlišení, + pro které jsou dělány bitmapové obrázky, což je 640x480 nebo 800x600 pro většinu vizuálních novel. + Jakékoliv zmenšování nebo zvětšování, ať už provedené enginem hry samotné nebo ručně za použití + editoru obrázků, <b>není</b> povoleno!</li> + <li>Všechny obrázky musí být screenshoty <b>hry samotné</b>, to znamená aby všechny okraje oken byly + odstraněny před nahráním. Nezajímají nás vaše těžce modifikované okraje oken ani vaše úžasné rozložení + AGTH.</li> + <li>Alespoň polovina screenshotů by měly být screenshot přímo ze hry jako takové. Což znamená, že by měly + obsahovat sprity postav nebo nějakou formu dialogu nebo uživatelské rozhraní. Jen CG obrázky událostí + bez jakéhokoliv textu nebo rozhraní jsou povoleny pro demonstraci stylu krslení, ale neměly by mezi + ostatními screenshoty převažovat.</li> + <li>Nahrávání screenshotů s erotickým obsahem je povoleno tak dlouho, dokud je poměr erotických a neerotických + screenshotů jakžtakž v souladu s poměrem erotického a neerotického obsahu ve VN samotné. Například pokud má + desetihodinová VN jen dvě desetiminutové H-scény, pak by asi nebylo patřičné nahrát více jak 2 až tři erotické + obrázky. Na druhou stranu, pokud je VN převážně o sexu, pak nebude dávat smysl nahrát erotický screenshot + jen jeden. Je doporučeno - i pro hry pouze o sexu - mít alespoň jeden neerotický screenshot.</li> + <li>Snažte se o co nejméně spoilerů. Je nemožné nahrát screenshoty, ktré jsou kompletně bez spoilerů, ale + je možné snížit množství spoilerů na minimum. Tedy jsou preferovány screenshoty ue začátku VN a záběry + z pozdějších částí hry jsou v pořádku pokud neodhalují žádné důležité informace z příběhu.</li> + <li>Obrázky, které jsou NSFW by tak měly být označeny, vizte doporučení k <a href="#4">obrázkům</a> výše.</li> + <li>Screenshoty musí být neoznačené: neměly by obsahovat copyright, internetové adresy nebo jiný text, který není + přítomný v původním screenshotu.</li> + <li>Screenshoty by ideálně měly být z anglického nebo z originálního (japonského) vydání. Ostatní jazyky + jsou pvoloeny, ale množství těchto obrázků by mělo být zachování na minimu.</li> +</ul> diff --git a/data/docs/3.cs b/data/docs/3.cs new file mode 100644 index 00000000..2e4b5369 --- /dev/null +++ b/data/docs/3.cs @@ -0,0 +1,138 @@ +:TITLE:Přidání/editace vydání +:INC:index + + +:SUB:Kdy přidat vydání +<p> + 'Vydání' je produkt - buď fyzický nebo digitální - obsahující vizuální novelu (i část). + To vylučuje soundtracky, drama CD, fandisky a ostatní produkty, které neobsahují + vizuální novelu samotnou.<br /> + Všechna vydání by měla být přidána samostatně. Například limitovaná a běžná edice + by neměly být kombinovány do jednoho vydání, i když sdílí datum vydání a obsah. + Pro komerční hry se dají jednotlivá vydání rozlišit podle jejich kódu JAN/UPC/EAN. +</p> + + +:SUB:Obecné informace +<dl> + <dt>Typ</dt><dd> + Je vydání kompletní, částečné nebo trial verze? + Kompletní vydání obsahuje vše. + Částečná vydání obsahují něco ze hry, ale stále jsou věci, které čekají na vydání. + Trial verze jsou výrazně zkrácená volná vydání, aby si člověk mohl hru vyzkoušet + před její koupí. Občas jsou trial verze sestříhány pro stažení na webu a nepředstavují + tak úplně finální produkt.<br /> + V případě patche pro překlad by měl typ značit zda patch slouží k překladu celé hry + (kompletní, complete) nebo pouze jejích částí (částečný, partial). + </dd><dt>Patch</dt><dd> + Použijte toto zaškrtnutí k označení toho, že vydání je (překladatelským) patchem, + použitým k opatchování jiného vydání. + </dd><dt>Freeware</dt><dd> + Toto zaškrtněte, pokud je hra volně ke stažení (či jinak volně dostupná) za nulovou cenu. + </dd><dt>Doujin</dt><dd> + Publikováno doujin kruhem, amatérskou skupinou nebo jedincem, v protikladu k právnické osobě, + jakou je například firma. Toto pole je ignorováno, pokud je typ vydání patch. + </dd><dt>Název (romaji)</dt><dd> + Název vydání latinkou (za užití romanizace nebo překladu) + </dd><dt>Originální název</dt><dd> + Pokud je oficiální název odlišný (obvykle kvůli jiným znakovým sadám), napište sem originální název. + </dd><dt>Jazyk</dt><dd> + V jakém jazyce je toto vydání? Uveďte jazyk, ve kterém je napsána většina hry. + </dd><dt>JAN/UPC/EAN</dt><dd> + <a href="http://en.wikipedia.org/wiki/Global_Trade_Item_Number">GTIN</a> kód produktu. + Často zvaný "JAN" pro japonská vydání, "UPC" v USA a Kanadě a "EAN" v Evropě. Systém automaticky + pozná typ podle kódu a na stránce vydání uvede příslušný termín. + </dd><dt>Číslo v katalogu</dt><dd> + Číslo v katalogu jak je mu přiřazeno producentem. Často se používá pro identifikaci vydání + na webshopech a obvykle se dá najít někde na obalu produktu. + </dd><dt>Oficiální internetová stránka</dt><dd> + URL oficiálních stránek pro tento produkt. + </dd><dt>Datum vydání</dt><dd> + Pro komerční hry datum prodeje. + Pro vše ostatní datum, kdy bylo vydání poprvé dostupné. + Pokud byla hra uvedena na internetové stránce, pak datum příspěvku, který ji oznámil. + </dd><dt>Věková přístupnost</dt><dd> + Minimální věková přístupnost pro vydání. Pro většinu vydání je toto specifikováno na obalu + nebo na internetových stránkách produktuT. + </dd><dt>Poznámky</dt><dd> + Další různé užitečné věci. + Obecně vzato sem patří extra (ale ne předobjednávkové bonusy) a informace o vývoji/překladu. + </dd> +</dl> + + +:SUB:Formát +<dl> + <dt>Rozlišení</dt><dd> + Primární/původní rozlišení obrazovky pro hru. + </dd><dt>Hlas</dt><dd> + Značí, zda toto vydání obsahuje nadabování ve VN/ADV částech hry. + <i>Plně s hlasem</i> znamená, že všechny postavy (obvykle až na hlavního hrdinu + a některé vedlejší postavy) jsou nadabovány ve všech scénách. <i>S hlasem pouze v ero scénách</i> + mluví samo za sebe, a <i>Částečně s hlasem</i> by mělo být použito, pokud je ve hře + nějaký dabing, ale pouze pro hlavní postavu nebo pouze v některých scénách. + </dd><dt>Animace</dt><dd> + To, zda má hra animace se dá upřesnit ve dvou částech: v jedné pro normální příběhovou část + a v jedné pro ero scény, pokud je hra má. <i>Jednoduchými animacemi</i> odkazujeme na + (obvykle opakující se) efekty jako padající lístky nebo sníh v pozadí nebo animované + obličejové výrazy jako mrkání očí a pohyby úst. + <i>Plně animovanými scénami</i> pak myslíme neopakující se scény v anime stylu. Některé hry + jsou v tomto stylu celé, jiné mají plně animovaných jen několik scén. Efekty jako pohyb + postav po obrazovce, základní zoomování a třesení obrázkem v pozadí nebereme jako "animace". + Minihry a jiné herní prvky jsou také vyloučeny, uvažujeme zde pouze příběhové a ero části (v ADV/VN stylu). + </dd> +</dl> +<p> + <b>POZNÁMKA</b>: Pole rozlišení, hlasu a animace nemají žádný význam pro patche a pro tato vydání + by měla zůstat prázdná. + <br /><br /> + <b>Platforma</b><br /> + Platformy, pro které byl produkt vydán.Nezahrnuje emulované platformy (jako Playstation 2 hry na Playstationu 3) + nebo WINE. DVD Přehrávačem se myslí hry hratelné jako běžné DVD video (DVDPG) a toto by nemělo být zaměňováno +s DVD jako s médiem. + <br /><br /> + <b>Média</b> +</p> +<dl> + <dt>Blu-ray</dt><dd> + Blu-ray Disk, obvykle 30-60GB+. Vyžaduje Blu-ray přehrávač/jednotku. Playstation 3 hry + jsou obvykle Blu-ray. + </dd><dt>CD</dt><dd> + CD-ROM, obvykle 700MB. + </dd><dt>DVD</dt><dd> + DVD5, obvykle 4.5GB, nebo DVD9, obvykle 9GB. DVDPG hry jsou na DVD. + </dd><dt>Disketa</dt><dd> + 5 1/4" nebo 3 3/4", ne větší než 1.44MB. + </dd><dt>GD</dt><dd> + Hry na Dreamcast jsou obvykle na GD discích. + </dd><dt>Stažení z internetu</dt><dd> + Cokoliv bez fyzického obalu, tedy získáno stažením přes síť. + </dd><dt>Paměťová karta</dt><dd> + Jakákoliv varianta SD (Secure Digital) karty, včetně MMC varianty, Compact Flash disku nebo "USB Sticku". + Hlavní rozdíl mezi těmito a Cartridgí (níže) je v tom, že paměťová karta je přepisovatelná (RW). + </dd><dt>Cartridge</dt><dd> + Srovnejte s paměťovou kartou (výše). Pouze pro čtení. Famicom (NES), Super Nintendo (SNES), + Game Boy Advanced (GBA) a Nintendo DS používají cartridge. + </dd><dt>Nintendo Optický Disk</dt><dd> + Optické disky, které nejsou CD ani DVD, a které používají některé konzole Nintendo. + </dd><dt>Ostatní</dt><dd> + Jakékoliv médium, které se nedá zahrnout pod jakýkoliv typ z výše uvedených by měl použít tuto volbu. + Tato by ale neměla být používána jen tak a je možné, že si její užití budete muset obhájit. + </dd><dt>UMD</dt><dd> + Universal Media Disk, obvykle 2.2GB. Tento formát používá Playstation Portable. + </dd> +</dl> + + +:SUB:Producenti +<p> + Firmy/skupiny/jedinci, kteří se podíleli na tvorbě, vývoji nebo překladu tohoto vydání. + Nezahrnuje distributory. +</p> + + +:SUB:Vztahy k vizuálním novelám +<p> + Vizuální novely, které toto vydání (ať už částečně nebo plně) zahrnuje. +</p> + diff --git a/data/docs/4.cs b/data/docs/4.cs new file mode 100644 index 00000000..2c4644ac --- /dev/null +++ b/data/docs/4.cs @@ -0,0 +1,36 @@ +:TITLE:Přidání/editace producenta +:INC:index + + +:SUB:Kdy přidat producenta +<p> + Záznam o producentovi by měl být vytvořen, pokud přidáváte vydání vizuální novely vytvořené + producentem, který ještě není zapsán v databázi. Producenti, kteří nemají v databázi zapsána + žádná vydání mohou být po čase vymazáni, takže záznam vytvořte pouze pokud ho provážete + s vydáním. Aby byl producent na seznamu, potřebuje alespoň jeden dokončený produkt. Což + znamená, že co se překladatelských projektů týká, přidávejte skupinu jako producenta až poté, + co opravdu dokončila projekt. +</p> + + +:SUB:Obecné informace +<dl> + <dt>Typ</dt><dd> + Typ producenta. + </dd><dt>Jméno (romaji)</dt><dd> + Jméno producenta v latince, za užití <a href="/d5.1">romanizace</a> + v případě, že originální jméno již nebylo latinkou. <a href="/d5.2">Kapitalizace</a> + je pro toto pole také důležitá. + </dd><dt>Originální jméno</dt><dd> + Pokud Jméno (viz výše) bylo romanizováno, nezapomeňte zde zapsat jméno originální (pravděpodobně japonské). + </dd><dt>Aliasy</dt><dd> + Ostatní jména, pod kterými je producent znám. Více aliasů by mělo být odděleno čárkou. + </dd><dt>Primární jazyk</dt><dd> + Jazyk, ve kterém producent ponejvíce pracuje. Standardně je to japonsky. + </dd><dt>Internetová stránka</dt><dd> + Oficiální webová stránka producenta. + </dd><dt>Popis</dt><dd> + Historie producenta nebo popis toho, jaké hry tvoří. + </dd> +</dl> + diff --git a/data/docs/5.cs b/data/docs/5.cs new file mode 100644 index 00000000..f30cb323 --- /dev/null +++ b/data/docs/5.cs @@ -0,0 +1,82 @@ +:TITLE:Doporučení k editacím +:INC:index + + +:SUB:Romanizace +<p> + Většina čtenářů VNDB jsou anglicky mluvící fanoušci vizuálních novel. Při psaní + databáze předpokládáme, že čtenáři, na které se zaměřujeme, neumí číst či + nerozpozná cokoliv, co není romanizováno. Proto je romanizace užita na mnoha + místech databáze: Hlavní názvy vizuálních novel, vydání a producentů by všechny + měly být příslušně romanizovány, pokud už v takovém stavu nebyly předtím.<br /> + Abychom udrželi databázi v jednotném stylu, rozhodli jsme se pro + <a href="http://en.wikipedia.org/wiki/Hepburn_romanization">Hepburnovu romanizaci</a> + na všech místech. Toto je také konzistentní s + <a href="http://wiki.anidb.net/w/Romanisation">romanizací AniDB</a>. + <br /> + Pro anglická (nebo jiná cizí) slova v neromanizovaném textu by měla původní slova + být použita pokud tak bylo původně zamýšleno. Pokud jsou tato slova v neromanizovaném + skriptu, měla by být romanizována vhodnou romanizační technikou. +</p> + + +:SUB:Kapitalizace +<p> + Občas se stává, že oficiální názvy nebo jména jsou kompletně v malých nebo + velkých písmenech. Pokud pro tuto volbu není žádný pořádný důvod (např. to, že + název je akronym), tyto názvy a jména by měly být příslušně převedeny do + normální anglické kapitalizace (jak je popsáno + <a href="http://en.wikipedia.org/wiki/Capitalization">na Wikipedii</a>) před + zapsáním do databáze.<br /> + Toto se týká jen romanizovaných názvů a hlavních názvů vizuálních novel, pole + 'Originální název' u producentů a jednotlivých vydání by stále mělo používat + oficiální kapitalizaci. +</p> + + +:SUB:Pořadí jmen +<p> + Ve většině anglicky mluvících zemí se jména píší v pořadí "křestní jméno, příjmení". + Toto nazýváme "západním psaním". + V angličtině je obvyklé na někoho volat jeho křestním jménem, pokud ho znáte dobře, jinak se použije příslušný titul a příjmení. + <br /> + V japonštině (a i v dalších jazycích) se jména píší v pořadí "příjmení, křestní jméno". + Toto nazýváme "japonským psaním". + V japonštině na někoho voláme jedním z jeho jmen s použitím příslušného sufixu. + <br /> + Aby pomohly anglicky mluvícím, některé zdroje (např. Wikipedia) užívají japonských jmen v západním psaní. + Zde na vndb.org preferujeme užívání původního psaní, které používala hra. + <br /> + Tedy, pokud byla hra původně japonská s japonskými jmény, použije se japonské psaní. + <br /> + Pokud byla hra původně anglická nebo postava měla kompletně cizí jméno (John Smith), použije se západního psaní. +</p> + + +:SUB:Shrnutí editací +<p> + Editování jakékoliv stránky zahrnuje volitelné pole "Shrnutí editace". + <br /> + To vám umožňuje vysvětlit o čem je vaše editace bez zbytečného zahlcování hlavní stránky. + <br /> + Můžete se zmínit o tom, proč jste pozměnili kategorii, změnili odkaz, nebo ukázat, odkud jsou vaše informace (aby je další přispěvatelé mohli ověřit). + <br /> + Možná chcete přidat vizuální novelu do databáze, ale nejste schopni pro ni najít další informace. + Pokud to zde napíšete, snad je jiný přispěvatel jednou najde a stránku dokončí. +</p> + + +:SUB:Popisy z vnějších zdrojů +<p> + Je možné přidat popis nebo poznámku k vizuální novele, producentovi a jednotlivým vydáním + v databázi. Přestože jsou preferovány původní popisy, užití citovaných popisů z vnějších zdrojů + je povoleno, pokud je na původní zdroj patřičně odkázáno. Preferovaná forma odkázání + na vnější zdroj je přidáním následujícího vzorového kódu pod popis:<br /> + [From [url=<b>URL</b>]<b>title or author</b>[/url]]<br /> + Což je aplikováno jako, například, '[From <a href="http://en.wikipedia.org/Wiki/Ever17">Wikipedia</a>]' + pro popisy převzaté z Wikipedie. Pokud popis není převzta doslova, ale má nějaké změny, + pak by 'From' mělo být nahrazeno něčím podoným a naznačujícím, že popis byl pozměněn, např. 'Edited from', 'Based on'.<br /> + Jelikož není povoleno odkazovat na stránky poskytující nebo vybízející k ilegálnímu stahování, + měla by adresa (URL) pro takovéto popisy zůstat vynechána. +</p> + diff --git a/data/docs/6.cs b/data/docs/6.cs new file mode 100644 index 00000000..6e9226f9 --- /dev/null +++ b/data/docs/6.cs @@ -0,0 +1,89 @@ +:TITLE:Frequently Asked Questions +:INC:index + + +:SUB:Co je to vizuální novela? +<p> + Na vizuální novelu se dá nahlížet jako na kombinaci novely a počítačové hry: + jsou to počítačové hry s dějovou linií obsahující spoustu textu a jen málo + interakce od hráče. Typická vizuální novela obsahuje text přes obrázek + v anime stylu v pozadí a je doprovázena hudbou na pozadí. V průběhu hry + obvykle hráč musí odpovědět na několik otázek, které budou mít dopad na + příběh, tudíž hraní vizuální novely podruhé s jinými odpověďmi může poskytnout + úplně jiný příběh.<br /> + <br /> + Pro více informací je tu <a href="http://en.wikipedia.org/wiki/Visual_Novel"> + článek o vizuálních novelách na Wikipedii</a> nebo popis na stránce + <a href="http://visual-novels.net/vn/index.php?option=com_content&task=view&id=259&Itemid=47">Visual-Novels.net</a>. + Pro obecný dojem z žánru doporučujeme jednu z volných krátkých vizuálních novel z + <a href="http://altogether.insani.org/">projektu al|together</a>. +</p> + + +:SUB:Co takové eroge, H-hry a dating simy? +<p> + Eroge nebo H-hra je vlastně jakákoliv japonská hra, která zahrnuje sexuální + obsah. Hodně vizuálních novel jsou eroge a hodně eroge jsou vizuální novely, + ale není to pravidlo. Definice dating simu je trochu vágnější, ale obvykle + je to to samé jako vizuální novela s tím, že herní systém dating simu staví + na statistikách.<br /> + <br /> + Neexistují žádné pevné hranice definice "vizuálních novel", většina + eroge a dating simů obsahuje prvky vizuálních novel, ale nemusí - + striktně řečeno - být vizuálními novelami jako takovými. Jelikož se VNDB + snaží o srozumitelnost, jednoduše přijímáme jakoukoliv hru, která obsahuje + prvky vizuální novely a je produkována japonskou nebo k japonsku vztaženou + společností nebo doujin kruhem, pro více informací se podívejte na + <a href="/d2">doporučení</a>. +</p> + + +:SUB:Proč databáze vizuálních novel? +<p> + Internet je veliký, hodně veliký, ale množství anglických zdrojů o vizuálních + novelách je jen velmi malé. VNDB se snaží posbírat a zveřejnit co možná nejvíce + informací, které by jinak byly jen velmi těžko k nalezení anglicky mluvícími + hráči. Touto cestou mohou mít fanoušci jednoduchý přehled o nových vydáních + a lokalizacích jejich oblíbené hry a nemusí přitom procházet množstvím + sobě si podobných japonských stránek. +</p> + + +:SUB:Jak mohu VNDB pomoct? +<p> + Je mnoho cest jak na VNDB přispět. První věc, kterou můžete udělat, je + volná editace jakýchkoliv informací, které lze nalézt na těchto stránkách, + takže pokud najdete chybu, stačí kliknout na odkaz "editovat" umístěný + na stránce vpravo nahoře. Můžete také přidávat nové informace (vizuální + novely, producenty, vydání) do databáze, i když před takovým přidáním, + prosíme, databázi nejdříve prohledejte, abychom se vyhnuli zdvojování + stránek.<br /> + <br /> + K diskusi o nových funkcích nebo pro pomoc s vývojem stránek samotných se můžete + kdykoliv účastnit diskuse na <a href="/t">diskusních boardech</a> + nebo se k nám přidat na IRC adrese <a href="irc://irc.synirc.net/vndb">#vndb @ irc.synirc.net</a>. + I pokud nepoužíváte IRC nebo jste jen líní nainstalovat si IRC klienta, můžete se stále přidat + k povídání za použití <a href="http://cgiirc.synirc.net/?chan=%23vndb">Webchatu</a>. + Stačí si vybrat přezdívku a stisknout tlačítko Login! +</p> + + +:SUB:Kde můžu stáhnout vizuální novely? +<p> + Tady ne. Neposkytujeme stahování ani odkazy na zdroje, které podporují ilegální šíření + vizuálních novel. +</p> + +:SUB:Mohu na VNDB odkázat? +<p> + Samozřejmě můžete! Máme dkonce několik ikonek, které můžete k odkazování a podpoře + VNDB použít. Přímé linkování je, na rozdíl od všech ostatních obrázků na těchto stránkách, povoleno.<br /> + <img src="http://static.yorhel.nl/2008/vndb_88x31.gif" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb1.gif" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb2.jpg" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb3.jpg" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb4.jpg" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb5.jpg" style="margin: 5px"> + <img src="http://static.yorhel.nl/2009/vndb6.jpg" style="margin: 5px"><br /> + Pokud cítíte, že ani jeden z těchto bannerů nevyhovuje tomu, co hledáte, neváhejte udělat + jeden sami. diff --git a/data/docs/7.cs b/data/docs/7.cs new file mode 100644 index 00000000..0b0ae6bc --- /dev/null +++ b/data/docs/7.cs @@ -0,0 +1,92 @@ +:TITLE:O nás +:INC:index + + +:SUB:Cíle +<p> + Naším hlavním cílem je vybudovat velkou, srozumitelnou a aktuální databázi pro + informace o všech existujících vizuálních novelách. VNDB se snaží být hlavním + místem, kde lze vyhledat obecné informace jak o vizuálních novelách samotných, + tak praktické informace okolo nich, jako jsou dostupná vydání a producenti.<br /> + Naším vedlejším cílem je propagovat toto úžasné médium zvané vizuální novely + širší veřejnosti, veřejnosti neomezené jen na lidi, kdo rozumí japonsky, ale + komukolibv, kdo se zajímá o literaturu, mangu, anime či hry, bez ohledu na + jejich místopisné zařazení či kulturní rozdíly. +</p> + + +:SUB:Stvoření +<p> + Vše to začalo poté, co <a href="/u2">yorhel</a> dočetl a dohrál + <a href="/v17">Ever17</a>. Pod mohutným dojmem z tohoto mistrovského díla ho napadlo + několik otázek: Po zjištění, že vizuální novely existují, proč stále trvalo několik + měsíců tuhle najít? Proč o ní nikdy předtím neslyšel? Jak může vizuální novela takové + kvality unikat pozornosti takřka všech online anime a hráčských komunit? A nejdůležitěji: + Je tam venku více takových vizuálních novel?<br /> + <br /> + VNDB se zrodila, aby odpověděla na poslední otázku. Kompletní absence jakéhokoliv + centrálního zdroje nebo alespoň jednoduchého seznamu vizuálních novel způsobila, že + bylo velmi obtížné najít nové hry nebo získat dobrý přehled toho, co bylo dostupné. + Problém by vyřešilo, kdyby existovalo nějaké centrální a dobře organizované místo, + kde by všichni mohli sdílet své informace a znalosti o vizuálních novelách.<br /> + <br /> + Po krátkých třech týdnech tvrdé dřiny spatřila v září 2007 první verze VNDB světlo + světa. Zmatenost a malá základna fanoušků okolo vizuálních novel, spolu s holým + minimem funkčnosti a neohebný systém přispívání, který tehdy fungoval, zapříčinily, + že databáze rostla jen pomalým tempem. Ale časem se o VNDB dozvědělo více lidí, + byly představeny nové, pokročilejší funkce a v odpověď na tyto věci začalo více lidí + přispívat informacemi. Představení vylepšeného a otevřeného systému přispívání + v únoru 2008 motivovala ještě více uživatelů k přidání dalších informací a v září 2008 + - rok po původní verzi VNDB - databáze zahrnuje přes 1000 vizuálních novel a 2000 + vydání, a i dnes stále pokračuje v růstu jak do velikosti, tak do kvality. +</p> + + +:SUB:Autoři +<p> + <b>Vývoj kódu</b><br /> + <dl> + <dt>Yorhel</dt><dd>Hlavní vývojářr.</dd> + <dt>3dB</dt><dd>Napsal současný kód ověřující autorizaci uživatelů a na diskusních boardech implementoval limitaci příspěvků za určitý čas.</dd> + </dl> + <br /> + + <b>Překlady</b><br /> + <dl> + <dt>Český</dt><dd><a href="mailto:nya.chan.production@gmail.com">Nya-chan Production</a></dd> + <dt>Maďarský</dt><dd><a href="mailto:bikmate@gmail.com">Bikfalvi Máté</a></dd> + <dt>Ruský</dt><dd><a href="mailto:winkillerstudio@gmail.com">Dmitri Poguliayev</a></dd> + </dl> + + <br /> + <b>Skiny</b> + <dl> + <dt>applehq</dt><dd> + <a href="?skin=lb">Little Busters! (pink)</a>, + <a href="?skin=term">Neon (black)</a> + </dd><dt>EchoMateria</dt><dd> + <a href="?skin=aselia_01">Aselia (sunset)</a>, + <a href="?skin=carnevale">Gekkou no Carnevale (black)</a>, + <a href="?skin=eiel">EIeL (sand)</a>, + <a href="?skin=ever17_01">Ever17 (light blue)</a>, + <a href="?skin=fate_01">Fate/stay night (rust)</a>, + <a href="?skin=fate_02">Fate/stay night (red)</a>, + <a href="?skin=higu">Higurashi no Naku Koro ni (orange)</a>, + <a href="?skin=lb_02">Little Busters! (sand)</a>, + <a href="?skin=haze">Primitive Link (haze)</a>, + <a href="?skin=saya">Saya no Uta (maroon)</a>, + <a href="?skin=seinarukana">Seinarukana (white)</a>, + <a href="?skin=taka">Sora no Iro, Mizu no Iro (turquoise)</a>, + <a href="?skin=tsukihime">Tsukihime (purple)</a>, + <a href="?skin=tsukihime_02">Tsukihime (black)</a> + </dd><dt>Yorhel</dt><dd> + <a href="?skin=angel">Angelic Serenade (dark blue)</a>, + <a href="?skin=grey">Touhou (grey)</a> + </dd> + </dl> + <br /> + + <b>5 nejaktivnějších přispívajících</b> +:TOP5CONTRIB: + ...a <a href="/u/all?o=d;s=changes">mnoho dalších</a>. +</p> diff --git a/data/docs/9.cs b/data/docs/9.cs new file mode 100644 index 00000000..f5ceef38 --- /dev/null +++ b/data/docs/9.cs @@ -0,0 +1,74 @@ +:TITLE:Diskusní boardy +:INC:index + + +:SUB:Představení +<p> + VNDB obsahuje pěkně integrované diskusní boardy, které se dají používat k, no, + diskusím. Protože nepoužíváme žádný populární nebo veřejně dostupný software + na fóra, ale místo toho jsme něco napsali sami, tyto diskusní boardy mají několik + odlišností oproti populárním boardům, na které můžete být zvyklí. +</p> + + +:SUB:Boardy +<p> + Aby se zabezpečilo, že hledající lidé najdou váš příspěvek, všechny thready patří + k jednomu nebo více 'boardům', které určují, o čem je daná diskuse. Podobá se to + boardům na ostatních fórche, ale zde má každá položka v databázi svůj vlastní board + a je možné odkázat thread do více než jednoho boardu. Použít se dají následující + boardy: +</p> +<dl> + <dt>db</dt><dd> + Diskuse o VNDB. Toto je obecný board pro thready, které nejsou o žádné určité položce + v databázi. + </dd><dt>v#</dt><dd> + Pro diskuse o určité vizuální novele. Board <i>v17</i>, například, se používá + pro všechny thready ohledně vizuální novely <a href="/v17">v17</a>. + </dd><dt>p#</dt><dd> + Stejně jako <i>v#</i>, ale pro producenty. + </dd><dt>u#</dt><dd> + <i>u#</i> board se dá použít pro upozornění některého uživatele této stránky ohledně + něčeho co by on/a měl/a vidět nebo k diskusi ohledně jeho/jejích editací. Podobá se to + klasické funkci 'soukromých zpráv' na mnoha stránkách, až na to, že to není 'soukromé'... + </dd><dt>an</dt><dd> + Požíváno pro oznámení ohledně stránek. Pouze pro moderátory. + </dd> +</dl> + + +:SUB:Formátování +<p> + Pro formátování vašich příspěvků můžete použít následující kódy: +</p> +<dl> + <dt>X# or X#.#</dt><dd> + 'VNDBID', jak jim říkáme. Jsou to písmena (d, p, r, u or v), za kterými následuje číslo a můžou být následovány + tečkou a druhým číslem. VNDBID budou automaticky převedeny na odkazy na příslušnou stránku v databázi. + Například pokud napíšete 'v4.4', pak dostanete '<a href="/v4.4">v4.4</a>'. + </dd><dt>URL</dt><dd> + Jakákoliv URL (bez použití [url] tagu, viz níže) bude převedena na odkaz, podobně jako VNDBID. + Příklad: 'http://vndb.org/' bude naformátováno jako '<a href="http://vndb.org/">link</a>'. + </dd><dt>[url]</dt><dd> + Klasický BBCode [url] tag. Dá se použít poze v podobě <i>[url=link]název odkazu[/url]</i>.<br /> + Např. '[url=/v]Seznam vizuálních novel[/url] a [url=http://blicky.net/]nějaká externí stránka[/url]' + bude zobrazeno jako '<a href="/v">Seznam vizuálních novel</a> a <a href="http://blicky.net/">nějaká externí stránka</a>' + </dd><dt>[spoiler]</dt><dd> + Tag [spoiler] by měl být použit pro skrytí informací, které by mohly pokazit potěšení z hraní vizuální novely + lidem, kteří ji ještě nehráli. + </dd><dt>[quote]</dt><dd> + Pokud se odkazujete na jiné lidi, umístěte citovaný příspěvek do [quote] .. [/quote] bloku. Prosíme, povšimněte si, + že populární syntaxe [quote=source] na VNDB nefunguje. (yet) + </dd><dt>[raw]</dt><dd> + Předveďte své dovednosti ve formátovacím kódu umístěním čehokoliv, co nechcete aby bylo naformátováno do [raw] + tagu. Jakýkoliv formátovací kód do teď zmíněný bude v [raw] .. [/raw] bloku ignorován. + </dd> +</dl> +<p> + Nemáme žádný tag [img] a pravděpodobně zde nikdy žádný nebude. Pokud chcete přidat + do příspěvku screenshoty nebo jiné obrázky, pak je, prosíme, nahrajte na externí + hostingovou službu (např. <a href="http://tinypic.com/" rel="nofollow">TinyPic</a>) a odkažte na ně ve svém příspěvku. +</p> + + diff --git a/data/docs/index.cs b/data/docs/index.cs new file mode 100644 index 00000000..08c8b500 --- /dev/null +++ b/data/docs/index.cs @@ -0,0 +1,14 @@ +<ul class="index"> + <li><b>Doporučení</b></li> + <li><a href="/d5">Doporučení k editacím</a></li> + <li><a href="/d2">Vizuální novely</a></li> + <li><a href="/d3">Vydání</a></li> + <li><a href="/d4">Producenti</a></li> + <li><a href="/d10">Tagy</a></li> + <li><b>O VNDB</b></li> + <li><a href="/d9">Diskusní boardy</a></li> + <li><a href="/d6">FAQ</a></li> + <li><a href="/d7">O nás</a></li> + <li><a href="/d8">Vývoj</a></li> +</ul> + diff --git a/data/docs/notfinished.cs b/data/docs/notfinished.cs new file mode 100644 index 00000000..ad45d31b --- /dev/null +++ b/data/docs/notfinished.cs @@ -0,0 +1,4 @@ +<div class="warning"> + Tato stránka ještě není dokončena!<br /> + Pokud byste nám chtěli pomoct s jejím dokončováním, pak se k nám, prosíme, připojte na <a href="irc://irc.synirc.net/vndb">IRC</a>. +</div> -- cgit v1.2.3 From 8ed189803adf0e8cd47e7be0566b4ca94bd7448b Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 24 Oct 2009 10:56:35 +0200 Subject: lang.pl: Added 'stage' functionality --- util/lang.pl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/util/lang.pl b/util/lang.pl index 28950f0f..087dea2e 100755 --- a/util/lang.pl +++ b/util/lang.pl @@ -35,6 +35,9 @@ $0 merge <lang> <file> $0 reorder <lang1>,<lang2>,.. Re-orders the translation lines in lang.txt using the specified order. + +$0 stage <lang> + Puts all changes of <lang> into the git index, and leaves everything else untouched. __ exit; } @@ -142,6 +145,17 @@ sub reorder { } +sub stage { + my $lang = shift; + chdir "$ROOT/data"; + rename 'lang.txt', '.lang.txt.tmp' or die $!; + `git checkout lang.txt`; + merge $lang, '.lang.txt.tmp'; + `git add lang.txt`; + rename '.lang.txt.tmp', 'lang.txt'; +} + + usage if !@ARGV; my $act = shift; stats if $act eq 'stats'; @@ -149,4 +163,5 @@ add @ARGV if $act eq 'add'; only @ARGV if $act eq 'only'; merge @ARGV if $act eq 'merge'; reorder @ARGV if $act eq 'reorder'; +stage @ARGV if $act eq 'stage'; -- cgit v1.2.3 From 0557a463cf3e1b2cd5dbb4f799a2d08c9a6cd789 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 24 Oct 2009 11:36:57 +0200 Subject: Added Spawned <> Originated from producer relation --- data/global.pl | 6 ++++-- data/lang.txt | 24 ++++++++++++++++++------ util/dump.sql | 2 +- util/updates/update_2.8.sql | 2 +- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/data/global.pl b/data/global.pl index a807c9ca..6dae908f 100644 --- a/data/global.pl +++ b/data/global.pl @@ -52,10 +52,12 @@ our %S = (%S, prod_relations => { 'old' => [ 0, 'new' ], 'new' => [ 1, 'old' ], - 'par' => [ 2, 'sub' ], - 'sub' => [ 3, 'par' ], + 'sub' => [ 2, 'par' ], + 'par' => [ 3, 'sub' ], 'imp' => [ 4, 'ipa' ], 'ipa' => [ 5, 'imp' ], + 'spa' => [ 6, 'ori' ], + 'ori' => [ 7, 'spa' ], }, age_ratings => { -1 => [ 'Unknown' ], diff --git a/data/lang.txt b/data/lang.txt index a14050c3..3debd07d 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -603,18 +603,18 @@ ru : Унаследована cs : Nahrazeno hu : Utódja -:_prodrel_par -en : Parent producer -ru : Исходная компания -cs : Mateřský producent -hu : Szüllő készítő - :_prodrel_sub en : Subsidiary ru : Второстепенная cs : Vedlejší hu : Alválalat +:_prodrel_par +en : Parent producer +ru : Исходная компания +cs : Mateřský producent +hu : Szüllő készítő + :_prodrel_imp en : Imprint ru : Марка @@ -627,6 +627,18 @@ ru : Исходный бренд cs : mateřská značka hu : Szüllő márka +:_prodrel_spa +en : Spawned +ru*: +cs*: +hu*: + +:_prodrel_ori +en : Originated from +ru*: +cs*: +hu*: + # release types diff --git a/util/dump.sql b/util/dump.sql index c04273b6..9f8710f8 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -8,7 +8,7 @@ CREATE LANGUAGE plpgsql; CREATE TYPE anime_type AS ENUM ('tv', 'ova', 'mov', 'oth', 'web', 'spe', 'mv'); CREATE TYPE dbentry_type AS ENUM ('v', 'r', 'p'); CREATE TYPE medium AS ENUM ('cd', 'dvd', 'gdr', 'blr', 'flp', 'mrt', 'mem', 'umd', 'nod', 'in', 'otc'); -CREATE TYPE producer_relation AS ENUM ('old', 'new', 'par', 'sub', 'imp', 'ipa'); +CREATE TYPE producer_relation AS ENUM ('old', 'new', 'sub', 'par', 'imp', 'ipa', 'spa', 'ori'); CREATE TYPE release_type AS ENUM ('complete', 'partial', 'trial'); CREATE TYPE vn_relation AS ENUM ('seq', 'preq', 'set', 'alt', 'char', 'side', 'par', 'ser', 'fan', 'orig'); diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index e299e608..3c1d7398 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -34,7 +34,7 @@ ALTER TABLE vn_relations ALTER COLUMN relation TYPE vn_relation USING -- producer relations -CREATE TYPE producer_relation AS ENUM ('old', 'new', 'par', 'sub', 'imp', 'ipa'); +CREATE TYPE producer_relation AS ENUM ('old', 'new', 'sub', 'par', 'imp', 'ipa', 'spa', 'ori'); CREATE TABLE producers_relations ( pid1 integer NOT NULL REFERENCES producers_rev (id), pid2 integer NOT NULL REFERENCES producers (id), -- cgit v1.2.3 From 56e691ac21163519392bb1711d173f4b52c24470 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 24 Oct 2009 11:39:45 +0200 Subject: Multi::RG: Minor log format change Better aligned, easier to read. --- lib/Multi/RG.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Multi/RG.pm b/lib/Multi/RG.pm index de3e89bf..b3f9bb46 100644 --- a/lib/Multi/RG.pm +++ b/lib/Multi/RG.pm @@ -192,7 +192,7 @@ sub finish { # num, res $_[KERNEL]->post(pg => do => "UPDATE $table SET rgraph = ? WHERE id IN($ids)", [ $id ]); # log - $_[KERNEL]->call(core => log => 'Generated %s relation graph #%d in %.2fs, V: %s', $table, $id, time-$_[HEAP]{start}, $ids); + $_[KERNEL]->call(core => log => 'Generated relation graph #%d in %.2fs, %s: %s', $id, time-$_[HEAP]{start}, uc $_[HEAP]{type}, $ids); # clean up delete @{$_[HEAP]}{qw| start id type nodes rels svg proc |}; -- cgit v1.2.3 From b4bef02c08a3bc8198f97d0e97701981f9bb85c8 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 24 Oct 2009 11:41:51 +0200 Subject: Removed update_rev() function and monthly revcache cron The changes.rev column should be correct in the first place, and in the (most likely) impossible condition that it isn't, the update_rev() function is more likely to make things worse. --- lib/Multi/Maintenance.pm | 12 ++---------- util/dump.sql | 25 ------------------------- util/updates/update_2.8.sql | 4 ++++ 3 files changed, 6 insertions(+), 35 deletions(-) diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm index 0bd5eb91..4f816e56 100644 --- a/lib/Multi/Maintenance.pm +++ b/lib/Multi/Maintenance.pm @@ -18,12 +18,12 @@ sub spawn { $p => [qw| _start shutdown set_daily daily set_monthly monthly log_stats vncache tagcache vnpopularity cleangraphs - usercache statscache revcache logrotate + usercache statscache logrotate |], ], heap => { daily => [qw|vncache tagcache vnpopularity cleangraphs|], - monthly => [qw|usercache statscache revcache logrotate|], + monthly => [qw|usercache statscache logrotate|], @_, }, ); @@ -173,14 +173,6 @@ sub statscache { } -sub revcache { - # This -really- shouldn't be necessary... - # Currently takes about 25 seconds to complete - $_[KERNEL]->post(pg => do => q|SELECT update_rev('vn', ''), update_rev('releases', ''), update_rev('producers', '')|, - undef, 'log_stats', 'revcache'); -} - - sub logrotate { my $dir = sprintf '%s/old', $VNDB::M{log_dir}; mkdir $dir if !-d $dir; diff --git a/util/dump.sql b/util/dump.sql index 9f8710f8..0fdf5696 100644 --- a/util/dump.sql +++ b/util/dump.sql @@ -420,31 +420,6 @@ ALTER TABLE wlists ADD FOREIGN KEY (vid) REFERENCES vn ------------------------- --- update_rev(table, ids) - updates the rev column in the changes table -CREATE FUNCTION update_rev(tbl text, ids text) RETURNS void AS $$ -DECLARE - r RECORD; - r2 RECORD; - i integer; - t text; - e text; -BEGIN - SELECT INTO t SUBSTRING(tbl, 1, 1); - e := ''; - IF ids <> '' THEN - e := ' WHERE id IN('||ids||')'; - END IF; - FOR r IN EXECUTE 'SELECT id FROM '||tbl||e LOOP - i := 1; - FOR r2 IN EXECUTE 'SELECT id FROM '||tbl||'_rev WHERE '||t||'id = '||r.id||' ORDER BY id ASC' LOOP - UPDATE changes SET rev = i WHERE id = r2.id; - i := i+1; - END LOOP; - END LOOP; -END; -$$ LANGUAGE plpgsql; - - -- update_vncache(id) - updates the c_* columns in the vn table CREATE FUNCTION update_vncache(id integer) RETURNS void AS $$ DECLARE diff --git a/util/updates/update_2.8.sql b/util/updates/update_2.8.sql index 3c1d7398..d8373210 100644 --- a/util/updates/update_2.8.sql +++ b/util/updates/update_2.8.sql @@ -207,3 +207,7 @@ END; $$ LANGUAGE plpgsql; SELECT tag_vn_calc(); + +-- remove update_rev() +DROP FUNCTION update_rev(text, text); + -- cgit v1.2.3 From e11b9e81d5405ba42add01c6d3dcc7029a014e0f Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 24 Oct 2009 12:05:58 +0200 Subject: d3: Wrote explanation about producer roles --- data/docs/3 | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/data/docs/3 b/data/docs/3 index f3f5fbdf..4ac8ded5 100644 --- a/data/docs/3 +++ b/data/docs/3 @@ -132,8 +132,22 @@ :SUB:Producers <p> - The companies/groups/individuals involved in the creation, development or translation - of this release. Does not include distributors. + The companies/groups/individuals involved in the development or publishing of + this release. Does not include distributors. The following roles can be selected: + <dl> + <dt>Developer</dt><dd> + The producer involved in the creation of the game itself, not necessarily of + this specific release. Keep in mind that producers that have made modifications + to a game but have not made the game itself should NOT be listed as developers. + </dd><dt>Publisher</dt><dd> + The producer responsible for publishing this specific release. The publisher may have + made modifications to the game (e.g. translating all text or porting to a different + platform), but was not involved in the creation process. + </dd><dt>Both</dt><dd> + When the release is developed and published by the same producer. This is often + true for doujin games and the first releases of commercial games. + </dd> + </dl> </p> -- cgit v1.2.3 From 3691e4a09a308dc3592a7624d33dbbfe08465b89 Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Sat, 24 Oct 2009 13:06:52 +0200 Subject: d4: Documented the producer relations --- data/docs/4 | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/data/docs/4 b/data/docs/4 index 927b7d2d..45acb927 100644 --- a/data/docs/4 +++ b/data/docs/4 @@ -35,3 +35,38 @@ </dd> </dl> + +:SUB:Relations +These relations provide information about which producers are related to each +other, and how they are related. Choosing the correct relation may be a bit +confusing, check the relation graph of the producer entry in case of doubt. +The following relations are defined: +<dl> + <dt>Formerly</dt><dd> + The current producer was earlier known as the selected producer. This can be + because of a name change, or when the earlier producer disbanded and the same + people started again under a different name. + </dd><dt>Succeeded by</dt><dd> + Reverse of <i>Formerly</i>. + </dd><dt>Subsidiary</dt><dd> + Selected producer is a subsidiary of the current producer. A subsidiary is + still "part" of the parent producer, but consist of a different group and + publishes under a different name. + </dd><dt>Parent producer</dt><dd> + Reverse of <i>Subsidiary</i>. + </dd><dt>Imprint</dt><dd> + Selected producer is an imprint of the current producer. Simply put, an + "imprint" is a different name for the same group of people, used when + publishing games. See <a href="http://en.wikipedia.org/wiki/Imprint">Wikipedia</a> for more info. + </dd><dt>Parent brand</dt><dd> + Reverse of <i>Imprint</i>. + </dd><dt>Spawned</dt><dd> + The selected producer was formed by former members of the current producers. + The difference with the <i>Formerly</i> relation is that the producer where the + members came from is still alive. + </dd><dt>Originated from</dt><dd> + Reverse of <i>Spawned</i>. + </dd> +</dl> + + -- cgit v1.2.3 From a8921887bddb7242a95e99b5177aff6ff6cd11be Mon Sep 17 00:00:00 2001 From: Dmitri Poguliayev <winkillerstudio@gmail.com> Date: Sat, 24 Oct 2009 14:51:19 +0200 Subject: L10N-RU: Synchronised lang.txt --- data/lang.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/lang.txt b/data/lang.txt index 3debd07d..aed32345 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -629,13 +629,13 @@ hu : Szüllő márka :_prodrel_spa en : Spawned -ru*: +ru : Порождена cs*: hu*: :_prodrel_ori en : Originated from -ru*: +ru : Вышла из cs*: hu*: @@ -905,13 +905,13 @@ hu : Ismeretlen :_vnlength_1 en : Very short[index,_1,, (< 2 hours), (OMGWTHOTL~, A Dream of Summer)] -ru : Очень короткая[index,_1,, (< 2 часов), (OMGWTFOTL~, A Dream Of Summer)] +ru : Крошечная[index,_1,, (< 2 часов), (OMGWTFOTL~, A Dream Of Summer)] cs : Velmi krátká[index,_1,, (< 2 hours), (OMGWTHOTL~, A Dream of Summer)] hu : Nagyon rövid[index,_1,, (< 2 óra), (OMGWTHOTL~, A Dream of Summer)] :_vnlength_2 en : Short[index,_1,, (2 - 10 hours), (Narcissu~, Planetarian)] -ru : Короткая[index,_1,, (2 - 10 часов), (Narcissu~, Planetarian)] +ru : Малая[index,_1,, (2 - 10 часов), (Narcissu~, Planetarian)] cs : Krátká[index,_1,, (2 - 10 hours), (Narcissu~, Planetarian)] hu : Rövid[index,_1,, (2 - 10 óra), (Narcissu~, Planetarian)] -- cgit v1.2.3