--- loncom/localize/lonlocal.pm 2003/09/17 01:45:14 1.4 +++ loncom/localize/lonlocal.pm 2003/10/04 20:49:40 1.19 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Localization routines # -# $Id: lonlocal.pm,v 1.4 2003/09/17 01:45:14 www Exp $ +# $Id: lonlocal.pm,v 1.19 2003/10/04 20:49:40 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -28,11 +28,143 @@ ###################################################################### ###################################################################### +=pod + +=head1 NAME + +Apache::lonlocal - provides localization services + +=head1 SYNOPSIS + +lonlocal provides localization services for LON-CAPA programmers based +on Locale::Maketext. See +C +for more information on Maketext. + +=head1 OVERVIEWX + +As of LON-CAPA 1.1, we've started to localize LON-CAPA using the +Locale::Maketext module. Internationalization is the bulk of the work +right now (pre-1.1); localizing can be done anytime, and involves +little or no programming. + +The internationalization process involves putting a wrapper around +on-screen user messages and menus and turning them into keys, +which the MaketextX library translates into the desired +language output using a look-up table ("lexicon").X + +As keys we are currently using the plain English messages, and +Maketext is configured to replace the message by its own key if no +translation is found. This makes it easy to phase in the +internationalization without disturbing the screen output. + +Internationalization is somewhat tedious and effectively impossible +for a non-fluent speaker to perform, but is fairly easy to create +translations, requiring no programming skill. As a result, this is one +area where you can really help LON-CAPA out, even if you aren't a +programmer, and we'd really appreciate it. + +=head1 How To Localize Handlers For Programmers + +Into the "use" section of a module, we need to insert + + use Apache::lonlocal; + +Note that there are B, we B to pollute our +namespace. + +Inside might be something like this + + sub message { + my $status=shift; + my $message='Status unknown'; + if ($status eq 'WON') { + $message='You have won.'; + } elsif ($status eq 'LOST') { + $message='You are a total looser.'; + } + return $message; + } + ... + $r->print('

Gamble your Homework Points

'); + ... + $r->print(<Rules: + No purchase necessary. Illegal where not allowed. + ENDMSG + +We have to now wrap the subroutine &mt()X ("maketext") around our +messages, but not around markup, etc. We also want minimal disturbance. +The first two examples are easy: + + sub message { + my $status=shift; + my $message='Status unknown'; + if ($status eq 'WON') { + $message='You have won.'; + } elsif ($status eq 'LOST') { + $message='You are a total looser.'; + } + return &mt($message); + } + ... + $r->print('

'.&mt('Gamble your Homework Points').'

'); + +The last one is a bummer, since you cannot call subroutines inside of +(< 'Rules', 'disclaimer' => + 'No purchase necessary. Illegal where not allowed.'); + $r->print(<$lt{'header'}: + $lt{'disclaimer'} + ENDMSG + +As a programmer, your job is done here. If everything worked, you +should see no changes on the screen. + +=head1 How To Localize LON-CAPA for Translators + +As a translator, you need to provide the lexicon for the keys, which in +this case is the plain text message. The lexicons sit in +loncom/localize/localize, with the language code as filename, for +example de.pm for the German translation. The file then simply looks +like this: + + 'You have won.' + => 'Sie haben gewonnen.', + + 'You are a total looser.' + => 'Sie sind der totale Verlierer.', + + 'Rules' + => 'Regeln', + + 'No purchase necessary. Illegal where not allowed.' + => 'Es ist erlaubt, einfach zu verlieren, und das ist Ihre Schuld.' + + +Comments may be added with the # symbol, which outside of a string +(the things with the apostrophe surrounding them, which are the +keys and translations) will cause the translation routines to +ignore the rest of the line. + +This is a relatively easy task, and any help is appreciated. + +Maketext can do a whole lot more, see +C +but for most purposes, we do not have to mess with that. + +=cut + package Apache::lonlocal; use strict; use Apache::localize; use Apache::File; +use locale; +use POSIX qw(locale_h); require Exporter; @@ -49,24 +181,62 @@ use vars qw($lh); sub mt (@) { unless ($ENV{'environment.translator'}) { - return $lh->maketext(@_); + if ($lh) { + return $lh->maketext(@_); + } else { + return @_; + } } else { - my $trans=$lh->maketext(@_); - my $link='[['.$trans.']]'; - if ($ENV{'transreroute'}) { - $reroute.=$link; - return $trans; + if ($lh) { + my $trans=$lh->maketext(@_); + my $link='[['.$trans.']]'; + if ($ENV{'transreroute'}) { + $reroute.=$link; + return $trans; + } else { + return $link; + } } else { - return $link; + return @_; } } } +# ============================================================== What language? + +sub current_language { + my $lang=$lh->maketext('language_code'); + return ($lang eq 'language_code'?'en':$lang); +} + +# ============================================================== What encoding? + +sub current_encoding { + if ($lh) { + my $enc=$lh->maketext('char_encoding'); + return ($enc eq 'char_encoding'?'':$enc); + } else { + return undef; + } +} + +# =============================================================== Which locale? +# Refer to locale -a +# +sub current_locale { + if ($lh) { + my $enc=$lh->maketext('lang_locale'); + return ($enc eq 'lang_locale'?'':$enc); + } else { + return undef; + } +} + # ============================================================== Translate hash sub texthash { @@ -76,13 +246,19 @@ sub texthash { } return %hash; } +# ======================================================== Re-route translation + +sub clearreroutetrans { + &reroutetrans(); + $reroute=''; +} # ======================================================== Re-route translation sub reroutetrans { $ENV{'transreroute'}=1; - $reroute=''; } + # ==================================================== End re-route translation sub endreroutetrans { $ENV{'transreroute'}=0; @@ -96,9 +272,65 @@ sub endreroutetrans { # ========= Get a handle (do not invoke in vain, leave this to access handlers) sub get_language_handle { + my $r=shift; $lh=Apache::localize->get_handle(&Apache::loncommon::preferred_languages); + if (&Apache::lonnet::mod_perl_version == 1) { + $r->content_languages([¤t_language()]); + } +### setlocale(LC_ALL,¤t_locale); +} + +# ========================================================== Localize localtime + +sub locallocaltime { + my $thistime=shift; + if ((¤t_language=~/^en/) || (!$lh)) { + return ''.localtime($thistime); + } else { + my $format=$lh->maketext('date_locale'); + if ($format eq 'date_locale') { + return ''.localtime($thistime); + } + my ($seconds,$minutes,$twentyfour,$day,$mon,$year,$wday,$yday,$isdst)= + localtime($thistime); + my $month=(split(/\,/,$lh->maketext('date_months')))[$mon]; + my $weekday=(split(/\,/,$lh->maketext('date_days')))[$wday]; + if ($seconds<10) { + $seconds='0'.$seconds; + } + if ($minutes<10) { + $minutes='0'.$minutes; + } + $year+=1900; + my $twelve=$twentyfour; + my $ampm; + if ($twelve>12) { + $twelve-=12; + $ampm=$lh->maketext('date_pm'); + } else { + $ampm=$lh->maketext('date_am'); + } + foreach + ('seconds','minutes','twentyfour','twelve','day','year', + 'month','weekday','ampm') { + $format=~s/\$$_/eval('$'.$_)/gse; + } + return $format; + } } +# ==================== Normalize string (reduce fragility in the lexicon files) + +# This normalizes a string to reduce fragility in the lexicon files of +# huge messages (such as are used by the helper), and allow useful +# formatting: reduce all consecutive whitespace to a single space, +# and remove all HTML +sub normalize_string { + my $s = shift; + $s =~ s/\s+/ /g; + $s =~ s/<[^>]+>//g; + return $s; +} 1; __END__ 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.