source: main/tags/2.52/gsdl/perllib/translator.pm@ 25422

Last change on this file since 25422 was 8102, checked in by mdewsnip, 20 years ago

Unfinished, but I'm committing it now so I don't lose it.

  • Property svn:keywords set to Author Date Id Revision
File size: 15.2 KB
Line 
1###########################################################################
2#
3# translator.pm --
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26
27# Common functions used by the different parts of the translator
28package translator;
29
30
31use util;
32use GDBM_File;
33
34
35my $gsdldir = "$ENV{'GSDLHOME'}";
36my $maincfgfile = &util::filename_cat($gsdldir, "etc", "main.cfg");
37my $translatordir = &util::filename_cat($gsdldir, "translator");
38my $translatorcfgfile = &util::filename_cat($gsdldir, "etc", "translator.cfg");
39
40my $cvsroot = ":pserver:cvs_anon\@cvs.scms.waikato.ac.nz:2402/usr/local/global-cvs/gsdl-src";
41
42
43sub get_translator_dir
44{
45 return $translatordir;
46}
47
48
49sub get_cvs_root
50{
51 return $cvsroot;
52}
53
54
55sub read_languages_from_main_cfg_file
56{
57 local %code2namehash = ();
58
59 # Read the main.cfg file
60 if (!open(MAIN_CFG_FILE, "<$maincfgfile")) {
61 print STDERR "Error: Could not open $maincfgfile.\n";
62 die "\n";
63 }
64 while (<MAIN_CFG_FILE>) {
65 local $line = $_;
66 chomp($line);
67
68 # Parse the lines containing a language definition
69 if ($line =~ m/^Language\s+/i) {
70 local ($langcode) = ($line =~ /shortname=(\S+)/i);
71 local ($langname) = ($line =~ /longname=(\"[^\"]+\"|\S+)/i);
72
73 # Casefold the language code, and remove any quotes around the language name
74 $langcode =~ tr/A-Z/a-z/;
75 $langname =~ s/^\"(.+)\"$/$1/;
76
77 $code2namehash{$langcode} = $langname;
78 }
79 }
80 close(MAIN_CFG_FILE);
81
82 return %code2namehash;
83}
84
85
86sub read_translation_files_from_config_file
87{
88 local %name2deschash = ();
89
90 # Read the translator config file
91 if (!open(CONFIG_FILE, "<$translatorcfgfile")) {
92 print STDERR "Error: Could not open $translatorcfgfile.\n";
93 die "\n";
94 }
95 while (<CONFIG_FILE>) {
96 local $line = $_;
97 chomp($line);
98
99 # Check if a file is being defined
100 if ($line =~ m/^File\s+/i) {
101 local ($fileid) = ($line =~ /id=(\S+)/i);
102 local ($filedesc) = ($line =~ /description=(\S+)/i);
103 $name2deschash{$fileid} = $filedesc;
104 }
105 }
106 close(CONFIG_FILE);
107
108 return %name2deschash;
109}
110
111
112sub read_file_data_from_config_file
113{
114 my ($sourceabbr, $targetabbr, $file) = @_;
115
116 # Read the translator config file
117 if (!open(CONFIG_FILE, "<$translatorcfgfile")) {
118 print STDERR "Error: Could not open $translatorcfgfile.\n";
119 die "\n";
120 }
121 while (<CONFIG_FILE>) {
122 local $line = $_;
123 chomp($line);
124
125 # Check if a file is being defined
126 if ($line =~ m/^File\s+/i) {
127 local @lineparts = split(/\s+/, $line);
128 local ($fileid) = ($lineparts[1] =~ m/^id=(.*)$/);
129
130 # If this is the file we want, return its details
131 if ($fileid eq $file) {
132 local ($filedesc) = ($lineparts[2] =~ m/^description=(.*)$/);
133 local ($sourcefile) = ($lineparts[3] =~ m/^sourcefile=(.*)$/);
134 local ($targetfile) = ($lineparts[4] =~ m/^targetfile=(.*)$/);
135 local ($filetype) = ($lineparts[5] =~ m/^type=(.*)$/);
136
137 # Determine sourcebase and targetbase, using the filetype
138 local $sourcebase = &get_file_base($sourceabbr, $filetype);
139 local $targetbase = &get_file_base($targetabbr, $filetype);
140
141 # Resolve instances of {sourceabbr}, {sourcebase}, {targetabbr}, {targetbase}
142 $sourcefile =~ s/\{sourceabbr\}/$sourceabbr/g;
143 $sourcefile =~ s/\{sourcebase\}/$sourcebase/g;
144 $targetfile =~ s/\{targetabbr\}/$targetabbr/g;
145 $targetfile =~ s/\{targetbase\}/$targetbase/g;
146
147 close(CONFIG_FILE);
148 return ($sourcefile, $targetfile, $filetype);
149 }
150 }
151 }
152 close(CONFIG_FILE);
153
154 return ();
155}
156
157
158sub get_translation_file_path
159{
160 my ($translationdir, $relativefilepath) = @_;
161
162 # Extract the file name from the relative file path
163 $relativefilepath =~ /([^\\\/]+)$/;
164 return &util::filename_cat($translationdir, $1);
165}
166
167
168sub get_file_base
169{
170 my ($langabbr, $filetype) = @_;
171
172 if ($filetype =~ /^macrofile/) {
173 return &get_macrofile_base($langabbr);
174 }
175 if ($filetype =~ /^resourcebundle/ || $filetype =~ /^myresourcebundle/) {
176 return &get_resource_bundle_base($langabbr);
177 }
178
179 print STDERR "Error: Unknown file type $filetype.\n";
180 die "\n";
181}
182
183
184sub process_file
185{
186 my ($filepath, $filetype) = @_;
187
188 # Build a mapping from key to lines
189 local %linehash = &build_key_to_line_mapping($filepath, $filetype);
190
191 # Build a mapping from chunk key to chunk text, and return
192 return &build_key_to_text_mapping($filepath, $filetype, %linehash);
193}
194
195
196sub build_key_to_line_mapping
197{
198 my ($filepath, $filetype) = @_;
199
200 if ($filetype =~ /^macrofile/) {
201 return &build_key_to_line_mapping_for_macrofile($filepath);
202 }
203 if ($filetype =~ /^resourcebundle/) {
204 return &build_key_to_line_mapping_for_resource_bundle($filepath);
205 }
206 if ($filetype =~ /^myresourcebundle/) {
207 return &build_key_to_line_mapping_for_my_resource_bundle($filepath);
208 }
209
210 print STDERR "Error: Unknown file type $filetype.\n";
211 die "\n";
212}
213
214
215sub build_key_to_text_mapping
216{
217 my ($filepath, $filetype, %linehash) = @_;
218
219 if (!open(FILE_IN, "<$filepath")) {
220 print STDERR "Error: Could not open file $filepath.\n";
221 die "\n";
222 }
223 local @lines = <FILE_IN>;
224 close FILE_IN;
225
226 my %chunks = ();
227
228 foreach $key (keys(%linehash)) {
229 # Chunk lines in linehash start at 0
230 local $chunkstart = (split(/-/, $linehash{$key}))[0];
231 local $chunkfinish = (split(/-/, $linehash{$key}))[1];
232
233 local $chunktext = $lines[$chunkstart];
234 for ($l = ($chunkstart + 1); $l <= $chunkfinish; $l++) {
235 $chunktext .= $lines[$l];
236 }
237
238 # Map from chunk key to (formatted) text
239 $chunks{$key} = &import_chunk($chunktext, $filetype);
240 }
241
242 return %chunks;
243}
244
245
246sub import_chunk
247{
248 local ($chunktext, $filetype) = @_;
249
250 if ($filetype =~ /^macrofile/) {
251 return &import_chunk_from_macrofile($chunktext);
252 }
253 if ($filetype =~ /^resourcebundle/) {
254 return &import_chunk_from_resource_bundle($chunktext);
255 }
256 if ($filetype =~ /^myresourcebundle/) {
257 return &import_chunk_from_my_resource_bundle($chunktext);
258 }
259
260 print STDERR "Error: Unknown file type $filetype.\n";
261 die "\n";
262}
263
264
265sub refresh_translation
266{
267 local ($translationdir, $sourcefile, $filetype) = @_;
268
269
270 # -----------------------------------------
271 # Process the source language file
272 # -----------------------------------------
273
274 # Parse the backup source language file, building a mapping from chunk key to chunk text
275 local $sourcepath = &get_translation_file_path($translationdir, $sourcefile);
276 local %backuphash = &process_file($sourcepath, $filetype);
277 print STDOUT "Number of backup chunks: " . scalar(keys(%backuphash)) . "\n";
278
279 # Remove the (possibly out of date) source file
280 local $hotsourcepath = &util::filename_cat($gsdldir, $sourcefile);
281# &util::rm($hotsourcepath);
282
283 # Get the latest version of the source file from CVS
284# local $sourceupdate = `cd $gsdldir; cvs -d $cvsroot update $sourcefile`;
285# if ($sourceupdate !~ /^U /) {
286# print STDERR "Error: Could not update source file.\n";
287# die "\n";
288# }
289
290 # Check that the source file now exists
291 if (!-e $hotsourcepath) {
292 print STDERR "Error: Source file $hotsourcepath does not exist.\n";
293 die "\n";
294 }
295
296 # Copy the new version of the source file to become the backup file
297 &util::cp($hotsourcepath, $sourcepath);
298
299 # Parse the new source language file, building a mapping from chunk key to chunk text
300 local %sourcehash = &process_file($sourcepath, $filetype);
301 print STDOUT "Number of source chunks: " . scalar(keys(%sourcehash)) . "\n";
302
303
304 # -----------------------------------------
305 # Rebuild the translation database
306 # -----------------------------------------
307
308 # Open the translation database for this file
309 local $translationdb = &util::filename_cat($translationdir, "translation.db");
310 local %translationdata = ();
311 tie(%translationdata, "GDBM_File", $translationdb, GDBM_WRCREAT, 0666);
312
313 # Remove translation data for any chunks that no longer exist
314 foreach $key (keys(%translationdata)) {
315 local $sourcekey = $key;
316 if ($sourcekey =~ /\*$/) {
317 chop($sourcekey);
318 }
319
320 # If the chunk doesn't exist in the new source file, remove it from the database
321 if (!defined($sourcehash{$sourcekey})) {
322 print STDOUT "Chunk with key $key no longer exists!\n";
323 delete $translationdata{$key};
324 }
325 }
326
327 # Update the translation database to reflect the new source file
328 foreach $key (keys(%sourcehash)) {
329 # Add translation data for any new chunks
330 if (!defined($backuphash{$key})) {
331 print STDOUT "Chunk with key $key is new!\n";
332 $translationdata{$key} = "";
333 }
334
335 # Source chunks that have changed since last time must have their translations updated
336 if ($backuphash{$key} && $backuphash{$key} ne $sourcehash{$key}) {
337 print STDOUT "Chunk with key $key needs updating!\n";
338 $translationdata{$key . "*"} = "";
339 }
340 }
341
342 # Close the old translation database
343 untie(%translationdata);
344}
345
346
347# ==========================================================================================
348
349sub get_macrofile_base
350{
351 local ($langcode) = @_;
352
353 # List special cases here (macrofile names differ from language longnames)
354 local %specialcases = ('id', 'indo',
355 'pt-br', 'port-br',
356 'pt-pt', 'port-pt',
357 'zh', 'chinese' );
358
359 # Special cases override main.cfg entries
360 if ($specialcases{$langcode}) {
361 return $specialcases{$langcode};
362 }
363
364 # Use the language name defined in the main.cfg file as the macrofile name
365 my %langhash = &read_languages_from_main_cfg_file();
366 my $langname = $langhash{$langcode} || die "Error: Language to base mapping undefined!\n";
367 $langname =~ tr/A-Z/a-z/;
368 return $langname;
369}
370
371
372sub build_key_to_line_mapping_for_macrofile
373{
374 local ($filepath) = @_;
375
376 # Open file for reading
377 if (!open(FILE_IN, "<$filepath")) {
378 print STDERR "Error: Could not open macrofile $filepath.\n";
379 die "\n";
380 }
381 local @lines = <FILE_IN>;
382 close FILE_IN;
383
384 # Initialise some local variables
385 local $currpackage;
386 local %linehash = ();
387
388 # Process the contents of the file, line by line
389 for ($i = 0; $i < scalar(@lines); $i++) {
390 local $line = $lines[$i];
391 $line =~ s/(\s*)$//; # Remove any nasty whitespace, carriage returns etc.
392
393 # Check if a new package is being defined
394 if ($line =~ m/^package\s+(.+)/) {
395 $currpackage = $1;
396 }
397
398 # Line contains a macro name
399 elsif ($line =~ m/^(_\w+_)/) {
400 local $macroname = $1;
401
402 # While there is still text of the macro to go...
403 local $startline = $i;
404 while ($line !~ /\}$/) {
405 $i++;
406 $line = $lines[$i];
407 $line =~ s/(\s*)$//; # Remove any nasty whitespace, carriage returns etc.
408 }
409
410 # The key consists of the package name and the macro name
411 local $key = $currpackage . "::" . $macroname;
412 # Map from key to line
413 $linehash{$key} = $startline . "-" . $i;
414 }
415
416 # Icon: line in format ## "sometext" ## macro ## macroname ##
417 elsif ($line =~ m/^\#\# (.*)/) {
418 local $macroname = $1;
419
420 # If the macro text contains a new line it will run over two lines
421 local $startline = $i;
422 unless ($line =~ m/^\#\# .*\#\#/) {
423 $i++;
424 $line = $lines[$i];
425 $macroname .= $line;
426 }
427
428 # Split the image macro header on ##
429 local @names = split(/\s*\#\#\s*/, $macroname);
430 # Overwrite macroname with macroname from ## ... ## ... ## HERE ###
431 $macroname = $names[(scalar @names) - 1];
432
433 # Read the rest of the text associated with the image macro
434 while (defined($line) && $line !~ /^\s*$/) {
435 $i++;
436 $line = $lines[$i];
437 }
438
439 # The key consists of package name and macro name
440 local $key = $currpackage . "::" . $macroname;
441 # Map from key to line
442 $linehash{$key} = $startline . "-" . ($i - 1);
443 }
444 }
445
446 return %linehash;
447}
448
449
450sub import_chunk_from_macrofile
451{
452 local ($chunktext) = @_;
453
454 # Is this an icon macro??
455 if ($chunktext =~ /^\#\# (.*)/) {
456 # Extract image macro text
457 $chunktext =~ /^\#\#\s+([^\#]+)\s+\#\#/;
458 $chunktext = $1;
459
460 # Remove enclosing quotes
461 $chunktext =~ s/^\"//;
462 $chunktext =~ s/\"$//;
463 }
464
465 # No, so it must be a text macro
466 else {
467 # Remove macro key
468 $chunktext =~ s/^_([^_]+)_(\s*)//;
469
470 # Remove language specifier
471 $chunktext =~ s/^\[l=.*\](\s*)//;
472
473 # Remove braces enclosing text
474 $chunktext =~ s/^{(\s*)((.|\n)*)}(\s*)/$2/;
475 }
476
477 return $chunktext;
478}
479
480
481# ------------------------------------------------------------------------------------------
482
483sub get_resource_bundle_base
484{
485 local ($langabbr) = @_;
486
487 return "";
488}
489
490
491sub build_key_to_line_mapping_for_resource_bundle
492{
493 local ($filepath) = @_;
494
495 # Open file for reading
496 if (!open(FILE_IN, "<$filepath")) {
497 print STDERR "Error: Could not open resource bundle $filepath.\n";
498 die "\n";
499 }
500 local @lines = <FILE_IN>;
501 close FILE_IN;
502
503 # Initialise some local variables
504 local %linehash = ();
505
506 # Process the contents of the file, line by line
507 for ($i = 0; $i < scalar(@lines); $i++) {
508 local $line = $lines[$i];
509 $line =~ s/(\s*)$//; # Remove any nasty whitespace, carriage returns etc.
510
511 # Line contains a dictionary string
512 if ($line =~ /^((\w|\.)+):(.*)$/) {
513 local $key = $1;
514
515 # Map from key to line
516 $linehash{$key} = $i . "-" . $i;
517 }
518 }
519
520 return %linehash;
521}
522
523
524sub import_chunk_from_resource_bundle
525{
526 local ($chunktext) = @_;
527
528 # Simple: just remove string key
529 $chunktext =~ s/^((\w|\.)+)://;
530
531 return $chunktext;
532}
533
534
535
536# ------------------------------------------------------------------------------------------
537
538sub build_key_to_line_mapping_for_my_resource_bundle
539{
540 local ($filepath) = @_;
541
542 # Open file for reading
543 if (!open(FILE_IN, "<$filepath")) {
544 print STDERR "Error: Could not open resource bundle $filepath.\n";
545 die "\n";
546 }
547 local @lines = <FILE_IN>;
548 close FILE_IN;
549
550 # Initialise some local variables
551 local %linehash = ();
552
553 # Process the contents of the file, line by line
554 for ($i = 0; $i < scalar(@lines); $i++) {
555 local $line = $lines[$i];
556 $line =~ s/(\s*)$//; # Remove any nasty whitespace, carriage returns etc.
557
558 # Line contains a dictionary string
559 if ($line =~ /^((\w|\.|\-)+):\"(.*)$/) {
560 local $key = $1;
561 local $text = $3;
562
563 # While there is still text of the chunk to go...
564 local $startline = $i;
565 while ($text !~ /\"$/ || $text =~ /\\\"$/) {
566 $i++;
567 $text = $lines[$i];
568 }
569
570 $linehash{$key} = $startline . "-" . $i;
571 }
572 }
573
574 return %linehash;
575}
576
577
578sub import_chunk_from_my_resource_bundle
579{
580 local ($chunktext) = @_;
581
582 # Remove chunk key and quotes
583 $chunktext =~ s/^((\w|\.|\-)+)://;
584 $chunktext =~ s/^\"//;
585 $chunktext =~ s/\"$//;
586
587 return $chunktext;
588}
589
590
5911;
Note: See TracBrowser for help on using the repository browser.