Changeset 24627


Ignore:
Timestamp:
09/21/11 16:52:59 (9 years ago)
Author:
anna
Message:

tidied up gti.pl

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone2/bin/script/gti.pl

    r24362 r24627  
    3333}
    3434
     35
    3536use iso639;
    3637use strict;
    3738use util;
    3839
    39 
    40 #my $anonymous_cvs_root = ":pserver:cvs_anon\@cvs.scms.waikato.ac.nz:2402/usr/local/global-cvs/gsdl-src";
    41 #my $anonymous_svn_root = "http://http://svn.greenstone.org/gsdl/trunk/";
    4240my $gsdl_root_directory = "$ENV{'GSDLHOME'}";
    4341my $gti_log_file = &util::filename_cat($gsdl_root_directory, "etc", "gti.log");
     
    4543
    4644my $gti_translation_files =
    47     [ # Greenstone macrofiles
    48       { 'key' => "coredm",
     45[ # Greenstone macrofiles
     46{ 'key' => "coredm",
    4947    'file_type' => "macrofile",
    5048    'source_file' => "macros/english.dm",
    5149    'target_file' => "macros/{bn:bengali;fa:farsi;gd:gaelic;id:indo;lv:latvian;pt-br:port-br;pt-pt:port-pt;zh-tr:chinese-trad;iso_639_1_target_language_name}.dm" },
    52       { 'key' => "auxdm",
     50
     51{ 'key' => "auxdm",
    5352    'file_type' => "macrofile",
    5453    'source_file' => "macros/english2.dm",
    5554    'target_file' => "macros/{bn:bengali;fa:farsi;gd:gaelic;id:indo;lv:latvian;pt-br:port-br;pt-pt:port-pt;zh-tr:chinese-trad;iso_639_1_target_language_name}2.dm" },
    5655
    57       # GLI dictionary
    58       { 'key' => "glidict",
     56# GLI dictionary
     57{ 'key' => "glidict",
    5958    'file_type' => "resource_bundle",
    6059    'source_file' => "gli/classes/dictionary.properties",
    6160    'target_file' => "gli/classes/dictionary_{target_language_code}.properties" },
    6261
    63       # GLI help
    64       { 'key' => "glihelp",
     62# GLI help
     63{ 'key' => "glihelp",
    6564    'file_type' => "greenstone_xml",
    6665    'source_file' => "gli/help/en/help.xml",
    6766    'target_file' => "gli/help/{target_language_code}/help.xml" },
    6867
    69       # Greenstone Perl modules
    70       { 'key' => "perlmodules",
     68# Greenstone Perl modules
     69{ 'key' => "perlmodules",
    7170    'file_type' => "resource_bundle",
    7271    'source_file' => "perllib/strings.properties",
    7372    'target_file' => "perllib/strings_{target_language_code}.properties" },
    7473
    75       # Greenstone tutorial exercises
    76       # { 'key' => "tutorials",
    77     # 'file_type' => "greenstone_xml",
    78     # 'source_file' => "gsdl-documentation/tutorials/xml-source/tutorial_en.xml",
    79     # 'target_file' => "gsdl-documentation/tutorials/xml-source/tutorial_{target_language_code}.xml" },
    80 
    81       # new Greenstone.org
    82       { 'key' => "greenorg",
    83         'file_type' => "resource_bundle",
    84         'source_file' => "greenstoneorg/website/classes/Gsc.properties",
    85         'target_file' => "greenstoneorg/website/classes/Gsc_{iso_639_1_target_language_name}.properties"
    86     # 'file_type' => "macrofile",
    87     # 'source_file' => "greenorg/macros/english.dm",
    88     # 'target_file' => "greenorg/macros/{iso_639_1_target_language_name}.dm"
    89       }
    90 
    91       # { 'key' => "gs3interface",
    92     #'file_type' => "resource_bundle",
    93     #'source_file' => "greenstone3",
    94     #'target_file' => "greenstone3"
    95       #}
    96     ];
     74# Greenstone tutorial exercises
     75# { 'key' => "tutorials",
     76# 'file_type' => "greenstone_xml",
     77# 'source_file' => "gsdl-documentation/tutorials/xml-source/tutorial_en.xml",
     78# 'target_file' => "gsdl-documentation/tutorials/xml-source/tutorial_{target_language_code}.xml" },
     79
     80# new Greenstone.org
     81{ 'key' => "greenorg",
     82    'file_type' => "resource_bundle",
     83    'source_file' => "greenstoneorg/website/classes/Gsc.properties",
     84    'target_file' => "greenstoneorg/website/classes/Gsc_{target_language_code}.properties"
     85}
     86
     87# { 'key' => "gs3interface",
     88#'file_type' => "resource_bundle",
     89#'source_file' => "greenstone3",
     90#'target_file' => "greenstone3"
     91#}
     92];
    9793
    9894my @gs3_interface_files = ("AbstractBrowse", "AbstractGS2FieldSearch", "Authentication", "CrossCollectionSearch", "GATEServices", "GS2Construct", "GS2LuceneSearch", "interface_default", "interface_nzdl", "IViaSearch", "LuceneSearch", "MapRetrieve", "MapSearch", "metadata_names", "PhindPhraseBrowse", "QBRWebServicesHelp", "Visualizer");
     
    105101    my @gti_command_arguments = @_;
    106102    my $module = $_[1];
    107 
     103   
    108104    # Open the GTI log file for appending, or write to STDERR if that fails
    109105    if (!open(GTI_LOG, ">>$gti_log_file")) {
    110     open(GTI_LOG, ">&STDERR");
    111     }
    112 
     106        open(GTI_LOG, ">&STDERR");
     107    }
     108   
    113109    # Log the command that launched this script
    114110    &log_message("Command: $0 @ARGV");
    115 
     111   
    116112    # Check that a command was supplied
    117113    if (!$gti_command) {
    118     &throw_fatal_error("Missing command.");
     114        &throw_fatal_error("Missing command.");
    119115    }     
    120 
     116   
    121117    # Process the command
    122118    if ($gti_command =~ /^get-all-chunks$/i) {
    123     # Check that GS3 interface is the target
    124     if ($module eq "gs3interface") {       
    125         print &get_all_chunks_for_gs3(@gti_command_arguments);
    126     } else {
    127         print &get_all_chunks(@gti_command_arguments);
    128     }
    129     }
    130     if ($gti_command =~ /^get-first-n-chunks-requiring-work$/i) {
    131     if ($module eq "gs3interface") {       
    132         print &get_first_n_chunks_requiring_work_for_gs3(@gti_command_arguments);
    133     } else {
    134         print &get_first_n_chunks_requiring_work(@gti_command_arguments);
    135     }
    136     }
    137     if ($gti_command =~ /^get-language-status$/i) {
    138     print &get_language_status(@gti_command_arguments);       
    139     }
    140     if ($gti_command =~ /^search-chunks$/i) {
    141     print &search_chunks(@gti_command_arguments);
    142     }
    143     if ($gti_command =~ /^submit-translations$/i) {
    144     # This command cannot produce any output since it reads input
    145     &submit_translations(@gti_command_arguments);
    146     }
    147     if ($gti_command =~ /^create-glihelp-zip-file$/i) {
    148     # This command cannot produce any output since it reads input
    149     &create_glihelp_zip_file(@gti_command_arguments);
    150     }
    151 #    else {
    152     # The command was not recognized
    153     #&throw_fatal_error("Unknown command \"$gti_command\".");
    154     #}
     119        # Check that GS3 interface is the target
     120        if ($module eq "gs3interface") {       
     121            print &get_all_chunks_for_gs3(@gti_command_arguments);
     122        } else {
     123            print &get_all_chunks(@gti_command_arguments);
     124        }
     125    }
     126    elsif ($gti_command =~ /^get-first-n-chunks-requiring-work$/i) {
     127        if ($module eq "gs3interface") {       
     128            print &get_first_n_chunks_requiring_work_for_gs3(@gti_command_arguments);
     129        } else {
     130            print &get_first_n_chunks_requiring_work(@gti_command_arguments);
     131        }
     132    }
     133    elsif ($gti_command =~ /^get-language-status$/i) {
     134        print &get_language_status(@gti_command_arguments);       
     135    }
     136    elsif ($gti_command =~ /^search-chunks$/i) {
     137        print &search_chunks(@gti_command_arguments);
     138    }
     139    elsif ($gti_command =~ /^submit-translations$/i) {
     140        # This command cannot produce any output since it reads input
     141        &submit_translations(@gti_command_arguments);
     142    }
     143    elsif ($gti_command =~ /^create-glihelp-zip-file$/i) {
     144        # This command cannot produce any output since it reads input
     145        &create_glihelp_zip_file(@gti_command_arguments);
     146    }
     147    else {
     148        # The command was not recognized
     149        &throw_fatal_error("Unknown command \"$gti_command\".");
     150    }
    155151}
    156152
     
    159155{
    160156    my $error_message = shift(@_);
    161 
     157   
    162158    # Write an XML error response
    163159    print "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
     
    165161    print "  <GTIError time=\"" . time() . "\">" . $error_message . "</GTIError>\n";
    166162    print "</GTIResponse>\n";
    167 
     163   
    168164    # Log the error message, then die
    169165    &log_message("Error: $error_message");
     
    185181    # The key of the file to translate (ensure it is lowercase)
    186182    my $translation_file_key = lc(shift(@_));
    187 
     183   
    188184    # Check that the necessary arguments were supplied
    189185    if (!$target_language_code || !$translation_file_key) {
    190     &throw_fatal_error("Missing command argument.");
    191     }
    192 
     186        &throw_fatal_error("Missing command argument.");
     187    }
     188   
    193189    # Get (and check) the translation configuration
    194190    my ($source_file, $target_file, $translation_file_type)
    195191    = &get_translation_configuration($target_language_code, $translation_file_key);
    196 
     192   
    197193    # Parse the source language and target language files
    198194    my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
     
    203199    my @target_file_lines = &read_file_lines($target_file_path);
    204200    my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
    205 
     201   
    206202    # Filter out any automatically translated chunks
    207203    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
    208     if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
    209         delete $source_file_key_to_line_mapping{$chunk_key};
    210         delete $target_file_key_to_line_mapping{$chunk_key};
    211     }
    212     }
    213 
     204        if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
     205            delete $source_file_key_to_line_mapping{$chunk_key};
     206            delete $target_file_key_to_line_mapping{$chunk_key};
     207        }
     208    }
     209   
    214210    my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
    215211    my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
    216212    &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
    217213    &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
    218 
     214   
    219215    my %source_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($source_file, \@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
    220216    my %target_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($target_file, \@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
    221 
     217   
    222218    my $xml_response = &create_xml_response_for_all_chunks($translation_file_key, $target_file, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping, \%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);   
    223219   
     
    234230    # The number of chunks to return (defaults to one if not specified)
    235231    my $num_chunks_to_return = shift(@_) || "1";
    236 
     232   
    237233    # Check that the necessary arguments were supplied
    238234    if (!$target_language_code || !$translation_file_key) {
    239     &throw_fatal_error("Missing command argument.");
    240     }
    241 
     235        &throw_fatal_error("Missing command argument.");
     236    }
     237   
    242238    # Get (and check) the translation configuration
    243239    my ($source_file, $target_file, $translation_file_type)
    244240    = &get_translation_configuration($target_language_code, $translation_file_key);
    245 
     241   
    246242    # Parse the source language and target language files
    247243    my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
     
    252248    my @target_file_lines = &read_file_lines($target_file_path);
    253249    my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
    254 
     250   
    255251    # Filter out any automatically translated chunks
    256252    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
    257     if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
    258         delete $source_file_key_to_line_mapping{$chunk_key};
    259         delete $target_file_key_to_line_mapping{$chunk_key};
    260     }
    261     }
    262 
     253        if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
     254            delete $source_file_key_to_line_mapping{$chunk_key};
     255            delete $target_file_key_to_line_mapping{$chunk_key};
     256        }
     257    }
     258   
    263259    my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
    264260    my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
    265261    &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
    266262    &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
    267 
     263   
    268264    # Determine the target file chunks requiring translation
    269265    my @target_file_keys_requiring_translation = &determine_chunks_requiring_translation(\%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping);
    270266    &log_message("Number of target chunks requiring translation: " . scalar(@target_file_keys_requiring_translation));
    271 
     267   
    272268    # Determine the target file chunks requiring updating
    273269    my %source_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($source_file, \@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
     
    275271    my @target_file_keys_requiring_updating = &determine_chunks_requiring_updating(\%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);
    276272    &log_message("Number of target chunks requiring updating: " . scalar(@target_file_keys_requiring_updating));
    277 
     273   
    278274    my $xml_response = &create_xml_response_for_chunks_requiring_work($translation_file_key, $target_file, scalar(keys(%source_file_key_to_text_mapping)), \@target_file_keys_requiring_translation, \@target_file_keys_requiring_updating, $num_chunks_to_return, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping, \%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);   
    279275   
     
    286282    # The code of the target language (ensure it is lowercase)
    287283    my $target_language_code = lc(shift(@_));
    288 
     284   
    289285    # Check that the necessary arguments were supplied
    290286    if (!$target_language_code) {
    291     &throw_fatal_error("Missing command argument.");
    292     }
    293 
     287        &throw_fatal_error("Missing command argument.");
     288    }
     289   
    294290    # Form an XML response to the command
    295291    my $xml_response = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
    296292    $xml_response .= "<GTIResponse>\n";
    297293    $xml_response .= "  <LanguageStatus code=\"$target_language_code\">\n";
    298 
     294   
    299295    foreach my $translation_file (@$gti_translation_files) {   
    300     my ($num_source_chunks, $num_target_chunks, $num_chunks_requiring_translation, $num_chunks_requiring_updating) = 0;
    301     my $target_file_name = "";
    302    
    303     if ($translation_file->{'key'} eq "gs3interface") {
    304         my (%source_file_key_to_text_mapping, %target_file_key_to_text_mapping, %source_file_key_to_last_update_date_mapping, %target_file_key_to_last_update_date_mapping ) = ();
    305         &build_gs3_configuration($target_language_code, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping, \%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping );   
    306        
    307         my @target_file_keys_requiring_translation = &determine_chunks_requiring_translation(\%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping);     
    308         my @target_file_keys_requiring_updating = &determine_chunks_requiring_updating(\%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);
    309 
    310         $num_source_chunks = scalar(keys(%source_file_key_to_text_mapping));
    311         $num_target_chunks = scalar(keys(%target_file_key_to_text_mapping));
    312         $num_chunks_requiring_translation = scalar(@target_file_keys_requiring_translation);
    313         $num_chunks_requiring_updating = scalar(@target_file_keys_requiring_updating);
    314     }
    315     else {
    316         # Get (and check) the translation configuration
    317         my ($source_file, $target_file, $translation_file_type) = &get_translation_configuration($target_language_code, $translation_file->{'key'});
    318         $target_file_name = $target_file;
    319 
    320         # Parse the source language and target language files
    321         my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
    322         my @source_file_lines = &read_file_lines($source_file_path);
    323         my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
    324 
    325         my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
    326         my @target_file_lines = &read_file_lines($target_file_path);
    327         my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
    328 
    329         # Filter out any automatically translated chunks
    330         foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
    331         if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
    332             delete $source_file_key_to_line_mapping{$chunk_key};
    333             delete $target_file_key_to_line_mapping{$chunk_key};
    334         }
    335         }
    336 
    337         my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
    338         my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
    339 
    340         # Determine the target file chunks requiring translation
    341         my @target_file_keys_requiring_translation = &determine_chunks_requiring_translation(\%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping);     
    342 
    343         # Determine the target file chunks requiring updating
    344         my @target_file_keys_requiring_updating = ();
    345         if (-e $target_file_path) {
    346         my %source_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($source_file, \@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
    347         my %target_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($target_file, \@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
    348         @target_file_keys_requiring_updating = &determine_chunks_requiring_updating(\%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);     
    349         }
    350 
    351         $num_source_chunks = scalar(keys(%source_file_key_to_text_mapping));
    352         $num_target_chunks = scalar(keys(%target_file_key_to_text_mapping));
    353         $num_chunks_requiring_translation = scalar(@target_file_keys_requiring_translation);
    354         $num_chunks_requiring_updating = scalar(@target_file_keys_requiring_updating);
    355     }
    356    
    357     &log_message("Status of " . $translation_file->{'key'});
    358     &log_message("Number of source chunks: " . $num_source_chunks);
    359     &log_message("Number of target chunks: " . $num_target_chunks);
    360     &log_message("Number of target chunks requiring translation: " . $num_chunks_requiring_translation);
    361     &log_message("Number of target chunks requiring updating: " . $num_chunks_requiring_updating);
    362 
    363     $xml_response .= "    <TranslationFile"
     296        my ($num_source_chunks, $num_target_chunks, $num_chunks_requiring_translation, $num_chunks_requiring_updating) = 0;
     297        my $target_file_name = "";
     298       
     299        if ($translation_file->{'key'} eq "gs3interface") {
     300            my (%source_file_key_to_text_mapping, %target_file_key_to_text_mapping, %source_file_key_to_last_update_date_mapping, %target_file_key_to_last_update_date_mapping ) = ();
     301            &build_gs3_configuration($target_language_code, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping, \%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping );   
     302           
     303            my @target_file_keys_requiring_translation = &determine_chunks_requiring_translation(\%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping);     
     304            my @target_file_keys_requiring_updating = &determine_chunks_requiring_updating(\%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);
     305           
     306            $num_source_chunks = scalar(keys(%source_file_key_to_text_mapping));
     307            $num_target_chunks = scalar(keys(%target_file_key_to_text_mapping));
     308            $num_chunks_requiring_translation = scalar(@target_file_keys_requiring_translation);
     309            $num_chunks_requiring_updating = scalar(@target_file_keys_requiring_updating);
     310        }
     311        else {
     312            # Get (and check) the translation configuration
     313            my ($source_file, $target_file, $translation_file_type) = &get_translation_configuration($target_language_code, $translation_file->{'key'});
     314            $target_file_name = $target_file;
     315           
     316            # Parse the source language and target language files
     317            my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
     318            my @source_file_lines = &read_file_lines($source_file_path);
     319            my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
     320           
     321            my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
     322            my @target_file_lines = &read_file_lines($target_file_path);
     323            my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
     324           
     325            # Filter out any automatically translated chunks
     326            foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
     327                if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
     328                    delete $source_file_key_to_line_mapping{$chunk_key};
     329                    delete $target_file_key_to_line_mapping{$chunk_key};
     330                }
     331            }
     332           
     333            my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
     334            my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
     335           
     336            # Determine the target file chunks requiring translation
     337            my @target_file_keys_requiring_translation = &determine_chunks_requiring_translation(\%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping);     
     338           
     339            # Determine the target file chunks requiring updating
     340            my @target_file_keys_requiring_updating = ();
     341            if (-e $target_file_path) {
     342                my %source_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($source_file, \@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
     343                my %target_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($target_file, \@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
     344                @target_file_keys_requiring_updating = &determine_chunks_requiring_updating(\%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);     
     345            }
     346           
     347            $num_source_chunks = scalar(keys(%source_file_key_to_text_mapping));
     348            $num_target_chunks = scalar(keys(%target_file_key_to_text_mapping));
     349            $num_chunks_requiring_translation = scalar(@target_file_keys_requiring_translation);
     350            $num_chunks_requiring_updating = scalar(@target_file_keys_requiring_updating);
     351        }
     352       
     353        &log_message("Status of " . $translation_file->{'key'});
     354        &log_message("Number of source chunks: " . $num_source_chunks);
     355        &log_message("Number of target chunks: " . $num_target_chunks);
     356        &log_message("Number of target chunks requiring translation: " . $num_chunks_requiring_translation);
     357        &log_message("Number of target chunks requiring updating: " . $num_chunks_requiring_updating);
     358       
     359        $xml_response .= "    <TranslationFile"
    364360        . " key=\"" . $translation_file->{'key'} . "\""
    365361        . " target_file_path=\"" . $target_file_name . "\""
     
    368364        . " num_chunks_requiring_updating=\"" . $num_chunks_requiring_updating . "\"\/>\n";
    369365    }
    370 
     366   
    371367    $xml_response .= "  </LanguageStatus>\n";
    372 
     368   
    373369    $xml_response .= "</GTIResponse>\n";
    374370    return $xml_response;
     
    384380    # The query string
    385381    my $query_string = join(' ', @_);
    386 
     382   
    387383    # Check that the necessary arguments were supplied
    388384    if (!$target_language_code || !$translation_file_key || !$query_string) {
    389     &throw_fatal_error("Missing command argument.");
    390     }
    391 
     385        &throw_fatal_error("Missing command argument.");
     386    }
     387   
    392388    my ($source_file, $target_file, $translation_file_type) = ();
    393389    my %source_file_key_to_text_mapping = ();
     
    396392   
    397393    if ($translation_file_key ne "gs3interface") {
    398     # Get (and check) the translation configuration
    399     ($source_file, $target_file, $translation_file_type) = &get_translation_configuration($target_language_code, $translation_file_key);
    400 
    401     # Parse the source language and target language files
    402     my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
    403     my @source_file_lines = &read_file_lines($source_file_path);
    404     my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
    405 
    406     my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
    407     my @target_file_lines = &read_file_lines($target_file_path);
    408     my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
    409 
    410     # Filter out any automatically translated chunks
    411     foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
    412         if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
    413         delete $source_file_key_to_line_mapping{$chunk_key};
    414         delete $target_file_key_to_line_mapping{$chunk_key};
    415         }
    416     }
    417 
    418     %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
    419     %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
     394        # Get (and check) the translation configuration
     395        ($source_file, $target_file, $translation_file_type) = &get_translation_configuration($target_language_code, $translation_file_key);
     396       
     397        # Parse the source language and target language files
     398        my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
     399        my @source_file_lines = &read_file_lines($source_file_path);
     400        my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
     401       
     402        my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
     403        my @target_file_lines = &read_file_lines($target_file_path);
     404        my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
     405       
     406        # Filter out any automatically translated chunks
     407        foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
     408            if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
     409                delete $source_file_key_to_line_mapping{$chunk_key};
     410                delete $target_file_key_to_line_mapping{$chunk_key};
     411            }
     412        }
     413       
     414        %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
     415        %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
    420416    }
    421417    else {
    422     # Not needed in this case
    423     my (%source_file_key_to_gti_command_mapping, %target_file_key_to_gti_command_mapping) = ();
    424     &build_gs3_configuration($target_language_code, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping,
    425                  \%source_file_key_to_gti_command_mapping, \%target_file_key_to_gti_command_mapping);
    426     }
    427 
     418        # Not needed in this case
     419        my (%source_file_key_to_gti_command_mapping, %target_file_key_to_gti_command_mapping) = ();
     420        &build_gs3_configuration($target_language_code, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping,
     421        \%source_file_key_to_gti_command_mapping, \%target_file_key_to_gti_command_mapping);
     422    }
     423   
    428424    &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
    429425    &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
    430 
     426   
    431427    # Determine the target file chunks matching the query
    432428    my @target_file_keys_matching_query = ();
    433429    foreach my $chunk_key (keys(%target_file_key_to_text_mapping)) {
    434     my $target_file_text = $target_file_key_to_text_mapping{$chunk_key};
    435     if ($target_file_text =~ /$query_string/i) {
    436         # &log_message("Chunk with key $chunk_key matches query.");
    437         push(@target_file_keys_matching_query, $chunk_key);
    438     }
    439     }
    440 
     430        my $target_file_text = $target_file_key_to_text_mapping{$chunk_key};
     431        if ($target_file_text =~ /$query_string/i) {
     432            # &log_message("Chunk with key $chunk_key matches query.");
     433            push(@target_file_keys_matching_query, $chunk_key);
     434        }
     435    }
     436   
    441437    # Form an XML response to the command
    442438    my $xml_response = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
    443439    $xml_response .= "<GTIResponse>\n";
    444 
     440   
    445441    $xml_response .= "  <ChunksMatchingQuery size=\"" . scalar(@target_file_keys_matching_query) . "\">\n";
    446442    foreach my $chunk_key (@target_file_keys_matching_query) {
    447     my $target_file_chunk_text = &make_text_xml_safe($target_file_key_to_text_mapping{$chunk_key});
    448 
    449     $xml_response .= "    <Chunk key=\"$chunk_key\">\n";
    450     $xml_response .= "      <TargetFileText>$target_file_chunk_text</TargetFileText>\n";
    451     $xml_response .= "    </Chunk>\n";
     443        my $target_file_chunk_text = &make_text_xml_safe($target_file_key_to_text_mapping{$chunk_key});
     444       
     445        $xml_response .= "    <Chunk key=\"$chunk_key\">\n";
     446        $xml_response .= "      <TargetFileText>$target_file_chunk_text</TargetFileText>\n";
     447        $xml_response .= "    </Chunk>\n";
    452448    }
    453449    $xml_response .= "  </ChunksMatchingQuery>\n";
    454 
     450   
    455451    $xml_response .= "</GTIResponse>\n";
    456452    return $xml_response;
     
    468464    # Whether to submit a target chunk even if it hasn't changed
    469465    my $force_submission_flag = shift(@_);
    470 
     466   
    471467    # Check that the necessary arguments were supplied
    472468    if (!$target_language_code || !$translation_file_key || !$submitter_username) {
    473     &log_message("Fatal error (but cannot be thrown): Missing command argument.");
    474     die "\n";
     469        &log_message("Fatal error (but cannot be thrown): Missing command argument.");
     470        die "\n";
    475471    }
    476472   
     
    479475    my %target_file_key_to_text_mapping = ();
    480476    my %target_file_key_to_gti_comment_mapping = ();
    481 
     477   
    482478    my (@source_file_lines, @target_file_lines) = ();
    483479    my ($source_file, $target_file, $translation_file_type);
    484 
     480   
    485481   
    486482    if ($translation_file_key ne "gs3interface") {
    487     # Get (and check) the translation configuration
    488     ($source_file, $target_file, $translation_file_type)
     483        # Get (and check) the translation configuration
     484        ($source_file, $target_file, $translation_file_type)
    489485        = &get_translation_configuration($target_language_code, $translation_file_key);
    490 
    491     # Parse the source language and target language files
    492     @source_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $source_file));
    493     my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
    494     %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
    495     %source_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);   
    496 
    497     @target_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $target_file));
    498     my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
    499     %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
    500     %target_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);   
     486       
     487        # Parse the source language and target language files
     488        @source_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $source_file));
     489        my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
     490        %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
     491        %source_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);   
     492       
     493        @target_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $target_file));
     494        my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
     495        %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
     496        %target_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);   
    501497    }
    502498    else {
    503     &build_gs3_configuration($target_language_code, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping,
    504                  \%source_file_key_to_gti_comment_mapping, \%target_file_key_to_gti_comment_mapping);
     499        &build_gs3_configuration($target_language_code, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping,
     500        \%source_file_key_to_gti_comment_mapping, \%target_file_key_to_gti_comment_mapping);
    505501    }
    506502    &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
    507503    &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
    508 
     504   
    509505    # Submission date
    510506    my $day = (localtime)[3];
     
    512508    my $year = (localtime)[5] + 1900;
    513509    my $submission_date = "$day-$month-$year";
    514 
     510   
    515511    open(SUBMISSION, "-");
    516512    my @submission_lines = <SUBMISSION>;
    517513    close(SUBMISSION);
    518 
     514   
    519515    # Remove any nasty carriage returns
    520516    # &log_message("Submission:");
    521517    foreach my $submission_line (@submission_lines) {
    522     $submission_line =~ s/\r$//;
    523     #&log_message("  $submission_line");
    524     }
    525 
     518        $submission_line =~ s/\r$//;
     519        #&log_message("  $submission_line");
     520    }
     521   
    526522    my %source_file_key_to_submission_mapping = ();
    527523    my %target_file_key_to_submission_mapping = ();
    528524    for (my $i = 0; $i < scalar(@submission_lines); $i++) {
    529     # Read source file part of submission
    530     if ($submission_lines[$i] =~ /^\<SourceFileText key=\"(.+)\"\>/) {
    531         my $chunk_key = $1;
    532 
    533         # Read the source file text
    534         my $source_file_chunk_text = "";
    535         $i++;
    536         while ($i < scalar(@submission_lines) && $submission_lines[$i] !~ /^\<\/SourceFileText\>/) {
    537         $source_file_chunk_text .= $submission_lines[$i];
    538         $i++;
    539         }
    540         $source_file_chunk_text =~ s/\n$//;  # Strip the extra newline character added
    541         $source_file_chunk_text = &unmake_text_xml_safe($source_file_chunk_text);
    542 
    543         #&log_message("Source file key: $chunk_key");
    544         #&log_message("Source file text: $source_file_chunk_text");
    545         $source_file_key_to_submission_mapping{$chunk_key} = $source_file_chunk_text;
    546     }
    547 
    548     # Read target file part of submission
    549     if ($submission_lines[$i] =~ /^\<TargetFileText key=\"(.+)\"\>/) {
    550         my $chunk_key = $1;
    551 
    552         # Read the target file text
    553         my $target_file_chunk_text = "";
    554         $i++;
    555         while ($i < scalar(@submission_lines) && $submission_lines[$i] !~ /^\<\/TargetFileText\>/) {
    556         $target_file_chunk_text .= $submission_lines[$i];
    557         $i++;
    558         }
    559         $target_file_chunk_text =~ s/\n$//;  # Strip the extra newline character added
    560         $target_file_chunk_text = &unmake_text_xml_safe($target_file_chunk_text);
    561 
    562         #&log_message("Target file key: $chunk_key");
    563         #&log_message("Target file text: $target_file_chunk_text");
    564         $target_file_key_to_submission_mapping{$chunk_key} = $target_file_chunk_text;
    565     }
    566     }
    567 
     525        # Read source file part of submission
     526        if ($submission_lines[$i] =~ /^\<SourceFileText key=\"(.+)\"\>/) {
     527            my $chunk_key = $1;
     528           
     529            # Read the source file text
     530            my $source_file_chunk_text = "";
     531            $i++;
     532            while ($i < scalar(@submission_lines) && $submission_lines[$i] !~ /^\<\/SourceFileText\>/) {
     533                $source_file_chunk_text .= $submission_lines[$i];
     534                $i++;
     535            }
     536            $source_file_chunk_text =~ s/\n$//;  # Strip the extra newline character added
     537            $source_file_chunk_text = &unmake_text_xml_safe($source_file_chunk_text);
     538           
     539            #&log_message("Source file key: $chunk_key");
     540            #&log_message("Source file text: $source_file_chunk_text");
     541            $source_file_key_to_submission_mapping{$chunk_key} = $source_file_chunk_text;
     542        }
     543       
     544        # Read target file part of submission
     545        if ($submission_lines[$i] =~ /^\<TargetFileText key=\"(.+)\"\>/) {
     546            my $chunk_key = $1;
     547           
     548            # Read the target file text
     549            my $target_file_chunk_text = "";
     550            $i++;
     551            while ($i < scalar(@submission_lines) && $submission_lines[$i] !~ /^\<\/TargetFileText\>/) {
     552                $target_file_chunk_text .= $submission_lines[$i];
     553                $i++;
     554            }
     555            $target_file_chunk_text =~ s/\n$//;  # Strip the extra newline character added
     556            $target_file_chunk_text = &unmake_text_xml_safe($target_file_chunk_text);
     557           
     558            #&log_message("Target file key: $chunk_key");
     559            #&log_message("Target file text: $target_file_chunk_text");
     560            $target_file_key_to_submission_mapping{$chunk_key} = $target_file_chunk_text;
     561        }
     562    }
     563   
    568564    # -----------------------------------------
    569565    #   Validate the translation submissions
    570566    # -----------------------------------------
    571 
     567   
    572568    # Check that the translations are valid
    573569    foreach my $chunk_key (keys(%source_file_key_to_submission_mapping)) {
    574     # Make sure the submitted chunk still exists in the source file
    575     if (!defined($source_file_key_to_text_mapping{$chunk_key})) {
    576         &log_message("Warning: Source chunk $chunk_key no longer exists (ignoring submission).");
    577         delete $source_file_key_to_submission_mapping{$chunk_key};
    578         delete $target_file_key_to_submission_mapping{$chunk_key};
    579         next;
    580     }
    581 
    582     # Make sure the submitted source chunk matches the source file chunk
    583     if ($source_file_key_to_submission_mapping{$chunk_key} ne &unmake_text_xml_safe($source_file_key_to_text_mapping{$chunk_key})) {
    584         &log_message("Warning: Source chunk $chunk_key has changed (ignoring submission).");
    585         &log_message("Submission source: $source_file_key_to_submission_mapping{$chunk_key}");
    586         &log_message("      Source text: $source_file_key_to_text_mapping{$chunk_key}");
    587         delete $source_file_key_to_submission_mapping{$chunk_key};
    588         delete $target_file_key_to_submission_mapping{$chunk_key};
    589         next;
    590     }
    591     }
    592 
     570        # Make sure the submitted chunk still exists in the source file
     571        if (!defined($source_file_key_to_text_mapping{$chunk_key})) {
     572            &log_message("Warning: Source chunk $chunk_key no longer exists (ignoring submission).");
     573            delete $source_file_key_to_submission_mapping{$chunk_key};
     574            delete $target_file_key_to_submission_mapping{$chunk_key};
     575            next;
     576        }
     577       
     578        # Make sure the submitted source chunk matches the source file chunk
     579        if ($source_file_key_to_submission_mapping{$chunk_key} ne &unmake_text_xml_safe($source_file_key_to_text_mapping{$chunk_key})) {
     580            &log_message("Warning: Source chunk $chunk_key has changed (ignoring submission).");
     581            &log_message("Submission source: $source_file_key_to_submission_mapping{$chunk_key}");
     582            &log_message("      Source text: $source_file_key_to_text_mapping{$chunk_key}");
     583            delete $source_file_key_to_submission_mapping{$chunk_key};
     584            delete $target_file_key_to_submission_mapping{$chunk_key};
     585            next;
     586        }
     587    }
     588   
    593589    # Apply the submitted translations
    594590    foreach my $chunk_key (keys(%target_file_key_to_submission_mapping)) {
    595     # Only apply the submission if it is a change, unless -force_submission has been specified
    596     if ($force_submission_flag || !defined($target_file_key_to_text_mapping{$chunk_key}) || $target_file_key_to_submission_mapping{$chunk_key} ne $target_file_key_to_text_mapping{$chunk_key}) {
    597         $target_file_key_to_text_mapping{$chunk_key} = $target_file_key_to_submission_mapping{$chunk_key};
    598         $target_file_key_to_gti_comment_mapping{$chunk_key} = "Updated $submission_date by $submitter_username";
    599     }
     591        # Only apply the submission if it is a change, unless -force_submission has been specified
     592        if ($force_submission_flag || !defined($target_file_key_to_text_mapping{$chunk_key}) || $target_file_key_to_submission_mapping{$chunk_key} ne $target_file_key_to_text_mapping{$chunk_key}) {
     593            $target_file_key_to_text_mapping{$chunk_key} = $target_file_key_to_submission_mapping{$chunk_key};
     594            $target_file_key_to_gti_comment_mapping{$chunk_key} = "Updated $submission_date by $submitter_username";
     595        }
    600596    }
    601597   
    602598    if ($translation_file_key ne "gs3interface") {
    603     eval "&write_translated_${translation_file_type}(\$source_file, \\\@source_file_lines, \\\%source_file_key_to_text_mapping, \$target_file, \\\@target_file_lines, \\\%target_file_key_to_text_mapping, \\\%target_file_key_to_gti_comment_mapping, \$target_language_code)";
     599        eval "&write_translated_${translation_file_type}(\$source_file, \\\@source_file_lines, \\\%source_file_key_to_text_mapping, \$target_file, \\\@target_file_lines, \\\%target_file_key_to_text_mapping, \\\%target_file_key_to_gti_comment_mapping, \$target_language_code)";
    604600    } else {
    605     eval "&write_translated_gs3interface(\\\%source_file_key_to_text_mapping, \\\%target_file_key_to_text_mapping, \\\%target_file_key_to_gti_comment_mapping, \$target_language_code)";
     601        eval "&write_translated_gs3interface(\\\%source_file_key_to_text_mapping, \\\%target_file_key_to_text_mapping, \\\%target_file_key_to_gti_comment_mapping, \$target_language_code)";
    606602    }
    607603}
     
    614610   
    615611    &log_message("Creating GLI Help zip file for $target_language_code");
    616 
     612   
    617613    my ($source_file, $target_file, $translation_file_type) = &get_translation_data_for($target_language_code, $translation_file_key);   
    618614   
    619615    my $classpath = &util::filename_cat($gsdl_root_directory, "gti-lib");
    620616    if ( ! -e $classpath) {
    621     &throw_fatal_error("$classpath doesn't exist! Need the files in this directory (ApplyXLST and its related files) to create the zip file for GLI Help");
     617        &throw_fatal_error("$classpath doesn't exist! Need the files in this directory (ApplyXLST and its related files) to create the zip file for GLI Help");
    622618    }   
    623619   
     
    627623    my $gen_many_html_xsl_filepath = &util::filename_cat($gli_help_directory, "gen-many-html.xsl");
    628624    if ( ! -e $gen_many_html_xsl_filepath) {
    629     &throw_fatal_error("$gen_many_html_xsl_filepath doesn't exist! Need this file to create the zip file for GLI Help");
    630     }
    631 
     625        &throw_fatal_error("$gen_many_html_xsl_filepath doesn't exist! Need this file to create the zip file for GLI Help");
     626    }
     627   
    632628    my $gen_index_xml_xsl_filepath = &util::filename_cat($gli_help_directory, "gen-index-xml.xsl");   
    633629    my $split_script_filepath = &util::filename_cat($gli_help_directory, "splithelpdocument.pl");   
     
    635631    my $target_file_directory = &util::filename_cat($gli_help_directory, $target_language_code);
    636632    $target_file_directory = $target_file_directory."/";
    637 
     633   
    638634    my $target_filepath = &util::filename_cat($gsdl_root_directory, $target_file);
    639     my $perl_exec = &util::get_perl_exec();
    640     my $java_exec = "java";
    641     if(defined($ENV{'JAVA_HOME'}) && $ENV{'JAVA_HOME'} ne ""){
    642     $java_exec = &util::filename_cat($ENV{'JAVA_HOME'}, "bin", "java");
    643     }
    644 
     635   
     636    my $perl_exec = &util::get_perl_exec();
     637    my $java_exec = "java";
     638    if(defined($ENV{'JAVA_HOME'}) && $ENV{'JAVA_HOME'} ne ""){
     639        $java_exec = &util::filename_cat($ENV{'JAVA_HOME'}, "bin", "java");
     640    }
     641   
    645642    my $cmd = "$java_exec -cp $classpath:$classpath/xalan.jar ApplyXSLT $target_language_code $gen_many_html_xsl_filepath $target_filepath | \"$perl_exec\" -S $split_script_filepath $target_file_directory";
    646643    my $response = `$cmd`;
    647     &log_message($cmd);
    648     &log_message($response);   
    649     &log_message("Created HTML operational files");
    650    
     644       
    651645    $cmd = "$java_exec -cp $classpath:$classpath/xalan.jar ApplyXSLT $target_language_code $gen_index_xml_xsl_filepath $target_filepath > " . $target_file_directory . "help_index.xml"; # 2>/dev/null";
    652646    $response = `$cmd`;
    653     &log_message($cmd);
    654     &log_message($response);   
    655     &log_message("Created xml index file");
    656 
     647   
    657648    my $zip_file_path = "/greenstone/custom/gti/" . $target_language_code . "_GLIHelp.zip";
    658649    $cmd = "zip -rj $zip_file_path $target_file_directory -i \*.htm \*.xml";
    659650    $response = `$cmd`;
    660     &log_message($cmd);
    661     &log_message($response);   
    662     &log_message("Created the zip file");
    663651}
    664652
     
    670658    # Get the key of the file to translate
    671659    my $translation_file_key = shift(@_);
    672 
     660   
    673661    # Read the translation data from the gti.cfg file
    674662    my ($source_file, $target_file, $translation_file_type) =
    675663    &get_translation_data_for($target_language_code, $translation_file_key);
    676 
     664   
    677665    # Check that the file to translate is defined in the gti.cfg file
    678666    if (!$source_file || !$target_file || !$translation_file_type) {
    679     &throw_fatal_error("Missing or incomplete specification for translation file \"$translation_file_key\" in gti.pl.");
    680     }
    681 
     667        &throw_fatal_error("Missing or incomplete specification for translation file \"$translation_file_key\" in gti.pl.");
     668    }
     669   
    682670    # Check that the source file exists
    683671    my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
    684672    if (!-e $source_file_path) {
    685     &throw_fatal_error("Source file $source_file_path does not exist.");
    686     }
    687 
     673        &throw_fatal_error("Source file $source_file_path does not exist.");
     674    }
     675   
    688676    # Check that the source file is up to date
    689677    # The "2>/dev/null" is very important! If it is missing this will never return when run from the receptionist
    690678    # unless ($translation_file_is_not_in_cvs) {
    691679    #my $source_file_cvs_status = `cd $gsdl_root_directory; cvs -d $anonymous_cvs_root update $source_file 2>/dev/null`;
    692         my $source_file_cvs_status = `cd $gsdl_root_directory; svn status $source_file 2>/dev/null`;
     680    my $source_file_cvs_status = `cd $gsdl_root_directory; svn status $source_file 2>/dev/null`;
    693681    if ($source_file_cvs_status =~ /^C /) {
    694682        &throw_fatal_error("Source file $source_file_path conflicts with the repository.");
     
    698686    }
    699687    # }
    700 
     688   
    701689    return ($source_file, $target_file, $translation_file_type);
    702690}
     
    706694{
    707695    my ($target_language_code, $translation_file_key) = @_;
    708 
     696   
    709697    foreach my $translation_file (@$gti_translation_files) {
    710     # If this isn't the correct translation file, move onto the next one
    711     next if ($translation_file_key ne $translation_file->{'key'});
    712 
    713     # Resolve the target language file
    714     my $target_language_file = $translation_file->{'target_file'};
    715     if ($target_language_file =~ /(\{.+\;.+\})/) {
    716         my $unresolved_target_language_file_part = $1;
    717 
    718         # Check for a special case for the target language code
    719         if ($unresolved_target_language_file_part =~ /(\{|\;)$target_language_code:([^\;]+)(\;|\})/) {
    720         my $resolved_target_language_file_part = $2;
    721         $target_language_file =~ s/$unresolved_target_language_file_part/$resolved_target_language_file_part/;
    722         }
    723         # Otherwise use the last part as the default value
    724         else {
    725         my ($default_target_language_file_part) = $unresolved_target_language_file_part =~ /([^\;]+)\}/;
    726         $target_language_file =~ s/$unresolved_target_language_file_part/\{$default_target_language_file_part\}/;           
     698        # If this isn't the correct translation file, move onto the next one
     699        next if ($translation_file_key ne $translation_file->{'key'});
     700       
     701        # Resolve the target language file
     702        my $target_language_file = $translation_file->{'target_file'};
     703        if ($target_language_file =~ /(\{.+\;.+\})/) {
     704            my $unresolved_target_language_file_part = $1;
     705           
     706            # Check for a special case for the target language code
     707            if ($unresolved_target_language_file_part =~ /(\{|\;)$target_language_code:([^\;]+)(\;|\})/) {
     708                my $resolved_target_language_file_part = $2;
     709                $target_language_file =~ s/$unresolved_target_language_file_part/$resolved_target_language_file_part/;
     710            }
     711            # Otherwise use the last part as the default value
     712            else {
     713                my ($default_target_language_file_part) = $unresolved_target_language_file_part =~ /([^\;]+)\}/;
     714            $target_language_file =~ s/$unresolved_target_language_file_part/\{$default_target_language_file_part\}/;           
    727715        }
    728716    }
    729 
     717   
    730718    # Resolve instances of {iso_639_1_target_language_name}
    731719    my $iso_639_1_target_language_name = $iso639::fromiso639{$target_language_code};
    732720    $iso_639_1_target_language_name =~ tr/A-Z/a-z/ if $iso_639_1_target_language_name;
    733721    $target_language_file =~ s/\{iso_639_1_target_language_name\}/$iso_639_1_target_language_name/g;
    734 
     722   
    735723    # Resolve instances of {target_language_code}
    736724    $target_language_file =~ s/\{target_language_code\}/$target_language_code/g;
    737 
     725   
    738726    return ($translation_file->{'source_file'}, $target_language_file, $translation_file->{'file_type'});
    739     }
    740 
    741     return ();
     727}
     728
     729return ();
    742730}
    743731
     
    746734{
    747735    my ($file_path) = @_;
    748 
     736   
    749737    if (!open(FILE_IN, "<$file_path")) {
    750     &log_message("Note: Could not open file $file_path.");
    751     return ();
     738        &log_message("Note: Could not open file $file_path.");
     739        return ();
    752740    }
    753741    my @file_lines = <FILE_IN>;
    754742    close(FILE_IN);
    755 
     743   
    756744    return @file_lines;
    757745}
     
    768756{
    769757    my ($file_lines, $key_to_line_mapping, $translation_file_type) = @_;
    770 
     758   
    771759    my %key_to_text_mapping = ();
    772760    foreach my $chunk_key (keys(%$key_to_line_mapping)) {
    773     my $chunk_starting_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[0];
    774     my $chunk_finishing_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[1];
    775 
    776     my $chunk_text = @$file_lines[$chunk_starting_line];
    777     for (my $l = ($chunk_starting_line + 1); $l <= $chunk_finishing_line; $l++) {
    778         $chunk_text .= @$file_lines[$l];
    779     }
    780 
    781     # Map from chunk key to text
    782     eval "\$key_to_text_mapping{\${chunk_key}} = &import_chunk_from_${translation_file_type}(\$chunk_text)";
    783     }
    784 
     761        my $chunk_starting_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[0];
     762        my $chunk_finishing_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[1];
     763       
     764        my $chunk_text = @$file_lines[$chunk_starting_line];
     765        for (my $l = ($chunk_starting_line + 1); $l <= $chunk_finishing_line; $l++) {
     766            $chunk_text .= @$file_lines[$l];
     767        }
     768       
     769        # Map from chunk key to text
     770        eval "\$key_to_text_mapping{\${chunk_key}} = &import_chunk_from_${translation_file_type}(\$chunk_text)";
     771    }
     772   
    785773    return %key_to_text_mapping;
    786774}
     
    790778{
    791779    my ($file, $file_lines, $key_to_line_mapping, $translation_file_type) = @_;
    792 
     780   
    793781    # If the files aren't in CVS then we can't tell anything about what needs updating
    794782    # return () if ($translation_file_is_not_in_cvs);
    795 
     783   
    796784    # Build a mapping from key to CVS date
    797785    # Need to be careful with this mapping because the chunk keys won't necessarily all be valid
    798786    my %key_to_cvs_date_mapping = &build_key_to_cvs_date_mapping($file, $translation_file_type);
    799 
     787   
    800788    # Build a mapping from key to comment date
    801789    my %key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping($file_lines, $key_to_line_mapping, $translation_file_type);
    802 
     790   
    803791    # Build a mapping from key to last update date (the latter of the CVS date and comment date)
    804792    my %key_to_last_update_date_mapping = ();
    805793    foreach my $chunk_key (keys(%$key_to_line_mapping)) {
    806     # Use the CVS date as a starting point
    807     my $chunk_cvs_date = $key_to_cvs_date_mapping{$chunk_key};
    808     $key_to_last_update_date_mapping{$chunk_key} = $chunk_cvs_date;
    809 
    810     # If a comment date exists and it is after the CVS date, use that instead
     794        # Use the CVS date as a starting point
     795        my $chunk_cvs_date = $key_to_cvs_date_mapping{$chunk_key};
     796        $key_to_last_update_date_mapping{$chunk_key} = $chunk_cvs_date;
     797       
     798        # If a comment date exists and it is after the CVS date, use that instead
    811799        # need to convert the comment date format to SVN format
    812     my $chunk_gti_comment = $key_to_gti_comment_mapping{$chunk_key};
    813     if (defined($chunk_gti_comment) && $chunk_gti_comment =~ /(\d?\d-\D\D\D-\d\d\d\d)/) {
    814         my $chunk_comment_date = $1;           
    815         # if the changes were made on 2009 Jan 27, ie. tidying up the GTI commands following each fragment,
    816         # then should use the GTI comment date instead
    817         # if ((!defined($chunk_cvs_date) || &is_date_after($chunk_comment_date, $chunk_cvs_date))) {
    818         if ((!defined($chunk_cvs_date) || &is_date_after($chunk_comment_date, $chunk_cvs_date)
    819          || (&is_date_after($chunk_cvs_date,$chunk_comment_date) && ($chunk_cvs_date eq "2009-01-27" || $chunk_cvs_date eq "2009-01-28")))) {
    820         $key_to_last_update_date_mapping{$chunk_key} = $chunk_comment_date;
    821        
    822         # &log_message("cvs date: $chunk_cvs_date, comment date: $chunk_comment_date");
    823         # die;
    824         }
    825     }
    826     }
    827 
     800        my $chunk_gti_comment = $key_to_gti_comment_mapping{$chunk_key};
     801        if (defined($chunk_gti_comment) && $chunk_gti_comment =~ /(\d?\d-\D\D\D-\d\d\d\d)/) {
     802            my $chunk_comment_date = $1;           
     803            if ((!defined($chunk_cvs_date) || &is_date_after($chunk_comment_date, $chunk_cvs_date))) {
     804                $key_to_last_update_date_mapping{$chunk_key} = $chunk_comment_date;         
     805            }
     806        }
     807    }
     808   
    828809    return %key_to_last_update_date_mapping;
    829810}
     
    833814{
    834815    my ($filename, $translation_file_type) = @_;
    835 
    836     # Use CVS to annotate each line of the file with the date it was last edited
     816   
     817    # Use SVN to annotate each line of the file with the date it was last edited
    837818    # The "2>/dev/null" is very important! If it is missing this will never return when run from the receptionist
    838     # my $cvs_annotated_file = `cd $gsdl_root_directory; cvs -d $anonymous_cvs_root annotate -F $filename 2>/dev/null`;   
    839     # my $cvs_annotated_file = `cd $gsdl_root_directory; export PATH=.:/research/lh92/programs/subversion/bin; svn annotate -v --force $filename`;
    840     my $cvs_annotated_file = `cd $gsdl_root_directory; svn annotate -v $filename`;
     819    my $cvs_annotated_file = `cd $gsdl_root_directory; svn annotate -v --force $filename 2>/dev/null`;
    841820   
    842821    my @cvs_annotated_file_lines = split(/\n/, $cvs_annotated_file);
    843 
     822   
    844823    my @cvs_annotated_file_lines_date = ();
    845824    foreach my $cvs_annotated_file_line (@cvs_annotated_file_lines) {
    846     # Extract the date from the CVS annotation at the front
    847         # cvs format : 07-Jun-02
    848         # svn format : 2007-07-16
    849     # $cvs_annotated_file_line =~ s/^\S+\s+\(\S+\s+(\S+)\):\s//;
     825        # Extract the date from the SVN annotation at the front
     826        # svn format : 2007-07-16
    850827        $cvs_annotated_file_line =~ s/^\s+\S+\s+\S+\s(\S+)//;
    851828       
     
    859836    # Build a key to line mapping for the CVS annotated file, for matching the chunk key to the CVS date
    860837    my %key_to_line_mapping = &build_key_to_line_mapping(\@cvs_annotated_file_lines, $translation_file_type);
    861        
     838   
    862839    my %key_to_cvs_date_mapping = ();
    863840    foreach my $chunk_key (keys(%key_to_line_mapping)) {
    864     my $chunk_starting_line = (split(/-/, $key_to_line_mapping{$chunk_key}))[0];
    865     my $chunk_finishing_line = (split(/-/, $key_to_line_mapping{$chunk_key}))[1];
    866                
    867     # Find the date this chunk was last edited, from the CVS annotation
    868     my $chunk_date = $cvs_annotated_file_lines_date[$chunk_starting_line];       
    869     for (my $l = ($chunk_starting_line + 1); $l <= $chunk_finishing_line; $l++) {
    870         if (&is_date_after($cvs_annotated_file_lines_date[$l], $chunk_date)) {
    871         # This part of the chunk has been updated more recently
    872         $chunk_date = $cvs_annotated_file_lines_date[$l];
    873         
    874         }
    875     }
    876 
    877     # Map from chunk key to CVS date
    878     $key_to_cvs_date_mapping{$chunk_key} = $chunk_date;
    879     }
    880 
     841        my $chunk_starting_line = (split(/-/, $key_to_line_mapping{$chunk_key}))[0];
     842        my $chunk_finishing_line = (split(/-/, $key_to_line_mapping{$chunk_key}))[1];
     843       
     844        # Find the date this chunk was last edited, from the CVS annotation
     845        my $chunk_date = $cvs_annotated_file_lines_date[$chunk_starting_line];       
     846        for (my $l = ($chunk_starting_line + 1); $l <= $chunk_finishing_line; $l++) {
     847            if (&is_date_after($cvs_annotated_file_lines_date[$l], $chunk_date)) {
     848                # This part of the chunk has been updated more recently
     849                $chunk_date = $cvs_annotated_file_lines_date[$l];
     850               
     851            }
     852        }
     853       
     854        # Map from chunk key to CVS date
     855        $key_to_cvs_date_mapping{$chunk_key} = $chunk_date;
     856    }
     857   
    881858    return %key_to_cvs_date_mapping;
    882859}
     
    886863{
    887864    my ($file_lines, $key_to_line_mapping, $translation_file_type) = @_;
    888 
     865   
    889866    my %key_to_gti_comment_mapping = ();
    890867    foreach my $chunk_key (keys(%$key_to_line_mapping)) {
    891     my $chunk_starting_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[0];
    892     my $chunk_finishing_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[1];
    893 
    894     my $chunk_text = @$file_lines[$chunk_starting_line];
    895     for (my $l = ($chunk_starting_line + 1); $l <= $chunk_finishing_line; $l++) {
    896         $chunk_text .= @$file_lines[$l];
    897     }
    898 
    899     # Map from chunk key to GTI comment
    900     my $chunk_gti_comment;
    901     eval "\$chunk_gti_comment = &get_${translation_file_type}_chunk_gti_comment(\$chunk_text)";
    902     $key_to_gti_comment_mapping{$chunk_key} = $chunk_gti_comment if (defined($chunk_gti_comment));
    903     }
    904 
     868        my $chunk_starting_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[0];
     869        my $chunk_finishing_line = (split(/-/, $key_to_line_mapping->{$chunk_key}))[1];
     870       
     871        my $chunk_text = @$file_lines[$chunk_starting_line];
     872        for (my $l = ($chunk_starting_line + 1); $l <= $chunk_finishing_line; $l++) {
     873            $chunk_text .= @$file_lines[$l];
     874        }
     875       
     876        # Map from chunk key to GTI comment
     877        my $chunk_gti_comment;
     878        eval "\$chunk_gti_comment = &get_${translation_file_type}_chunk_gti_comment(\$chunk_text)";
     879        $key_to_gti_comment_mapping{$chunk_key} = $chunk_gti_comment if (defined($chunk_gti_comment));
     880    }
     881   
    905882    return %key_to_gti_comment_mapping;
    906883}
     
    911888    my $source_file_key_to_text_mapping = shift(@_);
    912889    my $target_file_key_to_text_mapping = shift(@_);
    913 
     890   
    914891    # Chunks needing translation are those in the source file with no translation in the target file
    915892    my @target_file_keys_requiring_translation = ();
    916893    foreach my $chunk_key (keys(%$source_file_key_to_text_mapping)) {
    917     if ($source_file_key_to_text_mapping->{$chunk_key} && !$target_file_key_to_text_mapping->{$chunk_key}) {
    918         # &log_message("Chunk with key $chunk_key needs translating.");
    919         push(@target_file_keys_requiring_translation, $chunk_key);
    920     }
    921     }
    922 
     894        if ($source_file_key_to_text_mapping->{$chunk_key} && !$target_file_key_to_text_mapping->{$chunk_key}) {
     895            # &log_message("Chunk with key $chunk_key needs translating.");
     896            push(@target_file_keys_requiring_translation, $chunk_key);
     897        }
     898    }
     899   
    923900    return @target_file_keys_requiring_translation;
    924901}
     
    929906    my $source_file_key_to_last_update_date_mapping = shift(@_);
    930907    my $target_file_key_to_last_update_date_mapping = shift(@_);
    931 
     908   
    932909    # Chunks needing updating are those in the target file that have been more recently edited in the source file
    933910    my @target_file_keys_requiring_updating = ();
    934911    foreach my $chunk_key (keys(%$source_file_key_to_last_update_date_mapping)) {
    935     my $source_chunk_last_update_date = $source_file_key_to_last_update_date_mapping->{$chunk_key};
    936     my $target_chunk_last_update_date = $target_file_key_to_last_update_date_mapping->{$chunk_key};
     912        my $source_chunk_last_update_date = $source_file_key_to_last_update_date_mapping->{$chunk_key};
     913        my $target_chunk_last_update_date = $target_file_key_to_last_update_date_mapping->{$chunk_key};
    937914       
    938915        # print "key: $chunk_key\nsource date : $source_chunk_last_update_date\ntarget date : $target_chunk_last_update_date\nafter? ". &is_date_after($source_chunk_last_update_date, $target_chunk_last_update_date) . "\n\n";       
    939                    
     916       
    940917        if (defined($target_chunk_last_update_date) && &is_date_after($source_chunk_last_update_date, $target_chunk_last_update_date)) {
    941         # &log_message("Chunk with key $chunk_key needs updating.");
    942         push(@target_file_keys_requiring_updating, $chunk_key);
    943     }
    944     }
    945 
     918            # &log_message("Chunk with key $chunk_key needs updating.");
     919            push(@target_file_keys_requiring_updating, $chunk_key);
     920        }
     921    }
     922   
    946923    return @target_file_keys_requiring_updating;
    947924}
     
    984961    my ($date1, $date2) = @_;
    985962    my %months = ("Jan", 1, "Feb", 2, "Mar", 3, "Apr",  4, "May",  5, "Jun",  6,
    986           "Jul", 7, "Aug", 8, "Sep", 9, "Oct", 10, "Nov", 11, "Dec", 12);
    987 
     963    "Jul", 7, "Aug", 8, "Sep", 9, "Oct", 10, "Nov", 11, "Dec", 12);
     964   
    988965    if(!defined $date1) {
    989966        return 1;
    990967    }
    991 
     968   
    992969    my @date1parts = split(/-/, $date1);
    993970    my @date2parts = split(/-/, $date2);
    994 
     971   
    995972    # Compare year - nasty because we have rolled over into a new century
    996973    my $year1 = $date1parts[2];
     
    1002979        $year2 += 2000;
    1003980    }
    1004 
     981   
    1005982    # Compare year
    1006983    if ($year1 > $year2) {
    1007     return 1;
     984        return 1;
    1008985    }
    1009986    elsif ($year1 == $year2) {
    1010     # Year is the same, so compare month
    1011     if ($months{$date1parts[1]} > $months{$date2parts[1]}) {
    1012         return 1;
    1013     }
    1014     elsif ($months{$date1parts[1]} == $months{$date2parts[1]}) {
    1015         # Month is the same, so compare day
    1016         if ($date1parts[0] > $date2parts[0]) {
     987        # Year is the same, so compare month
     988        if ($months{$date1parts[1]} > $months{$date2parts[1]}) {
     989            return 1;
     990        }
     991        elsif ($months{$date1parts[1]} == $months{$date2parts[1]}) {
     992            # Month is the same, so compare day
     993            if ($date1parts[0] > $date2parts[0]) {
     994                return 1;
     995            }
     996        }
     997    }
     998   
     999    return 0;
     1000}
     1001
     1002sub is_date_after
     1003{
     1004    my ($date1, $date2) = @_;
     1005   
     1006    if(!defined $date1) {
    10171007        return 1;
    1018         }
    1019     }
    1020     }
    1021 
    1022     return 0;
    1023 }
    1024 
    1025 sub is_date_after
    1026 {
    1027     my ($date1, $date2) = @_;
    1028    
    1029     if(!defined $date1) {
    1030       return 1;
    10311008    }
    10321009    if(!defined $date2) {
    1033       return 0;
     1010        return 0;
    10341011    }
    10351012   
    10361013    # 16-Aug-2006
    10371014    if($date1=~ /(\d+?)-(\S\S\S)-(\d\d\d\d)/){
    1038        my %months = ("Jan", "01", "Feb", "02", "Mar", "03", "Apr",  "04", "May",  "05", "Jun",  "06",
    1039           "Jul", "07", "Aug", "08", "Sep", "09", "Oct", "10", "Nov", "11", "Dec", "12");
    1040        $date1=$3 . "-" . $months{$2} . "-" . $1;
    1041        # print "** converted date1: $date1\n";
     1015        my %months = ("Jan", "01", "Feb", "02", "Mar", "03", "Apr",  "04", "May",  "05", "Jun",  "06",
     1016        "Jul", "07", "Aug", "08", "Sep", "09", "Oct", "10", "Nov", "11", "Dec", "12");
     1017        $date1=$3 . "-" . $months{$2} . "-" . $1;
     1018        # print "** converted date1: $date1\n";
    10421019    }
    10431020    if($date2=~ /(\d+?)-(\S\S\S)-(\d\d\d\d)/){
    1044        my %months = ("Jan", "01", "Feb", "02", "Mar", "03", "Apr",  "04", "May",  "05", "Jun",  "06",
    1045           "Jul", "07", "Aug", "08", "Sep", "09", "Oct", "10", "Nov", "11", "Dec", "12");
    1046        $date2=$3 . "-" . $months{$2} . "-" . $1;
    1047        # print "** converted date2: $date2\n";
     1021        my %months = ("Jan", "01", "Feb", "02", "Mar", "03", "Apr",  "04", "May",  "05", "Jun",  "06",
     1022        "Jul", "07", "Aug", "08", "Sep", "09", "Oct", "10", "Nov", "11", "Dec", "12");
     1023        $date2=$3 . "-" . $months{$2} . "-" . $1;
     1024        # print "** converted date2: $date2\n";
    10481025    }
    10491026   
     
    10551032    # Compare year
    10561033    if ($date1parts[0] > $date2parts[0]) {
    1057     return 1;
     1034        return 1;
    10581035    }
    10591036    elsif ($date1parts[0] == $date2parts[0]) {
    1060     # Year is the same, so compare month
    1061     if ($date1parts[1] > $date2parts[1]) {
    1062         return 1;
    1063     }
    1064     elsif ($date1parts[1] == $date2parts[1]) {
    1065         # Month is the same, so compare day
    1066         if ($date1parts[2] > $date2parts[2]) {
    1067         return 1;
    1068         }
    1069     }
     1037        # Year is the same, so compare month
     1038        if ($date1parts[1] > $date2parts[1]) {
     1039            return 1;
     1040        }
     1041        elsif ($date1parts[1] == $date2parts[1]) {
     1042            # Month is the same, so compare day
     1043            if ($date1parts[2] > $date2parts[2]) {
     1044                return 1;
     1045            }
     1046        }
    10701047    }   
    10711048   
     
    10771054{
    10781055    my ($translation_file_key, $target_file, $total_num_chunks, $target_files_keys_requiring_translation, $target_files_keys_requiring_updating, $num_chunks_to_return, $source_files_key_to_text_mapping, $target_files_key_to_text_mapping, $source_files_key_to_last_update_date_mapping, $target_files_key_to_last_update_date_mapping) = @_;
    1079 
     1056   
    10801057    # Form an XML response to the command
    10811058    my $xml_response = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
     
    10871064    . " num_chunks_requiring_translation=\"" . scalar(@$target_files_keys_requiring_translation) . "\""
    10881065    . " num_chunks_requiring_updating=\"" . scalar(@$target_files_keys_requiring_updating) . "\"\/>\n";
    1089 
     1066   
    10901067    # Do chunks requiring translation first
    10911068    if ($num_chunks_to_return > scalar(@$target_files_keys_requiring_translation)) {
    1092     $xml_response .= "  <ChunksRequiringTranslation size=\"" . scalar(@$target_files_keys_requiring_translation) . "\">\n";
     1069        $xml_response .= "  <ChunksRequiringTranslation size=\"" . scalar(@$target_files_keys_requiring_translation) . "\">\n";
    10931070    }
    10941071    else {
    1095     $xml_response .= "  <ChunksRequiringTranslation size=\"" . $num_chunks_to_return . "\">\n";
    1096     }
    1097 
     1072        $xml_response .= "  <ChunksRequiringTranslation size=\"" . $num_chunks_to_return . "\">\n";
     1073    }
     1074   
    10981075    my @sorted_chunk_keys = sort (@$target_files_keys_requiring_translation);
    10991076    foreach my $chunk_key (@sorted_chunk_keys) {
    1100     last if ($num_chunks_to_return == 0);
    1101 
    1102     my $source_file_chunk_date = $source_files_key_to_last_update_date_mapping->{$chunk_key} || "";
    1103     my $source_file_chunk_text = &make_text_xml_safe($source_files_key_to_text_mapping->{$chunk_key}); 
    1104    
    1105     $xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";
    1106     $xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";   
    1107     $xml_response .= "      <TargetFileText></TargetFileText>\n";
    1108     $xml_response .= "    </Chunk>\n";
    1109 
    1110     $num_chunks_to_return--;
    1111     }
    1112 
     1077        last if ($num_chunks_to_return == 0);
     1078       
     1079        my $source_file_chunk_date = $source_files_key_to_last_update_date_mapping->{$chunk_key} || "";
     1080        my $source_file_chunk_text = &make_text_xml_safe($source_files_key_to_text_mapping->{$chunk_key}); 
     1081       
     1082        $xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";
     1083        $xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";   
     1084        $xml_response .= "      <TargetFileText></TargetFileText>\n";
     1085        $xml_response .= "    </Chunk>\n";
     1086       
     1087        $num_chunks_to_return--;
     1088    }
     1089   
    11131090    $xml_response .= "  </ChunksRequiringTranslation>\n";
    1114 
     1091   
    11151092    # Then do chunks requiring updating
    11161093    if ($num_chunks_to_return > scalar(@$target_files_keys_requiring_updating)) {
    1117     $xml_response .= "  <ChunksRequiringUpdating size=\"" . scalar(@$target_files_keys_requiring_updating) . "\">\n";
     1094        $xml_response .= "  <ChunksRequiringUpdating size=\"" . scalar(@$target_files_keys_requiring_updating) . "\">\n";
    11181095    }
    11191096    else {
    1120     $xml_response .= "  <ChunksRequiringUpdating size=\"" . $num_chunks_to_return . "\">\n";
    1121     }
    1122        
     1097        $xml_response .= "  <ChunksRequiringUpdating size=\"" . $num_chunks_to_return . "\">\n";
     1098    }
     1099   
    11231100    # foreach my $chunk_key (@target_file_keys_requiring_updating) {
    11241101    @sorted_chunk_keys = sort (@$target_files_keys_requiring_updating);
    11251102    foreach my $chunk_key (@sorted_chunk_keys) {
    1126     last if ($num_chunks_to_return == 0);
    1127 
    1128     my $source_file_chunk_date = $source_files_key_to_last_update_date_mapping->{$chunk_key} || "";
    1129     my $source_file_chunk_text = &make_text_xml_safe($source_files_key_to_text_mapping->{$chunk_key});
    1130     my $target_file_chunk_date = $target_files_key_to_last_update_date_mapping->{$chunk_key} || "";
    1131     my $target_file_chunk_text = &make_text_xml_safe($target_files_key_to_text_mapping->{$chunk_key});
    1132 
    1133     $xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";   
    1134     $xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";
    1135     $xml_response .= "      <TargetFileText date=\"$target_file_chunk_date\">$target_file_chunk_text</TargetFileText>\n";
    1136     $xml_response .= "    </Chunk>\n";
    1137 
    1138     $num_chunks_to_return--;
    1139     }
    1140 
     1103        last if ($num_chunks_to_return == 0);
     1104       
     1105        my $source_file_chunk_date = $source_files_key_to_last_update_date_mapping->{$chunk_key} || "";
     1106        my $source_file_chunk_text = &make_text_xml_safe($source_files_key_to_text_mapping->{$chunk_key});
     1107        my $target_file_chunk_date = $target_files_key_to_last_update_date_mapping->{$chunk_key} || "";
     1108        my $target_file_chunk_text = &make_text_xml_safe($target_files_key_to_text_mapping->{$chunk_key});
     1109       
     1110        $xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";   
     1111        $xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";
     1112        $xml_response .= "      <TargetFileText date=\"$target_file_chunk_date\">$target_file_chunk_text</TargetFileText>\n";
     1113        $xml_response .= "    </Chunk>\n";
     1114       
     1115        $num_chunks_to_return--;
     1116    }
     1117   
    11411118    $xml_response .= "  </ChunksRequiringUpdating>\n";
    1142 
     1119   
    11431120    $xml_response .= "</GTIResponse>\n";
    1144 
     1121   
    11451122    return $xml_response;
    11461123}
     
    11501127{
    11511128    my ($translation_file_key, $target_file, $source_file_key_to_text_mapping, $target_file_key_to_text_mapping, $source_file_key_to_last_update_date_mapping, $target_file_key_to_last_update_date_mapping) = @_;
    1152 
     1129   
    11531130    # Form an XML response to the command
    11541131    my $xml_response = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
     
    11601137    # Do all the chunks
    11611138    $xml_response .= "  <Chunks size=\"" . scalar(keys(%$source_file_key_to_text_mapping)) . "\">\n";
    1162 
     1139   
    11631140    my @sorted_chunk_keys = sort (keys(%$source_file_key_to_text_mapping));
    11641141    foreach my $chunk_key (@sorted_chunk_keys) {
    1165     my $source_file_chunk_date = $source_file_key_to_last_update_date_mapping->{$chunk_key} || "";
    1166     my $source_file_chunk_text = &make_text_xml_safe($source_file_key_to_text_mapping->{$chunk_key});
    1167 
    1168     $xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";
    1169     $xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";
    1170     if (defined($target_file_key_to_text_mapping->{$chunk_key})) {
    1171         my $target_file_chunk_date = $target_file_key_to_last_update_date_mapping->{$chunk_key} || "";
    1172         my $target_file_chunk_text = &make_text_xml_safe($target_file_key_to_text_mapping->{$chunk_key});
    1173         $xml_response .= "      <TargetFileText date=\"$target_file_chunk_date\">$target_file_chunk_text</TargetFileText>\n";
    1174     }
    1175     else {
    1176         $xml_response .= "      <TargetFileText></TargetFileText>\n";
    1177     }
    1178 
    1179     $xml_response .= "    </Chunk>\n";
     1142        my $source_file_chunk_date = $source_file_key_to_last_update_date_mapping->{$chunk_key} || "";
     1143        my $source_file_chunk_text = &make_text_xml_safe($source_file_key_to_text_mapping->{$chunk_key});
     1144       
     1145        $xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";
     1146        $xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";
     1147        if (defined($target_file_key_to_text_mapping->{$chunk_key})) {
     1148            my $target_file_chunk_date = $target_file_key_to_last_update_date_mapping->{$chunk_key} || "";
     1149            my $target_file_chunk_text = &make_text_xml_safe($target_file_key_to_text_mapping->{$chunk_key});
     1150            $xml_response .= "      <TargetFileText date=\"$target_file_chunk_date\">$target_file_chunk_text</TargetFileText>\n";
     1151        }
     1152        else {
     1153            $xml_response .= "      <TargetFileText></TargetFileText>\n";
     1154        }
     1155       
     1156        $xml_response .= "    </Chunk>\n";
    11801157    }
    11811158    $xml_response .= "  </Chunks>\n";
     
    11931170{
    11941171    my (@file_lines) = @_;
    1195 
     1172   
    11961173    my $macro_package;
    11971174    my %chunk_key_to_line_mapping = ();
    11981175    # Process the contents of the file, line by line
    11991176    for (my $i = 0; $i < scalar(@file_lines); $i++) {
    1200     my $line = $file_lines[$i];
    1201     $line =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
    1202 
    1203     # Check if a new package is being defined
    1204     if ($line =~ m/^package\s+(.+)/) {
    1205         $macro_package = $1;
    1206     }
    1207 
    1208     # Line contains a macro name
    1209     elsif ($line =~ m/^(_\w+_)/) {
    1210         my $macro_key = $1;
    1211         $line =~ s/\s*([^\\]\#[^\}]+)?$//;  # Remove any comments and nasty whitespace
    1212 
    1213         # While there is still text of the macro to go...
    1214         my $startline = $i;
    1215         while ($line !~ /\}$/) {
    1216         $i++;
    1217         if ($i == scalar(@file_lines)) {
    1218             &throw_fatal_error("Could not find end of macro $macro_key.");
    1219         }
    1220         $line = $file_lines[$i];
    1221         $line =~ s/\s*([^\\]\#[^\}]+)?$//;  # Remove any comments and nasty whitespace
    1222         }
    1223 
     1177        my $line = $file_lines[$i];
     1178        $line =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
     1179       
     1180        # Check if a new package is being defined
     1181        if ($line =~ m/^package\s+(.+)/) {
     1182            $macro_package = $1;
     1183        }
     1184       
     1185        # Line contains a macro name
     1186        elsif ($line =~ m/^(_\w+_)/) {
     1187            my $macro_key = $1;
     1188            $line =~ s/\s*([^\\]\#[^\}]+)?$//;  # Remove any comments and nasty whitespace
     1189           
     1190            # While there is still text of the macro to go...
     1191            my $startline = $i;
     1192            while ($line !~ /\}$/) {
     1193                $i++;
     1194                if ($i == scalar(@file_lines)) {
     1195                    &throw_fatal_error("Could not find end of macro $macro_key.");
     1196                }
     1197                $line = $file_lines[$i];
     1198                $line =~ s/\s*([^\\]\#[^\}]+)?$//;  # Remove any comments and nasty whitespace
     1199            }
     1200       
    12241201        # The chunk key consists of the package name and the macro key
    12251202        my $chunk_key = $macro_package . "." . $macro_key;
     
    12271204        $chunk_key_to_line_mapping{$chunk_key} = $startline . "-" . $i;
    12281205    }
    1229 
     1206   
    12301207    # Icon: line in format ## "image text" ## image_type ## macro_name ##
    12311208    elsif ($line =~ m/^\#\# .* \#\# .* \#\# (.*) \#\#/) {
    1232         # The chunk key consists of package name and macro key
    1233         my $chunk_key = $macro_package . "." . $1;
    1234         # Map from chunk key to line
    1235         $chunk_key_to_line_mapping{$chunk_key} = $i . "-" . $i;
    1236     }
    1237     }
    1238 
    1239     return %chunk_key_to_line_mapping;
     1209    # The chunk key consists of package name and macro key
     1210    my $chunk_key = $macro_package . "." . $1;
     1211    # Map from chunk key to line
     1212    $chunk_key_to_line_mapping{$chunk_key} = $i . "-" . $i;
     1213}
     1214}
     1215
     1216return %chunk_key_to_line_mapping;
    12401217}
    12411218
     
    12441221{
    12451222    my ($chunk_text) = @_;
    1246 
     1223   
    12471224    # Is this an icon macro??
    12481225    if ($chunk_text =~ /^\#\# (.*)/) {
    1249     # Extract image macro text
    1250     $chunk_text =~ /^\#\#\s+([^\#]+)\s+\#\#/;
    1251     $chunk_text = $1;
    1252 
     1226        # Extract image macro text
     1227        $chunk_text =~ /^\#\#\s+([^\#]+)\s+\#\#/;
     1228        $chunk_text = $1;
     1229   
    12531230    # Remove enclosing quotes
    12541231    $chunk_text =~ s/^\"//;
    12551232    $chunk_text =~ s/\"$//;
    1256     }
    1257 
    1258     # No, so it must be a text macro
    1259     else {
     1233}
     1234
     1235# No, so it must be a text macro
     1236else {
    12601237    # Remove macro key
    12611238    $chunk_text =~ s/^_([^_]+)_(\s*)//;
    1262 
     1239   
    12631240    # Remove language specifier
    12641241    $chunk_text =~ s/^\[l=.*\](\s*)//;
    1265 
     1242   
    12661243    # Remove braces enclosing text
    12671244    $chunk_text =~ s/^{(\s*)((.|\n)*)}(\s*)(\#.+\s*)?/$2/;
    1268     }
    1269 
    1270     return $chunk_text;
     1245}
     1246
     1247return $chunk_text;
    12711248}
    12721249
     
    12751252{
    12761253    my ($chunk_text) = @_;
    1277 
     1254   
    12781255    # Check for an "Updated DD-MMM-YYYY" comment at the end of the chunk
    12791256    if ($chunk_text =~ /\#\s+(Updated\s+\d?\d-\D\D\D-\d\d\d\d.*)\s*$/i) {
    1280     return $1;
    1281     }
    1282 
    1283     return undef;
     1257        return $1;
     1258}
     1259
     1260return undef;
    12841261}
    12851262
     
    12881265{
    12891266    my ($chunk_key) = @_;
    1290 
     1267   
    12911268    # The _httpiconX_, _widthX_ and _heightX_ image macros are automatically translated
    12921269    if ($chunk_key =~ /\._(httpicon|width|height)/) {
    1293     return 1;
    1294     }
    1295 
     1270        return 1;
     1271    }
     1272   
    12961273    return 0;
    12971274}
     
    13091286    my $target_file_key_to_gti_comment_mapping = shift(@_);
    13101287    my $target_language_code = shift(@_);
    1311 
     1288   
    13121289    # Build a mapping from source file line to chunk key
    13131290    my %source_file_key_to_line_mapping = &build_key_to_line_mapping_for_macrofile(@source_file_lines);
    13141291    my %source_file_line_to_key_mapping = ();
    13151292    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
    1316     $source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
     1293        $source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
    13171294    }
    13181295    my @source_file_line_keys = (sort sort_by_line (keys(%source_file_line_to_key_mapping)));
    13191296    my $source_file_line_number = 0;
    1320 
     1297   
    13211298    # Build a mapping from target file line to chunk key
    13221299    my %target_file_key_to_line_mapping = &build_key_to_line_mapping_for_macrofile(@target_file_lines);
    13231300    my %target_file_line_to_key_mapping = ();
    13241301    foreach my $chunk_key (keys(%target_file_key_to_line_mapping)) {
    1325     $target_file_line_to_key_mapping{$target_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
     1302        $target_file_line_to_key_mapping{$target_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
    13261303    }
    13271304    my @target_file_line_keys = (sort sort_by_line (keys(%target_file_line_to_key_mapping)));
    1328 
     1305   
    13291306    # Write the new target file
    13301307    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
    13311308    if (!open(TARGET_FILE, ">$target_file_path")) {
    1332     &throw_fatal_error("Could not write target file $target_file_path.");
    1333     }
    1334 
     1309        &throw_fatal_error("Could not write target file $target_file_path.");
     1310    }
     1311   
    13351312    # Use the header from the target file, to keep language and author information
    13361313    if (scalar(@target_file_line_keys) > 0) {
    1337     my $target_file_line_number = 0;
    1338     my $target_file_chunk_starting_line_number = (split(/-/, $target_file_line_keys[0]))[0];
    1339     while ($target_file_line_number < $target_file_chunk_starting_line_number) {
    1340         my $target_file_line = $target_file_lines[$target_file_line_number];
    1341         last if ($target_file_line =~ /^\# -- Missing translation: /);  # We don't want to get into the macros
    1342         print TARGET_FILE $target_file_line;
    1343         $target_file_line_number++;
    1344     }
    1345 
    1346     $source_file_line_number = (split(/-/, $source_file_line_keys[0]))[0];
    1347     }
    1348 
     1314        my $target_file_line_number = 0;
     1315        my $target_file_chunk_starting_line_number = (split(/-/, $target_file_line_keys[0]))[0];
     1316        while ($target_file_line_number < $target_file_chunk_starting_line_number) {
     1317            my $target_file_line = $target_file_lines[$target_file_line_number];
     1318            last if ($target_file_line =~ /^\# -- Missing translation: /);  # We don't want to get into the macros
     1319                print TARGET_FILE $target_file_line;
     1320            $target_file_line_number++;
     1321        }
     1322       
     1323        $source_file_line_number = (split(/-/, $source_file_line_keys[0]))[0];
     1324    }
     1325   
    13491326    # Model the new target file on the source file, with the target file translations
    13501327    foreach my $line_key (@source_file_line_keys) {
    1351     # Fill in the gaps before this chunk starts
    1352     my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
    1353     my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
    1354     while ($source_file_line_number < $source_file_chunk_starting_line_number) {
    1355         print TARGET_FILE $source_file_lines[$source_file_line_number];
    1356         $source_file_line_number++;
    1357     }
    1358     $source_file_line_number = $source_file_chunk_finishing_line_number + 1;
    1359 
    1360     my $chunk_key = $source_file_line_to_key_mapping{$line_key};
    1361     my $source_file_chunk_text = $source_file_key_to_text_mapping->{$chunk_key};
    1362     my $target_file_chunk_text = $target_file_key_to_text_mapping->{$chunk_key} || "";
    1363 
    1364     my $macrofile_key = $chunk_key;
    1365     $macrofile_key =~ s/^(.+?)\.//;
    1366 
    1367     # If no translation exists for this chunk, show this, and move on
    1368     if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
    1369         print TARGET_FILE "# -- Missing translation: $macrofile_key\n";
    1370         next;
    1371     }
    1372 
    1373     # Grab the source chunk text
    1374     my $source_file_chunk = $source_file_lines[$source_file_chunk_starting_line_number];
    1375     for (my $l = ($source_file_chunk_starting_line_number + 1); $l <= $source_file_chunk_finishing_line_number; $l++) {
    1376         $source_file_chunk .= $source_file_lines[$l];
    1377     }
    1378 
    1379     # Is this an icon macro??
    1380     if ($source_file_chunk =~ /^\#\# (.*)/) {
    1381         # Escape any newline and question mark characters so the source text is replaced correctly
    1382         $source_file_chunk_text =~ s/\\/\\\\/g;
     1328        # Fill in the gaps before this chunk starts
     1329        my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
     1330        my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
     1331        while ($source_file_line_number < $source_file_chunk_starting_line_number) {
     1332            print TARGET_FILE $source_file_lines[$source_file_line_number];
     1333            $source_file_line_number++;
     1334        }
     1335        $source_file_line_number = $source_file_chunk_finishing_line_number + 1;
     1336       
     1337        my $chunk_key = $source_file_line_to_key_mapping{$line_key};
     1338        my $source_file_chunk_text = $source_file_key_to_text_mapping->{$chunk_key};
     1339        my $target_file_chunk_text = $target_file_key_to_text_mapping->{$chunk_key} || "";
     1340       
     1341        my $macrofile_key = $chunk_key;
     1342        $macrofile_key =~ s/^(.+?)\.//;
     1343       
     1344        # If no translation exists for this chunk, show this, and move on
     1345        if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
     1346            print TARGET_FILE "# -- Missing translation: $macrofile_key\n";
     1347            next;
     1348        }
     1349       
     1350        # Grab the source chunk text
     1351        my $source_file_chunk = $source_file_lines[$source_file_chunk_starting_line_number];
     1352        for (my $l = ($source_file_chunk_starting_line_number + 1); $l <= $source_file_chunk_finishing_line_number; $l++) {
     1353            $source_file_chunk .= $source_file_lines[$l];
     1354        }
     1355       
     1356        # Is this an icon macro??
     1357        if ($source_file_chunk =~ /^\#\# (.*)/) {
     1358            # Escape any newline and question mark characters so the source text is replaced correctly
     1359            $source_file_chunk_text =~ s/\\/\\\\/g;
    13831360        $source_file_chunk_text =~ s/\?/\\\?/g;
    1384 
     1361       
    13851362        # Build the new target chunk from the source chunk
    13861363        my $target_file_chunk = $source_file_chunk;
     
    13891366        print TARGET_FILE "$target_file_chunk";
    13901367    }
    1391 
     1368   
    13921369    # No, it is just a normal text macro
    13931370    else {
    13941371        print TARGET_FILE "$macrofile_key [l=$target_language_code] {$target_file_chunk_text}";
    13951372    }
    1396 
     1373   
    13971374    # Add the "updated" comment, if one exists
    13981375    if ($target_file_key_to_gti_comment_mapping->{$chunk_key}) {
     
    14001377    }
    14011378    print TARGET_FILE "\n";
    1402     }
    1403 
    1404     close(TARGET_FILE);
     1379}
     1380
     1381close(TARGET_FILE);
    14051382}
    14061383
     
    14181395{
    14191396    my (@file_lines) = @_;
    1420 
     1397   
    14211398    my %chunk_key_to_line_mapping = ();
    14221399    for (my $i = 0; $i < scalar(@file_lines); $i++) {
    1423     my $line = $file_lines[$i];
    1424     $line =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
    1425 
    1426     # Line contains a dictionary string
    1427     if ($line =~ /^(\S+?)[:|=](.*)$/) {
    1428         my $chunk_key = $1;
    1429 
    1430         # Map from chunk key to line
    1431         $chunk_key_to_line_mapping{$chunk_key} = $i . "-" . $i;
    1432     }
    1433     }
    1434 
     1400        my $line = $file_lines[$i];
     1401        $line =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
     1402       
     1403        # Line contains a dictionary string
     1404        if ($line =~ /^(\S+?)[:|=](.*)$/) {
     1405            my $chunk_key = $1;
     1406           
     1407            # Map from chunk key to line
     1408            $chunk_key_to_line_mapping{$chunk_key} = $i . "-" . $i;
     1409        }
     1410    }
     1411   
    14351412    return %chunk_key_to_line_mapping;
    14361413}
     
    14401417{
    14411418    my ($chunk_text) = @_;
    1442 
     1419   
    14431420    # Simple: just remove string key
    14441421    $chunk_text =~ s/^(\S+?)[:|=](\s*)//;
    14451422    $chunk_text =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
    14461423    $chunk_text =~ s/(\s*)\#\s+Updated\s+(\d?\d-\D\D\D-\d\d\d\d.*)\s*$//i;
    1447 
     1424   
    14481425    return $chunk_text;
    14491426}
     
    14531430{
    14541431    my ($chunk_text) = @_;
    1455 
     1432   
    14561433    # Check for an "Updated DD-MMM-YYYY" comment at the end of the chunk
    14571434    if ($chunk_text =~ /\#\s+(Updated\s+\d?\d-\D\D\D-\d\d\d\d.*)\s*$/i) {
    1458     return $1;
    1459     }
    1460 
    1461     return undef;
     1435        return $1;
     1436}
     1437
     1438return undef;
    14621439}
    14631440
     
    14801457    my $target_file_key_to_gti_comment_mapping = shift(@_);
    14811458    my $target_language_code = shift(@_);  # Not used
    1482 
     1459   
    14831460    # Build a mapping from chunk key to source file line, and from source file line to chunk key
    14841461    my %source_file_key_to_line_mapping = &build_key_to_line_mapping_for_resource_bundle(@source_file_lines);
    14851462    my %source_file_line_to_key_mapping = ();
    14861463    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
    1487     $source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
    1488     }
    1489 
     1464        $source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
     1465    }
     1466   
    14901467    # Write the new target file
    14911468    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
    14921469    if (!open(TARGET_FILE, ">$target_file_path")) {
    1493     &throw_fatal_error("Could not write target file $target_file_path.");
    1494     }
    1495 
     1470        &throw_fatal_error("Could not write target file $target_file_path.");
     1471    }
     1472   
    14961473    # Model the new target file on the source file, with the target file translations
    14971474    my $source_file_line_number = 0;
    14981475    foreach my $line_key (sort sort_by_line (keys(%source_file_line_to_key_mapping))) {
    1499     # Fill in the gaps before this chunk starts
    1500     my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
    1501     my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
    1502     while ($source_file_line_number < $source_file_chunk_starting_line_number) {
    1503         print TARGET_FILE $source_file_lines[$source_file_line_number];
    1504         $source_file_line_number++;
    1505     }
    1506     $source_file_line_number = $source_file_chunk_finishing_line_number + 1;
    1507 
    1508     my $chunk_key = $source_file_line_to_key_mapping{$line_key};
    1509     my $source_file_chunk_text = $source_file_key_to_text_mapping->{$chunk_key};
    1510     my $target_file_chunk_text = $target_file_key_to_text_mapping->{$chunk_key} || "";
    1511 
    1512     # If no translation exists for this chunk, show this, and move on
    1513     if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
    1514         print TARGET_FILE "# -- Missing translation: $chunk_key\n";
    1515         next;
    1516     }
    1517 
    1518     print TARGET_FILE "$chunk_key:$target_file_chunk_text";
    1519     if ($target_file_key_to_gti_comment_mapping->{$chunk_key}) {
    1520         print TARGET_FILE "  # " . $target_file_key_to_gti_comment_mapping->{$chunk_key};
    1521     }
    1522     print TARGET_FILE "\n";
    1523     }
    1524 
     1476        # Fill in the gaps before this chunk starts
     1477        my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
     1478        my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
     1479        while ($source_file_line_number < $source_file_chunk_starting_line_number) {
     1480            print TARGET_FILE $source_file_lines[$source_file_line_number];
     1481            $source_file_line_number++;
     1482        }
     1483        $source_file_line_number = $source_file_chunk_finishing_line_number + 1;
     1484       
     1485        my $chunk_key = $source_file_line_to_key_mapping{$line_key};
     1486        my $source_file_chunk_text = $source_file_key_to_text_mapping->{$chunk_key};
     1487        my $target_file_chunk_text = $target_file_key_to_text_mapping->{$chunk_key} || "";
     1488       
     1489        # If no translation exists for this chunk, show this, and move on
     1490        if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
     1491            print TARGET_FILE "# -- Missing translation: $chunk_key\n";
     1492            next;
     1493        }
     1494       
     1495        print TARGET_FILE "$chunk_key:$target_file_chunk_text";
     1496        if ($target_file_key_to_gti_comment_mapping->{$chunk_key}) {
     1497            print TARGET_FILE "  # " . $target_file_key_to_gti_comment_mapping->{$chunk_key};
     1498        }
     1499        print TARGET_FILE "\n";
     1500    }
     1501   
    15251502    close(TARGET_FILE);
    15261503}
     
    15331510{
    15341511    my (@file_lines) = @_;
    1535 
     1512   
    15361513    my %chunk_key_to_line_mapping = ();
    15371514    for (my $i = 0; $i < scalar(@file_lines); $i++) {
    1538     my $line = $file_lines[$i];
    1539     $line =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
    1540 
    1541     # Line contains a string to translate
    1542     if ($line =~ /^\s*<Text id=\"(.*?)\">/) {
    1543         my $chunk_key = $1;
    1544         $line =~ s/\s*$//;  # Remove any nasty whitespace
    1545         $line =~ s/<Updated date=\"\d?\d-\D\D\D-\d\d\d\d.*\"\/>$//;
    1546 
    1547         # While there is still text of the string to go...
    1548         my $startline = $i;
    1549         while ($line !~ /<\/Text>$/) {
    1550         $i++;
    1551         if ($i == scalar(@file_lines)) {
    1552             &throw_fatal_error("Could not find end of string $chunk_key.");
    1553         }
    1554         $line = $file_lines[$i];
    1555         $line =~ s/\s*$//;  # Remove any nasty whitespace
    1556         $line =~ s/<Updated date=\"\d?\d-\D\D\D-\d\d\d\d.*\"\/>$//;
    1557         }
    1558 
    1559         # Map from chunk key to line
    1560         if (!defined($chunk_key_to_line_mapping{$chunk_key})) {
    1561         $chunk_key_to_line_mapping{$chunk_key} = $startline . "-" . $i;
    1562         }
    1563         else {
    1564         &throw_fatal_error("Duplicate key $chunk_key.");
    1565         }
    1566     }
    1567     }
    1568 
     1515        my $line = $file_lines[$i];
     1516        $line =~ s/(\s*)$//;  # Remove any nasty whitespace, carriage returns etc.
     1517       
     1518        # Line contains a string to translate
     1519        if ($line =~ /^\s*<Text id=\"(.*?)\">/) {
     1520            my $chunk_key = $1;
     1521            $line =~ s/\s*$//;  # Remove any nasty whitespace
     1522            $line =~ s/<Updated date=\"\d?\d-\D\D\D-\d\d\d\d.*\"\/>$//;
     1523           
     1524            # While there is still text of the string to go...
     1525            my $startline = $i;
     1526            while ($line !~ /<\/Text>$/) {
     1527                $i++;
     1528                if ($i == scalar(@file_lines)) {
     1529                    &throw_fatal_error("Could not find end of string $chunk_key.");
     1530                }
     1531                $line = $file_lines[$i];
     1532                $line =~ s/\s*$//;  # Remove any nasty whitespace
     1533                $line =~ s/<Updated date=\"\d?\d-\D\D\D-\d\d\d\d.*\"\/>$//;
     1534            }
     1535           
     1536            # Map from chunk key to line
     1537            if (!defined($chunk_key_to_line_mapping{$chunk_key})) {
     1538                $chunk_key_to_line_mapping{$chunk_key} = $startline . "-" . $i;
     1539            }
     1540            else {
     1541                &throw_fatal_error("Duplicate key $chunk_key.");
     1542            }
     1543        }
     1544    }
     1545   
    15691546    return %chunk_key_to_line_mapping;
    15701547}
     
    15741551{
    15751552    my ($chunk_text) = @_;
    1576 
     1553   
    15771554    # Simple: just remove the Text tags
    15781555    $chunk_text =~ s/^\s*<Text id=\"(.*?)\">(\s*)//;
    15791556    $chunk_text =~ s/<Updated date=\"\d?\d-\D\D\D-\d\d\d\d.*\"\/>$//;
    15801557    $chunk_text =~ s/<\/Text>$//;
    1581 
     1558   
    15821559    return $chunk_text;
    15831560}
     
    15871564{
    15881565    my ($chunk_text) = @_;
    1589 
     1566   
    15901567    # Check for an "Updated DD-MMM-YYYY" comment at the end of the chunk
    15911568    if ($chunk_text =~ /<Updated date=\"(\d?\d-\D\D\D-\d\d\d\d.*)\"\/>$/i) {
    1592     return $1;
    1593     }
    1594 
     1569        return $1;
     1570    }
     1571   
    15951572    return undef;
    15961573}
     
    16141591    my $target_file_key_to_gti_comment_mapping = shift(@_);
    16151592    my $target_language_code = shift(@_);  # Not used
    1616 
     1593   
    16171594    # Build a mapping from chunk key to source file line, and from source file line to chunk key
    16181595    my %source_file_key_to_line_mapping = &build_key_to_line_mapping_for_greenstone_xml(@source_file_lines);
    16191596    my %source_file_line_to_key_mapping = ();
    16201597    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
    1621     $source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
    1622     }
    1623 
     1598        $source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
     1599    }
     1600   
    16241601    # Write the new target file
    16251602    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
    16261603    if (!open(TARGET_FILE, ">$target_file_path")) {
    1627     &throw_fatal_error("Could not write target file $target_file_path.");
    1628     }
    1629 
     1604        &throw_fatal_error("Could not write target file $target_file_path.");
     1605    }
     1606   
    16301607    # Model the new target file on the source file, with the target file translations
    16311608    my $source_file_line_number = 0;
    16321609    foreach my $line_key (sort sort_by_line (keys(%source_file_line_to_key_mapping))) {
    1633     # Fill in the gaps before this chunk starts
    1634     my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
    1635     my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
    1636     while ($source_file_line_number < $source_file_chunk_starting_line_number) {
    1637         print TARGET_FILE $source_file_lines[$source_file_line_number];
    1638         $source_file_line_number++;
    1639     }
    1640     $source_file_line_number = $source_file_chunk_finishing_line_number + 1;
    1641 
    1642     my $chunk_key = $source_file_line_to_key_mapping{$line_key};
    1643     my $source_file_chunk_text = $source_file_key_to_text_mapping->{$chunk_key};
    1644     my $target_file_chunk_text = $target_file_key_to_text_mapping->{$chunk_key} || "";
    1645     $target_file_chunk_text =~ s/(\n)*$//g;
    1646 
    1647     # If no translation exists for this chunk, show this, and move on
    1648     if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
    1649         print TARGET_FILE "<!-- Missing translation: $chunk_key -->\n";
    1650         next;
    1651     }
    1652 
    1653     print TARGET_FILE "<Text id=\"$chunk_key\">$target_file_chunk_text</Text>";
    1654     if ($target_file_key_to_gti_comment_mapping->{$chunk_key}) {
    1655         my $chunk_gti_comment = $target_file_key_to_gti_comment_mapping->{$chunk_key};
    1656         $chunk_gti_comment =~ s/^Updated //;
    1657         print TARGET_FILE "<Updated date=\"" . $chunk_gti_comment . "\"\/>";
    1658     }
    1659     print TARGET_FILE "\n";
    1660     }
    1661 
     1610        # Fill in the gaps before this chunk starts
     1611        my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
     1612        my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
     1613        while ($source_file_line_number < $source_file_chunk_starting_line_number) {
     1614            print TARGET_FILE $source_file_lines[$source_file_line_number];
     1615            $source_file_line_number++;
     1616        }
     1617        $source_file_line_number = $source_file_chunk_finishing_line_number + 1;
     1618       
     1619        my $chunk_key = $source_file_line_to_key_mapping{$line_key};
     1620        my $source_file_chunk_text = $source_file_key_to_text_mapping->{$chunk_key};
     1621        my $target_file_chunk_text = $target_file_key_to_text_mapping->{$chunk_key} || "";
     1622        $target_file_chunk_text =~ s/(\n)*$//g;
     1623       
     1624        # If no translation exists for this chunk, show this, and move on
     1625        if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
     1626            print TARGET_FILE "<!-- Missing translation: $chunk_key -->\n";
     1627            next;
     1628        }
     1629       
     1630        print TARGET_FILE "<Text id=\"$chunk_key\">$target_file_chunk_text</Text>";
     1631        if ($target_file_key_to_gti_comment_mapping->{$chunk_key}) {
     1632            my $chunk_gti_comment = $target_file_key_to_gti_comment_mapping->{$chunk_key};
     1633            $chunk_gti_comment =~ s/^Updated //;
     1634            print TARGET_FILE "<Updated date=\"" . $chunk_gti_comment . "\"\/>";
     1635        }
     1636        print TARGET_FILE "\n";
     1637    }
     1638   
    16621639    # Fill in the end of the file
    16631640    while ($source_file_line_number < scalar(@source_file_lines)) {
    1664     print TARGET_FILE $source_file_lines[$source_file_line_number];
    1665     $source_file_line_number++;
    1666     }
    1667 
     1641        print TARGET_FILE $source_file_lines[$source_file_line_number];
     1642        $source_file_line_number++;
     1643    }
     1644   
    16681645    close(TARGET_FILE);
    16691646}
     
    16781655    my $target_language_code = lc(shift(@_));
    16791656    my $translation_file_key = lc(shift(@_));
    1680 
     1657   
    16811658    # Check that the necessary arguments were supplied
    16821659    if (!$target_language_code) {
    1683     &throw_fatal_error("Missing command argument.");
    1684     }
    1685 
     1660        &throw_fatal_error("Missing command argument.");
     1661    }
     1662   
    16861663    # Get (and check) the translation configuration
    16871664    # my ($source_file_dir, $target_file, $translation_file_type) = &get_translation_configuration($target_language_code, $translation_file_key);
     
    16911668    my %source_files_key_to_last_update_date_mapping = ();
    16921669    my %target_files_key_to_last_update_date_mapping = ();
    1693 
     1670   
    16941671    &build_gs3_configuration($target_language_code, \%source_files_key_to_text_mapping, \%target_files_key_to_text_mapping, \%source_files_key_to_last_update_date_mapping, \%target_files_key_to_last_update_date_mapping);
    1695 
     1672   
    16961673    &log_message("Total number of source chunks: " . scalar(keys(%source_files_key_to_text_mapping)));
    16971674    &log_message("Total number of target chunks: " . scalar(keys(%target_files_key_to_text_mapping)));
    1698 
     1675   
    16991676    my $xml_response = &create_xml_response_for_all_chunks($translation_file_key, "", \%source_files_key_to_text_mapping, \%target_files_key_to_text_mapping, \%source_files_key_to_last_update_date_mapping, \%target_files_key_to_last_update_date_mapping);   
    17001677    return $xml_response;
     
    17131690    # Check that the necessary arguments were supplied
    17141691    if (!$target_language_code || !$translation_file_key) {
    1715     &throw_fatal_error("Missing command argument.");
     1692        &throw_fatal_error("Missing command argument.");
    17161693    }
    17171694   
     
    17201697    my %source_files_key_to_last_update_date_mapping = ();
    17211698    my %target_files_key_to_last_update_date_mapping = ();
    1722 
     1699   
    17231700    &build_gs3_configuration($target_language_code, \%source_files_key_to_text_mapping, \%target_files_key_to_text_mapping,
    1724                  \%source_files_key_to_last_update_date_mapping, \%target_files_key_to_last_update_date_mapping);
     1701    \%source_files_key_to_last_update_date_mapping, \%target_files_key_to_last_update_date_mapping);
    17251702   
    17261703    # Determine the target file chunks requiring translation
     
    17301707    &log_message("Total number of target chunks requiring translation: " . scalar(@target_files_keys_requiring_translation));
    17311708    &log_message("Total number of target chunks requiring updating: " . scalar(@target_files_keys_requiring_updating));
    1732 
     1709   
    17331710    my $xml_response = &create_xml_response_for_chunks_requiring_work($translation_file_key, "", scalar(keys(%source_files_key_to_text_mapping)),
    1734                                       \@target_files_keys_requiring_translation, \@target_files_keys_requiring_updating,
    1735                                       $num_chunks_to_return, \%source_files_key_to_text_mapping, \%target_files_key_to_text_mapping,
    1736                                       \%source_files_key_to_last_update_date_mapping, \%target_files_key_to_last_update_date_mapping);
    1737    
     1711    \@target_files_keys_requiring_translation, \@target_files_keys_requiring_updating,
     1712    $num_chunks_to_return, \%source_files_key_to_text_mapping, \%target_files_key_to_text_mapping,
     1713    \%source_files_key_to_last_update_date_mapping, \%target_files_key_to_last_update_date_mapping);
     1714   
    17381715    return $xml_response;
    17391716}
     
    17481725    my $source_file_directory = "greenstone3";
    17491726    my $translation_file_type = "resource_bundle";
    1750 
     1727   
    17511728    foreach my $interface_file_key (@gs3_interface_files) {
    1752 
    1753     &log_message("Greenstone 3 interface file: " . $interface_file_key);
    1754 
    1755     # Parse the source language and target language files
    1756     my $source_file = &util::filename_cat($source_file_directory, $interface_file_key.".properties");
    1757     my @source_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $source_file));
    1758     my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
    1759     my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
    1760     my %source_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
    1761    
    1762     my $target_file = &util::filename_cat($source_file_directory, $interface_file_key."_".$target_language_code.".properties");
    1763     my @target_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $target_file));
    1764     my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
    1765     my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
    1766     my %target_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
    1767 
    1768 
    1769     # Filter out any automatically translated chunks
    1770     foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
    1771         if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
    1772         delete $source_file_key_to_line_mapping{$chunk_key};
    1773         delete $target_file_key_to_line_mapping{$chunk_key};
    1774         }
    1775     }
    1776 
    1777     &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
    1778     &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
    1779 
    1780     foreach my $chunk_key (keys(%source_file_key_to_text_mapping)) {
    1781         my $global_chunk_key = "$interface_file_key.$chunk_key";
    1782         $source_files_key_to_text_mapping->{$global_chunk_key} = $source_file_key_to_text_mapping{$chunk_key};
    1783         $source_files_key_to_gti_comment_mapping->{$global_chunk_key} = $source_file_key_to_gti_comment_mapping{$chunk_key};
    1784 
    1785         if (defined $target_file_key_to_text_mapping{$chunk_key}) {
    1786         $target_files_key_to_text_mapping->{$global_chunk_key} = $target_file_key_to_text_mapping{$chunk_key};
    1787         $target_files_key_to_gti_comment_mapping->{$global_chunk_key} = $target_file_key_to_gti_comment_mapping{$chunk_key};
    1788         }
    1789     }   
     1729       
     1730        &log_message("Greenstone 3 interface file: " . $interface_file_key);
     1731       
     1732        # Parse the source language and target language files
     1733        my $source_file = &util::filename_cat($source_file_directory, $interface_file_key.".properties");
     1734        my @source_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $source_file));
     1735        my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
     1736        my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
     1737        my %source_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
     1738       
     1739        my $target_file = &util::filename_cat($source_file_directory, $interface_file_key."_".$target_language_code.".properties");
     1740        my @target_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $target_file));
     1741        my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
     1742        my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
     1743        my %target_file_key_to_gti_comment_mapping = &build_key_to_gti_comment_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
     1744       
     1745       
     1746        # Filter out any automatically translated chunks
     1747        foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
     1748            if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
     1749                delete $source_file_key_to_line_mapping{$chunk_key};
     1750                delete $target_file_key_to_line_mapping{$chunk_key};
     1751            }
     1752        }
     1753       
     1754        &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
     1755        &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
     1756       
     1757        foreach my $chunk_key (keys(%source_file_key_to_text_mapping)) {
     1758            my $global_chunk_key = "$interface_file_key.$chunk_key";
     1759            $source_files_key_to_text_mapping->{$global_chunk_key} = $source_file_key_to_text_mapping{$chunk_key};
     1760            $source_files_key_to_gti_comment_mapping->{$global_chunk_key} = $source_file_key_to_gti_comment_mapping{$chunk_key};
     1761           
     1762            if (defined $target_file_key_to_text_mapping{$chunk_key}) {
     1763                $target_files_key_to_text_mapping->{$global_chunk_key} = $target_file_key_to_text_mapping{$chunk_key};
     1764                $target_files_key_to_gti_comment_mapping->{$global_chunk_key} = $target_file_key_to_gti_comment_mapping{$chunk_key};
     1765            }
     1766        }   
    17901767    }
    17911768}
     
    18001777   
    18011778    my @sorted_chunk_keys = sort (keys(%$source_file_key_to_text_mapping));
    1802 
     1779   
    18031780    my %translated_interface_file_keys = ();
    18041781    foreach my $chunk_key (keys(%$target_file_key_to_text_mapping)) {
    1805     $chunk_key =~ /^([^\.]+)?\.(.*)$/;
    1806     if (!defined $translated_interface_file_keys{$1}) {
    1807         &log_message("Updated interface file: " . $1); 
    1808         $translated_interface_file_keys{$1}="";
    1809     }
     1782        $chunk_key =~ /^([^\.]+)?\.(.*)$/;
     1783        if (!defined $translated_interface_file_keys{$1}) {
     1784            &log_message("Updated interface file: " . $1); 
     1785            $translated_interface_file_keys{$1}="";
     1786        }
    18101787    }
    18111788    &log_message("Updated interface files: " . scalar(keys(%translated_interface_file_keys)));
     
    18141791   
    18151792    foreach my $interface_file_key (keys(%translated_interface_file_keys)) {
    1816    
    1817     # Build a mapping from chunk key to source file line, and from source file line to chunk key
    1818     my $source_file = &util::filename_cat($source_file_directory, "$interface_file_key.properties");
    1819     my @source_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $source_file));
    1820     my %source_file_key_to_line_mapping = &build_key_to_line_mapping_for_resource_bundle(@source_file_lines);
    1821     my %source_file_line_to_key_mapping = ();
    1822     foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
    1823         $source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
    1824     }
    1825    
    1826     # Write the new target file
    1827     my $target_file = &util::filename_cat($source_file_directory, $interface_file_key . "_" . $target_language_code . ".properties");
    1828     my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
    1829     if (!open(TARGET_FILE, ">$target_file_path")) {
    1830         &throw_fatal_error("Could not write target file $target_file_path.");
    1831     }
    1832 
    1833     # Model the new target file on the source file, with the target file translations
    1834     my $source_file_line_number = 0;
    1835     foreach my $line_key (sort sort_by_line (keys(%source_file_line_to_key_mapping))) {
    1836         # Fill in the gaps before this chunk starts
    1837         my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
    1838         my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
    1839         while ($source_file_line_number < $source_file_chunk_starting_line_number) {
    1840         print TARGET_FILE $source_file_lines[$source_file_line_number];
    1841         $source_file_line_number++;
    1842         }
    1843         $source_file_line_number = $source_file_chunk_finishing_line_number + 1;
    1844 
    1845         my $chunk_key = $source_file_line_to_key_mapping{$line_key};
    1846         my $global_chunk_key = "$interface_file_key.$chunk_key";
    1847         my $source_file_chunk_text = $source_file_key_to_text_mapping->{$global_chunk_key};
    1848         my $target_file_chunk_text = $target_file_key_to_text_mapping->{$global_chunk_key} || "";
    1849 
    1850         # If no translation exists for this chunk, show this, and move on
    1851         if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
    1852         print TARGET_FILE "# -- Missing translation: $chunk_key\n";
    1853         next;
    1854         }
    1855 
    1856         print TARGET_FILE "$chunk_key:$target_file_chunk_text";
    1857         if ($target_file_key_to_gti_comment_mapping->{$global_chunk_key}) {
    1858         print TARGET_FILE "  # " . $target_file_key_to_gti_comment_mapping->{$global_chunk_key};
    1859         }
    1860         print TARGET_FILE "\n";
    1861     }
    1862 
    1863     close(TARGET_FILE);
     1793       
     1794        # Build a mapping from chunk key to source file line, and from source file line to chunk key
     1795        my $source_file = &util::filename_cat($source_file_directory, "$interface_file_key.properties");
     1796        my @source_file_lines = &read_file_lines(&util::filename_cat($gsdl_root_directory, $source_file));
     1797        my %source_file_key_to_line_mapping = &build_key_to_line_mapping_for_resource_bundle(@source_file_lines);
     1798        my %source_file_line_to_key_mapping = ();
     1799        foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
     1800            $source_file_line_to_key_mapping{$source_file_key_to_line_mapping{$chunk_key}} = $chunk_key;
     1801        }
     1802       
     1803        # Write the new target file
     1804        my $target_file = &util::filename_cat($source_file_directory, $interface_file_key . "_" . $target_language_code . ".properties");
     1805        my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
     1806        if (!open(TARGET_FILE, ">$target_file_path")) {
     1807            &throw_fatal_error("Could not write target file $target_file_path.");
     1808        }
     1809       
     1810        # Model the new target file on the source file, with the target file translations
     1811        my $source_file_line_number = 0;
     1812        foreach my $line_key (sort sort_by_line (keys(%source_file_line_to_key_mapping))) {
     1813            # Fill in the gaps before this chunk starts
     1814            my $source_file_chunk_starting_line_number = (split(/-/, $line_key))[0];
     1815            my $source_file_chunk_finishing_line_number = (split(/-/, $line_key))[1];
     1816            while ($source_file_line_number < $source_file_chunk_starting_line_number) {
     1817                print TARGET_FILE $source_file_lines[$source_file_line_number];
     1818                $source_file_line_number++;
     1819            }
     1820            $source_file_line_number = $source_file_chunk_finishing_line_number + 1;
     1821           
     1822            my $chunk_key = $source_file_line_to_key_mapping{$line_key};
     1823            my $global_chunk_key = "$interface_file_key.$chunk_key";
     1824            my $source_file_chunk_text = $source_file_key_to_text_mapping->{$global_chunk_key};
     1825            my $target_file_chunk_text = $target_file_key_to_text_mapping->{$global_chunk_key} || "";
     1826           
     1827            # If no translation exists for this chunk, show this, and move on
     1828            if ($source_file_chunk_text ne "" && $target_file_chunk_text eq "") {
     1829                print TARGET_FILE "# -- Missing translation: $chunk_key\n";
     1830                next;
     1831            }
     1832           
     1833            print TARGET_FILE "$chunk_key:$target_file_chunk_text";
     1834            if ($target_file_key_to_gti_comment_mapping->{$global_chunk_key}) {
     1835                print TARGET_FILE "  # " . $target_file_key_to_gti_comment_mapping->{$global_chunk_key};
     1836            }
     1837            print TARGET_FILE "\n";
     1838        }
     1839       
     1840        close(TARGET_FILE);
    18641841    }           
    18651842}
Note: See TracChangeset for help on using the changeset viewer.