¿Por qué tu código C++ debería hablar todos los idiomas del mundo?
\n\nImagina: has escrito un parser ideal o un servidor de alto rendimiento en C++. Es increíblemente rápido, usa memoria mínima, pero muestra mensajes solo en ruso. Y mañana, una corporación japonesa compra tu producto. ¿Qué hacer? ¿Reescribir toda la salida? ¿Insertar cientos de if (lang == "jp")? Ese es un camino al infierno.
Conoce la internacionalización en C++ (o simplemente i18n C++ — de la palabra "internationalization", donde hay 18 letras entre la i y la n). Esto no es solo "traducir botones", sino toda una filosofía de diseño que permite que tu aplicación funcione correctamente con cualquier idioma, cultura y codificación. Sin la internacionalización en C++, un proyecto está condenado a un nicho local. Con ella, entras al mercado global.
\n\nEn este artículo, desglosaremos cómo dominar la localización en C++ usando herramientas estándar y bibliotecas potentes. Sin rodeos: solo código funcional y casos reales.
\n\nLos tres pilares de la internacionalización: Locale, Codificación y Mensajes
\n\nAntes de escribir código, entendamos en qué consiste prácticamente la internacionalización en C++. Debes resolver tres tareas:
\n\n- \n
- Locale: Cómo formatear fechas, números y moneda. En EE. UU. escriben 03/15/2024, en Alemania — 15.03.2024. \n
- Codificación: Cómo trabajar con Unicode. Cirílico, caracteres chinos, escritura árabe — todo esto debe almacenarse y mostrarse sin texto corrupto. \n
- Mensajes: Cómo almacenar y sustituir cadenas traducidas. "File not found" en ruso es "Файл не найден". \n
Ignorar incluso un punto convertirá tu aplicación en una calabaza. Vamos en orden.
\n\nNivel básico: Locale estándar y std::locale
\n\nLa biblioteca estándar de C++ proporciona la clase std::locale. Esta es tu primera herramienta para la internacionalización en C++. Puede cambiar separadores decimales y formatos de salida de fechas.
Ejemplo: formateando números y fechas
\n\n#include <iostream>\n#include <locale>\n#include <ctime>\n#include <iomanip>\n\nvoid print_date(double value) {\n std::cout.imbue(std::locale("en_US.UTF-8"));\n std::cout << "EN: " << value << std::endl;\n\n std::cout.imbue(std::locale("de_DE.UTF-8"));\n std::cout << "DE: " << value << std::endl;\n\n std::cout.imbue(std::locale("ru_RU.UTF-8"));\n std::cout << "RU: " << value << std::endl;\n}\n\nint main() {\n double pi = 3.14159;\n print_date(pi);\n\n // Working with dates\n std::time_t t = std::time(nullptr);\n std::tm* tm = std::localtime(&t);\n\n std::cout.imbue(std::locale("en_US.UTF-8"));\n std::cout << "EN date: " << std::put_time(tm, "%x") << std::endl;\n\n std::cout.imbue(std::locale("ru_RU.UTF-8"));\n std::cout << "RU date: " << std::put_time(tm, "%x") << std::endl;\n\n return 0;\n}\n\nImportante: Los nombres de locale (ej., "ru_RU.UTF-8") dependen del sistema operativo. En Windows, podrían llamarse "Russian_Russia.1251". Este es el primer punto doloroso. La localización en C++ estándar mediante std::locale está bien para tareas simples, pero para proyectos serios, es mejor usar bibliotecas especializadas.
Nivel avanzado: Boost.Locale — el mejor amigo del internacionalizador
\n\nSi escribes en C++ y quieres hacer internacionalización en C++ correctamente — instala Boost.Locale. Esta biblioteca resuelve los tres problemas: puede trabajar con Unicode, formatear cualquier cosa y extraer cadenas traducidas de archivos .po y .mo (formato GNU gettext).
\n\nInstalación y configuración
\nBoost.Locale es parte de Boost. Inclúyelo en tu CMakeLi