第14章:国际化(i18n)

第14章:国际化(i18n)


作者:步子哥 (steper@foxmail.com)


14.1 为什么需要国际化?

不同语言的用户

// 不支持国际化
Label label = new Label(shell, SWT.NONE);
label.setText("Hello, World!");  // 只支持英文

// 支持国际化
Label label = new Label(shell, SWT.NONE);
label.setText(getMessage("greeting"));  // 根据语言显示不同文本

费曼解释:国际化的重要性

国际化 = 多语言菜单
- 英语菜单:Hello, World!
- 中文菜单:你好,世界!
- 西班牙语菜单:Hola, Mundo!
- 不同语言的用户看到不同菜单

类比:
国际化 = 多语言说明书
- 英语说明书:English Manual
- 中文说明书:中文说明书
- 西班牙语说明书:Manual en Español
- 不同语言的用户看到不同说明书

日期、数字格式的差异

// 英语格式(美国)
SimpleDateFormat enDateFormat = new SimpleDateFormat("MM/dd/yyyy");
System.out.println(enDateFormat.format(new Date()));  // 01/13/2026

// 中文格式(中国)
SimpleDateFormat zhDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
System.out.println(zhDateFormat.format(new Date()));  // 2026年01月13日

// 英语格式(数字)
DecimalFormat enNumberFormat = new DecimalFormat("#,##0.00");
System.out.println(enNumberFormat.format(1234567.89));  // 1,234,567.89

// 中文格式(数字)
DecimalFormat zhNumberFormat = new DecimalFormat("#,##0.00");
System.out.println(zhNumberFormat.format(1234567.89));  // 1,234,567.89

费曼解释:不同地区的格式差异

日期格式 = 写日记的格式
- 英语(美国):01/13/2026(月/日/年)
- 中文(中国):2026年01月13日(年/月/日)
- 西班牙语(西班牙):13/01/2026(日/月/年)

数字格式 = 写数字的格式
- 英语(美国):1,234,567.89(千分位逗号,小数点)
- 中文(中国):1,234,567.89(千分位逗号,小数点)
- 德语(德国):1.234.567,89(千分位点号,逗号)

类比:
日期格式 = 日历格式
- 美国日历:01/13/2026
- 中国日历:2026年01月13日
- 西班牙日历:13/01/2026

数字格式 = 账本格式
- 美国账本:1,234,567.89
- 中国账本:1,234,567.89
- 德国账本:1.234.567,89

代码示例:国际化的重要性

public class I18nExample {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("国际化示例");
        shell.setLayout(new GridLayout(1, false));
        
        // 不支持国际化
        Label noI18nLabel = new Label(shell, SWT.WRAP);
        noI18nLabel.setText("不支持国际化:只显示英文 \"Hello, World!\"");
        GridData labelData = new GridData();
        labelData.horizontalAlignment = GridData.FILL;
        labelData.grabExcessHorizontalSpace = true;
        noI18nLabel.setLayoutData(labelData);
        
        // 支持国际化
        Label i18nLabel = new Label(shell, SWT.WRAP);
        i18nLabel.setText("支持国际化:根据用户语言显示不同文本");
        i18nLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        
        // 选择语言
        Composite languagePanel = new Composite(shell, SWT.NONE);
        languagePanel.setLayout(new FillLayout(SWT.HORIZONTAL));
        
        Button enButton = new Button(languagePanel, SWT.PUSH);
        enButton.setText("英语");
        enButton.addListener(SWT.Selection, event -> {
            Locale locale = Locale.US;
            showLocalizedMessage(locale);
        });
        
        Button zhButton = new Button(languagePanel, SWT.PUSH);
        zhButton.setText("中文");
        zhButton.addListener(SWT.Selection, event -> {
            Locale locale = Locale.CHINA;
            showLocalizedMessage(locale);
        });
        
        Button esButton = new Button(languagePanel, SWT.PUSH);
        esButton.setText("西班牙语");
        esButton.addListener(SWT.Selection, event -> {
            Locale locale = new Locale("es", "ES");
            showLocalizedMessage(locale);
        });
        
        // 显示当前系统语言
        Button systemButton = new Button(shell, SWT.PUSH);
        systemButton.setText("显示系统语言");
        systemButton.addListener(SWT.Selection, event -> {
            Locale systemLocale = Locale.getDefault();
            showLocalizedMessage(systemLocale);
        });
        
        shell.setBounds(100, 100, 500, 200);
        shell.open();
        
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        
        display.dispose();
    }
    
    private static void showLocalizedMessage(Locale locale) {
        String language = locale.getDisplayLanguage();
        String country = locale.getDisplayCountry();
        String greeting = getGreeting(locale);
        String date = getFormattedDate(locale);
        String number = getFormattedNumber(locale);
        
        String message = String.format(
            "语言:%s\n地区:%s\n\n问候:%s\n日期:%s\n数字:1,234,567.89",
            language, country, greeting, date
        );
        
        System.out.println(message);
    }
    
    private static String getGreeting(Locale locale) {
        String language = locale.getLanguage();
        
        switch (language) {
            case "en":
                return "Hello, World!";
            case "zh":
                return "你好,世界!";
            case "es":
                return "Hola, Mundo!";
            default:
                return "Hello, World!";
        }
    }
    
    private static String getFormattedDate(Locale locale) {
        DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, locale);
        return dateFormat.format(new Date());
    }
    
    private static String getFormattedNumber(Locale locale) {
        NumberFormat numberFormat = NumberFormat.getInstance(locale);
        return numberFormat.format(1234567.89);
    }
}

14.2 资源束(ResourceBundle)的使用

创建属性文件

messages.properties(英语)

greeting=Hello, World!
welcome=Welcome to my application!
name=Name:
email=Email:
save=Save
cancel=Cancel
exit=Exit

messages_zh.properties(中文)

greeting=\u4f60\u597d\uff0c\u4e16\u754c\uff01
welcome=\u6b22\u8fce\u4f7f\u7528\u6211\u7684\u5e94\u7528\uff01
name=\u59d3\u540d\uff1a
email=\u90ae\u7bb1\uff1a
save=\u4fdd\u5b58
cancel=\u53d6\u6d88
exit=\u9000\u51fa

messages_es.properties(西班牙语)

greeting=Hola, Mundo!
welcome=¡Bienvenido a mi aplicación!
name=Nombre:
email=Correo electrónico:
save=Guardar
cancel=Cancelar
exit=Salir

费曼解释:属性文件的命名规则

属性文件命名 = 命名规范
- messages.properties:默认(英语)
- messages_zh.properties:中文
- messages_es.properties:西班牙语
- messages_fr.properties:法语
- 格式:messages_语言_地区.properties

类比:
属性文件命名 = 多语言书名
- 英文书:The Lord of the Rings
- 中文书:魔戒
- 西班牙语书:El Señor de los Anillos
- 法语书:Le Seigneur des Anneaux

加载资源

// 加载默认资源(英语)
ResourceBundle bundle = ResourceBundle.getBundle("messages");

// 加载指定语言的资源
Locale locale = new Locale("zh", "CN");
ResourceBundle zhBundle = ResourceBundle.getBundle("messages", locale);

// 获取资源
String greeting = bundle.getString("greeting");
System.out.println("问候:" + greeting);  // Hello, World!

String zhGreeting = zhBundle.getString("greeting");
System.out.println("中文问候:" + zhGreeting);  // 你好,世界!

费曼解释:ResourceBundle 的加载机制

ResourceBundle = 多语言书库
- 你要借一本书(加载资源)
- 你告诉图书管理员:你要什么语言(Locale)
- 图书管理员给你对应语言的书(ResourceBundle)
- 你阅读书中的内容(getString)

类比:
ResourceBundle = 多语言菜单
- 你要点菜(加载资源)
- 你告诉服务员:你要什么语言菜单(Locale)
- 服务员给你对应语言的菜单(ResourceBundle)
- 你点菜单上的菜(getString)

占位符替换

// 属性文件
// welcome=Welcome, {0}!

// 加载资源
ResourceBundle bundle = ResourceBundle.getBundle("messages");

// 替换占位符
String welcome = MessageFormat.format(bundle.getString("welcome"), "John");
System.out.println("欢迎:" + welcome);  // Welcome, John!

费曼解释:占位符的原理

占位符 = 填空题
- 题目:Welcome, {0}!
- 答案:John
- 填空:Welcome, John!

类比:
占位符 = 邮件模板
- 模板:尊敬的 {0} 先生/女士:
- 填写:尊敬的 John 先生/女士:

代码示例:资源束的使用

public class ResourceBundleExample {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("资源束示例");
        shell.setLayout(new GridLayout(1, false));
        
        // 加载资源
        ResourceBundle bundle = ResourceBundle.getBundle("messages");
        
        // 显示问候
        Label greetingLabel = new Label(shell, SWT.WRAP | SWT.CENTER);
        greetingLabel.setText(bundle.getString("greeting"));
        GridData greetingData = new GridData();
        greetingData.horizontalAlignment = GridData.FILL;
        greetingData.grabExcessHorizontalSpace = true;
        greetingLabel.setLayoutData(greetingData);
        
        // 显示欢迎
        Label welcomeLabel = new Label(shell, SWT.WRAP | SWT.CENTER);
        String welcome = MessageFormat.format(bundle.getString("welcome"), System.getProperty("user.name"));
        welcomeLabel.setText(welcome);
        welcomeLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        
        // 按钮:切换语言
        Button enButton = new Button(shell, SWT.PUSH);
        enButton.setText("English");
        enButton.addListener(SWT.Selection, event -> {
            Locale locale = Locale.US;
            ResourceBundle enBundle = ResourceBundle.getBundle("messages", locale);
            updateUI(enBundle);
        });
        
        Button zhButton = new Button(shell, SWT.PUSH);
        zhButton.setText("中文");
        zhButton.addListener(SWT.Selection, event -> {
            Locale locale = Locale.CHINA;
            ResourceBundle zhBundle = ResourceBundle.getBundle("messages", locale);
            updateUI(zhBundle);
        });
        
        Button esButton = new Button(shell, SWT.PUSH);
        esButton.setText("Español");
        esButton.addListener(SWT.Selection, event -> {
            Locale locale = new Locale("es", "ES");
            ResourceBundle esBundle = ResourceBundle.getBundle("messages", locale);
            updateUI(esBundle);
        });
        
        shell.setBounds(100, 100, 400, 200);
        shell.open();
        
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        
        display.dispose();
    }
    
    private static void updateUI(ResourceBundle bundle) {
        // 注意:实际应用中需要传递 shell 和 Label 的引用
        // 这里只是为了演示,实际需要重构代码
        System.out.println("切换语言:" + bundle.getLocale().getDisplayLanguage());
        System.out.println("问候:" + bundle.getString("greeting"));
        System.out.println("欢迎:" + bundle.getString("welcome"));
    }
}

14.3 SWT 的国际化支持

控件文本的翻译

// 加载资源
ResourceBundle bundle = ResourceBundle.getBundle("messages");

// 创建控件
Label nameLabel = new Label(shell, SWT.NONE);
nameLabel.setText(bundle.getString("name"));

Text nameText = new Text(shell, SWT.BORDER);

Label emailLabel = new Label(shell, SWT.NONE);
emailLabel.setText(bundle.getString("email"));

Text emailText = new Text(shell, SWT.BORDER);

// 按钮
Button saveButton = new Button(shell, SWT.PUSH);
saveButton.setText(bundle.getString("save"));

Button cancelButton = new Button(shell, SWT.PUSH);
cancelButton.setText(bundle.getString("cancel"));

费曼解释:控件文本翻译的流程

控件文本翻译 = 多语言标签
- 标签(控件)上有文字(文本)
- 不同语言显示不同文字(翻译)

类比:
控件文本翻译 = 多语言路标
- 路标(控件)上有文字(文本)
- 不同语言显示不同文字(翻译)

菜单的翻译

// 加载资源
ResourceBundle bundle = ResourceBundle.getBundle("messages");

// 创建菜单
Menu menuBar = new Menu(shell, SWT.BAR);
shell.setMenuBar(menuBar);

MenuItem fileMenu = new MenuItem(menuBar, SWT.CASCADE);
fileMenu.setText(bundle.getString("file"));

Menu fileMenuContent = new Menu(shell, SWT.DROP_DOWN);
fileMenu.setMenu(fileMenuContent);

MenuItem newItem = new MenuItem(fileMenuContent, SWT.PUSH);
newItem.setText(bundle.getString("new"));

MenuItem openItem = new MenuItem(fileMenuContent, SWT.PUSH);
openItem.setText(bundle.getString("open"));

new MenuItem(fileMenuContent, SWT.SEPARATOR);

MenuItem exitItem = new MenuItem(fileMenuContent, SWT.PUSH);
exitItem.setText(bundle.getString("exit"));

费曼解释:菜单翻译的流程

菜单翻译 = 多语言餐厅菜单
- 菜单(Menu)上有菜名(菜单项)
- 不同语言显示不同菜名(翻译)

类比:
菜单翻译 = 多语言路标
- 路标(Menu)上有文字(菜单项)
- 不同语言显示不同文字(翻译)

错误消息的翻译

// 加载资源
ResourceBundle bundle = ResourceBundle.getBundle("messages");

// 属性文件
// error.invalidEmail=Invalid email address!
// error.emptyField=The {0} field cannot be empty!

// 显示错误消息
MessageBox messageBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
messageBox.setText(bundle.getString("error"));

String email = "";
if (!email.contains("@")) {
    messageBox.setMessage(bundle.getString("error.invalidEmail"));
    messageBox.open();
}

费曼解释:错误消息翻译的流程

错误消息翻译 = 多语言警示牌
- 警示牌(MessageBox)上有文字(错误消息)
- 不同语言显示不同文字(翻译)

类比:
错误消息翻译 = 多语言警告
- 警告(MessageBox)上有文字(错误消息)
- 不同语言显示不同文字(翻译)

代码示例:SWT 国际化

public class SWTI18nExample {
    private static ResourceBundle bundle;
    
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(2, false));
        
        // 加载默认资源
        bundle = ResourceBundle.getBundle("messages");
        
        // 标题
        Label titleLabel = new Label(shell, SWT.NONE);
        titleLabel.setText(bundle.getString("greeting"));
        GridData titleData = new GridData();
        titleData.horizontalSpan = 2;
        titleData.horizontalAlignment = GridData.CENTER;
        titleData.grabExcessHorizontalSpace = true;
        titleLabel.setLayoutData(titleData);
        
        // 姓名
        Label nameLabel = new Label(shell, SWT.NONE);
        nameLabel.setText(bundle.getString("name"));
        
        Text nameText = new Text(shell, SWT.BORDER);
        GridData nameData = new GridData();
        nameData.horizontalAlignment = GridData.FILL;
        nameData.grabExcessHorizontalSpace = true;
        nameText.setLayoutData(nameData);
        
        // 邮箱
        Label emailLabel = new Label(shell, SWT.NONE);
        emailLabel.setText(bundle.getString("email"));
        
        Text emailText = new Text(shell, SWT.BORDER);
        GridData emailData = new GridData();
        emailData.horizontalAlignment = GridData.FILL;
        emailData.grabExcessHorizontalSpace = true;
        emailText.setLayoutData(emailData);
        
        // 按钮
        Button saveButton = new Button(shell, SWT.PUSH);
        saveButton.setText(bundle.getString("save"));
        saveButton.addListener(SWT.Selection, event -> {
            String name = nameText.getText().trim();
            String email = emailText.getText().trim();
            
            if (name.isEmpty()) {
                showError("error.emptyField", bundle.getString("name"));
                return;
            }
            
            if (email.isEmpty()) {
                showError("error.emptyField", bundle.getString("email"));
                return;
            }
            
            if (!email.contains("@")) {
                showError("error.invalidEmail", null);
                return;
            }
            
            showSuccess();
        });
        
        Button cancelButton = new Button(shell, SWT.PUSH);
        cancelButton.setText(bundle.getString("cancel"));
        cancelButton.addListener(SWT.Selection, event -> {
            shell.dispose();
        });
        
        // 语言切换
        Button enButton = new Button(shell, SWT.PUSH);
        enButton.setText("English");
        enButton.addListener(SWT.Selection, event -> {
            Locale locale = Locale.US;
            bundle = ResourceBundle.getBundle("messages", locale);
            updateUI(shell, nameLabel, emailLabel, saveButton, cancelButton);
        });
        
        Button zhButton = new Button(shell, SWT.PUSH);
        zhButton.setText("中文");
        zhButton.addListener(SWT.Selection, event -> {
            Locale locale = Locale.CHINA;
            bundle = ResourceBundle.getBundle("messages", locale);
            updateUI(shell, nameLabel, emailLabel, saveButton, cancelButton);
        });
        
        shell.setBounds(100, 100, 400, 200);
        shell.open();
        
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        
        display.dispose();
    }
    
    private static void updateUI(Shell shell, Label nameLabel, Label emailLabel, 
            Button saveButton, Button cancelButton) {
        shell.setText(bundle.getString("title"));
        nameLabel.setText(bundle.getString("name"));
        emailLabel.setText(bundle.getString("email"));
        saveButton.setText(bundle.getString("save"));
        cancelButton.setText(bundle.getString("cancel"));
        shell.layout();
    }
    
    private static void showError(String errorKey, String fieldName) {
        Display display = Display.getCurrent();
        Shell shell = display.getActiveShell();
        
        String errorMessage;
        if (fieldName != null) {
            errorMessage = MessageFormat.format(bundle.getString(errorKey), fieldName);
        } else {
            errorMessage = bundle.getString(errorKey);
        }
        
        MessageBox messageBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
        messageBox.setText(bundle.getString("error"));
        messageBox.setMessage(errorMessage);
        messageBox.open();
    }
    
    private static void showSuccess() {
        Display display = Display.getCurrent();
        Shell shell = display.getActiveShell();
        
        MessageBox messageBox = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
        messageBox.setText(bundle.getString("success"));
        messageBox.setMessage(bundle.getString("save.success"));
        messageBox.open();
    }
}

14.4 RTL(从右到左)语言支持

从右到左的布局

// 创建 RTL 布局
Composite rtlComposite = new Composite(shell, SWT.RIGHT_TO_LEFT);
rtlComposite.setLayout(new GridLayout(2, false));

// 标签
Label nameLabel = new Label(rtlComposite, SWT.NONE);
nameLabel.setText("姓名:");

Text nameText = new Text(rtlComposite, SWT.BORDER);

// 邮箱
Label emailLabel = new Label(rtlComposite, SWT.NONE);
emailLabel.setText("邮箱:");

Text emailText = new Text(rtlComposite, SWT.BORDER);

费曼解释:RTL 布局的作用

RTL = 从右到左
- 英语(LTR):Hello, World!(从左到右)
- 阿拉伯语(RTL):مرحبا بالعالم!(从右到左)
- 希伯来语(RTL):שלום עולם!(从右到左)

类比:
RTL = 反向阅读
- 英语(LTR):从左到右读
- 阿拉伯语(RTL):从右到左读
- 就像有人从右边往左边走

支持阿拉伯语、希伯来语

// 检测是否是 RTL 语言
Locale locale = Locale.getDefault();
boolean isRTL = locale.getLanguage().equals("ar") || locale.getLanguage().equals("he");

if (isRTL) {
    // 创建 RTL 布局
    Composite rtlComposite = new Composite(shell, SWT.RIGHT_TO_LEFT);
    // 添加控件...
} else {
    // 创建 LTR 布局
    Composite ltrComposite = new Composite(shell, SWT.NONE);
    // 添加控件...
}

费曼解释:如何检测 RTL 语言?

检测 RTL 语言 = 检查语言代码
- 阿拉伯语:ar(RTL)
- 希伯来语:he(RTL)
- 其他语言:默认为 LTR

类比:
检测 RTL 语言 = 检查书写方向
- 英语:从左到右写
- 阿拉伯语:从右到左写
- 检查语言代码,知道书写方向

代码示例:RTL 语言支持

public class RTLLanguageExample {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("RTL 语言支持");
        shell.setLayout(new GridLayout(1, false));
        
        // 检测系统语言
        Locale systemLocale = Locale.getDefault();
        boolean isRTL = systemLocale.getLanguage().equals("ar") || 
                       systemLocale.getLanguage().equals("he");
        
        Label languageLabel = new Label(shell, SWT.WRAP | SWT.CENTER);
        languageLabel.setText("系统语言:" + systemLocale.getDisplayLanguage() + 
            "\n是否是 RTL:" + (isRTL ? "是" : "否"));
        GridData languageData = new GridData();
        languageData.horizontalAlignment = GridData.FILL;
        languageData.grabExcessHorizontalSpace = true;
        languageLabel.setLayoutData(languageData);
        
        // LTR 布局
        Group ltrGroup = new Group(shell, SWT.NONE);
        ltrGroup.setText("LTR 布局(英语)");
        ltrGroup.setLayout(new GridLayout(2, false));
        ltrGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        
        Label ltrNameLabel = new Label(ltrGroup, SWT.NONE);
        ltrNameLabel.setText("姓名:");
        
        Text ltrNameText = new Text(ltrGroup, SWT.BORDER);
        ltrNameText.setText("Hello, World!");
        
        Label ltrEmailLabel = new Label(ltrGroup, SWT.NONE);
        ltrEmailLabel.setText("邮箱:");
        
        Text ltrEmailText = new Text(ltrGroup, SWT.BORDER);
        ltrEmailText.setText("test@example.com");
        
        // RTL 布局
        Group rtlGroup = new Group(shell, SWT.RIGHT_TO_LEFT);
        rtlGroup.setText("RTL 布局(阿拉伯语)");
        rtlGroup.setLayout(new GridLayout(2, false));
        rtlGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        
        Label rtlNameLabel = new Label(rtlGroup, SWT.NONE);
        rtlNameLabel.setText("الاسم:");
        
        Text rtlNameText = new Text(rtlGroup, SWT.BORDER);
        rtlNameText.setText("مرحبا بالعالم!");
        
        Label rtlEmailLabel = new Label(rtlGroup, SWT.NONE);
        rtlEmailLabel.setText("البريد الإلكتروني:");
        
        Text rtlEmailText = new Text(rtlGroup, SWT.BORDER);
        rtlEmailText.setText("test@example.com");
        
        // 按钮:切换到 RTL 布局
        Button rtlButton = new Button(shell, SWT.PUSH);
        rtlButton.setText("切换到 RTL");
        rtlButton.addListener(SWT.Selection, event -> {
            Group group = new Group(shell, SWT.RIGHT_TO_LEFT);
            group.setText("新 RTL 布局");
            group.setLayout(new GridLayout(2, false));
            
            Label nameLabel = new Label(group, SWT.NONE);
            nameLabel.setText("الاسم:");
            
            Text nameText = new Text(group, SWT.BORDER);
            nameText.setText("مرحبا بالعالم!");
            
            group.pack();
            group.setVisible(true);
        });
        
        shell.setBounds(100, 100, 500, 400);
        shell.open();
        
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        
        display.dispose();
    }
}

14.5 本章小结

国际化总结

概念作用类比
ResourceBundle加载多语言资源多语言书库
属性文件存储多语言文本多语言菜单
占位符替换动态内容填空题
RTL从右到左布局反向阅读
MessageFormat格式化消息邮件模板

费曼测试:你能解释清楚吗?

  1. 为什么需要国际化?

- 不同语言的用户看到不同语言的内容

  1. ResourceBundle 的加载机制?

- 根据 Locale 加载对应语言的资源文件

  1. 占位符的作用?

- 替换动态内容,如用户名、日期等

  1. RTL 布局的含义?

- 从右到左的布局,支持阿拉伯语、希伯来语等

下一章预告

现在你已经掌握了国际化,
可以支持多种语言,
服务全球用户。

下一章,我们将学习主题与样式,
让应用支持 Dark Mode,
提升用户体验。

练习题:

  1. 创建一个应用,支持英语和中文,通过 ResourceBundle 加载资源。
  2. 创建一个表单,包含姓名、邮箱,支持多语言。
  3. 创建一个应用,支持阿拉伯语,使用 RTL 布局。

(提示:使用 ResourceBundle.getBundle("messages") 加载资源,使用 SWT.RIGHTTOLEFT 创建 RTL 布局)

← 返回目录