2002-01-24 Hans Breuer <hans@breuer.org>
[dia.git] / xml-i18n-update.in.kg
blobb57378a52c6547eda2d1f87f293e8312b128fb1e
1 #!@XML_I18N_TOOLS_PERL@ -w
3 #  The GNOME Translation Update Tool
5 #  Copyright (C) 2000 Free Software Foundation.
7 #  This library is free software; you can redistribute it and/or
8 #  modify it under the terms of the GNU General Public License as
9 #  published by the Free Software Foundation; either version 2 of the
10 #  License, or (at your option) any later version.
12 #  This script is distributed in the hope that it will be useful,
13 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 #  General Public License for more details.
17 #  You should have received a copy of the GNU General Public License
18 #  along with this library; if not, write to the Free Software
19 #  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #  Author(s): Kenneth Christiansen
23 ## Release information
24 my $PROGRAM  = "xml-i18n-update";
25 my $VERSION  = "0.9";
26 my $_PACKAGE = "xml-i18n-tools";
28 ## Loaded modules
29 use strict;
30 use Getopt::Long;
31 use Cwd;
32 use File::Copy;
33 use File::Find;
35 ## Scalars used by the option stuff
36 my $LANG           = $ARGV[0];
37 my $HELP_ARG       = "0";
38 my $VERSION_ARG    = "0";
39 my $DIST_ARG       = "0";
40 my $POT_ARG        = "0";
41 my $HEADERS_ARG    = "0";
42 my $MAINTAIN_ARG   = "0";
43 my $REPORT_ARG     = "0";
44 my $VERBOSE        = "0";
46 my @languages;
47 my %po_files_by_lang = ();
49 my $xml_extension = 
50 "xml(\.in)*|".          # .in is not required
51 "ui|".
52 "glade(\.in)*|".        # .in is not required
53 "desktop(\.in)+|".
54 "directory(\.in)+|".
55 "soundlist(\.in)+|".
56 "keys(\.in)+|".
57 "oaf(\.in)+|".
58 "server(\.in)+|".
59 "etspec|".
60 "sheet(\.in)+|".
61 "pong(\.in)+";
63 my $PACKAGE = &find_package_name;
65 ## Always print as the first thing
66 $| = 1;
68 ## Give error if script is run without an argument
69 if (! $LANG){
70     print "${PROGRAM}:  missing file arguments\n";
71     print "Try `${PROGRAM} --help' for more information.\n";
72     exit;
75 ## Handle options
76 GetOptions (
77             "help|h|?"          => \$HELP_ARG,
78             "version|v"         => \$VERSION_ARG,
79             "dist|d"            => \$DIST_ARG,
80             "pot|p"             => \$POT_ARG,
81             "headers|s"         => \$HEADERS_ARG,
82             "maintain|m"        => \$MAINTAIN_ARG,
83             "report|r"          => \$REPORT_ARG,
84             "verbose|x"         => \$VERBOSE
85             ) or &invalid_option;
88 ## Use the supplied arguments
89 ## Check for options.
90 ## This section will check for the different options.
92 sub split_on_argument {
94     if ($VERSION_ARG) {
95         &version;
97     } elsif ($HELP_ARG) {
98         &help;
100     } elsif ($DIST_ARG) {
101         &merging;
102         &status;
104     } elsif ($POT_ARG) {
105         &gen_headers;
106         &generate_pot;
108     } elsif ($HEADERS_ARG) {
109         &gen_headers;
110         exit;
112     } elsif ($MAINTAIN_ARG) {
113         &maintain;
115     } elsif ($REPORT_ARG) {
116         &show_status;
118     } elsif ($LANG) {
119         if ($LANG =~ /^-/){ ## not an option
120             &help;
121         } else {
122             &main;
123         }
125     } else {
126         &help;
127     }
130 &split_on_argument;
132 sub main
134    if(-s "$LANG.po"){
135         print "Working, please wait..." unless $VERBOSE;
136         &gen_headers;
137         &generate_pot;
138         &merging;
139         &status;
140    }
142    ## Report error if the language file supplied
143    ## to the command line is non-existent
144    else {
145         &not_existing;
146    }
149 sub determine_type($) {
150    my $type = $_;
152    my $gettext_type;
154    if ($type =~ /\[type: (gettext\/[^\]].*)]/) {
155         $gettext_type=$1;
156    }
157    elsif ($type =~ /(?:xml(\.in)*|ui|oaf(?:\.in)+|sheet(?:\.in)+|pong(?:\.in)+|etspec)$/) {
158         $gettext_type="gettext\/xml";
159    }
160    elsif ($type =~ /glade(\.in)*$/) {
161         $gettext_type="gettext\/glade";
162    }
163    elsif ($type =~ /(?:desktop(?:\.in)+|directory(?:\.in)+|soundlist(?:\.in)+)$/) {
164         $gettext_type="gettext\/ini";
165    }
166    elsif ($type =~ /keys(\.in)+$/) {
167         $gettext_type="gettext\/keys";
168    }
169    else { $gettext_type=""; }
171    return $gettext_type;
174 sub version{
176     ## Print version information
177     print "${PROGRAM} (${_PACKAGE}) $VERSION\n";
178     print "Written by Kenneth Christiansen <kenneth\@gnome.org>, 2000.\n\n";
179     print "Copyright (C) 2000 Free Software Foundation, Inc.\n";
180     print "This is free software; see the source for copying conditions.  There is NO\n";
181     print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
182     exit;
185 sub help
187     ## Print usage information
188     print "Usage: ./${PROGRAM} [OPTIONS] ...LANGCODE\n";
189     print "Updates pot files and merge them with the translations.\n\n";
190     print "  -H, --help                   shows this help page\n";
191     print "  -P, --pot                    generate the pot file only\n";
192     print "  -S, --headers                generate the XML headerfiles in POTFILES.in\n";
193     print "  -M, --maintain               search for missing files in POTFILES.in\n";
194     print "  -R, --report                 creates a status report for the module.\n";
195     print "  -X, --verbose                show lots of feedback\n";
196     print "  -V, --version                shows the version\n";
197     print "\nExamples of use:\n";
198     print "${PROGRAM} --pot    just creates a new pot file from the source\n";
199     print "${PROGRAM} da       created new pot file and updated the da.po file\n\n";
200     print "Report bugs to <kenneth\@gnome.org>.\n";
201     exit;
204 sub maintain
206     my (@buf_i18n_plain,
207         @buf_i18n_xml,
208         @buf_potfiles,
209         @buf_potfiles_ignore,
210         @buf_allfiles,
211         @buf_allfiles_sorted,
212         @buf_potfiles_sorted
213     );
215     ## Search and find all translatable files
216     find sub { push @buf_i18n_plain, "$File::Find::name" if /\.(c|y|cc|c\+\+|h|gob)$/ }, "..";
217     find sub { push @buf_i18n_xml, "$File::Find::name" if /\.($xml_extension)$/ }, "..";
219     open(POTFILES, "POTFILES.in") || die "$PROGRAM:  there's no POTFILES.in!!!\n";
220     @buf_potfiles = <POTFILES>;
222     print "Searching for missing translatable files...\n";
224     ## Check if we should ignore some found files, when
225     ## comparing with POTFILES.in
226     if (-s "POTFILES.skip"){
227         open FILE, "POTFILES.skip";
228         while (<FILE>) {
229             if (/^[^#]/){
230                 push @buf_potfiles_ignore, $_;
231             }
232         }
233         print "Found POTFILES.skip: Ignoring files...\n";
234         @buf_potfiles = (@buf_potfiles_ignore, @buf_potfiles);
235     }
237     foreach my $file (@buf_i18n_plain){
238         open FILE, "<$file";
239         while (<FILE>) {
240             if (/_\(\"/){
241                 ## Remove the first 3 chars and add newline
242                 push @buf_allfiles, unpack("x3 A*", $file) . "\n";
243                 last;
244             }
245         }
246     }
248     foreach my $file (@buf_i18n_xml){
249         open FILE, "<$file";
250         while (<FILE>) {
251             if (/\s_(.*)=\"/){
252                 ## Remove the first 3 chars and add newline
253                 push @buf_allfiles, unpack("x3 A*", $file) . "\n";
254                 last;
255             }
256         }
257     }
259     @buf_allfiles_sorted = sort (@buf_allfiles);
260     @buf_potfiles_sorted = sort (@buf_potfiles);
262     my %in2;
263     foreach (@buf_potfiles_sorted) {
264         $in2{$_} = 1;
265     }
267     my @result;
269     foreach (@buf_allfiles_sorted){
270         if (!exists($in2{$_})){
271             push @result, $_
272         }
273     }
275     ## Save file with information about the files missing
276     ## if any, and give information about this proceedier
277     if(@result){
278         open OUT, ">missing";
279         print OUT @result;
280         print "\nHere is the result:\n\n", @result, "\n";
281         print "The file \"missing\" has been placed in the current directory.\n";
282         print "Files supposed to be ignored should be placed in \"POTFILES.skip\"\n";
283     }
285     ## If there is nothing to complain about, notice the user
286     else{
287         print "\nWell, it's all perfect! Congratulation!\n";
288     }
291 sub invalid_option
293     ## Handle invalid arguments
294     print "${PROGRAM}: invalid option -- $LANG\n";
295     print "Try `${PROGRAM} --help' for more information.\n";
296     exit 1;
299 sub gen_headers
301     my $XML_I18N_EXTRACT = `which xml-i18n-extract 2>/dev/null`;
302     chomp $XML_I18N_EXTRACT;
304     $XML_I18N_EXTRACT = $ENV{"XML_I18N_EXTRACT"} if $ENV{"XML_I18N_EXTRACT"};
306     ## Generate the .h header files, so we can allow glade and
307     ## xml translation support
308     if (! -s $XML_I18N_EXTRACT)
309     {
310         print "\n *** The xml-i18n-extract script wasn't found!"
311              ."\n *** Without this xml-i18n-update can not generate files.\n";
312         exit;
313     }
314     else
315     {
316         open FILE, "<POTFILES.in";
317         while (<FILE>) {
318            chomp;
320            ## Find xml files in POTFILES.in and generate the
321            ## files with help from the xml-i18n-extract script
323            my $gettext_type=&determine_type($1);
325            if (/\.($xml_extension)$/ || /^\[/){
326                $_ =~ s/^\[[^\[].*]\s*//;
327                my $filename = "../$_";
329                if ($VERBOSE){
330                    system($XML_I18N_EXTRACT, "--update", "--type=$gettext_type", $filename);
331                } else {
332                    system($XML_I18N_EXTRACT, "--update", "--type=$gettext_type", "--quiet", $filename);
333                }
334            }
335        }
336        close FILE;
337    }
340 sub generate_pot
342     ## Generate the potfiles from the POTFILES.in file
344     print "Building the $PACKAGE.pot...\n" if $VERBOSE;
346     move("POTFILES.in", "POTFILES.in.old");
348     open INFILE, "<POTFILES.in.old";
349     open OUTFILE, ">POTFILES.in";
350     while (<INFILE>) {
351         s/\.($xml_extension)$/$&.h/;
352         s/^\[.*]\s*(.*)/$1.h/;
353         print OUTFILE $_;
354     }
355     close OUTFILE;
356     close INFILE;
358     my $gettext_test   ="test \! -f $PACKAGE\.po \|\| \( rm -f \.\/$PACKAGE\.pot "
359                        ."&& mv $PACKAGE\.po \.\/$PACKAGE\.pot \)";
361     system("xgettext", "--default-domain\=$PACKAGE", "--directory\=\.\.",
362            "--add-comments", "--keyword\=\_", "--keyword\=N\_",
363            "--files-from\=\.\/POTFILES\.in");
365     system($gettext_test);
367     print "Wrote $PACKAGE.pot\n" if $VERBOSE;
369     move("POTFILES.in.old", "POTFILES.in");
371     print "Removing generated header (.h) files..." if $VERBOSE;
373     open FILE, "<POTFILES.in";
374     while (<FILE>)
375     {
376         chomp;
377         unlink "../$_.h" if /\.($xml_extension)$/;
378     }
379     close FILE;
380     print "done\n" if $VERBOSE;
383 sub merging
385     if ($ARGV[1]){
386         $LANG   = $ARGV[1];
387     } else {
388         $LANG   = $ARGV[0];
389     }
391     if ($ARGV[0] ne "--dist" && $ARGV[0] ne "-D") {
392         print "Merging $LANG.po with $PACKAGE.pot..." if $VERBOSE;
393     }
395     &perform_merge($LANG);
396     ## Remove the "messages" trash file generated by gettext
397     unlink "messages";
400 sub perform_merge
402     my ($LANG) = @_;
404     copy("$LANG.po", "$LANG.po.old") || die "copy failed: $!";
406     ## Preform merge
407     system("msgmerge", "$LANG.po.old", "$PACKAGE.pot", "-o", "$LANG.po");
409     ## Remove the backup file
410     unlink "$LANG.po.old";
413 sub not_existing
415     ## Report error if supplied language file is non-existing
416     print "$PROGRAM:  sorry, $LANG.po does not exist!\n";
417     print "Try `$PROGRAM --help' for more information.\n";
418     exit;
421 sub gather_po_files
423     my @po_files = glob("./*.po");
425     @languages = map (&po_file2lang, @po_files);
427     foreach my $lang (@languages) {
428         $po_files_by_lang{$lang} = shift (@po_files);
429     }
432 sub po_file2lang
434     my $tmp = $_;
435     $tmp =~ s/^.*\/(.*)\.po$/$1/;
436     return $tmp;
439 sub status
441     ## Print statistics
442     system("msgfmt", "--statistics", "$LANG.po");
443     print "\n";
446 sub show_status
448     &gen_headers;
449     &generate_pot;
450     &gather_po_files;
452     foreach my $lang (@languages){
453         print "$lang: ";
454         &perform_merge($lang);
455     }
457     print "\n\n * Current translation support in $PACKAGE \n\n";
459     foreach my $lang (@languages){
460         print "$lang: ";
461         ## Print statistics
462         system("msgfmt", "--statistics", "$lang.po");
463     }
466 sub find_package_name
468     my $base_dirname = getcwd();
469     $base_dirname =~ s@.*/@@;
471     my ($conf_in, $src_dir);
473     if ($base_dirname eq "po") {
474         if (-f "../configure.in") {
475             $conf_in = "../configure.in";
476         } else {
477             my $makefile_source;
478             local (*IN);
479             open (IN, "<Makefile") || die "can't open Makefile: $!";
481             while (<IN>) {
482                 if (/^top_srcdir[ \t]*=/) {
483                     $src_dir = $_;
484                     # print "${src_dir}\n";
486                     $src_dir =~ s/^top_srcdir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/;
487                     # print "${src_dir}\n";
488                     chomp $src_dir;
489                     $conf_in = "$src_dir" . "/configure.in" . "\n";
490                     last;
491                 }
492             }
493             $conf_in || die "Cannot find top_srcdir in Makefile."
494         }
496         my $conf_source; {
497            local (*IN);
498            local $/; # slurp mode
499            open (IN, "<$conf_in") || die "can't open $conf_in: $!";
500            $conf_source = <IN>;
501         }
503         if ($conf_source =~ /AM_INIT_AUTOMAKE\(([^,]*),(.*)/) {
504             my $package_name = $1;
505             if ($package_name =~ /^[\$](.*)/){
506                 if ($conf_source =~ /$1=(.*)/) {
507                     $package_name = $1;
508                 }
509             }
510             return $package_name;
511         }
512     }
514     print "$PROGRAM: Unable to determine package name.\n" .
515           "Make sure to run this script inside the po directory.\n";
516     exit;