From d74459f35a868f790c6d5358142b38a4ed7328ae Mon Sep 17 00:00:00 2001 From: tipaul Date: Fri, 5 Dec 2003 16:53:46 +0000 Subject: [PATCH] translator tool. see translator_doc.txt --- misc/translator/opac.fr | 239 +++++++++++++++ misc/translator/text-extract.pl | 23 ++ misc/translator/tmpl_process.pl | 458 +++++++++++++++++++++++++++++ misc/translator/translator_doc.txt | 54 ++++ 4 files changed, 774 insertions(+) create mode 100644 misc/translator/opac.fr create mode 100755 misc/translator/text-extract.pl create mode 100755 misc/translator/tmpl_process.pl create mode 100644 misc/translator/translator_doc.txt diff --git a/misc/translator/opac.fr b/misc/translator/opac.fr new file mode 100644 index 0000000000..74e44f744d --- /dev/null +++ b/misc/translator/opac.fr @@ -0,0 +1,239 @@ +1 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +2 +20 +2002 +2003 +2004 +2005 +2006 +21 +22 +23 +24 +25 +26 +27 +28 +29 +3 +30 +31 +4 +5 +6 +7 +8 +9 +Account for Compte de +Additional Author: Autres auteurs +Advanced Search, More Options Recherche avancée +AMOUNT COUT +An Error has Occurred Une erreur s'est produite +Any Tout +Apr Avril +Are any of our records incorrect? Have you moved recently, got a new phone number or e-mail address? Un changement à nous faire connaitre ? +ARE OUR RECORDS CORRECT? Est-ce correct +Aug Aout +Author Auteur +Author: Auteur +Available Disponible +BARCODE CODE BARRE +Barcode Code barre +bgcolor='#ffffcc' align=center> +bgcolor='#ffffcc'> +Biblio number: Notice biblio : +BIBLIO RECORD Notice bibliographique +Biblionumber: Numéro notice : +Cancelled: Annulé +Cannot be Reserved Non réservable +Cardnumber: N° de carte +Catalogue Search Recherche catalogue +Charges Charges +City Ville +Class Classe +Classification: +Collection: +Compact Disc +Copies Copies +Current Branch: Annexe +Current Loan Prêt +Date Due Date retour +Date: +Day Jour +Dec +Dewey: +Due date Date retour +Easy / Picture Books +Easy Reader Lecture facile +Email Mail +End reserve on this date: Annuler réservation à cette date +Exact +Feb Fev +Fiction +FINES & CHARGES Dettes +Firstname Prénom +GROUP - GROUPE +Group Number: Numéro groupe : +Hi Bonjour, +Home Accueil +Home Branch: Annexe propriétaire +Home phone Téléphone maison +Illus: +Illustrator Illustrateur +in dans +input{font-size:16px} +ISBN: +Item Count Nombre d'ouvrages +Item lost: Ouvrage perdu +Item Type Type d'ouvrage +Item Type: Type d'ouvrage : +items currently issued. Ouvrage en prêt actuellement +items currently reserved. Ouvrages réservés actuellement +Itemtype Type d'ouvrage +Jan Jan +Join Rejoindre +Jul Juill +Jun Juin +Junior Fiction +Junior Non-Fiction +Keywords Mot-clefs +KOHA +Koha Login Identifiant Koha +KOHA: Become a Member KOHA : s'abonner +KOHA: Catalogue Search Recherche catalogue +Koha: Horowhenua Library Trust Catalogue and Member Services Koha, catalogue et outils abonnés +KOHA: Members Area Zone abonnés +KOHA: OPAC Catalogue Search Recherche OPAC +Last borrowed: Dernier prêt +Last Borrower 1: Dernier emprunteur 1 +Last Borrower 2: Dernier emprunteur 2 +Last Seen Vu +Last seen: Vu : +Library Card: Carte lecteur +Loan Length: Durée prêt +Location Localisation +Log In S'identifier +Log In to Koha S'identifier +Log Out Déconnecter +Logged in as: Connecté en tant que : +Logged in as: Connecté en tant que: +Logged in as: [ +Logout Déconnecter +Mar Mars +May Mai +Members Home Accueil lecteur +Month Mois +Next Records Enregistrement suivant +No Non +No. of Items: N° ouvrage +Non-Fiction +Normal Normal +Not Reservable Non réservable +Note that if you enter a value in Keyword and a value somewhere else, only keyword will be used Notez que le mot clef est prioritaire +Note there will be a reserve charge of Il y aura des frais de réservation de +Notes: Notes +Nov +Oct +of de +OK Start Search +on issue bit En prêt ? +Online En ligne +OR : OU +OR one or more from : OU un ou plus de : +Pages: +Paid for: Payé pour : +Password: Mot de passe : +pick up at: Prendre à : +Place: +Please confirm that you wish to request an item of these types: Confirmez que vous souhaitez réserver un ouvrage : +Please select the branch from which you want to collect the item: Sélectionnez l'annexe ou vous prendrez l'ouvrage +Please select which item types are ok for you. The first of these item that matches one of these types that becomes available will be set kept for you. Sélectionnez les types d'ouvrages souhaités. Le premier disponible sera gardé pour vous. +Please, change what's needed. An email will be sent to the library. Changer le nécessaire +Previous Records Précédents +Published by : Publié par +Publisher: Editions +records. lignes +Reference Books +Renewals: Renouvellements +Rental Charge: Coût du prêt +Replacement Price: Coût de remplacement +Request Demande +Reserve date Date réservation +Reserve on this date: Réserver à cette date : +Reserve page for item: Réservation de l'ouvrage : +reserves already on this item. Réservations déjà faites sur cet ouvrage +reserves. Réservations +Results Résultats +Results through of records. +results found Réponses trouvées +Search IGNORE +search IGNORE +Search the Catalogue Chercher dans le catalogue +Sep Sep +Serial: Périodique +Size: Taille +Something new ? quelque chose à modifier ? +Sorry, KOHA doesnt think you have permission for this page INTERDIT ! +Sorry, KOHA doesnt think you have permission for this page. INTERDIT +Sorry, there were no results Désolé, aucun résultat ! +Sorry, you cannot make more than Impossible de faire plus de +Sorry, you cannot make more than reserves. Désolé, vous ne pouvez pas faire plus de réservations +Sorry, you cannot make reserves because you owe Vous ne pouvez réserver parce que vous devez +Sorry, you cannot make reserves because you owe . DESOLE +Sorry, your session has timed out, please login again. Déconnecté. Identifiez vous à nouveau. +STILL OWING EN ATTENTE +Street address Adresse postale +Subject Sujet +Subject: Sujet : +Subtitle: Sous-titre +Surname Nom +Teacher Reference Ref. prof. +text/html; charset=iso8859-1 +There are Il y a +through à +Title Titre +to Koha à Koha +Total Due Total dû +Total Number of Items: Nombre total d'exemplaires +Try another Essayez un autre +Type in the box and press the enter key. Saisissez et validez avec Entrée +Unititle: Titre unifié +Update Record Mettre à jour +URL: URL +View Accounts Voir compte +Volume: +Website Site web +WELCOME TO THE KOHA OPAC Bienvenue dans l'OPAC de Koha +WELCOME TO THE KOHA OPAC +Which is to be picked up from Qui sera retiré à +Work/Fax phone Tel bureau +Year Année +Year : Année : +Yes Oui +YesNo +You already have a reserve placed on this item. Vous avez déjà placé une réservation sur cet exemplaire +You are accessing koha from a different ip address! please login again. Vous avez changé d'adresse IP. Identifiez vous à nouveau +You did not specify any seach criteria Vous n'avez pas spécifié de critère +You entered an incorrect username or password, please try again. Identifiant ou mot de passe erroné. Essayez encore. +You have Vous avez +You have items currently issued. Vous avez exemplaires en prêt +You have items currently reserved. Vous avez exemplaires réservés +You have a credit of Vous avez un crédit de +You have no items on issue. Vous n'avez pas d'exemplaire en prêt +You have outstanding charges and fines of Vous avez des dettes de +You have reserved items waiting: Vouas avez des réservations en attente +You must select a branch for pickup! Sélectionnez une annexe ou retirer l'ouvrage +You must select at least on item type! Vous devez sélectionner au moins 1 type d'exemplaire +You searched on Recherche effectuée sur +Young Adult Fiction +Your changes won't appear until the library has validated them. Vos changement n'apparaitront que lorsque la bibliothèque les aura validé diff --git a/misc/translator/text-extract.pl b/misc/translator/text-extract.pl new file mode 100755 index 0000000000..a13caff459 --- /dev/null +++ b/misc/translator/text-extract.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl +use HTML::Tree; +use Getopt::Std; +getopt("f:"); + my $tree = HTML::TreeBuilder->new; # empty tree + + $tree->parse_file($opt_f); + sub give_id { + my $x = $_[0]; + foreach my $c ($x->content_list) { + next if (ref($c) && $c->tag() eq "~comment"); + print "$c\n" unless ref($c); + if (ref($c) && $c->attr('alt')) { + print $c->attr('alt')."\n"; + } + if (ref($c) && $c->tag() eq 'meta') { + print $c->attr('content')."\n "; + } + give_id($c) if ref $c; # ignore text nodes + } + }; + give_id($tree); + $tree = $tree->delete; diff --git a/misc/translator/tmpl_process.pl b/misc/translator/tmpl_process.pl new file mode 100755 index 0000000000..8ecc045fa7 --- /dev/null +++ b/misc/translator/tmpl_process.pl @@ -0,0 +1,458 @@ +#!/usr/bin/perl + +use strict; +use Getopt::Long; + +my (@in_files, $str_file, $split_char, $recursive, $type, $out_dir, $in_dir, @excludes, $filter); +my $help; +my $exclude_regex; + +$split_char = ' '; + +GetOptions( + 'input|i=s' => \@in_files, + 'outputdir|o=s' => \$out_dir, + 'str-file|s=s' => \$str_file, + 'recursive|r' => \$recursive, + 'filter=s' => \$filter, + 'type=s' => \$type, + 'exclude=s' => \@excludes, + 'sep=s' => \$split_char, + 'help' => \$help); + +help() if $help; + +# utiliser glob() pour tous les fichiers d'un repertoire + +my $action = shift or usage(); +my %strhash = (); + +# Checks for missing input and string list arguments + +if( !defined(@in_files) || !defined($str_file) ) +{ + usage("You must at least specify input and string list filenames."); +} + +# Type match defaults to *.tmpl if not specified +$type = "tmpl|inc" if !defined($type); + +$filter = "./text-extract.pl -f" if !defined($filter); +# Input is not a file nor a directory +if( !(-d $in_files[0]) && !(-f $in_files[0])) +{ + usage("Unknow input. Input must a file or a directory. (Symbolic links are not supported for the moment)."); +} +elsif( -d $in_files[0] ) +{ + # input is a directory, generates list of files to process + $in_dir = $in_files[0]; + $in_dir =~ s/\/$//; # strips the trailing / if any + + print "Generating list of files to process...\n"; + + @in_files = (); + @in_files = &listfiles(\@in_files, $in_dir, $type, $recursive); + + if(scalar(@in_files) == 0) + { + warn "Nothing to process in $in_dir matching *.$type."; + exit -1; + } +} + +# Generates the global exclude regular expression +$exclude_regex = "(".join("|", @excludes).")" if @excludes; + +if( $action eq "create" ) +{ + # updates the list. As the list is empty, every entry will be added + %strhash = &update_strhash(\%strhash, \@in_files, $exclude_regex, $filter); + # saves the list to the file + write_strhash(\%strhash, $str_file, "\t"); +} +elsif( $action eq "update" ) +{ + # restores the string list from file + %strhash = &restore_strhash(\%strhash, $str_file, $split_char); + # updates the list, adding new entries if any + %strhash = &update_strhash(\%strhash, \@in_files, $exclude_regex, $filter); + # saves the list to the file + write_strhash(\%strhash, $str_file, $split_char); +} +elsif( $action eq "install" ) +{ + if(!defined($out_dir)) + { + usage("You must specify an output directory when using the install method."); + } + + if( $in_dir eq $out_dir ) + { + warn "You must specify a different input and output directory.\n"; + exit -1; + } + + # restores the string list from file + %strhash = &restore_strhash(\%strhash, $str_file, $split_char); + # creates the new tmpl file using the new translation + &install_strhash(\%strhash, \@in_files, $in_dir, $out_dir); +} +else +{ + usage("Unknown action specified."); +} + +exit 0; + +########################################################## +# Creates the new template files in the output directory # +########################################################## + +sub install_strhash +{ + my($strhash, $in_files, $in_dir, $out_dir) = @_; + + my $fh_in; my $fh_out; # handles for input and output files + my $tmp_dir; # temporary directory name (used to create destination dir) + + $out_dir =~ s/\/$//; # chops the trailing / if any. + + # Processes every entry found. + foreach my $file (@{$in_files}) + { + if( !open($fh_in, "< $file") ) + { + warn "Can't open $file : $!\n"; + next; + } + + # generates the name of the output file + my $out_file = $file; + + if(!defined $in_dir) + { + # processing single files not an entire directory + $out_file = "$out_dir/$file"; + } + else + { + $out_file =~ s/^$in_dir/$out_dir/; + } + + my $slash = rindex($out_file, "\/"); + $tmp_dir = substr($out_file, 0, $slash); #gets the directory where the file will be saved + + # the file doesn't exist + if( !(-f $tmp_dir) && !(-l $tmp_dir) && !(-e $tmp_dir) ) + { + if(!mkdir($tmp_dir,0775)) # creates with rwxrwxr-x permissions + { + warn("Make directory $tmp_dir : $!"); + close($fh_in); + exit(1); + } + } + elsif((-f $tmp_dir) || (-l $tmp_dir)) + { + warn("Unable to create directory $tmp_dir.\n A file or symbolic link with the same name already exists."); + close($fh_in); + exit(1); + } + + # opens handle for output + if( !open($fh_out, "> $out_file") ) + { + warn "Can't write $out_file : $!\n"; + close($fh_in); + next; + } + + print "Generating $out_file...\n"; + + while(my $line = <$fh_in>) + { + foreach my $text (sort {length($b) <=> length($a)} keys %{$strhash}) + { + # Test if the key has been translated + if( %{$strhash}->{$text} != 1 ) + { + # Does the line contains text that needs to be changed ? + if( $line =~ /$text/ && %{$strhash}->{$text} ne "IGNORE") + { + # changing text + my $subst = %{$strhash}->{$text}; + $line =~ s/(\W)$text(\W)/$1$subst$2/g; + } + } + } + + # Writing the modified (or not) line to output + printf($fh_out "%s", $line); + } + + close($fh_in); + close($fh_out); + } +} + +######################################################## +# Updates the string list hash with the new components # +######################################################## + +sub update_strhash +{ + my($strhash, $in_files, $exclude, $filter)= @_; + + my $fh; + + # Processes every file entries + foreach my $in (@{$in_files}) + { + + print "Processing $in...\n"; + + # Creates a filehandle containing all the strings returned by + # the plain text program extractor + open($fh, "$filter $in |") or print "$filter $in : $!"; + next $in if !defined $fh; + + # Processes every string returned + while(my $str = <$fh>) + { + $str =~ s/[\n\r\f]+$//; # chomps the trailing \n (or if file was edited with Windows) + $str =~ s/^\s+//; # remove trailing blanks + $str =~ s/\s+$//; + + # the line begins with letter(s) followed by optional words and/or spaces + if($str =~ /^[ ]*[\w]+[ \w]*/) + { + # the line is to be excluded ? + if( !(defined($exclude) && ($str =~ /$exclude/o) && $str>0) ) + { + if( !defined(%{$strhash}->{$str}) ) + { + # the line is not already in the list so add it + %{$strhash}->{$str} = 1; + } + } + } + } + + close($fh); + } + + return %{$strhash}; +} + +##################################################### +# Reads the input file and returns a generated hash # +##################################################### + +sub restore_strhash +{ + my($strhash, $str_file, $split_char) = @_; + + my $fh; + + open($fh, "< $str_file") or die "$str_file : $!"; + + print "Restoring string list from $str_file...\n"; + + while( my $line = <$fh> ) + { + chomp $line; + + # extracts the two fields + my ($original, $translated) = split(/$split_char/, $line, 2); + + if($translated ne "") + { + # the key has been translated + %{$strhash}->{$original} = $translated; + } + else + { + # the key exist but has no translation. + %{$strhash}->{$original} = 1; + } + + } + + close($fh); + + return %{$strhash}; +} + +######################################### +# Writes the string hashtable to a file # +######################################### + +sub write_strhash +{ + my($strhash, $str_file, $split_char) = @_; + + my $fh; + + # Opens a handle for saving the list + open($fh, "> $str_file") or die "$str_file : $!"; + + print "Writing string list to $str_file...\n"; + + foreach my $str(sort {uc($a) cmp uc($b) || length($a) <=> length($b)} keys %{$strhash}) + { + if(%{$strhash}->{$str} != 1) + { + printf($fh "%s%s%s\n", $str, $split_char, %{$strhash}->{$str}); + } + else + { + printf($fh "%s%s\n", $str, $split_char); + } + } + + close($fh); +} + +######################################################## +# List the contents of dir matching the pattern *.type # +######################################################## + +sub listfiles +{ + my($in_files, $dir, $type, $recursive) = @_; + + my $dir_h; +# my @types = split(/ /,$type); + opendir($dir_h, $dir) or warn("Can't open $dir : $!\n"); + + my @tmp_list = grep(!/^\.\.?$/, readdir($dir_h)); + + closedir($dir_h); + + foreach my $tmp_file (@tmp_list) + { + + if( $recursive && (-d "$dir/$tmp_file") ) # entry is a directory + { + @{$in_files} = listfiles($in_files, "$dir/$tmp_file", $type); + } + elsif( $tmp_file =~ /\.$type$/ ) + { + push(@{$in_files}, "$dir/$tmp_file"); + } + } + return @{$in_files}; +} + +###################################### +# DEBUG ROUTINE # +# Prints the contents of a hashtable # +###################################### + +sub print_strhash +{ + my($strhash, $split_char) = @_; + + foreach my $str(sort keys %{$strhash}) + { + if(%{$strhash}->{$str} != 1) + { + printf("%s%s%s\n", $str, $split_char, %{$strhash}->{$str}); + } + else + { + printf("%s%s\n", $str, $split_char); + } + } +} + +######################################### +# Short help messsage printing function # +######################################### + +sub usage +{ + warn join(" ", @_)."\n" if @_; + warn < tag between 2 strings, text-extract sometimes merges both strings, and so can't replace them in the translated template. I've solved all those cases with a
or another HTML statement. + +- SHORT STATEMENTS + short statements (like "in") can be replaced stupidly (like in cgi-bin => gives cgi-bdans in french). the workaround has been to replace only complete words ( +line 185 of tmpl_process : +$line =~ s/(\W)$text(\W)/$1$subst$2/g; +) +Don't seem to have any side effect. + +- WORD exist in FILENAME +words that are in the templates and in a perl script name are replaced ! +For example : Search is replace by Recherche in french, thus,giving , which is wrong... +The only way I've found to solve this is to ignore any translation whose translation string is IGNORE +(search is the only cas i've found in french opac) + +- MISSING STRINGS +Maybe some strings that should be translated are missing. +You can add whatever you want in text-extract.pl. +For instance, it extracts : +- standard text +- text in alt="SOMETEXT" +- meta html encoding (8859-1) to enable non european translations. + +COPYRIGHT +====== +@ paul poulain (paul.poulain _@_ free.fr) & Jerome Vizcaino vizcainj _@_ esiee.fr -- 2.39.5