+ map { deletetranslations($_) } grep istranslatablefile($_), @deleted;
+}
+
+sub change (@) {
+ my @rendered=@_;
+
+ # All meta titles are first extracted at scan time, i.e. before we turn
+ # PO files back into translated markdown; escaping of double-quotes in
+ # PO files breaks the meta plugin's parsing enough to save ugly titles
+ # to %pagestate at this time.
+ #
+ # Then, at render time, every page passes in turn through the Great
+ # Rendering Chain (filter->preprocess->linkify->htmlize), and the meta
+ # plugin's preprocess hook is this time in a position to correctly
+ # extract the titles from slave pages.
+ #
+ # This is, unfortunately, too late: if the page A, linking to the page
+ # B, is rendered before B, it will display the wrongly-extracted meta
+ # title as the link text to B.
+ #
+ # On the one hand, such a corner case only happens on rebuild: on
+ # refresh, every rendered page is fixed to contain correct meta titles.
+ # On the other hand, it can take some time to get every page fixed.
+ # We therefore re-render every rendered page after a rebuild to fix them
+ # at once. As this more or less doubles the time needed to rebuild the
+ # wiki, we do so only when really needed.
+
+ if (@rendered
+ && exists $config{rebuild} && defined $config{rebuild} && $config{rebuild}
+ && UNIVERSAL::can("IkiWiki::Plugin::meta", "getsetup")
+ && exists $config{meta_overrides_page_title}
+ && defined $config{meta_overrides_page_title}
+ && $config{meta_overrides_page_title}) {
+ debug(sprintf(gettext("rebuilding all pages to fix meta titles")));
+ resetalreadyfiltered();
+ require IkiWiki::Render;
+ foreach my $file (@rendered) {
+ debug(sprintf(gettext("building %s"), $file));
+ IkiWiki::render($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;
+ # 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 ($masterfile eq "$config{srcdir}/$file" &&
+ ((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 grep { $po=~/\Q$_\E/ } @{$config{underlaydirs}};
+ push @pofiles, $po;
+ }
+ if (@pofiles) {
+ refreshpofiles($masterfile, @pofiles);
+ map { IkiWiki::rcs_add($_) } @pofiles if $config{rcs};
+ $updated_po_files=1;
+ }
+ }
+
+ if ($updated_po_files) {
+ commit_and_refresh(
+ gettext("updated PO files"),
+ "IkiWiki::Plugin::po::change");
+ }
+}
+
+sub checkcontent (@) {
+ my %params=@_;
+
+ if (istranslation($params{page})) {
+ my $res = isvalidpo($params{content});
+ if ($res) {
+ return undef;
+ }
+ else {
+ return "$res";
+ }
+ }
+ return undef;
+}
+
+sub canremove (@) {
+ my %params = @_;
+
+ if (istranslation($params{page})) {
+ return gettext("Can not remove a translation. If the master page is removed, ".
+ "however, its translations will be removed as well.");
+ }
+ return undef;
+}
+
+sub canrename (@) {
+ my %params = @_;
+ my $session = $params{session};
+
+ if (istranslation($params{src})) {
+ my $masterpage = masterpage($params{src});
+ # Tell the difference between:
+ # - a translation being renamed as a consequence of its master page
+ # being renamed, which is allowed
+ # - a user trying to directly rename a translation, which is forbidden
+ # by looking for the master page in the list of to-be-renamed pages we
+ # saved early in the renaming process.
+ my $orig_torename = $session->param("po_orig_torename");
+ unless (grep { $_ eq $masterpage } @{$orig_torename}) {
+ return gettext("Can not rename a translation. If the master page is renamed, ".
+ "however, its translations will be renamed as well.");
+ }
+ }
+ return undef;
+}
+
+# As we're previewing or saving a page, the content may have
+# changed, so tell the next filter() invocation it must not be lazy.
+sub editcontent () {
+ my %params=@_;
+
+ unsetalreadyfiltered($params{page}, $params{page});
+ 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);
+ }