6 my (@in_files, $str_file, $split_char, $recursive, $type, $out_dir, $in_dir, @excludes, $filter);
13 'input|i=s' => \@in_files,
14 'outputdir|o=s' => \$out_dir,
15 'str-file|s=s' => \$str_file,
16 'recursive|r' => \$recursive,
17 'filter=s' => \$filter,
19 'exclude=s' => \@excludes,
20 'sep=s' => \$split_char,
21 'help' => sub { help() },
22 ) || (usage(), exit(-1));
24 # utiliser glob() pour tous les fichiers d'un repertoire
26 my $action = shift or usage();
29 # Checks for missing input and string list arguments
31 if( !@in_files || !defined($str_file) )
33 usage("You must at least specify input and string list filenames.");
36 # Type match defaults to *.tmpl if not specified
37 $type = "tmpl|inc" if !defined($type);
39 $filter = "./text-extract.pl -f" if !defined($filter);
40 # Input is not a file nor a directory
41 if( !(-d $in_files[0]) && !(-f $in_files[0]))
43 usage("Unknown input. Input must a file or a directory. (Symbolic links are not supported for the moment.)");
45 elsif( -d $in_files[0] )
47 # input is a directory, generates list of files to process
48 $in_dir = $in_files[0];
49 $in_dir =~ s/\/$//; # strips the trailing / if any
51 print "Generating list of files to process...\n";
54 @in_files = &listfiles(\@in_files, $in_dir, $type, $recursive);
56 if(scalar(@in_files) == 0)
58 warn "Nothing to process in $in_dir matching *.$type.";
63 # Generates the global exclude regular expression
64 $exclude_regex = "(".join("|", @excludes).")" if @excludes;
66 if( $action eq "create" )
68 # updates the list. As the list is empty, every entry will be added
69 %strhash = &update_strhash(\%strhash, \@in_files, $exclude_regex, $filter);
70 # saves the list to the file
71 write_strhash(\%strhash, $str_file, "\t");
73 elsif( $action eq "update" )
75 # restores the string list from file
76 %strhash = &restore_strhash(\%strhash, $str_file, $split_char);
77 # updates the list, adding new entries if any
78 %strhash = &update_strhash(\%strhash, \@in_files, $exclude_regex, $filter);
79 # saves the list to the file
80 write_strhash(\%strhash, $str_file, $split_char);
82 elsif( $action eq "install" )
84 if(!defined($out_dir))
86 usage("You must specify an output directory when using the install method.");
89 if( $in_dir eq $out_dir )
91 warn "You must specify a different input and output directory.\n";
95 # restores the string list from file
96 %strhash = &restore_strhash(\%strhash, $str_file, $split_char);
97 # creates the new tmpl file using the new translation
98 &install_strhash(\%strhash, \@in_files, $in_dir, $out_dir);
102 usage("Unknown action specified.");
107 ##########################################################
108 # Creates the new template files in the output directory #
109 ##########################################################
113 my($strhash, $in_files, $in_dir, $out_dir) = @_;
115 my $fh_in; my $fh_out; # handles for input and output files
116 my $tmp_dir; # temporary directory name (used to create destination dir)
118 $out_dir =~ s/\/$//; # chops the trailing / if any.
120 # Processes every entry found.
121 foreach my $file (@{$in_files})
123 if( !open($fh_in, "< $file") )
125 warn "Can't open $file : $!\n";
129 # generates the name of the output file
130 my $out_file = $file;
134 # processing single files not an entire directory
135 $out_file = "$out_dir/$file";
139 $out_file =~ s/^$in_dir/$out_dir/;
142 my $slash = rindex($out_file, "\/");
143 $tmp_dir = substr($out_file, 0, $slash); #gets the directory where the file will be saved
145 # the file doesn't exist
146 if( !(-f $tmp_dir) && !(-l $tmp_dir) && !(-e $tmp_dir) )
148 if(!mkdir($tmp_dir,0775)) # creates with rwxrwxr-x permissions
150 warn("Make directory $tmp_dir : $!");
155 elsif((-f $tmp_dir) || (-l $tmp_dir))
157 warn("Unable to create directory $tmp_dir.\n A file or symbolic link with the same name already exists.");
162 # opens handle for output
163 if( !open($fh_out, "> $out_file") )
165 warn "Can't write $out_file : $!\n";
170 print "Generating $out_file...\n";
172 while(my $line = <$fh_in>)
174 foreach my $text (sort {length($b) <=> length($a)} keys %{$strhash})
176 # Test if the key has been translated
177 if( %{$strhash}->{$text} != 1 )
179 # Does the line contains text that needs to be changed ?
180 if( $line =~ /$text/ && %{$strhash}->{$text} ne "IGNORE")
183 my $subst = %{$strhash}->{$text};
184 $line =~ s/(\W)$text(\W)/$1$subst$2/g;
188 $line =~ s/\<TMPL_(.*?)\>/\<\!-- TMPL_$1 --\>/g;
189 $line =~ s/\<\/TMPL_(.*?)\>/\<\!-- \/TMPL_$1 --\>/g;
190 # Writing the modified (or not) line to output
191 printf($fh_out "%s", $line);
199 ########################################################
200 # Updates the string list hash with the new components #
201 ########################################################
205 my($strhash, $in_files, $exclude, $filter)= @_;
209 # Processes every file entries
210 foreach my $in (@{$in_files})
213 print "Processing $in...\n";
215 # Creates a filehandle containing all the strings returned by
216 # the plain text program extractor
217 open($fh, "$filter $in |") or print "$filter $in : $!";
218 next $in if !defined $fh;
220 # Processes every string returned
221 while(my $str = <$fh>)
223 $str =~ s/[\n\r\f]+$//; # chomps the trailing \n (or <cr><lf> if file was edited with Windows)
224 $str =~ s/^\s+//; # remove trailing blanks, ':' or '*'
225 $str =~ s/\s*\**:*\s*$//;
227 # the line begins with letter(s) followed by optional words and/or spaces
228 if($str =~ /^[ ]*[\w]+[ \w]*/)
230 # the line is to be excluded ?
231 if( !(defined($exclude) && ($str =~ /$exclude/o) && $str>0) )
233 if( !defined(%{$strhash}->{$str}) )
235 # the line is not already in the list so add it
236 %{$strhash}->{$str}=1;
248 #####################################################
249 # Reads the input file and returns a generated hash #
250 #####################################################
254 my($strhash, $str_file, $split_char) = @_;
258 open($fh, "< $str_file") or die "$str_file : $!";
260 print "Restoring string list from $str_file...\n";
262 while( my $line = <$fh> )
266 # extracts the two fields
267 my ($original, $translated) = split(/$split_char/, $line, 2);
269 if($translated ne "*****")
271 # the key has been translated
272 %{$strhash}->{$original} = $translated;
276 # the key exist but has no translation.
277 %{$strhash}->{$original} = 1;
287 #########################################
288 # Writes the string hashtable to a file #
289 #########################################
293 my($strhash, $str_file, $split_char) = @_;
297 # Opens a handle for saving the list
298 open($fh, "> $str_file") or die "$str_file : $!";
300 print "Writing string list to $str_file...\n";
302 foreach my $str(sort {uc($a) cmp uc($b) || length($a) <=> length($b)} keys %{$strhash})
304 if(%{$strhash}->{$str} != 1)
306 printf($fh "%s%s%s\n", $str, $split_char, %{$strhash}->{$str});
310 printf($fh "%s%s%s\n", $str, $split_char,"*****") unless ($str >0);
317 ########################################################
318 # List the contents of dir matching the pattern *.type #
319 ########################################################
323 my($in_files, $dir, $type, $recursive) = @_;
326 # my @types = split(/ /,$type);
327 opendir($dir_h, $dir) or warn("Can't open $dir : $!\n");
329 my @tmp_list = grep(!/^\.\.?$/, readdir($dir_h));
333 foreach my $tmp_file (@tmp_list)
336 if( $recursive && (-d "$dir/$tmp_file") ) # entry is a directory
338 @{$in_files} = listfiles($in_files, "$dir/$tmp_file", $type);
340 elsif( $tmp_file =~ /\.$type$/ )
342 push(@{$in_files}, "$dir/$tmp_file");
348 ######################################
350 # Prints the contents of a hashtable #
351 ######################################
355 my($strhash, $split_char) = @_;
357 foreach my $str(sort keys %{$strhash})
359 if(%{$strhash}->{$str} != 1)
361 printf("%s%s%s\n", $str, $split_char, %{$strhash}->{$str});
365 printf("%s%s\n", $str, $split_char);
370 #########################################
371 # Short help messsage printing function #
372 #########################################
376 warn join(" ", @_)."\n" if @_;
379 Usage : $0 method -i input.tmpl|/input/dir -s strlist.file
380 [-o /output/dir] [options]
382 where method can be :
383 * create : creates the string list from scratch using the input files.
384 * update : updates an existing string list, adding the new strings to
385 the list, leaving the others alone.
386 * install : creates the new .tmpl files using the string list config file
387 (--outputdir must be used to specify the output directory).
389 Use $0 --help for a complete listing of options.
394 ##############################################
395 # Long help message describing every options #
396 ##############################################
401 Usage : $0 method [options]
403 where method can be :
404 * create : creates the string list from scratch using the input files.
405 * update : updates an existing string list, adding the new strings to
406 the list, leaving the others alone.
407 * install : creates the new .tmpl files using the string list config file
408 (-o must be used to specify the output directory).
413 Specify the input to process. Input can be a file or a directory.
414 When input is a directory, files matching the --type option will be
416 When using files, the parameter can be repeated to process a list
419 Example: $0 create -i foo.tmpl --input=bar.tmpl -s foobar.txt
422 Specify the file where the different strings will be stored.
425 Specify the output directory to use when generating the translated
429 Use the recursive mode to process every entry in subdirectories.
430 Note: Symbolic links used to link directories are not supported.
433 Defines the type of files to match when input is a directory.
434 By default --type=tmpl
437 Use this option to exclude some entries extracted by the program.
438 This option can be repeated to exclude many types of strings.
440 Example: $0 create -i foo.tmpl -s foo.txt --exclude=^\[0-9\]+\$
441 will create a list from foo.tmpl called foo.txt where lines
442 composed of numbers only are excluded. Special characters need to
446 Specify the program to use to extract plain text from files.
447 Default is str-extract which means str-extract must be in the path
451 Use this option to specify the char to be used to separate entries
452 in the string list file.