source: trunk/third/oaf/xml-i18n-update.in @ 16756

Revision 16756, 12.7 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16755, which included commits to RCS files with non-trunk default branches.
Line 
1#!@XML_I18N_TOOLS_PERL@ -w
2
3#  The GNOME Translation Update Tool
4#
5#  Copyright (C) 2000 Free Software Foundation.
6#
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.
11#
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.
16#
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.
20#
21#  Author(s): Kenneth Christiansen
22
23## Release information
24my $PROGRAM  = "xml-i18n-update";
25my $VERSION  = "0.9";
26my $_PACKAGE = "xml-i18n-tools";
27
28## Loaded modules
29use strict;
30use Getopt::Long;
31use Cwd;
32use File::Copy;
33use File::Find;
34
35## Scalars used by the option stuff
36my $LANG           = $ARGV[0];
37my $HELP_ARG       = "0";
38my $VERSION_ARG    = "0";
39my $DIST_ARG       = "0";
40my $POT_ARG        = "0";
41my $HEADERS_ARG    = "0";
42my $MAINTAIN_ARG   = "0";
43my $REPORT_ARG     = "0";
44my $VERBOSE        = "0";
45
46my @languages;
47my %po_files_by_lang = ();
48
49my $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)+";
62
63my $PACKAGE = &find_package_name;
64
65## Always print as the first thing
66$| = 1;
67
68## Give error if script is run without an argument
69if (! $LANG){
70    print "${PROGRAM}:  missing file arguments\n";
71    print "Try `${PROGRAM} --help' for more information.\n";
72    exit;
73}
74
75## Handle options
76GetOptions (
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;
86
87
88## Use the supplied arguments
89## Check for options.
90## This section will check for the different options.
91
92sub split_on_argument {
93
94    if ($VERSION_ARG) {
95        &version;
96
97    } elsif ($HELP_ARG) {
98        &help;
99
100    } elsif ($DIST_ARG) {
101        &merging;
102        &status;
103
104    } elsif ($POT_ARG) {
105        &gen_headers;
106        &generate_pot;
107
108    } elsif ($HEADERS_ARG) {
109        &gen_headers;
110        exit;
111
112    } elsif ($MAINTAIN_ARG) {
113        &maintain;
114
115    } elsif ($REPORT_ARG) {
116        &show_status;
117
118    } elsif ($LANG) {
119        if ($LANG =~ /^-/){ ## not an option
120            &help;
121        } else {
122            &main;
123        }
124
125    } else {
126        &help;
127    }
128}
129
130&split_on_argument;
131
132sub main
133{
134   if(-s "$LANG.po"){
135        print "Working, please wait..." unless $VERBOSE;
136        &gen_headers;
137        &generate_pot;
138        &merging;
139        &status;
140   }
141
142   ## Report error if the language file supplied
143   ## to the command line is non-existent
144   else {
145        &not_existing;
146   }
147}
148
149sub determine_type($) {
150   my $type = $_;
151
152   my $gettext_type;
153
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=""; }
170
171   return $gettext_type;
172}
173
174sub version{
175
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;
183}
184
185sub help
186{
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;
202}
203
204sub maintain
205{
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    );
214
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)$/ }, "..";
218
219    open(POTFILES, "POTFILES.in") || die "$PROGRAM:  there's no POTFILES.in!!!\n";
220    @buf_potfiles = <POTFILES>;
221
222    print "Searching for missing translatable files...\n";
223
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    }
236
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    }
247
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    }
258
259    @buf_allfiles_sorted = sort (@buf_allfiles);
260    @buf_potfiles_sorted = sort (@buf_potfiles);
261
262    my %in2;
263    foreach (@buf_potfiles_sorted) {
264        $in2{$_} = 1;
265    }
266
267    my @result;
268
269    foreach (@buf_allfiles_sorted){
270        if (!exists($in2{$_})){
271            push @result, $_
272        }
273    }
274
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    }
284
285    ## If there is nothing to complain about, notice the user
286    else{
287        print "\nWell, it's all perfect! Congratulation!\n";
288    }
289}
290
291sub invalid_option
292{
293    ## Handle invalid arguments
294    print "${PROGRAM}: invalid option -- $LANG\n";
295    print "Try `${PROGRAM} --help' for more information.\n";
296    exit 1;
297}
298
299sub gen_headers
300{
301    my $XML_I18N_EXTRACT = `which xml-i18n-extract 2>/dev/null`;
302    chomp $XML_I18N_EXTRACT;
303
304    $XML_I18N_EXTRACT = $ENV{"XML_I18N_EXTRACT"} if $ENV{"XML_I18N_EXTRACT"};
305
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;
319
320           ## Find xml files in POTFILES.in and generate the
321           ## files with help from the xml-i18n-extract script
322
323           my $gettext_type=&determine_type($1);
324
325           if (/\.($xml_extension)$/ || /^\[/){
326               $_ =~ s/^\[[^\[].*]\s*//;
327               my $filename = "../$_";
328
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   }
338}
339
340sub generate_pot
341{
342    ## Generate the potfiles from the POTFILES.in file
343
344    print "Building the $PACKAGE.pot...\n" if $VERBOSE;
345
346    move("POTFILES.in", "POTFILES.in.old");
347
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;
357
358    my $gettext_test   ="test \! -f $PACKAGE\.po \|\| \( rm -f \.\/$PACKAGE\.pot "
359                       ."&& mv $PACKAGE\.po \.\/$PACKAGE\.pot \)";
360
361    system("xgettext", "--default-domain\=$PACKAGE", "--directory\=\.\.",
362           "--add-comments", "--keyword\=\_", "--keyword\=N\_", "--keyword\=U\_",
363           "--files-from\=\.\/POTFILES\.in");
364
365    system($gettext_test);
366
367    print "Wrote $PACKAGE.pot\n" if $VERBOSE;
368
369    move("POTFILES.in.old", "POTFILES.in");
370
371    print "Removing generated header (.h) files..." if $VERBOSE;
372
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;
381}
382
383sub merging
384{
385    if ($ARGV[1]){
386        $LANG   = $ARGV[1];
387    } else {
388        $LANG   = $ARGV[0];
389    }
390
391    if ($ARGV[0] ne "--dist" && $ARGV[0] ne "-D") {
392        print "Merging $LANG.po with $PACKAGE.pot..." if $VERBOSE;
393    }
394
395    &perform_merge($LANG);
396    ## Remove the "messages" trash file generated by gettext
397    unlink "messages";
398}
399
400sub perform_merge
401{
402    my ($LANG) = @_;
403
404    copy("$LANG.po", "$LANG.po.old") || die "copy failed: $!";
405
406    ## Preform merge
407    system("msgmerge", "$LANG.po.old", "$PACKAGE.pot", "-o", "$LANG.po");
408
409    ## Remove the backup file
410    unlink "$LANG.po.old";
411}
412
413sub not_existing
414{
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;
419}
420
421sub gather_po_files
422{
423    my @po_files = glob("./*.po");
424
425    @languages = map (&po_file2lang, @po_files);
426
427    foreach my $lang (@languages) {
428        $po_files_by_lang{$lang} = shift (@po_files);
429    }
430}
431
432sub po_file2lang
433{
434    my $tmp = $_;
435    $tmp =~ s/^.*\/(.*)\.po$/$1/;
436    return $tmp;
437}
438
439sub status
440{
441    ## Print statistics
442    system("msgfmt", "--statistics", "$LANG.po");
443    print "\n";
444}
445
446sub show_status
447{
448    &gen_headers;
449    &generate_pot;
450    &gather_po_files;
451
452    foreach my $lang (@languages){
453        print "$lang: ";
454        &perform_merge($lang);
455    }
456
457    print "\n\n * Current translation support in $PACKAGE \n\n";
458
459    foreach my $lang (@languages){
460        print "$lang: ";
461        ## Print statistics
462        system("msgfmt", "--statistics", "$lang.po");
463    }
464}
465
466sub find_package_name
467{
468    my $base_dirname = getcwd();
469    $base_dirname =~ s@.*/@@;
470
471    my ($conf_in, $src_dir);
472
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: $!";
480
481            while (<IN>) {
482                if (/^top_srcdir[ \t]*=/) {
483                    $src_dir = $_;
484                    # print "${src_dir}\n";
485
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        }
495
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        }
502
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    }
513
514    print "$PROGRAM: Unable to determine package name.\n" .
515          "Make sure to run this script inside the po directory.\n";
516    exit;
517}
Note: See TracBrowser for help on using the repository browser.