Blob Blame History Raw
From b70d42ae5acf4b7fcc806935d97215b679ed843b Mon Sep 17 00:00:00 2001
From: Martin Quinson <martin.quinson@ens-rennes.fr>
Date: Fri, 1 Mar 2024 01:10:23 +0100
Subject: [PATCH] Fix the --translate-only option

I added a lot of verbose messages to understand what's going on,
rewrote a bit of code I didn't understant but was not recently
modified, and the bug introduced last month was gone.

At the end, I'm not sure of what happened, but this
fixes https://github.com/mquinson/po4a/issues/482

Thanks Alexander for the diagnostic and the reproducer!
---
 NEWS                                     |  3 +
 po4a                                     | 78 +++++++++++++++++-------
 t/Testhelper.pm                          |  2 +-
 t/add/modifiers/_output                  |  1 +
 t/cfg-multi.t                            | 22 ++++++-
 t/cfg/args-alias-redef/_output           |  1 +
 t/cfg/args-alias/_output                 |  1 +
 t/cfg/args-alias/_output-keep100         |  1 +
 t/cfg/args-global/_output                |  1 +
 t/cfg/args-global/_output-keep100        |  1 +
 t/cfg/args-master/_output                |  1 +
 t/cfg/args-master/_output-keep100        |  1 +
 t/cfg/multiple-fuzzied-noup/_output      |  1 +
 t/cfg/multiple-nopo/_output-noupdate     |  1 +
 t/cfg/multiple-uptodate/_output-only-one |  4 ++
 t/cfg/multiple-uptodate/_output-only-two |  5 ++
 t/cfg/single-fuzzied-noup/_output        |  1 +
 t/cfg/single-nopo/_output-noupdate       |  1 +
 18 files changed, 101 insertions(+), 25 deletions(-)
 create mode 100644 t/cfg/multiple-uptodate/_output-only-one
 create mode 100644 t/cfg/multiple-uptodate/_output-only-two

diff --git a/po4a b/po4a
index 14222062f..72736013e 100755
--- a/po4a
+++ b/po4a
@@ -1319,11 +1319,12 @@ while (<CONFIG>) {
         }
         if ( scalar @{ $po4a_opts{"partial"} } ) {
             foreach my $file ( @{ $po4a_opts{"partial"} } ) {
-                if ( grep ( m/(\S+):\Q$file\E\b/, @split_args ) ) {
-                    $partial{'lang'}{$1}      = 1;
-                    $partial{'master'}{$main} = 1;
-                    $partial{'files'}{$file}  = 1;
-                    last;
+                foreach my $arg (@split_args) {
+                    if ( $arg =~ m/(\S+):\Q$file\E\b/ ) {
+                        $partial{'lang'}{$1}      = 1;
+                        $partial{'master'}{$main} = 1;
+                        $partial{'files'}{$file}  = 1;
+                    }
                 }
             }
         }
@@ -1344,7 +1345,7 @@ while (<CONFIG>) {
             $document{$main}{'format'} = $aliases{$1}{"module"};
             if ( defined $aliases{$1}{"options"} ) {
 
-                #                print STDERR "Override the global options with the alias ones\n";
+                # print STDERR "Override the global options with the alias ones\n";
                 %options = %{ $aliases{$1}{"options"} };    # XXX not a merge, but overwrite
             }
         }
@@ -1440,16 +1441,18 @@ while (<CONFIG>) {
             }
         }
     } elsif ( $cmd =~ m/po4a_alias: *(.*)/ ) {
-        my $name  = $1;
+        my $name = $1;
         shift @split_args;
 
-        if ( defined $aliases{$name} ) { # If that alias was previously defined
-            die "Alias $name redefined from ".$aliases{$name}{"module"}." to $main\n"
-                if ( $aliases{$name}{"module"} ne $main );  # Sanity checks
-            # Concat the new content to the existing alias
-            @split_args = map { parse_config_options( "$config_file:$nb", $_, \%{ $aliases{$name}{"options"} } ); } @split_args;
-        } else {
-            # Otherwise, define a new option set accordingly
+        if ( defined $aliases{$name} ) {    # If that alias was previously defined
+            die "Alias $name redefined from " . $aliases{$name}{"module"} . " to $main\n"
+              if ( $aliases{$name}{"module"} ne $main );
+
+            # Concat the new content to the existing alias after a sanity check
+            @split_args =
+              map { parse_config_options( "$config_file:$nb", $_, \%{ $aliases{$name}{"options"} } ); } @split_args;
+
+        } else {                            # Otherwise, define a new option set accordingly
             my %alias = ();
             $alias{"module"} = $main;
 
@@ -1530,13 +1533,33 @@ if ( $pot_filename =~ m/\$master/ ) {
 
         # Skip documents not specified, strings are read directly from POT file
         foreach my $master ( keys %document ) {
-            next                      unless length $master;
-            delete $document{$master} unless exists $partial{'master'}{$master};
+            next unless length $master;
+            if ( exists $partial{'master'}{$master} ) {
+                print wrap_msg( gettext("Document %s kept for update (--translate-only)."), $master )
+                  if ( $po4a_opts{"verbose"} );
+            } else {
+                print wrap_msg( gettext("Skip the update of %s as requested (--translate-only)."), $master )
+                  if ( $po4a_opts{"verbose"} );
+                delete $document{$master};
+            }
         }
 
         # Do not read PO files if no file is processed for this language
-        foreach my $lang ( keys %po_filename ) {
-            delete $po_filename{$lang} unless exists $partial{'lang'}{$lang};
+        my $skipped_langs = "";
+        my $kept_langs    = "";
+        foreach my $lang ( sort keys %po_filename ) {
+            if ( exists $partial{'lang'}{$lang} ) {
+                $kept_langs .= " $lang";
+            } else {
+                $skipped_langs .= " $lang";
+                delete $po_filename{$lang};
+            }
+        }
+        if ( $po4a_opts{"verbose"} ) {
+            $skipped_langs =~ s/^ //;
+            $kept_langs    =~ s/^ //;
+            print wrap_msg( gettext("Languages skipped because of --translate-only: %s; kept languages: %s."),
+                $skipped_langs, $kept_langs );
         }
     }
 
@@ -1654,8 +1677,16 @@ if ($update_pot_file) {
     print wrap_msg( gettext(" (%d entries)"), $potfile->count_entries() )
       unless ( $po4a_opts{"quiet"} );
 } else {
-    print wrap_msg( gettext("POT file %s already up to date."), $pot_filename )
-      if ( $po4a_opts{"verbose"} and not $po4a_opts{"no-update"} );
+    if ( $po4a_opts{"no-update"} ) {
+        print wrap_msg( gettext("NOT updating the POT file %s as requested (--no-update)."), $pot_filename )
+          if ( $po4a_opts{"verbose"} );
+    } elsif ( scalar @{ $po4a_opts{"partial"} } ) {
+        print wrap_msg( gettext("NOT updating the POT file %s because of --translate-only."), $pot_filename )
+          if ( $po4a_opts{"verbose"} );
+    } else {
+        print wrap_msg( gettext("POT file %s already up to date."), $pot_filename )
+          if ( $po4a_opts{"verbose"} and not $po4a_opts{"no-update"} );
+    }
 }
 
 my %split_po;           # po_files: '$lang','$master' => '$path'
@@ -1930,7 +1961,12 @@ if ( not $po4a_opts{"no-translations"} ) {
             next if ( $master eq '' );
             next unless defined $document{$master}{$lang};
             if ( scalar @{ $po4a_opts{"partial"} } ) {
-                next unless defined $partial{'files'}{ $document{$master}{$lang} };
+                unless ( defined $partial{'files'}{ $document{$master}{$lang} } ) {
+                    print wrap_msg( gettext("Skip master file %s in language %s because of --translate-only."),
+                        $master, $lang )
+                      if ( $po4a_opts{"verbose"} );
+                    next;
+                }
             }
 
             unless ( $po4a_opts{"force"} ) {
diff --git a/t/Testhelper.pm b/t/Testhelper.pm
index 889128a4a..187a3f4fb 100644
--- a/t/Testhelper.pm
+++ b/t/Testhelper.pm
@@ -270,7 +270,7 @@ sub run_one_po4aconf {
     pass("Change directory back to $cwd");
 
     my $expected_outfile = $t->{'expected_outfile'} // "$path/_output";
-    unless ( $t->{'diff_outfile'} ) {
+    unless ( -e $expected_outfile ) {
         $expected_outfile = "$path/$expected_outfile"
           if ( not -e $expected_outfile ) && ( -e "$path/$expected_outfile" );
         unless ( -e $expected_outfile ) {
diff --git a/t/add/modifiers/_output b/t/add/modifiers/_output
index 7a93e0caf..a6fcb4050 100644
--- a/t/add/modifiers/_output
+++ b/t/add/modifiers/_output
@@ -1,4 +1,5 @@
 NOT creating modifiers.pot as requested (--no-update).
+NOT updating the POT file modifiers.pot as requested (--no-update).
 with-1 is 100% translated (2 strings).
 without-2 is 100% translated (2 strings).
 without-3 is 100% translated (2 strings).
diff --git a/t/cfg-multi.t b/t/cfg-multi.t
index aec9dde00..80fbb56bc 100644
--- a/t/cfg-multi.t
+++ b/t/cfg-multi.t
@@ -11,9 +11,9 @@ use Testhelper;
 
 my @tests;
 push @tests, {
-    'doc'         => 'Multiple languages, no pot no po',
-    'po4a.conf'   => 'cfg/multiple-nopotpo/po4a.conf',
-    'closed_path' => 'cfg/*/',                             # Do not use or modify the other tests
+    'doc'            => 'Multiple languages, no pot no po',
+    'po4a.conf'      => 'cfg/multiple-nopotpo/po4a.conf',
+    'closed_path'    => 'cfg/*/',                             # Do not use or modify the other tests
     'expected_files' => 'multiple.de.po multiple.es.po multiple.fr.po multiple.it.po multiple.pot',
   },
   {
@@ -48,6 +48,22 @@ push @tests, {
       . 'multiple.man.de.1 multiple.man.es.1 multiple.man.fr.1 multiple.man.it.1 multiple.pot',
 
   },
+  {
+    'doc'              => 'Multiple languages, translation uptodate, translate only one language',
+    'po4a.conf'        => 'cfg/multiple-uptodate/po4a.conf',
+    'options'          => ' --translate-only multiple.man.de.1',
+    'closed_path'      => 'cfg/*/',
+    'expected_outfile' => 'cfg/multiple-uptodate/_output-only-one',
+    'expected_files'   => 'multiple.man.de.1',
+  },
+  {
+    'doc'              => 'Multiple languages, translation uptodate, translate only two languages',
+    'po4a.conf'        => 'cfg/multiple-uptodate/po4a.conf',
+    'options'          => ' --translate-only multiple.man.de.1 --translate-only multiple.man.es.1',
+    'closed_path'      => 'cfg/*/',
+    'expected_outfile' => 'cfg/multiple-uptodate/_output-only-two',
+    'expected_files'   => 'multiple.man.de.1 multiple.man.es.1',
+  },
   {
     'doc'            => 'Multiple languages, translation already fuzzy',
     'po4a.conf'      => 'cfg/multiple-fuzzy/po4a.conf',
diff --git a/t/cfg/args-alias-redef/_output b/t/cfg/args-alias-redef/_output
index d0467854e..b6bfe9945 100644
--- a/t/cfg/args-alias-redef/_output
+++ b/t/cfg/args-alias-redef/_output
@@ -1,4 +1,5 @@
 NOT creating args.pot as requested (--no-update).
+NOT updating the POT file args.pot as requested (--no-update).
 man.de.1 is 20% translated (1 of 5 strings).
 Discard man.es.1 (3 of 5 strings; only 60% translated; need 70%).
 man.fr.1 is 80% translated (4 of 5 strings).
diff --git a/t/cfg/args-alias/_output b/t/cfg/args-alias/_output
index 0a88fc814..da4af66dc 100644
--- a/t/cfg/args-alias/_output
+++ b/t/cfg/args-alias/_output
@@ -1,4 +1,5 @@
 NOT creating args.pot as requested (--no-update).
+NOT updating the POT file args.pot as requested (--no-update).
 man.de.1 is 20% translated (1 of 5 strings).
 Discard man.de.2 (1 of 5 strings; only 20% translated; need 80%).
 Discard man.es.1 (3 of 5 strings; only 60% translated; need 70%).
diff --git a/t/cfg/args-alias/_output-keep100 b/t/cfg/args-alias/_output-keep100
index ec49800ce..cacbc50f3 100644
--- a/t/cfg/args-alias/_output-keep100
+++ b/t/cfg/args-alias/_output-keep100
@@ -1,4 +1,5 @@
 NOT creating args.pot as requested (--no-update).
+NOT updating the POT file args.pot as requested (--no-update).
 Discard man.de.1 (1 of 5 strings; only 20% translated; need 100%).
 Discard man.de.2 (1 of 5 strings; only 20% translated; need 100%).
 Discard man.es.1 (3 of 5 strings; only 60% translated; need 100%).
diff --git a/t/cfg/args-global/_output b/t/cfg/args-global/_output
index 32a9b921c..b649c4434 100644
--- a/t/cfg/args-global/_output
+++ b/t/cfg/args-global/_output
@@ -1,4 +1,5 @@
 NOT creating args.pot as requested (--no-update).
+NOT updating the POT file args.pot as requested (--no-update).
 man.de.1 is 20% translated (1 of 5 strings).
 man.es.1 is 60% translated (3 of 5 strings).
 man.fr.1 is 80% translated (4 of 5 strings).
diff --git a/t/cfg/args-global/_output-keep100 b/t/cfg/args-global/_output-keep100
index c0b91f56c..2b9d1e4a1 100644
--- a/t/cfg/args-global/_output-keep100
+++ b/t/cfg/args-global/_output-keep100
@@ -1,4 +1,5 @@
 NOT creating args.pot as requested (--no-update).
+NOT updating the POT file args.pot as requested (--no-update).
 Discard man.de.1 (1 of 5 strings; only 20% translated; need 100%).
 Discard man.es.1 (3 of 5 strings; only 60% translated; need 100%).
 Discard man.fr.1 (4 of 5 strings; only 80% translated; need 100%).
diff --git a/t/cfg/args-master/_output b/t/cfg/args-master/_output
index 208d3a1c7..db00cb6a9 100644
--- a/t/cfg/args-master/_output
+++ b/t/cfg/args-master/_output
@@ -1,4 +1,5 @@
 NOT creating args.pot as requested (--no-update).
+NOT updating the POT file args.pot as requested (--no-update).
 Discard man.de.1 (1 of 5 strings; only 20% translated; need 22%).
 Discard man.es.1 (3 of 5 strings; only 60% translated; need 66%).
 man.fr.1 is 80% translated (4 of 5 strings).
diff --git a/t/cfg/args-master/_output-keep100 b/t/cfg/args-master/_output-keep100
index c0b91f56c..2b9d1e4a1 100644
--- a/t/cfg/args-master/_output-keep100
+++ b/t/cfg/args-master/_output-keep100
@@ -1,4 +1,5 @@
 NOT creating args.pot as requested (--no-update).
+NOT updating the POT file args.pot as requested (--no-update).
 Discard man.de.1 (1 of 5 strings; only 20% translated; need 100%).
 Discard man.es.1 (3 of 5 strings; only 60% translated; need 100%).
 Discard man.fr.1 (4 of 5 strings; only 80% translated; need 100%).
diff --git a/t/cfg/multiple-fuzzied-noup/_output b/t/cfg/multiple-fuzzied-noup/_output
index 9f3763842..a33da7709 100644
--- a/t/cfg/multiple-fuzzied-noup/_output
+++ b/t/cfg/multiple-fuzzied-noup/_output
@@ -1,4 +1,5 @@
 NOT updating multiple.pot as requested (--no-update).
+NOT updating the POT file multiple.pot as requested (--no-update).
 Discard multiple.man.de.1 (3 of 4 strings; only 75% translated; need 80%).
 Discard multiple.man.es.1 (3 of 4 strings; only 75% translated; need 80%).
 Discard multiple.man.fr.1 (3 of 4 strings; only 75% translated; need 80%).
diff --git a/t/cfg/multiple-nopo/_output-noupdate b/t/cfg/multiple-nopo/_output-noupdate
index bd913a32e..d3cc84a76 100644
--- a/t/cfg/multiple-nopo/_output-noupdate
+++ b/t/cfg/multiple-nopo/_output-noupdate
@@ -1,4 +1,5 @@
 NOT updating multiple.pot as requested (--no-update).
+NOT updating the POT file multiple.pot as requested (--no-update).
 PO file multiple.de.po for language de is missing -- skipping.
 PO file multiple.es.po for language es is missing -- skipping.
 PO file multiple.fr.po for language fr is missing -- skipping.
diff --git a/t/cfg/multiple-uptodate/_output-only-one b/t/cfg/multiple-uptodate/_output-only-one
new file mode 100644
index 000000000..50b13626d
--- /dev/null
+++ b/t/cfg/multiple-uptodate/_output-only-one
@@ -0,0 +1,4 @@
+Document multiple.man.1 kept for update (--translate-only).
+Languages skipped because of --translate-only: es fr it; kept languages: de.
+NOT updating the POT file multiple.pot because of --translate-only.
+multiple.man.de.1 is 100% translated (4 strings).
diff --git a/t/cfg/multiple-uptodate/_output-only-two b/t/cfg/multiple-uptodate/_output-only-two
new file mode 100644
index 000000000..1c2f2fbdf
--- /dev/null
+++ b/t/cfg/multiple-uptodate/_output-only-two
@@ -0,0 +1,5 @@
+Document multiple.man.1 kept for update (--translate-only).
+Languages skipped because of --translate-only: fr it; kept languages: de es.
+NOT updating the POT file multiple.pot because of --translate-only.
+multiple.man.de.1 is 100% translated (4 strings).
+multiple.man.es.1 is 100% translated (4 strings).
diff --git a/t/cfg/single-fuzzied-noup/_output b/t/cfg/single-fuzzied-noup/_output
index fde8e19f8..9fb696e0b 100644
--- a/t/cfg/single-fuzzied-noup/_output
+++ b/t/cfg/single-fuzzied-noup/_output
@@ -1,2 +1,3 @@
 NOT updating single-fuzzied-noup.pot as requested (--no-update).
+NOT updating the POT file single-fuzzied-noup.pot as requested (--no-update).
 Discard single-fuzzied-noup.man.fr.1 (3 of 4 strings; only 75% translated; need 80%).
diff --git a/t/cfg/single-nopo/_output-noupdate b/t/cfg/single-nopo/_output-noupdate
index c8d15b4c8..223727166 100644
--- a/t/cfg/single-nopo/_output-noupdate
+++ b/t/cfg/single-nopo/_output-noupdate
@@ -1,2 +1,3 @@
 NOT updating single.pot as requested (--no-update).
+NOT updating the POT file single.pot as requested (--no-update).
 PO file single.fr.po for language fr is missing -- skipping.