Guía de internacionalización de Java: Traduzca archivos .properties con IA
Configure ResourceBundle, estructure los archivos .properties, traduzca a más de 40 idiomas con IA y, a continuación, haga 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 obtener una descripción general del servicio de Java independiente, consulte traducir aplicaciones Java con IA.
ResourceBundle carga el archivo .properties correcto en tiempo de ejecución
El sistema de internacionalización 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 según el 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 faltantes tampoco aparecen como errores. Para llamar 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 ocurre 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 del archivo anterior al sufijo del locale. Es lo que ResourceBundle.getBundle() utiliza 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 variables:
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 manualmente como con una herramienta de IA como PTC.
1. Utilice claves claras y descriptivas que indiquen 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 una vez iniciada 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 imposible la traducción correcta.
3. Procese 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 según el valor proporcionado. ChoiceFormat es simple 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 en á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 para cada 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:separa las claves de los valores.#o!inicia un comentario.\introduce secuencias de escape (como\npara un salto de línea).
Escape 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. De lo contrario, los caracteres que no son ASCII se corrompen y las traducciones se vuelven ilegibles. Históricamente, los archivos .properties de Java usaban ISO-8859-1, lo que requería escapes \uXXXX para los caracteres que no eran ASCII. Java 9+ los lee como UTF-8 de forma predeterminada, así que compruebe su versión del entorno de ejecución antes de depender del formato UTF-8 sin procesar.
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 incrustadas en el código no se traducirán. Su aplicación terminará mostrando una mezcla de idiomas.
Formatee fechas, horas, números y moneda 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 hacer esto 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 incruste en el código "$", separadores de miles "," o 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.
Configure 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. bajo 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 desde el encabezado Accept-Language o 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 configure las rutas de salida. PTC analiza la estructura de clave-valor, reconoce los marcadores de posición deMessageFormat({0},{1}) y los patrones deChoiceFormat, y lee cualquier comentario de#como contexto para el traductor. - Añada una breve descripción de su aplicación Java y su público. PTC usa esto 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) reconocerá 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 cadena nueva, cada actualización de texto, cada clave eliminada debe propagarse a 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 mediante 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.
Haga commit de un .ptc-config.yml que nombre su archivo de origen y a dónde pertenecen las traducciones:
# .ptc-config.yml
source_locale: en
files:
- file: src/main/resources/messages.properties
output: src/main/resources/messages_{{lang}}.properties
Luego añada la acción PTC Translate a su flujo de trabajo. Lleva una versión fijada de la CLI de PTC en su interior, por lo que su compilación no descarga nada en tiempo de ejecución:
# .github/workflows/translate.yml
name: Translate
on:
push:
branches: [main]
paths:
- 'src/main/resources/messages.properties'
workflow_dispatch: {}
jobs:
translate:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: OnTheGoSystems/ptc-action@v1
with:
api-token: ${{ secrets.PTC_API_TOKEN }}
create-pr: true
PTC sincroniza las nuevas cadenas de origen, traduce solo lo que ha cambiado y abre un PR con los 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: 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 en inglés incrustada en el código fuera de
messageSource.getMessage()que se muestra sin traducir.
El 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 lo vuelve a ejecutar 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 de diseño, acepción incorrecta) se solucionan automáticamente. Los problemas en su código Java (falta de llamada a messageSource.getMessage(), cadena incrustada en el código, concatenación de oraciones que debería usar MessageFormat) regresan como prompts listos para pegar para Cursor o Claude Code.
El resultado: un JAR multilingüe verificado por lanzamiento. No solo archivos properties traducidos.
Traduzca notas de lanzamiento, archivos README y correos electrónicos para clientes
Sus notas de lanzamiento, archivos README en su repositorio interno de Maven o GitHub, correos electrónicos dirigidos a clientes, documentación de soporte y páginas wiki internas viven 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 usan el mismo glosario y voz de marca que sus 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 los clientes necesitan traducción a medida que llegan. La API REST de PTC traduce este contenido bajo demanda con autenticación Bearer, usando 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 las 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:
- Traduzca aplicaciones Java con IA: descripción general del servicio para equipos de Java.
- Referencia de la API de PTC: endpoints de la API REST para la integración con CI.
- Localización de software con IA diseñada para pipelines de CI/CD: descripción general del servicio para equipos de ingeniería.