Perldoc update
[koha_fer] / misc / translator / tmpl_process3.pl
index 0dd4f0c..2324a18 100755 (executable)
@@ -6,7 +6,7 @@
 
 =head1 NAME
 
-tmpl_process3.pl - Experimental version of tmpl_process.pl
+tmpl_process3.pl - Alternative version of tmpl_process.pl
 using gettext-compatible translation files
 
 =cut
@@ -16,7 +16,7 @@ use Getopt::Long;
 use Locale::PO;
 use File::Temp qw( :POSIX );
 use TmplTokenizer;
-use VerboseWarnings qw( error_normal warn_normal );
+use VerboseWarnings qw( :warn :die );
 
 ###############################################################################
 
@@ -90,10 +90,11 @@ sub text_replace (**) {
            print $output find_translation($t);
        } elsif ($kind eq TmplTokenType::TEXT_PARAMETRIZED) {
            my $fmt = find_translation($s->form);
-           print $output TmplTokenizer::parametrize($fmt, [ map {
+           print $output TmplTokenizer::parametrize($fmt, 1, $s, sub {
+               $_ = $_[0];
                my($kind, $t, $attr) = ($_->type, $_->string, $_->attributes);
                $kind == TmplTokenType::TAG && %$attr?
-                   text_replace_tag($t, $attr): $t } $s->parameters ], [ $s->anchors ]);
+                   text_replace_tag($t, $attr): $t });
        } elsif ($kind eq TmplTokenType::TAG && %$attr) {
            print $output text_replace_tag($t, $attr);
        } elsif (defined $t) {
@@ -127,6 +128,35 @@ sub listfiles ($$) {
 
 ###############################################################################
 
+sub usage ($) {
+    my($exitcode) = @_;
+    my $h = $exitcode? *STDERR: *STDOUT;
+    print $h <<EOF;
+Usage: $0 create [OPTION]
+  or:  $0 update [OPTION]
+  or:  $0 install [OPTION]
+  or:  $0 --help
+Create or update PO files from templates, or install translated templates.
+
+  -i, --input=SOURCE          Get or update strings from SOURCE file.
+                              SOURCE is a directory if -r is also specified.
+  -o, --outputdir=DIRECTORY   Install translation(s) to specified DIRECTORY
+      --pedantic-warnings     Issue warnings even for detected problems
+                              which are likely to be harmless
+  -r, --recursive             SOURCE in the -i option is a directory
+  -s, --str-file=FILE         Specify FILE as the translation (po) file
+                              for input (install) or output (create, update)
+  -x, --exclude=REGEXP        Exclude files matching the given REGEXP
+      --help                  Display this help and exit
+
+The -o option is ignored for the "create" and "update" actions.
+Try `perldoc $0' for perhaps more information.
+EOF
+    exit($exitcode);
+}
+
+###############################################################################
+
 sub usage_error (;$) {
     for my $msg (split(/\n/, $_[0])) {
        print STDERR "$msg\n";
@@ -144,14 +174,12 @@ GetOptions(
     'str-file|s=s'                     => \$str_file,
     'exclude|x=s'                      => \@excludes,
     'pedantic-warnings|pedantic'       => sub { $pedantic_p = 1 },
+    'help'                             => \&usage,
 ) || usage_error;
 
 VerboseWarnings::set_application_name $0;
 VerboseWarnings::set_pedantic_mode $pedantic_p;
 
-# try to make sure .po files are backed up (see BUGS)
-$ENV{VERSION_CONTROL} = 't';
-
 # keep the buggy Locale::PO quiet if it says stupid things
 $SIG{__WARN__} = sub {
        my($s) = @_;
@@ -196,6 +224,8 @@ $href = Locale::PO->load_file_ashash($str_file);
 
 # guess the charsets. HTML::Templates defaults to iso-8859-1
 if (defined $href) {
+    die "$str_file: PO file is corrupted, or not a PO file\n"
+           unless defined $href->{'""'};
     $charset_out = TmplTokenizer::charset_canon $2
            if $href->{'""'}->msgstr =~ /\bcharset=(["']?)([^;\s"'\\]+)\1/;
     for my $msgid (keys %$href) {
@@ -213,10 +243,15 @@ if (!defined $charset_in) {
 }
 
 my $xgettext = './xgettext.pl';        # actual text extractor script
+my $st;
 
 if ($action eq 'create')  {
     # updates the list. As the list is empty, every entry will be added
-    die "$str_file: Output file already exists" if -f $str_file;
+    if (!-s $str_file) {
+       warn "Removing empty file $str_file\n";
+       unlink $str_file || die "$str_file: $!\n";
+    }
+    die "$str_file: Output file already exists\n" if -f $str_file;
     my($tmph, $tmpfile) = tmpnam();
     # Generate the temporary file that acts as <MODULE>/POTFILES.in
     for my $input (@in_files) {
@@ -224,9 +259,9 @@ if ($action eq 'create')  {
     }
     close $tmph;
     # Generate the specified po file ($str_file)
-    my $st = system ($xgettext, '-s', '-f', $tmpfile, '-o', $str_file);
+    $st = system ($xgettext, '-s', '-f', $tmpfile, '-o', $str_file);
     warn_normal "Text extraction failed: $xgettext: $!\n", undef if $st != 0;
-    unlink $tmpfile || warn_normal "$tmpfile: unlink failed: $!\n", undef;
+#   unlink $tmpfile || warn_normal "$tmpfile: unlink failed: $!\n", undef;
 
 } elsif ($action eq 'update') {
     my($tmph1, $tmpfile1) = tmpnam();
@@ -238,20 +273,21 @@ if ($action eq 'create')  {
     }
     close $tmph1;
     # Generate the temporary file that acts as <MODULE>/<LANG>.pot
-    my $st = system($xgettext, '-s', '-f', $tmpfile1, '-o', $tmpfile2,
+    $st = system($xgettext, '-s', '-f', $tmpfile1, '-o', $tmpfile2,
+           '--po-mode',
            (defined $charset_in? ('-I', $charset_in): ()),
            (defined $charset_out? ('-O', $charset_out): ()));
     if ($st == 0) {
        # Merge the temporary "pot file" with the specified po file ($str_file)
        # FIXME: msgmerge(1) is a Unix dependency
        # FIXME: need to check the return value
-       system('msgmerge', '-U', '-s', $str_file, $tmpfile2);
+       $st = system('msgmerge', '-U', '-s', $str_file, $tmpfile2);
     } else {
-       warn_normal "Text extraction failed: $xgettext: $!\n", undef;
-       warn_normal "Will not run msgmerge\n", undef;
+       error_normal "Text extraction failed: $xgettext: $!\n", undef;
+       error_additional "Will not run msgmerge\n", undef;
     }
-    unlink $tmpfile1 || warn_normal "$tmpfile1: unlink failed: $!\n", undef;
-    unlink $tmpfile2 || warn_normal "$tmpfile2: unlink failed: $!\n", undef;
+#   unlink $tmpfile1 || warn_normal "$tmpfile1: unlink failed: $!\n", undef;
+#   unlink $tmpfile2 || warn_normal "$tmpfile2: unlink failed: $!\n", undef;
 
 } elsif ($action eq 'install') {
     if(!defined($out_dir)) {
@@ -296,6 +332,12 @@ if ($action eq 'create')  {
 } else {
     usage_error('Unknown action specified.');
 }
+
+if ($st == 0) {
+    printf "The %s seems to be successful.\n", $action;
+} else {
+    printf "%s FAILED.\n", "\u$action";
+}
 exit 0;
 
 ###############################################################################
@@ -306,50 +348,89 @@ exit 0;
 
 =head1 DESCRIPTION
 
-This is an experimental version of the tmpl_process.pl script,
-using standard gettext-style PO files.  Note that the behaviour
-of this script should still be considered unstable.
+This is an alternative version of the tmpl_process.pl script,
+using standard gettext-style PO files.  While there still might
+be changes made to the way it extracts strings, at this moment
+it should be stable enough for general use; it is already being
+used for the Chinese and Polish translations.
 
 Currently, the create, update, and install actions have all been
 reimplemented and seem to work.
 
+=head2 Features
+
+=over
+
+=item -
+
+Translation files in standard Uniforum PO format.
+All standard tools including all gettext tools,
+plus PO file editors like kbabel(1) etc.
+can be used.
+
+=item -
+
+Minor changes in whitespace in source templates
+do not generally require new strings to be re-translated.
+
+=item -
+
+Able to handle <TMPL_VAR> variables in the templates;
+<TMPL_VAR> variables are usually extracted in proper context.
+
+=item -
+
+Able to handle text input and radio button INPUT elements
+in the templates; these INPUT elements are also usually
+extracted in proper context.
+
+=item -
+
+Automatic comments in the generated PO files to provide
+even more context (line numbers, and the names and types
+of the variables).
+
+=item -
+
+Using the PO format also means translators can add their
+own comments in the translation files, if necessary.
+
+=item -
+
+Create, update, and install actions are all based on the
+same scanner module. This ensures that when installing the
+translation file, nothing that should not be translated is
+accidentally translated.
+
+=back
+
+=head1 NOTES
+
 The create action calls xgettext.pl to do the actual work;
 the update action calls xgettext.pl and msgmerge(1) to do the
 actual work.
 
-The script can detect <TMPL_VAR> directives embedded inside what
-appears to be a full sentence (this actual work being done by
-TmplTokenizer(3)); these larger patterns appear in the translation
-file as c-format strings with %s.
-
-Whitespace in extracted strings are folded to single blanks, in
-order to prevent new strings from appearing when minor changes in
-the original templates occur, and to prevent overly difficult to
-read strings in the PO file.
-
 =head1 BUGS
 
-The --help option has not been implemented yet.
-
 xgettext.pl must be present in the current directory; the
 msgmerge(1) command must also be present in the search path.
 The script currently does not check carefully whether these
 dependent commands are present.
 
-If xgettext.pl is interrupted by the user, a corrupted po file
-will result. This is very seriously wrong.
-
 Locale::PO(3) has a lot of bugs. It can neither parse nor
 generate GNU PO files properly; a couple of workarounds have
 been written in TmplTokenizer and more is likely to be needed
 (e.g., to get rid of the "Strange line" warning for #~).
 
+This script may not work in Windows.
+
 There are probably some other bugs too, since this has not been
 tested very much.
 
 =head1 SEE ALSO
 
 xgettext.pl,
+TmplTokenizer.pm,
 msgmerge(1),
 Locale::PO(3),
 translator_doc.txt