如何使用 ResourceBundle 从 java 文件中读取阿拉伯语或波斯语(键和值)
How to read Arabic or Persian (key and values) from java file with ResourceBundle
我正在尝试从 java 文件而不是带有 ResourceBundle 的属性文件中读取阿拉伯语和波斯语的键和值,但它显示未知字符。
我所做的是将 3 个文件编码为:
1. LabelsBundle_en_US.java
2. LabelsBundle_ar_AE.java
3.LabelsBundle_fa_IR.java
我的 LabelsBundle_en_US.java 文件如下所示:
public class LabelsBundle_en_US extends ListResourceBundle{
static final Object[][] contents = {
{"REGISTER","Registration Form"},
{"USERNAME","Email"},
{"PASSWORD","Password"},
{"CONFIRM_PASS","Confirm Password"},
{"SUBMIT","Register"}
};
protected Object[][] getContents(){
return contents;
}
}//class
我的 LabelsBundle_fa_IR.java 文件如下所示:
public class LabelsBundle_fa_IR extends ListResourceBundle{
static final Object[][] contents = {
{"REGISTER","ثبت نام"},
{"USERNAME","ایمیل"},
{"PASSWORD","رمز"},
{"CONFIRM_PASS","مرور رمز"},
{"SUBMIT","ارسال"}
};
protected Object[][] getContents(){
return contents;
}
}//class
这是我的 servlet:
protected void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException{
res.setContentType("text/html; charset=UTF-8");
req.setCharacterEncoding("UTF-8");
res.setCharacterEncoding("UTF-8");
StringWriter sWriter = new StringWriter();
PrintWriter out = new PrintWriter(sWriter);
String country = req.getParameter("country");
String language = req.getParameter("language");
Locale locale=null;
if(country == null){
locale = new Locale("en","US");
}
else{
locale = new Locale(language, country);
}
ResourceBundle rb = ResourceBundle.getBundle("com.i18n.resource.bundles.LabelsBundle",locale);
req.setAttribute("resource", rb);
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">"+
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"fi\" dir=\"auto\">"+
"<head>"+
"<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />"+
"<body>"+
"<center><h1>"+rb.getString("REGISTER")+"</h1></center>"+
"<table border=0 width=540 align=center>"+
"<tr><td colspan=2 align=center><h1>"+rb.getString("REGISTER")+"</h1></td></tr>"+
"<tr><td>"+rb.getString("USERNAME")+"</td><td><input type=text name=username></td></tr>"+
"<tr><td>"+rb.getString("PASSWORD")+"</td><td><input type=password name=password></td></tr>"+
"<tr><td>"+rb.getString("CONFIRM_PASS")+"</td><td><input type=password name=cPass></td></tr>"+
"<tr><td colspan=2 align=center><input type=submit value="+rb.getString("SUBMIT")+"></td></tr>"+
"</table></html>");
res.getWriter().print(sWriter.toString());
}//doGet
此代码在语言为 en_US 时工作正常,但当我将其更改为阿拉伯语或波斯语时,它显示为:
ط«ط¨طھ ظ†ط§ظ…
ط§غŒظ…غŒظ„
ط±ظ…ط²
ظ…ط±ظˆط± ط±ظ…ط²
ط§ط±ط³ط§ظ„
请指教
String USERNAME = new String(rb.getString("USERNAME").getBytes(), "UTF-8");
就我个人而言,我认为没有充分的理由将 ListResourceBundle 用于字符串。
但是,嘿,无论如何......
这里的问题是源 .java 文件的编码问题。
您可能将文件编码为 utf-8,但 Java 编译器不知道,并使用系统编码。
一个。您可以使用 -encoding:
将所需的编码传递给编译器
javac -encoding utf-8 LabelsBundle_fa_IR.java
b。您可以对字符串进行 Unicode 转义,使文件成为 ASCII。
这些字符将不可读(将是“...\u0646...”),但编译器不会再混淆了:
native2ascii -encoding utf-8 LabelsBundle_fa_IR.java asciifile
rename asciifile LabelsBundle_fa_IR.java
我假设您没有发送 .java 本地化文件:-)
大多数本地化工具从文件中提取可本地化的内容,对其进行翻译,然后生成 java 返回。通常有一个选项可以使用 unicode-escape 生成它,因此无需一直转到 .java 并在那里转换。
===
这是一个错误的答案:
rb.getString("USERNAME").getBytes(), "UTF-8");
getBytes 取决于系统编码,但那是运行时编码。
所以这是你服务器的编码,而不是用来编译你的 java 文件的编码。可能不一样。
===
为什么我更喜欢 .properties 而不是 ListResourceBundle:
本地化(通过翻译,而不是技术人员)不会发生在 .java 文件上。
必须提取字符串,然后放回去。由于 .java 文件
可以包含代码什么的,在这个过程中更容易损坏。
大多数本地化工具都能很好地处理 .properties,但 ListResourceBundle
.properties 文件的编码定义明确:Latin 1。
没有"magic",不依赖于系统。
所以你在编译时不需要特殊的标志。
ListResourceBundle 非常适合特定于语言环境的对象。
思考商业逻辑,例如复杂的税收规则,
或特殊的工作流程。这就是为什么它是从 String 到 Object 的映射。
您当然可以将字符串放在那里,但是 .properties 或 .xml
专为字符串设计。
我正在尝试从 java 文件而不是带有 ResourceBundle 的属性文件中读取阿拉伯语和波斯语的键和值,但它显示未知字符。
我所做的是将 3 个文件编码为: 1. LabelsBundle_en_US.java 2. LabelsBundle_ar_AE.java 3.LabelsBundle_fa_IR.java
我的 LabelsBundle_en_US.java 文件如下所示:
public class LabelsBundle_en_US extends ListResourceBundle{
static final Object[][] contents = {
{"REGISTER","Registration Form"},
{"USERNAME","Email"},
{"PASSWORD","Password"},
{"CONFIRM_PASS","Confirm Password"},
{"SUBMIT","Register"}
};
protected Object[][] getContents(){
return contents;
}
}//class
我的 LabelsBundle_fa_IR.java 文件如下所示:
public class LabelsBundle_fa_IR extends ListResourceBundle{
static final Object[][] contents = {
{"REGISTER","ثبت نام"},
{"USERNAME","ایمیل"},
{"PASSWORD","رمز"},
{"CONFIRM_PASS","مرور رمز"},
{"SUBMIT","ارسال"}
};
protected Object[][] getContents(){
return contents;
}
}//class
这是我的 servlet:
protected void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException{
res.setContentType("text/html; charset=UTF-8");
req.setCharacterEncoding("UTF-8");
res.setCharacterEncoding("UTF-8");
StringWriter sWriter = new StringWriter();
PrintWriter out = new PrintWriter(sWriter);
String country = req.getParameter("country");
String language = req.getParameter("language");
Locale locale=null;
if(country == null){
locale = new Locale("en","US");
}
else{
locale = new Locale(language, country);
}
ResourceBundle rb = ResourceBundle.getBundle("com.i18n.resource.bundles.LabelsBundle",locale);
req.setAttribute("resource", rb);
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">"+
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"fi\" dir=\"auto\">"+
"<head>"+
"<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />"+
"<body>"+
"<center><h1>"+rb.getString("REGISTER")+"</h1></center>"+
"<table border=0 width=540 align=center>"+
"<tr><td colspan=2 align=center><h1>"+rb.getString("REGISTER")+"</h1></td></tr>"+
"<tr><td>"+rb.getString("USERNAME")+"</td><td><input type=text name=username></td></tr>"+
"<tr><td>"+rb.getString("PASSWORD")+"</td><td><input type=password name=password></td></tr>"+
"<tr><td>"+rb.getString("CONFIRM_PASS")+"</td><td><input type=password name=cPass></td></tr>"+
"<tr><td colspan=2 align=center><input type=submit value="+rb.getString("SUBMIT")+"></td></tr>"+
"</table></html>");
res.getWriter().print(sWriter.toString());
}//doGet
此代码在语言为 en_US 时工作正常,但当我将其更改为阿拉伯语或波斯语时,它显示为:
ط«ط¨طھ ظ†ط§ظ…
ط§غŒظ…غŒظ„
ط±ظ…ط²
ظ…ط±ظˆط± ط±ظ…ط²
ط§ط±ط³ط§ظ„
请指教
String USERNAME = new String(rb.getString("USERNAME").getBytes(), "UTF-8");
就我个人而言,我认为没有充分的理由将 ListResourceBundle 用于字符串。 但是,嘿,无论如何......
这里的问题是源 .java 文件的编码问题。
您可能将文件编码为 utf-8,但 Java 编译器不知道,并使用系统编码。
一个。您可以使用 -encoding:
将所需的编码传递给编译器javac -encoding utf-8 LabelsBundle_fa_IR.java
b。您可以对字符串进行 Unicode 转义,使文件成为 ASCII。 这些字符将不可读(将是“...\u0646...”),但编译器不会再混淆了:
native2ascii -encoding utf-8 LabelsBundle_fa_IR.java asciifile
rename asciifile LabelsBundle_fa_IR.java
我假设您没有发送 .java 本地化文件:-) 大多数本地化工具从文件中提取可本地化的内容,对其进行翻译,然后生成 java 返回。通常有一个选项可以使用 unicode-escape 生成它,因此无需一直转到 .java 并在那里转换。
===
这是一个错误的答案:
rb.getString("USERNAME").getBytes(), "UTF-8");
getBytes 取决于系统编码,但那是运行时编码。
所以这是你服务器的编码,而不是用来编译你的 java 文件的编码。可能不一样。
===
为什么我更喜欢 .properties 而不是 ListResourceBundle:
本地化(通过翻译,而不是技术人员)不会发生在 .java 文件上。 必须提取字符串,然后放回去。由于 .java 文件 可以包含代码什么的,在这个过程中更容易损坏。 大多数本地化工具都能很好地处理 .properties,但 ListResourceBundle
.properties 文件的编码定义明确:Latin 1。 没有"magic",不依赖于系统。 所以你在编译时不需要特殊的标志。
ListResourceBundle 非常适合特定于语言环境的对象。 思考商业逻辑,例如复杂的税收规则, 或特殊的工作流程。这就是为什么它是从 String 到 Object 的映射。 您当然可以将字符串放在那里,但是 .properties 或 .xml 专为字符串设计。