如何在 Java/Swing 应用程序中实现多语言?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/902031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement multilanguage in Java/Swing applications?
提问by m_vitaly
What are the different ways of implementing multilingual support in Swing applications?
在 Swing 应用程序中实现多语言支持的不同方式有哪些?
Are you using ResourceBundle with property file and implementing it in every frame? Does it work good for you? What if you use some kind of GUI editor? Is there any other way around?
您是否将 ResourceBundle 与属性文件一起使用并在每一帧中实现它?它对你有好处吗?如果您使用某种 GUI 编辑器会怎样?有没有其他办法?
At work we are using Matisse4MyEclipse and the code gets regenerated every time we save the screen, so simply using Externalize Strings won't work here. One way is to define it as custom property for each component, which is very annoying. Another way is to go over the multilanguage components and their properties again after matisse's generated code, which is a pain, too.
在工作中,我们使用 Matisse4MyEclipse,每次保存屏幕时都会重新生成代码,因此在这里仅使用外部化字符串是行不通的。一种方法是将其定义为每个组件的自定义属性,这很烦人。另一种方法是在 matisse 生成的代码之后再次检查多语言组件及其属性,这也很痛苦。
采纳答案by Rastislav Komara
Well, you had to use ResourceBundle
s. But if you are setting the componet text property use instead of human readable text the text for RB.getString()
. Then if the Matisse regenerates form the bundle key will stay and localization will work. Example:
好吧,您必须使用ResourceBundle
s。但是,如果您要设置组件文本属性,请使用RB.getString()
. 然后,如果 Matisse 重新生成,bundle key 将保留并且本地化将起作用。例子:
I will use this image from Matisse pages:
(source: myeclipseide.com).
我将使用来自 Matisse 页面的这张图片:(来源:myeclipseide.com)。
there you can see the the property text. There is value "My New Label". Instead of this you can use rb.getString("myNewLabel.my.message")
where rb
is ResourceBundle
. The only problem should be too intelligent properties editor going against you. I never work with any wysiwyg editor (personal preference, I do always UI design by hand).
在那里你可以看到属性文本。有“我的新标签”的价值。您可以使用rb.getString("myNewLabel.my.message")
where rb
is代替这个ResourceBundle
。唯一的问题应该是过于智能的属性编辑器对您不利。我从不使用任何所见即所得的编辑器(个人喜好,我总是手工进行 UI 设计)。
回答by duffymo
I don't know of any way besides ResourceBundle.
除了ResourceBundle,我不知道还有什么方法。
Why do you keep regenerating code? I would imagine that it would be fine once you got a page started, but after that it'd be largely unnecessary. Sounds like code generation is your real problem. It's not saving you anything.
为什么要不断地重新生成代码?我想一旦你开始一个页面就可以了,但在那之后它基本上是不必要的。听起来像代码生成是你真正的问题。它不会为你节省任何东西。
Do you try to compose pages out of several Components? I can imagine a common header, footer, and menu that wouldn't have to change all the time. It could be a design issue.
您是否尝试用多个组件组合页面?我可以想象一个不需要一直更改的通用页眉、页脚和菜单。可能是设计问题。
Spring has very nice support for I18N. Maybe it can help you here.
Spring 对 I18N 有很好的支持。也许它可以在这里帮助你。
回答by adrian.tarau
This is how I implemented the internationalization :
这就是我实现国际化的方式:
- give a name to every component which has an internationalized text
- at runtime, take the container(frame, dialog, applet) ,iterate all the components and build an i18n key for every component using its name and all parent names.
- for every component type(JTextField, JLable, etc) define some keys for every internationalize field(text, label, hint, etc).
- take this i18n key and query your ResourceBundle, take the results and populate the component fields.
- 为每个具有国际化文本的组件命名
- 在运行时,获取 container(frame, dialog, applet) ,迭代所有组件并使用其名称和所有父名称为每个组件构建一个 i18n 键。
- 对于每个组件类型(JTextField、JLable 等),为每个国际化字段(文本、标签、提示等)定义一些键。
- 获取此 i18n 键并查询您的 ResourceBundle,获取结果并填充组件字段。
It works with generated code or with manual created code.
它适用于生成的代码或手动创建的代码。
Edit: Here it is :
编辑:这里是:
public void buildIds() {
buildId(true);
int count = getComponentCount();
if (count == 0) {
return;
}
for (int i = 0; i < count; i++) {
Component component = getComponent(i);
if (component instanceof AbstractComponent) {
((AbstractComponent) component).buildIds();
}
}
}
protected void buildId(boolean fireChange) {
String prevId = this.id;
String computedId;
if (getName() == null) {
computedId = ClassUtilities.shortClassName(getClass()).toLowerCase() + "_" + Long.toHexString(ID_GENERATOR.getAndIncrement());
} else {
java.util.List<Component> parents = null;
Component parent = getParent();
if (parent != null) {
StringBuilder buider = new StringBuilder(80);
parents = new ArrayList<Component>();
while (parent != null) {
if (parent.getName() != null) {
parents.add(parent);
}
parent = parent.getParent();
}
Collections.reverse(parents);
if (parents.size() > 0) {
for (Component component : parents) {
if (buider.length() > 0) {
buider.append('.');
}
buider.append(component.getName());
}
buider.append('.');
}
buider.append(name);
computedId = buider.toString().toLowerCase();
} else {
computedId = name;
}
}
this.id = computedId;
if (fireChange && prevId != null && !prevId.equals(computedId)) {
componentIdChanged(this, prevId);
}
}
回答by Pankaj Mandale
Use ResourceBundle class and set the language to locale:
使用 ResourceBundle 类并将语言设置为语言环境:
Following is code in java
以下是java中的代码
private static Map<String, ResourceBundle> resourceBundles;
private static ResourceBundle loadBundle(String language) {
if (resourceBundles == null) {
resourceBundles = new HashMap<String, ResourceBundle>();
}
ResourceBundle currentBundle = resourceBundles.get(language);
if (currentBundle == null) {
Locale locale = new Locale(language);
currentBundle = ResourceBundle.getBundle("i18n.Messages", locale);
resourceBundles.put(language, currentBundle);
}
return currentBundle;
}
public static String messageForKey(String key, String language) {
ResourceBundle currentBundle = loadBundle(language);
return currentBundle.getString(key);
}