]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/Plugin/po.pm
po: new po_translation_status_in_links option
[git.ikiwiki.info.git] / IkiWiki / Plugin / po.pm
index ae97a2f380bb9fbc0518ea865dda04bcccd5cae2..33bc2b0577153b20815fb4dd1b8e9519b7972be5 100644 (file)
@@ -35,7 +35,7 @@ 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 => "renamepage", id => "po", call => \&renamepage);
+       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);
@@ -48,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);
 } #}}}
 
 
@@ -108,6 +110,13 @@ sub getsetup () { #{{{
                        safe => 1,
                        rebuild => 1,
                },
+               po_translation_status_in_links => {
+                       type => "boolean",
+                       example => 1,
+                       description => "display translation status in links to translations",
+                       safe => 1,
+                       rebuild => 1,
+               },
 } #}}}
 
 sub checkconfig () { #{{{
@@ -142,6 +151,10 @@ 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';
        }
+       if (! exists $config{po_translation_status_in_links} ||
+           ! defined $config{po_translation_status_in_links}) {
+               $config{po_translation_status_in_links}=1;
+       }
        push @{$config{wiki_file_prune_regexps}}, qr/\.pot$/;
 } #}}}
 
@@ -327,25 +340,27 @@ 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.
-#
-# FIXME:
-# This hook is called once per page linking to the old page, which
-# means our delete hook won't know it should not delete a renamed orphan
-# page's translation.
-#
-# Moreover, we can't recognize such pages at delete stage:
-# existing links are fixed in the renaming process, so every
-# renamed page's old location will be an orphan anyway at this time.
-sub renamepage(@) { #{{{
-       my %params=@_;
-       my $oldpage=$params{oldpage};
-       my $newpage=$params{newpage};
-
-       setrenamed($oldpage, $newpage) if istranslatable($oldpage);
-       return $params{content};
+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(@) { #{{{
@@ -353,18 +368,12 @@ sub mydelete(@) { #{{{
 
        map {
                deletetranslations($_);
-       } grep { istranslatablefile($_) && ! renamed(pagename($_))} @deleted;
+       } grep { istranslatablefile($_) } @deleted;
 } #}}}
 
 sub change(@) { #{{{
        my @rendered=@_;
 
-       my $eachrenamed=eachrenamed();
-       while (my ($oldpage, $newpage) = $eachrenamed->()) {
-               renametranslations($oldpage, $newpage);
-       }
-       resetrenamed();
-
        my $updated_po_files=0;
 
        # Refresh/create POT and PO files as needed.
@@ -393,26 +402,9 @@ sub change(@) { #{{{
        }
 
        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");
        }
 } #}}}
 
@@ -486,9 +478,34 @@ 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 unless $config{po_translation_status_in_links};
+       return $res.' ('.percenttranslated($page).' %)';
+} #}}}
 
 # ,----
 # | Blackboxes for private data
@@ -526,35 +543,6 @@ sub myurlto ($$;$) { #{{{
        } #}}}
 }
 
-{
-       my %renamed;
-
-       sub renamed ($) { #{{{
-               my $page=shift;
-
-               if (exists $renamed{$page} &&
-                   defined $renamed{$page}) {
-                       return $renamed{$page};
-               }
-               return;
-       } #}}}
-
-       sub setrenamed ($$) { #{{{
-               my $oldpage=shift;
-               my $newpage=shift;
-
-               $renamed{$oldpage}=$newpage;
-       } #}}}
-
-       sub resetrenamed () { #{{{
-               undef %renamed;
-       } #}}}
-
-       sub eachrenamed () { #{{{
-               return sub { each %renamed };
-       } #}}}
-}
-
 # ,----
 # | Helper functions
 # `----
@@ -756,6 +744,7 @@ sub urlto_with_orig_beautiful_urlpath($$) { #{{{
 sub percenttranslated ($) { #{{{
        my $page=shift;
 
+       $page=~s/^\///;
        return gettext("N/A") unless istranslation($page);
        my $file=srcfile($pagesources{$page});
        my $masterfile = srcfile($pagesources{masterpage($page)});
@@ -822,21 +811,57 @@ sub homepageurl (;$) { #{{{
        return urlto('', $page);
 } #}}}
 
-# - do *not* implement this until the renamepage hook works
-# - do *not* delete translations of pages that were orphans
-#   before being renamed (see renamepage hook comments above)
 sub deletetranslations ($) { #{{{
        my $deletedmasterfile=shift;
 
-       debug "po(deletetranslations): TODO: delete translations of $deletedmasterfile";
-} #}}}
+       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}};
 
-sub renametranslations (@) { #{{{
-       my ($oldpage, $newpage)=shift;
+       map {
+               if ($config{rcs}) {
+                       IkiWiki::rcs_remove($_);
+               }
+               else {
+                       IkiWiki::prune("$config{srcdir}/$_");
+               }
+       } @todelete;
 
-       debug "po(renametranslations): TODO: rename translations of $oldpage to $newpage";
+       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