diff options
Diffstat (limited to 'xml-i18n-merge.in')
-rw-r--r-- | xml-i18n-merge.in | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/xml-i18n-merge.in b/xml-i18n-merge.in new file mode 100644 index 0000000..f492f4d --- /dev/null +++ b/xml-i18n-merge.in @@ -0,0 +1,401 @@ +#!@XML_I18N_TOOLS_PERL@ -w + +# +# The XML Translation Merge Tool +# +# Copyright (C) 2000 Free Software Foundation. +# Copyright (C) 2000, 2001 Eazel, Inc +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This script is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this library; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Authors: Maciej Stachowiak <mjs@eazel.com> +# Kenneth Christiansen <kenneth@gnu.org> +# Darin Adler <darin@eazel.com> +# + + +## Release information +my $PROGRAM = "xml-i18n-merge"; +my $PACKAGE = "xml-i18n-tools"; +my $VERSION = "0.8.2"; + +## Script options - Enable by setting value to 1 +my $ENABLE_XML = "1"; + +## Loaded modules +use strict; +use File::Basename; +use Getopt::Long; + +## Scalars used by the option stuff +my $HELP_ARG = "0"; +my $VERSION_ARG = "0"; +my $XML_STYLE_ARG = "0"; +my $KEYS_STYLE_ARG = "0"; +my $DESKTOP_STYLE_ARG = "0"; +my $QUIET_ARG = "0"; + + +## Handle options +GetOptions ( + "help|h|?" => \$HELP_ARG, + "version|v" => \$VERSION_ARG, + "quiet|q" => \$QUIET_ARG, + "xml-style|o" => \$XML_STYLE_ARG, + "keys-style|k" => \$KEYS_STYLE_ARG, + "desktop-style|d" => \$DESKTOP_STYLE_ARG + ) or &error; + + +my $PO_DIR; +my $FILE; +my $OUTFILE; + +my @languages; +my %po_files_by_lang = (); +my %translations = (); + +&split_on_argument; + + +## Check for options. +## This section will check for the different options. + +sub split_on_argument { + + if ($VERSION_ARG) { + &version; + + } elsif ($HELP_ARG) { + &help; + } elsif ($XML_STYLE_ARG && @ARGV > 2) { + &place_normal; + &message; + &preparation; + &xml_merge_translations; + } elsif ($KEYS_STYLE_ARG && @ARGV > 2) { + &place_normal; + &message; + &preparation; + &keys_merge_translations; + } elsif ($DESKTOP_STYLE_ARG && @ARGV > 2) { + &place_normal; + &message; + &preparation; + &desktop_merge_translations; + } else { + &help; + } +} + + +sub place_normal { + $PO_DIR = $ARGV[0]; + $FILE = $ARGV[1]; + $OUTFILE = $ARGV[2]; +} + + +## Sub for printing release information +sub version{ + print "${PROGRAM} (${PACKAGE}) ${VERSION}\n"; + print "Written by Maciej Stachowiak and Kenneth Christiansen, 2000.\n\n"; + print "Copyright (C) 2000 Free Software Foundation, Inc.\n"; + print "Copyright (C) 2000, 2001 Eazel, Inc.\n"; + print "This is free software; see the source for copying conditions. There is NO\n"; + print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"; + exit; +} + +## Sub for printing usage information +sub help{ + print "Usage: ${PROGRAM} [OPTIONS] PO_DIRECTORY FILENAME OUTPUT_FILE\n"; + print "Generates an xml file that includes translated versions of some attributes,\n"; + print "from an untranslated source and a po directory that includes translations.\n"; + print " -v, --version shows the version\n"; + print " -h, --help shows this help page\n"; + print " -q, --quiet quiet mode\n"; + print " -o, --xml-style includes translations in the xml style\n"; + print " -k, --keys-style includes translations in the keys style\n"; + print " -d, --desktop-style includes translations in the desktop style\n"; + print "\nReport bugs to <mjs\@eazel.com>.\n"; + exit; +} + + +## Sub for printing error messages +sub error{ +# print "xml-i18n-merge: invalid option @ARGV\n"; + print "Try `${PROGRAM} --help' for more information.\n"; + exit; +} + + +sub message { + print "Merging translations into $OUTFILE.\n" unless $QUIET_ARG; +} + + + +sub preparation { + &gather_po_files; + &create_translation_database; +} + + + +# General-purpose code for looking up translations in .po files + +sub gather_po_files +{ + my @po_files = glob("${PO_DIR}/*.po"); + + @languages = map (&po_file2lang, @po_files); + + foreach my $lang (@languages) { + $po_files_by_lang{$lang} = shift (@po_files); + } +} + +sub po_file2lang +{ + my $tmp = $_; + $tmp =~ s/^.*\/(.*)\.po$/$1/; + return $tmp; +} + + +sub create_translation_database +{ + foreach my $lang (@languages) { + + my $po_file = $po_files_by_lang{$lang}; + + open PO_FILE, "<$po_file"; + + while (<PO_FILE>) { + if (/^#,.*fuzzy/) { + $_ = <PO_FILE>; next; + } + if (/^msgid "(.*)"/ ) { + my $msgid = $1; + $_ = <PO_FILE>; + + if (/^msgstr "(.+)"/) { + my $msgstr = $1; + $translations{$lang . "|" . $msgid} = $msgstr; + # print "[$lang]$msgstr\n"; + } + } + } + } +} + +sub lookup_translations +{ + my ($value) = @_; + + my %transmap = (); + + foreach my $lang (@languages) { + my $translation = lookup_translation ($value, $lang); + + if ($translation) { + $transmap{$lang} = $translation; + } + } + + return %transmap; +} + + +sub lookup_translation +{ + my ($string, $lang) = @_; + $string =~ s/\+/\\+/g; + + my $salt = "$lang|$string"; + + if ($translations{$salt}) { + return $translations{$salt}; + } + + return ""; +} + + +sub entity_encode_translations +{ + my %transmap = @_; + + foreach my $key (keys %transmap) { + $transmap{$key} = entity_encode ($transmap{$key}); + } + + return %transmap; +} + + +sub entity_encode +{ + my ($pre_encoded) = @_; + + $pre_encoded =~ s/\\(.)/$1/g; + my @list_of_chars = unpack ('C*', $pre_encoded); + + return join ('', map (&entity_encode_int, @list_of_chars)); +} + +sub entity_encode_int +{ + if ($_ > 127 || $_ == 34 || $_ == 38) { + return "&#" . $_ . ";"; + } else { + return chr $_; + } +} + + + + + +## OAF/XML-specific merge code + +sub xml_merge_translations +{ + my $xml_source; { + local (*INPUT); + local $/; # slurp mode + open INPUT, "<$FILE" or die "can't open $FILE: $!"; + $xml_source = <INPUT>; + close INPUT; + } + + open OUTPUT, ">$OUTFILE"; + + while ($xml_source =~ /[ \t]*<[^<]*\s_\w+="[^"]*"[^<]*>/m) { + print OUTPUT $`; + my $orig_node = $&; + $xml_source = $'; + + my $non_translated_line = $orig_node; + $non_translated_line =~ s/_(\w+)="/$1="/; + + my $new_node = $non_translated_line; + + my $value_str = $orig_node; + $value_str =~ s/.*_\w+="([^"]*)".*/$1/s; + + if ($value_str) { + my %value_translation_map = entity_encode_translations + (lookup_translations ($value_str)); + + foreach my $key (keys %value_translation_map) { + my $translation = $value_translation_map{$key}; + + my $translated_line = $orig_node; + $translated_line =~ s/name="([^"]*)"/name="$1-$key"/; + $translated_line =~ s/(\s*)_(\w+)="[^"]*"/$1$2="$translation"/; + + $new_node .= "\n$translated_line"; + } + } + + $xml_source = $new_node . $xml_source; + } + + print OUTPUT $xml_source; + + close OUTPUT; +} + +sub keys_merge_translations +{ + open INPUT, "<${FILE}"; + + open OUTPUT, ">${OUTFILE}"; + + while (<INPUT>) { + chomp; + if (/^\s*_\w+=.*/) { + my $orig_line = $_; + + my $non_translated_line = $orig_line; + $non_translated_line =~ s/_([^="]*)=/$1=/; + + print OUTPUT "${non_translated_line}\n"; + + my $value_str = $orig_line; + $value_str =~ s/.*_\w+=(.*)/$1/; + + if ($value_str) { + my %value_translation_map = lookup_translations ($value_str); + + foreach my $key (sort keys %value_translation_map) { + my $translation = $value_translation_map{$key}; + + my $translated_line = $orig_line; + $translated_line =~ s/_([^="]*)=([^\n]*)/\[$key]$1=$translation/; + print OUTPUT "$translated_line\n"; + } + } + } else { + print OUTPUT "$_\n"; + } + } + + close OUTPUT; + close INPUT; +} + +sub desktop_merge_translations +{ + open INPUT, "<${FILE}"; + + open OUTPUT, ">${OUTFILE}"; + + while (<INPUT>) { + chomp; + if (/^\s*_\w+=.*/) { + my $orig_line = $_; + + my $non_translated_line = $orig_line; + $non_translated_line =~ s/_([^="]*)=/$1=/; + + print OUTPUT "${non_translated_line}\n"; + + my $value_str = $orig_line; + $value_str =~ s/.*_\w+=(.*)/$1/; + + if ($value_str) { + my %value_translation_map = lookup_translations ($value_str); + + foreach my $key (sort keys %value_translation_map) { + my $translation = $value_translation_map{$key}; + + my $translated_line = $orig_line; + $translated_line =~ s/^_([^="]*)=([^\n]*)/$1\[$key]=$translation/; + print OUTPUT "$translated_line\n"; + } + } + } else { + print OUTPUT "$_\n"; + } + } + + close OUTPUT; + close INPUT; + +} |