X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/blobdiff_plain/949c4c0c3a9d188e263068e675e0f2416f313c15..7ef0c19cdfcb751d2e98c9a38e7460c3e16b3268:/IkiWiki/Plugin/po.pm diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm index d741a7928..01912f813 100644 --- a/IkiWiki/Plugin/po.pm +++ b/IkiWiki/Plugin/po.pm @@ -1,14 +1,14 @@ #!/usr/bin/perl # .po as a wiki page type # Licensed under GPL v2 or greater -# Copyright (C) 2008 intrigeri +# Copyright (C) 2008-2009 intrigeri # inspired by the GPL'd po4a-translate, # which is Copyright 2002, 2003, 2004 by Martin Quinson (mquinson#debian.org) package IkiWiki::Plugin::po; use warnings; use strict; -use IkiWiki 2.00; +use IkiWiki 3.00; use Encode; use Locale::Po4a::Chooser; use Locale::Po4a::Po; @@ -39,10 +39,12 @@ sub import { hook(type => "rename", id => "po", call => \&renamepages, first => 1); hook(type => "delete", id => "po", call => \&mydelete); hook(type => "change", id => "po", call => \&change); - hook(type => "cansave", id => "po", call => \&cansave); + # hook(type => "cansave", id => "po", call => \&cansave); hook(type => "canremove", id => "po", call => \&canremove); hook(type => "canrename", id => "po", call => \&canrename); hook(type => "editcontent", id => "po", call => \&editcontent); + hook(type => "formbuilder_setup", id => "po", call => \&formbuilder_setup, last => 1); + hook(type => "formbuilder", id => "po", call => \&formbuilder); $origsubs{'bestlink'}=\&IkiWiki::bestlink; inject(name => "IkiWiki::bestlink", call => \&mybestlink); @@ -126,11 +128,13 @@ sub getsetup () { sub checkconfig () { foreach my $field (qw{po_master_language po_slave_languages}) { if (! exists $config{$field} || ! defined $config{$field}) { - error(sprintf(gettext("Must specify %s"), $field)); + error(sprintf(gettext("Must specify %s when using the %s plugin"), + $field, 'po')); } } if (! (keys %{$config{po_slave_languages}})) { - error(gettext("At least one slave language must be defined in po_slave_languages")); + error(gettext("At least one slave language must be defined ". + "in po_slave_languages when using the po plugin")); } map { islanguagecode($_) @@ -147,8 +151,8 @@ sub checkconfig () { elsif (! grep { $config{po_link_to} eq $_ } ('default', 'current', 'negotiated')) { - warn(sprintf(gettext('po_link_to=%s is not a valid setting, falling back to po_link_to=default'), - $config{po_link_to})); + warn(sprintf(gettext('%s is not a valid value for po_link_to, falling back to po_link_to=default'), + $config{po_link_to})); $config{po_link_to}='default'; } elsif ($config{po_link_to} eq "negotiated" && ! $config{usedirs}) { @@ -439,6 +443,76 @@ sub editcontent () { return $params{content}; } +sub formbuilder_setup (@) { + my %params=@_; + my $form=$params{form}; + my $q=$params{cgi}; + + return unless defined $form->field("do"); + + if ($form->field("do") eq "create") { + # Warn the user: new pages must be written in master language. + my $template=template("pocreatepage.tmpl"); + $template->param(LANG => $config{po_master_language}{name}); + $form->tmpl_param(message => $template->output); + } + elsif ($form->field("do") eq "edit") { + # Remove the rename/remove buttons on slave pages. + # This has to be done after the rename/remove plugins have added + # their buttons, which is why this hook must be run last. + # The canrename/canremove hooks already ensure this is forbidden + # at the backend level, so this is only UI sugar. + if (istranslation($form->field("page"))) { + map { + for (my $i = 0; $i < @{$params{buttons}}; $i++) { + if (@{$params{buttons}}[$i] eq $_) { + delete @{$params{buttons}}[$i]; + last; + } + } + } qw(Rename Remove); + } + } +} + +sub formbuilder (@) { + my %params=@_; + my $form=$params{form}; + my $q=$params{cgi}; + + return unless defined $form->field("do"); + + # Do not allow to create pages of type po: they are automatically created. + # The main reason to do so is to bypass the "favor the type of linking page + # on page creation" logic, which is unsuitable when a broken link is clicked + # on a slave (PO) page. + # This cannot be done in the formbuilder_setup hook as the list of types is + # computed later. + if ($form->field("do") eq "create") { + for my $field ($form->field) { + next unless "$field" eq "type"; + if ($field->type eq 'select') { + # remove po from the list of types + my @types = grep { $_ ne 'po' } $field->options; + $field->options(\@types) if scalar @types; + } + else { + # make sure the default value is not po; + # does this case actually happen? + debug "po(formbuilder) ".gettext("type field is not select - not implemented yet"); + } + } + } + + # Prevent invalid PO content to be saved. + # This cannot be done in the formbuilder_setup hook as the editpage plugin + # unconditionally sets the editcontent field's validate code later. + elsif ($form->field("do") eq "edit") { + if (istranslation($form->field("page"))) { + $form->field(name => "editcontent", validate => \&isvalidpo); + } + } +} # ,---- # | Injected functions @@ -528,7 +602,7 @@ sub mynicepagetitle ($;$) { my $res = $origsubs{'nicepagetitle'}->($page, $unescaped); return $res unless istranslation($page); return $res unless $config{po_translation_status_in_links}; - return $res.' ('.percenttranslated($page).' %)'; + return $res.' ('.percenttranslated($page).' %)'; } # ,---- @@ -723,17 +797,23 @@ sub refreshpofiles ($@) { my @pofiles=@_; my $potfile=potfile($masterfile); - error("[po/refreshpofiles] POT file ($potfile) does not exist") unless (-e $potfile); + (-e $potfile) + or error("po(refreshpofiles) ".sprintf(gettext("POT file (%s) does not exist"), + $potfile)); foreach my $pofile (@pofiles) { IkiWiki::prep_writefile(basename($pofile),dirname($pofile)); if (-e $pofile) { system("msgmerge", "-U", "--backup=none", $pofile, $potfile) == 0 - or error("[po/refreshpofiles:$pofile] failed to update"); + or error("po(refreshpofiles) ". + sprintf(gettext("failed to update %s"), + $pofile)); } else { File::Copy::syscopy($potfile,$pofile) - or error("[po/refreshpofiles:$pofile] failed to copy the POT file"); + or error("po(refreshpofiles) ". + sprintf(gettext("failed to copy the POT file to %s"), + $pofile)); } } } @@ -780,8 +860,10 @@ sub percenttranslated ($) { 'file_in_name' => [ $masterfile ], 'file_in_charset' => 'utf-8', 'file_out_charset' => 'utf-8', - ) or error("[po/percenttranslated:$page]: failed to translate"); + ) or error("po(percenttranslated) ". + sprintf(gettext("failed to translate %s"), $page)); my ($percent,$hit,$queries) = $doc->stats(); + $percent =~ s/\.[0-9]+$//; return $percent; } @@ -908,17 +990,17 @@ sub po_to_markup ($$;$) { DIR => File::Spec->tmpdir, UNLINK => 1)->filename; - sub failure ($) { - my $msg = '[po/po_to_markup:'.$page.'] ' . shift; + my $fail = sub ($) { + my $msg = "po(po_to_markup) - $page : " . shift; if ($nonfatal) { warn $msg; return undef; } error($msg, sub { unlink $infile, $outfile}); - } + }; writefile(basename($infile), File::Spec->tmpdir, $content) - or return failure("failed to write $infile"); + or return $fail->(sprintf(gettext("failed to write %s"), $infile)); my $masterfile = srcfile($pagesources{masterpage($page)}); my %options = ( @@ -930,10 +1012,12 @@ sub po_to_markup ($$;$) { 'file_in_name' => [ $masterfile ], 'file_in_charset' => 'utf-8', 'file_out_charset' => 'utf-8', - ) or return failure("failed to translate"); - $doc->write($outfile) or return failure("could not write $outfile"); + ) or return $fail->(gettext("failed to translate")); + $doc->write($outfile) + or return $fail->(sprintf(gettext("failed to write %s"), $outfile)); - $content = readfile($outfile) or return failure("could not read $outfile"); + $content = readfile($outfile) + or return $fail->(sprintf(gettext("failed to read %s"), $outfile)); # Unlinking should happen automatically, thanks to File::Temp, # but it does not work here, probably because of the way writefile() @@ -963,14 +1047,14 @@ sub isvalidpo ($) { DIR => File::Spec->tmpdir, UNLINK => 1)->filename; - sub failure ($) { + my $fail = sub ($) { my $msg = '[po/isvalidpo] ' . shift; unlink $infile; return IkiWiki::FailReason->new("$msg"); - } + }; writefile(basename($infile), File::Spec->tmpdir, $content) - or return failure("failed to write $infile"); + or return $fail->(sprintf(gettext("failed to write %s"), $infile)); my $res = (system("msgfmt", "--check", $infile, "-o", "/dev/null") == 0);