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
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
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.
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
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
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.
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]]>.
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.
93 push(@MyRules, \&TranslationLinkRule);
95 sub TranslationLinkRule {
96 if (m/\G$TranslationLinkPattern/cog) {
97 $TranslationLinkData{$1} = $2;
98 $Page{translations} = join($FS, %TranslationLinkData);
106 We hook into C<GetFooterLinks> and print a line of translations, as
107 well as a link to the translate action.
111 *TranslationLinkOldGetFooterLinks = *GetFooterLinks;
112 *GetFooterLinks = *TranslationLinkNewGetFooterLinks;
114 sub TranslationLinkNewGetFooterLinks {
115 my $html = TranslationLinkOldGetFooterLinks(@_);
117 if ($id and not $rev) {
121 if ($Page{translations}) {
122 %translations = split(/$FS/, $Page{translations});
123 $bar = join(' ', map {
125 if ($TranslationLinkTarget{$_}) {
126 $url = $TranslationLinkTarget{$_};
127 $url =~ s/\%s/$translations{$_}/g or $url .= $translations{$_};
129 $url = ScriptUrl($translations{$_});
131 $q->a({-href=>$url, -class=>"translation $_"}, T($_));
132 } keys %translations);
135 foreach (keys %Languages) {
136 if (not $translations{$_}) {
140 # If the current page is autodetected to have exactly one
141 # translation, then remove that language from the list of missing
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;
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
166 $Action{translate} = \&DoTranslationLink;
168 sub DoTranslationLink {
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);
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',
193 -labels=>\%Translate));
194 print $q->p(Ts('Please indicate a page name for the translation of %s.',
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',
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();