source: trunk/third/gnome-core/xml-i18n-update.in @ 15821

Revision 15821, 12.5 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15820, 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.8.2";
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 = "xml|ui|glade|desktop\.in|directory\.in|"
50                   ."soundlist\.in|keys\.in|oaf(\.in)+";
51
52my $PACKAGE = &find_package_name;
53
54## Always print as the first thing
55$| = 1;
56
57## Give error if script is run without an argument
58if (! $LANG){
59    print "${PROGRAM}:  missing file arguments\n";
60    print "Try `${PROGRAM} --help' for more information.\n";
61    exit;
62}
63
64## Handle options
65GetOptions (
66            "help|h|?"          => \$HELP_ARG,
67            "version|v"         => \$VERSION_ARG,
68            "dist|d"            => \$DIST_ARG,
69            "pot|p"             => \$POT_ARG,
70            "headers|s"         => \$HEADERS_ARG,
71            "maintain|m"        => \$MAINTAIN_ARG,
72            "report|r"          => \$REPORT_ARG,
73            "verbose|x"         => \$VERBOSE
74            ) or &invalid_option;
75
76
77## Use the supplied arguments
78## Check for options.
79## This section will check for the different options.
80
81sub split_on_argument {
82
83    if ($VERSION_ARG) {
84        &version;
85
86    } elsif ($HELP_ARG) {
87        &help;
88
89    } elsif ($DIST_ARG) {
90        &merging;
91        &status;
92
93    } elsif ($POT_ARG) {
94        &gen_headers;
95        &generate_pot;
96
97    } elsif ($HEADERS_ARG) {
98        &gen_headers;
99        exit;
100
101    } elsif ($MAINTAIN_ARG) {
102        &maintain;
103
104    } elsif ($REPORT_ARG) {
105        &show_status;
106
107    } elsif ($LANG) {
108        if ($LANG =~ /^-/){ ## not an option
109            &help;
110        } else {
111            &main;
112        }
113
114    } else {
115        &help;
116    }
117}
118
119&split_on_argument;
120
121sub main
122{
123   if(-s "$LANG.po"){
124        print "Working, please wait..." unless $VERBOSE;
125        &gen_headers;
126        &generate_pot;
127        &merging;
128        &status;
129   }
130
131   ## Report error if the language file supplied
132   ## to the command line is non-existent
133   else {
134        &not_existing;
135   }
136}
137
138sub determine_type($) {
139   my $type = $_;
140
141   my $gettext_type;
142
143   if ($type =~ /\[type: (gettext\/[^\]].*)]/) {
144        $gettext_type=$1;
145   }
146   elsif ($type =~ /(xml|ui|oaf(\.in)+)$/) {
147        $gettext_type="gettext\/xml";
148   }
149   elsif ($type =~ /glade$/) {
150        $gettext_type="gettext\/glade";
151   }
152   elsif ($type =~ /desktop(\.in)+$/) {
153        $gettext_type="gettext\/ini";
154   }
155   elsif ($type =~ /directory(\.in)+$/) {
156        $gettext_type="gettext\/ini";
157   }
158   elsif ($type =~ /keys(\.in)+$/) {
159        $gettext_type="gettext\/keys";
160   }
161   else { $gettext_type=""; }
162
163   return $gettext_type;
164}
165
166sub version{
167
168    ## Print version information
169    print "${PROGRAM} (${_PACKAGE}) $VERSION\n";
170    print "Written by Kenneth Christiansen <kenneth\@gnome.org>, 2000.\n\n";
171    print "Copyright (C) 2000 Free Software Foundation, Inc.\n";
172    print "This is free software; see the source for copying conditions.  There is NO\n";
173    print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
174    exit;
175}
176
177sub help
178{
179    ## Print usage information
180    print "Usage: ./${PROGRAM} [OPTIONS] ...LANGCODE\n";
181    print "Updates pot files and merge them with the translations.\n\n";
182    print "  -H, --help                   shows this help page\n";
183    print "  -P, --pot                    generate the pot file only\n";
184    print "  -S, --headers                generate the XML headerfiles in POTFILES.in\n";
185    print "  -M, --maintain               search for missing files in POTFILES.in\n";
186    print "  -R, --report                 creates a status report for the module.\n";
187    print "  -X, --verbose                show lots of feedback\n";
188    print "  -V, --version                shows the version\n";
189    print "\nExamples of use:\n";
190    print "${PROGRAM} --pot    just creates a new pot file from the source\n";
191    print "${PROGRAM} da       created new pot file and updated the da.po file\n\n";
192    print "Report bugs to <kenneth\@gnome.org>.\n";
193    exit;
194}
195
196sub maintain
197{
198    my (@buf_i18n_plain,
199        @buf_i18n_xml,
200        @buf_potfiles,
201        @buf_potfiles_ignore,
202        @buf_allfiles,
203        @buf_allfiles_sorted,
204        @buf_potfiles_sorted
205    );
206
207    ## Search and find all translatable files
208    find sub { push @buf_i18n_plain, "$File::Find::name" if /\.(c|y|cc|c\+\+|h|gob)$/ }, "..";
209    find sub { push @buf_i18n_xml, "$File::Find::name" if /\.($xml_extension)$/ }, "..";
210
211    open(POTFILES, "POTFILES.in") || die "$PROGRAM:  there's no POTFILES.in!!!\n";
212    @buf_potfiles = <POTFILES>;
213
214    print "Searching for missing translatable files...\n";
215
216    ## Check if we should ignore some found files, when
217    ## comparing with POTFILES.in
218    if (-s "POTFILES.skip"){
219        open FILE, "POTFILES.skip";
220        while (<FILE>) {
221            if (/^[^#]/){
222                push @buf_potfiles_ignore, $_;
223            }
224        }
225        print "Found POTFILES.skip: Ignoring files...\n";
226        @buf_potfiles = (@buf_potfiles_ignore, @buf_potfiles);
227    }
228
229    foreach my $file (@buf_i18n_plain){
230        open FILE, "<$file";
231        while (<FILE>) {
232            if (/_\(\"/){
233                ## Remove the first 3 chars and add newline
234                push @buf_allfiles, unpack("x3 A*", $file) . "\n";
235                last;
236            }
237        }
238    }
239
240    foreach my $file (@buf_i18n_xml){
241        open FILE, "<$file";
242        while (<FILE>) {
243            if (/\s_(.*)=\"/){
244                ## Remove the first 3 chars and add newline
245                push @buf_allfiles, unpack("x3 A*", $file) . "\n";
246                last;
247            }
248        }
249    }
250
251    @buf_allfiles_sorted = sort (@buf_allfiles);
252    @buf_potfiles_sorted = sort (@buf_potfiles);
253
254    my %in2;
255    foreach (@buf_potfiles_sorted) {
256        $in2{$_} = 1;
257    }
258
259    my @result;
260
261    foreach (@buf_allfiles_sorted){
262        if (!exists($in2{$_})){
263            push @result, $_
264        }
265    }
266
267    ## Save file with information about the files missing
268    ## if any, and give information about this proceedier
269    if(@result){
270        open OUT, ">missing";
271        print OUT @result;
272        print "\nHere is the result:\n\n", @result, "\n";
273        print "The file \"missing\" has been placed in the current directory.\n";
274        print "Files supposed to be ignored should be placed in \"POTFILES.skip\"\n";
275    }
276
277    ## If there is nothing to complain about, notice the user
278    else{
279        print "\nWell, it's all perfect! Congratulation!\n";
280    }
281}
282
283sub invalid_option
284{
285    ## Handle invalid arguments
286    print "${PROGRAM}: invalid option -- $LANG\n";
287    print "Try `${PROGRAM} --help' for more information.\n";
288    exit 1;
289}
290
291sub gen_headers
292{
293    my $XML_I18N_EXTRACT = `which xml-i18n-extract 2>/dev/null`;
294    chomp $XML_I18N_EXTRACT;
295
296    $XML_I18N_EXTRACT = $ENV{"XML_I18N_EXTRACT"} if $ENV{"XML_I18N_EXTRACT"};
297
298    ## Generate the .h header files, so we can allow glade and
299    ## xml translation support
300    if (! -s $XML_I18N_EXTRACT)
301    {
302        print "\n *** The xml-i18n-extract script wasn't found!"
303             ."\n *** Without this xml-i18n-update can not generate files.\n";
304        exit;
305    }
306    else
307    {
308        open FILE, "<POTFILES.in";
309        while (<FILE>) {
310           chomp;
311
312           ## Find xml files in POTFILES.in and generate the
313           ## files with help from the xml-i18n-extract script
314
315           my $gettext_type=&determine_type($1);
316
317           if (/\.($xml_extension)$/ || /^\[/){
318               $_ =~ s/^\[[^\[].*]\s*//;
319               my $filename = "../$_";
320
321               if ($VERBOSE){
322                   system($XML_I18N_EXTRACT, "--update", "--type=$gettext_type", $filename);
323               } else {
324                   system($XML_I18N_EXTRACT, "--update", "--type=$gettext_type", "--quiet", $filename);
325               }
326           }
327       }
328       close FILE;
329   }
330}
331
332sub generate_pot
333{
334    ## Generate the potfiles from the POTFILES.in file
335
336    print "Building the $PACKAGE.pot...\n" if $VERBOSE;
337
338    move("POTFILES.in", "POTFILES.in.old");
339
340    open INFILE, "<POTFILES.in.old";
341    open OUTFILE, ">POTFILES.in";
342    while (<INFILE>) {
343        s/\.($xml_extension)$/$&.h/;
344        s/^\[.*]\s*(.*)/$1.h/;
345        print OUTFILE $_;
346    }
347    close OUTFILE;
348    close INFILE;
349
350    my $gettext_test   ="test \! -f $PACKAGE\.po \|\| \( rm -f \.\/$PACKAGE\.pot "
351                       ."&& mv $PACKAGE\.po \.\/$PACKAGE\.pot \)";
352
353    system("xgettext", "--default-domain\=$PACKAGE", "--directory\=\.\.",
354           "--add-comments", "--keyword\=\_", "--keyword\=N\_",
355           "--files-from\=\.\/POTFILES\.in");
356
357    system($gettext_test);
358
359    print "Wrote $PACKAGE.pot\n" if $VERBOSE;
360
361    move("POTFILES.in.old", "POTFILES.in");
362
363    print "Removing generated header (.h) files..." if $VERBOSE;
364
365    open FILE, "<POTFILES.in";
366    while (<FILE>)
367    {
368        chomp;
369        unlink "../$_.h" if /\.($xml_extension)$/;
370    }
371    close FILE;
372    print "done\n" if $VERBOSE;
373}
374
375sub merging
376{
377    if ($ARGV[1]){
378        $LANG   = $ARGV[1];
379    } else {
380        $LANG   = $ARGV[0];
381    }
382
383    if ($ARGV[0] ne "--dist" && $ARGV[0] ne "-D") {
384        print "Merging $LANG.po with $PACKAGE.pot..." if $VERBOSE;
385    }
386
387    &perform_merge($LANG);
388    ## Remove the "messages" trash file generated by gettext
389    unlink "messages";
390}
391
392sub perform_merge
393{
394    my ($LANG) = @_;
395
396    copy("$LANG.po", "$LANG.po.old") || die "copy failed: $!";
397
398    ## Preform merge
399    system("msgmerge", "$LANG.po.old", "$PACKAGE.pot", "-o", "$LANG.po");
400
401    ## Remove the backup file
402    unlink "$LANG.po.old";
403}
404
405sub not_existing
406{
407    ## Report error if supplied language file is non-existing
408    print "$PROGRAM:  sorry, $LANG.po does not exist!\n";
409    print "Try `$PROGRAM --help' for more information.\n";
410    exit;
411}
412
413sub gather_po_files
414{
415    my @po_files = glob("./*.po");
416
417    @languages = map (&po_file2lang, @po_files);
418
419    foreach my $lang (@languages) {
420        $po_files_by_lang{$lang} = shift (@po_files);
421    }
422}
423
424sub po_file2lang
425{
426    my $tmp = $_;
427    $tmp =~ s/^.*\/(.*)\.po$/$1/;
428    return $tmp;
429}
430
431sub status
432{
433    ## Print statistics
434    system("msgfmt", "--statistics", "$LANG.po");
435    print "\n";
436}
437
438sub show_status
439{
440    &gen_headers;
441    &generate_pot;
442    &gather_po_files;
443
444    foreach my $lang (@languages){
445        print "$lang: ";
446        &perform_merge($lang);
447    }
448
449    print "\n\n * Current translation support in $PACKAGE \n\n";
450
451    foreach my $lang (@languages){
452        print "$lang: ";
453        ## Print statistics
454        system("msgfmt", "--statistics", "$lang.po");
455    }
456}
457
458sub find_package_name
459{
460    my $base_dirname = getcwd();
461    $base_dirname =~ s@.*/@@;
462
463    my ($conf_in, $src_dir);
464
465    if ($base_dirname eq "po") {
466        if (-f "../configure.in") {
467            $conf_in = "../configure.in";
468        } else {
469            my $makefile_source;
470            local (*IN);
471            open (IN, "<Makefile") || die "can't open Makefile: $!";
472
473            while (<IN>) {
474                if (/^top_srcdir[ \t]*=/) {
475                    $src_dir = $_;
476                    # print "${src_dir}\n";
477
478                    $src_dir =~ s/^top_srcdir[ \t]*=[ \t]*([^ \t\n\r]*)/$1/;
479                    # print "${src_dir}\n";
480                    chomp $src_dir;
481                    $conf_in = "$src_dir" . "/configure.in" . "\n";
482                    last;
483                }
484            }
485
486            $conf_in || die "Cannot find top_srcdir in Makefile."
487        }
488
489        my $conf_source; {
490           local (*IN);
491           local $/; # slurp mode
492           open (IN, "<$conf_in") || die "can't open $conf_in: $!";
493           $conf_source = <IN>;
494        }
495
496        if ($conf_source =~ /AM_INIT_AUTOMAKE\(([^,]*),(.*)/) {
497            my $package_name = $1;
498            if ($package_name =~ /^[\$](.*)/){
499                if ($conf_source =~ /$1=(.*)/) {
500                    $package_name = $1;
501                }
502            }
503            return $package_name;
504        }
505    }
506
507    print "$PROGRAM: Unable to determine package name.\n" .
508          "Make sure to run this script inside the po directory.\n";
509    exit;
510}
Note: See TracBrowser for help on using the repository browser.