<html>
        <head>
                <title>Perl i18n</title>
        </head
<body>

<h1>Perl i18n</h1>

<ul>
        <li> Locales en Perl </li>
        <li> Uso de Unicode </li>
        <li> Modules para programes multi-linguales </li>
</ul>

<table cellpadding="5" cellspacing="0" border="1">
<tr><th colspan="2">Documentacion</th></tr>
<tr><td> perluniintro </td><td> Perl Unicode Introduction </td></tr>
<tr><td> perlunicode </td><td> Unicode Support in Perl </td></tr> 
<tr><td> perllocale </td><td> Perl locale handling </td></tr>
</table>

<h2> Locales en Perl </h2>

<h3> Como usar locales en perl</h3>

<p>Probamos <samp>perl -V:d_setlocale</samp> para ver si perl crea que 
se puede usar locales en este sistema. (Tiene que tener el valor 
<b>define</b>).</p>

<p>Para usar los locales tenemos que tener <samp>use locale</samp>
y una de las siguentes cosas para tener el entorno:</p>
<ol>
        <li> Los variables del entorno tiene que estar</li>
        <li> El script tiene que usar <samp>setlocale</samp></li>
</ol>

<h4>use locale pragma</h4>

<p> El uso de locales affecta: </p>
<ul>
        <li>Orden de strings y numeros (p.j. <samp>cmp</samp>)</li>
        <li>Expressiones regulares y conversion de <i class="changeme">case</i></li>
        <li>Formato de numeros, y fechas</li>
</ul>

<p><b>Nota:</b> El uso de locales tiene implicaciones de seguridad, 
para ejemplo un usuario puede definir su proprio locale en que <b>|</b>
ó <b>&gt;</b> era alpanumerico. Entonces perl puede marcar algunas cosas 
como inseguro (con <i>taint</i>) cuando usamos <samp>locale</samp>.

<h4>Variables de Entorno</h4>

<dl>
        <dt>PERL_BADLANG</dt>
        <dd>A string that can suppress Perl's warning about failed locale settings at startup</dd>

        <dt>LC_ALL</dt>
        <dd> Si está definido sobre-escribe todos las otras valores </dd>

        <dt>LC_CTYPE</dt>
        <dd> chooses the character type locale</dd>

        <dt>LC_COLLATE</dt>
        <dd> chooses the collation (sorting) locale </dd>

        <dt>LC_MONETARY</dt>
        <dd> chooses the monetary formatting locale </dd>

        <dt>LC_NUMERIC</dt>
        <dd> chooses the numeric format locale </dd>

        <dt>LC_TIME</dt>
        <dd> chooses the date and time formatting locale </dd>

        <dt>LC_MESSAGES</dt>
        <dd> chooses the message format </dd>

        <dt>LANG</dt>
        <dd> Se usa como valor para <i>XX</i> por defecto si <samp>LC_ALL</samp> ni <samp>LC_</samp><i>XX</i>
        están definidos. </dd>
</dl>

<p>De estos variables perl core no usa LC_MESSAGES ni LC_MONETARY pero 
podría ser que otros programas ó modules son affectados por su 
valor.</p>

<h4>setlocale</h4>

<p>Por defecto las valores están definido por el entorno pero aveces 
querremos cambiar las valores durante el ejeccion del programa y esto
lo podemos hacer con la funcion <samp>setlocale</samp> (dentro de 
<samp>POSIX</samp>). </p>

<p>
        <samp>use POSIX qw(locale_h);</samp><br>
        <samp>setlocale( <i>variable</i>, <i>valor</i> ) </samp></p>
</p>

<p>Si no pasamos un segundo argumento y el primer valor no es LC_ALL
devuelve el valor de este variable</p>

<p>Si no pasamos un segundo argumento y el primer valor es LC_ALL el 
valor devuelto depende de la implementacion, probablemente sería 
una lista de locales ó un locale pero consulta el documentacion 
de <samp>setlocale</samp> para detallos de como funciona.</p>

<p>Si pasamos dos argumentos validos el variable tendrá el valor
de segundo argumento y se devuelve el nuevo valor. (Podría ser
que el valor puesto no es exactamente lo mismo que el segundo 
argumento - será un alias para el valor especificado</p>

<p>Si el segundo argumento es "" el valor está puesto al valor 
definido por el entorno. Normalmente este el valor en el entorno
cuando perl arrancaba depende del sistema cambios al entorno 
durante la ejecuccion del programa podría tomar effecto ó no.</p>

<h4>Valores de los variables</h4>

<p>Hemos dado dos maneras de definir los valores pero todavía no 
hemos visto que valores podemos dar! </p>

<p>Pues el hecho es que depende del sistema, el forma basico es: 
<br />idioma_region.codeset<br />
pero en muchos casos ni region ni codeset están.</p>

<p> Noralmente se usa valores definido por los estandares ISO</p>
<dl>
        <dt>idioma</dt>
        <dd>los codigos de dos letras desde ISO 639 (p.j. ca)</dd>

        <dt>region o pais</dt>
        <dd>los codigos de dos letras desde ISO 3166 (p.j. es)</dd>

        <dt>codeset</dt>
        <dd>Para valores de tipo latino viene de ISO 8859</dd>
</dl>

<p>Hay dos valores especiales <samp>C</samp> y <samp>POSIX</samp>. 
Estos son los valores que se usa por defecto si el programa no dispone
de informacion de su entorno. Su idiomia es ingles (estados unidos)
y el codeset es ASCII. No todos los sistemas tiene POSIX por lo tanto
es mejor usar C cuando tengas que especificar este locale.</p>
</p>

<h4>POSIX::localeconv()</h4>

<p>Te da informacion sobre los valores affectados por LC_NUMERIC y LC_MONETARY. </p>

<p>No toma argumentos y devuelve la informacion en una referencia a un hash.</p>

<p>Para ejemplo, el siguente codigo devuelve , si LC_NUMERIC es <samp>es</samp>
y . si es <samp>en</samp></p>

<pre>
        use POSIX qw(locale_h);
        my $decimales = ${localeconv()}{'decimal_point'};
</pre>

<h2> Uso de Unicode </h2>

En perl el uso de locales y unicode juntos puede causar problemas, por lo 
tanto mejor no usarlas juntas. Pero si tienes que usarlo hay algunas cosas
que son importante saber.

Sólo tratamos de perl &gt; 5.8 por que antes que esto unicode en perl
era interesante para usar. 

<h3>use utf8</h3>

Aparte de 5.8 sólo tenemos que usar esto para indicar que nuestro 
programa está codificado como utf8, esto nos permite usar utf8 en los
nombres de identifadores y en los literales.

<h3>Unicode en entrada/salida</h3>

<p>Hay que usar el sistema de entrada/salida de PerlIO, comprueba esto
con: <samp>perl -V:useperlio</samp></p>

<p>Para leer y escribir ficheros en utf8 tenemos que usar el 
<i class="changeme">layer</i> utf8, esto se hacer a mientras 
tienes algo abierto con <samp>binmode(STDOUT, ":utf8");</samp>
y a la hora de abrir un fichero con <samp>open(FH, "<:utf8", "file")</samp>
Se puede definir globalmente con el variable de entorno <b>PERL_UNICODE</b>
o con la opcion de la linea de comando <b>-C</b> </p>

<p>Tambíen se puede cambiar de codificacion usando ":locale" (con 
el open pragma sólo) o con las funciones de <samp>Encode</samp> pero
como la cosa se pone mucha más complicado cuando tenemos que traducir
entre codificaciones no hablamos de esto.</p>

<h2> Modules </h2>

Todos de estos son utiles:
<ul>
<li> I18N::LangTags </li>
<li> Locale::Country </li>
<li> Locale::Language </li>
<li> Locale::Maketext </li>
<li> Unicode::Normalize </li>
<li> Unicode::CharName </li>
<li> Unicode::Collate </li>
</ul>

<h3> Locale::Maketext </h3>

<p>Este module es la clave en una programa que tiene que tratar de varios
lenguas. El uso se muestra aquí </p>

<h4>test.pl</h4>
<pre>
use PinckyWeb::L10N;
use lib '.';

my $lh = PinckyWeb::L10N->get_handle() || die "What language? $!";
print $lh->maketext("Minimum ([_1]) is larger than maximum ([_2])!\n", 20, 10);
print $lh->maketext("You won!"), "\n";
print $lh->maketext("Your search matched [quant,_1,document]!");
</pre>

<h4>PinckyWeb/L10N.pm</h4>
<pre>
package PinckyWeb::L10N;
use base qw(Locale::Maketext);
1;
</pre>

<h4>PinckyWeb/L10N/es.pm</h4>
<pre>
package PinckyWeb::L10N::es;

use base qw(PinckyWeb::L10N);
  %Lexicon = (
    "Minimum ([_1]) is larger than maximum ([_2])!\n" => "El minimo de [_1] es más grande que el maximo de [_2]\n",
    'You won!' => 'Has ganado!',
    'Your search matched [quant,_1,document]!' 
        => sub { return "La busqueda ha encontrado ". Locale::Maketext->quant($_[1],"documento") },
    '_AUTO' => 1,
  );

1;
</pre>

<h4>PinckyWeb/L10N/en.pm</h4>
<pre>
package PinckyWeb::L10N::en;

use base qw(PinckyWeb::L10N);
  %Lexicon = (
    '_AUTO' => 1,
  );

1;
</pre>
</body>
</html>