";
} # }}}
diff --git a/IkiWiki/Plugin/polygen.pm b/IkiWiki/Plugin/polygen.pm
index 966b6cb51..63f6bf5db 100644
--- a/IkiWiki/Plugin/polygen.pm
+++ b/IkiWiki/Plugin/polygen.pm
@@ -29,7 +29,7 @@ sub preprocess (@) { #{{{
my $grmfile = '/usr/share/polygen/ita/polygen.grm';
if (! -d '/usr/share/polygen') {
- return "[[polygen not installed]]";
+ return "[[".gettext("polygen not installed")."]]";
}
find({wanted => sub {
if (substr($File::Find::name, -length($grammar)) eq $grammar) {
@@ -48,10 +48,10 @@ sub preprocess (@) { #{{{
}
if ($?) {
- $res="[[polygen failed]]";
+ $res="[[".gettext("polygen failed")."]]";
}
- # Strip trainling spaces and newlines so that we flow well with the
+ # Strip trailing spaces and newlines so that we flow well with the
# markdown text
$res =~ s/\s*$//;
return $res;
diff --git a/IkiWiki/Plugin/search.pm b/IkiWiki/Plugin/search.pm
index 942b94986..1b5c66716 100644
--- a/IkiWiki/Plugin/search.pm
+++ b/IkiWiki/Plugin/search.pm
@@ -31,7 +31,7 @@ sub getopt () { #{{{
sub checkconfig () { #{{{
foreach my $required (qw(url cgiurl)) {
if (! length $config{$required}) {
- error("Must specify $required when using the search plugin\n");
+ error(sprintf(gettext("Must specify %s when using the search plugin"), $required));
}
}
} #}}}
@@ -55,13 +55,13 @@ sub pagetemplate (@) { #{{{
} #}}}
sub delete (@) { #{{{
- debug("cleaning hyperestraier search index");
+ debug(gettext("cleaning hyperestraier search index"));
estcmd("purge -cl");
estcfg();
} #}}}
sub change (@) { #{{{
- debug("updating hyperestraier search index");
+ debug(gettext("updating hyperestraier search index"));
estcmd("gather -cm -bc -cl -sd",
map {
Encode::encode_utf8($config{destdir}."/".$_)
diff --git a/IkiWiki/Plugin/shortcut.pm b/IkiWiki/Plugin/shortcut.pm
index e4a9ab1a6..9479306a8 100644
--- a/IkiWiki/Plugin/shortcut.pm
+++ b/IkiWiki/Plugin/shortcut.pm
@@ -21,13 +21,13 @@ sub preprocess_shortcut (@) { #{{{
my %params=@_;
if (! defined $params{name} || ! defined $params{url}) {
- return "[[shortcut missing name or url parameter]]";
+ return "[[".gettext("shortcut missing name or url parameter")."]]";
}
hook(type => "preprocess", no_override => 1, id => $params{name},
call => sub { shortcut_expand($params{url}, $params{desc}, @_) });
- return "shortcut $params{name} points to $params{url}";
+ return sprintf(gettext("shortcut %s points to %s"), $params{name}, $params{url});
} # }}}
sub shortcut_expand ($$@) { #{{{
diff --git a/IkiWiki/Plugin/smiley.pm b/IkiWiki/Plugin/smiley.pm
index 0c6f5d427..85a719337 100644
--- a/IkiWiki/Plugin/smiley.pm
+++ b/IkiWiki/Plugin/smiley.pm
@@ -19,7 +19,7 @@ sub setup () { #{{{
}
if (! %smileys) {
- debug("failed to parse any smileys, disabling plugin");
+ debug(gettext("failed to parse any smileys, disabling plugin"));
return;
}
diff --git a/IkiWiki/Plugin/template.pm b/IkiWiki/Plugin/template.pm
index 095705604..23d9d65d8 100644
--- a/IkiWiki/Plugin/template.pm
+++ b/IkiWiki/Plugin/template.pm
@@ -16,17 +16,16 @@ sub preprocess (@) { #{{{
my %params=@_;
if (! exists $params{id}) {
- return "[[template missing id parameter]]"
+ return "[[".gettext("template missing id parameter")."]]";
}
my $template_page="templates/$params{id}";
add_depends($params{page}, $template_page);
my $template_file=$pagesources{$template_page};
- return "[[template ".
- htmllink($params{page}, $params{destpage}, $template_page).
- " not found]]"
- unless defined $template_file;
+ return sprintf(gettext("template %s not found"),
+ htmllink($params{page}, $params{destpage}, $template_page))
+ unless defined $template_file;
my $template;
eval {
@@ -43,7 +42,7 @@ sub preprocess (@) { #{{{
);
};
if ($@) {
- return "[[template failed to process: $@]]";
+ return "[[".gettext("template failed to process:")." $@]]";
}
foreach my $param (keys %params) {
diff --git a/IkiWiki/Rcs/Stub.pm b/IkiWiki/Rcs/Stub.pm
index 087f2508c..03757758a 100644
--- a/IkiWiki/Rcs/Stub.pm
+++ b/IkiWiki/Rcs/Stub.pm
@@ -63,7 +63,7 @@ sub rcs_notify () {
sub rcs_getctime ($) {
# Optional, used to get the page creation time from the RCS.
- error "getctime not implemented";
+ error gettext("getctime not implemented");
}
1
diff --git a/IkiWiki/Rcs/svn.pm b/IkiWiki/Rcs/svn.pm
index 848dfac3a..30020c1fc 100644
--- a/IkiWiki/Rcs/svn.pm
+++ b/IkiWiki/Rcs/svn.pm
@@ -203,7 +203,7 @@ sub rcs_recentchanges ($) { #{{{
sub rcs_notify () { #{{{
if (! exists $ENV{REV}) {
- error("REV is not set, not running from svn post-commit hook, cannot send notifications");
+ error(gettext("REV is not set, not running from svn post-commit hook, cannot send notifications"));
}
my $rev=int(possibly_foolish_untaint($ENV{REV}));
diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
index 678075b82..30249b9bd 100644
--- a/IkiWiki/Render.pm
+++ b/IkiWiki/Render.pm
@@ -93,8 +93,8 @@ sub genpage ($$$) { #{{{
$template->param(historyurl => $u);
$actions++;
}
- if ($config{discussion} && (length $config{cgiurl} || exists $links{"$page/discussion"})) {
- $template->param(discussionlink => htmllink($page, $page, "Discussion", 1, 1));
+ if ($config{discussion} && (length $config{cgiurl} || exists $links{$page."/".gettext("discussion")})) {
+ $template->param(discussionlink => htmllink($page, $page, gettext("Discussion"), 1, 1));
$actions++;
}
@@ -157,7 +157,7 @@ sub scan ($) { #{{{
if ($config{discussion}) {
# Discussion links are a special case since they're
# not in the text of the page, but on its template.
- push @links, "$page/discussion";
+ push @links, $page."/".gettext("discussion");
}
$links{$page}=\@links;
@@ -224,7 +224,7 @@ sub refresh () { #{{{
elsif (! -d $_ && ! -l $_) {
my ($f)=/$config{wiki_file_regexp}/; # untaint
if (! defined $f) {
- warn("skipping bad filename $_\n");
+ warn(sprintf(gettext("skipping bad filename %s"), $_)."\n");
}
else {
$f=~s/^\Q$config{srcdir}\E\/?//;
@@ -244,7 +244,7 @@ sub refresh () { #{{{
elsif (! -d $_ && ! -l $_) {
my ($f)=/$config{wiki_file_regexp}/; # untaint
if (! defined $f) {
- warn("skipping bad filename $_\n");
+ warn(sprintf(gettext("skipping bad filename %s"), $_)."\n");
}
else {
# Don't add pages that are in the
@@ -284,7 +284,7 @@ sub refresh () { #{{{
my @del;
foreach my $page (keys %oldpagemtime) {
if (! $exists{$page}) {
- debug("removing old page $page");
+ debug(sprintf(gettext("removing old page %s"), $page));
push @del, $pagesources{$page};
$links{$page}=[];
$renderedfiles{$page}=[];
@@ -303,7 +303,7 @@ sub refresh () { #{{{
if (! exists $oldpagemtime{$page} ||
mtime(srcfile($file)) > $oldpagemtime{$page} ||
$forcerebuild{$page}) {
- debug("scanning $file");
+ debug(sprintf(gettext("scanning %s"), $file));
push @changed, $file;
scan($file);
}
@@ -312,7 +312,7 @@ sub refresh () { #{{{
# render changed and new pages
foreach my $file (@changed) {
- debug("rendering $file");
+ debug(sprintf(gettext("rendering %s"), $file));
render($file);
$rendered{$file}=1;
}
@@ -324,7 +324,7 @@ sub refresh () { #{{{
foreach my $page (keys %{$backlinks{$p}}) {
my $file=$pagesources{$page};
next if $rendered{$file};
- debug("rendering $file, which links to $p");
+ debug(sprintf(gettext("rendering %s, which links to %s"), $file, $p));
render($file);
$rendered{$file}=1;
}
@@ -341,7 +341,7 @@ sub refresh () { #{{{
next if $f eq $file;
my $page=pagename($file);
if (pagespec_match($page, $depends{$p})) {
- debug("rendering $f, which depends on $page");
+ debug(sprintf(gettext("rendering %s, which depends on %s"), $f, $page));
render($f);
$rendered{$f}=1;
last;
@@ -379,7 +379,7 @@ sub refresh () { #{{{
my $linkfile=$pagesources{$link};
if (defined $linkfile) {
next if $rendered{$linkfile};
- debug("rendering $linkfile, to update its backlinks");
+ debug(sprintf(gettext("rendering %s, to update its backlinks"), $linkfile));
render($linkfile);
$rendered{$linkfile}=1;
}
@@ -391,7 +391,7 @@ sub refresh () { #{{{
my $page=pagename($src);
foreach my $file (@{$oldrenderedfiles{$page}}) {
if (! grep { $_ eq $file } @{$renderedfiles{$page}}) {
- debug("removing $file, no longer rendered by $page");
+ debug(sprintf(gettext("removing %s, no longer rendered by %s"), $file, $page));
prune($config{destdir}."/".$file);
}
}
@@ -417,7 +417,7 @@ sub commandline_render () { #{{{
$file=~s/\Q$config{srcdir}\E\/?//;
my $type=pagetype($file);
- die "ikiwiki: cannot render $srcfile\n" unless defined $type;
+ die sprintf(gettext("ikiwiki: cannot render %s"), $srcfile)."\n" unless defined $type;
my $content=readfile($srcfile);
my $page=pagename($file);
$pagesources{$page}=$file;
diff --git a/IkiWiki/Setup.pm b/IkiWiki/Setup.pm
index 2b4c76bd0..560bc798b 100644
--- a/IkiWiki/Setup.pm
+++ b/IkiWiki/Setup.pm
@@ -10,7 +10,7 @@ package IkiWiki;
sub setup () { # {{{
my $setup=possibly_foolish_untaint($config{setup});
delete $config{setup};
- open (IN, $setup) || error("read $setup: $!\n");
+ open (IN, $setup) || error(sprintf(gettext("cannot read %s: %s"), $setup, $!));
my $code;
{
local $/=undef;
diff --git a/IkiWiki/Setup/Standard.pm b/IkiWiki/Setup/Standard.pm
index 77c164e34..1e65b23e3 100644
--- a/IkiWiki/Setup/Standard.pm
+++ b/IkiWiki/Setup/Standard.pm
@@ -35,7 +35,7 @@ sub setup_standard {
}
if (! $config{render} && (! $config{refresh} || $config{wrappers})) {
- debug("generating wrappers..");
+ debug(gettext("generating wrappers.."));
my @wrappers=@{$setup{wrappers}};
delete $setup{wrappers};
my %startconfig=(%config);
@@ -71,10 +71,10 @@ sub setup_standard {
}
elsif (! $config{refresh}) {
$config{rebuild}=1;
- debug("rebuilding wiki..");
+ debug(gettext("rebuilding wiki.."));
}
else {
- debug("refreshing wiki..");
+ debug(gettext("refreshing wiki.."));
}
loadplugins();
@@ -83,7 +83,7 @@ sub setup_standard {
loadindex();
refresh();
- debug("done");
+ debug(gettext("done"));
saveindex();
}
diff --git a/IkiWiki/UserInfo.pm b/IkiWiki/UserInfo.pm
index d48b8071c..03d63cc23 100644
--- a/IkiWiki/UserInfo.pm
+++ b/IkiWiki/UserInfo.pm
@@ -125,14 +125,15 @@ sub send_commit_mails ($$$@) { #{{{
my $diff=$diffsub->();
my $message=$messagesub->();
- my $subject="update of $config{wikiname}'s ";
+ my $pagelist;
if (@changed_pages > 2) {
- $subject.="$changed_pages[0] $changed_pages[1] etc";
+ $pagelist="$changed_pages[0] $changed_pages[1] ...";
}
else {
- $subject.=join(" ", @changed_pages);
+ $pagelist.=join(" ", @changed_pages);
}
- $subject.=" by $user";
+ my $subject=sprintf(gettext("update of %s's %s by %s"),
+ $config{wikiname}, $pagelist, $user);
my $template=template("notifymail.tmpl");
$template->param(
@@ -146,11 +147,11 @@ sub send_commit_mails ($$$@) { #{{{
defined(my $pid = fork) or error("Can't fork: $!");
return if $pid;
setsid() or error("Can't start a new session: $!");
- eval q{use POSIX âsetsidâ};
+ eval q{use POSIX 'setsid'};
chdir '/';
open STDIN, '/dev/null';
open STDOUT, '>/dev/null';
- open STDERR, '>&STDOUT' or error("Canât dup stdout: $!");
+ open STDERR, '>&STDOUT' or error("Can't dup stdout: $!");
unlockwiki(); # don't need to keep a lock on the wiki
@@ -162,7 +163,7 @@ sub send_commit_mails ($$$@) { #{{{
From => "$config{wikiname} <$config{adminemail}>",
Subject => $subject,
Message => $template->output,
- ) or error("Failed to send update notification mail");
+ );
}
exit 0; # daemon process done
diff --git a/IkiWiki/Wrapper.pm b/IkiWiki/Wrapper.pm
index a3ecccd5b..e761085fb 100644
--- a/IkiWiki/Wrapper.pm
+++ b/IkiWiki/Wrapper.pm
@@ -13,15 +13,15 @@ sub gen_wrapper () { #{{{
$config{destdir}=abs_path($config{destdir});
my $this=abs_path($0);
if (! -x $this) {
- error("$this doesn't seem to be executable");
+ error(sprintf(gettext("%s doesn't seem to be executable"), $this));
}
if ($config{setup}) {
- error("cannot create a wrapper that uses a setup file");
+ error(gettext("cannot create a wrapper that uses a setup file"));
}
my $wrapper=possibly_foolish_untaint($config{wrapper});
if (! defined $wrapper || ! length $wrapper) {
- error("wrapper filename not specified");
+ error(gettext("wrapper filename not specified"));
}
delete $config{wrapper};
@@ -59,7 +59,7 @@ EOF
$configstring=~s/"/\\"/g;
$configstring=~s/\n/\\\n/g;
- open(OUT, ">$wrapper.c") || error("failed to write $wrapper.c: $!");;
+ open(OUT, ">$wrapper.c") || error(sprintf(gettext("failed to write %s: %s"), "$wrapper.c", $!));;
print OUT <<"EOF";
/* A wrapper for ikiwiki, can be safely made suid. */
#define _GNU_SOURCE
@@ -94,14 +94,14 @@ $envsave
EOF
close OUT;
if (system("gcc", "$wrapper.c", "-o", $wrapper) != 0) {
- error("failed to compile $wrapper.c");
+ error(sprintf(gettext("failed to compile %s"), "$wrapper.c"));
}
unlink("$wrapper.c");
if (defined $config{wrappermode} &&
! chmod(oct($config{wrappermode}), $wrapper)) {
error("chmod $wrapper: $!");
}
- print "successfully generated $wrapper\n";
+ printf(gettext("successfully generated %s\n"), $wrapper);
} #}}}
1
diff --git a/Makefile.PL b/Makefile.PL
index a6292a422..e0eaf4e32 100755
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -32,10 +32,12 @@ extra_build:
./mdwn2man ikiwiki 1 doc/usage.mdwn > ikiwiki.man
./mdwn2man ikiwiki-mass-rebuild 8 doc/ikiwiki-mass-rebuild.mdwn > ikiwiki-mass-rebuild.man
./pm_filter $(PREFIX) $(VER) $(PROBABLE_INST_LIB) < ikiwiki.in > ikiwiki.out
-
+ $(MAKE) -C po
+
extra_clean:
rm -rf html doc/.ikiwiki
rm -f ikiwiki.man ikiwiki-mass-rebuild.man ikiwiki.out
+ $(MAKE) -C po clean
extra_install:
install -d $(DESTDIR)$(PREFIX)/share/ikiwiki/templates
@@ -58,6 +60,8 @@ extra_install:
install -d $(DESTDIR)$(PREFIX)/bin
install ikiwiki.out $(DESTDIR)$(PREFIX)/bin/ikiwiki
+
+ $(MAKE) -C po install
}
}
diff --git a/debian/changelog b/debian/changelog
index e455be1a3..a607476fc 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -14,6 +14,9 @@ ikiwiki (1.37) UNRELEASED; urgency=low
* Improve code that ignores files in the underlaydir if the srcdir has a
file building the same page. Now it will work even if the extensions of
the source files differ.
+ * Initial work on internationalization of the program code. po/ikiwiki.pot
+ is available for translation.
+ * Export gettext() from IkiWiki module.
-- Joey Hess Thu, 28 Dec 2006 17:13:43 -0500
diff --git a/debian/control b/debian/control
index 279f93199..d29a03846 100644
--- a/debian/control
+++ b/debian/control
@@ -11,7 +11,7 @@ Package: ikiwiki
Architecture: all
Depends: ${perl:Depends}, libxml-simple-perl, markdown, libtimedate-perl, libhtml-template-perl, libhtml-scrubber-perl, libcgi-formbuilder-perl (>= 3.02.02), libtime-duration-perl, libcgi-session-perl (>= 4.14-1), libmail-sendmail-perl, gcc | c-compiler, libc6-dev | libc-dev, libhtml-parser-perl, liburi-perl
Recommends: subversion | git-core | tla | mercurial, hyperestraier
-Suggests: viewcvs, librpc-xml-perl, libtext-wikiformat-perl, python-docutils, polygen, tidy, libxml-feed-perl, libmailtools-perl, perlmagick, libfile-mimeinfo-perl, libnet-openid-consumer-perl, libcrypt-ssleay-perl
+Suggests: viewcvs, librpc-xml-perl, libtext-wikiformat-perl, python-docutils, polygen, tidy, libxml-feed-perl, libmailtools-perl, perlmagick, libfile-mimeinfo-perl, libnet-openid-consumer-perl, libcrypt-ssleay-perl, liblocale-gettext-perl
Description: a wiki compiler
ikiwiki converts a directory full of wiki pages into html pages suitable
for publishing on a website. Unlike many wikis, ikiwiki does not have its
diff --git a/doc/bugs/hardcoded___34__Discussion__34___link.mdwn b/doc/bugs/hardcoded___34__Discussion__34___link.mdwn
index fc8406d87..4436f7101 100644
--- a/doc/bugs/hardcoded___34__Discussion__34___link.mdwn
+++ b/doc/bugs/hardcoded___34__Discussion__34___link.mdwn
@@ -38,5 +38,7 @@ or "History".
>> In my wiki I use only Polish name of pages, so I would like to have
>> dyskusja.html page, instead of discussion.html page. --Pawel
->>> I have an incomplete i10n patch for such hardcoded strings in the code,
->>> which I hope to finish up eventually --[[Joey]]
+>>> Ikiwiki is now fully internationalised, so you can change the name of
+>>> the Discussion page and quite a lot more (but hardly everything) by
+>>> translating it. [[bugs/done]]! There's a `po/debconf.pot` in the source
+>>> now for translating. See [[translation]]. --[[Joey]]
diff --git a/doc/install.mdwn b/doc/install.mdwn
index 04600b17f..d9c2a79f7 100644
--- a/doc/install.mdwn
+++ b/doc/install.mdwn
@@ -11,7 +11,7 @@ installed, and also uses the following perl modules if available:
[[cpan CGI::Session]], [[cpan CGI::FormBuilder]] (version 3.02.02 or newer),
[[cpan Mail::Sendmail]], [[cpan Time::Duration]], [[cpan TimeDate]],
[[cpan HTML::Scrubber]], [[cpan RPC::XML]], [[cpan XML::Simple]],
-[[cpan XML::Feed]], [[cpan File::MimeInfo]].
+[[cpan XML::Feed]], [[cpan File::MimeInfo]], [[cpan Locale::gettext]].
The [[tla]] support also needs the [[cpan MailTools]] perl module.
diff --git a/doc/patchqueue/l10n.mdwn b/doc/patchqueue/l10n.mdwn
index 85e4f21e2..3369bec11 100644
--- a/doc/patchqueue/l10n.mdwn
+++ b/doc/patchqueue/l10n.mdwn
@@ -22,13 +22,6 @@ I've revised the patches (tested OK):
However...
-> There are two places in IkiWiki, subject to localization: HTML::Template
-
-Unfortunately this is not correct. There a few (?) exceptional places, for
-example button texts in CGI.pm:
-
- my @buttons=("Save Page", "Preview", "Cancel");
-
> fine. Also a final note, I haven't examined the quality of generated
> templates yet.
@@ -55,43 +48,14 @@ Birisi[1], ki muhtemelen bu sizsiniz, [2] üzerindeki
bulundu. Parola: -- ikiwiki [1] Parolayı isteyen
kullanıcının ait IP adresi: [2]
-----
-
-> Unfortunately this is not correct. There a few (?) exceptional places, for
-> example button texts in CGI.pm:
->
-> my @buttons=("Save Page", "Preview", "Cancel");
-
-Hmm, I've thought on this issue. Using Locale::gettext seems to be the
-natural solution. But this would need to create another po file and also,
-ikiwiki would depend another Perl module. Kinda overkill...
-
-I have another idea... What about to create another (flat) template file
-for this sort of strings? Something like strings.tmpl with the content:
-
- Save Page, Preview, Cancel
-
-or we could categorize these strings in some variables (',' is the
-delimiter for this code snippet):
-
-
- Save Page, Preview, Cancel
-
-
-and then (preferably in a separate wrapper function in CGI.pm):
-
- my $template=template("strings.tmpl");
- $template->param("BUTTONS", 1);
- my @buttons=split(/\s*,\s*/, $template->output);
-
-You get the idea... I've tried this method. All in one po file, kind of
-ugly, but it _really_ works.
-
-> > fine. Also a final note, I haven't examined the quality of generated
-> > templates yet.
->
> Looks like, tmpl_process3 cannot preserve line breaks in template files.
> For example, it processed the following template:
This could be easily worked around in tmpl_process3, but I wouldn't like to
maintain a separate utility.
+
+----
+
+As to the hardcoded strings in ikiwiki, I've internationalized the program,
+and there is a po/ikiwiki.pot in the source that can be translated.
+--[[Joey]]
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index f808d2e1e..6c475024a 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -382,6 +382,10 @@ path to the first file found.
Given a time, formats it for display.
+#### `gettext`
+
+This is the standard gettext function, although slightly optimised.
+
## RCS plugins
ikiwiki's support for revision control systems also uses pluggable perl
diff --git a/doc/translation.mdwn b/doc/translation.mdwn
new file mode 100644
index 000000000..4f7bf347f
--- /dev/null
+++ b/doc/translation.mdwn
@@ -0,0 +1,32 @@
+If you want to translate your wiki into another language, there are
+essentailly three peices needed for a complete translation:
+
+1. The messages in the ikiwiki program itself need to be translated.
+ Ikiwiki is internationalised, and most such messages are already marked
+ with `gettext()`. The source has a `po/ikiwiki.pot` that can be copied
+ and translated as a po file. All very standard.
+
+ Note that a few things in the source are not currently translated. These
+ include:
+
+ * Error messages of the "should never happen" variety.
+ * Certian info in commit messages, which is not visible from inside the
+ wiki, but is visible in the commit logs. This needs to stay in English
+ so that ikiwiki can parse it back out of the logs.
+ * Some parts of FormBuilder forms, which should be translatable by
+ adding templates. Note that these forms don't need templates for the
+ English version.
+ * The name of the `index` page, which has a special meaning to browsers
+ anyway.
+ * The names of some other pages, like `sidebar` and `openid`.
+ * The names and values of parameters, both to the program, in the setup
+ file, and in preprocessor directives.
+
+1. The templates also need to be translated. Some work has been done on an
+ infrastructure for maintaining translated templates, as documented in
+ [[patchqueue/l10n]], but until that's complete, you'd need to copy and
+ translate the templates by hand.
+
+1. The basewiki itself needs to be translated. Whether to only translate
+ the page contents, or also translate the page names, is an open
+ question.
diff --git a/ikiwiki.in b/ikiwiki.in
index d18970d0f..11d562523 100755
--- a/ikiwiki.in
+++ b/ikiwiki.in
@@ -10,7 +10,7 @@ use lib '.'; # For use in nonstandard directory, munged by Makefile.
use IkiWiki;
sub usage () { #{{{
- die "usage: ikiwiki [options] source dest\n";
+ die gettext("usage: ikiwiki [options] source dest"), "\n";
} #}}}
sub getconfig () { #{{{
diff --git a/po/Makefile b/po/Makefile
new file mode 100644
index 000000000..fa129de81
--- /dev/null
+++ b/po/Makefile
@@ -0,0 +1,44 @@
+# List here all source files with translatable strings.
+POTFILES=$(sort $(shell find ../IkiWiki -type f -name \*.pm)) \
+ ../ikiwiki.in ../IkiWiki.pm
+
+POFILES=$(wildcard *.po)
+MOFILES=$(POFILES:.po=.mo)
+
+all: ikiwiki.pot $(MOFILES)
+
+install: all
+ for file in $(MOFILES); do \
+ lang=`echo $$file | sed 's/\.mo//'`; \
+ install -d $(DESTDIR)$(PREFIX)/share/locale/$$lang/LC_MESSAGES/; \
+ install -m 0644 $$file $(DESTDIR)$(PREFIX)/share/locale/$$lang/LC_MESSAGES/ikiwiki.mo; \
+ done
+
+ikiwiki.pot: $(POTFILES)
+ @echo "Rebuilding the pot file"
+ xgettext $(POTFILES) -o ikiwiki.pot -Lperl
+
+clean:
+ rm -f ikiwiki.pot $(MOFILES) messages messages.mo
+
+%.mo: %.po
+ msgfmt -o $@ $<
+
+%.po: ikiwiki.pot
+ @echo -n "Merging ikiwiki.pot and $@"
+ @msgmerge $@ ikiwiki.pot -o $@.new
+# Typically all that changes was a date. I'd prefer not to commit such
+# changes, so detect and ignore them.
+ @if [ "`diff $@ $@.new | grep '[<>]' | wc -l`" -ne 2 ]; then \
+ mv -f $@.new $@; \
+ else \
+ rm -f $@.new; \
+ fi
+ @msgfmt --statistics $@
+
+check:
+ @for file in $(POFILES); do \
+ lang=`echo $$file | sed 's/\.po//'`; \
+ printf "$$lang: "; \
+ msgfmt -o /dev/null -c -v --statistics $$lang.po;\
+ done
diff --git a/po/ikiwiki.pot b/po/ikiwiki.pot
new file mode 100644
index 000000000..bc4d7a9d3
--- /dev/null
+++ b/po/ikiwiki.pot
@@ -0,0 +1,358 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-12-28 23:36-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../IkiWiki/CGI.pm:49
+#, perl-format
+msgid "%s is locked by %s and cannot be edited"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:139
+msgid "You need to log in first."
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:257
+msgid "Preferences saved."
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:408 ../IkiWiki/Render.pm:96 ../IkiWiki/Render.pm:160
+msgid "discussion"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:445
+#, perl-format
+msgid "creating %s"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:462 ../IkiWiki/CGI.pm:505
+#, perl-format
+msgid "editing %s"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:622
+msgid "You are banned."
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:61
+#, perl-format
+msgid "aggregate plugin missing %s parameter"
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:89
+msgid "new feed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:103
+msgid "posts"
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:105
+msgid "new"
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:206
+#, perl-format
+msgid "expiring %s (%s days old)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:213
+#, perl-format
+msgid "expiring %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:236
+#, perl-format
+msgid "checking feed %s\t..."
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:241
+#, perl-format
+msgid "could not find feed at %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:250
+msgid "feed crashed XML::Feed!"
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:273
+#, perl-format
+msgid "processed ok at "
+msgstr ""
+
+#: ../IkiWiki/Plugin/aggregate.pm:314
+#, perl-format
+msgid "creating new page %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:36
+msgid "There are no broken links!"
+msgstr ""
+
+#: ../IkiWiki/Plugin/fortune.pm:18
+msgid "fortune failed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/googlecalendar.pm:22
+msgid "googlecalendar failed to find url in html"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:37
+msgid "Must specify url to wiki with --url when using --rss or --atom"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:97
+#, perl-format
+msgid "unknown sort type %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:368
+msgid "RPC::XML::Client not found, not pinging"
+msgstr ""
+
+#: ../IkiWiki/Plugin/linkmap.pm:99
+msgid "linkmap failed to run dot"
+msgstr ""
+
+#: ../IkiWiki/Plugin/mdwn.pm:37
+#, perl-format
+msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/mirrorlist.pm:23
+msgid "Mirrors"
+msgstr ""
+
+#: ../IkiWiki/Plugin/mirrorlist.pm:23
+msgid "Mirror"
+msgstr ""
+
+#: ../IkiWiki/Plugin/openid.pm:36
+msgid "What's this?"
+msgstr ""
+
+#: ../IkiWiki/Plugin/openid.pm:37
+msgid "Get an OpenID"
+msgstr ""
+
+#: ../IkiWiki/Plugin/orphans.pm:41
+msgid "All pages are linked to by other pages."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:104
+msgid "(use FirstnameLastName)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:144
+msgid "Account creation successful. Now you can Login."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:147
+msgid "Error creating account."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:168
+msgid "Failed to send mail"
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:170
+msgid "Your password has been emailed to you."
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:64
+msgid "vote"
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:72
+msgid "Total votes:"
+msgstr ""
+
+#: ../IkiWiki/Plugin/polygen.pm:32
+msgid "polygen not installed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/polygen.pm:51
+msgid "polygen failed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/search.pm:34
+#, perl-format
+msgid "Must specify %s when using the search plugin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/search.pm:58
+msgid "cleaning hyperestraier search index"
+msgstr ""
+
+#: ../IkiWiki/Plugin/search.pm:64
+msgid "updating hyperestraier search index"
+msgstr ""
+
+#: ../IkiWiki/Plugin/shortcut.pm:24
+msgid "shortcut missing name or url parameter"
+msgstr ""
+
+#: ../IkiWiki/Plugin/shortcut.pm:30
+#, perl-format
+msgid "shortcut %s points to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/smiley.pm:22
+msgid "failed to parse any smileys, disabling plugin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/template.pm:19
+msgid "template missing id parameter"
+msgstr ""
+
+#: ../IkiWiki/Plugin/template.pm:26
+#, perl-format
+msgid "template %s not found"
+msgstr ""
+
+#: ../IkiWiki/Plugin/template.pm:45
+msgid "template failed to process:"
+msgstr ""
+
+#: ../IkiWiki/Rcs/Stub.pm:66
+msgid "getctime not implemented"
+msgstr ""
+
+#: ../IkiWiki/Rcs/svn.pm:206
+msgid ""
+"REV is not set, not running from svn post-commit hook, cannot send "
+"notifications"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:97
+msgid "Discussion"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:227 ../IkiWiki/Render.pm:247
+#, perl-format
+msgid "skipping bad filename %s"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:287
+#, perl-format
+msgid "removing old page %s"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:306
+#, perl-format
+msgid "scanning %s"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:315
+#, perl-format
+msgid "rendering %s"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:327
+#, perl-format
+msgid "rendering %s, which links to %s"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:344
+#, perl-format
+msgid "rendering %s, which depends on %s"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:382
+#, perl-format
+msgid "rendering %s, to update its backlinks"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:394
+#, perl-format
+msgid "removing %s, no longer rendered by %s"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:420
+#, perl-format
+msgid "ikiwiki: cannot render %s"
+msgstr ""
+
+#: ../IkiWiki/Setup.pm:13
+#, perl-format
+msgid "cannot read %s: %s"
+msgstr ""
+
+#: ../IkiWiki/Setup/Standard.pm:38
+msgid "generating wrappers.."
+msgstr ""
+
+#: ../IkiWiki/Setup/Standard.pm:74
+msgid "rebuilding wiki.."
+msgstr ""
+
+#: ../IkiWiki/Setup/Standard.pm:77
+msgid "refreshing wiki.."
+msgstr ""
+
+#: ../IkiWiki/Setup/Standard.pm:86
+msgid "done"
+msgstr ""
+
+#: ../IkiWiki/UserInfo.pm:135
+#, perl-format
+msgid "update of %s's %s by %s"
+msgstr ""
+
+#: ../IkiWiki/Wrapper.pm:16
+#, perl-format
+msgid "%s doesn't seem to be executable"
+msgstr ""
+
+#: ../IkiWiki/Wrapper.pm:20
+msgid "cannot create a wrapper that uses a setup file"
+msgstr ""
+
+#: ../IkiWiki/Wrapper.pm:24
+msgid "wrapper filename not specified"
+msgstr ""
+
+#: ../IkiWiki/Wrapper.pm:62
+#, perl-format
+msgid "failed to write %s: %s"
+msgstr ""
+
+#: ../IkiWiki/Wrapper.pm:97
+#, perl-format
+msgid "failed to compile %s"
+msgstr ""
+
+#: ../IkiWiki/Wrapper.pm:104
+#, perl-format
+msgid "successfully generated %s\n"
+msgstr ""
+
+#: ../ikiwiki.in:13
+msgid "usage: ikiwiki [options] source dest"
+msgstr ""
+
+#: ../IkiWiki.pm:99
+msgid "Must specify url to wiki with --url when using --cgi"
+msgstr ""
+
+#: ../IkiWiki.pm:142 ../IkiWiki.pm:143
+msgid "Error"
+msgstr ""
+
+#: ../IkiWiki.pm:514
+#, perl-format
+msgid "%s preprocessing loop detected on %s at depth %i"
+msgstr ""
--
2.26.2