Usuario:ManuelRomero/ProgramacionWeb/Docker/ejemplo
De WikiEducator
Contenido
gettext()
- Función en php que nos va a permitir tener nuestra página en varios lenguajes, lo que se llama internacionalizar nuestra aplicación de una forma profesional
https://www.gnu.org/software/gettext/manual/gettext.html http://www.albertlanchas.com/articulos/internacionalizacion-php-gettext
Preparación de un docker para la práctica
- Vamos a usar un docker límpio con volumen para realizar esta práctica
- De este modo repasaremos todos las herramientas que usamos habitualmente
- Instalamos docker con un directorio común entre contenedor y anfitrión, y exponemos el puerto 21080 en el anfitrión (La máquina windows o linux) para acceder al servidor web del contenedor (puerto 80)
docker run --name xxxx -t -i -v host_path:continer:path -p 21080:80 ubuntu:latest
docker run --name idiomas1 -t -i -v $HOME/app_idiomas:/var/www/idiomas_2020 ubuntu:latest
https://norfipc.com/inf/variables-entorno.html |
- Cambiar los colores al hacer un ls de los directorios
(Si nos apetece, podemos personalizar un poco el bash ....)
- A veces los colores que se ven al listar los ficheros y directorios no son los que más nos gustan, pero podemos adaptarlos modificando nuestro fichero de configuración de bash.
- Son muchas las web donde podemos sacar esta información
- También podemos dejar los colores como están
http://linux-sxs.org/housekeeping/lscolors.html |
alias ls='ls --color' LS_COLORS='di=1:fi=0:ln=31:pi=5:so=5:bd=5:cd=5:or=31:mi=0:ex=35:*.rpm=90' export LS_COLORS
- Cargamos el fichero de configuración
source .bashrc
o
. .bashrc
- Instalando paquetes
- Vamos a instalar algunos paquetes en este contenedor, pues el contenedor de la imagen ubuntu:latest viene solo con el sistema base, y he querido que sea así para ser consciente de todo lo que va a tener nuestro contenedor.
- Yo instalo net-tools para poder ver la ip (comando ifconfig), y vim para tener un editor, podéis instalar nano, o pico como otras opciones.
- Actualizamos e instalamos apache2, php y el módulo de apache2 para intepretar código php
- Durante la instalación nos pedirá el continente y el país o zona para establecer la marca horaria,
- Después levantamos el servicio
sudo apt-get update apt-get install apache2 php libapache2-mod-php vim net-tools service apache2 start
Instalación de la librería para gestionar idiomas
- Para poder usar esta función debemos tener instalado el paquete de ubuntu identificado con el mismo nombre.
apt-get install gettext
- Fichero de configuración de php (En mi caso)
/etc/php/7.2/apache/php.ini
y quitamos el comentario ; de la extensión gettext
- Yo me instalo previamente vim, por ser un editor que uso, se puede instalar y usar otro editor como nano, pico
.... ;extension=gd2 extension=gettext ;extension=gmp ....
- Ahora instalamos la librería de php para usar gettext
sudo apt-get install php-gettext
- Reiniciamos servicio
sudo service apache2 restart
- Para instalar los idiomas
sudo apt-get install locales
Para ver los idiomas que tengo actualmente instalados miramos con el comando
locale -a
Si queremos agregar nuevos idiomas ejecutamos la reconfiguración de los idiomas instalados
# dpkg-reconfigure locales
- Nos aparece una lista de los locales disponibles y seleccionamos los que nos interesen.
- Vamos a agregar en sistema de codificación utf-8, el español, el francés y el inglés para nuestra práctica.
son los códigos (los podemos ver en la lista) 158. en_US.UTF-8 UTF-8, 182. es_ES.UTF-8 UTF-8, 233. fr_FR.UTF-8 UTF-8 , dependerá de versiones instaladas, en cualquier caso mirar la lista y seleccionamos el idioma correspondiente.
establecemos por defecto el es-ES-UTF8
Estructura de directorios
- Se trata de tener un directorio por cada idioma que queramos hacer traducir
- En concreto estableceremos los directorios de configuraciones regionales.
- Estos directorios se esperan bajo locale.
- Este es un posible nombre, podemos poner el que queramos. El nombre de este directorio es importante, ya que lo necesitaremos para una función en php.bindtextdomail
- Los nombres de cada directorio de cada idioma a de ser un nombre estandarizado
- Debemos usar las abreviaturas de las dos letras minúsculas del idioma según la especificación ISO-639-1, seguido de un guión bajo, seguido de las dos letras en mayúscula que corresponderán al código del país según la especificación ISO-3166-1.
- Podemos obtener una lista de las localizaciones instaladas en nuestro sistema
locale -a
- Como ejemplo crearemos 3 idiomas (fr, en, es)
- Se crean directorios con el nombre
ii_PP
- ii son dos letras para especificar el idioma de acuerdo a la especificación ISO-639-1
- PP son dos letras en mayúsculas correspondinetes al país según la especificación ISO-3166-1
- Dentro de cada directorio crearemos el directorio LC_MESSAGES (Este nombre sí debe ser exactamente así)
Escribiendo el fichero del proyecto
- Ahora vamos a ver cómo establecemos en el proyecto las cadenas que queremos traducir
- Para ello vamos lo que vamos a hacer, es en lugar de escribir la cadena de texto, para cada una de ellas vamos a usar un código de identificación que vamos a pasar a la función gettext.
- Por ejemplo si queremos poner un mensaje de bienvenida, querríamos escribir
<h1>Bienvenido a este sitio web</h1>
- en lugar de ello escribiremos
<h1><?php echo gettext("Bienvenido a este sitio web") ?></h1>
- La idea es que en lugar de escribr el texto que queremos que aparezca, este texto lo pasemos por la función de php gettext que lo que va a hacer es buscar dentro de los ficheros de traducción que tengamos, elegir el que corresponda al idioma que tengamos establecidos y darnos el valor correspondiente a ese contenido. Ese contendio lo conoceremos como etiqueta o código del texto a poner. El hecho de escribir el texto completo es para facilitarnos las cosas, pero podríamos poner un código o etiqueta, por ejemplo
<h1><?php echo gettext("Wellcome") ?></h1>
- La diferencia será que en los diferentes ficheros de traducción a idiomas (ahora los analizaremos y aprenderemos a crear), tendremos
- En el fichero de español en el primer caso
msgid "Bienvenido a este sitio web" msgstr "Bienvenido a este sitio web"
- En el fichero de inglés en el segundo caso
msgid "Bienvenido a este sitio web" msgstr "Wellcome to this website"
- En el fichero de español en el segundo caso
msgid "Wellcome" msgstr "Bienvenido a este sitio web"
- En el fichero de inglés en el segundo caso
msgid "Wellcome" msgstr "Wellcome to this website"
- Por lo tanto, el código del mensaje es elegido por nosotros, podemos poner lo que queramos, de lo que se trata, es que ya no escribiremos texto directamente, si no códigos que pasamos a la función gettext
- Alternativamente podemos usar el alias guión bajo _ en lugar del nombre de la función gettext, por comodidad
- Vamos a probar un ejemplo una vez instalado todo.
- Lo pirmero escribimos nuestro fichero php que retorna un recurso
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title><?php echo _("WELLCOME") ?></title> </head> <body> <h1><title><?php echo _("WELLCOME") ?></title></h1> <h2><title><?php echo _("CHOOSE_LANGUAGE") ?></title></h2> <form action="index.php" method='POST'> <?php echo _("NAME") ?><input type="text" name="nombre"><br /> <?php echo _("PASS") ?><input type="text" name="pass"><br /> <input type="submit" value="<?php echo _("LOGIN") ?>" > </form> </body> </html>
- Si probamos a ejecutarlo sin haber configurado los ficheros de idiomas, gettext retorna la propia etiqueta como texto, que es lo que visualizará.
- 2.-Creamos los ficheros de traducción
Creando los ficheros de texto
- Creamos los ficheros con el texto en el idioma específico. Son ficheros de texto con extensión po (portable object)
- El nombre del fichero podemos selecionar el que queramos, pero hemos de mantener el mismo nombre para los diferentes idiomas. Este nombre es importante ya que lo tendremos que establecer en la función bindtextdomain de php (al igual que la carpeta raíz dónde están estos ficheros)
- En este fichero lo que vamos a tener es el código del mensaje y su texto en un idioma concreto.
- Tendremos un fichero para cada idioma, de forma que según la configuración del idioma gettext tomará un fichero u otro con el texto que queremos que aparezca.
- Las palabras reservadas en este fichero son (hay más, usaremos estas)
msgid para establecer el código que hayamos puesto. msgstr para establecer el texto correspondiente a ese código en el idioma concreto que estemos estableciendo.
- Para crearlo lo podemos hacer a mano, pero mejor es usar la herramienta xgettext, con la que le decimos que extraiga
- Para ello nos ubicamos en el directorio del idioma. El fichero ha de existir, por lo que previamente lo creamos, lo podemos hacer con una sola instrucción (touch messages.po, creará el fichero, y luego xgettext cogerá ese fichero para escribir en él).
xgettext --language=PHP --from-code=UTF-8 -o messages.po -j messages.po /var/www/idiomas/index.php
- La opción -j, aunque aquí no sirve, se utilizaría si quiero recuperar parte de traducciones ya realizadas en ese fichero
- Es posible que al hacer nos dé un warning
messages.po: warning: Charset "CHARSET" is not a portable encoding name. Message conversion to user's charset might not work.
- En este caso , si editamos el fichero creado (ver mas abajo), debemo localizar la línea dónde aparece charset y cambiarlo a UTF-8
# SOME DESCRIPTIVE TITLE. ..... <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" .....
Lo cambiamos
# SOME DESCRIPTIVE TITLE. ..... <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" .....
- Este fichero debemos crearlo en cada una de las 3 carpetas para los tres idiomas (es_ES, fr_FR, en_US)
Si ahora abrimos el fichero vemos el contenido que la herramienta xgettext ha creado (ya cambiado el charset)
# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-02-21 12:50+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: /var/www/html/index.php:10 /var/www/html/index.php:14 msgid "WELLCOME" msgstr "" #: /var/www/html/index.php:15 msgid "CHOOSE_LANGUAGE" msgstr "" #: /var/www/html/index.php:18 msgid "NAME" msgstr "" #: /var/www/html/index.php:19 msgid "PASS" msgstr "" #: /var/www/html/index.php:20 msgid "LOGIN" msgstr ""
- Ahora lo que toca es en cada fichero escribir la traducción al texto correspondiente
- En inglés
#: /var/www/html/index.php:10 /var/www/html/index.php:14 msgid "WELLCOME" msgstr "Welcome to this website" #: /var/www/html/index.php:15 msgid "CHOOSE_LANGUAGE" msgstr "Select a language" #: /var/www/html/index.php:18 msgid "NAME" msgstr "Name" #: /var/www/html/index.php:19 msgid "PASS" msgstr "Password" #: /var/www/html/index.php:20 msgid "LOGIN" msgstr "Login"
- En francés
#: /var/www/html/index.php:10 /var/www/html/index.php:14 msgid "WELLCOME" msgstr "Bienvenue sur ce site" #: /var/www/html/index.php:15 msgid "CHOOSE_LANGUAGE" msgstr "Choisissez une langue" #: /var/www/html/index.php:18 msgid "NAME" msgstr "Nom" #: /var/www/html/index.php:19 msgid "PASS" msgstr "Mot de Passe" #: /var/www/html/index.php:20 msgid "LOGIN" msgstr "S' identifier"
- En español
msgid "WELLCOME" msgstr "Bienvenido a este sitio web" #: /var/www/html/index.php:15 msgid "CHOOSE_LANGUAGE" msgstr "Seleccionar el idioma" #: /var/www/html/index.php:18 msgid "NAME" msgstr "Nombre" #: /var/www/html/index.php:19 msgid "PASS" msgstr "Contraseña" #: /var/www/html/index.php:20 msgid "LOGIN" msgstr "Acceso"
- Una herramienta a usar puede ser poedit (Hay varias, esta parece que tiene mucha aceptación)
- Ahora debemos generar el fichero mo (Machine Object) a partir del po (Portable Object)
- Para ello podemos ejecutar la herramienta msgfmt
msgfmt -o fichero.mo fichero.po
- Esto lo hemos de hacer para cada fichero mo, de modo que en nuestro caso, al final tendremos esta estrucctura de ficheros
- Se puede probar con la herramienta poedit que también aporta diccionario para la traducción
- O bien instalar el editor poedit, hay mas.
apt-get install poedit
La página oficial
https://poedit.net/
Poniendo la aplicación en funcionamiento
- Ahora toca usar funciones de la librería gettext para establecer el idioma.
- Es habitual que haya un un idioma por defecto y en caso de que el usuario seleccione otro idioma, actualizarlo.
Funciones de gettext en php
http://php.net/manual/es/book.gettext.php |
- Como hemos comentado gettext permite internacionalizar una aplicación permitiendo adaptarlas a los valores establecidos para los difentes países
- Se trata de establecer valores de entorno a variables que especifican el idioma/país que queremos usar.
- En función de ese valor se irá a buscar la traducción del texto al fichero establecido en el idioma seleccionado.
- Ahora debemos de usar unas funciones de php con el objetivo de establecer el valor de locale
- Para ello vamos a usar una serie de funciones de php disponibles por la librería php-gettext
- Establece la variable de entorno LC_ALL a la configuración regional concreta
- En nuestro caso sería suficiente con establecer LANG.
(valores es_ES o fr_FR o en_US en nuestro caso)
putenv("LC_ALL=es_ES.utf8");
Tip: Para ver los valores exactos que hay que establecer, debemos ver cómo identifica el sistema a estos idiomas, para lo cual basta con escribier en el sistema operativo locale -a
- Conviente verificar si se ha realizado bien o no la acción establecida
$idioma = "es_ES.utf8"; if (!putenv("LC_ALL=$idioma")) echo "No se ha podido establecer variable de entorno LC_ALL al valor $idioma");
- Es parecida a puntenv, pero en este caso establecemos un valor para LC_ALL
- En este caso se retorno el valor establecido si se ha realizado correctamente o null si no se ha podido realizar la asignación
setlocale(LC_ALL, "es_ES.utf8");
- Îgual que en el caso anterior se puede verificar la asignación
$idioma = "es_ES.utf8"; $asignación = setlocale (LC_ALL, $idioma); echo "Se ha establecido para la categoría LC_ALL el valor $asignación";
- Establece la ruta del dominio. Es decir el nombre del fichero que contiene las traducciones de las cadenas, así como el directorio que lo contiene
- No hay que especificar la extensión la cual ya está establecida mo (machine object)
Valores en nuestro caso messages para el nombre del fichero o dominio (primer parámetro) y locale' para el nombre del directorio (segundo parámetro)
- Devuelve la ruta completa para el dominio establecido
$dominio = "messages"; $dir = "locale"; $ruta_dominio = bindtextdomail($dominio, $dir); echo "Se ha establecido la ruta $ruta_dominio para los ficheros de traducción";
- En el ejemplo
- Agregando estas funciones en el fichero index.php que estamos implementando como ejemplo
<?php $msj =""; //Variable que me dará información si algo no ha funcionado $idioma = "es_ES.utf8"; // $idioma = "fr_FR.utf8"; //Para cambiar a idioma francés // $idioma = "en_US.utf8"; //Para cambiar a idioma inglés if (!putenv("LC_ALL=$idioma")) $msj="No se ha podido establecer el idioma $idioma en variables de entorno<br />"; if (setlocale(LC_ALL, $idioma)=="") $msj.="No se ha podido cargar el idioma $idioma como categoría LC_ALL"; echo setlocale (LC_ALL, 0); $dominio = "texto"; echo bindtextdomain($dominio, "locales"); ?> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title><?php echo _("WELLCOME") ?></title> </head> <body> <?= $msj ?> <h1><?php echo gettext("WELLCOME") ?></h1> <h2><?php echo _("CHOOSE_LANGUAGE") ?></h2> <form action="index.php" method="POST"> <?php echo _("NAME") ?><input type="text" name="nombre"><br /> <?php echo _("PASS") ?><input type="text" name="pass"><br /> <input type="submit" value="<?php echo _("LOGIN") ?>" > </form> </body> </html> </soruce> ;Otras funciones que pueden ser de interés ;textdomain() Establece el dominio para la librería gettext de php, similar a bindtextdomain ;bind_textdomain_codeset :Especifica el juego de caracteres en que los mensajes del catálogo del dominio serán devueltos ;dcgettext : Sobrescribe el dominio de la búsqueda única del mensaje ;dcngettext : Versión plural de dcgettext ;dgettext : Sobrescribe el dominio actual ;dngettext : Versión plural de dgettext ;gettext : Consultar un mensaje en el dominio actual ;ngettext : Versión plural de gettext ;textdomain : Establece el dominio actual <!-- ===Instalar el idioma=== https://es.stackoverflow.com/questions/98786/gettext-no-realiza-las-traducciones-en-web-php </div> -->