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

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