wiki.pl: Port some fixes from upstream
[Orgmuse.git] / modules / translation-links.pl
bloba7255a9cba291b5d687e30a0d0e875c24c6f1e78
1 # Copyright (C) 2008, 2012 Alex Schroeder <alex@gnu.org>
3 # This program is free software; you can redistribute it and/or modify it under
4 # the terms of the GNU General Public License as published by the Free Software
5 # Foundation; either version 3 of the License, or (at your option) any later
6 # version.
8 # This program is distributed in the hope that it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 # details.
13 # You should have received a copy of the GNU General Public License along with
14 # this program. If not, see <http://www.gnu.org/licenses/>.
16 $ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/translation-links.pl">translation-links.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Translation_Links">Translation Links</a></p>';
18 =head1 Translation Links
20 This package allows Oddmuse to support translation links.
22 The prerequisite is that you set the C<%Languages> option.
24 Example:
26 %Languages = ('de' => '\b(der|die|das|und|oder)\b',
27 'en' => '\b(the|he|she|that|this)\b');
29 This defines the I<known languages>: de and en, in our example.
31 The known languages should not contain any characters with a special
32 meaning in a regular expresion, nor should it contain a space or an
33 underscore.
35 =head2 %TranslationLinkTarget
37 This option maps languages to URLs. If this option is not set, all
38 links will point to the default URL of the wiki, C<$ScriptName>.
40 You can use this together with the namespace extension. Here's an
41 example:
43 $TranslationLinkTarget{en} = "$ScriptName/En";
44 $TranslationLinkTarget{de} = "$ScriptName/De";
46 Or you can use a setup using a different wrapper script per language:
48 $TranslationLinkTarget{en} = "$ScriptName-en";
49 $TranslationLinkTarget{de} = "$ScriptName-de";
51 =head2 $TranslationLinkHelpPage
53 When translating a page, people will be offered a link to a help page.
54 The default page is called TranslationHelp.
56 =cut
58 use vars qw($TranslationLinkPattern %TranslationLinkTarget
59 $TranslationLinkHelpPage);
61 $TranslationLinkHelpPage = 'TranslationHelp';
63 =head2 $TranslationLinkPattern
65 This regular expression is formed via all the defined languages and
66 C<$FreeLinkPattern> if C<$FreeLinks> is set and/or C<$LinkPattern> if
67 C<$WikiLinks> is set. It matches things such as C<[[en:HomePage]]>.
69 =cut
71 push(@MyInitVariables, \&TranslationLinkInit);
73 my %TranslationLinkData;
75 sub TranslationLinkInit {
76 $TranslationLinkPattern = '\[\[(' . join('|', keys %Languages) . '):(';
77 $TranslationLinkPattern .= $FreeLinkPattern if $FreeLinks;
78 $TranslationLinkPattern .= '|' if $FreeLinks or $WikiLinks;
79 $TranslationLinkPattern .= $LinkPattern if $WikiLinks;
80 $TranslationLinkPattern .= ')\]\]';
81 %TranslationLinkData = ();
84 =head2 TranslationLinkRule
86 The translation links will not be rendered, that is text such as
87 C<[[en:HomePage]]> does not produce any HTML output directly. We will
88 collect the translation links as we go, however, and store them in our
89 C<%Page> which will be saved to disk if no HTML cache exists.
91 =cut
93 push(@MyRules, \&TranslationLinkRule);
95 sub TranslationLinkRule {
96 if (m/\G$TranslationLinkPattern/cog) {
97 $TranslationLinkData{$1} = $2;
98 $Page{translations} = join($FS, %TranslationLinkData);
99 return '';
101 return undef;
104 =head2 Footer Links
106 We hook into C<GetFooterLinks> and print a line of translations, as
107 well as a link to the translate action.
109 =cut
111 *TranslationLinkOldGetFooterLinks = *GetFooterLinks;
112 *GetFooterLinks = *TranslationLinkNewGetFooterLinks;
114 sub TranslationLinkNewGetFooterLinks {
115 my $html = TranslationLinkOldGetFooterLinks(@_);
116 my ($id, $rev) = @_;
117 if ($id and not $rev) {
118 OpenPage($id);
119 my $bar;
120 my %translations;
121 if ($Page{translations}) {
122 %translations = split(/$FS/, $Page{translations});
123 $bar = join(' ', map {
124 my $url;
125 if ($TranslationLinkTarget{$_}) {
126 $url = $TranslationLinkTarget{$_};
127 $url =~ s/\%s/$translations{$_}/g or $url .= $translations{$_};
128 } else {
129 $url = ScriptUrl($translations{$_});
131 $q->a({-href=>$url, -class=>"translation $_"}, T($_));
132 } keys %translations);
134 my %missing;
135 foreach (keys %Languages) {
136 if (not $translations{$_}) {
137 $missing{$_} = 1;
140 # If the current page is autodetected to have exactly one
141 # translation, then remove that language from the list of missing
142 # languages.
143 my @current = split(/,/, $Page{languages});
144 if ($#current == 0) {
145 delete $missing{$current[0]};
147 if (scalar keys %missing) {
148 $bar .= ' ' . ScriptLink("action=translate;id=$id;missing="
149 . join('_', sort keys %missing),
150 T('Add Translation'), 'translation new');
152 $html = $q->span({-class=>'translation bar'}, $q->br(), $bar) . $html;
154 return $html;
157 =head2 Translate Action
159 The translate action knows what page the user is trying to translate,
160 and it knows what translations seem to be missing. By selecting the
161 appropriate checkbox, a translation link will be added to the source
162 page.
164 =cut
166 $Action{translate} = \&DoTranslationLink;
168 sub DoTranslationLink {
169 my $source = shift;
170 my $target = FreeToNormal(GetParam('target', ''));
171 my $error = ValidId($target)
172 || ($source eq $target and T("Please provide a different page name for the translation."));
173 my $lang = GetParam('translation', '');
174 if (not $error and $lang) {
175 OpenPage(FreeToNormal($source));
176 Save($OpenPageName, "[[$lang:$target]]\n" . $Page{text},
177 Tss('Added translation: %1 (%2)',
178 NormalToFree($target), T($lang)), 1);
179 DoEdit($target);
180 } else {
181 my @missing = split(/_/, GetParam('missing', ''));
182 print GetHeader(undef, Ts('Translate %s', NormalToFree($source)));
183 print $q->start_div({-class=>'content translate'}), GetFormStart();
184 print $q->p(Ts('Thank you for writing a translation of %s.', $source),
185 T('Please indicate what language you will be using.'));
186 if (defined $q->param('target') and not $lang) {
187 print $q->div({-class=>'message'}, $q->p(T('Language is missing')));
189 print $q->p(T('Suggested languages:')),
190 $q->p($q->radio_group(-name=>'translation',
191 -values=>\@missing,
192 -linebreak=>'true',
193 -labels=>\%Translate));
194 print $q->p(Ts('Please indicate a page name for the translation of %s.',
195 $source),
196 Ts('More help may be available here: %s.',
197 GetPageLink($TranslationLinkHelpPage)));
198 if (defined $q->param('target') and $error) {
199 print $q->div({-class=>'message'}, $q->p($error));
201 print $q->p($q->label({-for=>'target'}, T('Translated page: ')),
202 $q->textfield('target', '', 40),
203 # don't use $q->hidden or you'll get encoding errors
204 $q->input({-type=>'hidden', -name=>'id',
205 -value=>$source}),
206 $q->input({-type=>'hidden', -name=>'action',
207 -value=>'translate'}),
208 $q->input({-type=>'hidden', -name=>'missing',
209 -value=>GetParam('missing', '')}),
210 $q->submit('dotranslate', T('Go!')));
211 print $q->endform, $q->end_div();
212 PrintFooter();