X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/36312b13b4eced4bc328ed09bb40307671490b35..0d874f0b69c25cb4c5faed59261446dad0b22d32:/IkiWiki/Plugin/po.pm diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm index a6342c74f..292775975 100644 --- a/IkiWiki/Plugin/po.pm +++ b/IkiWiki/Plugin/po.pm @@ -35,6 +35,8 @@ sub import { #{{{ hook(type => "filter", id => "po", call => \&filter); hook(type => "htmlize", id => "po", call => \&htmlize); hook(type => "pagetemplate", id => "po", call => \&pagetemplate, last => 1); + hook(type => "rename", id => "po", call => \&renamepages); + hook(type => "delete", id => "po", call => \&mydelete); hook(type => "change", id => "po", call => \&change); hook(type => "editcontent", id => "po", call => \&editcontent); @@ -46,6 +48,8 @@ sub import { #{{{ inject(name => "IkiWiki::targetpage", call => \&mytargetpage); $origsubs{'urlto'}=\&IkiWiki::urlto; inject(name => "IkiWiki::urlto", call => \&myurlto); + $origsubs{'nicepagetitle'}=\&IkiWiki::nicepagetitle; + inject(name => "IkiWiki::nicepagetitle", call => \&mynicepagetitle); } #}}} @@ -150,6 +154,7 @@ sub needsbuild () { #{{{ # a given master page was rendered because its source file was changed @origneedsbuild=(@$needsbuild); + flushmemoizecache(); buildtranslationscache(); # make existing translations depend on the corresponding master page @@ -324,56 +329,71 @@ sub pagetemplate (@) { #{{{ } } # }}} +# Add the renamed page translations to the list of to-be-renamed pages. +# Save information about master page rename, so that: +# - our delete hook can ignore the translations not renamed already +# - our change hook can rename the translations accordingly. +sub renamepages() { #{{{ + my $torename=shift; + my @torename=@{$torename}; + + foreach my $rename (@torename) { + next unless istranslatable($rename->{src}); + my %otherpages=%{otherlanguages($rename->{src})}; + while (my ($lang, $otherpage) = each %otherpages) { + push @{$torename}, { + src => $otherpage, + srcfile => $pagesources{$otherpage}, + dest => otherlanguage($rename->{dest}, $lang), + destfile => $rename->{dest}.".".$lang.".po", + required => 0, + }; + } + } +} #}}} + +sub mydelete(@) { #{{{ + my @deleted=@_; + + map { + deletetranslations($_); + } grep { istranslatablefile($_) } @deleted; +} #}}} + sub change(@) { #{{{ my @rendered=@_; my $updated_po_files=0; # Refresh/create POT and PO files as needed. - foreach my $page (map pagename($_), @rendered) { - next unless istranslatable($page); - my $file=srcfile($pagesources{$page}); + foreach my $file (@rendered) { + next unless istranslatablefile($file); + my $page=pagename($file); + my $masterfile=srcfile($file); my $updated_pot_file=0; # Only refresh Pot file if it does not exist, or if # $pagesources{$page} was changed: don't if only the HTML was # refreshed, e.g. because of a dependency. if ((grep { $_ eq $pagesources{$page} } @origneedsbuild) - || ! -e potfile($file)) { - refreshpot($file); + || ! -e potfile($masterfile)) { + refreshpot($masterfile); $updated_pot_file=1; } my @pofiles; map { push @pofiles, $_ if ($updated_pot_file || ! -e $_); - } (pofiles($file)); + } (pofiles($masterfile)); if (@pofiles) { - refreshpofiles($file, @pofiles); + refreshpofiles($masterfile, @pofiles); map { IkiWiki::rcs_add($_); } @pofiles if ($config{rcs}); $updated_po_files=1; } } if ($updated_po_files) { - # Check staged changes in. - if ($config{rcs}) { - IkiWiki::disable_commit_hook(); - IkiWiki::rcs_commit_staged(gettext("updated PO files"), - "IkiWiki::Plugin::po::change", "127.0.0.1"); - IkiWiki::enable_commit_hook(); - IkiWiki::rcs_update(); - } - # Reinitialize module's private variables. - resetalreadyfiltered(); - resettranslationscache(); - flushmemoizecache(); - # Trigger a wiki refresh. - require IkiWiki::Render; - # without preliminary saveindex/loadindex, refresh() - # complains about a lot of uninitialized variables - IkiWiki::saveindex(); - IkiWiki::loadindex(); - IkiWiki::refresh(); - IkiWiki::saveindex(); + commit_and_refresh( + gettext("updated PO files"), + "IkiWiki::Plugin::po::change"); } } #}}} @@ -447,9 +467,33 @@ sub myurlto ($$;$) { #{{{ && istranslatable('index')) { return IkiWiki::beautify_urlpath(IkiWiki::baseurl($from) . "index." . lang($from) . ".$config{htmlext}"); } - return $origsubs{'urlto'}->($to,$from,$absolute); + # avoid using our injected beautify_urlpath if run by cgi_editpage, + # so that one is redirected to the just-edited page rather than to the + # negociated translation; to prevent unnecessary fiddling with caller/inject, + # we only do so when our beautify_urlpath would actually do what we want to + # avoid, i.e. when po_link_to = negotiated + if ($config{po_link_to} eq "negotiated") { + my @caller = caller(1); + my $run_by_editpage = ($caller[3] eq "IkiWiki::cgi_editpage"); + inject(name => "IkiWiki::beautify_urlpath", call => $origsubs{'beautify_urlpath'}) + if $run_by_editpage; + my $res = $origsubs{'urlto'}->($to,$from,$absolute); + inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath) + if $run_by_editpage; + return $res; + } + else { + return $origsubs{'urlto'}->($to,$from,$absolute) + } } #}}} +sub mynicepagetitle ($;$) { #{{{ + my ($page, $unescaped) = (shift, shift); + + my $res = $origsubs{'nicepagetitle'}->($page, $unescaped); + return $res unless istranslation($page); + return $res." (".percenttranslated($page).")"; +} #}}} # ,---- # | Blackboxes for private data @@ -487,7 +531,6 @@ sub myurlto ($$;$) { #{{{ } #}}} } - # ,---- # | Helper functions # `---- @@ -500,16 +543,21 @@ sub maybe_add_leading_slash ($;$) { #{{{ return $str; } #}}} -sub istranslatable ($) { #{{{ - my $page=shift; - - $page=~s#^/##; - my $file=$pagesources{$page}; +sub istranslatablefile ($) { #{{{ + my $file=shift; return 0 unless defined $file; return 0 if (defined pagetype($file) && pagetype($file) eq 'po'); return 0 if $file =~ /\.pot$/; - return 1 if pagespec_match($page, $config{po_translatable_pages}); + return 1 if pagespec_match(pagename($file), $config{po_translatable_pages}); + return; +} #}}} + +sub istranslatable ($) { #{{{ + my $page=shift; + + $page=~s#^/##; + return 1 if istranslatablefile($pagesources{$page}); return; } #}}} @@ -568,20 +616,24 @@ sub islanguagecode ($) { #{{{ return ($code =~ /^[a-z]{2}$/); } #}}} -sub otherlanguages($) { #{{{ +sub otherlanguage ($$) { #{{{ + my $page=shift; + my $code=shift; + + return masterpage($page) if $code eq $config{po_master_language}{code}; + return masterpage($page) . '.' . $code; +} #}}} + +sub otherlanguages ($) { #{{{ my $page=shift; my %ret; - if (istranslatable($page)) { - %ret = %{$translations{$page}} if defined $translations{$page}; - } - elsif (istranslation($page)) { - my $masterpage = masterpage($page); - $ret{$config{po_master_language}{code}} = $masterpage; - foreach my $lang (sort keys %{$translations{$masterpage}}) { - next if $lang eq lang($page); - $ret{$lang} = $translations{$masterpage}{$lang}; - } + return \%ret unless (istranslation($page) || istranslatable($page)); + my $curlang=lang($page); + foreach my $lang + ($config{po_master_language}{code}, keys %{$config{po_slave_languages}}) { + next if $lang eq $curlang; + $ret{$lang}=otherlanguage($page, $lang); } return \%ret; } #}}} @@ -746,6 +798,58 @@ sub homepageurl (;$) { #{{{ return urlto('', $page); } #}}} +sub deletetranslations ($) { #{{{ + my $deletedmasterfile=shift; + + my $deletedmasterpage=pagename($deletedmasterfile); + my @todelete; + map { + my $file = newpagefile($deletedmasterpage.'.'.$_, 'po'); + my $absfile = "$config{srcdir}/$file"; + if (-e $absfile && ! -l $absfile && ! -d $absfile) { + push @todelete, $file; + } + } keys %{$config{po_slave_languages}}; + + map { + if ($config{rcs}) { + IkiWiki::rcs_remove($_); + } + else { + IkiWiki::prune("$config{srcdir}/$_"); + } + } @todelete; + + if (scalar @todelete) { + commit_and_refresh( + gettext("removed obsolete PO files"), + "IkiWiki::Plugin::po::deletetranslations"); + } +} #}}} + +sub commit_and_refresh ($$) { #{{{ + my ($msg, $author) = (shift, shift); + + if ($config{rcs}) { + IkiWiki::disable_commit_hook(); + IkiWiki::rcs_commit_staged($msg, $author, "127.0.0.1"); + IkiWiki::enable_commit_hook(); + IkiWiki::rcs_update(); + } + # Reinitialize module's private variables. + resetalreadyfiltered(); + resettranslationscache(); + flushmemoizecache(); + # Trigger a wiki refresh. + require IkiWiki::Render; + # without preliminary saveindex/loadindex, refresh() + # complains about a lot of uninitialized variables + IkiWiki::saveindex(); + IkiWiki::loadindex(); + IkiWiki::refresh(); + IkiWiki::saveindex(); +} #}}} + # ,---- # | PageSpec's # `----