hook(type => "formbuilder_setup", id => "po", call => \&formbuilder_setup, last => 1);
hook(type => "formbuilder", id => "po", call => \&formbuilder);
- $origsubs{'bestlink'}=\&IkiWiki::bestlink;
- inject(name => "IkiWiki::bestlink", call => \&mybestlink);
- $origsubs{'beautify_urlpath'}=\&IkiWiki::beautify_urlpath;
- inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath);
- $origsubs{'targetpage'}=\&IkiWiki::targetpage;
- inject(name => "IkiWiki::targetpage", call => \&mytargetpage);
- $origsubs{'urlto'}=\&IkiWiki::urlto;
- inject(name => "IkiWiki::urlto", call => \&myurlto);
- $origsubs{'cgiurl'}=\&IkiWiki::cgiurl;
- inject(name => "IkiWiki::cgiurl", call => \&mycgiurl);
+ if (! %origsubs) {
+ $origsubs{'bestlink'}=\&IkiWiki::bestlink;
+ inject(name => "IkiWiki::bestlink", call => \&mybestlink);
+ $origsubs{'beautify_urlpath'}=\&IkiWiki::beautify_urlpath;
+ inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath);
+ $origsubs{'targetpage'}=\&IkiWiki::targetpage;
+ inject(name => "IkiWiki::targetpage", call => \&mytargetpage);
+ $origsubs{'urlto'}=\&IkiWiki::urlto;
+ 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);
+ }
}
return
plugin => {
safe => 0,
- rebuild => 1,
+ rebuild => 1, # format plugin
+ section => "format",
},
po_master_language => {
type => "string",
$field, 'po'));
}
}
+ delete $config{po_slave_languages}{$config{po_master_language}{code}};;
map {
islanguagecode($_)
if ($config{po_master_language}{code} ne 'en') {
# Add underlay containing translated source files
# for the master language.
- add_underlay("locale/$config{po_master_language}{code}/$underlay");
+ add_underlay("locale/$config{po_master_language}{code}/$underlay")
+ if -d "$config{underlaydirbase}/locale/$config{po_master_language}{code}/$underlay";
}
}
}
if (istranslation($page)) {
foreach my $destpage (@{$links{$page}}) {
if (istranslatable($destpage)) {
- # replace one occurence of $destpage in $links{$page}
- # (we only want to replace the one that was added by
- # IkiWiki::Plugin::link::scan, other occurences may be
- # there for other reasons)
+ # replace the occurence of $destpage in $links{$page}
for (my $i=0; $i<@{$links{$page}}; $i++) {
if (@{$links{$page}}[$i] eq $destpage) {
@{$links{$page}}[$i] = $destpage . '.' . lang($page);
&& $masterpage eq "index") {
$template->param('parentlinks' => []);
}
-} # }}}
+ if (ishomepage($page) && $template->query(name => "title")) {
+ $template->param(title => $config{wikiname});
+ }
+}
# Add the renamed page translations to the list of to-be-renamed pages.
sub renamepages (@) {
resetalreadyfiltered();
require IkiWiki::Render;
foreach my $file (@rendered) {
- debug(sprintf(gettext("building %s"), $file));
- IkiWiki::render($file);
+ IkiWiki::render($file, sprintf(gettext("building %s"), $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;
+
+ # Avoid touching underlay files.
+ next if $masterfile ne "$config{srcdir}/$file";
+
# Only refresh POT file if it does not exist, or if
- # $pagesources{$page} was changed: don't if only the HTML was
+ # the source 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))) {
+ if ((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 ! $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};
+ map { s/^\Q$config{srcdir}\E\/*//; 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");
+ gettext("updated PO files"));
}
}
if ($form->field("do") eq "create") {
foreach my $field ($form->field) {
next unless "$field" eq "type";
- if ($field->type eq 'select') {
- # remove po from the list of types
- my @types = grep { $_ ne 'po' } $field->options;
- $field->options(\@types) if @types;
+ next unless $field->type eq 'select';
+ my $orig_value = $field->value;
+ # remove po from the list of types
+ my @types = grep { $_->[0] ne 'po' } $field->options;
+ $field->options(\@types) if @types;
+ # favor the type of linking page's masterpage
+ if ($orig_value eq 'po') {
+ my ($from, $type);
+ if (defined $form->field('from')) {
+ ($from)=$form->field('from')=~/$config{wiki_file_regexp}/;
+ $from = masterpage($from);
+ }
+ if (defined $from && exists $pagesources{$from}) {
+ $type=pagetype($pagesources{$from});
+ }
+ $type=$config{default_pageext} unless defined $type;
+ $field->value($type) ;
}
}
}
my $page=shift;
my $link=shift;
+ return $origsubs{'bestlink'}->($page, $link)
+ if defined $config{po_link_to} && $config{po_link_to} eq "default";
+
my $res=$origsubs{'bestlink'}->(masterpage($page), $link);
+ my @caller = caller(1);
if (length $res
- && ($config{po_link_to} eq "current" || $config{po_link_to} eq "negotiated")
&& istranslatable($res)
- && istranslation($page)) {
+ && istranslation($page)
+ && !(exists $caller[3] && defined $caller[3]
+ && ($caller[3] eq "IkiWiki::PageSpec::match_link"))) {
return $res . "." . lang($page);
}
return $res;
my $url=shift;
my $res=$origsubs{'beautify_urlpath'}->($url);
- if ($config{po_link_to} eq "negotiated") {
+ if (defined $config{po_link_to} && $config{po_link_to} eq "negotiated") {
$res =~ s!/\Qindex.$config{po_master_language}{code}.$config{htmlext}\E$!/!;
$res =~ s!/\Qindex.$config{htmlext}\E$!/!;
map {
# 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
+ # avoid, i.e. when po_link_to = negotiated.
+ # also avoid doing so when run by cgi_goto, so that the links on recentchanges
+ # page actually lead to the exact page they pretend to.
if ($config{po_link_to} eq "negotiated") {
my @caller = caller(1);
- my $run_by_editpage = 0;
- $run_by_editpage = 1 if (exists $caller[3] && defined $caller[3]
- && $caller[3] eq "IkiWiki::cgi_editpage");
+ my $use_orig = 0;
+ $use_orig = 1 if (exists $caller[3] && defined $caller[3]
+ && ($caller[3] eq "IkiWiki::cgi_editpage" ||
+ $caller[3] eq "IkiWiki::Plugin::goto::cgi_goto")
+ );
inject(name => "IkiWiki::beautify_urlpath", call => $origsubs{'beautify_urlpath'})
- if $run_by_editpage;
+ if $use_orig;
my $res = $origsubs{'urlto'}->($to,$from,$absolute);
inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath)
- if $run_by_editpage;
+ if $use_orig;
return $res;
}
else {
return $origsubs{'cgiurl'}->(%params);
}
+sub myrootpage (@) {
+ my %params=@_;
+
+ my $rootpage;
+ if (exists $params{rootpage}) {
+ $rootpage=$origsubs{'bestlink'}->($params{page}, $params{rootpage});
+ if (!length $rootpage) {
+ $rootpage=$params{rootpage};
+ }
+ }
+ else {
+ $rootpage=masterpage($params{page});
+ }
+ return $rootpage;
+}
+
# ,----
# | Blackboxes for private data
# `----
my $type=pagetype($file);
return 0 if ! defined $type || $type eq 'po';
return 0 if $file =~ /\.pot$/;
+ return 0 if ! defined $config{po_translatable_pages};
return 1 if pagespec_match(pagename($file), $config{po_translatable_pages});
return;
}
my $masterfile=shift;
my $potfile=potfile($masterfile);
- my %options = ("markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0);
- my $doc=Locale::Po4a::Chooser::new('text',%options);
+ my $doc=Locale::Po4a::Chooser::new(po4a_type($masterfile),
+ po4a_options($masterfile));
$doc->{TT}{utf_mode} = 1;
- $doc->{TT}{file_in_charset} = 'utf-8';
- $doc->{TT}{file_out_charset} = 'utf-8';
+ $doc->{TT}{file_in_charset} = 'UTF-8';
+ $doc->{TT}{file_out_charset} = 'UTF-8';
$doc->read($masterfile);
# let's cheat a bit to force porefs option to be passed to
# Locale::Po4a::Po; this is undocument use of internal
# Locale::Po4a::TransTractor's data, compulsory since this module
# prevents us from using the porefs option.
$doc->{TT}{po_out}=Locale::Po4a::Po->new({ 'porefs' => 'none' });
- $doc->{TT}{po_out}->set_charset('utf-8');
+ $doc->{TT}{po_out}->set_charset('UTF-8');
# do the actual work
$doc->parse;
IkiWiki::prep_writefile(basename($potfile),dirname($potfile));
my $page=shift;
$page=~s/^\///;
- return gettext("0") unless istranslation($page);
+ return gettext("N/A") unless istranslation($page);
my $file=srcfile($pagesources{$page});
my $masterfile = srcfile($pagesources{masterpage($page)});
- my %options = (
- "markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0,
- );
- my $doc=Locale::Po4a::Chooser::new('text',%options);
+ my $doc=Locale::Po4a::Chooser::new(po4a_type($masterfile),
+ po4a_options($masterfile));
$doc->process(
'po_in_name' => [ $file ],
'file_in_name' => [ $masterfile ],
- 'file_in_charset' => 'utf-8',
- 'file_out_charset' => 'utf-8',
+ 'file_in_charset' => 'UTF-8',
+ 'file_out_charset' => 'UTF-8',
) or error("po(percenttranslated) ".
sprintf(gettext("failed to translate %s"), $page));
my ($percent,$hit,$queries) = $doc->stats();
master => 1,
};
}
- else {
+ elsif (istranslation($otherpage)) {
push @ret, {
url => urlto_with_orig_beautiful_urlpath($otherpage, $page),
code => $lang,
return urlto('', $page);
}
+sub ishomepage ($) {
+ my $page = shift;
+
+ return 1 if $page eq 'index';
+ map { return 1 if $page eq 'index.'.$_ } keys %{$config{po_slave_languages}};
+ return undef;
+}
+
sub deletetranslations ($) {
my $deletedmasterfile=shift;
if (@todelete) {
commit_and_refresh(
- gettext("removed obsolete PO files"),
- "IkiWiki::Plugin::po::deletetranslations");
+ gettext("removed obsolete PO files"));
}
}
-sub commit_and_refresh ($$) {
- my ($msg, $author) = (shift, shift);
+sub commit_and_refresh ($) {
+ my $msg = shift;
if ($config{rcs}) {
IkiWiki::disable_commit_hook();
- IkiWiki::rcs_commit_staged($msg, $author, "127.0.0.1");
+ IkiWiki::rcs_commit_staged(
+ message => $msg,
+ );
IkiWiki::enable_commit_hook();
IkiWiki::rcs_update();
}
IkiWiki::saveindex();
}
-# on success, returns the filtered content.
-# on error, if $nonfatal, warn and return undef; else, error out.
-sub po_to_markup ($$;$) {
+sub po_to_markup ($$) {
my ($page, $content) = (shift, shift);
- my $nonfatal = shift;
$content = '' unless defined $content;
$content = decode_utf8(encode_utf8($content));
my $fail = sub ($) {
my $msg = "po(po_to_markup) - $page : " . shift;
- if ($nonfatal) {
- warn $msg;
- return undef;
- }
error($msg, sub { unlink $infile, $outfile});
};
or return $fail->(sprintf(gettext("failed to write %s"), $infile));
my $masterfile = srcfile($pagesources{masterpage($page)});
- my %options = (
- "markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0,
- );
- my $doc=Locale::Po4a::Chooser::new('text',%options);
+ my $doc=Locale::Po4a::Chooser::new(po4a_type($masterfile),
+ po4a_options($masterfile));
$doc->process(
'po_in_name' => [ $infile ],
'file_in_name' => [ $masterfile ],
- 'file_in_charset' => 'utf-8',
- 'file_out_charset' => 'utf-8',
+ 'file_in_charset' => 'UTF-8',
+ 'file_out_charset' => 'UTF-8',
) or return $fail->(gettext("failed to translate"));
$doc->write($outfile)
or return $fail->(sprintf(gettext("failed to write %s"), $outfile));
- $content = readfile($outfile)
- or return $fail->(sprintf(gettext("failed to read %s"), $outfile));
+ $content = readfile($outfile);
# Unlinking should happen automatically, thanks to File::Temp,
# but it does not work here, probably because of the way writefile()
"to previous page to continue edit"));
}
+sub po4a_type ($) {
+ my $file = shift;
+
+ my $pagetype = pagetype($file);
+ if ($pagetype eq 'html') {
+ return 'xhtml';
+ }
+ return 'text';
+}
+
+sub po4a_options($) {
+ my $file = shift;
+
+ my %options;
+ my $pagetype = pagetype($file);
+
+ if ($pagetype eq 'html') {
+ # how to disable options is not consistent across po4a modules
+ $options{includessi} = '';
+ $options{includeexternal} = 0;
+ }
+ elsif ($pagetype eq 'mdwn') {
+ $options{markdown} = 1;
+ }
+ else {
+ $options{markdown} = 0;
+ }
+
+ return %options;
+}
+
# ,----
# | PageSpecs
# `----
}
}
+sub match_needstranslation ($$;@) {
+ my $page=shift;
+ my $wanted=shift;
+
+ if (defined $wanted && $wanted ne "") {
+ if ($wanted !~ /^\d+$/) {
+ return IkiWiki::FailReason->new("parameter is not an integer");
+ }
+ elsif ($wanted > 100) {
+ return IkiWiki::FailReason->new("parameter is greater than 100");
+ }
+ }
+ else {
+ $wanted=100;
+ }
+
+ my $percenttranslated=IkiWiki::Plugin::po::percenttranslated($page);
+ if ($percenttranslated eq 'N/A') {
+ return IkiWiki::FailReason->new("file is not a translatable page");
+ }
+ elsif ($percenttranslated < $wanted) {
+ return IkiWiki::SuccessReason->new("file has $percenttranslated translated");
+ }
+ else {
+ return IkiWiki::FailReason->new("file is translated enough");
+ }
+}
+
1