公司的应用要求都做国际化,jsp页面中有大量的中文,需要将它们使用spring 的国际化标签实现国际化;一个一个手工去查找中文、再转换为spring国际化标签、并生成中英文的国际化资源文件,这是个重复且无聊的工作,页面少还好,如果页面多,会让人发狂,所以写了一个提取jsp页面中的中文,将它们替换为国际化标签,并生成国际化资源文件的小工具;
主要代码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.fanyti.ChineseToPinyin;
/**
* 扫描jsp文件中的中文,提取出中文,生成i18n的properties文件和jsp国际化后的文件;
*
* 使用方式:
* 1. 需要国际化的文件放在JSP_SOURCE_PATH路径下,生成的国际化文件放在JSP_CREATE_PATH路径下,项目已经存在的国际化资源文件(只要中文的)放到EXIST_I18n_ZH_CN_FILE_PATH路径下
* 2. 生成的国际化文件放在I18N_FILE_SAVE_PATH目录下,生成的国际化文件名称为PROP_NAME_ENG(英文资源文件)、PROP_NAME_GBK(中文资源文件);
* 3. 根据上面的配置修改JSP_SOURCE_PATH、JSP_CREATE_PATH、EXIST_I18n_ZH_CN_FILE_PATH、I18N_FILE_SAVE_PATH这四个常量路径的值;
* 4. 生成的国际化文件中,key的前缀为I18N_KEY_PREFIX变量指定;
*
* 注意:需要国际化的文件只要将项目中jsp文件所在父文件夹拷贝过来即可,应用会自动遍历各级子目录下的文件,并按照同样的目录结构去生成国际化好的jsp文件
* @author zqz
*/
public class Il8nJspTool {
/**国际化文件中国际化key的前缀**/
private static final String I18N_KEY_PREFIX = "com.newsys";
/**
* 请先配置好以下路径
*/
// 要国际化的jsp文件存放路径
private static final String JSP_SOURCE_PATH = "E:\\newsysi18n";
// 国际化后生成的文件的存储路径
private static final String JSP_CREATE_PATH = "E:\\newsysi18n_";
// 已经存在的国际化文件请放在这个目录下,防止对已经国际化的中文再生成重复的国际化文件,这个目录下只存放中文国际化文件即可;
private static final String EXIST_I18n_ZH_CN_FILE_PATH = "E:\\newsysi18n_\\i18n_source";
/**
* 请配置要生成的国际化文件的文件名
*/
// 生成的国际化文件名称,生成的文件保存在当前classpath目录下,重复执行会覆盖之前的执行结果
private static final String I18N_FILE_SAVE_PATH = "E:\\newsysi18n_\\i18n_create\\";
private static final String PROP_NAME_ENG$ = "$autocreate_i18n_en.properties";
private static final String PROP_NAME_ENG = "autocreate_i18n_en.properties";
private static final String PROP_NAME_GBK = "autocreate_i18n_zh_CN.properties";
// 文件编码utf-8
private static final String ENCODING = "utf-8";
public static final int BUFF_SIZE = 10240;
// 配置中文
private static final Pattern CHINESE_PATTERN = Pattern
.compile("[\\w\\ufe30-\\uffa0\\u4e00-\\u9fa5]*([\\u4e00-\\u9fa5]+[\\P{Punct}-,]{0,1})+[ \\w\\ufe30-\\uffa0\\u4e00-\\u9fa5]*\\P{Punct}{0,1}");
// html注释<!-- XXXX -->
private static String regEx_html = "<!--.*?-->";
private static Pattern p_html = Pattern.compile(regEx_html, Pattern.DOTALL);
// jsp的注释<%-- XXXXX --%>
private static String regEx_jsp = "<%--.*?--%>";
private static Pattern p_jsp = Pattern.compile(regEx_jsp, Pattern.DOTALL);
// js注释/* XXXX */
private static String regEx_js1 = "/\\*.*?\\*/";
private static Pattern p_js1 = Pattern.compile(regEx_js1, Pattern.DOTALL);
// js注释 // XXXXX
private static String regEx_js2 = "//[\\s\\S]*?\n";
private static java.util.regex.Pattern p_js2 = Pattern.compile(regEx_js2, Pattern.CASE_INSENSITIVE);
// jsp中的java代码 ${XXXX}
private static String regEx_java = "\\$\\{.*?\\}";
private static Pattern p_java = Pattern.compile(regEx_java, Pattern.DOTALL);
// jsp代码<% XXXX %>
private static String regEx_jsp2 = "<%.*?%>";
private static Pattern p_jsp2 = Pattern.compile(regEx_jsp2, Pattern.DOTALL);
// 已经国际化的kv
private static Map<String, String> existMap ;
// 不匹配的中文缓存
private static Map<String, String> noReplace = new HashMap<String, String>();
// 需要被国际化的jsp文件列表
private static List<File> fileList = new ArrayList<File>();
// 被匹配的中文内容 key为匹配到的中文 ,value为Il8NBean
private static Map<String, IL8NBean> i18nMatchCache = new HashMap<String, IL8NBean>();
private final static String IL8N_TAGLIB_FMT = "<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/jstl/fmt\" %>\r\n";
private final static String IL8N_TAGLIB_FMT_CHECK = "uri=\"http://java.sun.com/jsp/jstl/fmt\"";
private final static String IL8N_TAGLIB_CHECK = "file=\"../include/taglibs.jsp\"%>";
/**
* @Description: TODO
* @param args
* @throws
* @author zhuqz
*/
public static void main(String[] args) {
// 初始化
init();
// 获取要国际化的中文,并在当前classpath下生成properties文件;
getChinereWord(JSP_SOURCE_PATH);
// 生成将中文替换为国际化key的jsp文件;
replace(JSP_SOURCE_PATH, JSP_CREATE_PATH);
}
//初始化
private static void init() {
// 不做国际化的内容,例如html页面上css中的字体
noReplace.put("微软雅黑", "");
noReplace.put("宋体", "");
// 缓存已经做过国际化的key和value;
existMap = loadExistI18nFiles();
// 获取需要被国际化的jsp文件列表
fileList = getJsps(new File(JSP_SOURCE_PATH));
}
/**
* 获取到当前已经国际化的key和value
* @return
*/
private static Map<String, String> loadExistI18nFiles() {
File baseDir = new File(EXIST_I18n_ZH_CN_FILE_PATH);
if(!baseDir.exists()){
return new HashMap<String,String>(0);
}
File[] files = baseDir.listFiles();
Map<String,String> existI18n = new HashMap<String,String>(3000);
for (File file : files)
if (file.isDirectory() && !file.isHidden())
continue;
else if (file.getName().toLowerCase().endsWith(".properties"))
existI18n.putAll(loadProperties(file));
return existI18n;
}
/**
* Map<value,key>
* @Description: 载入已经存在的国际化文件
* @param fileName
* @return
* @throws
* @author zhuqz
*/
private static Map<String, String> loadProperties(File file) {
Map<String, String> map = new HashMap<String, String>();
Properties prop = new Properties();
InputStream in = null;
try {
in = new FileInputStream(file);
prop.load(new InputStreamReader(in, "UTF-8"));
System.out.println("加载已经存在的国际化文件:"+file);
} catch (IOException e) {
e.printStackTrace();
}
for (Map.Entry<Object, Object> e : prop.entrySet()) {
map.put(String.valueOf(e.getValue()), String.valueOf(e.getKey()));
}
return map;
}
/**
*
* @param sourcePath
* @param targetPath
*/
private static void replace(String sourcePath, String targetPath) {
System.out.println("共有文件:" + fileList.size());
for (File file : fileList) {
// 查找当前要替换的字符
String content = file2String(file, "utf-8");
content = p_html.matcher(content).replaceAll("\n");
content = p_jsp2.matcher(content).replaceAll("\n");
content = p_js1.matcher(content).replaceAll("\n");
content = p_js2.matcher(content).replaceAll("\n");
content = p_java.matcher(content).replaceAll("\n");
// 获取国际化后的文件内容
content = getI18nContent(file, content);
// 生成国际化文件
File newFile = new File(file.getAbsolutePath().replace(sourcePath, targetPath));
File dir = new File(newFile.getPath().substring(0, newFile.getPath().lastIndexOf("\\")));
if (!dir.exists()) {
dir.mkdirs();
}
string2File(content, newFile);
}
}
/**
* 获取文件国际化后的内容
* @param file
* @param content
* @return
*/
private static String getI18nContent( File file, String content) {
// System.out.println(content);
/** 本页面匹配到的中文 */
Matcher ma = CHINESE_PATTERN.matcher(content);
// 缓存当前页面需要被匹配中文和生成的key Map<中文,匹配到的key>
Map<String, String> selfMap = new HashMap<String, String>();
//用来标记是否有匹配的中文
boolean isMatch = false;
while (ma.find()) {
String pipei = ma.group().trim();
// 忽略需要被排除的中文
if (noReplace.get(pipei) != null) {
continue;
}
IL8NBean i18nBean = i18nMatchCache.get(pipei);
if(i18nBean != null){
String key = i18nBean.getKey();
if (key != null) {
selfMap.put(pipei, key);
}
isMatch = true;
}
}
/** 开始替换 **/
content = file2String(file, "utf-8");
StringBuffer sb = new StringBuffer();
ma = CHINESE_PATTERN.matcher(content);
while (ma.find()) {
if (noReplace.get(ma.group().trim()) != null) {
continue;
}
String key = selfMap.get(ma.group().trim());
//替换
ma.appendReplacement(sb, key == null ? ma.group() : getI18nString(key));
}
ma.appendTail(sb);
/** 判断是否已经添加国际化标签,没有则添加 */
if (isMatch && sb.indexOf(IL8N_TAGLIB_CHECK) < 0 && sb.indexOf(IL8N_TAGLIB_FMT_CHECK) < 0) {
return new StringBuilder(IL8N_TAGLIB_FMT).append(sb.toString()).toString();
}
return sb.toString();
}
/**
* 返回国际化标签
* @param str
* @return
*/
private static String getI18nString(String str) {
return "<fmt:message key=\"" + str + "\"/>";
}
/**
* @Description: 扫描jsp,提取中文,并翻译,生成国际化资源文件
* @param path 要国际化的jsp文件存储路径
* @param i18nKeyPrefix 国际化key的前缀
* @throws
* @author zhuqz
*/
private static void getChinereWord(String path) {
for (File file : fileList) {
String content = file2String(file, "utf-8");
// 预处理
// 去掉html注释 <!--.*?-->
content = p_html.matcher(content).replaceAll("\n");
// 去掉jsp注释 <%--.*?--%>
content = p_jsp.matcher(content).replaceAll("\n");
// 去掉jsp注释2 /* */
content = p_js1.matcher(content).replaceAll("\n");
// 去掉jsp注释3 //
content = p_js2.matcher(content).replaceAll("\n");
content = p_java.matcher(content).replaceAll("\n");
// 匹配中文
Matcher ma = CHINESE_PATTERN.matcher(content);
boolean has = false;
while (ma.find()) {
// 获取到匹配的中文
String pipei = ma.group().trim();
// 过滤掉不需要匹配的中文内容
if (noReplace.get(ma.group().trim()) != null) {
continue;
}
has = true;
IL8NBean il8 = i18nMatchCache.get(pipei);
if (il8 == null)
il8 = new IL8NBean();
//查找key是否已经被国际化
String pinyinValueKey = existMap.get(pipei);
il8.setChinese(pipei);
il8.setKey(pinyinValueKey == null ?
new StringBuffer(I18N_KEY_PREFIX)
.append(".")
.append(ChineseToPinyin.getAll(pipei))
.toString() : pinyinValueKey);
il8.setFile(file.getAbsolutePath().replace(JSP_SOURCE_PATH, ""));
i18nMatchCache.put(pipei, il8);
System.out.println(ma.group());
}
if (has) {
System.out.println("文件:" + file.getPath());
// break;
}
}
// 打印出全部的中文和生成的key;
for (Map.Entry<String, IL8NBean> e : i18nMatchCache.entrySet()) {
System.out.println(e.getValue().getChinese() + ":::" + e.getValue().getKey());
}
System.out.println(i18nMatchCache.size());
// 翻译
translate(i18nMatchCache);
// 生成i18n文件
createIL8NFile(i18nMatchCache);
}
/**
*
* @Description: 翻译中文为英文,这里都用"english"字符串代替,可以在这里调用翻译工具自动翻译;
* @param map
* @throws
* @author zhuqz
*/
private static void translate(Map<String, IL8NBean> map) {
int i = 0;
for (Map.Entry<String, IL8NBean> e : map.entrySet()) {
try {
e.getValue().setEnglish("english");
} catch (Exception ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
System.out.println(
e.getValue().getChinese() + ":::" + e.getValue().getEnglish() + ":::" + e.getValue().getKey());
System.out.println(map.size() + "--" + (++i));
}
}
/**
* @Description: 生成国际化文件
* @param map
* @throws
* @author zhuqz
*/
private static void createIL8NFile(Map<String, IL8NBean> map) {
Writer osw_eng = null, osw_gbk = null, osw_eng$ = null;
try {
osw_eng = new OutputStreamWriter(new FileOutputStream(I18N_FILE_SAVE_PATH+PROP_NAME_ENG), ENCODING);
osw_gbk = new OutputStreamWriter(new FileOutputStream(I18N_FILE_SAVE_PATH+PROP_NAME_GBK), ENCODING);
osw_eng$ = new OutputStreamWriter(new FileOutputStream(I18N_FILE_SAVE_PATH+PROP_NAME_ENG$), ENCODING);
int existCount = 0;
for (Map.Entry<String, IL8NBean> entry : map.entrySet()) {
// 已经被国际化的key就不再处理了;
if(existMap.get(entry.getKey()) != null){
existCount++;
continue;
}
osw_eng$.write(
"#" + entry.getValue().getChinese() + "--->" + entry.getValue().getFiles().toString() + "\n");
osw_eng$.write(entry.getValue().getKey() + "=$" + entry.getValue().getEnglish() + "$\n");
osw_eng$.write("\n");
osw_eng.write(
"#" + entry.getValue().getChinese() + "--->" + entry.getValue().getFiles().toString() + "\n");
osw_eng.write(entry.getValue().getKey() + "=" + entry.getValue().getEnglish() + "\n");
osw_eng.write("\n");
osw_gbk.write("#" + entry.getValue().getFiles().toString() + "\n");
osw_gbk.write(entry.getValue().getKey() + "=" + entry.getKey() + "\n");
osw_gbk.write("\n");
}
System.out.println("\n\r\n\r生成国际化资源文件");
System.out.println(I18N_FILE_SAVE_PATH+PROP_NAME_GBK);
System.out.println(I18N_FILE_SAVE_PATH+PROP_NAME_ENG);
System.out.println("共有"+map.size()+"个key,"+existCount+"个key已经存在,"+ (map.size() - existCount)+"个key已写入国际化文件");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (osw_eng != null) {
try {
osw_eng.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (osw_eng$ != null) {
try {
osw_eng$.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (osw_gbk != null) {
try {
osw_gbk.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 将文本写入到文件
* @param content
* @param file
*/
public static void string2File(String content, File file) {
try {
Writer osw = new OutputStreamWriter(new FileOutputStream(file), ENCODING);
osw.write(content);
osw.close();
System.out.println("生成国际化jsp文件:"+file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 遍历path目录,获取全部的jsp文件,并将其放入到fileList列表里面;
* @param path
* @param fileList
*/
private static List<File> getJsps(File path) {
List<File> fileList = new ArrayList<File>();
File[] files = path.listFiles();
for (File file : files)
if (file.isDirectory() && !file.isHidden()){
fileList.addAll(getJsps(file));
}else if (file.getName().toLowerCase().endsWith(".jsp")){
fileList.add(file);
System.out.println("需国际化的jsp文件:"+file.getAbsolutePath());
}
return fileList;
}
/**
* 读取文件内容,返回字符串;
* @param file
* @param encoding
* @return
*/
public static String file2String(File file, String encoding) {
StringWriter writer = new StringWriter();
try {
InputStreamReader reader = new InputStreamReader(new FileInputStream(file), encoding);
char[] buffer = new char[BUFF_SIZE];
int n;
while (-1 != (n = reader.read(buffer))) {
writer.write(buffer, 0, n);
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return writer.toString();
}
static class ComparatorStrLength implements Comparator<String> {
public int compare(String str1, String str2) {
int length1 = str1 == null ? 0 : str1.length();
int length2 = str2 == null ? 0 : str2.length();
return length2 - length1;
}
}
}
辅助类
import java.util.HashSet;
import java.util.Set;
/**
* 国际化辅助类
* @author zqz
*/
public class IL8NBean {
/**
* 国际化文件中的key
*/
private String key;
/**
* 需要被国际化的中文
*/
private String chinese;
/**
* 中文翻译后的英文
*/
private String english;
/**
* 记录哪些文件包含有这个中文
*/
private Set<String> files = new HashSet<String>(5);
public void setFile(String file){
files.add(file);
}
public StringBuilder getFiles(){
StringBuilder sb =new StringBuilder();
for(String str:files){
sb.append(str).append(";");
}
return sb;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getEnglish() {
return english;
}
public void setEnglish(String english) {
this.english = english;
}
public String getChinese() {
return chinese;
}
public void setChinese(String chinese) {
this.chinese = chinese;
}
@Override
public String toString() {
return "IL8NBean [key=" + key + ", chinese=" + chinese + ", english=" + english + ", files=" + files + "]";
}
}
获取汉字拼音的工具类
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
/**
* 将中文转换为拼音
* @author zqz
*
*/
public class ChineseToPinyin {
/**
* 获取全拼拼音,如果长度大于40,那么就取每个汉字开头拼音字母;
* @param src
* @return
*/
public static String getAll(String src){
String result= getPingYin(src).replaceAll("\\W", "");
if(result.length()>40){
result = getPinYinHeadChar(src).replaceAll("\\W", "");
}
return result;
}
public static String get(String src){
String result = null;
boolean isHeader = false;
if(src.length()>7){
result = getPinYinHeadChar(src);
isHeader = true;
}else{
result = getPingYin(src);
}
result = result.replaceAll("\\W", "");
if(isHeader && result.length()<6){
result=getPingYin(src).replaceAll("\\W", "");
}
return result;
}
/**
* 首字母转大写
* @param s
* @return
*/
public static String toUpperCaseFirstOne(String s){
if(Character.isUpperCase(s.charAt(0)))
return s;
else
return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
}
/**
* 将汉字转换为全拼
* @param src
* @return
*/
public static String getPingYin(String src) {
char[] t1 = null;
t1 = src.toCharArray();
String[] t2 = new String[t1.length];
HanyuPinyinOutputFormat t3 = new HanyuPinyinOutputFormat();
t3.setCaseType(HanyuPinyinCaseType.LOWERCASE);
t3.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
t3.setVCharType(HanyuPinyinVCharType.WITH_V);
String t4 = "";
int t0 = t1.length;
try {
boolean first = false;
for (int i = 0; i < t0; i++) {
// 判断是否为汉字字符
if (java.lang.Character.toString(t1[i]).matches(
"[\\u4E00-\\u9FA5]+")) {
t2 = PinyinHelper.toHanyuPinyinStringArray(t1[i], t3);
t4 += first?toUpperCaseFirstOne(t2[0]):t2[0];
first = true;
} else
t4 += java.lang.Character.toString(t1[i]);
}
// System.out.println(t4);
return t4;
} catch (BadHanyuPinyinOutputFormatCombination e1) {
e1.printStackTrace();
}
return t4;
}
/**
* 返回中文的首字母
* @param str
* @return
*/
public static String getPinYinHeadChar(String str) {
String convert = "";
for (int j = 0; j < str.length(); j++) {
char word = str.charAt(j);
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
if (pinyinArray != null) {
convert += pinyinArray[0].charAt(0);
} else {
convert += word;
}
}
return convert;
}
/**
* 将字符串转移为ASCII码
* @param cnStr
* @return
*/
public static String getCnASCII(String cnStr) {
StringBuffer strBuf = new StringBuffer();
byte[] bGBK = cnStr.getBytes();
for (int i = 0; i < bGBK.length; i++) {
strBuf.append(Integer.toHexString(bGBK[i] & 0xff));
}
return strBuf.toString();
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
System.out.println(getPingYin("綦江1_qq县").replaceAll("\\W", ""));
System.out.println(getPinYinHeadChar("綦江县"));
System.out.println(getCnASCII("綦江县"));
System.out.println(getAll("綦江县"));
System.out.println(getPingYin("綦江县"));
}
}
依赖的jar包
<!-- https://mvnrepository.com/artifact/com.belerweb/pinyin4j -->
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.0</version>
</dependency>
2018-05-02
又搞了一个对js文件做国际化的工具类:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.fanyti.ChineseToPinyin;
/**
* javascript文件国际化
* js国际化原理就是根据语言加载不同js国际化文件,js国际化文件里面有一个对象,这个对象是当前语言的一个map;
* @author zqz
*
*/
public class Il8nJavascriptTool {
/**文件编码*/
private static final String ENCODING = "utf-8";
/** 文件缓冲大小*/
public static final int BUFF_SIZE = 10240;
/**js国际化资源对象名称,全部的国际化key都会放在这个对象里面;*/
private final static String GLOBAL_VARIABLE_NAME = "message_source_i18n";
/** 现有的国际化文件,只需要中文 **/
private static final String EXIST_I18n_FILES = "E:\\newsysi18n_\\js_i18n_source\\";
/**需要被国际化的js文件,将需要国际化的js文件,按照js文件存放的目录结构,放在这个目录下即可*/
private static final String sourcePath = "E:\\newsysi18n\\";
/**国际化后生成的js文件**/
private static final String targetPath = "E:\\newsysi18n_\\";
/**
* 国际化后生成的key和value文件,将文件中的内容拷贝到一个GLOBAL_VARIABLE_NAME参数指定的名称的js对象中即可
* 例如GLOBAL_VARIABLE_NAME=message_source_i18n, 则生成文件:
1. js_autocreate_i18n_zh_CN.properties文件内容:
com_zqz_bianJi:"编辑",
com_zqz_shanChu:"删除",
com_zqz_add:"添加",
2. js_autocreate_i18n_en.properties文件内容:
com_zqz_bianJi:"edit",
com_zqz_shanChu:"delete",
com_zqz_add:"add",
那么把这些内容分别放到两个js文件中
js_autocreate_i18n_zh_CN.js文件内容:
var message_source_i18n = {
com_zqz_bianJi:"编辑",
com_zqz_shanChu:"删除",
com_zqz_add:"添加"
}
js_autocreate_i18n_en.js文件内容:
var js_autocreate_i18n_en = {
com_zqz_bianJi:"edit",
com_zqz_shanChu:"delete",
com_zqz_add:"add"
}
然后在页面上如果是中文则载入js_autocreate_i18n_zh_CN.js,如果是英文则载入js_autocreate_i18n_en.js文件
*
* */
private static final String PROP_NAME_ENG$ = "$js_autocreate_i18n_en.properties";
private static final String PROP_NAME_ENG = "js_autocreate_i18n_en.properties";
private static final String PROP_NAME_GBK = "js_autocreate_i18n_zh_CN.properties";
/** 缓存现有国际化文件中国际化了的ket和value(只有中文)Entyty<中文,国际化key> **/
private static Map<String, String> existI18nWord = new HashMap<String, String>();
/** 用来存储需要被国际化的key和value,Entyty<中文,IL8NBean> **/
private static final Map<String, IL8NBean> needToI18n = new HashMap<String, IL8NBean>();
private static final Pattern CHINESE_PATTERN = Pattern
.compile("[ \\w\\ufe30-\\uffa0\\u4e00-\\u9fa5]*[\\u4e00-\\u9fa5]+[\\w\\ufe30-\\uffa0\\u4e00-\\u9fa5!。!?]*");
private static final Pattern CHINESE_PATTERN2 = Pattern.compile(
"[\"']?[ \\w\\ufe30-\\uffa0\\u4e00-\\u9fa5]*[\\u4e00-\\u9fa5]+[ \\w\\ufe30-\\uffa0\\u4e00-\\u9fa5!。!?]*[\"']?");
// html注释<!-- XXXX -->
private static String regEx_html = "<!--.*?-->";
private static Pattern p_html = Pattern.compile(regEx_html, Pattern.DOTALL);
// js注释/* XXXX */
private static String regEx_js1 = "/\\*.*?\\*/";
private static Pattern p_js1 = Pattern.compile(regEx_js1, Pattern.DOTALL);
// js注释 // XXXXX
private static String regEx_js2 = "//[\\s\\S]*?\n";
private static Pattern p_js2 = Pattern.compile(regEx_js2, Pattern.CASE_INSENSITIVE);
public static void main(String[] args) {
getExistI18nJsFile();
getChinereWord(sourcePath, "com_lens_");
replace(sourcePath, targetPath);
}
/**
* 获取已经做过国际化的中文及其key
*/
private static void getExistI18nJsFile() {
File[] files = new File(EXIST_I18n_FILES).listFiles();
for (File file : files) {
if (file.getName().endsWith(".js"))
readExistI18nJsFile(file);
}
}
/**
* 按行读取文件内容
*
* @param file
*/
private static void readExistI18nJsFile(File file) {
FileInputStream inputStream = null;
BufferedReader bufferedReader = null;
try {
inputStream = new FileInputStream(file);
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,ENCODING));
String str = null;
while ((str = bufferedReader.readLine()) != null) {
praiseLine(str.trim());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
bufferedReader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/** 匹配js国际化行 **/
private final static String JS_I18N_LINE_PATTERN = "^\\w+:\\s{0,3}[\"\'].+[\"\'],?$";
/**
* 解析国际化行,并放入缓存
*
* @param str
*/
private static void praiseLine(String str) {
if (str == null || "".equals(str)) {
return;
}
if (Pattern.matches(JS_I18N_LINE_PATTERN, str)) {
String key = str.substring(0, str.indexOf(":")).trim();
String value = null;
int startIndex = -1;
if ((startIndex = str.indexOf("\"")) > -1) {
value = str.substring(startIndex + 1, str.lastIndexOf("\""));
} else if ((startIndex = str.indexOf("\'")) > -1) {
value = str.substring(startIndex + 1, str.lastIndexOf("\'"));
}
existI18nWord.put(value, key);
}
}
/**
* 扫描js文件,提取中文,并翻译,生成国际化资源文件
*
* @Description: TODO
* @param path
* @param appName
* @author zhuqz
*/
private static void getChinereWord(String path, String appName) {
List<File> files = new ArrayList<File>();
getJsFiles(new File(path), files);
int fileSize = 0;
for (File file : files) {
String content = file2String(file, "utf-8");
content = p_html.matcher(content).replaceAll("");
content = p_js1.matcher(content).replaceAll("");
content = p_js2.matcher(content).replaceAll("");
Matcher ma = CHINESE_PATTERN.matcher(content);
boolean has = false;
while (ma.find()) {
has = true;
String pipei = ma.group().trim();
IL8NBean il8;
if (existI18nWord.get(pipei) != null) {
il8 = new IL8NBean();
il8.setKey(existI18nWord.get(pipei));
} else {
il8 = needToI18n.get(pipei);
if (il8 == null)
il8 = new IL8NBean();
il8.setKey(new StringBuffer(appName).append(ChineseToPinyin.getAll(pipei)).toString());
}
il8.setFile(file.getAbsolutePath().replace(sourcePath, ""));
il8.setChinese(pipei);
needToI18n.put(pipei, il8);
System.out.println(il8.getChinese() + ":::::" + il8.getKey() + "::::");
}
if (has) {
fileSize++;
System.out.println("文件:" + file.getPath());
}
}
System.out.println(needToI18n.size() + ":::" + fileSize);
translate();
createIL8NFile();
}
private static void replace(String sourcePath, String targetPath) {
/** 国际化map<中文,替换的key> **/
List<File> files = new ArrayList<File>();
getJsFiles(new File(sourcePath), files);
System.out.println("共有文件:" + files.size());
for (File file : files) {
// 查找当前要替换的字符
String content = file2String(file, "utf-8");
content = p_html.matcher(content).replaceAll("");
content = p_js1.matcher(content).replaceAll("");
content = p_js2.matcher(content).replaceAll("");
content = tihuanWithYinHao(needToI18n, file, content);
// 生成国际化文件
File newFile = new File(file.getAbsolutePath().replace(sourcePath, targetPath));
File dir = new File(newFile.getPath().substring(0, newFile.getPath().lastIndexOf("\\")));
if (!dir.exists()) {
dir.mkdirs();
}
string2File(content, newFile);
}
}
/**
* 替换带引号的js代码中的中文 “中文” ,'中文'
*
* @param map
* @param file
* @param content
* @return
* @throws
* @author zhuqz
*/
private static String tihuanWithYinHao(Map<String, IL8NBean> map, File file, String content) {
// System.out.println(content);
/** 本页面匹配到的中文 */
Matcher ma = CHINESE_PATTERN.matcher(content);
Map<String, String> selfMap = new HashMap<String, String>();
while (ma.find()) {
String pipei = ma.group().trim();
String key = map.get(pipei).getKey();
if (key != null) {
selfMap.put(pipei, key);
}
}
/** 开始替换 **/
content = file2String(file, "utf-8");
StringBuffer sb = new StringBuffer();
ma = CHINESE_PATTERN2.matcher(content);
while (ma.find()) {
String pipei = ma.group().trim();
System.out.println(pipei);
String key = null;
if ((pipei.startsWith("'") && pipei.endsWith("'")) || (pipei.startsWith("\"") && pipei.endsWith("\""))) {
System.out.println(pipei.substring(1, pipei.length() - 1));
key = selfMap.get(pipei.substring(1, pipei.length() - 1));
} else
key = selfMap.get(pipei);
ma.appendReplacement(sb, key == null ? ma.group() : getI18nString(pipei, key));
}
ma.appendTail(sb);
return sb.toString();
}
/**
* @Description: js国际化替换
* @param str
* @param key
* @return
* @throws
* @author zhuqz
*/
private static String getI18nString(String str, String key) {
if (str.startsWith("'") && str.endsWith("'")) {
return new StringBuilder(GLOBAL_VARIABLE_NAME).append(".").append(key).toString();
} else if (str.startsWith("\"") && str.endsWith("\"")) {
return new StringBuilder(GLOBAL_VARIABLE_NAME).append(".").append(key).toString();
} else {
return new StringBuilder("'+").append(GLOBAL_VARIABLE_NAME).append(".").append(key).append("+'").toString();
}
}
/**
* 生成国际化文件
*
* @Description: TODO
* @param map
* @throws
* @author zhuqz
*/
private static void createIL8NFile() {
Writer osw_eng = null, osw_gbk = null, osw_eng$ = null;
try {
osw_eng = new OutputStreamWriter(new FileOutputStream(PROP_NAME_ENG), ENCODING);
osw_gbk = new OutputStreamWriter(new FileOutputStream(PROP_NAME_GBK), ENCODING);
osw_eng$ = new OutputStreamWriter(new FileOutputStream(PROP_NAME_ENG$), ENCODING);
for (Map.Entry<String, IL8NBean> entry : needToI18n.entrySet()) {
if (existI18nWord.get(entry.getKey()) != null) {
continue;
}
osw_eng$.write("/**" + entry.getValue().getChinese() + "--->" + entry.getValue().getFiles().toString()
+ "**/\n");
osw_eng$.write(entry.getValue().getKey() + ":\"$" + entry.getValue().getEnglish() + "$\",\n");
osw_eng$.write("\n");
osw_eng.write("/**" + entry.getValue().getChinese() + "--->" + entry.getValue().getFiles().toString()
+ "**/\n");
osw_eng.write(entry.getValue().getKey() + ":\"" + entry.getValue().getEnglish() + "\",\n");
osw_eng.write("\n");
osw_gbk.write("/**" + entry.getValue().getFiles().toString() + "**/\n");
osw_gbk.write(entry.getValue().getKey() + ":\"" + entry.getKey() + "\",\n");
osw_gbk.write("\n");
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (osw_eng != null) {
try {
osw_eng.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (osw_eng$ != null) {
try {
osw_eng$.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (osw_gbk != null) {
try {
osw_gbk.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 翻译
*
* @Description: TODO
* @param map
* @throws
* @author zhuqz
*/
private static void translate() {
int i = 0;
for (Map.Entry<String, IL8NBean> e : needToI18n.entrySet()) {
try {
// e.getValue().setEnglish(TranslateUtil.translate(e.getValue().getChinese(),TranslateUtil.CHINA,
// TranslateUtil.ENGLISH));
e.getValue().setEnglish("english");
} catch (Exception ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
System.out.println(
e.getValue().getChinese() + ":::" + e.getValue().getEnglish() + ":::" + e.getValue().getKey());
System.out.println(needToI18n.size() + "--" + (++i));
}
}
private static void getJsFiles(File path, List<File> fileList) {
File[] files = path.listFiles();
for (File file : files)
if (file.isDirectory() && !file.isHidden())
getJsFiles(file, fileList);
else if (file.getName().toLowerCase().endsWith(".js"))
fileList.add(file);
}
public static String file2String(File file, String encoding) {
StringWriter writer = new StringWriter();
try {
InputStreamReader reader = new InputStreamReader(new FileInputStream(file), encoding);
char[] buffer = new char[BUFF_SIZE];
int n;
while (-1 != (n = reader.read(buffer))) {
writer.write(buffer, 0, n);
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return writer.toString();
}
public static void string2File(String content, File file) {
try {
Writer osw = new OutputStreamWriter(new FileOutputStream(file), ENCODING);
osw.write(content);
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}