2008-10-05 04:11:02 +02:00
|
|
|
#!/usr/bin/perl
|
|
|
|
# .po as a wiki page type
|
2008-11-06 13:01:33 +01:00
|
|
|
# Licensed under GPL v2 or greater
|
2009-01-02 16:54:03 +01:00
|
|
|
# Copyright (C) 2008-2009 intrigeri <intrigeri@boum.org>
|
2008-10-05 19:42:43 +02:00
|
|
|
# inspired by the GPL'd po4a-translate,
|
|
|
|
# which is Copyright 2002, 2003, 2004 by Martin Quinson (mquinson#debian.org)
|
2008-10-05 04:11:02 +02:00
|
|
|
package IkiWiki::Plugin::po;
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
2009-01-02 11:22:54 +01:00
|
|
|
use IkiWiki 3.00;
|
2008-10-05 04:11:02 +02:00
|
|
|
use Encode;
|
2009-07-19 17:50:56 +02:00
|
|
|
use Locale::Po4a::Common qw(nowrapi18n !/.*/);
|
2008-10-05 19:42:43 +02:00
|
|
|
use Locale::Po4a::Chooser;
|
2008-10-18 21:47:49 +02:00
|
|
|
use Locale::Po4a::Po;
|
2008-10-14 16:36:01 +02:00
|
|
|
use File::Basename;
|
2008-10-14 17:17:24 +02:00
|
|
|
use File::Copy;
|
2008-10-14 16:36:01 +02:00
|
|
|
use File::Spec;
|
2008-10-05 19:42:43 +02:00
|
|
|
use File::Temp;
|
2008-10-11 03:41:12 +02:00
|
|
|
use Memoize;
|
2008-11-07 21:27:00 +01:00
|
|
|
use UNIVERSAL;
|
2008-10-11 03:41:12 +02:00
|
|
|
|
|
|
|
my %translations;
|
2008-11-06 15:54:55 +01:00
|
|
|
my @origneedsbuild;
|
2008-11-11 04:05:39 +01:00
|
|
|
my %origsubs;
|
2008-11-02 18:29:23 +01:00
|
|
|
|
2008-11-12 22:32:47 +01:00
|
|
|
memoize("istranslatable");
|
2008-10-11 03:41:12 +02:00
|
|
|
memoize("_istranslation");
|
2008-10-15 02:25:34 +02:00
|
|
|
memoize("percenttranslated");
|
2008-11-02 18:29:23 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub import {
|
2008-10-05 04:11:02 +02:00
|
|
|
hook(type => "getsetup", id => "po", call => \&getsetup);
|
2008-10-10 13:57:48 +02:00
|
|
|
hook(type => "checkconfig", id => "po", call => \&checkconfig);
|
2008-10-14 15:24:58 +02:00
|
|
|
hook(type => "needsbuild", id => "po", call => \&needsbuild);
|
2009-03-29 20:31:32 +02:00
|
|
|
hook(type => "scan", id => "po", call => \&scan, last => 1);
|
2008-10-05 04:11:02 +02:00
|
|
|
hook(type => "filter", id => "po", call => \&filter);
|
|
|
|
hook(type => "htmlize", id => "po", call => \&htmlize);
|
2008-11-04 20:05:21 +01:00
|
|
|
hook(type => "pagetemplate", id => "po", call => \&pagetemplate, last => 1);
|
2009-01-01 17:49:10 +01:00
|
|
|
hook(type => "rename", id => "po", call => \&renamepages, first => 1);
|
2008-11-13 01:38:22 +01:00
|
|
|
hook(type => "delete", id => "po", call => \&mydelete);
|
2008-11-06 15:54:55 +01:00
|
|
|
hook(type => "change", id => "po", call => \&change);
|
2009-01-19 19:53:32 +01:00
|
|
|
hook(type => "checkcontent", id => "po", call => \&checkcontent);
|
2009-01-01 16:38:16 +01:00
|
|
|
hook(type => "canremove", id => "po", call => \&canremove);
|
2009-01-01 16:50:24 +01:00
|
|
|
hook(type => "canrename", id => "po", call => \&canrename);
|
2008-11-04 17:56:42 +01:00
|
|
|
hook(type => "editcontent", id => "po", call => \&editcontent);
|
2009-01-02 15:50:47 +01:00
|
|
|
hook(type => "formbuilder_setup", id => "po", call => \&formbuilder_setup, last => 1);
|
2009-01-02 13:43:40 +01:00
|
|
|
hook(type => "formbuilder", id => "po", call => \&formbuilder);
|
2008-11-05 21:09:54 +01:00
|
|
|
|
|
|
|
$origsubs{'bestlink'}=\&IkiWiki::bestlink;
|
2008-11-02 17:56:15 +01:00
|
|
|
inject(name => "IkiWiki::bestlink", call => \&mybestlink);
|
2008-11-05 21:09:54 +01:00
|
|
|
$origsubs{'beautify_urlpath'}=\&IkiWiki::beautify_urlpath;
|
2008-11-02 18:29:23 +01:00
|
|
|
inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath);
|
2008-11-05 21:09:54 +01:00
|
|
|
$origsubs{'targetpage'}=\&IkiWiki::targetpage;
|
2008-11-02 18:48:56 +01:00
|
|
|
inject(name => "IkiWiki::targetpage", call => \&mytargetpage);
|
2008-11-06 17:28:04 +01:00
|
|
|
$origsubs{'urlto'}=\&IkiWiki::urlto;
|
|
|
|
inject(name => "IkiWiki::urlto", call => \&myurlto);
|
2009-01-15 21:49:32 +01:00
|
|
|
$origsubs{'cgiurl'}=\&IkiWiki::cgiurl;
|
|
|
|
inject(name => "IkiWiki::cgiurl", call => \&mycgiurl);
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-05 04:11:02 +02:00
|
|
|
|
2008-11-11 04:05:39 +01:00
|
|
|
|
|
|
|
# ,----
|
|
|
|
# | Table of contents
|
|
|
|
# `----
|
|
|
|
|
|
|
|
# 1. Hooks
|
|
|
|
# 2. Injected functions
|
|
|
|
# 3. Blackboxes for private data
|
|
|
|
# 4. Helper functions
|
2009-01-26 19:33:02 +01:00
|
|
|
# 5. PageSpecs
|
2008-11-11 04:05:39 +01:00
|
|
|
|
|
|
|
|
|
|
|
# ,----
|
|
|
|
# | Hooks
|
|
|
|
# `----
|
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub getsetup () {
|
2008-10-05 04:11:02 +02:00
|
|
|
return
|
|
|
|
plugin => {
|
|
|
|
safe => 0,
|
2008-11-11 04:05:39 +01:00
|
|
|
rebuild => 1,
|
2008-10-05 04:11:02 +02:00
|
|
|
},
|
2008-10-05 21:34:43 +02:00
|
|
|
po_master_language => {
|
2008-10-05 04:11:02 +02:00
|
|
|
type => "string",
|
2008-10-05 21:34:43 +02:00
|
|
|
example => {
|
|
|
|
'code' => 'en',
|
|
|
|
'name' => 'English'
|
|
|
|
},
|
|
|
|
description => "master language (non-PO files)",
|
2008-11-06 13:26:45 +01:00
|
|
|
safe => 1,
|
2008-10-05 21:34:43 +02:00
|
|
|
rebuild => 1,
|
|
|
|
},
|
|
|
|
po_slave_languages => {
|
|
|
|
type => "string",
|
2008-10-13 18:21:59 +02:00
|
|
|
example => {
|
|
|
|
'fr' => 'Français',
|
|
|
|
'es' => 'Castellano',
|
|
|
|
'de' => 'Deutsch'
|
2008-10-05 04:11:02 +02:00
|
|
|
},
|
2008-10-05 21:34:43 +02:00
|
|
|
description => "slave languages (PO files)",
|
2008-11-06 13:26:45 +01:00
|
|
|
safe => 1,
|
2008-10-05 04:11:02 +02:00
|
|
|
rebuild => 1,
|
|
|
|
},
|
2008-10-10 21:47:20 +02:00
|
|
|
po_translatable_pages => {
|
|
|
|
type => "pagespec",
|
2009-07-21 09:56:34 +02:00
|
|
|
example => "* and !*/Discussion",
|
2008-10-10 21:47:20 +02:00
|
|
|
description => "PageSpec controlling which pages are translatable",
|
|
|
|
link => "ikiwiki/PageSpec",
|
2008-11-06 13:29:48 +01:00
|
|
|
safe => 1,
|
2008-10-10 21:47:20 +02:00
|
|
|
rebuild => 1,
|
|
|
|
},
|
2008-10-10 15:48:35 +02:00
|
|
|
po_link_to => {
|
|
|
|
type => "string",
|
|
|
|
example => "current",
|
|
|
|
description => "internal linking behavior (default/current/negotiated)",
|
2008-11-06 13:47:09 +01:00
|
|
|
safe => 1,
|
2008-10-10 13:57:48 +02:00
|
|
|
rebuild => 1,
|
|
|
|
},
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-10 13:57:48 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub checkconfig () {
|
2009-07-20 07:19:05 +02:00
|
|
|
foreach my $field (qw{po_master_language}) {
|
2008-10-10 13:57:48 +02:00
|
|
|
if (! exists $config{$field} || ! defined $config{$field}) {
|
2009-01-02 17:24:54 +01:00
|
|
|
error(sprintf(gettext("Must specify %s when using the %s plugin"),
|
|
|
|
$field, 'po'));
|
2008-10-10 13:57:48 +02:00
|
|
|
}
|
|
|
|
}
|
2009-07-20 07:19:05 +02:00
|
|
|
|
2008-11-06 13:26:45 +01:00
|
|
|
map {
|
|
|
|
islanguagecode($_)
|
2008-11-06 13:55:03 +01:00
|
|
|
or error(sprintf(gettext("%s is not a valid language code"), $_));
|
2008-11-06 13:26:45 +01:00
|
|
|
} ($config{po_master_language}{code}, keys %{$config{po_slave_languages}});
|
2009-07-20 07:19:05 +02:00
|
|
|
|
2008-10-10 21:47:20 +02:00
|
|
|
if (! exists $config{po_translatable_pages} ||
|
|
|
|
! defined $config{po_translatable_pages}) {
|
2008-11-05 21:18:07 +01:00
|
|
|
$config{po_translatable_pages}="";
|
2008-10-10 21:47:20 +02:00
|
|
|
}
|
2008-11-06 13:47:09 +01:00
|
|
|
if (! exists $config{po_link_to} ||
|
|
|
|
! defined $config{po_link_to}) {
|
|
|
|
$config{po_link_to}='default';
|
|
|
|
}
|
2009-03-29 20:31:32 +02:00
|
|
|
elsif ($config{po_link_to} !~ /^(default|current|negotiated)$/) {
|
2009-01-02 17:24:54 +01:00
|
|
|
warn(sprintf(gettext('%s is not a valid value for po_link_to, falling back to po_link_to=default'),
|
|
|
|
$config{po_link_to}));
|
2008-11-06 13:47:09 +01:00
|
|
|
$config{po_link_to}='default';
|
|
|
|
}
|
|
|
|
elsif ($config{po_link_to} eq "negotiated" && ! $config{usedirs}) {
|
|
|
|
warn(gettext('po_link_to=negotiated requires usedirs to be enabled, falling back to po_link_to=default'));
|
|
|
|
$config{po_link_to}='default';
|
2008-10-10 13:57:48 +02:00
|
|
|
}
|
2009-07-20 07:19:05 +02:00
|
|
|
|
2008-10-10 21:56:40 +02:00
|
|
|
push @{$config{wiki_file_prune_regexps}}, qr/\.pot$/;
|
2009-07-20 07:19:05 +02:00
|
|
|
|
po: Add support for mo files in underlays
In order to support translated basewiki and other underlays, we need
support for mo files in underlays.
The code did not allow this before, because if a mo file was in an
underlay, then it might try to update it, and its pot, and write to the
underlay, which is guaranteed to either fail due to permissions, or be
undesirable.
To fix, my approach is to just detect if a mo or pot file that is about to
be updated is in an underlay, and skip updating it. This seems to work
well:
- If the mo is out of date in the underlay, it won't get updated, but this
would probably be due to a problem in the underlay, or more likely,
the wiki is being rebuilt and so it *thinks* the mo is out of date,
but it's really not (and it would be a waste of time to rebuild it
anyway).
- If a page from the basewiki is edited, it is saved to the srcdir,
which causes generation of an updated mo and pot also in the srcdir;
the underlay stops being used for that page, and everything seems
to work.
Note that I am not including an underlay search directory for pot files.
They *seem* to be unnecessary for the underlay, since the mo files
in there never need to be updated.
2009-07-21 11:31:51 +02:00
|
|
|
# Translated versions of the underlays are added if available.
|
2009-07-21 12:38:40 +02:00
|
|
|
foreach my $underlay ("basewiki",
|
|
|
|
map { m/^\Q$config{underlaydirbase}\E\/*(.*)/ }
|
|
|
|
reverse @{$config{underlaydirs}}) {
|
po: Add support for mo files in underlays
In order to support translated basewiki and other underlays, we need
support for mo files in underlays.
The code did not allow this before, because if a mo file was in an
underlay, then it might try to update it, and its pot, and write to the
underlay, which is guaranteed to either fail due to permissions, or be
undesirable.
To fix, my approach is to just detect if a mo or pot file that is about to
be updated is in an underlay, and skip updating it. This seems to work
well:
- If the mo is out of date in the underlay, it won't get updated, but this
would probably be due to a problem in the underlay, or more likely,
the wiki is being rebuilt and so it *thinks* the mo is out of date,
but it's really not (and it would be a waste of time to rebuild it
anyway).
- If a page from the basewiki is edited, it is saved to the srcdir,
which causes generation of an updated mo and pot also in the srcdir;
the underlay stops being used for that page, and everything seems
to work.
Note that I am not including an underlay search directory for pot files.
They *seem* to be unnecessary for the underlay, since the mo files
in there never need to be updated.
2009-07-21 11:31:51 +02:00
|
|
|
next if $underlay=~/^locale\//;
|
|
|
|
|
2009-07-21 12:38:40 +02:00
|
|
|
# Underlays containing the po files for slave languages.
|
po: Add support for mo files in underlays
In order to support translated basewiki and other underlays, we need
support for mo files in underlays.
The code did not allow this before, because if a mo file was in an
underlay, then it might try to update it, and its pot, and write to the
underlay, which is guaranteed to either fail due to permissions, or be
undesirable.
To fix, my approach is to just detect if a mo or pot file that is about to
be updated is in an underlay, and skip updating it. This seems to work
well:
- If the mo is out of date in the underlay, it won't get updated, but this
would probably be due to a problem in the underlay, or more likely,
the wiki is being rebuilt and so it *thinks* the mo is out of date,
but it's really not (and it would be a waste of time to rebuild it
anyway).
- If a page from the basewiki is edited, it is saved to the srcdir,
which causes generation of an updated mo and pot also in the srcdir;
the underlay stops being used for that page, and everything seems
to work.
Note that I am not including an underlay search directory for pot files.
They *seem* to be unnecessary for the underlay, since the mo files
in there never need to be updated.
2009-07-21 11:31:51 +02:00
|
|
|
foreach my $ll (keys %{$config{po_slave_languages}}) {
|
2009-07-21 13:16:26 +02:00
|
|
|
add_underlay("po/$ll/$underlay")
|
|
|
|
if -d "$config{underlaydirbase}/po/$ll/$underlay";
|
po: Add support for mo files in underlays
In order to support translated basewiki and other underlays, we need
support for mo files in underlays.
The code did not allow this before, because if a mo file was in an
underlay, then it might try to update it, and its pot, and write to the
underlay, which is guaranteed to either fail due to permissions, or be
undesirable.
To fix, my approach is to just detect if a mo or pot file that is about to
be updated is in an underlay, and skip updating it. This seems to work
well:
- If the mo is out of date in the underlay, it won't get updated, but this
would probably be due to a problem in the underlay, or more likely,
the wiki is being rebuilt and so it *thinks* the mo is out of date,
but it's really not (and it would be a waste of time to rebuild it
anyway).
- If a page from the basewiki is edited, it is saved to the srcdir,
which causes generation of an updated mo and pot also in the srcdir;
the underlay stops being used for that page, and everything seems
to work.
Note that I am not including an underlay search directory for pot files.
They *seem* to be unnecessary for the underlay, since the mo files
in there never need to be updated.
2009-07-21 11:31:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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");
|
2009-07-20 07:19:05 +02:00
|
|
|
}
|
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-05 04:11:02 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub needsbuild () {
|
2008-10-14 15:24:58 +02:00
|
|
|
my $needsbuild=shift;
|
|
|
|
|
2008-11-06 15:54:55 +01:00
|
|
|
# backup @needsbuild content so that change() can know whether
|
|
|
|
# a given master page was rendered because its source file was changed
|
|
|
|
@origneedsbuild=(@$needsbuild);
|
2008-10-15 06:47:06 +02:00
|
|
|
|
2008-11-12 23:22:26 +01:00
|
|
|
flushmemoizecache();
|
2008-11-10 13:56:46 +01:00
|
|
|
buildtranslationscache();
|
2008-10-15 00:05:52 +02:00
|
|
|
|
|
|
|
# make existing translations depend on the corresponding master page
|
|
|
|
foreach my $master (keys %translations) {
|
2008-11-10 14:49:58 +01:00
|
|
|
map add_depends($_, $master), values %{otherlanguages($master)};
|
2008-10-15 00:05:52 +02:00
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-13 17:19:56 +02:00
|
|
|
|
2008-11-11 04:32:20 +01:00
|
|
|
# Massage the recorded state of internal links so that:
|
|
|
|
# - it matches the actually generated links, rather than the links as written
|
|
|
|
# in the pages' source
|
|
|
|
# - backlinks are consistent in all cases
|
2008-12-31 23:54:21 +01:00
|
|
|
sub scan (@) {
|
2008-11-07 21:27:00 +01:00
|
|
|
my %params=@_;
|
|
|
|
my $page=$params{page};
|
|
|
|
my $content=$params{content};
|
|
|
|
|
|
|
|
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)
|
|
|
|
for (my $i=0; $i<@{$links{$page}}; $i++) {
|
|
|
|
if (@{$links{$page}}[$i] eq $destpage) {
|
2008-11-10 20:35:53 +01:00
|
|
|
@{$links{$page}}[$i] = $destpage . '.' . lang($page);
|
2008-11-07 21:27:00 +01:00
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elsif (! istranslatable($page) && ! istranslation($page)) {
|
|
|
|
foreach my $destpage (@{$links{$page}}) {
|
|
|
|
if (istranslatable($destpage)) {
|
2008-11-11 04:32:20 +01:00
|
|
|
# make sure any destpage's translations has
|
|
|
|
# $page in its backlinks
|
|
|
|
push @{$links{$page}},
|
|
|
|
values %{otherlanguages($destpage)};
|
2008-11-07 21:27:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-07 21:27:00 +01:00
|
|
|
|
2008-11-04 17:56:42 +01:00
|
|
|
# We use filter to convert PO to the master page's format,
|
|
|
|
# since the rest of ikiwiki should not work on PO files.
|
2008-12-31 23:54:21 +01:00
|
|
|
sub filter (@) {
|
2008-10-05 04:11:02 +02:00
|
|
|
my %params = @_;
|
2008-11-05 21:18:07 +01:00
|
|
|
|
2008-10-05 19:42:43 +02:00
|
|
|
my $page = $params{page};
|
2008-10-11 03:02:43 +02:00
|
|
|
my $destpage = $params{destpage};
|
2009-01-01 21:56:36 +01:00
|
|
|
my $content = $params{content};
|
|
|
|
if (istranslation($page) && ! alreadyfiltered($page, $destpage)) {
|
|
|
|
$content = po_to_markup($page, $content);
|
|
|
|
setalreadyfiltered($page, $destpage);
|
|
|
|
}
|
2008-10-05 04:11:02 +02:00
|
|
|
return $content;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-05 04:11:02 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub htmlize (@) {
|
2008-10-05 04:11:02 +02:00
|
|
|
my %params=@_;
|
2008-11-05 21:18:07 +01:00
|
|
|
|
2008-10-05 19:56:53 +02:00
|
|
|
my $page = $params{page};
|
2008-10-05 19:42:43 +02:00
|
|
|
my $content = $params{content};
|
2008-11-12 18:03:14 +01:00
|
|
|
|
|
|
|
# ignore PO files this plugin did not create
|
|
|
|
return $content unless istranslation($page);
|
2008-10-05 19:56:53 +02:00
|
|
|
|
|
|
|
# force content to be htmlize'd as if it was the same type as the master page
|
2008-11-12 18:03:14 +01:00
|
|
|
return IkiWiki::htmlize($page, $page,
|
2009-01-26 19:33:02 +01:00
|
|
|
pagetype(srcfile($pagesources{masterpage($page)})),
|
|
|
|
$content);
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-05 04:11:02 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub pagetemplate (@) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my %params=@_;
|
|
|
|
my $page=$params{page};
|
|
|
|
my $destpage=$params{destpage};
|
|
|
|
my $template=$params{template};
|
2008-11-10 21:19:21 +01:00
|
|
|
|
2008-11-11 04:05:39 +01:00
|
|
|
my ($masterpage, $lang) = istranslation($page);
|
2008-10-13 22:07:21 +02:00
|
|
|
|
2008-10-15 02:25:34 +02:00
|
|
|
if (istranslation($page) && $template->query(name => "percenttranslated")) {
|
|
|
|
$template->param(percenttranslated => percenttranslated($page));
|
|
|
|
}
|
2008-10-19 00:05:13 +02:00
|
|
|
if ($template->query(name => "istranslation")) {
|
2009-01-26 23:21:14 +01:00
|
|
|
$template->param(istranslation => scalar istranslation($page));
|
2008-10-19 00:05:13 +02:00
|
|
|
}
|
|
|
|
if ($template->query(name => "istranslatable")) {
|
|
|
|
$template->param(istranslatable => istranslatable($page));
|
|
|
|
}
|
2008-11-11 15:27:39 +01:00
|
|
|
if ($template->query(name => "HOMEPAGEURL")) {
|
|
|
|
$template->param(homepageurl => homepageurl($page));
|
|
|
|
}
|
2008-10-13 22:07:21 +02:00
|
|
|
if ($template->query(name => "otherlanguages")) {
|
2008-11-10 14:49:58 +01:00
|
|
|
$template->param(otherlanguages => [otherlanguagesloop($page)]);
|
|
|
|
map add_depends($page, $_), (values %{otherlanguages($page)});
|
2008-10-13 22:07:21 +02:00
|
|
|
}
|
2009-06-03 18:30:00 +02:00
|
|
|
if ($config{discussion} && istranslation($page)) {
|
|
|
|
my $discussionlink=gettext("discussion");
|
|
|
|
if ($page !~ /.*\/\Q$discussionlink\E$/i &&
|
|
|
|
(length $config{cgiurl} ||
|
|
|
|
exists $links{$masterpage."/".$discussionlink})) {
|
|
|
|
$template->param('discussionlink' => htmllink(
|
|
|
|
$page,
|
|
|
|
$destpage,
|
|
|
|
$masterpage . '/' . gettext("Discussion"),
|
|
|
|
noimageinline => 1,
|
|
|
|
forcesubpage => 0,
|
|
|
|
linktext => gettext("Discussion"),
|
2009-01-26 19:33:02 +01:00
|
|
|
));
|
2009-06-03 18:30:00 +02:00
|
|
|
}
|
2008-11-03 00:52:27 +01:00
|
|
|
}
|
2008-11-10 13:00:05 +01:00
|
|
|
# Remove broken parentlink to ./index.html on home page's translations.
|
|
|
|
# It works because this hook has the "last" parameter set, to ensure it
|
|
|
|
# runs after parentlinks' own pagetemplate hook.
|
2008-11-04 20:05:21 +01:00
|
|
|
if ($template->param('parentlinks')
|
|
|
|
&& istranslation($page)
|
|
|
|
&& $masterpage eq "index") {
|
|
|
|
$template->param('parentlinks' => []);
|
|
|
|
}
|
2008-10-13 22:07:21 +02:00
|
|
|
} # }}}
|
|
|
|
|
2008-12-30 22:55:04 +01:00
|
|
|
# Add the renamed page translations to the list of to-be-renamed pages.
|
2009-03-29 20:52:29 +02:00
|
|
|
sub renamepages (@) {
|
2009-01-27 16:57:52 +01:00
|
|
|
my %params = @_;
|
2009-01-01 17:49:10 +01:00
|
|
|
|
2009-03-08 11:44:00 +01:00
|
|
|
my %torename = %{$params{torename}};
|
2009-01-27 16:57:52 +01:00
|
|
|
my $session = $params{session};
|
2008-12-30 22:55:04 +01:00
|
|
|
|
2009-01-01 17:49:10 +01:00
|
|
|
# Save the page(s) the user asked to rename, so that our
|
|
|
|
# canrename hook can tell the difference between:
|
|
|
|
# - a translation being renamed as a consequence of its master page
|
|
|
|
# being renamed
|
|
|
|
# - a user trying to directly rename a translation
|
2009-01-27 16:57:52 +01:00
|
|
|
# This is why this hook has to be run first, before the list of pages
|
|
|
|
# to rename is modified by other plugins.
|
2009-03-08 11:44:00 +01:00
|
|
|
my @orig_torename;
|
|
|
|
@orig_torename=@{$session->param("po_orig_torename")}
|
|
|
|
if defined $session->param("po_orig_torename");
|
|
|
|
push @orig_torename, $torename{src};
|
|
|
|
$session->param(po_orig_torename => \@orig_torename);
|
2009-01-01 17:49:10 +01:00
|
|
|
IkiWiki::cgi_savesession($session);
|
|
|
|
|
2009-03-08 11:44:00 +01:00
|
|
|
return () unless istranslatable($torename{src});
|
|
|
|
|
|
|
|
my @ret;
|
|
|
|
my %otherpages=%{otherlanguages($torename{src})};
|
|
|
|
while (my ($lang, $otherpage) = each %otherpages) {
|
|
|
|
push @ret, {
|
|
|
|
src => $otherpage,
|
|
|
|
srcfile => $pagesources{$otherpage},
|
|
|
|
dest => otherlanguage($torename{dest}, $lang),
|
|
|
|
destfile => $torename{dest}.".".$lang.".po",
|
|
|
|
required => 0,
|
|
|
|
};
|
2008-12-30 22:55:04 +01:00
|
|
|
}
|
2009-01-27 16:57:52 +01:00
|
|
|
return @ret;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-13 03:55:55 +01:00
|
|
|
|
2009-03-29 20:52:29 +02:00
|
|
|
sub mydelete (@) {
|
2008-11-13 01:38:22 +01:00
|
|
|
my @deleted=@_;
|
|
|
|
|
2009-01-01 00:58:06 +01:00
|
|
|
map { deletetranslations($_) } grep istranslatablefile($_), @deleted;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-13 01:38:22 +01:00
|
|
|
|
2009-03-29 20:52:29 +02:00
|
|
|
sub change (@) {
|
2008-11-06 15:54:55 +01:00
|
|
|
my @rendered=@_;
|
|
|
|
|
po(change): re-render all rendered files in one corner case
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's passes on row 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.
Signed-off-by: intrigeri <intrigeri@boum.org>
2009-01-16 01:33:07 +01:00
|
|
|
# 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.
|
|
|
|
#
|
2009-03-29 20:52:29 +02:00
|
|
|
# Then, at render time, every page passes in turn through the Great
|
po(change): re-render all rendered files in one corner case
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's passes on row 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.
Signed-off-by: intrigeri <intrigeri@boum.org>
2009-01-16 01:33:07 +01:00
|
|
|
# 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.
|
|
|
|
#
|
2009-03-29 20:52:29 +02:00
|
|
|
# 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.
|
po(change): re-render all rendered files in one corner case
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's passes on row 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.
Signed-off-by: intrigeri <intrigeri@boum.org>
2009-01-16 01:33:07 +01:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
2009-01-26 19:17:14 +01:00
|
|
|
if (@rendered
|
po(change): re-render all rendered files in one corner case
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's passes on row 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.
Signed-off-by: intrigeri <intrigeri@boum.org>
2009-01-16 01:33:07 +01:00
|
|
|
&& 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}) {
|
2009-07-23 00:53:23 +02:00
|
|
|
debug(sprintf(gettext("rebuilding all pages to fix meta titles")));
|
po(change): re-render all rendered files in one corner case
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's passes on row 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.
Signed-off-by: intrigeri <intrigeri@boum.org>
2009-01-16 01:33:07 +01:00
|
|
|
resetalreadyfiltered();
|
|
|
|
require IkiWiki::Render;
|
|
|
|
foreach my $file (@rendered) {
|
2009-07-23 00:53:23 +02:00
|
|
|
debug(sprintf(gettext("building %s"), $file));
|
po(change): re-render all rendered files in one corner case
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's passes on row 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.
Signed-off-by: intrigeri <intrigeri@boum.org>
2009-01-16 01:33:07 +01:00
|
|
|
IkiWiki::render($file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-06 15:54:55 +01:00
|
|
|
my $updated_po_files=0;
|
|
|
|
|
|
|
|
# Refresh/create POT and PO files as needed.
|
po: Add support for mo files in underlays
In order to support translated basewiki and other underlays, we need
support for mo files in underlays.
The code did not allow this before, because if a mo file was in an
underlay, then it might try to update it, and its pot, and write to the
underlay, which is guaranteed to either fail due to permissions, or be
undesirable.
To fix, my approach is to just detect if a mo or pot file that is about to
be updated is in an underlay, and skip updating it. This seems to work
well:
- If the mo is out of date in the underlay, it won't get updated, but this
would probably be due to a problem in the underlay, or more likely,
the wiki is being rebuilt and so it *thinks* the mo is out of date,
but it's really not (and it would be a waste of time to rebuild it
anyway).
- If a page from the basewiki is edited, it is saved to the srcdir,
which causes generation of an updated mo and pot also in the srcdir;
the underlay stops being used for that page, and everything seems
to work.
Note that I am not including an underlay search directory for pot files.
They *seem* to be unnecessary for the underlay, since the mo files
in there never need to be updated.
2009-07-21 11:31:51 +02:00
|
|
|
# (But avoid doing so if they are in an underlay directory.)
|
2009-01-01 00:58:06 +01:00
|
|
|
foreach my $file (grep {istranslatablefile($_)} @rendered) {
|
2008-11-13 01:07:52 +01:00
|
|
|
my $masterfile=srcfile($file);
|
po: Add support for mo files in underlays
In order to support translated basewiki and other underlays, we need
support for mo files in underlays.
The code did not allow this before, because if a mo file was in an
underlay, then it might try to update it, and its pot, and write to the
underlay, which is guaranteed to either fail due to permissions, or be
undesirable.
To fix, my approach is to just detect if a mo or pot file that is about to
be updated is in an underlay, and skip updating it. This seems to work
well:
- If the mo is out of date in the underlay, it won't get updated, but this
would probably be due to a problem in the underlay, or more likely,
the wiki is being rebuilt and so it *thinks* the mo is out of date,
but it's really not (and it would be a waste of time to rebuild it
anyway).
- If a page from the basewiki is edited, it is saved to the srcdir,
which causes generation of an updated mo and pot also in the srcdir;
the underlay stops being used for that page, and everything seems
to work.
Note that I am not including an underlay search directory for pot files.
They *seem* to be unnecessary for the underlay, since the mo files
in there never need to be updated.
2009-07-21 11:31:51 +02:00
|
|
|
my $page=pagename($file);
|
2008-11-06 15:54:55 +01:00
|
|
|
my $updated_pot_file=0;
|
po: Add support for mo files in underlays
In order to support translated basewiki and other underlays, we need
support for mo files in underlays.
The code did not allow this before, because if a mo file was in an
underlay, then it might try to update it, and its pot, and write to the
underlay, which is guaranteed to either fail due to permissions, or be
undesirable.
To fix, my approach is to just detect if a mo or pot file that is about to
be updated is in an underlay, and skip updating it. This seems to work
well:
- If the mo is out of date in the underlay, it won't get updated, but this
would probably be due to a problem in the underlay, or more likely,
the wiki is being rebuilt and so it *thinks* the mo is out of date,
but it's really not (and it would be a waste of time to rebuild it
anyway).
- If a page from the basewiki is edited, it is saved to the srcdir,
which causes generation of an updated mo and pot also in the srcdir;
the underlay stops being used for that page, and everything seems
to work.
Note that I am not including an underlay search directory for pot files.
They *seem* to be unnecessary for the underlay, since the mo files
in there never need to be updated.
2009-07-21 11:31:51 +02:00
|
|
|
# Only refresh POT file if it does not exist, or if
|
2008-11-10 13:00:05 +01:00
|
|
|
# $pagesources{$page} was changed: don't if only the HTML was
|
|
|
|
# refreshed, e.g. because of a dependency.
|
po: Add support for mo files in underlays
In order to support translated basewiki and other underlays, we need
support for mo files in underlays.
The code did not allow this before, because if a mo file was in an
underlay, then it might try to update it, and its pot, and write to the
underlay, which is guaranteed to either fail due to permissions, or be
undesirable.
To fix, my approach is to just detect if a mo or pot file that is about to
be updated is in an underlay, and skip updating it. This seems to work
well:
- If the mo is out of date in the underlay, it won't get updated, but this
would probably be due to a problem in the underlay, or more likely,
the wiki is being rebuilt and so it *thinks* the mo is out of date,
but it's really not (and it would be a waste of time to rebuild it
anyway).
- If a page from the basewiki is edited, it is saved to the srcdir,
which causes generation of an updated mo and pot also in the srcdir;
the underlay stops being used for that page, and everything seems
to work.
Note that I am not including an underlay search directory for pot files.
They *seem* to be unnecessary for the underlay, since the mo files
in there never need to be updated.
2009-07-21 11:31:51 +02:00
|
|
|
if ($masterfile eq "$config{srcdir}/$file" &&
|
|
|
|
((grep { $_ eq $pagesources{$page} } @origneedsbuild)
|
|
|
|
|| ! -e potfile($masterfile))) {
|
2008-11-13 01:07:52 +01:00
|
|
|
refreshpot($masterfile);
|
2008-11-06 15:54:55 +01:00
|
|
|
$updated_pot_file=1;
|
|
|
|
}
|
|
|
|
my @pofiles;
|
po: Add support for mo files in underlays
In order to support translated basewiki and other underlays, we need
support for mo files in underlays.
The code did not allow this before, because if a mo file was in an
underlay, then it might try to update it, and its pot, and write to the
underlay, which is guaranteed to either fail due to permissions, or be
undesirable.
To fix, my approach is to just detect if a mo or pot file that is about to
be updated is in an underlay, and skip updating it. This seems to work
well:
- If the mo is out of date in the underlay, it won't get updated, but this
would probably be due to a problem in the underlay, or more likely,
the wiki is being rebuilt and so it *thinks* the mo is out of date,
but it's really not (and it would be a waste of time to rebuild it
anyway).
- If a page from the basewiki is edited, it is saved to the srcdir,
which causes generation of an updated mo and pot also in the srcdir;
the underlay stops being used for that page, and everything seems
to work.
Note that I am not including an underlay search directory for pot files.
They *seem* to be unnecessary for the underlay, since the mo files
in there never need to be updated.
2009-07-21 11:31:51 +02:00
|
|
|
foreach my $po (pofiles($masterfile)) {
|
|
|
|
next if ! $updated_pot_file && ! -e $po;
|
|
|
|
next if grep { $po=~/\Q$_\E/ } @{$config{underlaydirs}};
|
|
|
|
push @pofiles, $po;
|
|
|
|
}
|
2008-11-06 15:54:55 +01:00
|
|
|
if (@pofiles) {
|
2008-11-13 01:07:52 +01:00
|
|
|
refreshpofiles($masterfile, @pofiles);
|
2009-01-01 00:58:06 +01:00
|
|
|
map { IkiWiki::rcs_add($_) } @pofiles if $config{rcs};
|
2008-11-06 15:54:55 +01:00
|
|
|
$updated_po_files=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($updated_po_files) {
|
2008-12-31 00:38:47 +01:00
|
|
|
commit_and_refresh(
|
|
|
|
gettext("updated PO files"),
|
|
|
|
"IkiWiki::Plugin::po::change");
|
2008-11-06 15:54:55 +01:00
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-06 15:54:55 +01:00
|
|
|
|
2009-01-19 19:53:32 +01:00
|
|
|
sub checkcontent (@) {
|
|
|
|
my %params=@_;
|
2009-01-01 19:48:48 +01:00
|
|
|
|
2009-01-19 19:53:32 +01:00
|
|
|
if (istranslation($params{page})) {
|
|
|
|
my $res = isvalidpo($params{content});
|
2009-01-01 23:10:16 +01:00
|
|
|
if ($res) {
|
2009-01-01 22:16:43 +01:00
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
else {
|
2009-01-01 23:10:16 +01:00
|
|
|
return "$res";
|
2009-01-01 22:16:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return undef;
|
2009-01-01 19:48:48 +01:00
|
|
|
}
|
|
|
|
|
2009-01-26 23:07:19 +01:00
|
|
|
sub canremove (@) {
|
|
|
|
my %params = @_;
|
2009-01-01 16:38:16 +01:00
|
|
|
|
2009-01-26 23:07:19 +01:00
|
|
|
if (istranslation($params{page})) {
|
2009-07-23 00:50:42 +02:00
|
|
|
return gettext("Can not remove a translation. If the master page is removed, ".
|
|
|
|
"however, its translations will be removed as well.");
|
2009-01-01 16:38:16 +01:00
|
|
|
}
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
|
2009-01-26 23:02:31 +01:00
|
|
|
sub canrename (@) {
|
2009-01-01 18:04:37 +01:00
|
|
|
my %params = @_;
|
2009-01-26 23:02:31 +01:00
|
|
|
my $session = $params{session};
|
2009-01-01 16:50:24 +01:00
|
|
|
|
2009-01-01 18:04:37 +01:00
|
|
|
if (istranslation($params{src})) {
|
|
|
|
my $masterpage = masterpage($params{src});
|
2009-01-01 17:49:10 +01:00
|
|
|
# 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");
|
2009-03-08 11:44:00 +01:00
|
|
|
unless (grep { $_ eq $masterpage } @{$orig_torename}) {
|
2009-07-23 00:50:42 +02:00
|
|
|
return gettext("Can not rename a translation. If the master page is renamed, ".
|
|
|
|
"however, its translations will be renamed as well.");
|
2009-01-01 17:49:10 +01:00
|
|
|
}
|
2009-01-01 16:50:24 +01:00
|
|
|
}
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
|
2008-11-11 14:11:34 +01:00
|
|
|
# As we're previewing or saving a page, the content may have
|
|
|
|
# changed, so tell the next filter() invocation it must not be lazy.
|
2008-12-31 23:54:21 +01:00
|
|
|
sub editcontent () {
|
2008-11-04 17:56:42 +01:00
|
|
|
my %params=@_;
|
2008-11-11 14:11:34 +01:00
|
|
|
|
2008-11-10 13:49:14 +01:00
|
|
|
unsetalreadyfiltered($params{page}, $params{page});
|
2008-11-04 17:56:42 +01:00
|
|
|
return $params{content};
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-04 17:56:42 +01:00
|
|
|
|
2009-01-02 12:15:21 +01:00
|
|
|
sub formbuilder_setup (@) {
|
|
|
|
my %params=@_;
|
|
|
|
my $form=$params{form};
|
|
|
|
my $q=$params{cgi};
|
|
|
|
|
2009-01-02 15:50:47 +01:00
|
|
|
return unless defined $form->field("do");
|
2009-01-02 12:15:21 +01:00
|
|
|
|
2009-01-02 15:50:47 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 12:15:21 +01:00
|
|
|
}
|
|
|
|
|
2009-01-02 13:43:40 +01:00
|
|
|
sub formbuilder (@) {
|
|
|
|
my %params=@_;
|
|
|
|
my $form=$params{form};
|
|
|
|
my $q=$params{cgi};
|
|
|
|
|
2009-01-02 17:51:17 +01:00
|
|
|
return unless defined $form->field("do");
|
2009-01-02 13:43:40 +01:00
|
|
|
|
2009-01-02 17:51:17 +01:00
|
|
|
# Do not allow to create pages of type po: they are automatically created.
|
|
|
|
# The main reason to do so is to bypass the "favor the type of linking page
|
|
|
|
# on page creation" logic, which is unsuitable when a broken link is clicked
|
|
|
|
# on a slave (PO) page.
|
|
|
|
# This cannot be done in the formbuilder_setup hook as the list of types is
|
|
|
|
# computed later.
|
|
|
|
if ($form->field("do") eq "create") {
|
2009-01-26 19:15:29 +01:00
|
|
|
foreach my $field ($form->field) {
|
2009-01-02 17:51:17 +01:00
|
|
|
next unless "$field" eq "type";
|
|
|
|
if ($field->type eq 'select') {
|
|
|
|
# remove po from the list of types
|
|
|
|
my @types = grep { $_ ne 'po' } $field->options;
|
2009-01-26 19:17:14 +01:00
|
|
|
$field->options(\@types) if @types;
|
2009-01-02 17:51:17 +01:00
|
|
|
}
|
2009-01-02 13:43:40 +01:00
|
|
|
}
|
2009-01-02 17:51:17 +01:00
|
|
|
}
|
2009-01-02 13:43:40 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
|
|
|
# ,----
|
|
|
|
# | Injected functions
|
|
|
|
# `----
|
|
|
|
|
2008-11-11 22:26:01 +01:00
|
|
|
# Implement po_link_to 'current' and 'negotiated' settings.
|
2008-12-31 23:54:21 +01:00
|
|
|
sub mybestlink ($$) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $page=shift;
|
|
|
|
my $link=shift;
|
|
|
|
|
2008-11-12 15:04:50 +01:00
|
|
|
my $res=$origsubs{'bestlink'}->(masterpage($page), $link);
|
2008-11-11 14:11:34 +01:00
|
|
|
if (length $res
|
2008-11-11 22:26:01 +01:00
|
|
|
&& ($config{po_link_to} eq "current" || $config{po_link_to} eq "negotiated")
|
2008-11-12 17:27:53 +01:00
|
|
|
&& istranslatable($res)
|
2008-11-11 14:11:34 +01:00
|
|
|
&& istranslation($page)) {
|
|
|
|
return $res . "." . lang($page);
|
2008-11-11 04:05:39 +01:00
|
|
|
}
|
2008-11-11 14:11:34 +01:00
|
|
|
return $res;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub mybeautify_urlpath ($) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $url=shift;
|
|
|
|
|
|
|
|
my $res=$origsubs{'beautify_urlpath'}->($url);
|
|
|
|
if ($config{po_link_to} eq "negotiated") {
|
|
|
|
$res =~ s!/\Qindex.$config{po_master_language}{code}.$config{htmlext}\E$!/!;
|
2008-11-11 18:42:14 +01:00
|
|
|
$res =~ s!/\Qindex.$config{htmlext}\E$!/!;
|
2008-11-11 22:26:01 +01:00
|
|
|
map {
|
|
|
|
$res =~ s!/\Qindex.$_.$config{htmlext}\E$!/!;
|
|
|
|
} (keys %{$config{po_slave_languages}});
|
2008-11-11 04:05:39 +01:00
|
|
|
}
|
|
|
|
return $res;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub mytargetpage ($$) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $page=shift;
|
|
|
|
my $ext=shift;
|
|
|
|
|
2008-11-11 14:11:34 +01:00
|
|
|
if (istranslation($page) || istranslatable($page)) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my ($masterpage, $lang) = (masterpage($page), lang($page));
|
|
|
|
if (! $config{usedirs} || $masterpage eq 'index') {
|
|
|
|
return $masterpage . "." . $lang . "." . $ext;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return $masterpage . "/index." . $lang . "." . $ext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $origsubs{'targetpage'}->($page, $ext);
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub myurlto ($$;$) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $to=shift;
|
|
|
|
my $from=shift;
|
|
|
|
my $absolute=shift;
|
|
|
|
|
|
|
|
# workaround hard-coded /index.$config{htmlext} in IkiWiki::urlto()
|
|
|
|
if (! length $to
|
|
|
|
&& $config{po_link_to} eq "current"
|
|
|
|
&& istranslatable('index')) {
|
|
|
|
return IkiWiki::beautify_urlpath(IkiWiki::baseurl($from) . "index." . lang($from) . ".$config{htmlext}");
|
|
|
|
}
|
2008-12-31 13:02:48 +01:00
|
|
|
# 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);
|
2009-01-01 01:14:06 +01:00
|
|
|
my $run_by_editpage = 0;
|
|
|
|
$run_by_editpage = 1 if (exists $caller[3] && defined $caller[3]
|
|
|
|
&& $caller[3] eq "IkiWiki::cgi_editpage");
|
2008-12-31 13:02:48 +01:00
|
|
|
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)
|
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2009-01-15 21:49:32 +01:00
|
|
|
sub mycgiurl (@) {
|
|
|
|
my %params=@_;
|
|
|
|
|
|
|
|
# slave pages have no subpages
|
|
|
|
if (istranslation($params{'from'})) {
|
|
|
|
$params{'from'} = masterpage($params{'from'});
|
|
|
|
}
|
|
|
|
return $origsubs{'cgiurl'}->(%params);
|
|
|
|
}
|
|
|
|
|
2008-11-11 04:05:39 +01:00
|
|
|
# ,----
|
|
|
|
# | Blackboxes for private data
|
|
|
|
# `----
|
|
|
|
|
|
|
|
{
|
|
|
|
my %filtered;
|
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub alreadyfiltered($$) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $page=shift;
|
|
|
|
my $destpage=shift;
|
|
|
|
|
2009-01-26 19:28:57 +01:00
|
|
|
return exists $filtered{$page}{$destpage}
|
|
|
|
&& $filtered{$page}{$destpage} eq 1;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub setalreadyfiltered($$) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $page=shift;
|
|
|
|
my $destpage=shift;
|
|
|
|
|
|
|
|
$filtered{$page}{$destpage}=1;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub unsetalreadyfiltered($$) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $page=shift;
|
|
|
|
my $destpage=shift;
|
|
|
|
|
|
|
|
if (exists $filtered{$page}{$destpage}) {
|
|
|
|
delete $filtered{$page}{$destpage};
|
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub resetalreadyfiltered() {
|
2008-11-11 04:05:39 +01:00
|
|
|
undef %filtered;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
# ,----
|
|
|
|
# | Helper functions
|
|
|
|
# `----
|
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub maybe_add_leading_slash ($;$) {
|
2008-11-12 17:27:53 +01:00
|
|
|
my $str=shift;
|
|
|
|
my $add=shift;
|
|
|
|
$add=1 unless defined $add;
|
|
|
|
return '/' . $str if $add;
|
|
|
|
return $str;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-12 17:27:53 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub istranslatablefile ($) {
|
2008-11-13 00:56:23 +01:00
|
|
|
my $file=shift;
|
2008-10-05 17:14:30 +02:00
|
|
|
|
2008-11-11 14:11:34 +01:00
|
|
|
return 0 unless defined $file;
|
2009-07-19 13:46:10 +02:00
|
|
|
my $type=pagetype($file);
|
|
|
|
return 0 if ! defined $type || $type eq 'po';
|
2008-11-11 14:11:34 +01:00
|
|
|
return 0 if $file =~ /\.pot$/;
|
2008-11-13 00:56:23 +01:00
|
|
|
return 1 if pagespec_match(pagename($file), $config{po_translatable_pages});
|
|
|
|
return;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-13 00:56:23 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub istranslatable ($) {
|
2008-11-13 00:56:23 +01:00
|
|
|
my $page=shift;
|
|
|
|
|
|
|
|
$page=~s#^/##;
|
|
|
|
return 1 if istranslatablefile($pagesources{$page});
|
2008-11-12 22:32:47 +01:00
|
|
|
return;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-10 21:47:20 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub _istranslation ($) {
|
2008-10-10 21:47:20 +02:00
|
|
|
my $page=shift;
|
2008-11-05 21:18:07 +01:00
|
|
|
|
2009-01-26 19:24:33 +01:00
|
|
|
$page='' unless defined $page && length $page;
|
2008-11-12 17:27:53 +01:00
|
|
|
my $hasleadingslash = ($page=~s#^/##);
|
2008-10-10 21:47:20 +02:00
|
|
|
my $file=$pagesources{$page};
|
2009-01-26 19:24:33 +01:00
|
|
|
return 0 unless defined $file
|
2008-11-11 14:11:34 +01:00
|
|
|
&& defined pagetype($file)
|
2009-01-26 19:24:33 +01:00
|
|
|
&& pagetype($file) eq 'po';
|
2008-11-11 14:11:34 +01:00
|
|
|
return 0 if $file =~ /\.pot$/;
|
2008-10-05 17:14:30 +02:00
|
|
|
|
|
|
|
my ($masterpage, $lang) = ($page =~ /(.*)[.]([a-z]{2})$/);
|
2009-01-26 19:24:33 +01:00
|
|
|
return 0 unless defined $masterpage && defined $lang
|
2008-11-11 14:11:34 +01:00
|
|
|
&& length $masterpage && length $lang
|
|
|
|
&& defined $pagesources{$masterpage}
|
2009-01-26 19:24:33 +01:00
|
|
|
&& defined $config{po_slave_languages}{$lang};
|
2008-10-05 17:14:30 +02:00
|
|
|
|
2008-11-12 17:52:00 +01:00
|
|
|
return (maybe_add_leading_slash($masterpage, $hasleadingslash), $lang)
|
|
|
|
if istranslatable($masterpage);
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-10 17:10:40 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub istranslation ($) {
|
2008-10-11 03:41:12 +02:00
|
|
|
my $page=shift;
|
2008-11-05 21:18:07 +01:00
|
|
|
|
2008-11-10 20:35:53 +01:00
|
|
|
if (1 < (my ($masterpage, $lang) = _istranslation($page))) {
|
2008-11-12 17:27:53 +01:00
|
|
|
my $hasleadingslash = ($masterpage=~s#^/##);
|
2008-10-11 03:41:12 +02:00
|
|
|
$translations{$masterpage}{$lang}=$page unless exists $translations{$masterpage}{$lang};
|
2008-11-12 22:32:47 +01:00
|
|
|
return (maybe_add_leading_slash($masterpage, $hasleadingslash), $lang);
|
2008-11-10 20:35:53 +01:00
|
|
|
}
|
2009-01-26 19:21:33 +01:00
|
|
|
return "";
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-10 20:35:53 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub masterpage ($) {
|
2008-11-10 20:35:53 +01:00
|
|
|
my $page=shift;
|
|
|
|
|
|
|
|
if ( 1 < (my ($masterpage, $lang) = _istranslation($page))) {
|
|
|
|
return $masterpage;
|
|
|
|
}
|
|
|
|
return $page;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-10 20:35:53 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub lang ($) {
|
2008-11-10 20:35:53 +01:00
|
|
|
my $page=shift;
|
|
|
|
|
|
|
|
if (1 < (my ($masterpage, $lang) = _istranslation($page))) {
|
|
|
|
return $lang;
|
2008-10-11 03:41:12 +02:00
|
|
|
}
|
2008-11-10 20:35:53 +01:00
|
|
|
return $config{po_master_language}{code};
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-11 03:41:12 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub islanguagecode ($) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $code=shift;
|
2008-11-11 14:11:34 +01:00
|
|
|
|
2009-01-26 19:28:57 +01:00
|
|
|
return $code =~ /^[a-z]{2}$/;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub otherlanguage ($$) {
|
2008-11-12 23:22:26 +01:00
|
|
|
my $page=shift;
|
|
|
|
my $code=shift;
|
|
|
|
|
|
|
|
return masterpage($page) if $code eq $config{po_master_language}{code};
|
|
|
|
return masterpage($page) . '.' . $code;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-12 23:22:26 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub otherlanguages ($) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $page=shift;
|
|
|
|
|
|
|
|
my %ret;
|
2009-01-26 19:24:33 +01:00
|
|
|
return \%ret unless istranslation($page) || istranslatable($page);
|
2008-11-12 23:22:26 +01:00
|
|
|
my $curlang=lang($page);
|
|
|
|
foreach my $lang
|
|
|
|
($config{po_master_language}{code}, keys %{$config{po_slave_languages}}) {
|
|
|
|
next if $lang eq $curlang;
|
|
|
|
$ret{$lang}=otherlanguage($page, $lang);
|
2008-11-11 04:05:39 +01:00
|
|
|
}
|
|
|
|
return \%ret;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub potfile ($) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $masterfile=shift;
|
|
|
|
|
|
|
|
(my $name, my $dir, my $suffix) = fileparse($masterfile, qr/\.[^.]*/);
|
|
|
|
$dir='' if $dir eq './';
|
|
|
|
return File::Spec->catpath('', $dir, $name . ".pot");
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub pofile ($$) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $masterfile=shift;
|
|
|
|
my $lang=shift;
|
|
|
|
|
|
|
|
(my $name, my $dir, my $suffix) = fileparse($masterfile, qr/\.[^.]*/);
|
|
|
|
$dir='' if $dir eq './';
|
|
|
|
return File::Spec->catpath('', $dir, $name . "." . $lang . ".po");
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub pofiles ($) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $masterfile=shift;
|
2008-11-11 14:11:34 +01:00
|
|
|
|
2008-11-11 04:05:39 +01:00
|
|
|
return map pofile($masterfile, $_), (keys %{$config{po_slave_languages}});
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub refreshpot ($) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $masterfile=shift;
|
|
|
|
|
|
|
|
my $potfile=potfile($masterfile);
|
|
|
|
my %options = ("markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0);
|
|
|
|
my $doc=Locale::Po4a::Chooser::new('text',%options);
|
|
|
|
$doc->{TT}{utf_mode} = 1;
|
|
|
|
$doc->{TT}{file_in_charset} = 'utf-8';
|
|
|
|
$doc->{TT}{file_out_charset} = 'utf-8';
|
|
|
|
$doc->read($masterfile);
|
2009-03-29 21:48:26 +02:00
|
|
|
# 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.
|
2009-01-01 00:58:06 +01:00
|
|
|
$doc->{TT}{po_out}=Locale::Po4a::Po->new({ 'porefs' => 'none' });
|
2008-11-11 04:05:39 +01:00
|
|
|
$doc->{TT}{po_out}->set_charset('utf-8');
|
|
|
|
# do the actual work
|
|
|
|
$doc->parse;
|
|
|
|
IkiWiki::prep_writefile(basename($potfile),dirname($potfile));
|
|
|
|
$doc->writepo($potfile);
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub refreshpofiles ($@) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $masterfile=shift;
|
|
|
|
my @pofiles=@_;
|
|
|
|
|
|
|
|
my $potfile=potfile($masterfile);
|
2009-01-26 19:10:37 +01:00
|
|
|
if (! -e $potfile) {
|
|
|
|
error("po(refreshpofiles) ".sprintf(gettext("POT file (%s) does not exist"), $potfile));
|
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
|
|
|
foreach my $pofile (@pofiles) {
|
|
|
|
IkiWiki::prep_writefile(basename($pofile),dirname($pofile));
|
2009-08-10 21:59:32 +02:00
|
|
|
|
|
|
|
if (! -e $pofile) {
|
|
|
|
# If the po file exists in an underlay, copy it
|
|
|
|
# from there.
|
|
|
|
my ($pobase)=$pofile=~/^\Q$config{srcdir}\E\/?(.*)$/;
|
|
|
|
foreach my $dir (@{$config{underlaydirs}}) {
|
|
|
|
if (-e "$dir/$pobase") {
|
|
|
|
File::Copy::syscopy("$dir/$pobase",$pofile)
|
|
|
|
or error("po(refreshpofiles) ".
|
|
|
|
sprintf(gettext("failed to copy underlay PO file to %s"),
|
|
|
|
$pofile));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-11 04:05:39 +01:00
|
|
|
if (-e $pofile) {
|
2009-07-22 17:48:49 +02:00
|
|
|
system("msgmerge", "--previous", "-q", "-U", "--backup=none", $pofile, $potfile) == 0
|
2009-01-02 17:24:54 +01:00
|
|
|
or error("po(refreshpofiles) ".
|
|
|
|
sprintf(gettext("failed to update %s"),
|
2009-01-02 15:00:34 +01:00
|
|
|
$pofile));
|
2008-11-11 04:05:39 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
File::Copy::syscopy($potfile,$pofile)
|
2009-01-02 17:24:54 +01:00
|
|
|
or error("po(refreshpofiles) ".
|
|
|
|
sprintf(gettext("failed to copy the POT file to %s"),
|
2009-01-02 15:00:34 +01:00
|
|
|
$pofile));
|
2008-11-11 04:05:39 +01:00
|
|
|
}
|
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub buildtranslationscache() {
|
2008-11-11 04:05:39 +01:00
|
|
|
# use istranslation's side-effect
|
|
|
|
map istranslation($_), (keys %pagesources);
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub resettranslationscache() {
|
2008-11-11 04:05:39 +01:00
|
|
|
undef %translations;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub flushmemoizecache() {
|
2008-11-12 22:32:47 +01:00
|
|
|
Memoize::flush_cache("istranslatable");
|
2008-11-12 21:15:33 +01:00
|
|
|
Memoize::flush_cache("_istranslation");
|
|
|
|
Memoize::flush_cache("percenttranslated");
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-12 21:15:33 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub urlto_with_orig_beautiful_urlpath($$) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $to=shift;
|
|
|
|
my $from=shift;
|
|
|
|
|
|
|
|
inject(name => "IkiWiki::beautify_urlpath", call => $origsubs{'beautify_urlpath'});
|
|
|
|
my $res=urlto($to, $from);
|
|
|
|
inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath);
|
|
|
|
|
|
|
|
return $res;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub percenttranslated ($) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $page=shift;
|
|
|
|
|
2008-12-31 16:31:18 +01:00
|
|
|
$page=~s/^\///;
|
2008-11-11 04:05:39 +01:00
|
|
|
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);
|
|
|
|
$doc->process(
|
2009-01-01 00:58:06 +01:00
|
|
|
'po_in_name' => [ $file ],
|
|
|
|
'file_in_name' => [ $masterfile ],
|
2008-11-11 04:05:39 +01:00
|
|
|
'file_in_charset' => 'utf-8',
|
|
|
|
'file_out_charset' => 'utf-8',
|
2009-01-02 17:24:54 +01:00
|
|
|
) or error("po(percenttranslated) ".
|
|
|
|
sprintf(gettext("failed to translate %s"), $page));
|
2008-11-11 04:05:39 +01:00
|
|
|
my ($percent,$hit,$queries) = $doc->stats();
|
2009-01-02 12:35:46 +01:00
|
|
|
$percent =~ s/\.[0-9]+$//;
|
2008-11-11 04:05:39 +01:00
|
|
|
return $percent;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub languagename ($) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $code=shift;
|
|
|
|
|
|
|
|
return $config{po_master_language}{name}
|
|
|
|
if $code eq $config{po_master_language}{code};
|
|
|
|
return $config{po_slave_languages}{$code}
|
|
|
|
if defined $config{po_slave_languages}{$code};
|
|
|
|
return;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub otherlanguagesloop ($) {
|
2008-11-11 04:05:39 +01:00
|
|
|
my $page=shift;
|
|
|
|
|
|
|
|
my @ret;
|
|
|
|
my %otherpages=%{otherlanguages($page)};
|
|
|
|
while (my ($lang, $otherpage) = each %otherpages) {
|
|
|
|
if (istranslation($page) && masterpage($page) eq $otherpage) {
|
|
|
|
push @ret, {
|
|
|
|
url => urlto_with_orig_beautiful_urlpath($otherpage, $page),
|
|
|
|
code => $lang,
|
|
|
|
language => languagename($lang),
|
|
|
|
master => 1,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
push @ret, {
|
2008-11-11 22:26:01 +01:00
|
|
|
url => urlto_with_orig_beautiful_urlpath($otherpage, $page),
|
2008-11-11 04:05:39 +01:00
|
|
|
code => $lang,
|
|
|
|
language => languagename($lang),
|
|
|
|
percent => percenttranslated($otherpage),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sort {
|
2009-07-20 06:23:33 +02:00
|
|
|
return -1 if $a->{code} eq $config{po_master_language}{code};
|
|
|
|
return 1 if $b->{code} eq $config{po_master_language}{code};
|
|
|
|
return $a->{language} cmp $b->{language};
|
|
|
|
} @ret;
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub homepageurl (;$) {
|
2008-11-11 15:27:39 +01:00
|
|
|
my $page=shift;
|
|
|
|
|
|
|
|
return urlto('', $page);
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-11 04:05:39 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub deletetranslations ($) {
|
2008-11-13 03:55:55 +01:00
|
|
|
my $deletedmasterfile=shift;
|
|
|
|
|
2008-12-31 00:38:47 +01:00
|
|
|
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}};
|
|
|
|
|
|
|
|
map {
|
|
|
|
if ($config{rcs}) {
|
|
|
|
IkiWiki::rcs_remove($_);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
IkiWiki::prune("$config{srcdir}/$_");
|
|
|
|
}
|
|
|
|
} @todelete;
|
|
|
|
|
2009-01-26 19:17:14 +01:00
|
|
|
if (@todelete) {
|
2008-12-31 00:38:47 +01:00
|
|
|
commit_and_refresh(
|
|
|
|
gettext("removed obsolete PO files"),
|
|
|
|
"IkiWiki::Plugin::po::deletetranslations");
|
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-12-31 00:38:47 +01:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub commit_and_refresh ($$) {
|
2008-12-31 00:38:47 +01:00
|
|
|
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();
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-11-13 03:55:55 +01:00
|
|
|
|
2009-01-01 21:56:36 +01:00
|
|
|
# on success, returns the filtered content.
|
|
|
|
# on error, if $nonfatal, warn and return undef; else, error out.
|
|
|
|
sub po_to_markup ($$;$) {
|
|
|
|
my ($page, $content) = (shift, shift);
|
|
|
|
my $nonfatal = shift;
|
|
|
|
|
|
|
|
$content = '' unless defined $content;
|
|
|
|
$content = decode_utf8(encode_utf8($content));
|
|
|
|
# CRLF line terminators make poor Locale::Po4a feel bad
|
|
|
|
$content=~s/\r\n/\n/g;
|
|
|
|
|
|
|
|
# There are incompatibilities between some File::Temp versions
|
|
|
|
# (including 0.18, bundled with Lenny's perl-modules package)
|
|
|
|
# and others (e.g. 0.20, previously present in the archive as
|
|
|
|
# a standalone package): under certain circumstances, some
|
|
|
|
# return a relative filename, whereas others return an absolute one;
|
|
|
|
# we here use this module in a way that is at least compatible
|
|
|
|
# with 0.18 and 0.20. Beware, hit'n'run refactorers!
|
|
|
|
my $infile = new File::Temp(TEMPLATE => "ikiwiki-po-filter-in.XXXXXXXXXX",
|
|
|
|
DIR => File::Spec->tmpdir,
|
|
|
|
UNLINK => 1)->filename;
|
|
|
|
my $outfile = new File::Temp(TEMPLATE => "ikiwiki-po-filter-out.XXXXXXXXXX",
|
|
|
|
DIR => File::Spec->tmpdir,
|
|
|
|
UNLINK => 1)->filename;
|
|
|
|
|
2009-01-02 15:14:58 +01:00
|
|
|
my $fail = sub ($) {
|
2009-01-02 15:00:34 +01:00
|
|
|
my $msg = "po(po_to_markup) - $page : " . shift;
|
2009-01-01 21:56:36 +01:00
|
|
|
if ($nonfatal) {
|
|
|
|
warn $msg;
|
|
|
|
return undef;
|
|
|
|
}
|
|
|
|
error($msg, sub { unlink $infile, $outfile});
|
2009-01-02 15:14:58 +01:00
|
|
|
};
|
2009-01-01 21:56:36 +01:00
|
|
|
|
|
|
|
writefile(basename($infile), File::Spec->tmpdir, $content)
|
2009-01-02 15:14:58 +01:00
|
|
|
or return $fail->(sprintf(gettext("failed to write %s"), $infile));
|
2009-01-01 21:56:36 +01:00
|
|
|
|
|
|
|
my $masterfile = srcfile($pagesources{masterpage($page)});
|
|
|
|
my %options = (
|
|
|
|
"markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0,
|
|
|
|
);
|
|
|
|
my $doc=Locale::Po4a::Chooser::new('text',%options);
|
|
|
|
$doc->process(
|
|
|
|
'po_in_name' => [ $infile ],
|
|
|
|
'file_in_name' => [ $masterfile ],
|
|
|
|
'file_in_charset' => 'utf-8',
|
|
|
|
'file_out_charset' => 'utf-8',
|
2009-01-02 15:14:58 +01:00
|
|
|
) or return $fail->(gettext("failed to translate"));
|
2009-01-02 15:00:34 +01:00
|
|
|
$doc->write($outfile)
|
2009-01-02 15:14:58 +01:00
|
|
|
or return $fail->(sprintf(gettext("failed to write %s"), $outfile));
|
2009-01-01 21:56:36 +01:00
|
|
|
|
2009-01-02 15:00:34 +01:00
|
|
|
$content = readfile($outfile)
|
2009-01-02 15:14:58 +01:00
|
|
|
or return $fail->(sprintf(gettext("failed to read %s"), $outfile));
|
2009-01-01 21:56:36 +01:00
|
|
|
|
|
|
|
# Unlinking should happen automatically, thanks to File::Temp,
|
|
|
|
# but it does not work here, probably because of the way writefile()
|
|
|
|
# and Locale::Po4a::write() work.
|
|
|
|
unlink $infile, $outfile;
|
|
|
|
|
|
|
|
return $content;
|
|
|
|
}
|
|
|
|
|
2009-01-01 23:10:16 +01:00
|
|
|
# returns a SuccessReason or FailReason object
|
|
|
|
sub isvalidpo ($) {
|
|
|
|
my $content = shift;
|
|
|
|
|
|
|
|
# NB: we don't use po_to_markup here, since Po4a parser does
|
|
|
|
# not mind invalid PO content
|
|
|
|
$content = '' unless defined $content;
|
|
|
|
$content = decode_utf8(encode_utf8($content));
|
|
|
|
|
|
|
|
# There are incompatibilities between some File::Temp versions
|
|
|
|
# (including 0.18, bundled with Lenny's perl-modules package)
|
|
|
|
# and others (e.g. 0.20, previously present in the archive as
|
|
|
|
# a standalone package): under certain circumstances, some
|
|
|
|
# return a relative filename, whereas others return an absolute one;
|
|
|
|
# we here use this module in a way that is at least compatible
|
|
|
|
# with 0.18 and 0.20. Beware, hit'n'run refactorers!
|
|
|
|
my $infile = new File::Temp(TEMPLATE => "ikiwiki-po-isvalidpo.XXXXXXXXXX",
|
|
|
|
DIR => File::Spec->tmpdir,
|
|
|
|
UNLINK => 1)->filename;
|
|
|
|
|
2009-01-02 15:14:58 +01:00
|
|
|
my $fail = sub ($) {
|
2009-01-01 23:32:52 +01:00
|
|
|
my $msg = '[po/isvalidpo] ' . shift;
|
2009-01-01 23:10:16 +01:00
|
|
|
unlink $infile;
|
|
|
|
return IkiWiki::FailReason->new("$msg");
|
2009-01-02 15:14:58 +01:00
|
|
|
};
|
2009-01-01 23:10:16 +01:00
|
|
|
|
|
|
|
writefile(basename($infile), File::Spec->tmpdir, $content)
|
2009-01-02 15:14:58 +01:00
|
|
|
or return $fail->(sprintf(gettext("failed to write %s"), $infile));
|
2009-01-01 23:10:16 +01:00
|
|
|
|
2009-01-01 23:33:16 +01:00
|
|
|
my $res = (system("msgfmt", "--check", $infile, "-o", "/dev/null") == 0);
|
2009-01-01 23:10:16 +01:00
|
|
|
|
|
|
|
# Unlinking should happen automatically, thanks to File::Temp,
|
|
|
|
# but it does not work here, probably because of the way writefile()
|
|
|
|
# and Locale::Po4a::write() work.
|
|
|
|
unlink $infile;
|
|
|
|
|
|
|
|
if ($res) {
|
|
|
|
return IkiWiki::SuccessReason->new("valid gettext data");
|
|
|
|
}
|
2009-07-21 12:39:21 +02:00
|
|
|
return IkiWiki::FailReason->new(gettext("invalid gettext data, go back ".
|
|
|
|
"to previous page to continue edit"));
|
2009-01-01 23:10:16 +01:00
|
|
|
}
|
|
|
|
|
2008-11-11 04:05:39 +01:00
|
|
|
# ,----
|
2009-01-26 19:33:02 +01:00
|
|
|
# | PageSpecs
|
2008-11-11 04:05:39 +01:00
|
|
|
# `----
|
|
|
|
|
2008-10-10 21:47:20 +02:00
|
|
|
package IkiWiki::PageSpec;
|
2008-10-10 17:10:40 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub match_istranslation ($;@) {
|
2008-10-10 21:47:20 +02:00
|
|
|
my $page=shift;
|
2008-11-05 21:18:07 +01:00
|
|
|
|
2008-10-11 03:01:59 +02:00
|
|
|
if (IkiWiki::Plugin::po::istranslation($page)) {
|
2008-10-10 21:47:20 +02:00
|
|
|
return IkiWiki::SuccessReason->new("is a translation page");
|
2008-10-10 17:10:40 +02:00
|
|
|
}
|
2008-10-10 21:47:20 +02:00
|
|
|
else {
|
|
|
|
return IkiWiki::FailReason->new("is not a translation page");
|
2008-10-10 17:10:40 +02:00
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-10 17:10:40 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub match_istranslatable ($;@) {
|
2008-10-10 21:47:20 +02:00
|
|
|
my $page=shift;
|
2008-11-05 21:18:07 +01:00
|
|
|
|
2008-10-11 03:01:59 +02:00
|
|
|
if (IkiWiki::Plugin::po::istranslatable($page)) {
|
2008-10-10 21:47:20 +02:00
|
|
|
return IkiWiki::SuccessReason->new("is set as translatable in po_translatable_pages");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return IkiWiki::FailReason->new("is not set as translatable in po_translatable_pages");
|
2008-10-10 17:10:40 +02:00
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-05 17:14:30 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub match_lang ($$;@) {
|
2008-10-15 00:35:17 +02:00
|
|
|
my $page=shift;
|
|
|
|
my $wanted=shift;
|
2008-11-05 21:18:07 +01:00
|
|
|
|
2008-10-15 00:35:17 +02:00
|
|
|
my $regexp=IkiWiki::glob2re($wanted);
|
2008-11-10 21:30:06 +01:00
|
|
|
my $lang=IkiWiki::Plugin::po::lang($page);
|
2009-01-26 19:24:33 +01:00
|
|
|
if ($lang !~ /^$regexp$/i) {
|
2008-10-15 00:35:17 +02:00
|
|
|
return IkiWiki::FailReason->new("file language is $lang, not $wanted");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return IkiWiki::SuccessReason->new("file language is $wanted");
|
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-15 00:35:17 +02:00
|
|
|
|
2008-12-31 23:54:21 +01:00
|
|
|
sub match_currentlang ($$;@) {
|
2008-10-15 01:23:19 +02:00
|
|
|
my $page=shift;
|
|
|
|
shift;
|
|
|
|
my %params=@_;
|
|
|
|
|
|
|
|
return IkiWiki::FailReason->new("no location provided") unless exists $params{location};
|
|
|
|
|
2008-11-10 21:30:06 +01:00
|
|
|
my $currentlang=IkiWiki::Plugin::po::lang($params{location});
|
|
|
|
my $lang=IkiWiki::Plugin::po::lang($page);
|
2008-10-15 01:23:19 +02:00
|
|
|
|
|
|
|
if ($lang eq $currentlang) {
|
|
|
|
return IkiWiki::SuccessReason->new("file language is the same as current one, i.e. $currentlang");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return IkiWiki::FailReason->new("file language is $lang, whereas current language is $currentlang");
|
|
|
|
}
|
2008-12-31 23:54:21 +01:00
|
|
|
}
|
2008-10-15 01:23:19 +02:00
|
|
|
|
2008-10-05 04:11:02 +02:00
|
|
|
1
|