本文目录导读:

我将为您提供一个完整的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国际化的完整实现,包括基础文本翻译、日期/数字/货币格式化、复数规则处理等核心功能,您可以根据实际项目需求进行调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播