From 912521ef0711204965aa2319d41c7741bd3f4f4c Mon Sep 17 00:00:00 2001 From: joey Date: Fri, 29 Dec 2006 04:38:40 +0000 Subject: [PATCH] * Initial work on internationalization of the program code. po/ikiwiki.pot is available for translation. * Export gettext() from IkiWiki module. --- IkiWiki.pm | 24 +- IkiWiki/CGI.pm | 22 +- IkiWiki/Plugin/aggregate.pm | 26 +- IkiWiki/Plugin/brokenlinks.pm | 2 +- IkiWiki/Plugin/fortune.pm | 2 +- IkiWiki/Plugin/googlecalendar.pm | 2 +- IkiWiki/Plugin/img.pm | 2 - IkiWiki/Plugin/inline.pm | 10 +- IkiWiki/Plugin/linkmap.pm | 2 +- IkiWiki/Plugin/mdwn.pm | 2 +- IkiWiki/Plugin/mirrorlist.pm | 4 +- IkiWiki/Plugin/openid.pm | 4 +- IkiWiki/Plugin/orphans.pm | 2 +- IkiWiki/Plugin/passwordauth.pm | 10 +- IkiWiki/Plugin/poll.pm | 4 +- IkiWiki/Plugin/polygen.pm | 6 +- IkiWiki/Plugin/search.pm | 6 +- IkiWiki/Plugin/shortcut.pm | 4 +- IkiWiki/Plugin/smiley.pm | 2 +- IkiWiki/Plugin/template.pm | 11 +- IkiWiki/Rcs/Stub.pm | 2 +- IkiWiki/Rcs/svn.pm | 2 +- IkiWiki/Render.pm | 26 +- IkiWiki/Setup.pm | 2 +- IkiWiki/Setup/Standard.pm | 8 +- IkiWiki/UserInfo.pm | 15 +- IkiWiki/Wrapper.pm | 12 +- Makefile.PL | 6 +- debian/changelog | 3 + debian/control | 2 +- ...hardcoded___34__Discussion__34___link.mdwn | 6 +- doc/install.mdwn | 2 +- doc/patchqueue/l10n.mdwn | 48 +-- doc/plugins/write.mdwn | 4 + doc/translation.mdwn | 32 ++ ikiwiki.in | 2 +- po/Makefile | 44 +++ po/ikiwiki.pot | 358 ++++++++++++++++++ 38 files changed, 575 insertions(+), 146 deletions(-) create mode 100644 doc/translation.mdwn create mode 100644 po/Makefile create mode 100644 po/ikiwiki.pot diff --git a/IkiWiki.pm b/IkiWiki.pm index b6a2a3649..faca32835 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -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", "

Error: @_

"); + print misctemplate(gettext("Error"), + "

".gettext("Error").": @_

"); } 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; diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm index a41349be5..511358ff5 100644 --- a/IkiWiki/CGI.pm +++ b/IkiWiki/CGI.pm @@ -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; } diff --git a/IkiWiki/Plugin/aggregate.pm b/IkiWiki/Plugin/aggregate.pm index 2a3f36fce..46cd3102c 100644 --- a/IkiWiki/Plugin/aggregate.pm +++ b/IkiWiki/Plugin/aggregate.pm @@ -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 "{url}."\">".$feed->{name}.": ". ($feed->{error} ? "" : "").$feed->{message}. ($feed->{error} ? "" : ""). - " (".$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}; diff --git a/IkiWiki/Plugin/brokenlinks.pm b/IkiWiki/Plugin/brokenlinks.pm index 6741f9081..e79ce1d81 100644 --- a/IkiWiki/Plugin/brokenlinks.pm +++ b/IkiWiki/Plugin/brokenlinks.pm @@ -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 "\n"; } # }}} diff --git a/IkiWiki/Plugin/fortune.pm b/IkiWiki/Plugin/fortune.pm index 4ff343e3a..3bab134be 100644 --- a/IkiWiki/Plugin/fortune.pm +++ b/IkiWiki/Plugin/fortune.pm @@ -15,7 +15,7 @@ sub preprocess (@) { #{{{ my $f = `fortune 2>/dev/null`; if ($?) { - return "[[fortune failed]]"; + return "[[".gettext("fortune failed")."]]"; } else { return "
$f
\n"; diff --git a/IkiWiki/Plugin/googlecalendar.pm b/IkiWiki/Plugin/googlecalendar.pm index dc0df0ad3..7620384f5 100644 --- a/IkiWiki/Plugin/googlecalendar.pm +++ b/IkiWiki/Plugin/googlecalendar.pm @@ -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+)"#; diff --git a/IkiWiki/Plugin/img.pm b/IkiWiki/Plugin/img.pm index 20893f56c..120326910 100644 --- a/IkiWiki/Plugin/img.pm +++ b/IkiWiki/Plugin/img.pm @@ -8,8 +8,6 @@ use strict; use IkiWiki; use Image::Magick; -my $convert = 'convert'; - my %imgdefaults; sub import { #{{{ diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index 70b353ec5..eb21959f9 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -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("Can’t 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(); diff --git a/IkiWiki/Plugin/linkmap.pm b/IkiWiki/Plugin/linkmap.pm index d7dffc941..e0c5fb475 100644 --- a/IkiWiki/Plugin/linkmap.pm +++ b/IkiWiki/Plugin/linkmap.pm @@ -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; diff --git a/IkiWiki/Plugin/mdwn.pm b/IkiWiki/Plugin/mdwn.pm index 625f77f21..c087f2b41 100644 --- a/IkiWiki/Plugin/mdwn.pm +++ b/IkiWiki/Plugin/mdwn.pm @@ -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; } } diff --git a/IkiWiki/Plugin/mirrorlist.pm b/IkiWiki/Plugin/mirrorlist.pm index 104587f3a..216d870fd 100644 --- a/IkiWiki/Plugin/mirrorlist.pm +++ b/IkiWiki/Plugin/mirrorlist.pm @@ -19,8 +19,8 @@ sub pagetemplate (@) { #{{{ sub mirrorlist ($) { #{{{ my $page=shift; - return "

Mirror". - (keys %{$config{mirrorlist}} > 1 ? "s" : ""). + return "

". + (keys %{$config{mirrorlist}} > 1 ? gettext("Mirrors") : gettext("Mirror")). ": ". join(", ", map { diff --git a/IkiWiki/Plugin/openid.pm b/IkiWiki/Plugin/openid.pm index 75f13f878..f43c4db7f 100644 --- a/IkiWiki/Plugin/openid.pm +++ b/IkiWiki/Plugin/openid.pm @@ -33,8 +33,8 @@ sub formbuilder_setup (@) { #{{{ label => "OpenID", size => 30, comment => '('. - htmllink("", "", "OpenID", 1, 0, "What's this?") - .($config{openidsignup} ? " | Get an OpenID" : "") + htmllink("", "", "OpenID", 1, 0, gettext("What's this?")) + .($config{openidsignup} ? " | ".gettext("Get an OpenID")."" : "") .')' ); diff --git a/IkiWiki/Plugin/orphans.pm b/IkiWiki/Plugin/orphans.pm index 3a8a7954f..6ba37615e 100644 --- a/IkiWiki/Plugin/orphans.pm +++ b/IkiWiki/Plugin/orphans.pm @@ -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 "

\n"; } # }}} diff --git a/IkiWiki/Plugin/passwordauth.pm b/IkiWiki/Plugin/passwordauth.pm index 1aac17a9e..7ffc12080 100644 --- a/IkiWiki/Plugin/passwordauth.pm +++ b/IkiWiki/Plugin/passwordauth.pm @@ -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"; } diff --git a/IkiWiki/Plugin/poll.pm b/IkiWiki/Plugin/poll.pm index c040deb76..a3321a32e 100644 --- a/IkiWiki/Plugin/poll.pm +++ b/IkiWiki/Plugin/poll.pm @@ -61,7 +61,7 @@ sub preprocess (@) { #{{{ $ret.="\n"; $ret.="\n"; $ret.="\n"; - $ret.="\n"; + $ret.="\n"; } $ret.="

\n
\n"; if ($open && exists $config{cgiurl}) { @@ -69,7 +69,7 @@ sub preprocess (@) { #{{{ } } if ($showtotal) { - $ret.="Total votes: $total\n"; + $ret.="".gettext("Total votes:")." $total\n"; } return "
$ret
"; } # }}} 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.32.0.93.g670b81a890