X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/e671e72053e81fa06cb9c9407ff17a0beff2f1fe..cddb39cbf5d385273645f62f15bdf29b7607aac2:/IkiWiki/Plugin/po.pm diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm index 14c7318fe..4e6eff94f 100644 --- a/IkiWiki/Plugin/po.pm +++ b/IkiWiki/Plugin/po.pm @@ -51,16 +51,20 @@ sub import { hook(type => "formbuilder_setup", id => "po", call => \&formbuilder_setup, last => 1); hook(type => "formbuilder", id => "po", call => \&formbuilder); - $origsubs{'beautify_urlpath'}=\&IkiWiki::beautify_urlpath; - inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath); - $origsubs{'targetpage'}=\&IkiWiki::targetpage; - inject(name => "IkiWiki::targetpage", call => \&mytargetpage); - $origsubs{'urlto'}=\&IkiWiki::urlto; - inject(name => "IkiWiki::urlto", call => \&myurlto); - $origsubs{'cgiurl'}=\&IkiWiki::cgiurl; - inject(name => "IkiWiki::cgiurl", call => \&mycgiurl); - $origsubs{'rootpage'}=\&IkiWiki::rootpage; - inject(name => "IkiWiki::rootpage", call => \&myrootpage); + if (! %origsubs) { + $origsubs{'bestlink'}=\&IkiWiki::bestlink; + inject(name => "IkiWiki::bestlink", call => \&mybestlink); + $origsubs{'beautify_urlpath'}=\&IkiWiki::beautify_urlpath; + inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath); + $origsubs{'targetpage'}=\&IkiWiki::targetpage; + inject(name => "IkiWiki::targetpage", call => \&mytargetpage); + $origsubs{'urlto'}=\&IkiWiki::urlto; + inject(name => "IkiWiki::urlto", call => \&myurlto); + $origsubs{'cgiurl'}=\&IkiWiki::cgiurl; + inject(name => "IkiWiki::cgiurl", call => \&mycgiurl); + $origsubs{'rootpage'}=\&IkiWiki::rootpage; + inject(name => "IkiWiki::rootpage", call => \&myrootpage); + } } @@ -83,7 +87,8 @@ sub getsetup () { return plugin => { safe => 0, - rebuild => 1, + rebuild => 1, # format plugin + section => "format", }, po_master_language => { type => "string", @@ -130,6 +135,7 @@ sub checkconfig () { $field, 'po')); } } + delete $config{po_slave_languages}{$config{po_master_language}{code}};; map { islanguagecode($_) @@ -153,10 +159,6 @@ sub checkconfig () { warn(gettext('po_link_to=negotiated requires usedirs to be enabled, falling back to po_link_to=default')); $config{po_link_to}='default'; } - unless ($config{po_link_to} eq 'default') { - $origsubs{'bestlink'}=\&IkiWiki::bestlink; - inject(name => "IkiWiki::bestlink", call => \&mybestlink); - } push @{$config{wiki_file_prune_regexps}}, qr/\.pot$/; @@ -175,7 +177,8 @@ sub checkconfig () { if ($config{po_master_language}{code} ne 'en') { # Add underlay containing translated source files # for the master language. - add_underlay("locale/$config{po_master_language}{code}/$underlay"); + add_underlay("locale/$config{po_master_language}{code}/$underlay") + if -d "$config{underlaydirbase}/locale/$config{po_master_language}{code}/$underlay"; } } } @@ -309,7 +312,7 @@ sub pagetemplate (@) { if (ishomepage($page) && $template->query(name => "title")) { $template->param(title => $config{wikiname}); } -} # }}} +} # Add the renamed page translations to the list of to-be-renamed pages. sub renamepages (@) { @@ -388,31 +391,32 @@ sub change (@) { resetalreadyfiltered(); require IkiWiki::Render; foreach my $file (@rendered) { - debug(sprintf(gettext("building %s"), $file)); - IkiWiki::render($file); + IkiWiki::render($file, sprintf(gettext("building %s"), $file)); } } my $updated_po_files=0; # Refresh/create POT and PO files as needed. - # (But avoid doing so if they are in an underlay directory.) foreach my $file (grep {istranslatablefile($_)} @rendered) { my $masterfile=srcfile($file); my $page=pagename($file); my $updated_pot_file=0; + + # Avoid touching underlay files. + next if $masterfile ne "$config{srcdir}/$file"; + # Only refresh POT file if it does not exist, or if - # $pagesources{$page} was changed: don't if only the HTML was + # the source was changed: don't if only the HTML was # refreshed, e.g. because of a dependency. - if ($masterfile eq "$config{srcdir}/$file" && - ((grep { $_ eq $pagesources{$page} } @origneedsbuild) - || ! -e potfile($masterfile))) { + if ((grep { $_ eq $pagesources{$page} } @origneedsbuild) || + ! -e potfile($masterfile)) { refreshpot($masterfile); $updated_pot_file=1; } my @pofiles; foreach my $po (pofiles($masterfile)) { - next if ! $updated_pot_file && ! -e $po; + next if ! $updated_pot_file && -e $po; next if grep { $po=~/\Q$_\E/ } @{$config{underlaydirs}}; push @pofiles, $po; } @@ -425,8 +429,7 @@ sub change (@) { if ($updated_po_files) { commit_and_refresh( - gettext("updated PO files"), - "IkiWiki::Plugin::po::change"); + gettext("updated PO files")); } } @@ -560,15 +563,20 @@ sub formbuilder (@) { # `---- # Implement po_link_to 'current' and 'negotiated' settings. -# Not injected otherwise. sub mybestlink ($$) { my $page=shift; my $link=shift; + return $origsubs{'bestlink'}->($page, $link) + if defined $config{po_link_to} && $config{po_link_to} eq "default"; + my $res=$origsubs{'bestlink'}->(masterpage($page), $link); + my @caller = caller(1); if (length $res && istranslatable($res) - && istranslation($page)) { + && istranslation($page) + && !(exists $caller[3] && defined $caller[3] + && ($caller[3] eq "IkiWiki::PageSpec::match_link"))) { return $res . "." . lang($page); } return $res; @@ -578,7 +586,7 @@ sub mybeautify_urlpath ($) { my $url=shift; my $res=$origsubs{'beautify_urlpath'}->($url); - if ($config{po_link_to} eq "negotiated") { + if (defined $config{po_link_to} && $config{po_link_to} eq "negotiated") { $res =~ s!/\Qindex.$config{po_master_language}{code}.$config{htmlext}\E$!/!; $res =~ s!/\Qindex.$config{htmlext}\E$!/!; map { @@ -722,6 +730,7 @@ sub istranslatablefile ($) { my $type=pagetype($file); return 0 if ! defined $type || $type eq 'po'; return 0 if $file =~ /\.pot$/; + return 0 if ! defined $config{po_translatable_pages}; return 1 if pagespec_match(pagename($file), $config{po_translatable_pages}); return; } @@ -839,18 +848,18 @@ sub refreshpot ($) { my $masterfile=shift; my $potfile=potfile($masterfile); - my %options = ("markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0); - my $doc=Locale::Po4a::Chooser::new('text',%options); + my $doc=Locale::Po4a::Chooser::new(po4a_type($masterfile), + po4a_options($masterfile)); $doc->{TT}{utf_mode} = 1; - $doc->{TT}{file_in_charset} = 'utf-8'; - $doc->{TT}{file_out_charset} = 'utf-8'; + $doc->{TT}{file_in_charset} = 'UTF-8'; + $doc->{TT}{file_out_charset} = 'UTF-8'; $doc->read($masterfile); # let's cheat a bit to force porefs option to be passed to # Locale::Po4a::Po; this is undocument use of internal # Locale::Po4a::TransTractor's data, compulsory since this module # prevents us from using the porefs option. $doc->{TT}{po_out}=Locale::Po4a::Po->new({ 'porefs' => 'none' }); - $doc->{TT}{po_out}->set_charset('utf-8'); + $doc->{TT}{po_out}->set_charset('UTF-8'); # do the actual work $doc->parse; IkiWiki::prep_writefile(basename($potfile),dirname($potfile)); @@ -931,15 +940,13 @@ sub percenttranslated ($) { return gettext("N/A") unless istranslation($page); my $file=srcfile($pagesources{$page}); my $masterfile = srcfile($pagesources{masterpage($page)}); - my %options = ( - "markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0, - ); - my $doc=Locale::Po4a::Chooser::new('text',%options); + my $doc=Locale::Po4a::Chooser::new(po4a_type($masterfile), + po4a_options($masterfile)); $doc->process( 'po_in_name' => [ $file ], 'file_in_name' => [ $masterfile ], - 'file_in_charset' => 'utf-8', - 'file_out_charset' => 'utf-8', + 'file_in_charset' => 'UTF-8', + 'file_out_charset' => 'UTF-8', ) or error("po(percenttranslated) ". sprintf(gettext("failed to translate %s"), $page)); my ($percent,$hit,$queries) = $doc->stats(); @@ -1025,17 +1032,18 @@ sub deletetranslations ($) { if (@todelete) { commit_and_refresh( - gettext("removed obsolete PO files"), - "IkiWiki::Plugin::po::deletetranslations"); + gettext("removed obsolete PO files")); } } -sub commit_and_refresh ($$) { - my ($msg, $author) = (shift, shift); +sub commit_and_refresh ($) { + my $msg = shift; if ($config{rcs}) { IkiWiki::disable_commit_hook(); - IkiWiki::rcs_commit_staged($msg, $author, "127.0.0.1"); + IkiWiki::rcs_commit_staged( + message => $msg, + ); IkiWiki::enable_commit_hook(); IkiWiki::rcs_update(); } @@ -1053,11 +1061,8 @@ sub commit_and_refresh ($$) { IkiWiki::saveindex(); } -# on success, returns the filtered content. -# on error, if $nonfatal, warn and return undef; else, error out. -sub po_to_markup ($$;$) { +sub po_to_markup ($$) { my ($page, $content) = (shift, shift); - my $nonfatal = shift; $content = '' unless defined $content; $content = decode_utf8(encode_utf8($content)); @@ -1080,10 +1085,6 @@ sub po_to_markup ($$;$) { my $fail = sub ($) { my $msg = "po(po_to_markup) - $page : " . shift; - if ($nonfatal) { - warn $msg; - return undef; - } error($msg, sub { unlink $infile, $outfile}); }; @@ -1091,21 +1092,18 @@ sub po_to_markup ($$;$) { or return $fail->(sprintf(gettext("failed to write %s"), $infile)); my $masterfile = srcfile($pagesources{masterpage($page)}); - my %options = ( - "markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0, - ); - my $doc=Locale::Po4a::Chooser::new('text',%options); + my $doc=Locale::Po4a::Chooser::new(po4a_type($masterfile), + po4a_options($masterfile)); $doc->process( 'po_in_name' => [ $infile ], 'file_in_name' => [ $masterfile ], - 'file_in_charset' => 'utf-8', - 'file_out_charset' => 'utf-8', + 'file_in_charset' => 'UTF-8', + 'file_out_charset' => 'UTF-8', ) 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 $fail->(sprintf(gettext("failed to read %s"), $outfile)); + $content = readfile($outfile); # Unlinking should happen automatically, thanks to File::Temp, # but it does not work here, probably because of the way writefile() @@ -1158,6 +1156,37 @@ sub isvalidpo ($) { "to previous page to continue edit")); } +sub po4a_type ($) { + my $file = shift; + + my $pagetype = pagetype($file); + if ($pagetype eq 'html') { + return 'xhtml'; + } + return 'text'; +} + +sub po4a_options($) { + my $file = shift; + + my %options; + my $pagetype = pagetype($file); + + if ($pagetype eq 'html') { + # how to disable options is not consistent across po4a modules + $options{includessi} = ''; + $options{includeexternal} = 0; + } + elsif ($pagetype eq 'mdwn') { + $options{markdown} = 1; + } + else { + $options{markdown} = 0; + } + + return %options; +} + # ,---- # | PageSpecs # `---- @@ -1218,4 +1247,19 @@ sub match_currentlang ($$;@) { } } +sub match_needstranslation ($$;@) { + my $page=shift; + + my $percenttranslated=IkiWiki::Plugin::po::percenttranslated($page); + if ($percenttranslated eq 'N/A') { + return IkiWiki::FailReason->new("file is not a translatable page"); + } + elsif ($percenttranslated < 100) { + return IkiWiki::SuccessReason->new("file has $percenttranslated translated"); + } + else { + return IkiWiki::FailReason->new("file is fully translated"); + } +} + 1