source: main/tags/2.40/gsdl/bin/script/submit_translation.pl@ 21085

Last change on this file since 21085 was 4178, checked in by mdewsnip, 21 years ago

Fairly extensive changes to incorporate the changes into the macrofiles, rather than generating the macrofiles from the translation database. This is much better because a diff between the version in CVS and the output from the translator with now be sensible (because the macros have not been rearranged and the comments lost).

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1#!/usr/bin/perl -w
2
3###########################################################################
4# submit_translation.pl
5#
6# A component of the Greenstone digital library software
7# from the New Zealand Digital Library Project at the
8# University of Waikato, New Zealand.
9#
10# Copyright (C) 1999 New Zealand Digital Library Project
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by
14# the Free Software Foundation; either version 2 of the License, or
15# (at your option) any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program; if not, write to the Free Software
24# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25#
26###########################################################################
27
28#SYNOPSIS OF CODE:
29#Processes translation when user clicks the 'SUBMIT TRANSLATION >>' button on
30#greenstone site. Takes the cgiargsclass and the language being translated
31#into, extracts the macronames and macrotext from the cgi data and hashes
32#them, then links this hash to a database and updates database appropriately
33
34BEGIN {
35 die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
36 unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
37}
38
39
40use util;
41use GDBM_File;
42
43
44my %translationdata = ();
45my %updatedata = ();
46
47
48sub main
49{
50 # Get the name of the source (base) language
51 my $sourcelang = shift(@_);
52 # Get the name of the target language
53 my $targetlang = shift(@_);
54 # Get the name of the args file with the cgiargsclass data in it
55 my $argsfile = shift(@_);
56
57 # Check that all arguments were supplied
58 if (!$sourcelang) {
59 die "Error: You didn't supply the name of the source language!\n";
60 }
61 if (!$targetlang) {
62 die "Error: You didn't supply the name of the target language!\n";
63 }
64 if (!$argsfile) {
65 die "Error: You didn't supply the name of the arguments file!\n";
66 }
67
68 # Casefold both language names
69 $sourcelang =~ tr/A-Z/a-z/;
70 $targetlang =~ tr/A-Z/a-z/;
71
72 my $gsdldir = "$ENV{'GSDLHOME'}";
73 my $langdir = util::filename_cat($gsdldir, "tmp", "lang");
74 my $translationdir = util::filename_cat($langdir, $sourcelang . "-" . $targetlang);
75 my $translationdb = util::filename_cat($translationdir, "translation.db");
76 my $updatedb = util::filename_cat($translationdir, "update.db");
77
78 # Open the two database files for the translation
79 tie(%translationdata, "GDBM_File", $translationdb, 1, 0640);
80 tie(%updatedata, "GDBM_File", $updatedb, 1, 0640);
81
82 # Parse the translation submissions
83 my $targetcode = $translationdata{"*target_lang_code*"};
84 print "Target code: $targetcode\n";
85 my $submissions = &parse_user_submission($sourcelang, $targetlang, $targetcode,
86 util::filename_cat($translationdir, $argsfile));
87
88 # Add the submissions to the translation database
89 &add_submissions_to_database($submissions);
90
91 # Writes the target macro files
92 my $macrosdir = util::filename_cat($gsdldir, "macros");
93 &update_target_macrofiles($targetlang, $macrosdir, $submissions);
94
95 # Clean up
96 untie %translationdata;
97 untie %updatedata;
98}
99
100
101sub parse_user_submission
102{
103 my ($sourcelang, $targetlang, $targetcode, $filename) = @_;
104
105 #opens the args file or kills program
106 open(ARGUMENTS, "<$filename") or die("Error: Could not open $filename.\n");
107
108 #stores a hash of macronames with numbers still appended and their values
109 my %distinctkeys = ();
110 my %icontextvals = ();
111
112 #while there are still lines left to read
113 my $macroname = "";
114 my $macrovalue = "";
115 while (<ARGUMENTS>) {
116 #gets the line
117 $line = $_;
118 #chomps off the final newline character
119 chomp($line);
120 # removes nasty carriage returns and formfeeds
121 $line =~ s/\r$//;
122 $line =~ s/\f$//;
123 # print "Line: $line\n";
124
125 # Does the line contain a new CGI argument?
126 if ($line =~ m/^ \"/) {
127 # If the line contains :: (browser converts to %3A%3A) then it has a macroname
128 if ($line =~ m/%3A%3A/) {
129 #hashes the previous macro and its value, provided the value is non-empty
130 if ($macrovalue =~ m/\S+/) {
131 # Add the icontext macros to a separate list
132 if ($macroname =~ m/::icontext$/) {
133 $icontextvals{$macroname} = $macrovalue;
134 }
135 else {
136 $distinctkeys{$macroname} = $macrovalue;
137 }
138 }
139
140 $macroname = $line;
141 #changes the codes back to ::
142 $macroname =~ s/%3A%3A/::/g;
143 #removes value of macro leaving just the name
144 $macroname =~ s/=.*//;
145 #saves the value
146 $macrovalue = $&;
147 #removes all " from macro
148 $macroname =~ s/\"//g;
149 #removes any whitespace from macro
150 $macroname =~ s/\s+//g;
151
152 #removes all " and = from value
153 $macrovalue =~ s/=//g;
154 $macrovalue =~ s/\A\"//;
155 $macrovalue =~ s/\"\Z//;
156 $macrovalue =~ s/<br>/\n/g;
157 }
158 else {
159 #hashes the previous macro and its value, provided the value is non-empty
160 if ($macroname ne "" && $macrovalue =~ m/\S+/) {
161 # Add the icontext macros to a separate list
162 if ($macroname =~ m/::icontext$/) {
163 $icontextvals{$macroname} = $macrovalue;
164 }
165 else {
166 $distinctkeys{$macroname} = $macrovalue;
167 }
168 }
169 $macroname = "";
170 $macrovalue = "";
171 }
172 }
173 # No, so check if it is part of a multi-line macro
174 else {
175 if ($macroname ne "") {
176 $extravalue = $line;
177 #removes all " and = from value
178 $extravalue =~ s/=//g;
179 $extravalue =~ s/\A\"//;
180 $extravalue =~ s/\"\Z//;
181 $extravalue =~ s/<br>/\n/g;
182 # add this line to the current macro value
183 $macrovalue = $macrovalue . "\n" . $extravalue;
184 }
185 }
186 }
187
188 close ARGUMENTS;
189
190 # Create a hash map containing the translations to add
191 my %translations = ();
192
193 for $sourcekey (sort keys %distinctkeys) {
194 my $macrotext = "";
195
196 # Check if this macro is an icon macro
197 my $iconkey = $sourcekey . "::icontext";
198 if ($icontextvals{$iconkey}) {
199 my $icontext = $icontextvals{$iconkey};
200
201 # Add the language code to each part of the icon macro
202 # -- This should be done by translate.pl when the images are created --
203 $icontext =~ s/(\n_[^_]+_)(\s*)/$1 \[l=$targetcode\] /g;
204 $icontext =~ s/( {_[^_]+_)(.*)(\/([^\/]+)})/$1\/$targetcode$3/g;
205
206 $macrotext = "## \"" . $distinctkeys{$sourcekey} . "\" " . $icontext . "\n";
207 }
208 # It must be a text macro
209 else {
210 $macrotext = "[l=$targetcode] {" . $distinctkeys{$sourcekey} . "}\n";
211 }
212
213 my $targetkey = &get_macroname_equivalent($sourcelang, $targetlang, $sourcekey);
214 $translations{$targetkey} = $macrotext;
215 }
216
217 return (\%translations);
218}
219
220
221sub get_macrofile_name
222{
223 my ($language, $suffix) = @_;
224
225 my $macrofilename = $language;
226
227 # Handles cases where the macro file name is different to the language name
228 $macrofilename = "port" if ($language =~ m/portuguese/);
229 $macrofilename = "indo" if ($language =~ m/indonesian/);
230
231 # Add suffix (if any) and file extension, and return
232 $macrofilename = $macrofilename . $suffix . ".dm";
233 return $macrofilename;
234}
235
236
237sub get_macroname_equivalent
238{
239 my ($languageA, $languageB, $languageAkey) = @_;
240
241 my $macrofile = $languageAkey;
242 $macrofile =~ s/^([^:]+)::(.*)/$1/;
243 my $key = $languageAkey;
244 $key =~ s/^([^:])+::(.*)/$2/;
245
246 my $languageBkey;
247 if ($macrofile eq &get_macrofile_name($languageA, "")) {
248 $languageBkey = &get_macrofile_name($languageB, "") . "::" . $key;
249 }
250 if ($macrofile eq &get_macrofile_name($languageA, "2")) {
251 $languageBkey = &get_macrofile_name($languageB, "2") . "::" . $key;
252 }
253
254 return ($languageBkey);
255}
256
257
258sub add_submissions_to_database
259{
260 my ($submissions) = @_;
261
262 # Write each submission to the database
263 foreach $key (sort keys(%$submissions)) {
264 $translationdata{$key} = $submissions->{$key};
265
266 # If this was one of the macros needing updating, it has been
267 if ($updatedata{$key}) {
268 delete $updatedata{$key};
269 }
270 }
271}
272
273
274sub update_target_macrofiles
275{
276 my ($targetlang, $macrosdir, $submissions) = @_;
277
278 # Split the submissions by macrofile
279 my %submissions1 = ();
280 my %submissions2 = ();
281 foreach $key (keys %$submissions) {
282 if (&core_or_auxiliary_macro($targetlang, $key) eq "core") {
283 $submissions1->{$key} = $submissions->{$key};
284 }
285 else {
286 $submissions2->{$key} = $submissions->{$key};
287 }
288 }
289
290 # Add the submissions into the appropriate files
291 my $macrofile1 = &get_macrofile_name($targetlang, "");
292 &add_submissions_into_macrofile($targetlang, $macrosdir, $macrofile1, $submissions1);
293 my $macrofile2 = &get_macrofile_name($targetlang, "2");
294 &add_submissions_into_macrofile($targetlang, $macrosdir, $macrofile2, $submissions2);
295}
296
297
298sub core_or_auxiliary_macro
299{
300 my ($language, $sourcekey) = @_;
301
302 my $macrofile = $sourcekey;
303 $macrofile =~ s/^([^:]+)::(.*)/$1/;
304
305 if ($macrofile eq ($language . ".dm")) {
306 return "core";
307 }
308 if ($macrofile eq ($language . "2.dm")) {
309 return "auxiliary";
310 }
311}
312
313
314sub add_submissions_into_macrofile
315{
316 my ($targetlang, $macrosdir, $macrofile, $submissions) = @_;
317
318 # Opens the macro file or dies a miserable death
319 my $macropath = util::filename_cat($macrosdir, $macrofile);
320 open(MACROFILE_IN, "<$macropath") or die "Error: Could not open $macropath.\n";
321 open(MACROFILE_TMP, ">$macrofile.tmp") or die "Error: Could not write $macrofile.tmp\n";
322
323 my $curroutline = 0;
324 my $currpackage;
325 my $currpackageinsertionpoint = $curroutline;
326 my %insertionpoints = ();
327 while (<MACROFILE_IN>) {
328 #currline++;
329
330 # Check if a new package is being defined
331 if (/^package (.*)/) {
332 # Is this the end of a previous package?
333 if ($currpackage) {
334 # Yes, so remember the insertion point for the package
335 $insertionpoints{$currpackageinsertionpoint} = $currpackage;
336 }
337 $currpackage = $1;
338 print MACROFILE_TMP $_;
339 $curroutline++;
340 }
341
342 # Check if an icon macro is being defined
343 elsif (/^(\#\# .*)/) {
344 my $iconmacro = $1;
345
346 # In the case where the macroname contains a new line, read the next line too
347 unless ($iconmacro =~ m/^\#\# .*\#\#/) {
348 $iconmacro .= "\n" . <MACROFILE_IN>;
349 chomp($iconmacro);
350 # $currline++;
351 $curroutline++;
352 }
353
354 # Split the icon macro header on "##"
355 my @iconparts = split(/\s*\#\#\s*/, $iconmacro);
356 # The macroname is the last element of the header (ie. ## ... ## ... ## this ##)
357 my $macroname = $iconparts[(scalar @iconparts) - 1];
358
359 # The key consists of macro file, package name, and macro name
360 my $macrokey = $macrofile . "::" . $currpackage . "::" . $macroname;
361
362 # Check if this macro has just been submitted
363 my $newsubmission = "false";
364 if ($submissions->{$macrokey}) {
365 # It has, so write the submitted text
366 $newsubmission = "true";
367 print MACROFILE_TMP $submissions->{$macrokey} . "\n";
368 $count = ($submissions->{$macrokey} =~ tr/\n/\n/);
369 $curroutline = $curroutline + $count;
370 delete $submissions->{$macrokey};
371 }
372 else {
373 # It hasn't, so write the old macro
374 print MACROFILE_TMP $iconmacro . "\n";
375 $curroutline++;
376 }
377
378 # Chew up the old macro text, spitting it out if necessary
379 do {
380 $_ = <MACROFILE_IN>;
381 # $currline++;
382 if ($newsubmission ne "true") {
383 print MACROFILE_TMP $_;
384 $curroutline++;
385 }
386 } until ($_ =~ /^\s+/);
387
388 # Remember where this macro finished
389 $currpackageinsertionpoint = $curroutline;
390 }
391
392 # Check if a text macro is being defined
393 elsif (/^(_\w+_)(.*)/) {
394 # Get the name of the macro
395 my $macroname = $1;
396 print MACROFILE_TMP $macroname;
397
398 # The key consists of macro file, package name, and macro name
399 my $macrokey = $macrofile . "::" . $currpackage . "::" . $macroname;
400
401 # Check if this macro has just been submitted
402 my $newsubmission = "false";
403 if ($submissions->{$macrokey}) {
404 # It has, so write the submitted text
405 $newsubmission = "true";
406 print MACROFILE_TMP $submissions->{$macrokey};
407 $count = ($submissions->{$macrokey} =~ tr/\n/\n/);
408 $curroutline = $curroutline + $count;
409 delete $submissions->{$macrokey};
410 }
411 else {
412 # It hasn't, so write the old macro text
413 print MACROFILE_TMP $2 . "\n";
414 $curroutline++;
415 }
416
417 # Chew up the old macro text, spitting it out if necessary
418 while ($_ !~ /.*\}/) {
419 $_ = <MACROFILE_IN>;
420 # $currline++;
421 if ($newsubmission ne "true") {
422 print MACROFILE_TMP $_;
423 $curroutline++;
424 }
425 }
426
427 # Remember where this macro finished
428 $currpackageinsertionpoint = $curroutline;
429 }
430
431 # The line must just be a comment or whitespace
432 else {
433 print MACROFILE_TMP $_;
434 $curroutline++;
435 }
436 }
437
438 # Close opened files
439 close MACROFILE_TMP;
440 close MACROFILE_IN;
441
442 open(MACROFILE_TMP, "<$macrofile.tmp") or die "Error: Could not open $macrofile.tmp\n";
443 # open(MACROFILE_OUT, ">$macrofile.out") or die "Error: Could not write $macrofile.out\n";
444 open(MACROFILE_OUT, ">$macropath") or die "Error: Could not write $macropath\n";
445
446 # Insert the new macro submissions in the correct place
447 $currline = 0;
448 while (<MACROFILE_TMP>) {
449 $currline++;
450
451 # Are we at a package insertion point?
452 if ($insertionpoints{$currline}) {
453 $currpackage = $insertionpoints{$currline};
454
455 # Yes, so check if there are any macros to insert here
456 foreach $key (keys %$submissions) {
457 $key =~ m/^[^:]+::([^:]+)::(.*)/;
458 my $packagename = $1;
459 my $macroname = $2;
460
461 if ($packagename eq $currpackage) {
462 # Insert this macro here
463 &write_macro_to_file($macroname, $submissions->{$key}, MACROFILE_OUT);
464 delete $submissions->{$key};
465 }
466 }
467 }
468
469 print MACROFILE_OUT $_;
470 }
471
472 # If there are any submissions still remaining, write them to a new package at the end
473 $currpackage = "";
474 foreach $key (sort (keys %$submissions)) {
475 $key =~ m/^[^:]+::([^:]+)::(.*)/;
476 my $packagename = $1;
477 my $macroname = $2;
478
479 if ($packagename ne $currpackage) {
480 # Write package header
481 print MACROFILE_OUT "\n";
482 print MACROFILE_OUT "########################################################\n";
483 print MACROFILE_OUT "package $packagename\n";
484 print MACROFILE_OUT "########################################################\n";
485
486 $currpackage = $packagename;
487 }
488
489 # Write macro
490 &write_macro_to_file($macroname, $submissions->{$key}, MACROFILE_OUT);
491 delete $submissions->{$key};
492 }
493
494 # Close opened files
495 close MACROFILE_OUT;
496 close MACROFILE_TMP;
497
498 # Delete the temporary file
499 unlink("$macrofile.tmp");
500}
501
502
503sub write_macro_to_file
504{
505 my ($macroname, $macrotext, $filehandle) = @_;
506
507 print MACROFILE_OUT "\n";
508 print MACROFILE_OUT "# Macro added using the translation agency\n";
509
510 if ($macrotext =~ m/\#\# (^|.)*/) {
511 # Icon macro
512 print MACROFILE_OUT $macrotext;
513 }
514 else {
515 # Text macro
516 print MACROFILE_OUT $macroname . $macrotext;
517 }
518}
519
520
521&main(@ARGV);
Note: See TracBrowser for help on using the repository browser.