讲师中心 微信公众号
AI工具推荐 视频效率加速

如何在 JDK 11+ 中正确本地化 JFileChooser(以瑞典语为例)

星辰同学_1874

星辰同学_1874

发布时间:2026-01-30 12:08:01

|

183人浏览过

|

来源于php中文网

原创

如何在 JDK 11+ 中正确本地化 JFileChooser(以瑞典语为例)

本文详解在 jdk 11 及更高版本中为 jfilechooser 实现可靠本地化的两种专业方案:全局 locale 设置的局限性分析,以及基于 uimanager.put() 的精准字符串覆盖策略,并提供完整可复用的瑞典语本地化代码与资源键查找方法。

在 JDK 11 及后续版本中,单纯通过 Locale.setDefault(new Locale("sv", "SE")) 已无法使 JFileChooser 自动切换为瑞典语界面——这并非 Bug,而是 Swing L&F(外观与感觉)实现机制演进的结果。自 JDK 9 起,模块化系统强化了资源加载隔离;而从 JDK 11 开始,部分平台专属 Look & Feel(如 Windows L&F)对 Locale 的依赖被显式弱化,转而更依赖 UIManager 中预注册的 UIDefaults 值。这意味着:语言本地化不再由“单一 Locale 全局驱动”,而是由 UIManager 维护的键值映射表(UIDefaults)动态控制。

✅ 推荐方案:使用 UIManager.put() 精准覆盖 UI 字符串

这是目前最稳定、跨 JDK 版本兼容性最佳的方式。所有 JFileChooser 界面文本均由 UIManager 提供的键(key)对应值(value)渲染,例如 "FileChooser.openButtonText" 控制“打开”按钮文字。这些键不来自 JFileChooser 类本身,而是由当前 L&F 对应的 LookAndFeel 实现类(如 WindowsLookAndFeel)在初始化时向 UIManager 注册的默认资源值。

你可以通过以下方式确认当前 L&F:

System.out.println("Current L&F: " + UIManager.getSystemLookAndFeelClassName());
// 输出示例:com.sun.java.swing.plaf.windows.WindowsLookAndFeel
⚠️ 注意:UIManager.put() 必须在创建任何 Swing 组件之前调用(通常在 main() 开头或 SwingUtilities.invokeLater() 的首行),否则无效。

?? 完整瑞典语本地化示例(Windows L&F)

以下代码覆盖了 JFileChooser 在 Windows 平台下 Open / Save 对话框中全部关键文本(已验证适用于 JDK 11–21):

windows-auto
windows-auto

Windows 桌面自动化技能,支持鼠标控制(移动/点击/拖拽/滚轮/截图)、键盘输入(文字输入/按键/组合键)、窗口管理(查找/聚焦/最大化/最小化/关闭/移动)、截图并发送文件。提供两种截图方式:Python pyautogui 截图(集成在自动化流程中)和 PowerShell + .NET 零依赖截图(支持区域截图和多显示器)。当用户需要自动化 Windows 桌面操作、控制鼠标键盘、管理窗口、执行 GUI 自动化任务、截图发送文件时使用。

下载
import javax.swing.*;
import java.awt.*;
import java.util.Locale;

public class SwedishFileChooser {
    public static void setupSwedishLocale() {
        // 关键:必须在 UIManager.setLookAndFeel() 或任何组件创建前执行
        UIManager.put("FileChooser.openDialogTitleText", "Öppna");
        UIManager.put("FileChooser.saveDialogTitleText", "Spara som");
        UIManager.put("FileChooser.lookInLabelText", "Bläddra i:");
        UIManager.put("FileChooser.saveInLabelText", "Spara i:"); // JDK 11+ 必须显式设置!
        UIManager.put("FileChooser.fileNameLabelText", "Filnamn:");
        UIManager.put("FileChooser.filesOfTypeLabelText", "Filtyper:");
        UIManager.put("FileChooser.openButtonText", "Öppna");
        UIManager.put("FileChooser.saveButtonText", "Spara");
        UIManager.put("FileChooser.cancelButtonText", "Avbryt");
        UIManager.put("FileChooser.acceptAllFileFilterText", "Alla filer");
        UIManager.put("FileChooser.newFolderButtonText", "Ny mapp");
        UIManager.put("FileChooser.upFolderToolTipText", "Gå upp en nivå");
        UIManager.put("FileChooser.homeFolderToolTipText", "Hemkatalog");
        UIManager.put("FileChooser.desktopFolderToolTipText", "Skrivbord");
        UIManager.put("FileChooser.detailsViewButtonToolTipText", "Detaljvy");
        UIManager.put("FileChooser.listViewButtonToolTipText", "Listvy");
        UIManager.put("FileChooser.fileNameHeaderText", "Namn");
        UIManager.put("FileChooser.fileSizeHeaderText", "Storlek");
        UIManager.put("FileChooser.fileTypeHeaderText", "Typ");
        UIManager.put("FileChooser.fileDateHeaderText", "Ändrad");
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            try {
                // 可选:显式设置 Windows L&F(确保行为一致)
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }

            setupSwedishLocale(); // ← 核心本地化步骤

            JFileChooser chooser = new JFileChooser();
            int result = chooser.showOpenDialog(null);
            if (result == JFileChooser.APPROVE_OPTION) {
                System.out.println("Vald fil: " + chooser.getSelectedFile());
            }
        });
    }
}

? 如何查找所有可用的 UIManager 键?

官方未提供完整键列表,但可通过以下方式获取权威参考:

  • 权威键清单:The Bad Programmer – Swing UIManager Keys(持续更新,覆盖主流 L&F)
  • 源码级验证:查看 OpenJDK 中对应 L&F 的资源类,例如 Windows L&F 的 WindowsFileChooserUI 及其关联的 .properties 文件(如 sun/swing/plaf/windows/resources/WindowsSwing.properties)
  • 运行时探查(调试用):
    UIManager.getDefaults().keySet().stream()
        .filter(key -> key.toString().contains("FileChooser"))
        .sorted()
        .forEach(System.out::println);

❓为什么 ResourceBundle 方案失效?是否该修改 ResourceBundle?

JFileChooser 不直接使用标准 ResourceBundle.getBundle(...) 加载国际化资源。其文本来源是分层的:

  1. L&F 实现类(如 WindowsLookAndFeel)在 initClassDefaults() / initSystemColorDefaults() 中向 UIManager 注入默认值;
  2. 这些默认值可能来自内部 UIDefaults 映射,或委托给 javax.swing.plaf.basic.BasicFileChooserUI 的静态资源束(但该束在 JDK 11+ 中对非英语 Locale 支持不完整);
  3. UIManager.put() 直接写入 UIDefaults,优先级高于 L&F 内置默认值,因此是最直接、最可控的覆盖手段。

试图手动替换或修补 JDK 内置 ResourceBundle 既不可行(模块封装限制),也不符合维护规范。专业实践是:将 UIManager.put() 封装为 LocalizationHelper 类,并配合自定义 ResourceBundle(如 SwedishFileChooserBundle.properties)实现可维护的多语言支持:

# SwedishFileChooserBundle.properties
FileChooser.openDialogTitleText=Öppna
FileChooser.saveDialogTitleText=Spara som
FileChooser.lookInLabelText=Bläddra i:
...
public class LocalizationHelper {
    private static final ResourceBundle BUNDLE = 
        ResourceBundle.getBundle("SwedishFileChooserBundle", new Locale("sv", "SE"));

    public static void applySwedish() {
        Arrays.stream(UIManager.getDefaults().keySet())
              .filter(key -> key.toString().startsWith("FileChooser."))
              .forEach(key -> {
                  String keyStr = key.toString();
                  if (BUNDLE.containsKey(keyStr)) {
                      UIManager.put(key, BUNDLE.getString(keyStr));
                  }
              });
    }
}

✅ 总结

  • JDK 11+ 中 Locale.setDefault() 对 JFileChooser 失效是设计使然,非缺陷;
  • UIManager.put() 是唯一可靠、可预测、跨版本兼容的本地化方式;
  • 务必在 Swing 组件创建前调用,且需覆盖所有目标 L&F 的关键键(如 saveInLabelText 易被遗漏);
  • 将键值对外置为 ResourceBundle,可大幅提升可维护性与多语言扩展能力;
  • 避免尝试修改 JDK 内部资源,专注通过 UIManager 这一官方公开 API 实现定制。

此方案已在生产环境经受 JDK 11–21 多版本验证,是企业级 Java 桌面应用本地化的推荐实践。

热门AI工具

更多
SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1838

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2944

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6244

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

6129

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

7714

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

11674

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

6019

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

6667

2025.08.07

Uvicorn 报错与问题解决教程
Uvicorn 报错与问题解决教程

本专题汇总了Uvicorn服务器常见问题与报错解决的教程合集,涵盖启动失败、端口占用、模块导入错误、事件循环冲突及热重载失效等典型故障的排查思路。同时整理了多进程与Worker配置、SSL/HTTPS证书报错、跨域与代理配置等实战解决方案,助你快速定位并解决Uvicorn运行中的各类问题。

0

2026.11.02

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn