本文目录导读:

我将为您提供一个完整的Java国际化(i18n)案例,涵盖基础到进阶的使用方法。
项目结构
src/
├── main/
│ └── java/
│ └── com/example/i18n/
│ ├── Main.java
│ ├── InternationalizationDemo.java
│ └── DynamicResourceBundle.java
└── resources/
└── messages/
├── messages.properties (默认英文)
├── messages_zh_CN.properties (简体中文)
├── messages_zh_TW.properties (繁体中文)
├── messages_fr_FR.properties (法语)
└── messages_ja_JP.properties (日语)
资源文件
messages.properties(默认英文)
greeting=Hello, {0}!
farewell=Goodbye, {0}!
welcome=Welcome to our application
date.format=yyyy-MM-dd HH:mm:ss
current.date=Current date: {0,date,long}
balance=Your account balance is {0,number,currency}
items.in.cart=You have {0} items in your cart
online.users=Currently {0} users online
# 名词
user=User
admin=Administrator
guest=Guest
# 错误消息
error.required=Field {0} is required
error.invalid=Invalid {0} format
error.notfound={0} not found
# 菜单
menu.home=Home
menu.about=About
menu.services=Services
menu.contact=Contact
messages_zh_CN.properties(简体中文)
greeting=你好,{0}!
farewell=再见,{0}!
welcome=欢迎使用我们的应用程序
date.format=yyyy年MM月dd日 HH时mm分ss秒
current.date=当前日期:{0,date,long}
balance=您的账户余额为 {0,number,currency}
items.in.cart=您有 {0} 件商品在购物车中
online.users=当前有 {0} 个用户在线
# 名词
user=用户
admin=管理员
guest=访客
# 错误消息
error.required=字段 {0} 是必填项
error.invalid={0} 格式不正确
error.notfound=未找到{0}
# 菜单
menu.home=首页
menu.about=关于我们
menu.services=服务
menu.contact=联系方式
messages_zh_TW.properties(繁体中文)
greeting=你好,{0}!
farewell=再見,{0}!
welcome=歡迎使用我們的應用程式
date.format=yyyy年MM月dd日 HH時mm分ss秒
current.date=當前日期:{0,date,long}
balance=您的賬戶餘額為 {0,number,currency}
items.in.cart=您有 {0} 件商品在購物車中
online.users=當前有 {0} 個用戶在線
# 名詞
user=用戶
admin=管理員
guest=訪客
# 錯誤消息
error.required=字段 {0} 是必填項
error.invalid={0} 格式不正確
error.notfound=未找到{0}
# 菜單
menu.home=首頁
menu.about=關於我們
menu.services=服務
menu.contact=聯繫方式
messages_fr_FR.properties(法语)
greeting=Bonjour, {0} !
farewell=Au revoir, {0} !
welcome=Bienvenue dans notre application
date.format=dd/MM/yyyy HH:mm:ss
current.date=Date actuelle : {0,date,long}
balance=Votre solde est de {0,number,currency}
items.in.cart=Vous avez {0} articles dans votre panier
online.users=Il y a actuellement {0} utilisateurs en ligne
# 名词
user=Utilisateur
admin=Administrateur
guest=Invité
# 错误消息
error.required=Le champ {0} est requis
error.invalid=Format {0} invalide
error.notfound={0} introuvable
# 菜单
menu.home=Accueil
menu.about=À propos
menu.services=Services
menu.contact=Contact
messages_ja_JP.properties(日语)
greeting=こんにちは、{0}さん!
farewell=さようなら、{0}さん!
welcome=私たちのアプリケーションへようこそ
date.format=yyyy年MM月dd日 HH時mm分ss秒
current.date=現在の日付:{0,date,long}
balance=あなたの口座残高は {0,number,currency} です
items.in.cart=カートには {0} 個の商品があります
online.users=現在 {0} 人のユーザーがオンラインです
# 名词
user=ユーザー
admin=管理者
guest=ゲスト
# 错误消息
error.required=フィールド {0} は必須です
error.invalid={0} の形式が無効です
error.notfound={0} が見つかりません
# 菜单
menu.home=ホーム
menu.about=私たちについて
menu.services=サービス
menu.contact=お問い合わせ
Java代码实现
Main.java
package com.example.i18n;
import java.util.Locale;
import java.util.ResourceBundle;
public class Main {
public static void main(String[] args) {
// 基础演示
System.out.println("=== 国际化基础演示 ===");
InternationalizationDemo.demoBasic();
// 高级特性演示
System.out.println("\n=== 国际化高级特性 ===");
InternationalizationDemo.demoAdvanced();
// 动态资源绑定演示
System.out.println("\n=== 动态资源绑定 ===");
DynamicResourceBundle.demo();
// 浏览器语言检测模拟
System.out.println("\n=== 浏览器语言检测模拟 ===");
simulateBrowserLanguage();
}
private static void simulateBrowserLanguage() {
// 模拟不同的用户语言设置
String[] acceptLanguages = {"zh-CN,zh;q=0.9,en;q=0.8", "en-US,en;q=0.9", "ja-JP,ja;q=0.9,en;q=0.8"};
for (String acceptLanguage : acceptLanguages) {
Locale locale = detectLocaleFromHeader(acceptLanguage);
System.out.println("Accept-Language: " + acceptLanguage);
System.out.println("Detected Locale: " + locale.getDisplayName());
System.out.println("Language: " + locale.getLanguage());
System.out.println("Country: " + locale.getCountry());
System.out.println("---");
}
}
private static Locale detectLocaleFromHeader(String acceptLanguage) {
// 简单解析 Accept-Language 头
String[] languages = acceptLanguage.split(",");
String primary = languages[0].trim().split(";")[0];
String[] parts = primary.split("-");
if (parts.length == 2) {
return new Locale(parts[0], parts[1]);
} else {
return new Locale(primary);
}
}
}
InternationalizationDemo.java
package com.example.i18n;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
public class InternationalizationDemo {
// 基础演示
public static void demoBasic() {
// 支持的语言列表
String[] supportedLocales = {"en", "zh_CN", "zh_TW", "fr_FR", "ja_JP"};
for (String localeString : supportedLocales) {
Locale locale = Locale.forLanguageTag(localeString.replace("_", "-"));
ResourceBundle bundle = ResourceBundle.getBundle("messages", locale);
System.out.println("\n=== " + locale.getDisplayName() + " ===");
// 基础文本
System.out.println(bundle.getString("welcome"));
System.out.println(MessageFormat.format(bundle.getString("greeting"), "John"));
System.out.println(MessageFormat.format(bundle.getString("farewell"), "John"));
// 菜单
System.out.println("Menu: " +
bundle.getString("menu.home") + " | " +
bundle.getString("menu.about") + " | " +
bundle.getString("menu.services") + " | " +
bundle.getString("menu.contact"));
}
}
// 高级特性演示
public static void demoAdvanced() {
// 演示日期和数字格式化
demoDateFormatting();
demoNumberFormatting();
// 演示复数规则
demoPluralRules();
// 演示选择格式
demoChoiceFormat();
// 演示货币格式化
demoCurrencyFormatting();
// 演示百分比格式化
demoPercentFormatting();
}
private static void demoDateFormatting() {
System.out.println("\n--- 日期格式化 ---");
Locale[] locales = {
Locale.ENGLISH, Locale.CHINA, Locale.TAIWAN,
Locale.FRANCE, Locale.JAPAN
};
Date now = new Date();
for (Locale locale : locales) {
DateFormat shortFormat = DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.SHORT, locale);
DateFormat longFormat = DateFormat.getDateTimeInstance(
DateFormat.LONG, DateFormat.LONG, locale);
System.out.println(locale.getDisplayName() + ":");
System.out.println(" 短格式: " + shortFormat.format(now));
System.out.println(" 长格式: " + longFormat.format(now));
}
}
private static void demoNumberFormatting() {
System.out.println("\n--- 数字格式化 ---");
double num = 1234567.89;
Locale[] locales = {
Locale.ENGLISH, Locale.CHINA, Locale.TAIWAN,
Locale.FRANCE, Locale.JAPAN
};
for (Locale locale : locales) {
NumberFormat nf = NumberFormat.getNumberInstance(locale);
System.out.println(locale.getDisplayName() + ": " + nf.format(num));
}
}
private static void demoCurrencyFormatting() {
System.out.println("\n--- 货币格式化 ---");
double amount = 1234567.89;
Locale[] locales = {
Locale.US, Locale.CHINA, Locale.TAIWAN,
Locale.FRANCE, Locale.JAPAN
};
for (Locale locale : locales) {
NumberFormat cf = NumberFormat.getCurrencyInstance(locale);
System.out.println(locale.getDisplayName() + ": " + cf.format(amount));
}
}
private static void demoPercentFormatting() {
System.out.println("\n--- 百分比格式化 ---");
double percent = 0.8567;
Locale[] locales = {
Locale.US, Locale.CHINA, Locale.FRANCE, Locale.JAPAN
};
for (Locale locale : locales) {
NumberFormat pf = NumberFormat.getPercentInstance(locale);
pf.setMaximumFractionDigits(2);
System.out.println(locale.getDisplayName() + ": " + pf.format(percent));
}
}
private static void demoPluralRules() {
System.out.println("\n--- 复数规则演示 ---");
String pattern = "你有一件物品|你有{0}件物品|你有{0}件物品";
for (int i = 0; i <= 5; i++) {
String[] parts = pattern.split("\\|");
String result;
if (i == 0) {
result = "你没有任何物品";
} else if (i == 1) {
result = "你有一件物品";
} else {
result = "你有" + i + "件物品";
}
System.out.println(i + " -> " + result);
}
}
private static void demoChoiceFormat() {
System.out.println("\n--- 选择格式 (ChoiceFormat) ---");
java.text.ChoiceFormat cf = new java.text.ChoiceFormat(
"0#没有用户|1#一个用户|2#两个用户|2<多个用户"
);
for (int i = 0; i <= 5; i++) {
System.out.println(i + " users: " + cf.format(i));
}
}
}
DynamicResourceBundle.java
package com.example.i18n;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.MissingResourceException;
public class DynamicResourceBundle {
public static void demo() {
// 演示动态语言切换
String[] locales = {"en", "zh_CN", "fr_FR"};
for (String localeString : locales) {
Locale locale = Locale.forLanguageTag(localeString.replace("_", "-"));
System.out.println("\n--- 切换到 " + locale.getDisplayName() + " ---");
// 创建资源绑定
ResourceBundle bundle = getBundle(locale);
// 演示完整的业务流程
simulateUserInterface(bundle, locale);
}
}
private static ResourceBundle getBundle(Locale locale) {
try {
return ResourceBundle.getBundle("messages", locale);
} catch (MissingResourceException e) {
System.err.println("警告: 找不到对应的资源文件,使用默认语言");
return ResourceBundle.getBundle("messages", Locale.ENGLISH);
}
}
private static void simulateUserInterface(ResourceBundle bundle, Locale locale) {
// 模拟用户界面
System.out.println("=== 用户界面模拟 ===");
// 登录界面
System.out.println("--- 登录界面 ---");
System.out.println(bundle.getString("welcome"));
System.out.println("用户名: John");
// 显示信息
System.out.println("--- 用户信息 ---");
// 日期格式化
java.text.DateFormat dateFormat = java.text.DateFormat.getDateInstance(
java.text.DateFormat.MEDIUM, locale);
Date now = new Date();
System.out.println(bundle.getString("current.date") + " " + dateFormat.format(now));
// 货币格式化
java.text.NumberFormat currencyFormat = java.text.NumberFormat.getCurrencyInstance(locale);
System.out.println(MessageFormat.format(bundle.getString("balance"),
currencyFormat.format(12345.67)));
// 数字格式化
java.text.NumberFormat numberFormat = java.text.NumberFormat.getNumberInstance(locale);
System.out.println(MessageFormat.format(bundle.getString("items.in.cart"),
numberFormat.format(3)));
// 错误消息
System.out.println("--- 错误消息 ---");
System.out.println(MessageFormat.format(bundle.getString("error.required"),
bundle.getString("user")));
System.out.println(MessageFormat.format(bundle.getString("error.invalid"),
"Email"));
// 菜单
System.out.println("--- 菜单 ---");
System.out.println("1. " + bundle.getString("menu.home"));
System.out.println("2. " + bundle.getString("menu.about"));
System.out.println("3. " + bundle.getString("menu.services"));
System.out.println("4. " + bundle.getString("menu.contact"));
}
}
运行结果示例
运行程序后,您将看到类似以下的输出:
=== 国际化基础演示 ===
=== English ===
Welcome to our application
Hello, John!
Goodbye, John!
Menu: Home | About | Services | Contact
=== 中文 (中国) ===
欢迎使用我们的应用程序
你好,John!
再见,John!
Menu: 首页 | 关于我们 | 服务 | 联系方式
=== 中文 (台湾) ===
歡迎使用我們的應用程式
你好,John!
再見,John!
Menu: 首頁 | 關於我們 | 服務 | 聯繫方式
=== 法语 (法国) ===
Bienvenue dans notre application
Bonjour, John !
Au revoir, John !
Menu: Accueil | À propos | Services | Contact
=== 日语 (日本) ===
私たちのアプリケーションへようこそ
こんにちは、Johnさん!
さようなら、Johnさん!
Menu: ホーム | 私たちについて | サービス | お問い合わせ
=== 国际化高级特性 ===
--- 日期格式化 ---
English: 1/16/24, 10:30 AM
中文 (中国): 2024年1月16日 上午10时30分
中文 (台湾): 2024年1月16日 上午10時30分
法语 (法国): 16/01/2024 10:30
日语 (日本): 2024/01/16 10:30
--- 数字格式化 ---
English: 1,234,567.89
中文 (中国): 1,234,567.89
中文 (台湾): 1,234,567.89
法语 (法国): 1 234 567,89
日语 (日本): 1,234,567.89
--- 货币格式化 ---
美国: $1,234,567.89
中国: ¥1,234,567.89
台湾: NT$1,234,567.89
法国: 1 234 567,89 €
日本: ¥1,234,567.89
...
关键知识点总结
1 资源文件命名规则
- 基础名称:
messages.properties - 特定语言:
messages_zh_CN.properties - 特定地区:
messages_zh_TW.properties
2 主要类
Locale: 表示特定的地理、政治或文化区域ResourceBundle: 加载和管理资源文件MessageFormat: 格式化包含占位符的消息NumberFormat: 格式化数字、货币、百分比DateFormat: 格式化日期和时间
3 最佳实践
// 1. 使用常量定义Locale
public class LocaleConstants {
public static final Locale ENGLISH = Locale.US;
public static final Locale CHINESE = Locale.CHINA;
public static final Locale JAPANESE = Locale.JAPAN;
}
// 2. 封装资源访问
public class I18nManager {
private static ResourceBundle bundle;
public static String getString(String key) {
return bundle.getString(key);
}
public static String getFormattedString(String key, Object... args) {
return MessageFormat.format(bundle.getString(key), args);
}
}
// 3. 使用属性模式(推荐)
public class Messages {
private static final String BASE_NAME = "messages";
public static String get(String key, Locale locale) {
return ResourceBundle.getBundle(BASE_NAME, locale).getString(key);
}
public static String get(String key, Locale locale, Object... args) {
return MessageFormat.format(get(key, locale), args);
}
}
这个案例展示了Java国际化的完整实现,包括基础文本翻译、日期/数字/货币格式化、复数规则处理等核心功能,您可以根据实际项目需求进行调整和扩展。