Guía de internacionalización de Java: Traduzca archivos .properties con IA
Configure ResourceBundle, estructure los archivos .properties, traduzca a 40 o más idiomas con IA y, a continuación, deje que PTC (Private Translation Cloud) revise la aplicación Java en ejecución mediante capturas de pantalla o la extensión de navegador. Al final, tendrá un JAR multilingüe listo para publicar, con cada idioma de destino verificado antes del lanzamiento. Para ver el resumen del servicio independiente para Java, consulte traducir aplicaciones Java con IA.
ResourceBundle carga el archivo .properties correcto en tiempo de ejecución
El sistema de i18n de Java se basa en dos elementos. Los archivos .properties que almacenan sus cadenas traducidas y la clase ResourceBundle que carga el archivo correcto en tiempo de ejecución en función del locale del usuario.
Cuando su aplicación se ejecuta, ResourceBundle comprueba el locale del usuario y carga el archivo correspondiente automáticamente. Si falta una traducción, recurre al archivo predeterminado de forma silenciosa. Nada falla, pero las traducciones que faltan tampoco aparecen como errores. Llamada a una cadena en el código:
ResourceBundle bundle = ResourceBundle.getBundle("messages", Locale.FRENCH);
String greeting = bundle.getString("welcome.message");
Ese es todo el mecanismo. El resto del trabajo de localización se realiza en los propios archivos .properties, por lo que estructurarlos correctamente es importante.
Configure su paquete de recursos con messages_{locale}.properties
Un paquete de recursos es un conjunto de archivos .properties que comparten un nombre base común. El nombre base es la parte del nombre de archivo anterior al sufijo del locale. Es lo que utiliza ResourceBundle.getBundle() para encontrar el archivo correcto en tiempo de ejecución.
src/main/resources/
messages.properties # default (usually English)
messages_fr.properties # French
messages_de.properties # German
messages_es.properties # Spanish
messages_ja.properties # Japanese
messages_zh_CN.properties # Simplified Chinese (note underscore, not hyphen)
Las aplicaciones más grandes suelen utilizar varios paquetes de recursos para mantener todo organizado:
src/main/resources/
messages.properties
errors.properties
emails.properties
Java espera un patrón de nomenclatura específico: basename_language.properties, o basename_language_COUNTRY.properties para las variantes regionales:
messages_fr.properties # French
messages_fr_CA.properties # French (Canada)
messages_pt_BR.properties # Portuguese (Brazil)
Los códigos de idioma siguen la norma ISO 639-1. Los códigos de país siguen la norma ISO 3166-1. Usar el formato incorrecto significa que ResourceBundle no encontrará el archivo en tiempo de ejecución.
Cargue y utilice el paquete de recursos en el código, con MessageFormat para la sustitución de marcadores de posición:
import java.util.Locale;
import java.util.ResourceBundle;
import java.text.MessageFormat;
public class App {
public static void main(String[] args) {
Locale locale = Locale.of("es");
ResourceBundle messages = ResourceBundle.getBundle("messages", locale);
String welcome = MessageFormat.format(
messages.getString("app.welcome"),
"My App"
);
System.out.println(welcome);
// -> "Bienvenido a My App"
}
}
Para cadenas simples sin marcadores de posición, messages.getString("key") es suficiente.
Seis convenciones que hacen que sus archivos .properties estén listos para traducir
Cada línea es un par clave-valor separado por =. La forma en que escribe su archivo de origen afecta directamente a la calidad de sus traducciones. Esto se aplica tanto si traduce de forma manual como con una herramienta de IA como PTC.
1. Utilice claves claras y descriptivas que nombren dónde aparece la cadena
Las claves deben dejar claro dónde y cómo se utiliza una cadena. Esto es importante cuando gestiona cientos de cadenas en varios archivos.
# Incorrect
btn1 = Submit
msg2 = Error
# Correct
form.submit.button = Submit
error.login.invalid_credentials = Invalid username or password
Nunca cambie una clave después de que haya comenzado la traducción. Cambiar una clave deja huérfana la traducción existente.
2. Utilice marcadores de posición numerados, no la concatenación de cadenas en el código
Escriba la oración completa en su archivo .properties y utilice marcadores de posición numerados para el contenido variable en lugar de concatenar cadenas en el código.
// Incorrect (in code)
"Hello, " + username + "! You have " + count + " new messages."
# Correct (in .properties)
dashboard.greeting = Hello, {0}! You have {1} new messages.
Muchos idiomas cambian el orden de las palabras y las reglas de concordancia, por lo que dividir las oraciones en fragmentos hace que la traducción correcta sea imposible.
3. Gestione la pluralización con ChoiceFormat, ICU o claves con sufijo
Para la pluralización en Java estándar, ChoiceFormat funciona directamente dentro de .properties:
messages.count = {0,choice,0#no messages|1#one message|1<{0} messages}
Java procesa esto en tiempo de ejecución y devuelve la forma correcta en función del valor introducido. ChoiceFormat es sencillo, pero se limita a la coincidencia de rangos numéricos. No procesa de forma nativa reglas de plurales complejas.
Para plurales adaptados al idioma (one/few/many/other del polaco, las seis formas del árabe), utilice MessageFormat de la biblioteca ICU4J:
String pattern = "{0, plural, one {# note} other {# notes}}";
String result = new com.ibm.icu.text.MessageFormat(pattern, locale).format(new Object[]{count});
O codifique los plurales como claves separadas con sufijos convencionales para que PTC pueda generar las categorías de plural correctas por idioma:
notes.count.zero=No notes yet
notes.count.one={0} note
notes.count.other={0} notes
PTC genera las categorías de plural correctas por idioma de destino. El polaco obtiene one / few / many / other. El japonés obtiene solo other.
4. Escape =, :, # y \ con una barra invertida
Los caracteres como =, :, # y \ tienen un significado especial en los archivos .properties:
=o:separan las claves de los valores.#o!inician un comentario.\introduce secuencias de escape (como\npara un salto de línea).
Escápelos con una barra invertida donde sea necesario:
support.link = Visit us at https\://support.example.com
5. Guarde los archivos .properties como UTF-8
Guarde siempre los archivos .properties en UTF-8. Sin él, los caracteres no ASCII se corrompen y las traducciones se vuelven ilegibles. Históricamente, los archivos .properties de Java eran ISO-8859-1, lo que requería escapes \uXXXX para los caracteres no ASCII. Java 9 y versiones posteriores los leen como UTF-8 de forma predeterminada, por lo que debe comprobar su versión en tiempo de ejecución antes de depender del UTF-8 sin formato.
6. Mantenga todo el texto visible para el usuario fuera del código
Si una cadena es visible para los usuarios, pertenece a un archivo .properties. Las cadenas hardcoded no se traducirán. Su aplicación terminará mostrando una mezcla de idiomas.
Formatee fechas, horas, números y monedas con helpers adaptados al locale
No todo lo que necesita localización se encuentra en un archivo .properties. Las fechas, las horas, los números y los valores de moneda se formatean en el código en tiempo de ejecución, y hacerlos correctamente importa tanto como sus cadenas traducidas.
Fechas con DateTimeFormatter:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
LocalDate today = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter
.ofLocalizedDate(FormatStyle.LONG)
.withLocale(Locale.of("fr"));
System.out.println(today.format(formatter));
// -> "27 mai 2026"
Moneda con NumberFormat:
import java.text.NumberFormat;
import java.util.Currency;
NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.of("de", "DE"));
formatter.setCurrency(Currency.getInstance("EUR"));
System.out.println(formatter.format(1999.99));
// -> "1.999,99 €"
Utilice siempre formateadores adaptados al locale. Nunca escriba de forma hardcoded "$", los separadores de miles "," o los patrones "MM/DD/YYYY".
Integre ResourceBundle en Spring Boot con MessageSource
Spring Boot envuelve ResourceBundle en un bean MessageSource que se integra con las funciones de i18n del framework. También cubre los mensajes de validación, las plantillas de Thymeleaf y la resolución del locale de las solicitudes web.
Configúrelo en application.properties:
spring.messages.basename=messages
spring.messages.encoding=UTF-8
spring.messages.fallback-to-system-locale=false
Coloque messages.properties, messages_es.properties, etc. en src/main/resources/.
Úselo en un controlador:
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
@RestController
public class GreetingController {
private final MessageSource messageSource;
public GreetingController(MessageSource messageSource) {
this.messageSource = messageSource;
}
@GetMapping("/greeting")
public String greeting(@RequestParam String name) {
return messageSource.getMessage(
"app.greeting",
new Object[]{name},
LocaleContextHolder.getLocale()
);
}
}
Configure el locale resolver para que lea del encabezado Accept-Language o de un parámetro de URL:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@Configuration
public class I18nConfig implements WebMvcConfigurer {
@Bean
public LocaleResolver localeResolver() {
AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
resolver.setDefaultLocale(Locale.ENGLISH);
return resolver;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang");
registry.addInterceptor(interceptor);
}
}
Ahora GET /greeting?name=World&lang=es devuelve la versión en español.
Traduzca archivos .properties de Java con PTC en 5 pasos
- Inicie un proyecto de PTC y elija su locale de origen (inglés /
messages.properties). - Suba sus archivos
.propertiesy establezca las rutas de salida. PTC analiza la estructura clave-valor, reconoce los marcadores de posición deMessageFormat({0},{1}) y los patrones deChoiceFormat, y lee cualquier comentario#como contexto para el traductor. - Añada una breve descripción de su aplicación Java y su público objetivo. PTC la utiliza para traducir con el tono y la terminología adecuados.
- Elija los idiomas de destino y confirme. La prueba cubre 20.000 palabras en 2 idiomas, sin tarjeta de crédito.
- Descargue los archivos
.propertiestraducidos desde la pestaña Files. Uno por idioma, con el sufijo correcto (messages_es.properties,messages_fr.properties). Estructuralmente idénticos al origen: mismas claves, mismos marcadores de posición, valores traducidos.
Colóquelos en src/main/resources/, vuelva a compilar y ResourceBundle.getBundle("messages", locale) detectará los nuevos idiomas automáticamente. Toda la configuración lleva unos 5 minutos.
Automatice la traducción de Java en cada lanzamiento con Git o la API de PTC
Traducir una vez es sencillo. Mantener las traducciones actualizadas a medida que su aplicación evoluciona es más difícil. Cada nueva cadena, cada actualización del texto, cada clave eliminada debe fluir hacia todos los idiomas. PTC ofrece dos formas de automatizarlo.
Integración con Git. Conecte su repositorio de GitHub, GitLab o Bitbucket a PTC. PTC monitoriza su archivo .properties de origen en busca de cambios. Cuando se añade o actualiza una cadena, PTC la traduce y devuelve los archivos actualizados a través de un merge request.
Integración con CI/CD. Si prefiere mantener todo dentro de su proceso de compilación existente, la API de PTC le permite subir su archivo de origen y recuperar las traducciones como parte de su trabajo de CI:
# .github/workflows/translate.yml
name: PTC translate
on:
push:
branches: [main]
paths:
- 'src/main/resources/messages.properties'
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Translate with PTC
run: |
cat > .ptc-config.yml <<'EOF'
source_locale: en
files:
- file: src/main/resources/messages.properties
output: src/main/resources/messages_{{lang}}.properties
EOF
curl -fsSL https://raw.githubusercontent.com/OnTheGoSystems/ptc-cli/main/ptc-cli.sh -o ptc-cli.sh
chmod +x ptc-cli.sh
./ptc-cli.sh --config-file .ptc-config.yml --api-token="${{ secrets.PTC_API_TOKEN }}"
PTC sincroniza las nuevas cadenas de origen, traduce solo lo que ha cambiado y abre un PR con los archivos messages_es.properties, messages_fr.properties actualizados, y así sucesivamente. Para los proyectos de Maven y Gradle, funciona el mismo flujo. A PTC no le importa su herramienta de compilación. Ambos enfoques significan que añadir un nuevo idioma más adelante es un cambio de configuración, no un nuevo proceso manual.
Revisión visual de la traducción de su aplicación Java traducida: publique sin control de calidad manual por idioma
Un archivo .properties traducido es necesario pero no suficiente. Ya sea que su aplicación Java sea un servicio web de Spring Boot que sirve HTML, una aplicación de escritorio Swing o una herramienta CLI del lado del servidor, el resultado renderizado puede tener problemas que ninguna revisión cadena por cadena puede detectar:
- Una etiqueta en alemán que desborda un botón de Swing.
- Un mensaje de validación en francés con la forma gramatical incorrecta.
- Una cadena hardcoded en inglés fuera de
messageSource.getMessage()que se muestra sin traducir.
AI Visual QA de PTC cubre ambas variantes de aplicaciones Java:
- Para Spring Boot o cualquier aplicación Java basada en web: instale la extensión de navegador de PTC y grabe un recorrido por las páginas críticas de su aplicación. PTC vuelve a ejecutarlo en cada idioma de destino después de cada actualización de traducción.
- Para aplicaciones de escritorio (Swing, JavaFX), de servidor (CLI) o cualquier aplicación Java que no sea de navegador: suba capturas de pantalla de la aplicación Java en ejecución en cada idioma de destino. La IA de visión de PTC inspecciona cada pantalla.
Los problemas que PTC puede solucionar en los archivos .properties (verbo/sustantivo, desbordamiento del diseño, acepción incorrecta) se solucionan automáticamente. Los problemas en su código Java (falta de llamada a messageSource.getMessage(), cadena hardcoded, concatenación de oraciones que debería usar MessageFormat) se devuelven como prompts listos para pegar para Cursor o Claude Code.
El resultado: un JAR multilingüe y verificado por lanzamiento. No solo archivos de propiedades traducidos.
Traduzca notas de lanzamiento, archivos README y correos electrónicos para clientes
Sus notas de lanzamiento, los archivos README en su repositorio interno de Maven o GitHub, los correos electrónicos dirigidos al cliente, la documentación de soporte y las páginas wiki internas se encuentran fuera de .properties. La función Paste to Translate de PTC procesa ese texto en el mismo proyecto. Pegue el texto de origen en el panel de control de PTC, elija los idiomas de destino y reciba traducciones que utilizan el mismo glosario y voz de marca que las cadenas dentro de la aplicación.
Traduzca datos empresariales, tickets de soporte y contenido del cliente con la API de PTC
Los datos empresariales, los tickets de soporte, las entradas de la base de conocimientos y el contenido enviado por el cliente necesitan traducción a medida que llegan. La API REST de PTC traduce este contenido bajo demanda con autenticación Bearer, utilizando el mismo glosario y voz de marca que sus traducciones de .properties.
PTC traduce su aplicación Java Y revisa el resultado en ejecución
Comience su prueba de 30 días: 20.000 palabras en 2 idiomas, sin tarjeta de crédito. Suba sus archivos .properties, obtenga versiones traducidas en minutos, luego suba capturas de pantalla (o instale la extensión de navegador para Spring Boot) y deje que PTC verifique la aplicación en ejecución.
Relacionado:
- Traducir aplicaciones Java con IA: resumen del servicio para equipos de Java.
- Referencia de la API de PTC: endpoints REST para la integración con CI.
- Localización de software con IA diseñada para pipelines de CI/CD: resumen del servicio para equipos de ingeniería.