X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/fbfda5ccfce40d3f0b5a6076ef02f07e9e5b8fd6..b5b8c5cec:/IkiWiki/Plugin/po.pm

diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm
index a233fb5af..6107a4a22 100644
--- a/IkiWiki/Plugin/po.pm
+++ b/IkiWiki/Plugin/po.pm
@@ -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,7 +47,7 @@ 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);
@@ -64,8 +66,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 +143,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 +154,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($_)
@@ -334,6 +342,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 +384,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 +433,7 @@ sub mydelete (@) {
 	map { deletetranslations($_) } grep istranslatablefile($_), @deleted;
 }
 
-sub change (@) {
+sub rendered (@) {
 	my @rendered=@_;
 
 	my $updated_po_files=0;
@@ -615,23 +637,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 +666,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
@@ -793,11 +824,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 +863,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 ($$) {
@@ -1015,8 +1059,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 +1072,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 +1084,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 +1125,7 @@ sub deletetranslations ($) {
 			IkiWiki::rcs_remove($_);
 		}
 		else {
-			IkiWiki::prune("$config{srcdir}/$_");
+			IkiWiki::prune("$config{srcdir}/$_", $config{srcdir});
 		}
 	} @todelete;
 
@@ -1227,6 +1275,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 +1290,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 +1342,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 {