php internationalization multilingual

gettext php



La mejor manera de internacionalizar el sitio web simple de PHP (4)

Aunque no necesita un marco, puede usar un marco. Las características de internacionalización en Zend Framework son bastante buenas y puedes usar esa parte en lugar de usar todas las partes (incluyendo MVC)

Tengo que desarrollar un sitio web php bastante simple, así que no necesito un framework. Pero debe admitir varios idiomas (EN / FR / CHINESE). Busqué el sistema incorporado php y encontré dos formas:

No tengo experiencia en i18n sin framework, así que cualquier consejo sobre cuál es la forma más simple de soportar multi idiomas?

Al final solo necesito una función que busque traducción en un archivo (un archivo por idioma). EQ: trans(''hello'');

=> en.yaml (yaml o no, es un ejemplo)

hello: "Hello world!"

=> fr.yaml

hello: "Bonjour tout le monde !"

Y si es posible, prefiero las implementaciones Pure PHP


Aunque ext/gettext y ext/intl están relacionados con i18 (internacionalización), gettext ocupa de la traducción, mientras que intl ocupa de la internacionalización de elementos como visualización de números y fechas, clasificación de pedidos y transliteración. Entonces realmente necesitarías ambos para una solución i18 completa. Dependiendo de sus necesidades, puede encontrar una solución casera basándose en las extensiones mencionadas anteriormente o en los componentes de uso proporcionados por algún marco:

Si solo necesita traducción y el sitio es lo suficientemente simple, tal vez su solución simple (leer un archivo de configuración de traducción en una matriz PHP, usar una función simple para recuperar un token) sea la más fácil.

La solución más simple que puedo pensar es:

$translation = array( ''Hello world!'' => array( ''fr'' => ''Bonjour tout le monde!'', ''de'' => ''Hallo Welt!'' ) ); if (!function_exists(''gettext'')) { function _($token, $lang = null) { global $translation; if ( empty($lang) || !array_key_exists($token, $translation) || !array_key_exists($lang, $translation[$token]) ) { return $token; } else { return $translation[$token][$lang]; } } } echo _(''Hello World!'');


Sé que esta es una vieja pregunta, pero siento que las respuestas carecen de un enfoque más práctico de principio a fin. Esto es lo que hice para que la traducción funcionara usando la biblioteca gettext de PHP y Poedit sin usar ninguna biblioteca PHP adicional en un servidor Debian:

Paso de preparación 1: Instalar gettext y las configuraciones regionales en el servidor

No estoy seguro de cómo se hace esto con otros sistemas operativos, pero para Debian, usted hace:

sudo apt-get install gettext sudo dpkg-reconfigure locales

Edición : asumí que Ubuntu sería lo mismo que Debian, pero aparentemente es un poco diferente. Consulte esta página para obtener instrucciones sobre cómo instalar configuraciones regionales en Ubuntu.

Asegúrese de seleccionar todas las configuraciones regionales que desea usar. Debería ver algo como:

Generating locales (this might take a while)... en_US.UTF-8... done es_MX.UTF-8... done fr_FR.UTF-8... done zh_CN.UTF-8... done Generation complete.

Nota: asegúrese de seleccionar las variantes y codificaciones de caracteres correctas (probablemente UTF-8) para cada idioma. Si instala es_MX.UTF-8 y trata de usar es_ES.UTF-8 o es_MX.ISO-8859-1 , no funcionará.

Paso de preparación 2: Instalar Poedit en las computadoras de los traductores

Poedit está disponible en el repositorio de software para la mayoría de los sistemas operativos Linux. Para Debian, simplemente ejecuta:

sudo apt-get install poedit

Para Windows y Mac, vaya a: https://poedit.net/download

Comience a codificar:

Ok, ahora estás listo para comenzar a codificar. Escribí la siguiente función de contenedor gettext() para traducir tanto singular como plurales:

function __($text, $plural=null, $number=null) { if (!isset($plural)) { return _($text); } return ngettext($text, $plural, $number); }

Ejemplo de uso:

// Singular echo __(''Hello world''); // Plural $exp = 3; printf( __( ''Your account will expire in %d day'', ''Your account will expire in %d days'', $exp ), $exp );

Esto funcionará para todos los idiomas, no solo para los idiomas donde el plural es cualquier cosa donde n != 1 - esto incluye idiomas con múltiples tipos de plural.

También puede agregar notas del traductor como esta:

/** NOTE: The name Coconut Hotel is a brand name and shouldn''t be translated. */ echo __(''Welcome to Coconut Hotel'');

Puede cambiar el texto de NOTE a lo que desee, pero deberá modificarlo en el script de shell a continuación. Importante : la nota de los traductores debe ser parte de un comentario en la línea inmediatamente anterior a la función __() o no se recogerá cuando escaneemos los archivos PHP para cadenas traducibles.

// Warning! THIS WILL NOT WORK! /* NOTE: This translator''s note will not be picked up because it is not immediately preceding the __() function. */ printf( __( ''Your account will expire in %d day'', ''Your account will expire in %d days'', $exp ), $exp ); // Warning! THIS WILL NOT WORK!

Después de que esté listo para enviar las cadenas a los traductores, guarde lo siguiente como un script de shell (por ejemplo, update.sh) en el directorio raíz de su aplicación:

#!/bin/sh find . -iname "*.php" | xargs xgettext --add-comments=NOTE --keyword=__:1,2 --keyword=__ --from-code=UTF-8 -o i18n.pot find . -name ''*.po'' | xargs -I{} msgmerge -U {} i18n.pot

Para ejecutarlo, simplemente hazlo:

cd /path/to/script && sh update.sh

Esto buscará recursivamente todos los archivos PHP en ese directorio y creará un archivo .pot (lo llamé i18n.pot , pero no i18n.pot en i18n.pot nombre que desee) y actualizará cualquier archivo .po existente que encuentre con las nuevas cadenas.

Luego, debemos crear los directorios en los que se almacenarán todos los archivos de configuración regional, uno para cada configuración regional. Deben tener el formato ./locale/{locale}/LC_MESSAGES . Por ejemplo:

cd /path/to/your/project mkdir -p ./locale/en_US.UTF-8/LC_MESSAGES mkdir -p ./locale/es_MX.UTF-8/LC_MESSAGES # ...etc.

Debe decidir sobre un dominio de texto para usar. Esto puede ser lo que quieras, pero el script buscará un archivo llamado {yourTextDomain}.mo dentro de la carpeta LC_MESSAGES para ese idioma. Pon lo siguiente en tu script PHP:

define(''TEXT_DOMAIN'', ''yourdomain''); bindtextdomain(TEXT_DOMAIN, __DIR__.''/locale''); textdomain(TEXT_DOMAIN); bind_textdomain_codeset(TEXT_DOMAIN, ''UTF-8'');

Luego, para cambiar a otra ubicación, haga lo siguiente:

$lang = ''es_MX.UTF-8''; // Change this to the language you want to use if (setlocale(LC_ALL, $lang) === false) { throw new Exception("Server error: The $lang locale is not installed"); } putenv(''LC_ALL=''.$lang));

Inicialmente, envía el archivo .pot generado por el script de arriba a los traductores. Luego abre Poedit y hace clic en File > New from POT/PO file el File > New from POT/PO file . Cuando lo guardan, deben guardarlo como {yourTextDomain}.po . {yourTextDomain} tiene que ser exactamente el mismo que el dominio de texto que tienes en tu script PHP. Cuando lo guardan, creará automáticamente tanto el archivo .po archivo .po . Ambos deben guardarse en el directorio LC_MESSAGES ese idioma cuando hayan finalizado la traducción.

Ahora, cuando actualice las cadenas en su archivo PHP, simplemente vuelva a ejecutar el script de shell y envíe los archivos .po recién actualizados a los traductores. A continuación, traducen las cadenas y se deben volver a cargar los archivos .po y .po .

Eso es. Puede parecer un poco difícil configurarlo, pero una vez que lo tienes funcionando, es realmente fácil.


Gettext parece ser lo que necesitas. Hay un archivo por idioma (excepto el original) y es muy fácil de usar:

echo _(''Bonjour, ça va ?'');

se imprimirá Hola, ¿cómo estás? en inglés.

Hay algunas herramientas con gettext que pueden escanear su archivo php y buscar cadenas traducibles (de hecho, todas las cadenas en _ () o gettext ()). Gracias a eso, no tiene que preocuparse por el archivo de idioma diferente. Simplemente codifica su sitio web en el idioma original y el archivo de idioma se creará automáticamente más adelante.

Sin embargo, gettext es más una herramienta de traducción, mientras que intl es realmente un i18n (formación de números, por ejemplo)