PTC

Guía de internacionalización de Java: traducir archivos .properties con IA

Configure ResourceBundle, estructure archivos .properties, traduzca a más de 40 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 finalizar, tendrá un JAR multilingüe listo para producción, con cada idioma de destino verificado antes del lanzamiento. Para obtener una visión general 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 según la configuración regional del usuario.

Cuando su aplicación se ejecuta, ResourceBundle comprueba la configuración regional del usuario y carga el archivo correspondiente de forma automática. Si falta una traducción, recurre al archivo predeterminado de manera silenciosa. Nada se rompe, pero las traducciones faltantes tampoco aparecen como errores. Así se llama 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 fundamental.

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 antes del sufijo de configuración regional. 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 la organización:

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 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 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 para que sus archivos .properties estén listos para la traducción

Cada línea es un par clave-valor separado por =. La forma en que escriba su archivo de origen afecta directamente a la calidad de sus traducciones. Esto se aplica tanto si traduce manualmente como si utiliza 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 después de haber comenzado la traducción. Cambiar una clave deja huérfana la traducción existente.

2. Utilice marcadores de posición numerados, no concatenación de cadenas en el código

Escriba la frase 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 frases en fragmentos imposibilita una traducción correcta.

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 los archivos .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 introducido. ChoiceFormat es sencillo pero se limita a la coincidencia de rangos numéricos. No gestiona de forma nativa reglas de pluralidad complejas.

Para plurales que dependen del idioma (como el sistema one/few/many/other del polaco o las seis formas del árabe), utilice MessageFormat de 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 adecuadas para cada idioma de destino. El polaco recibe one / few / many / other. El japonés recibe solo other.

4. Escape =, :, # y \ con una barra invertida

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 \n para 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. Sin esto, los caracteres que no sean ASCII se corromperán y las traducciones resultarán ilegibles. Históricamente, los archivos .properties de Java eran ISO-8859-1, lo que requería escapes \uXXXX para caracteres no ASCII. Java 9 y versiones posteriores los leen como UTF-8 por defecto, así que compruebe su versión de tiempo de ejecución antes de confiar en UTF-8 puro.

6. Mantenga todo el texto orientado al usuario fuera del código

Si una cadena es visible para los usuarios, debe estar en un archivo .properties. Las cadenas hardcodeadas no se traducirán. Su aplicación acabará mostrando una mezcla de idiomas.

Formatee fechas, horas, números y monedas con asistentes que reconozcan la configuración regional

No todo lo que necesita localización reside 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 hacerlo bien es tan importante 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 que reconozcan la configuración regional. Nunca hardcodee "$", puntos o comas como separadores de miles, ni patrones "MM/DD/YYYY".

Conecte 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 mensajes de validación, plantillas de Thymeleaf y la resolución de la configuración regional 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/.

Uso 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 resolvedor de configuración regional 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

  1. Inicie un proyecto en PTC y elija su idioma de origen (inglés / messages.properties).
  2. Suba sus archivos .properties y establezca las rutas de salida. PTC analiza la estructura clave-valor, reconoce los marcadores de posición de MessageFormat ({0}, {1}) y los patrones de ChoiceFormat, y lee cualquier comentario con # como contexto para el traductor.
  3. Añada una breve descripción de su aplicación Java y su audiencia. PTC utiliza esto para traducir con el tono y la terminología adecuados.
  4. Elija los idiomas de destino y confirme. La prueba gratuita cubre 20.000 palabras en 2 idiomas, sin tarjeta de crédito.
  5. Descargue los archivos .properties traducidos desde la pestaña Archivos de recursos. 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/, recompile 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 de texto y cada clave eliminada debe reflejarse en todos los idiomas. PTC ofrece dos formas de automatizarlo.

Integración con Git. Conecte su repositorio de GitHub, GitLab o Bitbucket a PTC. PTC supervisa su archivo .properties de origen en busca de cambios. Cuando se añade o actualiza una cadena, PTC la traduce y entrega los archivos actualizados mediante una pull request.

Integración con CI/CD. Si prefiere mantener todo dentro de su proceso de compilación actual, la API de PTC le permite subir su archivo de origen y recuperar las traducciones como parte de su tarea 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: Trigger PTC translation
        run: |
          curl -X POST https://api.ptc.wpml.org/v1/projects/${{ secrets.PTC_PROJECT_ID }}/sync \
            -H "Authorization: Bearer ${{ secrets.PTC_API_KEY }}"

PTC sincroniza las nuevas cadenas de origen, traduce solo lo que ha cambiado y abre una PR con los archivos messages_es.properties, messages_fr.properties, etc., actualizados. Para proyectos Maven y Gradle, el flujo es el mismo. 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: lance 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 Spring Boot que sirve HTML, una aplicación de escritorio Swing o una herramienta de CLI en el servidor, el resultado renderizado puede presentar problemas que ninguna revisión a nivel de cadena puede detectar:

  • Una etiqueta en alemán que se desborda en un botón de Swing.
  • Un mensaje de validación en francés con una forma gramatical incorrecta.
  • Una cadena en inglés hardcodeada fuera de messageSource.getMessage() que aparece sin traducir.

AI Visual QA de PTC cubre ambos tipos 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 reproduce 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 corregir en los archivos .properties (verbo/sustantivo, desbordamiento de diseño, sentido incorrecto) se solucionan automáticamente. Los problemas en su código Java (falta de llamada a messageSource.getMessage(), cadena hardcodeada, concatenación de frases que debería usar MessageFormat) se devuelven como prompts listos para pegar en Cursor o Claude Code.

El resultado: un JAR multilingüe verificado por cada lanzamiento. No solo archivos de propiedades traducidos.

Traduzca notas de lanzamiento, archivos README y correos electrónicos de clientes

Sus notas de lanzamiento, archivos README en su repositorio interno de Maven o GitHub, correos electrónicos para clientes, documentación de soporte y páginas de wiki interna residen fuera de los archivos .properties. La función Pegar para traducir de PTC gestiona esos textos 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 utilicen el mismo glosario y voz de marca que las cadenas de su aplicación.

Traduzca datos empresariales, tickets de soporte y contenido de clientes 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 mediante token Bearer, utilizando el mismo glosario y voz de marca que las traducciones de sus archivos .properties.

PTC traduce su aplicación Java Y revisa el resultado en ejecución

Comience su prueba gratuita 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 y, a continuación, 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: