]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/Plugin/po.pm
Add modified opengraph plugin.
[git.ikiwiki.info.git] / IkiWiki / Plugin / po.pm
index a233fb5affee8927c2d667244c170bf406982403..13b98b739bcd3ea76a6c059f95601bdadc6c1aa6 100644 (file)
@@ -23,13 +23,14 @@ use File::Copy;
 use File::Spec;
 use File::Temp;
 use Memoize;
-use UNIVERSAL;
 
 my ($master_language_code, $master_language_name);
 my %translations;
 my @origneedsbuild;
 my %origsubs;
 my @slavelanguages; # language codes ordered as in config po_slave_languages
+my %slavelanguages; # language code to name lookup
+my $language_code_pattern = '[a-zA-Z]+(?:_[a-zA-Z]+)?';
 
 memoize("istranslatable");
 memoize("_istranslation");
@@ -37,7 +38,8 @@ memoize("percenttranslated");
 
 sub import {
        hook(type => "getsetup", id => "po", call => \&getsetup);
-       hook(type => "checkconfig", id => "po", call => \&checkconfig);
+       hook(type => "checkconfig", id => "po", call => \&checkconfig,
+               last => 1);
        hook(type => "needsbuild", id => "po", call => \&needsbuild);
        hook(type => "scan", id => "po", call => \&scan, last => 1);
        hook(type => "filter", id => "po", call => \&filter);
@@ -45,11 +47,10 @@ sub import {
        hook(type => "pagetemplate", id => "po", call => \&pagetemplate, last => 1);
        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 => "rendered", id => "po", call => \&rendered);
        hook(type => "checkcontent", id => "po", call => \&checkcontent);
        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);
 
@@ -64,8 +65,11 @@ sub import {
                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 (IkiWiki->can('rootpage')) {
+                       $origsubs{'rootpage'}=\&IkiWiki::rootpage;
+                       inject(name => "IkiWiki::rootpage", call => \&myrootpage)
+                               if defined $origsubs{'rootpage'};
+               }
                $origsubs{'isselflink'}=\&IkiWiki::isselflink;
                inject(name => "IkiWiki::isselflink", call => \&myisselflink);
        }
@@ -138,6 +142,7 @@ sub checkconfig () {
                else {
                        $master_language_code=$config{po_master_language}{code};
                        $master_language_name=$config{po_master_language}{name};
+                       $config{po_master_language}=joinlangpair($master_language_code, $master_language_name);
                }
        }
        if (! defined $master_language_code) {
@@ -148,23 +153,25 @@ sub checkconfig () {
        }
 
        if (ref $config{po_slave_languages} eq 'ARRAY') {
-               my %slaves;
                foreach my $pair (@{$config{po_slave_languages}}) {
                        my ($code, $name)=splitlangpair($pair);
-                       if (defined $code) {
+                       if (defined $code && ! exists $slavelanguages{$code}) {
                                push @slavelanguages, $code;
-                               $slaves{$code} = $name;
+                               $slavelanguages{$code} = $name;
                        }
                }
-               $config{po_slave_languages} = \%slaves;
        }
        elsif (ref $config{po_slave_languages} eq 'HASH') {
+               %slavelanguages=%{$config{po_slave_languages}};
                @slavelanguages = sort {
                        $config{po_slave_languages}->{$a} cmp $config{po_slave_languages}->{$b};
-               } keys %{$config{po_slave_languages}};
+               } keys %slavelanguages;
+               $config{po_slave_languages}=[
+                       map { joinlangpair($_, $slavelanguages{$_}) } @slavelanguages
+               ]
        }
 
-       delete $config{po_slave_languages}{$master_language_code};
+       delete $slavelanguages{$master_language_code};
 
        map {
                islanguagecode($_)
@@ -295,9 +302,8 @@ sub filter (@) {
        my $page = $params{page};
        my $destpage = $params{destpage};
        my $content = $params{content};
-       if (istranslation($page) && ! alreadyfiltered($page, $destpage)) {
+       if (istranslation($page)) {
                $content = po_to_markup($page, $content);
-               setalreadyfiltered($page, $destpage);
        }
        return $content;
 }
@@ -334,6 +340,19 @@ sub pagetemplate (@) {
        if ($template->query(name => "istranslatable")) {
                $template->param(istranslatable => istranslatable($page));
        }
+       my $lang_code = istranslation($page) ? lang($page) : $master_language_code;
+       if ($template->query(name => "lang_code")) {
+               $template->param(lang_code => $lang_code);
+       }
+       if ($template->query(name => "html_lang_code")) {
+               $template->param(html_lang_code => htmllangcode($lang_code));
+       }
+       if ($template->query(name => "html_lang_dir")) {
+               $template->param(html_lang_dir => htmllangdir($lang_code));
+       }
+       if ($template->query(name => "lang_name")) {
+               $template->param(lang_name => languagename($lang_code));
+       }
        if ($template->query(name => "HOMEPAGEURL")) {
                $template->param(homepageurl => homepageurl($page));
        }
@@ -363,7 +382,8 @@ sub pagetemplate (@) {
            && $masterpage eq "index") {
                $template->param('parentlinks' => []);
        }
-       if (ishomepage($page) && $template->query(name => "title")) {
+       if (ishomepage($page) && $template->query(name => "title")
+           && !$template->param("title_overridden")) {
                $template->param(title => $config{wikiname});
        }
 }
@@ -411,7 +431,7 @@ sub mydelete (@) {
        map { deletetranslations($_) } grep istranslatablefile($_), @deleted;
 }
 
-sub change (@) {
+sub rendered (@) {
        my @rendered=@_;
 
        my $updated_po_files=0;
@@ -498,15 +518,6 @@ sub canrename (@) {
        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};
@@ -526,7 +537,7 @@ sub formbuilder_setup (@) {
                # 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"))) {
+               if (istranslation(scalar $form->field("page"))) {
                        map {
                                for (my $i = 0; $i < @{$params{buttons}}; $i++) {
                                        if (@{$params{buttons}}[$i] eq $_) {
@@ -615,23 +626,27 @@ sub mybeautify_urlpath ($) {
        return $res;
 }
 
-sub mytargetpage ($$) {
+sub mytargetpage ($$;$) {
        my $page=shift;
        my $ext=shift;
+       my $filename=shift;
 
        if (istranslation($page) || istranslatable($page)) {
                my ($masterpage, $lang) = (masterpage($page), lang($page));
-               if (! $config{usedirs} || $masterpage eq 'index') {
+               if (defined $filename) {
+                       return $masterpage . "/" . $filename . "." . $lang . "." . $ext;
+               }
+               elsif (! $config{usedirs} || $masterpage eq 'index') {
                        return $masterpage . "." . $lang . "." . $ext;
                }
                else {
                        return $masterpage . "/index." . $lang . "." . $ext;
                }
        }
-       return $origsubs{'targetpage'}->($page, $ext);
+       return $origsubs{'targetpage'}->($page, $ext, $filename);
 }
 
-sub myurlto ($$;$) {
+sub myurlto ($;$$) {
        my $to=shift;
        my $from=shift;
        my $absolute=shift;
@@ -640,7 +655,12 @@ sub myurlto ($$;$) {
        if (! length $to
            && $config{po_link_to} eq "current"
            && istranslatable('index')) {
-               return IkiWiki::beautify_urlpath(IkiWiki::baseurl($from) . "index." . lang($from) . ".$config{htmlext}");
+               if (defined $from) {
+                       return IkiWiki::beautify_urlpath(IkiWiki::baseurl($from) . "index." . lang($from) . ".$config{htmlext}");
+               }
+               else {
+                       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
@@ -705,42 +725,6 @@ sub myisselflink ($$) {
        return;
 }
 
-# ,----
-# | Blackboxes for private data
-# `----
-
-{
-       my %filtered;
-
-       sub alreadyfiltered($$) {
-               my $page=shift;
-               my $destpage=shift;
-
-               return exists $filtered{$page}{$destpage}
-                        && $filtered{$page}{$destpage} eq 1;
-       }
-
-       sub setalreadyfiltered($$) {
-               my $page=shift;
-               my $destpage=shift;
-
-               $filtered{$page}{$destpage}=1;
-       }
-
-       sub unsetalreadyfiltered($$) {
-               my $page=shift;
-               my $destpage=shift;
-
-               if (exists $filtered{$page}{$destpage}) {
-                       delete $filtered{$page}{$destpage};
-               }
-       }
-
-       sub resetalreadyfiltered() {
-               undef %filtered;
-       }
-}
-
 # ,----
 # | Helper functions
 # `----
@@ -793,11 +777,11 @@ sub _istranslation ($) {
                         && pagetype($file) eq 'po';
        return 0 if $file =~ /\.pot$/;
 
-       my ($masterpage, $lang) = ($page =~ /(.*)[.]([a-z]{2})$/);
+       my ($masterpage, $lang) = ($page =~ /(.*)[.]($language_code_pattern)$/);
        return 0 unless defined $masterpage && defined $lang
                         && length $masterpage && length $lang
                         && defined $pagesources{$masterpage}
-                        && defined $config{po_slave_languages}{$lang};
+                        && defined $slavelanguages{$lang};
 
        return (maybe_add_leading_slash($masterpage, $hasleadingslash), $lang)
                if istranslatable($masterpage);
@@ -832,10 +816,23 @@ sub lang ($) {
        return $master_language_code;
 }
 
+sub htmllangcode ($) {
+       (my $lang = shift) =~ tr/_/-/;
+       return $lang;
+}
+
+sub htmllangdir ($) {
+       my $lang = shift;
+       if ($lang =~ /^(ar|fa|he)/) {
+               return 'rtl';
+       }
+       return 'ltr';
+}
+
 sub islanguagecode ($) {
        my $code=shift;
 
-       return $code =~ /^[a-z]{2}$/;
+       return $code =~ /^$language_code_pattern$/;
 }
 
 sub otherlanguage_page ($$) {
@@ -949,10 +946,9 @@ sub refreshpofiles ($@) {
                }
 
                if (-e $pofile) {
-                       system("msgmerge", "--previous", "-q", "-U", "--backup=none", $pofile, $potfile) == 0
-                               or error("po(refreshpofiles) ".
-                                        sprintf(gettext("failed to update %s"),
-                                                $pofile));
+                       if (! (system("msgmerge", "--previous", "-q", "-U", "--backup=none", $pofile, $potfile) == 0)) {
+                               print STDERR ("po(refreshpofiles) ". sprintf(gettext("failed to update %s"), $pofile));
+                       }
                }
                else {
                        File::Copy::syscopy($potfile,$pofile)
@@ -1015,8 +1011,8 @@ sub languagename ($) {
 
        return $master_language_name
                if $code eq $master_language_code;
-       return $config{po_slave_languages}{$code}
-               if defined $config{po_slave_languages}{$code};
+       return $slavelanguages{$code}
+               if defined $slavelanguages{$code};
        return;
 }
 
@@ -1028,6 +1024,8 @@ sub otherlanguagesloop ($) {
                push @ret, {
                        url => urlto_with_orig_beautiful_urlpath(masterpage($page), $page),
                        code => $master_language_code,
+                       html_code => htmllangcode($master_language_code),
+                       html_dir => htmllangdir($master_language_code),
                        language => $master_language_name,
                        master => 1,
                };
@@ -1038,6 +1036,8 @@ sub otherlanguagesloop ($) {
                push @ret, {
                        url => urlto_with_orig_beautiful_urlpath($otherpage, $page),
                        code => $lang,
+                       html_code => htmllangcode($lang),
+                       html_dir => htmllangdir($lang),
                        language => languagename($lang),
                        percent => percenttranslated($otherpage),
                }
@@ -1077,7 +1077,7 @@ sub deletetranslations ($) {
                        IkiWiki::rcs_remove($_);
                }
                else {
-                       IkiWiki::prune("$config{srcdir}/$_");
+                       IkiWiki::prune("$config{srcdir}/$_", $config{srcdir});
                }
        } @todelete;
 
@@ -1099,7 +1099,6 @@ sub commit_and_refresh ($) {
                IkiWiki::rcs_update();
        }
        # Reinitialize module's private variables.
-       resetalreadyfiltered();
        resettranslationscache();
        flushmemoizecache();
        # Trigger a wiki refresh.
@@ -1227,6 +1226,7 @@ sub po4a_options($) {
                # how to disable options is not consistent across po4a modules
                $options{includessi} = '';
                $options{includeexternal} = 0;
+               $options{ontagerror} = 'warn';
        }
        elsif ($pagetype eq 'mdwn') {
                $options{markdown} = 1;
@@ -1241,17 +1241,24 @@ sub po4a_options($) {
 sub splitlangpair ($) {
        my $pair=shift;
 
-       my ($code, $name) = ( $pair =~ /^([a-z]{2})\|(.+)$/ );
+       my ($code, $name) = ( $pair =~ /^($language_code_pattern)\|(.+)$/ );
        if (! defined $code || ! defined $name ||
            ! length $code || ! length $name) {
                # not a fatal error to avoid breaking if used with web setup
-               print STDERR sprintf(gettext("%s has invalid syntax: must use CODE|NAME"),
-                       $pair)."\n";
+               warn sprintf(gettext("%s has invalid syntax: must use CODE|NAME"),
+                       $pair);
        }
 
        return $code, $name;
 }
 
+sub joinlangpair ($$) {
+       my $code=shift;
+       my $name=shift;
+
+       return "$code|$name";
+}
+
 # ,----
 # | PageSpecs
 # `----
@@ -1286,7 +1293,7 @@ sub match_lang ($$;@) {
 
        my $regexp=IkiWiki::glob2re($wanted);
        my $lang=IkiWiki::Plugin::po::lang($page);
-       if ($lang !~ /^$regexp$/i) {
+       if ($lang !~ $regexp) {
                return IkiWiki::FailReason->new("file language is $lang, not $wanted");
        }
        else {