Guia de internacionalização em Java: traduza arquivos .properties com IA
Configure o ResourceBundle, estruture os arquivos .properties, traduza para 40+ idiomas com IA e, em seguida, deixe a PTC (Private Translation Cloud) revisar o aplicativo Java em execução por meio de capturas de tela ou da extensão do navegador. No final, você terá um JAR multilíngue pronto para publicar, com cada idioma de destino verificado antes do lançamento. Para a visão geral do serviço Java autônomo, consulte traduzir aplicativos Java com IA.
O ResourceBundle carrega o arquivo .properties correto em tempo de execução
O sistema de i18n do Java é construído em torno de duas coisas. Os arquivos .properties que armazenam suas strings traduzidas e a classe ResourceBundle que carrega o arquivo correto em tempo de execução com base no locale do usuário.
Quando seu aplicativo é executado, o ResourceBundle verifica o locale do usuário e carrega o arquivo correspondente automaticamente. Se faltar uma tradução, ele faz o fallback para o arquivo padrão silenciosamente. Nada quebra, mas as traduções ausentes também não aparecem como erros. Chamando uma string no código:
ResourceBundle bundle = ResourceBundle.getBundle("messages", Locale.FRENCH);
String greeting = bundle.getString("welcome.message");
Esse é todo o mecanismo. O resto do trabalho de localização acontece nos próprios arquivos .properties, e é por isso que estruturá-los corretamente é importante.
Configure seu resource bundle com messages_{locale}.properties
Um resource bundle é um conjunto de arquivos .properties que compartilham um nome base comum. O nome base é a parte do nome do arquivo antes do sufixo de locale. É o que o ResourceBundle.getBundle() usa para encontrar o arquivo correto em tempo de execução.
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)
Aplicativos maiores frequentemente usam múltiplos resource bundles para manter as coisas organizadas:
src/main/resources/
messages.properties
errors.properties
emails.properties
O Java espera um padrão de nomenclatura específico: basename_language.properties, ou basename_language_COUNTRY.properties para variantes regionais:
messages_fr.properties # French
messages_fr_CA.properties # French (Canada)
messages_pt_BR.properties # Portuguese (Brazil)
Os códigos de idioma seguem a ISO 639-1. Os códigos de país seguem a ISO 3166-1. Usar o formato errado significa que o ResourceBundle não encontrará o arquivo em tempo de execução.
Carregue e use o bundle no código, com MessageFormat para substituição de placeholders:
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 strings simples sem placeholders, messages.getString("key") é suficiente.
Seis convenções que deixam seus arquivos .properties prontos para tradução
Cada linha é um par chave-valor separado por =. A forma como você escreve seu arquivo de origem afeta diretamente a qualidade das suas traduções. Isso vale quer você traduza manualmente ou com uma ferramenta de IA como a PTC.
1. Use chaves claras e descritivas que nomeiam onde a string aparece
As chaves devem deixar óbvio onde e como uma string é usada. Isso é importante quando você está gerenciando centenas de strings em vários arquivos.
# Incorrect
btn1 = Submit
msg2 = Error
# Correct
form.submit.button = Submit
error.login.invalid_credentials = Invalid username or password
Nunca altere uma chave depois que a tradução tiver começado. Alterar uma chave desvincula a tradução existente.
2. Use placeholders numerados, não concatenação de strings no código
Escreva a frase completa no seu arquivo .properties e use placeholders numerados para conteúdo variável em vez de concatenar strings no código.
// Incorrect (in code)
"Hello, " + username + "! You have " + count + " new messages."
# Correct (in .properties)
dashboard.greeting = Hello, {0}! You have {1} new messages.
Muitos idiomas mudam a ordem das palavras e as regras de concordância, portanto, dividir frases em fragmentos torna a tradução correta impossível.
3. Lide com a pluralização usando ChoiceFormat, ICU ou chaves com sufixo
Para pluralização no Java padrão, o ChoiceFormat funciona diretamente dentro do .properties:
messages.count = {0,choice,0#no messages|1#one message|1<{0} messages}
O Java processa isso em tempo de execução e retorna a forma correta com base no valor passado. O ChoiceFormat é simples, mas limitado à correspondência de intervalos numéricos. Ele não lida nativamente com regras complexas de plural.
Para plurais sensíveis ao idioma (one/few/many/other do polonês, as seis formas do árabe), use o MessageFormat da ICU4J:
String pattern = "{0, plural, one {# note} other {# notes}}";
String result = new com.ibm.icu.text.MessageFormat(pattern, locale).format(new Object[]{count});
Ou codifique os plurais como chaves separadas com sufixos convencionais para que a PTC possa gerar as categorias de plural corretas por idioma:
notes.count.zero=No notes yet
notes.count.one={0} note
notes.count.other={0} notes
A PTC gera as categorias de plural corretas por idioma de destino. O polonês recebe one / few / many / other. O japonês recebe apenas other.
4. Escape =, :, # e \ com uma barra invertida
Caracteres como =, :, # e \ têm um significado especial em arquivos .properties:
=ou:separa chaves de valores.#ou!inicia um comentário.\introduz sequências de escape (como\npara nova linha).
Escape com uma barra invertida onde for necessário:
support.link = Visit us at https\://support.example.com
5. Salve os arquivos .properties em UTF-8
Sempre salve os arquivos .properties em UTF-8. Sem isso, caracteres não ASCII ficam corrompidos e as traduções se tornam ilegíveis. Historicamente, os arquivos .properties do Java eram ISO-8859-1, exigindo escapes \uXXXX para caracteres não ASCII. O Java 9+ os lê como UTF-8 por padrão, então verifique sua versão de tempo de execução antes de depender do UTF-8 puro.
6. Mantenha todo o texto voltado para o usuário fora do código
Se uma string é visível para os usuários, ela pertence a um arquivo .properties. Strings hardcoded não serão traduzidas. Seu aplicativo acabará mostrando uma mistura de idiomas.
Formate datas, horas, números e moedas com auxiliares sensíveis ao locale
Nem tudo que precisa de localização vive em um arquivo .properties. Datas, horas, números e valores monetários são formatados no código em tempo de execução, e acertá-los é tão importante quanto suas strings traduzidas.
Datas com 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"
Moedas com 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 €"
Sempre use formatadores sensíveis ao locale. Nunca deixe "$", separadores de milhares "," ou padrões "MM/DD/YYYY" hardcoded.
Conecte o ResourceBundle ao Spring Boot com MessageSource
O Spring Boot envolve o ResourceBundle em um bean MessageSource que se integra aos recursos de i18n do framework. Ele também cobre mensagens de validação, templates do Thymeleaf e resolução de locale de requisições web.
Configure no 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. em src/main/resources/.
Use em um controller:
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 o resolvedor de locale para ler do cabeçalho Accept-Language ou de um 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);
}
}
Agora o GET /greeting?name=World&lang=es retorna a versão em espanhol.
Traduza arquivos .properties do Java com a PTC em 5 passos
- Inicie um projeto na PTC e escolha seu locale de origem (inglês /
messages.properties). - Faça o upload dos seus arquivos
.propertiese defina os caminhos de saída. A PTC analisa a estrutura de chave-valor, reconhece placeholdersMessageFormat({0},{1}) e padrõesChoiceFormat, e lê quaisquer comentários#como contexto para o tradutor. - Adicione uma breve descrição do seu aplicativo Java e público. A PTC usa isso para traduzir com o tom e a terminologia corretos.
- Escolha os idiomas de destino e confirme. O teste cobre 20.000 palavras para 2 idiomas, sem cartão de crédito.
- Baixe os arquivos
.propertiestraduzidos da aba Files. Um por idioma, com o sufixo correto (messages_es.properties,messages_fr.properties). Estruturalmente idênticos à origem: mesmas chaves, mesmos placeholders, valores traduzidos.
Solte-os em src/main/resources/, recompile, e o ResourceBundle.getBundle("messages", locale) detecta os novos idiomas automaticamente. Toda a configuração leva cerca de 5 minutos.
Automatize a tradução em Java a cada lançamento com Git ou a API da PTC
Traduzir uma vez é simples. Manter as traduções atualizadas à medida que seu aplicativo evolui é mais difícil. Cada nova string, cada atualização de texto, cada chave removida precisa fluir para todos os idiomas. A PTC oferece duas maneiras de automatizar isso.
Integração com Git. Conecte seu repositório do GitHub, GitLab ou Bitbucket à PTC. A PTC monitora seu arquivo .properties de origem em busca de alterações. Quando uma string é adicionada ou atualizada, a PTC a traduz e entrega os arquivos atualizados de volta via um merge request.
Integração com CI/CD. Se você prefere manter tudo dentro do seu processo de build existente, a API da PTC permite que você envie seu arquivo de origem e recupere as traduções como parte da sua tarefa 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 }}"
A PTC sincroniza as novas strings de origem, traduz apenas o que mudou e abre um PR com os arquivos messages_es.properties, messages_fr.properties atualizados, e assim por diante. Para projetos Maven e Gradle, o mesmo fluxo funciona. A PTC não se importa com a sua ferramenta de build. Ambas as abordagens significam que adicionar um novo idioma mais tarde é uma alteração de configuração, não um novo processo manual.
Revisão visual de tradução do seu aplicativo Java traduzido - publique sem QA manual por idioma
Um arquivo .properties traduzido é necessário, mas não suficiente. Quer o seu aplicativo Java seja um serviço web Spring Boot servindo HTML, um aplicativo desktop Swing ou uma ferramenta de CLI do lado do servidor, o resultado renderizado pode ter problemas que nenhuma revisão por string consegue capturar:
- Um rótulo em alemão que causa um estouro em um botão do Swing.
- Uma mensagem de validação em francês com a forma gramatical incorreta.
- Uma string hardcoded em inglês fora do
messageSource.getMessage()que aparece não traduzida.
O AI Visual QA da PTC cobre ambas as variantes de aplicativos Java:
- Para Spring Boot ou qualquer aplicativo Java baseado na web: instale a extensão do navegador da PTC e faça um percurso gravado das páginas críticas do seu aplicativo. A PTC o reproduz em todos os idiomas de destino após cada atualização de tradução.
- Para desktop (Swing, JavaFX), servidor (CLI) ou qualquer aplicativo Java sem navegador: faça o upload de capturas de tela do aplicativo Java em execução em cada idioma de destino. A IA de visão da PTC inspeciona cada tela.
Os problemas que a PTC pode corrigir nos arquivos .properties (verbo/substantivo, estouro de layout, acepção incorreta) são corrigidos automaticamente. Problemas no seu código Java (chamada messageSource.getMessage() ausente, string hardcoded, concatenação de frases que deveria usar MessageFormat) retornam como prompts prontos para colar para o Cursor ou Claude Code.
O resultado: um JAR multilíngue verificado por lançamento. Não apenas arquivos de propriedades traduzidos.
Traduza notas de lançamento, READMEs e e-mails para clientes
Suas notas de lançamento, READMEs no seu repositório Maven interno ou GitHub, e-mails voltados para o cliente, documentação de suporte e páginas de wiki internas vivem fora do .properties. O recurso Paste to Translate da PTC lida com esse texto no mesmo projeto. Cole o texto de origem no painel da PTC, escolha os idiomas de destino e receba de volta traduções que usam o mesmo glossário e voz da marca que as suas strings no aplicativo.
Traduza dados corporativos, tickets de suporte e conteúdo do cliente com a API da PTC
Dados corporativos, tickets de suporte, entradas de base de conhecimento e conteúdo do cliente enviado precisam de tradução assim que chegam. A API REST da PTC traduz esse conteúdo sob demanda com autenticação por token Bearer, usando o mesmo glossário e voz da marca que as suas traduções em .properties.
A PTC traduz o seu aplicativo Java E revisa o resultado em execução
Comece seu teste de 30 dias - 20.000 palavras para 2 idiomas, sem cartão de crédito. Faça o upload dos seus arquivos .properties, obtenha versões traduzidas em minutos, depois faça o upload de capturas de tela (ou instale a extensão do navegador para Spring Boot) e deixe a PTC verificar o aplicativo em execução.
Relacionados:
- Traduzir aplicativos Java com IA - visão geral do serviço para equipes Java.
- Referência da API da PTC - endpoints da API REST para integração com CI.
- Localização de software por IA construída para pipelines de CI/CD - visão geral do serviço para equipes de engenharia.