Annotation of loncom/localize/lonlocal.pm, revision 1.60.4.3

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Localization routines
                      3: #
1.60.4.3! raeburn     4: # $Id: lonlocal.pm,v 1.60.4.2 2010/12/06 00:35:19 raeburn Exp $
1.1       www         5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
                     28: ######################################################################
                     29: ######################################################################
1.10      bowersj2   30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: Apache::lonlocal - provides localization services
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
                     39: lonlocal provides localization services for LON-CAPA programmers based
                     40: on Locale::Maketext. See
                     41: C<http://search.cpan.org/dist/Locale-Maketext/lib/Locale/Maketext.pod>
                     42: for more information on Maketext.
                     43: 
                     44: =head1 OVERVIEWX<internationalization>
                     45: 
                     46: As of LON-CAPA 1.1, we've started to localize LON-CAPA using the
                     47: Locale::Maketext module. Internationalization is the bulk of the work
                     48: right now (pre-1.1); localizing can be done anytime, and involves 
                     49: little or no programming.
                     50: 
                     51: The internationalization process involves putting a wrapper around
                     52: on-screen user messages and menus and turning them into keys,
                     53: which the MaketextX<Maketext> library translates into the desired
                     54: language output using a look-up table ("lexicon").X<lexicon>
                     55: 
                     56: As keys we are currently using the plain English messages, and
                     57: Maketext is configured to replace the message by its own key if no
                     58: translation is found. This makes it easy to phase in the
                     59: internationalization without disturbing the screen output.
                     60: 
                     61: Internationalization is somewhat tedious and effectively impossible
                     62: for a non-fluent speaker to perform, but is fairly easy to create
                     63: translations, requiring no programming skill. As a result, this is one
                     64: area where you can really help LON-CAPA out, even if you aren't a
                     65: programmer, and we'd really appreciate it.
                     66: 
                     67: =head1 How To Localize Handlers For Programmers
                     68: 
                     69: Into the "use" section of a module, we need to insert
                     70: 
                     71:  use Apache::lonlocal;
                     72: 
                     73: Note that there are B<no parentheses>, we B<want> to pollute our
                     74: namespace. 
                     75: 
                     76: Inside might be something like this
                     77: 
                     78:  sub message {
                     79:      my $status=shift;
                     80:      my $message='Status unknown';
                     81:      if ($status eq 'WON') {
                     82:         $message='You have won.';
                     83:      } elsif ($status eq 'LOST') {
                     84:         $message='You are a total looser.';
                     85:      }
                     86:      return $message;
                     87:  }
                     88:  ...
                     89:  $r->print('<h3>Gamble your Homework Points</h3>');
                     90:  ...
                     91:  $r->print(<<ENDMSG);
                     92:  <font size="1">Rules:</font>
                     93:  <font size="0">No purchase necessary. Illegal where not allowed.</font>
                     94:  ENDMSG
                     95: 
                     96: We have to now wrap the subroutine &mt()X<mt> ("maketext") around our 
                     97: messages, but not around markup, etc. We also want minimal disturbance. 
                     98: The first two examples are easy:
                     99: 
                    100:  sub message {
                    101:      my $status=shift;
                    102:      my $message='Status unknown';
                    103:      if ($status eq 'WON') {
                    104:         $message='You have won.';
                    105:      } elsif ($status eq 'LOST') {
                    106:         $message='You are a total looser.';
                    107:      }
                    108:      return &mt($message);
                    109:  }
                    110:  ...
                    111:  $r->print('<h3>'.&mt('Gamble your Homework Points').'</h3>');
                    112: 
                    113: The last one is a bummer, since you cannot call subroutines inside of 
                    114: (<<MARKER). I have written a little subroutine to generate a translated 
                    115: hash for that purpose:
                    116: 
                    117:  my %lt=&Apache::lonlocal::texthash('header' => 'Rules', 'disclaimer' => 
                    118:  'No purchase necessary. Illegal where not allowed.');
                    119:  $r->print(<<ENDMSG);
                    120:  <font size="1">$lt{'header'}:</font>
                    121:  <font size="0">$lt{'disclaimer'}</font>
                    122:  ENDMSG
                    123: 
                    124: As a programmer, your job is done here. If everything worked, you 
                    125: should see no changes on the screen.
                    126: 
                    127: =head1 How To Localize LON-CAPA for Translators
                    128: 
                    129: As a translator, you need to provide the lexicon for the keys, which in 
                    130: this case is the plain text message. The lexicons sit in 
                    131: loncom/localize/localize, with the language code as filename, for 
                    132: example de.pm for the German translation. The file then simply looks 
                    133: like this:
                    134: 
                    135:     'You have won.'
                    136:  => 'Sie haben gewonnen.',
                    137: 
                    138:     'You are a total looser.'
                    139:  => 'Sie sind der totale Verlierer.',
                    140: 
                    141:     'Rules'
                    142:  => 'Regeln',
                    143: 
                    144:     'No purchase necessary. Illegal where not allowed.'
                    145:  => 'Es ist erlaubt, einfach zu verlieren, und das ist Ihre Schuld.'
                    146: 
                    147: 
                    148: Comments may be added with the # symbol, which outside of a string
                    149: (the things with the apostrophe surrounding them, which are the 
                    150: keys and translations) will cause the translation routines to
                    151: ignore the rest of the line.
                    152: 
                    153: This is a relatively easy task, and any help is appreciated.
                    154: 
                    155: Maketext can do a whole lot more, see
                    156: C<http://search.cpan.org/dist/Locale-Maketext/lib/Locale/Maketext.pod>
                    157: but for most purposes, we do not have to mess with that.
                    158: 
                    159: =cut
1.1       www       160: 
                    161: package Apache::lonlocal;
                    162: 
                    163: use strict;
                    164: use Apache::localize;
1.14      www       165: use locale;
1.39      albertel  166: use POSIX qw(locale_h strftime);
1.42      albertel  167: use DateTime();
1.46      raeburn   168: use DateTime::TimeZone;
1.49      raeburn   169: use DateTime::Locale;
1.1       www       170: 
                    171: require Exporter;
                    172: 
                    173: our @ISA = qw (Exporter);
1.48      raeburn   174: our @EXPORT = qw(mt mtn ns mt_user);
1.1       www       175: 
1.57      www       176: my %mtcache=();
                    177: 
1.1       www       178: # ========================================================= The language handle
                    179: 
1.57      www       180: use vars qw($lh $current_language);
1.1       www       181: 
                    182: # ===================================================== The "MakeText" function
                    183: 
                    184: sub mt (@) {
1.36      albertel  185: #    open(LOG,'>>/home/www/loncapa/loncom/localize/localize/newphrases.txt');
                    186: #    print LOG (@_[0]."\n");
                    187: #    close(LOG);
1.26      www       188:     if ($lh) {
1.44      raeburn   189:         if ($_[0] eq '') {
                    190:             if (wantarray) {
                    191:                 return @_;
                    192:             } else {
                    193:                 return $_[0];
                    194:             }
                    195:         } else {
1.57      www       196:             if ($#_>0) { return $lh->maketext(@_); }
                    197:             if ($mtcache{$current_language.':'.$_[0]}) {
                    198:                return $mtcache{$current_language.':'.$_[0]};
                    199:             }
                    200:             my $translation=$lh->maketext(@_);
                    201:             $mtcache{$current_language.':'.$_[0]}=$translation;
                    202:             return $translation; 
1.44      raeburn   203:         }
1.3       www       204:     } else {
1.31      albertel  205: 	if (wantarray) {
                    206: 	    return @_;
                    207: 	} else {
                    208: 	    return $_[0];
                    209: 	}
1.4       www       210:     }
                    211: }
                    212: 
1.48      raeburn   213: sub mt_user {
                    214:     my ($user_lh,@what) = @_;
                    215:     if ($user_lh) {
                    216:         if ($what[0] eq '') {
                    217:             if (wantarray) {
                    218:                 return @what;
                    219:             } else {
                    220:                 return $what[0];
                    221:             }
                    222:         } else {
                    223:             return $user_lh->maketext(@what);
                    224:         }
                    225:     } else {
                    226:         if (wantarray) {
                    227:             return @what;
                    228:         } else {
                    229:             return $what[0];
                    230:         }
                    231:     }
                    232: }
                    233: 
1.6       www       234: # ============================================================== What language?
                    235: 
                    236: sub current_language {
1.20      albertel  237:     if ($lh) {
                    238: 	my $lang=$lh->maketext('language_code');
                    239: 	return ($lang eq 'language_code'?'en':$lang);
                    240:     }
1.21      www       241:     return 'en';
1.6       www       242: }
                    243: 
1.52      raeburn   244: sub preferred_languages {
1.60.4.1  raeburn   245:     my $defdom = &Apache::lonnet::default_login_domain();
                    246:     foreach my $domtype ($Apache::lonnet::env{'user.domain'},$Apache::lonnet::env{'request.role.domain'},$defdom) {
                    247:         next if ($domtype eq '');
1.60.4.3! raeburn   248:         if ($domtype =~ /^(\w{2})\w?i$/) {
        !           249:             return ($1.'i');
        !           250:         } elsif ($domtype =~ /^(\w{2})\w?itest$/) {
1.60.4.2  raeburn   251:             return ($1.'t');
1.60.4.1  raeburn   252:         } else {
                    253:             return ('gci');
                    254:         }
                    255:     }
1.52      raeburn   256:     my @languages=();
                    257:     if (($Apache::lonnet::env{'request.role.adv'}) && ($Apache::lonnet::env{'form.languages'})) {
                    258:         @languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$Apache::lonnet::env{'form.languages'}));
                    259:     }
                    260:     if ($Apache::lonnet::env{'course.'.$Apache::lonnet::env{'request.course.id'}.'.languages'}) {
                    261:         @languages=(@languages,split(/\s*(\,|\;|\:)\s*/,
                    262:                  $Apache::lonnet::env{'course.'.$Apache::lonnet::env{'request.course.id'}.'.languages'}));
                    263:     }
                    264: 
                    265:     if ($Apache::lonnet::env{'environment.languages'}) {
                    266:         @languages=(@languages,
                    267:                     split(/\s*(\,|\;|\:)\s*/,$Apache::lonnet::env{'environment.languages'}));
                    268:     }
                    269:     my $browser=$ENV{'HTTP_ACCEPT_LANGUAGE'};
                    270:     if ($browser) {
                    271:         my @browser =
                    272:             map { (split(/\s*;\s*/,$_))[0] } (split(/\s*,\s*/,$browser));
                    273:         push(@languages,@browser);
                    274:     }
                    275: 
1.60      raeburn   276:     foreach my $domtype ($Apache::lonnet::env{'user.domain'},$Apache::lonnet::env{'request.role.domain'},$defdom) {
1.52      raeburn   277:         if ($domtype ne '') {
                    278:             my %domdefs = &Apache::lonnet::get_domain_defaults($domtype);
                    279:             if ($domdefs{'lang_def'} ne '') {
                    280:                 push(@languages,$domdefs{'lang_def'});
                    281:             }
                    282:         }
                    283:     }
                    284:     return &get_genlanguages(@languages);
                    285: }
                    286: 
                    287: sub get_genlanguages {
                    288:     my (@languages) = @_;
                    289: # turn "en-ca" into "en-ca,en"
                    290:     my @genlanguages;
                    291:     foreach my $lang (@languages) {
                    292:         unless ($lang=~/\w/) { next; }
                    293:         push(@genlanguages,$lang);
                    294:         if ($lang=~/(\-|\_)/) {
                    295:             push(@genlanguages,(split(/(\-|\_)/,$lang))[0]);
                    296:         }
                    297:     }
                    298:     #uniqueify the languages list
                    299:     my %count;
                    300:     @genlanguages = map { $count{$_}++ == 0 ? $_ : () } @genlanguages;
                    301:     return @genlanguages;
                    302: }
                    303: 
1.8       www       304: # ============================================================== What encoding?
                    305: 
                    306: sub current_encoding {
1.33      albertel  307:     my $default='UTF-8';
1.56      bisitz    308: # UTF-8 character encoding needed for the whole LON-CAPA system
                    309: # (interface language and homework problem content)
                    310: # See Bugzilla 5702 vs. 2189 and 4067
                    311: #    if ($Apache::lonnet::env{'browser.os'} eq 'win' && 
                    312: #	$Apache::lonnet::env{'browser.type'} eq 'explorer') {
                    313: #        $default='ISO-8859-1';
                    314: #    }
1.12      albertel  315:     if ($lh) {
                    316: 	my $enc=$lh->maketext('char_encoding');
1.33      albertel  317: 	return ($enc eq 'char_encoding'?$default:$enc);
1.12      albertel  318:     } else {
1.33      albertel  319: 	return $default;
1.12      albertel  320:     }
1.8       www       321: }
                    322: 
1.15      www       323: # =============================================================== Which locale?
                    324: # Refer to locale -a
                    325: #
                    326: sub current_locale {
                    327:     if ($lh) {
                    328: 	my $enc=$lh->maketext('lang_locale');
                    329: 	return ($enc eq 'lang_locale'?'':$enc);
                    330:     } else {
                    331: 	return undef;
                    332:     }
                    333: }
                    334: 
1.4       www       335: # ============================================================== Translate hash
                    336: 
                    337: sub texthash {
                    338:     my %hash=@_;
                    339:     foreach (keys %hash) {
                    340: 	$hash{$_}=&mt($hash{$_});
                    341:     }
                    342:     return %hash;
1.1       www       343: }
                    344: 
                    345: # ========= Get a handle (do not invoke in vain, leave this to access handlers)
                    346: 
                    347: sub get_language_handle {
1.9       www       348:     my $r=shift;
1.31      albertel  349:     if ($r) {
                    350: 	my $headers=$r->headers_in;
                    351: 	$ENV{'HTTP_ACCEPT_LANGUAGE'}=$headers->{'Accept-language'};
                    352:     }
1.52      raeburn   353:     my @languages=&preferred_languages();
1.29      www       354:     $ENV{'HTTP_ACCEPT_LANGUAGE'}='';
                    355:     $lh=Apache::localize->get_handle(@languages);
1.57      www       356:     $current_language=&current_language();
1.37      albertel  357:     if ($r) {
1.12      albertel  358: 	$r->content_languages([&current_language()]);
1.8       www       359:     }
1.16      www       360: ###    setlocale(LC_ALL,&current_locale);
1.18      www       361: }
                    362: 
                    363: # ========================================================== Localize localtime
1.35      www       364: sub gettimezone {
1.53      raeburn   365:     my ($timezone) = @_;
                    366:     if ($timezone ne '') {
                    367:         if (!DateTime::TimeZone->is_valid_name($timezone)) {
                    368:             $timezone = 'local';
                    369:         }
                    370:         return $timezone;
                    371:     }
                    372:     my $cid = $Apache::lonnet::env{'request.course.id'};  
                    373:     if ($cid ne '') {
                    374:         if ($Apache::lonnet::env{'course.'.$cid.'.timezone'}) {
                    375:             $timezone = $Apache::lonnet::env{'course.'.$cid.'.timezone'};    
                    376:         } else {
                    377:             my $cdom = $Apache::lonnet::env{'course.'.$cid.'.domain'};
                    378:             if ($cdom ne '') {
                    379:                 my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
                    380:                 if ($domdefaults{'timezone_def'} ne '') {
                    381:                     $timezone = $domdefaults{'timezone_def'};
                    382:                 }
1.45      raeburn   383:             }
                    384:         }
1.50      raeburn   385:     } elsif ($Apache::lonnet::env{'request.role.domain'} ne '') {
                    386:         my %uroledomdefs = 
                    387:             &Apache::lonnet::get_domain_defaults($Apache::lonnet::env{'request.role.domain'});
                    388:         if ($uroledomdefs{'timezone_def'} ne '') {
                    389:             $timezone = $uroledomdefs{'timezone_def'};
                    390:         }
                    391:     } elsif ($Apache::lonnet::env{'user.domain'} ne '') {
                    392:         my %udomdefaults = 
                    393:             &Apache::lonnet::get_domain_defaults($Apache::lonnet::env{'user.domain'});
                    394:         if ($udomdefaults{'timezone_def'} ne '') {
                    395:             $timezone = $udomdefaults{'timezone_def'};
                    396:         }
1.42      albertel  397:     }
1.46      raeburn   398:     if ($timezone ne '') {
                    399:         if (DateTime::TimeZone->is_valid_name($timezone)) {
                    400:             return $timezone;
                    401:         }
                    402:     }
1.42      albertel  403:     return 'local';
1.35      www       404: }
1.18      www       405: 
                    406: sub locallocaltime {
1.59      droeschl  407:     my ($thistime,$timezone) = @_;
1.58      lueken    408: 
1.40      albertel  409:     if (!defined($thistime) || $thistime eq '') {
                    410: 	return &mt('Never');
                    411:     }
1.47      raeburn   412:     if (($thistime < 0) || ($thistime eq 'NaN')) {
                    413:         &Apache::lonnet::logthis("Unexpected time (negative or NaN) '$thistime' passed to lonlocal::locallocaltime");  
                    414:         return &mt('Never');
                    415:     }
                    416:     if ($thistime !~ /^\d+$/) {
                    417:         &Apache::lonnet::logthis("Unexpected non-numeric time '$thistime' passed to lonlocal::locallocaltime");
                    418:         return &mt('Never');
                    419:     }
1.42      albertel  420: 
1.59      droeschl  421:     my $dt = DateTime->from_epoch(epoch => $thistime)
                    422:                      ->set_time_zone(gettimezone($timezone));
1.58      lueken    423: 
1.59      droeschl  424:     # TimeZone tries to determine the 'local' timezone from $ENV{TZ} if this
                    425:     # fails it searches through various system files. Under certain
                    426:     # circumstances this is an extremly expensive operation.
                    427:     # So after the first run we store the timezone in $ENV{TZ} to significantly
                    428:     # speed up future lookups. 
                    429:     $ENV{TZ} = $dt->time_zone()->name() 
                    430:         if (! $ENV{TZ} && gettimezone($timezone) eq 'local');
1.58      lueken    431: 
1.18      www       432:     if ((&current_language=~/^en/) || (!$lh)) {
1.42      albertel  433: 
                    434: 	return $dt->strftime("%a %b %e %I:%M:%S %P %Y (%Z)");
1.18      www       435:     } else {
                    436: 	my $format=$lh->maketext('date_locale');
                    437: 	if ($format eq 'date_locale') {
1.42      albertel  438: 	    return $dt->strftime("%a %b %e %I:%M:%S %P %Y (%Z)");
1.18      www       439: 	}
1.42      albertel  440: 	my $time_zone  = $dt->time_zone_short_name();
                    441: 	my $seconds    = $dt->second();
                    442: 	my $minutes    = $dt->minute();
                    443: 	my $twentyfour = $dt->hour();
                    444: 	my $day        = $dt->day_of_month();
                    445: 	my $mon        = $dt->month()-1;
                    446: 	my $year       = $dt->year();
1.43      www       447: 	my $wday       = $dt->wday();
                    448:         if ($wday==7) { $wday=0; }
1.42      albertel  449: 	my $month  =(split(/\,/,$lh->maketext('date_months')))[$mon];
1.18      www       450: 	my $weekday=(split(/\,/,$lh->maketext('date_days')))[$wday];
                    451: 	if ($seconds<10) {
                    452: 	    $seconds='0'.$seconds;
                    453: 	}
                    454: 	if ($minutes<10) {
                    455: 	    $minutes='0'.$minutes;
                    456: 	}
                    457: 	my $twelve=$twentyfour;
1.19      www       458: 	my $ampm;
1.18      www       459: 	if ($twelve>12) {
                    460: 	    $twelve-=12;
1.19      www       461: 	    $ampm=$lh->maketext('date_pm');
1.18      www       462: 	} else {
1.19      www       463: 	    $ampm=$lh->maketext('date_am');
1.18      www       464: 	}
1.42      albertel  465: 	foreach ('seconds','minutes','twentyfour','twelve','day','year',
                    466: 		 'month','weekday','ampm') {
1.18      www       467: 	    $format=~s/\$$_/eval('$'.$_)/gse;
                    468: 	}
1.42      albertel  469: 	return $format." ($time_zone)";
1.18      www       470:     }
1.1       www       471: }
                    472: 
1.49      raeburn   473: sub getdatelocale {
                    474:     my ($datelocale,$locale_obj);
                    475:     if ($Apache::lonnet::env{'course.'.$Apache::lonnet::env{'request.course.id'}.'.datelocale'}) {
                    476:         $datelocale = $Apache::lonnet::env{'course.'.$Apache::lonnet::env{'request.course.id'}.'.datelocale'};
                    477:     } elsif ($Apache::lonnet::env{'request.course.id'} ne '') {
                    478:         my $cdom = $Apache::lonnet::env{'course.'.$Apache::lonnet::env{'request.course.id'}.'.domain'};
                    479:         if ($cdom ne '') {
                    480:             my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
                    481:             if ($domdefaults{'datelocale_def'} ne '') {
                    482:                 $datelocale = $domdefaults{'datelocale_def'};
                    483:             }
                    484:         }
                    485:     } elsif ($Apache::lonnet::env{'user.domain'} ne '') {
                    486:         my %udomdefaults = &Apache::lonnet::get_domain_defaults($Apache::lonnet::env{'user.domain'});
                    487:         if ($udomdefaults{'datelocale_def'} ne '') {
                    488:             $datelocale = $udomdefaults{'datelocale_def'};
                    489:         }
                    490:     }
                    491:     if ($datelocale ne '') {
                    492:         eval {
                    493:             $locale_obj = DateTime::Locale->load($datelocale);
                    494:         };
                    495:         if (!$@) {
                    496:             if ($locale_obj->id() eq $datelocale) {
                    497:                 return $locale_obj;
                    498:             }
                    499:         }
                    500:     }
                    501:     return $locale_obj;
                    502: }
                    503: 
1.51      jms       504: =pod 
                    505: 
                    506: =item * normalize_string
                    507: 
                    508: Normalize string (reduce fragility in the lexicon files)
1.49      raeburn   509: 
1.51      jms       510: This normalizes a string to reduce fragility in the lexicon files of
                    511: huge messages (such as are used by the helper), and allow useful
                    512: formatting: reduce all consecutive whitespace to a single space,
                    513: and remove all HTML
                    514: 
                    515: =cut
1.17      bowersj2  516: 
                    517: sub normalize_string {
                    518:     my $s = shift;
                    519:     $s =~ s/\s+/ /g;
                    520:     $s =~ s/<[^>]+>//g;
1.22      bowersj2  521:     # Pop off beginning or ending spaces, which aren't good
                    522:     $s =~ s/^\s+//;
                    523:     $s =~ s/\s+$//;
1.17      bowersj2  524:     return $s;
                    525: }
1.22      bowersj2  526: 
1.51      jms       527: =pod 
                    528: 
                    529: =item * ns
                    530: 
                    531: alias for normalize_string; recommend using it only in the lexicon
                    532: 
                    533: =cut
                    534: 
1.22      bowersj2  535: sub ns {
                    536:     return normalize_string(@_);
                    537: }
                    538: 
1.51      jms       539: =pod
                    540: 
                    541: =item * mtn
                    542: 
                    543: mtn: call the mt function and the normalization function easily.
                    544: Returns original non-normalized string if there was no translation
                    545: 
                    546: =cut
                    547: 
1.22      bowersj2  548: sub mtn (@) {
                    549:     my @args = @_; # don't want to modify caller's string; if we
                    550: 		   # didn't care about that we could set $_[0]
                    551: 		   # directly
                    552:     $args[0] = normalize_string($args[0]);
                    553:     my $translation = &mt(@args);
                    554:     if ($translation ne $args[0]) {
                    555: 	return $translation;
                    556:     } else {
                    557: 	return $_[0];
                    558:     }
1.27      www       559: }
                    560: 
                    561: # ---------------------------------------------------- Replace MT{...} in files
                    562: 
                    563: sub transstatic {
                    564:     my $strptr=shift;
                    565:     $$strptr=~s/MT\{([^\}]*)\}/&mt($1)/gse;
                    566: }
                    567: 
1.41      albertel  568: =pod 
                    569: 
                    570: =item * mt_escape
                    571: 
                    572: mt_escape takes a string reference and escape the [] in there so mt
                    573: will leave them as is and not try to expand them
                    574: 
                    575: =cut
                    576: 
                    577: sub mt_escape {
                    578:     my ($str_ref) = @_;
                    579:     $$str_ref =~s/~/~~/g;
                    580:     $$str_ref =~s/([\[\]])/~$1/g;
                    581: }
                    582: 
1.1       www       583: 1;
                    584: 
                    585: __END__

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
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.