1#!/usr/bin/perl -w 2# 3# <@LICENSE> 4# Licensed to the Apache Software Foundation (ASF) under one or more 5# contributor license agreements. See the NOTICE file distributed with 6# this work for additional information regarding copyright ownership. 7# The ASF licenses this file to you under the Apache License, Version 2.0 8# (the "License"); you may not use this file except in compliance with 9# the License. You may obtain a copy of the License at: 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, software 14# distributed under the License is distributed on an "AS IS" BASIS, 15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16# See the License for the specific language governing permissions and 17# limitations under the License. 18# </@LICENSE> 19 20use strict; 21use warnings; 22use FindBin; 23use Getopt::Std; 24 25# Lingua::Translate has a bunch of requirements (see bottom of its perldoc) 26use Lingua::Translate; 27 28# %rules and %scores from tmp/rules.pl 29our ($opt_c, $opt_e, $opt_h, $opt_n, $opt_r, %rules, %scores); 30 31sub usage { 32 die "generate-translation language output_file 33 34 -h print this help 35 -e STR use STR as destination character set (using Lingua::Translate) 36 -r STR use STR as destination character set (using recode) 37 -n N translate first N rules (used for testing) 38 -c DIR use DIR as rules directory 39 40 language should be a two letter language code from this list: 41 42 zh: Chinese-simplified 43 zt: Chinese-traditional 44 nl: Dutch 45 fr: French 46 de: German 47 el: Greek 48 it: Italian 49 ja: Japanese 50 ko: Korean 51 pt: Portuguese 52 ru: Russian 53 es: Spanish 54 55 progress is displayed on standard error 56"; 57} 58 59getopts("hc:e:n:r:"); 60usage() if ($opt_h || @ARGV < 2); 61 62# options 63my $dest = shift @ARGV; 64my $output = shift @ARGV; 65my $cffile = $opt_c || "$FindBin::Bin/../rules"; 66my $enc = $opt_e || "utf8"; 67my $recode = $opt_r || "UTF-8"; 68 69# rule => configuration hashes 70my %english; 71my %old; 72my %translation; 73 74# translation cache 75my %lang_cache; 76 77# do the work 78read_rules($cffile); 79generate_translation(); 80print_translation(); 81 82sub read_rules { 83 my ($cffile) = @_; 84 85 system("$FindBin::Bin/../build/parse-rules-for-masses -d \"$cffile\"") 86 and die "unable to parse rules\n"; 87 require "$FindBin::Bin/tmp/rules.pl" 88 or die "unable to read tmp/rules.pl\n"; 89} 90 91sub generate_translation { 92 my $fish = Lingua::Translate->new(src => "en", 93 dest => $dest, 94 dest_enc => $enc) 95 or die "no translation server available for en -> $dest\n"; 96 97 # see if we had an old translation 98 if (-f "$FindBin::Bin/../rules/30_text_$dest.cf") { 99 open(OLD, "$FindBin::Bin/../rules/30_text_$dest.cf"); 100 while(<OLD>) { 101 if (/^lang\s+$dest\s+describe\s+(\S+)\s+(.*?)\s*$/) { 102 $old{$1} = "lang $dest describe $1 $2\n"; 103 } 104 } 105 close(OLD); 106 } 107 108 # try to generate new translation 109 my $count = 0; 110 for my $name (sort keys %rules) { 111 next if ($name eq '_scoreset'); 112 113 my $lang_name = $name; 114 my $lang_describe = ''; 115 if ($rules{$name}->{lang}) { 116 next; 117 } 118 if (defined $rules{$name}->{describe}) { 119 # translate name if it appears in the description 120 my $describe = $rules{$name}->{describe}; 121 if ($describe =~ /$name/) { 122 eval { 123 $lang_name = $fish->translate($name); # dies or croaks on error 124 }; 125 if ($@) { 126 $lang_name = '[A-Z]+[A-Z0-9_]+[A-Z0-9]'; 127 } 128 } 129 # English version 130 $english{$name} = "describe $name\t$describe\n"; 131 # translate description 132 eval { 133 if (defined $lang_cache{$describe}) { 134 $lang_describe = $lang_cache{$describe}; 135 } 136 else { 137 # dies or croaks on error 138 $lang_describe = $fish->translate($describe); 139 $lang_describe =~ s/\s+/ /sg; 140 $lang_describe =~ s/ $//g; 141 $lang_cache{$describe} = $lang_describe; 142 } 143 }; 144 # didn't work 145 if ($@) { 146 print STDERR "x"; 147 } 148 else { 149 $lang_describe =~ s/$lang_name/$name/; 150 $translation{$name} = "lang $dest describe $name\t$lang_describe\n"; 151 print STDERR "."; 152 } 153 $count++; 154 last if ($opt_n && $count == $opt_n); 155 } 156 } 157 print STDERR "\n" if $count > 0; 158} 159 160sub print_translation { 161 my $charset = $enc; 162 if ($opt_r) { 163 $charset = $recode; 164 } 165 $charset =~ s/utf-?8/utf-8/i; 166 167 open(OUTPUT, "> $output"); 168 print OUTPUT <<'EOF'; 169# 170# Please don't modify this file as your changes will be overwritten with 171# the next update. Use @@LOCAL_RULES_DIR@@/local.cf instead. 172# See 'perldoc Mail::SpamAssassin::Conf' for details. 173# 174# <@LICENSE> 175# Licensed to the Apache Software Foundation (ASF) under one or more 176# contributor license agreements. See the NOTICE file distributed with 177# this work for additional information regarding copyright ownership. 178# The ASF licenses this file to you under the Apache License, Version 2.0 179# (the "License"); you may not use this file except in compliance with 180# the License. You may obtain a copy of the License at: 181# 182# http://www.apache.org/licenses/LICENSE-2.0 183# 184# Unless required by applicable law or agreed to in writing, software 185# distributed under the License is distributed on an "AS IS" BASIS, 186# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 187# See the License for the specific language governing permissions and 188# limitations under the License. 189# </@LICENSE> 190# 191########################################################################### 192 193# character set used in the following texts 194EOF 195 print OUTPUT <<EOF; 196lang $dest report_charset $charset 197 198# make me pretty 199EOF 200 open(MISC, "$FindBin::Bin/../rules/10_misc.cf"); 201 while (<MISC>) { 202 if (/^(?:clear_report_template|report|clear_unsafe_report_template|unsafe_report)\b/) { 203 print OUTPUT "lang $dest $_"; 204 } 205 } 206 207 print OUTPUT "\n\n"; 208 209 for (sort keys %english) { 210 print OUTPUT "# $english{$_}"; 211 print OUTPUT "# $translation{$_}" if $translation{$_}; 212 print OUTPUT "# $old{$_}" if $old{$_}; 213 print OUTPUT "\n"; 214 } 215 216 system("/usr/bin/recode $enc..$recode $output") if $opt_r; 217} 218