source: main/tags/2.40/gsdl/bin/script/inittranslation.pl@ 21085

Last change on this file since 21085 was 4182, checked in by mdewsnip, 21 years ago

(The previous log message) + "properly".

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 21.9 KB
Line 
1#!/usr/bin/perl -w
2
3###########################################################################
4#
5# inittranslation.pl
6#
7# A component of the Greenstone digital library software
8# from the New Zealand Digital Library Project at the
9# University of Waikato, New Zealand.
10#
11# Copyright (C) 1999 New Zealand Digital Library Project
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License as published by
15# the Free Software Foundation; either version 2 of the License, or
16# (at your option) any later version.
17#
18# This program is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21# GNU General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26#
27###########################################################################
28
29
30BEGIN {
31 die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
32 unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
33}
34
35
36use util;
37use GDBM_File;
38
39
40my %updatedata = ();
41
42
43sub main
44{
45 # Get the name of the source (base) language
46 my $sourcelang = shift(@_);
47 # Get the name of the target language
48 my $targetlang = shift(@_);
49 my $usecvs = shift(@_);
50
51 # Check that both arguments were supplied
52 if (!$sourcelang) {
53 die "Error: You didn't supply the name of the source language!\n";
54 }
55 if (!$targetlang) {
56 die "Error: You didn't supply the name of the target language!\n";
57 }
58
59 # Casefold both language names
60 $sourcelang =~ tr/A-Z/a-z/;
61 $targetlang =~ tr/A-Z/a-z/;
62
63 my $gsdldir = "$ENV{'GSDLHOME'}";
64 my $macrosdir = util::filename_cat($gsdldir, "macros");
65 my $langdir = util::filename_cat($gsdldir, "tmp", "lang");
66
67 # Make sure this is a new translation process
68 my $translationdir = util::filename_cat($langdir, "$sourcelang-$targetlang");
69 if (-e $translationdir) {
70 print STDERR "Note: Translation has already been initialised (exiting).\n";
71 return;
72 }
73
74 # If the source language is not English, it may not be up to date
75 if ($sourcelang !~ m/english/) {
76 print STDERR "Warning: Source language is not English. You should check that" .
77 " the source language is up to date before beginning.\n";
78 }
79
80 # Check that the source language macro files exist, and parse them
81 my $sourcedmname1 = &get_macrofile_name($sourcelang, "");
82 my $sourcehash1 = &parse_macrofile($macrosdir, $sourcedmname1);
83 my $sourcedmname2 = &get_macrofile_name($sourcelang, "2");
84 my $sourcehash2 = &parse_macrofile($macrosdir, $sourcedmname2);
85
86 # Make sure some macros exist to be translated
87 if (!$sourcehash1 && !$sourcehash2) {
88 die "Error: No source macro information exists.\n";
89 }
90
91 # Combine the two source hashes
92 my $sourcehash = &combine_hashes($sourcehash1, $sourcehash2);
93
94 # Create a directory to store the data for the new translation, make world-writeable
95 my $currentmask = umask;
96 umask(0000);
97 if (! mkdir($translationdir, 0777)) {
98 umask($currentmask);
99 die "Error: Couldn't create directory $translationdir.\n";
100 }
101
102 # Start a new database for the translation information
103 my $translationdb = util::filename_cat($translationdir, "translation.db");
104 my %translationdata = ();
105 tie(%translationdata, "GDBM_File", $translationdb, GDBM_WRCREAT, 0666);
106
107 # Work out what the target language code should be, and store it in the database
108 my $maincfgfile = util::filename_cat($gsdldir, "etc", "main.cfg");
109 my $languagecodes = &get_language_codes();
110 my $targetcode = &get_language_code($targetlang, $maincfgfile, $languagecodes);
111 $translationdata{"*target_lang_code*"} = $targetcode;
112
113 # Start a new update database
114 my $updatedb = util::filename_cat($translationdir, "update.db");
115 tie(%updatedata, "GDBM_File", $updatedb, GDBM_WRCREAT, 0666);
116 umask($currentmask);
117
118 # Create the target language macro files if they don't exist
119 my $targetdmname1 = &get_macrofile_name($targetlang, "");
120 my $targetdmfile1 = util::filename_cat($macrosdir, $targetdmname1);
121 if (! -e $targetdmfile1) {
122 my $sourcedmfile1 = util::filename_cat($macrosdir, $sourcedmname1);
123 &create_empty_macrofile($sourcedmfile1, $targetdmfile1);
124 }
125 my $targetdmname2 = &get_macrofile_name($targetlang, "2");
126 my $targetdmfile2 = util::filename_cat($macrosdir, $targetdmname2);
127 if (! -e $targetdmfile2) {
128 my $sourcedmfile2 = util::filename_cat($macrosdir, $sourcedmname2);
129 &create_empty_macrofile($sourcedmfile2, $targetdmfile2);
130 }
131
132 # Parse the target language macro files
133 my $targethash1 = &parse_macrofile($macrosdir, $targetdmname1);
134 my $targethash2 = &parse_macrofile($macrosdir, $targetdmname2);
135
136 # Combine the two target hashes
137 my $targethash = &combine_hashes($targethash1, $targethash2);
138
139 # Initialise the translation database with the current contents of the macrofiles
140 foreach $sourcekey (sort keys(%$sourcehash)) {
141 $translationdata{$sourcekey} = $sourcehash->{$sourcekey};
142 }
143 foreach $targetkey (sort keys(%$targethash)) {
144 $translationdata{$targetkey} = $targethash->{$targetkey};
145 }
146
147 # Use CVS to initialise the update database, if desired
148 if ($usecvs && $usecvs eq "true") {
149 &initialise_update_db($sourcelang, $targetlang, $targethash, $macrosdir);
150 }
151
152 # Clean up
153 untie %translationdata;
154 untie %updatedata;
155}
156
157
158sub get_macrofile_name
159{
160 my ($language, $suffix) = @_;
161
162 my $macrofilename = $language;
163
164 # Handles cases where the macro file name is different to the language name
165 $macrofilename = "port" if ($language =~ m/portuguese/);
166 $macrofilename = "indo" if ($language =~ m/indonesian/);
167
168 # Add suffix (if any) and file extension, and return
169 $macrofilename = $macrofilename . $suffix . ".dm";
170 return $macrofilename;
171}
172
173
174sub get_language_code
175{
176 my ($language, $maincfgfile, $languagecodes) = @_;
177
178 # Check if the language is in the main.cfg file
179 open(MAIN_CFG_IN, "<$maincfgfile") or die "Error: Could not open $maincfgfile.\n";
180 my $lastlangline;
181 while (<MAIN_CFG_IN>) {
182 $line = $_;
183 chomp($line);
184 # print "Line: $line\n";
185 if ($line =~ m/^Language\s+/i) {
186 my @args = split(/ +/,$line);
187 my ($lang_abbr) = ($args[1] =~ m/^shortname=(.*)$/);
188 $lang_abbr =~ tr/A-Z/a-z/;
189 my ($lang_long) = ($args[2] =~ m/^longname=(.*)$/);
190 $lang_long =~ tr/A-Z/a-z/;
191
192 # Is this the language we are translating into?
193 if ($lang_long eq $language) {
194 return $lang_abbr;
195 }
196
197 $lastlangline = $line;
198 }
199 }
200 close MAIN_CFG_IN;
201
202 # Try to find it using the ISO 639 language codes
203 my $langcode;
204 if ($languagecodes->{$language}) {
205 $langcode = $languagecodes->{$language};
206 }
207 # Otherwise we just have to make something up
208 else {
209 $langcode = &make_up_language_code($language, $languagecodes);
210 }
211
212 # Add the new language code into the main.cfg file, and make sure it is world writeable
213 my $currentmask = umask;
214 umask(0000);
215 if (! open(MAIN_CFG_OUT,">$maincfgfile.new")) {
216 umask($currentmask);
217 die "Error: Could not create $maincfgfile.new: $!\n";
218 }
219 umask($currentmask);
220
221 open MAIN_CFG_IN, "<$maincfgfile" or die "Error: Could not open $maincfgfile.\n";
222 my $inmacros = "false";
223 while (<MAIN_CFG_IN>) {
224 $line = $_;
225 chomp($line);
226 print MAIN_CFG_OUT $line;
227 if ($line =~ m/^macrofiles /) {
228 $inmacros = "true";
229 }
230 if ($inmacros eq "true" && $line !~ m/\\$/) {
231 print MAIN_CFG_OUT " \\\n";
232 print MAIN_CFG_OUT " $language" . ".dm $language" . "2.dm";
233 $inmacros = "false";
234 }
235 print MAIN_CFG_OUT "\n";
236
237 if ($line eq $lastlangline) {
238 # Change language into title case
239 my $langtitlecase = $language;
240 substr($langtitlecase, 0, 1) =~ tr/a-z/A-Z/;
241 print MAIN_CFG_OUT ("Language shortname=$langcode longname=$langtitlecase ",
242 "default_encoding=utf-8\n");
243 }
244 }
245 close MAIN_CFG_IN;
246 close MAIN_CFG_OUT;
247
248 # Delete the old main.cfg and replace it with the new one
249 unlink($maincfgfile);
250 rename("$maincfgfile.new", $maincfgfile);
251
252 return $langcode;
253}
254
255
256sub make_up_language_code
257{
258 my ($language, $languagecodes) = @_;
259
260 # !! TO FINISH !!
261 print STDERR "Making up language code...\n";
262 $langcode = $& if ($language =~ m/\w\w/);
263 $language =~ s/\A.//;
264
265 return $langcode;
266}
267
268
269sub create_empty_macrofile
270{
271 my ($sourcedmfile, $targetdmfile) = @_;
272
273 open(SOURCE_DM_FILE_IN, "<$sourcedmfile") or die "Error: Could not open file.\n";
274 open(TARGET_DM_FILE_OUT, ">$targetdmfile") or die "Error: Could not write file.\n";
275
276 # Reads in contents of macro file, line by line
277 while (<SOURCE_DM_FILE_IN>) {
278 # Check if a new package is being defined
279 if (s/^package //) {
280 $packagename = $_;
281 chomp($packagename);
282
283 # It is, so write an empty package section to the target macro file
284 print TARGET_DM_FILE_OUT "package $packagename\n";
285 print TARGET_DM_FILE_OUT "# text macros\n";
286 print TARGET_DM_FILE_OUT "# icons\n";
287 }
288 }
289
290 close SOURCE_DM_FILE_IN;
291 close TARGET_DM_FILE_OUT;
292}
293
294
295sub parse_macrofile
296{
297 my ($macrosdir, $macrofile) = @_;
298
299 # Opens macro file or returns
300 my $macropath = util::filename_cat($macrosdir, $macrofile);
301 open(IN, "<$macropath") or return;
302
303 # Initialises some local variables
304 my $currpackage;
305 my %macros = ();
306
307 # Reads in contents of macro file, line by line
308 while (<IN>) {
309 # Check if a new package is being defined
310 if (s/^package //) {
311 $currpackage = $_;
312 chomp($currpackage);
313 }
314
315 # Line contains a macro name
316 elsif (/^(_\w+_)/) {
317 # gets the name of the macro ($1 contains text matched by corresponding
318 # set of parentheses in the last matched pattern within the dynamic scope
319 # which here matches (_\w+_) )
320 my $macroname = $1;
321 my $macrotext;
322
323 # get the first line of the macro
324 $_ =~ s/^_\w+_ *//;
325 # while there is still text of the macro to go...
326 while ($_ !~ /.*\}/) {
327 # ... adds it to the macrotext variable
328 $macrotext .= $_;
329 $_ = <IN>;
330 }
331 $macrotext .= $_;
332
333 # The key consists of macro file, package name, and macro name
334 my $key = $macrofile . "::" . $currpackage . "::" . $macroname;
335 # Store the macro text in the database
336 $macros{$key} = $macrotext;
337 }
338
339 # Icon: line in format ## "sometext" ## macro ## macroname ##
340 elsif (/^\#\# .*/) {
341 my $macroname = $_;
342 my $macrotext;
343
344 #if the macro text contains a new line will run over two lines
345 unless ($macroname =~ m/^\#\# .*\#\#/) {
346 $macroname = $_;
347 chomp($macroname);
348 $_ = <IN>;
349 $macroname .= $_;
350 }
351
352 #split the image macro header on ##
353 my @names = split(/\s*\#\#\s*/, $macroname);
354 #save current contents of macroname into macrotext
355 $macrotext .= $macroname;
356 $_ = <IN>;
357 # overwrite macroname with macroname from ## ... ## ... ## HERE ###
358 $macroname = $names[(scalar @names) - 1];
359
360 # read in the rest of the text associated with the image macro
361 while ($_ !~ /^\s+/) {
362 $macrotext .= $_;
363 $_ = <IN>;
364 }
365
366 # key to the hash and the database
367 my $key = $macrofile . "::" . $currpackage . "::" . $macroname;
368 # print "Icon, key: $key\n text: $macrotext\n";
369 # hashes macroname and macrotext
370 $macros{$key} = $macrotext;
371 }
372 }
373 close IN;
374
375 return (\%macros);
376}
377
378
379# Combines two existing hashes of the same format together
380sub combine_hashes
381{
382 my ($hash1, $hash2) = @_;
383 my %combined = ();
384
385 foreach $key (sort (keys %$hash1)) {
386 $combined{$key} = $hash1->{$key};
387 }
388 foreach $key (sort (keys %$hash2)) {
389 $combined{$key} = $hash2->{$key};
390 }
391
392 return (\%combined);
393}
394
395
396sub initialise_update_db
397{
398 my ($sourcelang, $targetlang, $targethash, $macrosdir) = @_;
399
400 # Use CVS to annotate each line of the source files with the date it was last edited
401 my $sourcedmfile1 = &get_macrofile_name($sourcelang, "");
402 my $annotatedsourcefile1 = qx/cd $macrosdir; cvs annotate $sourcedmfile1/;
403 my $annotatedsourcehash1 = &parse_annotated_macrofile($annotatedsourcefile1);
404 my $sourcedmfile2 = &get_macrofile_name($sourcelang, "2");
405 my $annotatedsourcefile2 = qx/cd $macrosdir; cvs annotate $sourcedmfile2/;
406 my $annotatedsourcehash2 = &parse_annotated_macrofile($annotatedsourcefile2);
407
408 # Use CVS to annotate each line of the target files with the date it was last edited
409 my $targetdmfile1 = &get_macrofile_name($targetlang, "");
410 my $annotatedtargetfile1 = qx/cd $macrosdir; cvs annotate $targetdmfile1/;
411 my $annotatedtargethash1 = &parse_annotated_macrofile($annotatedtargetfile1);
412 my $targetdmfile2 = &get_macrofile_name($targetlang, "2");
413 my $annotatedtargetfile2 = qx/cd $macrosdir; cvs annotate $targetdmfile2/;
414 my $annotatedtargethash2 = &parse_annotated_macrofile($annotatedtargetfile2);
415
416 # Macros needing updating are those in the target file that have been more recently
417 # edited in the source file
418 foreach $targetkey (sort (keys(%$annotatedtargethash1))) {
419 my $targetdate = $annotatedtargethash1->{$targetkey};
420 my $sourcedate = $annotatedsourcehash1->{$targetkey};
421 if (&is_date_before($targetdate, $sourcedate) eq "true") {
422 # print "Macro needs updating!!\n";
423 $targetkey = &get_macrofile_name($targetlang, "") . "::" . $targetkey;
424 # print "Target key: $targetkey";
425 # print " Original target text: $targethash->{$targetkey}\n";
426 $updatedata{$targetkey} = $targethash->{$targetkey};
427 }
428 }
429
430 foreach $targetkey (sort (keys(%$annotatedtargethash2))) {
431 my $targetdate = $annotatedtargethash2->{$targetkey};
432 my $sourcedate = $annotatedsourcehash2->{$targetkey};
433 if (&is_date_before($targetdate, $sourcedate) eq "true") {
434 # print "Macro needs updating!!\n";
435 $targetkey = &get_macrofile_name($targetlang, "2") . "::" . $targetkey;
436 # print "Target key: $targetkey";
437 # print " Original target text: $targethash->{$targetkey}\n";
438 $updatedata{$targetkey} = $targethash->{$targetkey};
439 }
440 }
441}
442
443
444sub parse_annotated_macrofile
445{
446 my ($annotatedfile) = @_;
447
448 # Initialises some local variables
449 my $currpackage;
450 my %macros = ();
451
452 my @annotations = split(/\n/, $annotatedfile);
453 for ($i = 0; $i < scalar(@annotations); $i++) {
454 $annotatedline = $annotations[$i];
455 chomp($annotatedline);
456 # print "Line: $annotatedline\n";
457 ($line = $annotatedline) =~ s/.*\(.*\):\s//;
458
459 # Check if a new package is being defined
460 if ($line =~ m/^package (.*)/) {
461 $currpackage = $1;
462 chomp($currpackage);
463 }
464
465 # Line contains a macro name
466 elsif ($line =~ m/^(_\w+_)/) {
467 # Gets the name of the macro ($1 contains text matched by corresponding set
468 # of parentheses in the last matched pattern within the dynamic scope)
469 my $macroname = $1;
470 my $macrodate = &extract_cvs_date($annotatedline);
471
472 # while there is still text of the macro to go...
473 while ($line !~ /.*\}/) {
474 $annotatedline = $annotations[++$i];
475 chomp($annotatedline);
476 my $linedate = &extract_cvs_date($annotatedline);
477 if (&is_date_before($macrodate, $linedate) eq "true") {
478 # This part of the macro has been updated more recently
479 $macrodate = $linedate;
480 }
481 ($line = $annotatedline) =~ s/.*\(.*\):\s//;
482 }
483
484 # The key consists of package name and macro name
485 my $key = $currpackage . "::" . $macroname;
486 # The key maps to the macrodate
487 $macros{$key} = $macrodate;
488 # print "Macro: $key Date: $macrodate\n\n";
489 }
490
491 # Icon: line in format ## "sometext" ## macro ## macroname ##
492 elsif ($line =~ m/^\#\# (.*)/) {
493 my $macroname = $1;
494 my $macrodate = &extract_cvs_date($annotatedline);
495
496 #if the macro text contains a new line will run over two lines
497 unless ($line =~ m/^\#\# .*\#\#/) {
498 $annotatedline = $annotations[++$i];
499 chomp($annotatedline);
500 ($line = $annotatedline) =~ s/.*\(.*\):\s//;
501 $macroname .= $line;
502 }
503
504 # Split the image macro header on ##
505 my @names = split(/\s*\#\#\s*/, $macroname);
506 # Overwrite macroname with macroname from ## ... ## ... ## HERE ###
507 $macroname = $names[(scalar @names) - 1];
508
509 # Read the rest of the text associated with the image macro
510 while ($line !~ /^\s*$/) {
511 $annotatedline = $annotations[++$i];
512 chomp($annotatedline);
513 my $linedate = &extract_cvs_date($annotatedline);
514 if (&is_date_before($macrodate, $linedate) eq "true") {
515 # This part of the macro has been updated more recently
516 $macrodate = $linedate;
517 }
518 ($line = $annotatedline) =~ s/.*\(.*\):\s//;
519 }
520
521 # The key consists of package name and macro name
522 my $key = $currpackage . "::" . $macroname;
523 # The key maps to the macrodate
524 $macros{$key} = $macrodate;
525 # print "Macro: $key Date: $macrodate\n\n";
526 }
527 }
528
529 return (\%macros);
530}
531
532
533sub extract_cvs_date
534{
535 my ($line) = @_;
536
537 # Cut the CVS annotation off the front and extract the date
538 $line =~ s/.*\(.*\):\s//;
539 $annotation = $&;
540 ($macrodate = $annotation) =~ s/.*\(.*(\s)+(.*)\): /$2/;
541 return $macrodate;
542}
543
544
545# Returns true if $date1 is before $date2, false otherwise
546sub is_date_before
547{
548 my ($date1, $date2) = @_;
549 my %months = ("Jan", 1, "Feb", 2, "Mar", 3, "Apr", 4, "May", 5, "Jun", 6,
550 "Jul", 7, "Aug", 8, "Sep", 9, "Oct", 10, "Nov", 11, "Dec", 12);
551
552 @date1parts = split(/-/,$date1);
553 @date2parts = split(/-/,$date2);
554
555 # Compare year - nasty because we have rolled over into a new century
556 $year1 = $date1parts[2];
557 if ($year1 < 80) {
558 $year1 += 100;
559 }
560 $year2 = $date2parts[2];
561 if ($year2 < 80) {
562 $year2 += 100;
563 }
564
565 # Compare year
566 if ($year1 < $year2) {
567 return "true";
568 }
569 elsif ($year1 == $year2) {
570 # Year is the same, so compare month
571 if ($months{$date1parts[1]} < $months{$date2parts[1]}) {
572 return "true";
573 }
574 elsif ($months{$date1parts[1]} == $months{$date2parts[1]}) {
575 # Month is the same, so compare day
576 if ($date1parts[0] < $date2parts[0]) {
577 return "true";
578 }
579 }
580 }
581
582 return "false";
583}
584
585
586sub display_hash
587{
588 my ($hash) = @_;
589
590 foreach $key (sort (keys %$hash)) {
591 print $key . "\n";
592 print $hash->{$key} . "\n";
593 }
594}
595
596
597&main(@ARGV);
598
599
600sub get_language_codes
601{
602 %languagecodes = (
603 'abkhazian', 'ab',
604 'afar', 'aa',
605 'afrikaans', 'af',
606 'albanian', 'sq',
607 'amharic', 'am',
608 'arabic', 'ar',
609 'armenian', 'hy',
610 'assamese', 'as',
611 'aymara', 'ay',
612 'azerbaijani', 'az',
613 'bashkir', 'ba',
614 'basque', 'eu',
615 'bengali', 'bn',
616 'bangla', 'bn',
617 'bhutani', 'dz',
618 'bihari', 'bh',
619 'bislama', 'bi',
620 'breton', 'br',
621 'bulgarian', 'bg',
622 'burmese', 'my',
623 'byelorussian', 'be',
624 'belarusian', 'be',
625 'cambodian', 'km',
626 'catalan', 'ca',
627 'chinese', 'zh',
628 'corsican', 'co',
629 'croatian', 'hr',
630 'czech', 'cs',
631 'danish', 'da',
632 'dutch', 'nl',
633 'english', 'en',
634 'esperanto', 'eo',
635 'estonian', 'et',
636 'faeroese', 'fo',
637 'farsi', 'fa',
638 'fiji', 'fj',
639 'finnish', 'fi',
640 'french', 'fr',
641 'frisian', 'fy',
642 'galician', 'gl',
643 'gaelic (scottish)', 'gd',
644 'gaelic (manx)', 'gv',
645 'georgian', 'ka',
646 'german', 'de',
647 'greek', 'el',
648 'greenlandic', 'kl',
649 'guarani', 'gn',
650 'gujarati', 'gu',
651 'hausa', 'ha',
652 'hebrew', 'iw',
653 'hindi', 'hi',
654 'hungarian', 'hu',
655 'icelandic', 'is',
656 'indonesian', 'id', # Should be 'in' for backward compatibility
657 'interlingua', 'ia',
658 'interlingue', 'ie',
659 'inuktitut', 'iu',
660 'inupiak', 'ik',
661 'irish', 'ga',
662 'italian', 'it',
663 'japanese', 'ja',
664 'javanese', 'jv',
665 'kannada', 'kn',
666 'kashmiri', 'ks',
667 'kazakh', 'kk',
668 'kinyarwanda', 'rw',
669 'ruanda', 'rw',
670 'kirghiz', 'ky',
671 'kirundi', 'rn',
672 'rundi', 'rn',
673 'korean', 'ko',
674 'kurdish', 'ku',
675 'laothian', 'lo',
676 'latin', 'la',
677 'latvian', 'lv',
678 'lettish', 'lv',
679 'limburgish', 'li',
680 'limburger', 'li',
681 'lingala', 'ln',
682 'lithuanian', 'lt',
683 'macedonian', 'mk',
684 'malagasy', 'mg',
685 'malay', 'ms',
686 'malayalam', 'ml',
687 'maltese', 'mt',
688 'maori', 'mi',
689 'marathi', 'mr',
690 'moldavian', 'mo',
691 'mongolian', 'mn',
692 'nauru', 'na',
693 'nepali', 'ne',
694 'norwegian', 'no',
695 'occitan', 'oc',
696 'oriya', 'or',
697 'oromo', 'om',
698 'afan', 'om',
699 'galla', 'om',
700 'pashto', 'ps',
701 'pushto', 'ps',
702 'polish', 'pl',
703 'portuguese', 'pt',
704 'punjabi', 'pa',
705 'quechua', 'qu',
706 'rhaeto-romance', 'rm',
707 'romanian', 'ro',
708 'russian', 'ru',
709 'samoan', 'sm',
710 'sangro', 'sg',
711 'sanskrit', 'sa',
712 'serbian', 'sr',
713 'serbo-croatian', 'sh',
714 'sesotho', 'st',
715 'setswana', 'tn',
716 'shona', 'sn',
717 'sindhi', 'sd',
718 'sinhalese', 'si',
719 'siswati', 'ss',
720 'slovak', 'sk',
721 'slovenian', 'sl',
722 'somali', 'so',
723 'spanish', 'es',
724 'sundanese', 'su',
725 'swahili', 'sw',
726 'kiswahili', 'sw',
727 'swedish', 'sv',
728 'tagalog', 'tl',
729 'tajik', 'tg',
730 'tamil', 'ta',
731 'tatar', 'tt',
732 'telugu', 'te',
733 'thai', 'th',
734 'tibetan', 'bo',
735 'tigrinya', 'ti',
736 'tonga', 'to',
737 'tsonga', 'ts',
738 'turkish', 'tr',
739 'turkmen', 'tk',
740 'twi', 'tw',
741 'uighur', 'ug',
742 'ukrainian', 'uk',
743 'urdu', 'ur',
744 'uzbek', 'uz',
745 'vietnamese', 'vi',
746 'volapÃŒk', 'vo',
747 'welsh', 'cy',
748 'wolof', 'wo',
749 'xhosa', 'xh',
750 'yiddish', 'ji',
751 'yoruba', 'yo',
752 'zulu', 'zu'
753 );
754
755 return (\%languagecodes);
756}
Note: See TracBrowser for help on using the repository browser.