* Initial work on internationalization of the program code. po/ikiwiki.pot
authorjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Fri, 29 Dec 2006 04:38:40 +0000 (04:38 +0000)
committerjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Fri, 29 Dec 2006 04:38:40 +0000 (04:38 +0000)
  is available for translation.
* Export gettext() from IkiWiki module.

38 files changed:
IkiWiki.pm
IkiWiki/CGI.pm
IkiWiki/Plugin/aggregate.pm
IkiWiki/Plugin/brokenlinks.pm
IkiWiki/Plugin/fortune.pm
IkiWiki/Plugin/googlecalendar.pm
IkiWiki/Plugin/img.pm
IkiWiki/Plugin/inline.pm
IkiWiki/Plugin/linkmap.pm
IkiWiki/Plugin/mdwn.pm
IkiWiki/Plugin/mirrorlist.pm
IkiWiki/Plugin/openid.pm
IkiWiki/Plugin/orphans.pm
IkiWiki/Plugin/passwordauth.pm
IkiWiki/Plugin/poll.pm
IkiWiki/Plugin/polygen.pm
IkiWiki/Plugin/search.pm
IkiWiki/Plugin/shortcut.pm
IkiWiki/Plugin/smiley.pm
IkiWiki/Plugin/template.pm
IkiWiki/Rcs/Stub.pm
IkiWiki/Rcs/svn.pm
IkiWiki/Render.pm
IkiWiki/Setup.pm
IkiWiki/Setup/Standard.pm
IkiWiki/UserInfo.pm
IkiWiki/Wrapper.pm
Makefile.PL
debian/changelog
debian/control
doc/bugs/hardcoded___34__Discussion__34___link.mdwn
doc/install.mdwn
doc/patchqueue/l10n.mdwn
doc/plugins/write.mdwn
doc/translation.mdwn [new file with mode: 0644]
ikiwiki.in
po/Makefile [new file with mode: 0644]
po/ikiwiki.pot [new file with mode: 0644]

index b6a2a3649d83a608b1ea41e4d7d46695f0219460..faca32835b095f7c428b3f74d0aabddc25b59d1c 100644 (file)
@@ -14,7 +14,7 @@ use vars qw{%config %links %oldlinks %oldpagemtime %pagectime %pagecase
 use Exporter q{import};
 our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match
                  bestlink htmllink readfile writefile pagetype srcfile pagename
-                 displaytime will_render
+                 displaytime will_render gettext
                  %config %links %renderedfiles %pagesources);
 our $VERSION = 1.01; # plugin interface version
 
@@ -96,7 +96,7 @@ sub checkconfig () { #{{{
        }
 
        if ($config{cgi} && ! length $config{url}) {
-               error("Must specify url to wiki with --url when using --cgi\n");
+               error(gettext("Must specify url to wiki with --url when using --cgi"));
        }
        
        $config{wikistatedir}="$config{srcdir}/.ikiwiki"
@@ -139,7 +139,8 @@ sub loadplugin ($) { #{{{
 sub error ($) { #{{{
        if ($config{cgi}) {
                print "Content-type: text/html\n\n";
-               print misctemplate("Error", "<p>Error: @_</p>");
+               print misctemplate(gettext("Error"),
+                       "<p>".gettext("Error").": @_</p>");
        }
        log_message(error => @_);
        exit(1);
@@ -510,7 +511,9 @@ sub preprocess ($$$;$) { #{{{
                        if ($preprocessing{$page}++ > 3) {
                                # Avoid loops of preprocessed pages preprocessing
                                # other pages that preprocess them, etc.
-                               return "[[$command preprocessing loop detected on $page at depth $preprocessing{$page}]]";
+                               return "[[".sprintf(gettext("%s preprocessing loop detected on %s at depth %i"),
+                                       $command, $page, $preprocessing{$page}).
+                               "]]";
                        }
                        my $ret=$hooks{preprocess}{$command}{call}->(
                                @params,
@@ -803,6 +806,19 @@ sub file_pruned ($$) { #{{{
        $file =~ m/$regexp/;
 } #}}}
 
+sub gettext { #{{{
+       # Only use gettext in the rare cases it's needed.
+       # This overrides future calls of this function.
+       if (exists $ENV{LANG} || exists $ENV{LC_ALL} || exists $ENV{LC_MESSAGES}) {
+               eval q{use Locale::gettext};
+               textdomain('ikiwiki');
+               return Locale::gettext::gettext(shift);
+       }
+       else {
+               return shift;
+       }
+} #}}}
+
 sub pagespec_match ($$) { #{{{
        my $page=shift;
        my $spec=shift;
index a41349be518a648fa9f71cd5df83b4810a3ce98c..511358ff55046157cfd7635800153d9c19f5dbb6 100644 (file)
@@ -45,8 +45,10 @@ sub page_locked ($$;$) { #{{{
                my $locked_pages=userinfo_get($admin, "locked_pages");
                if (pagespec_match($page, userinfo_get($admin, "locked_pages"))) {
                        return 1 if $nonfatal;
-                       error(htmllink("", "", $page, 1)." is locked by ".
-                             userlink($admin)." and cannot be edited.");
+
+                       error(sprintf(gettext("%s is locked by %s and cannot be edited"),
+                               htmllink("", "", $page, 1),
+                               userlink($admin)));
                }
        }
 
@@ -134,7 +136,7 @@ sub cgi_signin ($$) { #{{{
        $form->field(name => "do", type => "hidden");
        
        if ($q->param("do") ne "signin" && !$form->submitted) {
-               $form->text("You need to log in first.");
+               $form->text(gettext("You need to log in first."));
        }
        
        run_hooks(formbuilder_setup => sub {
@@ -242,7 +244,7 @@ sub cgi_prefs ($$) { #{{{
                redirect($q, $config{url});
                return;
        }
-       elsif ($form->submitted eq "Save Preferences" && $form->validate) {
+       elsif ($form->submitted eq 'Save Preferences' && $form->validate) {
                foreach my $field (qw(email subscriptions locked_pages)) {
                        if (defined $form->field($field) && length $form->field($field)) {
                                userinfo_set($user_name, $field, $form->field($field)) || error("failed to set $field");
@@ -252,7 +254,7 @@ sub cgi_prefs ($$) { #{{{
                        set_banned_users(grep { ! is_admin($_) }
                                        split(' ', $form->field("banned_users")));
                }
-               $form->text("Preferences saved.");
+               $form->text(gettext("Preferences saved."));
        }
        
        if (exists $hooks{formbuilder}) {
@@ -403,7 +405,7 @@ sub cgi_editpage ($$) { #{{{
                                $dir=~s![^/]+/+$!!;
                                
                                if ((defined $form->field('subpage') && length $form->field('subpage')) ||
-                                   $page eq 'discussion') {
+                                   $page eq gettext('discussion')) {
                                        $best_loc="$from/$page";
                                }
                                else {
@@ -440,7 +442,7 @@ sub cgi_editpage ($$) { #{{{
                                options => \@page_locs, value => $best_loc);
                        $form->field(name => "type", type => 'select',
                                options => \@page_types);
-                       $form->title("creating ".pagetitle($page));
+                       $form->title(sprintf(gettext("creating %s"), pagetitle($page)));
                }
                elsif ($form->field("do") eq "edit") {
                        page_locked($page, $session);
@@ -457,7 +459,7 @@ sub cgi_editpage ($$) { #{{{
                        $form->tmpl_param("page_select", 0);
                        $form->field(name => "page", type => 'hidden');
                        $form->field(name => "type", type => 'hidden');
-                       $form->title("editing ".pagetitle($page));
+                       $form->title(sprintf(gettext("editing %s"), pagetitle($page)));
                }
                
                print $form->render(submit => \@buttons);
@@ -500,7 +502,7 @@ sub cgi_editpage ($$) { #{{{
                                $form->tmpl_param("page_select", 0);
                                $form->field(name => "page", type => 'hidden');
                                $form->field(name => "type", type => 'hidden');
-                               $form->title("editing $page");
+                               $form->title(sprintf(gettext("editing %s"), $page));
                                print $form->render(submit => \@buttons);
                                return;
                        }
@@ -617,7 +619,7 @@ sub cgi (;$$) { #{{{
        if (defined $session->param("name") && userinfo_get($session->param("name"), "banned")) {
                print $q->header(-status => "403 Forbidden");
                $session->delete();
-               print "You are banned.";
+               print gettext("You are banned.");
                cgi_savesession($session);
                exit;
        }
index 2a3f36fcebd07be205075b81e57c49737ce35d74..46cd3102c5d5064f15229f0a2e3ab03f675e0c9f 100644 (file)
@@ -58,7 +58,7 @@ sub preprocess (@) { #{{{
 
        foreach my $required (qw{name url}) {
                if (! exists $params{$required}) {
-                       return "[[aggregate plugin missing $required parameter]]";
+                       return "[[".sprintf(gettext("aggregate plugin missing %s parameter"), $required)."]]";
                }
        }
 
@@ -86,7 +86,7 @@ sub preprocess (@) { #{{{
        $feed->{lastupdate}=0 unless defined $feed->{lastupdate};
        $feed->{numposts}=0 unless defined $feed->{numposts};
        $feed->{newposts}=0 unless defined $feed->{newposts};
-       $feed->{message}="new feed" unless defined $feed->{message};
+       $feed->{message}=gettext("new feed") unless defined $feed->{message};
        $feed->{error}=0 unless defined $feed->{error};
        $feed->{tags}=[];
        while (@_) {
@@ -100,8 +100,9 @@ sub preprocess (@) { #{{{
        return "<a href=\"".$feed->{url}."\">".$feed->{name}."</a>: ".
               ($feed->{error} ? "<em>" : "").$feed->{message}.
               ($feed->{error} ? "</em>" : "").
-              " (".$feed->{numposts}." posts".
-              ($feed->{newposts} ? "; ".$feed->{newposts}." new" : "").
+              " (".$feed->{numposts}." ".gettext("posts").
+              ($feed->{newposts} ? "; ".$feed->{newposts}.
+                                   " ".gettext("new") : "").
               ")";
 } # }}}
 
@@ -202,13 +203,14 @@ sub expire () { #{{{
                        if ($feed->{expireage}) {
                                my $days_old = (time - $IkiWiki::pagectime{$item->{page}}) / 60 / 60 / 24;
                                if ($days_old > $feed->{expireage}) {
-                                       debug("expiring ".$item->{page}." ($days_old days old)");
+                                       debug(sprintf(gettext("expiring %s (%s days old)"),
+                                               $item->{page}, $days_old));
                                        $item->{expired}=1;
                                }
                        }
                        elsif ($feed->{expirecount} &&
                               $count >= $feed->{expirecount}) {
-                               debug("expiring ".$item->{page});
+                               debug(sprintf(gettext("expiring %s"), $item->{page}));
                                $item->{expired}=1;
                        }
                        else {
@@ -231,12 +233,12 @@ sub aggregate () { #{{{
                $feed->{newposts}=0;
                $IkiWiki::forcerebuild{$feed->{sourcepage}}=1;
 
-               debug("checking feed ".$feed->{name}." ...");
+               debug(sprintf(gettext("checking feed %s ..."), $feed->{name}));
 
                if (! length $feed->{feedurl}) {
                        my @urls=XML::Feed->find_feeds($feed->{url});
                        if (! @urls) {
-                               $feed->{message}="could not find feed at ".$feed->{feedurl};
+                               $feed->{message}=sprintf(gettext("could not find feed at %s"), $feed->{feedurl});
                                $feed->{error}=1;
                                debug($feed->{message});
                                next;
@@ -245,7 +247,7 @@ sub aggregate () { #{{{
                }
                my $f=eval{XML::Feed->parse(URI->new($feed->{feedurl}))};
                if ($@) {
-                       $feed->{message}="feed crashed XML::Feed! $@";
+                       $feed->{message}=gettext("feed crashed XML::Feed!")." ($@)";
                        $feed->{error}=1;
                        debug($feed->{message});
                        next;
@@ -268,8 +270,8 @@ sub aggregate () { #{{{
                        );
                }
 
-               $feed->{message}="processed ok at ".
-                       displaytime($feed->{lastupdate});
+               $feed->{message}=sprintf(gettext("processed ok at "),
+                       displaytime($feed->{lastupdate}));
                $feed->{error}=0;
        }
 } #}}}
@@ -309,7 +311,7 @@ sub add_page (@) { #{{{
                        $c++
                }
                $guid->{page}=$page;
-               debug("creating new page $page");
+               debug(sprintf(gettext("creating new page %s"), $page));
        }
        $guid->{feed}=$feed->{name};
        
index 6741f90817dca6895ab1eae90f898c4fd4c40176..e79ce1d810ec09e5591e49357e897c82405249d6 100644 (file)
@@ -33,7 +33,7 @@ sub preprocess (@) { #{{{
                }
        }
        
-       return "There are no broken links!" unless @broken;
+       return gettext("There are no broken links!") unless @broken;
        my %seen;
        return "<ul>\n".join("\n", map { "<li>$_</li>" } grep { ! $seen{$_}++ } sort @broken)."</ul>\n";
 } # }}}
index 4ff343e3a0c891f5e7b0fd7019706f946d16be61..3bab134bed8e8d4bf152dee04bbff1bdb42a9727 100644 (file)
@@ -15,7 +15,7 @@ sub preprocess (@) { #{{{
        my $f = `fortune 2>/dev/null`;
 
        if ($?) {
-               return "[[fortune failed]]";
+               return "[[".gettext("fortune failed")."]]";
        }
        else {
                return "<pre>$f</pre>\n";
index dc0df0ad3ff6d523571366b651a8f171e3799698..7620384f52d9a2bf3c724418d4c401233993c0d0 100644 (file)
@@ -19,7 +19,7 @@ sub preprocess (@) { #{{{
        # Avoid XSS attacks..
        my ($url)=$params{html}=~m#iframe\s+src="http://www\.google\.com/calendar/embed\?([^"<>]+)"#;
        if (! defined $url || ! length $url) {
-               return "[[googlecalendar failed to find url in html]]";
+               return "[[".gettext("googlecalendar failed to find url in html")."]]";
        }
        my ($height)=$params{html}=~m#height="(\d+)"#;
        my ($width)=$params{html}=~m#width="(\d+)"#;
index 20893f56c284812783c2ab31f699b9ae4a8b9473..120326910988e4a2457b16268a89a79b7349e7e5 100644 (file)
@@ -8,8 +8,6 @@ use strict;
 use IkiWiki;
 use Image::Magick;
 
-my $convert = 'convert';
-
 my %imgdefaults;
 
 sub import { #{{{
index 70b353ec5ef5970852677cf8ae02e4070641fdf4..eb21959f90120ff2b463eedd8ae3da1416858f8c 100644 (file)
@@ -34,7 +34,7 @@ sub getopt () { #{{{
 
 sub checkconfig () { #{{{
        if (($config{rss} || $config{atom}) && ! length $config{url}) {
-               error("Must specify url to wiki with --url when using --rss or --atom");
+               error(gettext("Must specify url to wiki with --url when using --rss or --atom"));
        }
        if ($config{rss}) {
                push @{$config{wiki_file_prune_regexps}}, qr/\.rss$/;
@@ -94,7 +94,7 @@ sub preprocess_inline (@) { #{{{
                @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
        }
        else {
-               return "unknown sort type $params{sort}";
+               return sprintf(gettext("unknown sort type %s"), $params{sort});
        }
 
        if (exists $params{skip}) {
@@ -365,7 +365,7 @@ sub pingurl (@) { #{{{
 
        eval q{require RPC::XML::Client};
        if ($@) {
-               debug("RPC::XML::Client not found, not pinging");
+               debug(gettext("RPC::XML::Client not found, not pinging"));
                return;
        }
 
@@ -373,11 +373,11 @@ sub pingurl (@) { #{{{
        defined(my $pid = fork) or error("Can't fork: $!");
        return if $pid;
        chdir '/';
-       eval q{use POSIX ’setsid’};
+       eval q{use POSIX 'setsid'};
        setsid() or error("Can't start a new session: $!");
        open STDIN, '/dev/null';
        open STDOUT, '>/dev/null';
-       open STDERR, '>&STDOUT' or error("Cant dup stdout: $!");
+       open STDERR, '>&STDOUT' or error("Can't dup stdout: $!");
 
        # Don't need to keep a lock on the wiki as a daemon.
        IkiWiki::unlockwiki();
index d7dffc941d93c828ca22ea091ebdde6062af26d2..e0c5fb475748c2bed09a4095acb061460143dc6b 100644 (file)
@@ -96,7 +96,7 @@ sub genmap ($) { #{{{
        waitpid $pid, 0;
        $SIG{PIPE}="DEFAULT";
        if ($sigpipe) {
-               return  "[[linkmap failed to run dot]]";
+               return  "[[".gettext("linkmap failed to run dot")."]]";
        }
 
        return $ret;
index 625f77f2121aa73b1b29e471bc1828592c260898..c087f2b41309f892e52476305bf31ccc48fb7840 100644 (file)
@@ -34,7 +34,7 @@ sub htmlize (@) { #{{{
                        }
                        else {
                                do "/usr/bin/markdown" ||
-                                       error("failed to load Markdown.pm perl module ($@) or /usr/bin/markdown ($!)");
+                                       error(sprintf(gettext("failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"), $@, $!));
                                $markdown_sub=\&Markdown::Markdown;
                        }
                }
index 104587f3a881ab8526ce79ef9c762d3624fe32af..216d870fda45e0e5e257ad08c403c1ce2adb0619 100644 (file)
@@ -19,8 +19,8 @@ sub pagetemplate (@) { #{{{
 
 sub mirrorlist ($) { #{{{
        my $page=shift;
-       return "<p>Mirror".
-               (keys %{$config{mirrorlist}} > 1 ? "s" : "").
+       return "<p>".
+               (keys %{$config{mirrorlist}} > 1 ? gettext("Mirrors") : gettext("Mirror")).
                ": ".
                join(", ",
                        map { 
index 75f13f878626e5b86cf632e13053170aa03facdb..f43c4db7ffc8806f1ba09e79c6d09757f6aa8484 100644 (file)
@@ -33,8 +33,8 @@ sub formbuilder_setup (@) { #{{{
                        label => "OpenID",
                        size => 30,
                        comment => '('.
-                               htmllink("", "", "OpenID", 1, 0, "What's this?")
-                               .($config{openidsignup} ? " | <a href=\"$config{openidsignup}\">Get an OpenID</a>" : "")
+                               htmllink("", "", "OpenID", 1, 0, gettext("What's this?"))
+                               .($config{openidsignup} ? " | <a href=\"$config{openidsignup}\">".gettext("Get an OpenID")."</a>" : "")
                                .')'
                );
 
index 3a8a7954fe1dd6e5c49b5ba12a7f5ec6557e6fa6..6ba37615e08cbffcd0f1a4169e75bb47ca47db70 100644 (file)
@@ -38,7 +38,7 @@ sub preprocess (@) { #{{{
                push @orphans, $page;
        }
        
-       return "All pages are linked to by other pages." unless @orphans;
+       return gettext("All pages are linked to by other pages.") unless @orphans;
        return "<ul>\n".join("\n", map { "<li>".htmllink($params{page}, $params{destpage}, $_, 1)."</li>" } sort @orphans)."</ul>\n";
 } # }}}
 
index 1aac17a9ebcf326f48771799c06826076b28566a..7ffc12080cdc6135dc64600f279135a7f7c1deb4 100644 (file)
@@ -101,7 +101,7 @@ sub formbuilder_setup (@) { #{{{
                }
                else {
                        # First time settings.
-                       $form->field(name => "name", comment => "(use FirstnameLastName)");
+                       $form->field(name => "name", comment => gettext("(use FirstnameLastName)"));
                        if ($session->param("name")) {
                                $form->field(name => "name", value => $session->param("name"));
                        }
@@ -141,10 +141,10 @@ sub formbuilder (@) { #{{{
                                        'regdate' => time})) {
                                        $form->field(name => "confirm_password", type => "hidden");
                                        $form->field(name => "email", type => "hidden");
-                                       $form->text("Account creation successful. Now you can Login.");
+                                       $form->text(gettext("Account creation successful. Now you can Login."));
                                }
                                else {
-                                       error("Error creating account.");
+                                       error(gettext("Error creating account."));
                                }
                        }
                        elsif ($form->submitted eq 'Mail Password') {
@@ -165,9 +165,9 @@ sub formbuilder (@) { #{{{
                                        From => "$config{wikiname} admin <$config{adminemail}>",
                                        Subject => "$config{wikiname} information",
                                        Message => $template->output,
-                               ) or error("Failed to send mail");
+                               ) or error(gettext("Failed to send mail"));
                        
-                               $form->text("Your password has been emailed to you.");
+                               $form->text(gettext("Your password has been emailed to you."));
                                $form->field(name => "name", required => 0);
                                push @$buttons, "Mail Password";
                        }
index c040deb7622cbaa71cc9ecb6f2427aa28e3832fa..a3321a32e51d57d898facca21ce50f143ea028f6 100644 (file)
@@ -61,7 +61,7 @@ sub preprocess (@) { #{{{
                        $ret.="<input type=\"hidden\" name=\"num\" value=\"$pagenum{$params{page}}\" />\n";
                        $ret.="<input type=\"hidden\" name=\"page\" value=\"$params{page}\" />\n";
                        $ret.="<input type=\"hidden\" name=\"choice\" value=\"$choice\" />\n";
-                       $ret.="<input type=\"submit\" value=\"vote\" />\n";
+                       $ret.="<input type=\"submit\" value=\"".gettext("vote")."\" />\n";
                }
                $ret.="</p>\n<hr class=poll align=left width=\"$percent%\"/>\n";
                if ($open && exists $config{cgiurl}) {
@@ -69,7 +69,7 @@ sub preprocess (@) { #{{{
                }
        }
        if ($showtotal) {
-               $ret.="<span>Total votes: $total</span>\n";
+               $ret.="<span>".gettext("Total votes:")." $total</span>\n";
        }
        return "<div class=poll>$ret</div>";
 } # }}}
index 966b6cb51d5a9bda7015935ff63a52ff0aa83c20..63f6bf5db59b7ad94987ca620fcda7ae837e973d 100644 (file)
@@ -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;
index 942b9498634042b7c62707746bdaeb7b80a79e1a..1b5c66716f90faaff3fd36d26d909cce5d1710d7 100644 (file)
@@ -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}."/".$_)
index e4a9ab1a6647455267a422f101666e26c8ae3a96..9479306a8c37d4558b05cead14ee47119c9477e9 100644 (file)
@@ -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 ($$@) { #{{{
index 0c6f5d4272cba5fb8aff8ea68bf76935fca0b299..85a719337518fc3443b501318ce54ec3847af63b 100644 (file)
@@ -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;
        }
        
index 09570560420e649a5e1a1e3f588f146f28aa5579..23d9d65d88835c12f81ea27134221965f89754dc 100644 (file)
@@ -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) {
index 087f2508c3cc1b218d09d876da9515d4a29d6a59..03757758aa2fc3815223430848b8bfac9bdd8fcc 100644 (file)
@@ -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
index 848dfac3a805f16adc65e1f46d7a1c11754cc70a..30020c1fcc23958c9ad4a25fb8b5bb5ac123ca2e 100644 (file)
@@ -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}));
        
index 678075b821178b089ea7c4dab27874a5e15647c2..30249b9bd1e6dfef00af3bfc1a4e0815bbbf9ac0 100644 (file)
@@ -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;
index 2b4c76bd0b228539cb94feb69fba97435fff9833..560bc798bf4cd03da85e16eeb97aeed4d72125a5 100644 (file)
@@ -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;
index 77c164e34a61f6cac39e7acb16f331aedfd21878..1e65b23e3bf5a42e5e102a2bf331b39e933b6185 100644 (file)
@@ -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();
 }
 
index d48b8071cc3082ea09efad02e1e7c75e32a3b37a..03d63cc23376722cee7663828e91e69b0fb79030 100644 (file)
@@ -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("Cant 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
index a3ecccd5be131b3e745a8d79db869f84a5acf1a9..e761085fb8d54cad74fdd41fe29071e93cac5c0d 100644 (file)
@@ -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
index a6292a4223e50b6797b6c541871276d8e08d64df..e0eaf4e32b56f97f6b3c9a5b74794fd69bbd3af5 100755 (executable)
@@ -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
 }
 }
 
index e455be1a33393be0123953acb03519c99c7afc77..a607476fc2d63203485cb78633761c1177823e72 100644 (file)
@@ -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 <joeyh@debian.org>  Thu, 28 Dec 2006 17:13:43 -0500
 
index 279f9319997ed97c7f1d5db26a12f1122bff172b..d29a03846a7545b8ce4b1ba8d6e03ac971805262 100644 (file)
@@ -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
index fc8406d8704c000cbb569f13bbf5b5fc61656e36..4436f71019d8ebdf00336a0a302247543672fc81 100644 (file)
@@ -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]]
index 04600b17f77717793eb66228433f341de9a25ff6..d9c2a79f7369bf4dba579e70d646725d0b0f4498 100644 (file)
@@ -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.
 
index 85e4f21e2f0a9a45e3ccb7658d3d270d7a6ae189..3369bec117f2d01db544f65d6575f84abe808715 100644 (file)
@@ -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, <TMPL_VAR WIKINAME>[2] üzerindeki
 bulundu. Parola: <TMPL_VAR USER_PASSWORD> -- ikiwiki [1] Parolayı isteyen
 kullanıcının ait IP adresi: <TMPL_VAR REMOTE_ADDR>[2] <TMPL_VAR WIKIURL>
 
-----
-
-> 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):
-
-    <TMPL_IF NAME="BUTTONS">
-    Save Page, Preview, Cancel
-    </TMPL_IF>
-
-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]]
index f808d2e1e089ac412cbabbc2a379e465ca19cbf4..6c475024a2adf45576895be5cbeded1355f97f85 100644 (file)
@@ -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 (file)
index 0000000..4f7bf34
--- /dev/null
@@ -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.
index d18970d0f931bbb7975552bea63b9e7a88a59eb3..11d562523807ea448c73ff81898d30341804830f 100755 (executable)
@@ -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 (file)
index 0000000..fa129de
--- /dev/null
@@ -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 (file)
index 0000000..bc4d7a9
--- /dev/null
@@ -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 <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\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 ""