source: trunk/third/gnome-vfs/xml-i18n-merge.in @ 15858

Revision 15858, 9.4 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15857, which included commits to RCS files with non-trunk default branches.
  • Property svn:executable set to *
Line 
1#!@XML_I18N_TOOLS_PERL@ -w
2
3#
4#  The XML Translation Merge Tool
5#
6#  Copyright (C) 2000 Free Software Foundation.
7#  Copyright (C) 2000, 2001 Eazel, Inc
8#
9#  This library is free software; you can redistribute it and/or
10#  modify it under the terms of the GNU General Public License as
11#  published by the Free Software Foundation; either version 2 of the
12#  License, or (at your option) any later version.
13#
14#  This script is distributed in the hope that it will be useful,
15#  but WITHOUT ANY WARRANTY; without even the implied warranty of
16#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17#  General Public License for more details.
18#
19#  You should have received a copy of the GNU General Public License
20#  along with this library; if not, write to the Free Software
21#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22#
23#  Authors:  Maciej Stachowiak <mjs@eazel.com>
24#            Kenneth Christiansen <kenneth@gnu.org>
25#            Darin Adler <darin@eazel.com>
26#
27
28
29## Release information
30my $PROGRAM      = "xml-i18n-merge";
31my $PACKAGE      = "xml-i18n-tools";
32my $VERSION      = "0.8.1";
33
34## Script options - Enable by setting value to 1
35my $ENABLE_XML   = "1";
36
37## Loaded modules
38use strict;
39use File::Basename;
40use Getopt::Long;
41
42## Scalars used by the option stuff
43my $HELP_ARG    = "0";
44my $VERSION_ARG = "0";
45my $XML_STYLE_ARG = "0";
46my $KEYS_STYLE_ARG = "0";
47my $DESKTOP_STYLE_ARG = "0";
48my $QUIET_ARG = "0";
49
50
51## Handle options
52GetOptions (
53            "help|h|?" => \$HELP_ARG,
54            "version|v" => \$VERSION_ARG,
55            "quiet|q" => \$QUIET_ARG,
56            "xml-style|o" => \$XML_STYLE_ARG,
57            "keys-style|k" => \$KEYS_STYLE_ARG,
58            "desktop-style|d" => \$DESKTOP_STYLE_ARG
59            ) or &error;
60
61
62my $PO_DIR;
63my $FILE;
64my $OUTFILE;
65
66my @languages;
67my %po_files_by_lang = ();
68my %translations = ();
69
70&split_on_argument;
71
72
73## Check for options.
74## This section will check for the different options.
75
76sub split_on_argument {
77
78    if ($VERSION_ARG) {
79        &version;
80
81    } elsif ($HELP_ARG) {
82        &help;
83    } elsif ($XML_STYLE_ARG && @ARGV > 2) {
84        &place_normal;
85        &message;
86        &preparation;
87        &xml_merge_translations;
88    } elsif ($KEYS_STYLE_ARG && @ARGV > 2) {
89        &place_normal;
90        &message;
91        &preparation;
92        &keys_merge_translations;
93    } elsif ($DESKTOP_STYLE_ARG && @ARGV > 2) {
94        &place_normal;
95        &message;
96        &preparation;
97        &desktop_merge_translations;
98    } else {
99        &help;
100    } 
101}   
102
103
104sub place_normal {
105    $PO_DIR = $ARGV[0];
106    $FILE = $ARGV[1];
107    $OUTFILE = $ARGV[2];
108}   
109
110
111## Sub for printing release information
112sub version{
113    print "${PROGRAM} (${PACKAGE}) ${VERSION}\n";
114    print "Written by Maciej Stachowiak and Kenneth Christiansen, 2000.\n\n";
115    print "Copyright (C) 2000 Free Software Foundation, Inc.\n";
116    print "Copyright (C) 2000, 2001 Eazel, Inc.\n";
117    print "This is free software; see the source for copying conditions.  There is NO\n";
118    print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
119    exit;
120}
121
122## Sub for printing usage information
123sub help{
124    print "Usage: ${PROGRAM} [OPTIONS] PO_DIRECTORY FILENAME OUTPUT_FILE\n";
125    print "Generates an xml file that includes translated versions of some attributes,\n";
126    print "from an untranslated source and a po directory that includes translations.\n";
127    print "  -v, --version                shows the version\n";
128    print "  -h, --help                   shows this help page\n";
129    print "  -q, --quiet                  quiet mode\n";
130    print "  -o, --xml-style              includes translations in the xml style\n";
131    print "  -k, --keys-style             includes translations in the keys style\n";
132    print "  -d, --desktop-style          includes translations in the desktop style\n";
133    print "\nReport bugs to <mjs\@eazel.com>.\n";
134    exit;
135}
136
137
138## Sub for printing error messages
139sub error{
140#   print "xml-i18n-merge: invalid option @ARGV\n";
141    print "Try `${PROGRAM} --help' for more information.\n";
142    exit;
143}
144
145
146sub message {
147    print "Merging translations into $OUTFILE.\n" unless $QUIET_ARG;
148}
149
150
151
152sub preparation {
153   &gather_po_files;
154   &create_translation_database;   
155}
156
157
158
159# General-purpose code for looking up translations in .po files
160
161sub gather_po_files
162{
163    my @po_files = glob("${PO_DIR}/*.po");
164
165    @languages = map (&po_file2lang, @po_files);
166
167    foreach my $lang (@languages) {
168        $po_files_by_lang{$lang} = shift (@po_files);
169    }
170}
171
172sub po_file2lang
173{
174    my $tmp = $_;
175    $tmp =~ s/^.*\/(.*)\.po$/$1/;
176    return $tmp;
177}
178
179
180sub create_translation_database
181{
182    foreach my $lang (@languages) {
183
184        my $po_file = $po_files_by_lang{$lang};
185
186        open PO_FILE, "<$po_file";     
187
188        while (<PO_FILE>) {
189            if (/^#,.*fuzzy/) {
190                $_ = <PO_FILE>; next;
191            }
192            if (/^msgid "(.*)"/ ) {
193                my $msgid = $1;
194                $_ = <PO_FILE>;
195               
196                if (/^msgstr "(.+)"/) {
197                    my $msgstr = $1;
198                    $translations{$lang . "|" . $msgid} = $msgstr;
199                    # print "[$lang]$msgstr\n";
200                }
201            }           
202        }
203    }
204}
205
206sub lookup_translations
207{
208    my ($value) = @_;
209 
210    my %transmap = ();
211
212    foreach my $lang (@languages) {
213        my $translation = lookup_translation ($value, $lang);
214           
215        if ($translation) {
216            $transmap{$lang} = $translation;
217        }
218    }
219
220    return %transmap;
221}
222
223
224sub lookup_translation
225{
226    my ($string, $lang) = @_;
227    $string =~ s/\+/\\+/g;
228 
229    my $salt = "$lang|$string";
230     
231    if ($translations{$salt}) {
232        return $translations{$salt};
233    }
234 
235    return "";
236}
237
238
239sub entity_encode_translations
240{
241    my %transmap = @_;
242
243    foreach my $key (keys %transmap) {
244        $transmap{$key} = entity_encode ($transmap{$key});
245    }
246
247    return %transmap;
248}
249
250
251sub entity_encode
252{
253    my ($pre_encoded) = @_;
254
255    my @list_of_chars = unpack ('C*', $pre_encoded);
256
257    return join ('', map (&entity_encode_int, @list_of_chars));
258}
259
260sub entity_encode_int
261{
262    # FIXME: should probably entity encode more stuff.
263    if ($_ > 127) {
264        return "&#" . $_ . ";";
265    } else {
266        return chr $_;
267    }
268}
269
270
271
272
273
274## OAF/XML-specific merge code
275 
276sub xml_merge_translations
277{
278    my $xml_source; {
279       local (*INPUT);
280       local $/; # slurp mode
281       open INPUT, "<$FILE" or die "can't open $FILE: $!";
282       $xml_source = <INPUT>;
283       close INPUT;
284    }
285
286    open OUTPUT, ">$OUTFILE";
287
288    while ($xml_source =~ /[ \t]*<[^<]*\s_\w+="[^"]*"[^<]*>/m) {
289        print OUTPUT $`;
290        my $orig_node = $&;
291        $xml_source = $';
292
293        my $non_translated_line = $orig_node;
294        $non_translated_line =~ s/_(\w+)="/$1="/;
295           
296        my $new_node = $non_translated_line;
297           
298        my $value_str = $orig_node;
299        $value_str =~ s/.*_\w+="([^"]*)".*/$1/s;
300
301        if ($value_str) {
302            my %value_translation_map = entity_encode_translations
303                (lookup_translations ($value_str));
304
305            foreach my $key (keys %value_translation_map) {
306                my $translation = $value_translation_map{$key};
307                   
308                my $translated_line = $orig_node;
309                $translated_line =~ s/name="([^"]*)"/name="$1-$key"/;
310                $translated_line =~ s/(\s*)_(\w+)="[^"]*"/$1$2="$translation"/;
311
312                $new_node .= "\n$translated_line";
313            }
314        }
315
316        $xml_source = $new_node . $xml_source;
317    }
318
319    print OUTPUT $xml_source;
320
321    close OUTPUT;
322}
323
324sub keys_merge_translations
325{       
326    open INPUT, "<${FILE}";
327
328    open OUTPUT, ">${OUTFILE}";
329
330    while (<INPUT>) {
331        chomp;
332        if (/^\s*_\w+=.*/)  {
333            my $orig_line = $_;
334   
335            my $non_translated_line = $orig_line;
336            $non_translated_line =~ s/_([^="]*)=/$1=/;
337           
338            print OUTPUT "${non_translated_line}\n";
339           
340            my $value_str = $orig_line;
341            $value_str =~ s/.*_\w+=(.*)/$1/;
342           
343            if ($value_str) {
344                my %value_translation_map = lookup_translations ($value_str);
345           
346                foreach my $key (sort keys %value_translation_map) {
347                    my $translation = $value_translation_map{$key};
348
349                    my $translated_line = $orig_line; 
350                    $translated_line =~ s/_([^="]*)=([^\n]*)/\[$key]$1=$translation/;
351                    print OUTPUT "$translated_line\n";
352                }
353            }
354        } else {
355            print OUTPUT "$_\n";
356        }
357    }
358                 
359    close OUTPUT;
360    close INPUT;
361}
362
363sub desktop_merge_translations
364{
365    open INPUT, "<${FILE}";
366
367    open OUTPUT, ">${OUTFILE}";
368
369    while (<INPUT>) {
370        chomp;
371        if (/^\s*_\w+=.*/)  {
372            my $orig_line = $_;
373
374            my $non_translated_line = $orig_line;
375            $non_translated_line =~ s/_([^="]*)=/$1=/;
376
377            print OUTPUT "${non_translated_line}\n";
378
379            my $value_str = $orig_line;
380            $value_str =~ s/.*_\w+=(.*)/$1/;
381
382            if ($value_str) {
383                my %value_translation_map = lookup_translations ($value_str);
384
385                foreach my $key (sort keys %value_translation_map) {
386                    my $translation = $value_translation_map{$key};
387
388                    my $translated_line = $orig_line;
389                    $translated_line =~ s/^_([^="]*)=([^\n]*)/$1\[$key]=$translation/;
390                    print OUTPUT "$translated_line\n";
391                }
392            }
393        } else {
394            print OUTPUT "$_\n";
395        }
396    }
397
398    close OUTPUT;
399    close INPUT;
400
401}
Note: See TracBrowser for help on using the repository browser.