]> sipb.mit.edu Git - ikiwiki.git/blob - doc/patchqueue/locale_patch.mdwn
* Match 'web commit from' in SVN and git, these are web commits too.
[ikiwiki.git] / doc / patchqueue / locale_patch.mdwn
1 From [[Faidon]]:
2
3 Joey,
4 Attached is a patch that adds locale support to ikiwiki.
5 A suitable locale is choosed in that order:
6 1) $config{locale}
7 2) $ENV{LC_ALL}
8 3) en_US.UTF-8
9 4) en_*.UTF-8
10 5) *.UTF-8
11 5) en_US
12 6) en_*
13 7) *
14 8) POSIX
15 (where * == the first item found)
16
17 The patch brings the following functionality:
18 a) Proper local time, either using a UTF-8 locale or not (by the means
19 of a new function decode_locale),
20 b) Support for UTF-8 (or ISO-8859-X) filenames in SVN. Before this
21 patch, commiting (or even rcs_updating) on repositories with UTF-8
22 filenames is impossible.
23
24 This is RFC because it has some hard-coded parts: 'locale -a' and
25 /usr/share/i18n/SUPPORTED. They obviously work on Debian, but I'm sure
26 they won't work on other distros, let along on other operating systems.
27
28 Besides that, it's quite a big of a change and I could use some comments
29 to make it better :)
30
31         Index: IkiWiki/Rcs/svn.pm
32         ===================================================================
33         --- IkiWiki/Rcs/svn.pm  (revision 904)
34         +++ IkiWiki/Rcs/svn.pm  (working copy)
35         @@ -174,16 +236,16 @@
36                 }
37                 my $rev=int(possibly_foolish_untaint($ENV{REV}));
38                 
39         -       my $user=`svnlook author $config{svnrepo} -r $rev`;
40         +       my $user=decode_locale(`svnlook author $config{svnrepo} -r $rev`);
41                 chomp $user;
42         -       my $message=`svnlook log $config{svnrepo} -r $rev`;
43         +       my $message=decode_locale(`svnlook log $config{svnrepo} -r $rev`);
44                 if ($message=~/$svn_webcommit/) {
45                         $user="$1";
46                         $message=$2;
47                 }
48          
49                 my @changed_pages;
50         -       foreach my $change (`svnlook changed $config{svnrepo} -r $rev`) {
51         +       foreach my $change (decode_locale(`svnlook changed $config{svnrepo} -r $rev`)) {
52                         chomp $change;
53                         if ($change =~ /^[A-Z]+\s+\Q$config{svnpath}\E\/(.*)/) {
54                                 push @changed_pages, $1;
55         @@ -197,7 +259,7 @@
56                         # subscribers a diff that might contain pages they did not
57                         # sign up for. Should separate the diff per page and
58                         # reassemble into one mail with just the pages subscribed to.
59         -               my $diff=`svnlook diff $config{svnrepo} -r $rev --no-diff-deleted`;
60         +               my $diff=decode_locale(`svnlook diff $config{svnrepo} -r $rev --no-diff-deleted`);
61          
62                         my $subject="$config{wikiname} update of ";
63                         if (@changed_pages > 2) {
64         Index: IkiWiki/Render.pm
65         ===================================================================
66         --- IkiWiki/Render.pm   (revision 904)
67         +++ IkiWiki/Render.pm   (working copy)
68         @@ -222,7 +222,7 @@
69                 eval q{use POSIX};
70                 # strftime doesn't know about encodings, so make sure
71                 # its output is properly treated as utf8
72         -       return decode_utf8(POSIX::strftime(
73         +       return decode_locale(POSIX::strftime(
74                                 $config{timeformat}, localtime($time)));
75          } #}}}
76          
77         Index: IkiWiki.pm
78         ===================================================================
79         --- IkiWiki.pm  (revision 904)
80         +++ IkiWiki.pm  (working copy)
81         @@ -9,6 +9,7 @@
82          # Optimisation.
83          use Memoize;
84          memoize("abs2rel");
85         +memoize("get_charset_from_locale");
86          
87          use vars qw{%config %links %oldlinks %oldpagemtime %pagectime
88                      %renderedfiles %pagesources %depends %hooks};
89         @@ -49,9 +50,15 @@
90                 adminemail => undef,
91                 plugin => [qw{mdwn inline htmlscrubber}],
92                 timeformat => '%c',
93         +       locale => get_preferred_locale(),
94          } #}}}
95             
96          sub checkconfig () { #{{{
97         +       debug("setting LC_ALL to '$config{locale}'");
98         +       eval q{use POSIX};
99         +       $ENV{LC_ALL} = $config{locale};
100         +       POSIX::setlocale(&POSIX::LC_ALL, $config{locale});
101         +
102                 if ($config{w3mmode}) {
103                         eval q{use Cwd q{abs_path}};
104                         $config{srcdir}=possibly_foolish_untaint(abs_path($config{srcdir}));
105         @@ -489,4 +496,50 @@
106                 $hooks{$param{type}}{$param{id}}=\%param;
107          } # }}}
108          
109         +sub get_preferred_locale() {
110         +       if (my $env = $ENV{LC_ALL}) {
111         +               return $env;
112         +       }
113         +
114         +       my @avail=`locale -a`;
115         +       chomp @avail;
116         +
117         +       return "POSIX" unless @avail;
118         +
119         +       my @ret;
120         +       # prefer UTF-8 locales
121         +       @avail = map { my $l = $_; $l =~ s/\.utf8/\.UTF-8/; $l; } @avail;
122         +       @avail = @ret if @ret = grep(/\.UTF-8$/, @avail);
123         +
124         +       # prefer en_US or en_ locales
125         +       return $ret[0] if @ret = grep(/^en_US/, @avail);
126         +       return $ret[0] if @ret = grep(/^en_/, @avail);
127         +       return $ret[0] if @ret = grep(/^[^.@]+$/, @avail);
128         +
129         +       # fallback to the first locale found
130         +       return $avail[0];
131         +} # }}}
132         +
133         +sub get_charset_from_locale($) {
134         +       my $locale=shift;
135         +       my ($l, $c);
136         +
137         +       my $supportedlist = "/usr/share/i18n/SUPPORTED";
138         +       if (defined $locale and open(SUPPORTED, "< $supportedlist")) {
139         +               while (<SUPPORTED>) {
140         +                       chomp;
141         +                       ($l, $c) = split(/\s+/);
142         +                       last if ($l eq $locale);
143         +               }
144         +               close(SUPPORTED);
145         +
146         +               return $c if ($l eq $locale);
147         +       }
148         +       return "ISO-8859-1";
149         +} # }}}
150         +
151         +sub decode_locale($) {
152         +       return decode(get_charset_from_locale($config{locale}), shift);
153         +} # }}}
154         +
155          1