Internacionalización (i18n) en PHP: de los fundamentos a las soluciones modernas
\n\nLa internacionalización (i18n) es el proceso de diseñar software de manera que pueda adaptarse fácilmente a diferentes idiomas y regiones sin modificar el código. En PHP existen varios enfoques para implementar i18n, desde funciones integradas hasta potentes bibliotecas. En este artículo, veremos las herramientas principales y las mejores prácticas.
\n\n¿Por qué es necesaria la internacionalización?
\nEl objetivo principal de i18n es separar el texto de la interfaz del código. Esto permite:
\n- \n
- Añadir nuevos idiomas sin cambiar la lógica de la aplicación \n
- Soportar múltiples locales (formatos de fecha, números, monedas) \n
- Simplificar el proceso de traducción para los traductores \n
- Cumplir con los estándares regionales (por ejemplo, formato de número de teléfono) \n
Soporte integrado: gettext
\nPHP ofrece un potente mecanismo gettext para trabajar con traducciones. Este es un enfoque clásico utilizado en la mayoría de los sistemas Linux.
\n\nInstalación y configuración
\nAsegúrese de que la extensión gettext esté instalada. En la mayoría de las distribuciones de Linux está disponible por defecto. Para Windows, puede ser necesario habilitar php_gettext.dll en php.ini.
Creación de archivos de traducción
\nPrimero, cree un directorio para los locales. Una estructura típica:
\nlocale/\n ru_RU/\n LC_MESSAGES/\n messages.po\n messages.mo\n en_US/\n LC_MESSAGES/\n messages.po\n messages.mo\n\nLos archivos .po (Portable Object) son archivos de texto con traducciones. Ejemplo de contenido de messages.po para ruso:
msgid "Welcome"\nmsgstr "Добро пожаловать"\n\nmsgid "Hello, %s!"\nmsgstr "Здравствуйте, %s!"\n\nCompile el .po a binario .mo con la utilidad msgfmt:
msgfmt locale/ru_RU/LC_MESSAGES/messages.po -o locale/ru_RU/LC_MESSAGES/messages.mo\n\nUso en el código
\nEjemplo de script PHP con gettext:
\n<?php\n// Establecemos el locale y el dominio\n$locale = 'ru_RU';\nputenv("LANG=$locale");\nsetlocale(LC_ALL, $locale);\nbindtextdomain('messages', __DIR__ . '/locale');\ntextdomain('messages');\n\n// Traducción de cadenas\necho gettext('Welcome'); // Muestra "Добро пожаловать"\necho _('Hello, %s!', 'Иван'); // Muestra "Здравствуйте, Иван!"\n?>\n\nLa función _() es una abreviatura de gettext(). Para traducciones con marcadores de posición, use sprintf():
echo sprintf(_('Hello, %s!'), $username);\n\nEnfoque moderno: symfony/translation
\nPara proyectos grandes, es más conveniente usar la biblioteca symfony/translation. Ofrece una interfaz más flexible, soporte para diferentes formatos (YAML, XLIFF, JSON) y se integra fácilmente con frameworks.
\n\nInstalación mediante Composer
\ncomposer require symfony/translation\n\nEjemplo de uso
\n<?php\nrequire_once __DIR__ . '/vendor/autoload.php';\n\nuse Symfony\\Component\\Translation\\Translator;\nuse Symfony\\Component\\Translation\\Loader\\ArrayLoader;\n\n$translator = new Translator('ru_RU');\n$translator->addLoader('array', new ArrayLoader());\n\n// Añadimos traducciones directamente (para demostración)\n$translator->addResource('array', [\n 'Welcome' => 'Добро пожаловать',\n 'Hello %name%' => 'Здравствуйте, %name%',\n], 'ru_RU');\n\n// Cambio a inglés\n$translator->setLocale('en_US');\n$translator->addResource('array', [\n 'Welcome' => 'Welcome',\n 'Hello %name%' => 'Hello, %name%',\n], 'en_US');\n\n// Uso\necho $translator->trans('Welcome'); // "Welcome"\necho $translator->trans('Hello %name%', ['%name%' => 'John']); // "Hello, John"\n?>\n\nTrabajo con archivos YAML
\nCree un archivo messages.ru.yaml: