Android开发中,有做过国际化的同学都知道,如果公司没有专门的翻译团队,需要开发自行翻译多国语言,是一件非常痛苦的事情。通常我们的做法是:
复制一行–>到百度翻译或谷歌翻译–>选取目标翻译语言–>复制翻译结果到对应的xml文件里。
这样有什么弊端呢?这是纯体力活,如果只有几行还好,但是上千行呢?如果只需翻译一两种外语还好,但是二十多种语言呢?岂不得累死,那么我们能不能相对优雅地完成翻译呢?
答案是可以的。首先,选择谷歌翻译,因为几乎支持所有语言互译,不要想着谷歌提供免费的api给我们使用,人家靠着这个赚钱呢,所以那些寻找免费api的同学可以歇歇了。我们思路如下:
用正则对原string.xml【①】进行处理,只保留value到另一个string.xml【②】文件里,一个value对应一行,然后一次性复制【②】的文本到谷歌翻译里,选择目标语言进行翻译,拷贝所有的翻译结果到【②】里保存,注意是override而不是append,并把相对应的key保存到一个List里。最后通过读取【②】中的行,与List的key拼接起来,就可以输出翻译结果到string.xml【③】了。代码如下:
注:使用Eclipse运行。
import java.io.BufferedReader;
import java.io.BufferedWriter;
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.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 javax.swing.JFrame;
import javax.swing.JOptionPane;
/**
*
* @author ZZC
*
* 功能:本程序为辅助翻译工具,协助Android开发人员快速把一个纯英文的strings.xml文件的字符串翻译成其他语言
* 使用:
* ① 拷贝未经翻译的strings.xml到项目的input文件夹里,运行程序,会在temp文件夹里生成临时文件
* ② 打开临时文件,ctrl+a, ctrl+c复制所有内容,拷贝到谷歌翻译进行相应翻译:https://translate.google.cn/
* ③ 拷贝翻译结果,覆盖粘贴到temp文件夹里的临时文件里保存,ctrl+s保存
* ④ 执行点击对话框的“确定”按钮,会在out文件夹生成翻译后的string.xml文件
*
*/
public class MainActivity {
private static Map<String, List<String>> fileNameKeyMap = new HashMap<>();
public static void main(String[] args) {
File inputDir = new File("input");
if (!inputDir.exists()) {
inputDir.mkdirs();
}
File[] inputFiles = inputDir.listFiles();
if (inputFiles == null || inputFiles.length == 0) {
System.out.println("input文件夹为空");
return;
}
for (File inputFile : inputFiles) {
generateTemp(inputFile);
}
JFrame jf=new JFrame();
jf.setAlwaysOnTop(true);
int input = JOptionPane.showConfirmDialog(jf, "请拷贝temp文件夹下的文本内容进行翻译,然后用翻译结果覆盖temp文件夹的文本内容并保存,完成之后,请点击确定按钮", "易翻译", JOptionPane.CLOSED_OPTION, JOptionPane.ERROR_MESSAGE);
if (input == JOptionPane.OK_OPTION || input == JOptionPane.CLOSED_OPTION) {
generateTarget();
System.exit(0);
}
}
/**
* 步骤一:
* 在temp文件夹内生成临时的翻译文本,执行完毕后,直接复制到谷歌翻译里进行翻译,翻译完成之后,需要复制翻译后的内容覆盖临时翻译文本,然后执行
* @param inputFile
*/
private static void generateTemp(File inputFile) {
List<String> keyList = new ArrayList<>();
StringBuilder inputBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), "UTF-8"));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
inputBuilder.append(line);
}
} catch (FileNotFoundException e) {
System.out.println("文件" + inputFile.getAbsolutePath() + "不存在");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
System.out.println("读取文件出错");
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
bufferedReader = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
String rawContent = inputBuilder.toString();
if (rawContent == null || rawContent.equals("")) {
// 说明内容为空
return;
}
// 查找行
String findLineRegStr = "<string[^>]*?>[\\s\\S]*?</string>";
Pattern findLinePattern = Pattern.compile(findLineRegStr);
Matcher findLineMatcher = findLinePattern.matcher(rawContent);
String findMiddleRegStr = ">[\\s\\S]*?</string>";
Pattern findMiddlePattern = Pattern.compile(findMiddleRegStr);
List<String> tempValueList = new ArrayList<>();
while (findLineMatcher.find()) {
String oneStr = findLineMatcher.group();
if (oneStr == null || oneStr.equals("")) {
System.out.println("请注意,请先去掉空行");
return;
}
oneStr = oneStr.replaceAll("\r", " ");
if (oneStr == null || oneStr.equals("")) {
System.out.println("请注意,请先去掉空行");
return;
}
//System.out.println(oneLineStr);
Matcher findMiddleMatcher = findMiddlePattern.matcher(oneStr);
if (findMiddleMatcher.find()) {
String tempValue = findMiddleMatcher.group();
// >,</string>最小长度为10
if (tempValue != null && !tempValue.equals("") && tempValue.length() >= 10) {
if (tempValue.length() == 10) {
System.out.println("请注意,请先去掉空值行:" + tempValue);
return;
}
// 去掉>
String withSuffixValue = tempValue.substring(1, tempValue.length());
// 去掉</string>
String value = withSuffixValue.substring(0, withSuffixValue.length()-9);
String[] lineSplits = oneStr.split(">");
if (lineSplits == null) {
System.out.println("这一行没有加入翻译:" + inputFile.getName() + ":" + oneStr);
continue;
}
if (lineSplits.length != 2) {
System.out.println("这一行没有加入翻译:" + inputFile.getName() + ":" + oneStr);
continue;
}
tempValueList.add(value);
keyList.add(lineSplits[0]);
}
}
}
if (tempValueList.size() == 0) {
System.out.println("没有需要翻译的语句");
return;
}
File tempDir = new File("temp");
if (!tempDir.exists()) {
tempDir.mkdirs();
}
FileOutputStream writerStream;
BufferedWriter tempWriter = null;
try {
writerStream = new FileOutputStream(new File(tempDir, inputFile.getName()), false);
tempWriter = new BufferedWriter(new OutputStreamWriter(writerStream, "UTF-8"));
for (int i = 0, len = tempValueList.size()-1; i <= len; i++) {
String value = tempValueList.get(i);
tempWriter.write(value);
if (i != len) {
tempWriter.newLine();
}
}
tempWriter.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (tempWriter != null) {
try {
tempWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
fileNameKeyMap.put(inputFile.getName(), keyList);
}
/**
* 步骤二:
* 在out文件夹生成最终的翻译文件
*/
private static void generateTarget() {
File tempDir = new File("temp");
if (!tempDir.exists()) {
System.out.println("请先执行步骤一");
return;
}
File[] tempFiles = tempDir.listFiles();
if (tempFiles == null || tempFiles.length == 0) {
System.out.println("请先执行步骤一");
return;
}
File outDir = new File("out");
if (!outDir.exists()) {
outDir.mkdirs();
}
String suffix = "</string>";
String prefix = ">";
for (File tempFile : tempFiles) {
BufferedReader bufferedReader = null;
BufferedWriter tempWriter = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(tempFile), "UTF-8"));
FileOutputStream writerStream = new FileOutputStream(new File("out", tempFile.getName()), false);
tempWriter = new BufferedWriter(new OutputStreamWriter(writerStream, "UTF-8"));
String line = null;
List<String> keyList = fileNameKeyMap.get(tempFile.getName());
if (keyList == null || keyList.size() == 0) {
continue;
}
int index = 0;
while ((line = bufferedReader.readLine()) != null) {
if (index >= keyList.size()) {
System.out.println("此value没有对应的key,请检查:" + line);
break;
}
String realLine = keyList.get(index) + prefix + line + suffix;
tempWriter.write(realLine);
tempWriter.newLine();
tempWriter.flush();
index++;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
System.out.println("读取文件出错");
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
bufferedReader = null;
} catch (IOException e) {
e.printStackTrace();
}
}
if (tempWriter != null) {
try {
tempWriter.close();
tempWriter = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
System.out.println("处理完毕,请查看out文件夹的文件");
}
}