¿Por qué tu sitio PHP debería hablar varios idiomas?
\n\nImagina que creas el producto perfecto: rápido, intuitivo y que resuelve problemas reales. Pero hay un detalle: tu interfaz solo está en español. Los clientes potenciales de Alemania, Japón o Brasil simplemente cierran la pestaña al no entender ni un botón. Esto no es solo una pérdida de ingresos, es perder mercados enteros.
\n\nLa internacionalización (i18n — por «internationalization», donde 18 letras separan la i y la n) y la localización (l10n) no son un simple requisito técnico, sino una herramienta estratégica. Muchos desarrolladores le temen a este concepto, pensando que tendrán que reescribir todo el código. La realidad es que organizar bien las traducciones en PHP es un proceso elegante que limpia tu código y globaliza tu negocio.
\n\nEn este artículo analizaremos tres enfoques reales para internacionalizar aplicaciones PHP: desde arrays simples hasta la potente extensión intl y el clásico gettext. Aprenderás no solo a traducir texto, sino a manejar correctamente fechas, números y formas plurales — porque en árabe, polaco o ruso las reglas de declinación son muy distintas.
Principales enfoques para i18n en PHP
\n\nAntes de escribir código, hay que elegir la arquitectura. Los métodos se dividen en tres categorías. La elección depende del tamaño del proyecto y los requisitos de rendimiento.
\n\n1. Arrays y archivos ini (enfoque DIY)
\n\nLa forma más sencilla es almacenar las traducciones en arrays asociativos o archivos .ini. Ideal para proyectos pequeños o MVPs.
// lang/es.php\nreturn [\n 'welcome' => '¡Bienvenido al sitio!',\n 'logout' => 'Cerrar sesión',\n 'cart_empty' => 'El carrito está vacío'\n];\n\n// lang/en.php\nreturn [\n 'welcome' => 'Welcome to the website!',\n 'logout' => 'Logout',\n 'cart_empty' => 'Cart is empty'\n];\n\nUsarlo es simple: cargamos el archivo correspondiente según la sesión o cookie del usuario.
\n\nfunction __($key) {\n static $lang = null;\n if ($lang === null) {\n $locale = $_SESSION['lang'] ?? 'es';\n $lang = include "lang/{$locale}.php";\n }\n return $lang[$key] ?? $key;\n}\n\necho __('welcome'); // ¡Bienvenido al sitio!\n\nVentajas: simplicidad, no requiere extensiones, fácil de cachear (incluso en Redis).
\nDesventajas: sin soporte para plurales (tendrías que implementarlo manualmente), poco práctico para proyectos grandes (cientos de miles de claves en un solo archivo).
2. Gettext — el clásico de siempre
\n\nGettext es el estándar de facto para internacionalización en el mundo Unix. En PHP está disponible mediante la extensión gettext. Es una herramienta potente utilizada en WordPress, Drupal y Symfony.
Primero creamos archivos .po (por ejemplo, para español):
# es_ES/LC_MESSAGES/messages.po\nmsgid "Hello, %s!"\nmsgstr "¡Hola, %s!"\n\nmsgid "You have %d new message"\nmsgid_plural "You have %d new messages"\nmsgstr[0] "Tienes %d mensaje nuevo"\nmsgstr[1] "Tienes %d mensajes nuevos"\n\nLuego compilamos a un archivo .mo (con la herramienta msgfmt). En el código PHP se ve así:
putenv('LC_ALL=es_ES.UTF-8');\nsetlocale(LC_ALL, 'es_ES.UTF-8');\nbindtextdomain('messages', './locale');\ntextdomain('messages');\n\necho gettext('Hello, %s!', 'Carlos'); // ¡Hola, Carlos!\n\n// Formas plurales — magia:\necho ngettext('%d message', '%d messages', 3); // 3 mensajes\n\nPor cierto, para agilizar el desarrollo usa Poedit — resalta las cadenas sin traducir.
\n\n3. Extensión Intl (PHP 5.3+)
\n\nSi no solo necesitas traducir texto, sino formatear correctamente números, fechas o monedas según los estándares de cada país, usa Intl. Es una capa sobre la biblioteca ICU (International Components for Unicode).
// Formateo de números