Android collates details of strings resources to be translated
- 2021-12-21 04:56:08
- OfStack
1. Problem description
The project needs to be internationalized in Russian. Some fields in the history code have Russian translation, while others have not. It is necessary to sort out the untranslated Chinese and translate it into Russian. (Because the project is componentized
module
Too much, so I feel that it is very troublesome to sort out one by one. If module is not much, I can directly handle it manually without the following)
2. General ideas
List all
res
Directory, depending on whether it contains
values-ru
Divide into two groups (semi-automatic)
Copy the Chinese files to be translated in the "Not Included" group (semi-automatic)
Copy the fields that need supplementary translation in the "Include" group (only manually)
Copy what needs to be translated
xml
File is converted into
excel
Used for translation (automatic)
Pass the translated document through
excel
Convert the formula of to
xml
Based on the res directory previously recorded, put it into the project (semi-automatic)
3. Code parsing
List all string. xml file paths
public static void listResPath(String src) throws Exception {
File path1 = new File(src);
if (!path1.exists()) {
return;
}
File[] items = path1.listFiles();
if (items == null) return;
for (File item : items) {
if (item.isFile()) {
if (!item.getName().equals("strings.xml")) continue;
System.out.println(item.getPath());
} else {
listResPath(item.getPath());
}
}
}
Manually find out the module that does not contain ru, and then look at which file should be translated under 1 in the project, and put the file path that needs to be translated into 1 txt, for example:
D:\work\aaa\src\main\res\values-zh-rCN\strings.xml
D:\work\bbb\src\main\res\values-zh-rCN\strings.xml
D:\work\ccc\src\main\res\values\strings.xml
D:\work\ddd\src\main\res\values-zh\strings.xml
Copy these files to the translate folder
private static List<String> needCopyFiles = new ArrayList<>();
private static void getNeedCopyFiles() {
try {
FileInputStream inputStream = new FileInputStream("D:\xxx\needCopy.txt");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String str;
while ((str = bufferedReader.readLine()) != null) {
if (!str.isEmpty()) {
needCopyFiles.add(str);
}
}
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void listResPath(String src) throws Exception {
File path1 = new File(src);
File path2 = new File("D:\xxx\translate");
if (!path1.exists()) {
return;
}
File[] items = path1.listFiles();
if (items == null) return;
for (File item : items) {
if (item.isFile()) {
if (!item.getName().equals("strings.xml")) continue;
if (needCopyFiles.contains(item.getPath())) {
System.out.println(item.getPath());
FileInputStream fis = new FileInputStream(item);
String[] dir = item.getPath().split("\\");
String fileName = dir[7]+dir[8]+".xml";
FileOutputStream fos = new FileOutputStream(path2 + File.separator + fileName);
byte[] b = new byte[1024];
for (int i=0; (i=fis.read(b))!=-1;) {
fos.write(b,0,i);
fos.flush();
}
fos.close();
fis.close();
}
} else {
listResPath(item.getPath());
}
}
}
Manually find out the module containing ru, see which fields need to be supplemented and translated in the project 1, copy these fields to the newly created xml file, and put these xml files in
translate
Folder.
Read the files in the translate folder to excel
import com.alibaba.excel.EasyExcel;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.*;
public class Strings2Excel {
private static final List<ExcelDataBean> excelDataBeanList = new ArrayList<>();
public static void main(String[] args) {
try {
traverseFile("D:\xxx\translate");
write2Excel();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void write2Excel() {
String dst = "D:\xxx\res.xlsx";
System.out.println("excel list size: " + excelDataBeanList.size());
EasyExcel.write(dst, ExcelDataBean.class).sheet("value").doWrite(excelDataBeanList);
}
public static void traverseFile(String src) throws Exception {
File path1 = new File(src);
if (!path1.exists()) {
System.out.println(" Source path does not exist ");
return;
}
File[] items = path1.listFiles();
if (items == null) return;
for (File item : items) {
readXml(item);
}
}
private static void readXml(File file) throws DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(file);
Element rootElement = document.getRootElement();
Iterator<Element> iterator = rootElement.elementIterator();
while (iterator.hasNext()) {
Element child = iterator.next();
String name = child.attribute(0).getValue();
String value = child.getStringValue();
System.out.println(name + " = " + value);
excelDataBeanList.add(new ExcelDataBean(name, value));
}
}
}
@Data
public class ExcelDataBean {
private String name;
private String value;
private String translate;
}
Dependencies to be introduced:
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.4</version>
</dependency>
<!--xls-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
</dependency>
</dependencies>
Because different modules may have duplicate Chinese text paragraphs, the translation colleagues have re-translated, so they get the translated ones
excel
After that, fill in the duplicate translation under 1. The idea is to read the file before translation to
excelDataBeanList
Read the translated file to
res
0
Based on the same Chinese field in both lists
excelDataBeanList
And then output it to a new file.
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class FillTranslated {
private static final List<ExcelDataBean> excelDataBeanList = new ArrayList<>();
private static final List<ExcelDataBean> translatedList = new ArrayList<>();
public static void main(String[] args) {
try {
readRes("D:\xxx\res.xlsx");
} catch (Exception e) {
e.printStackTrace();
}
}
private static void readRes(String s) {
File file = new File(s);
EasyExcel.read(file, ExcelDataBean.class, new AnalysisEventListener<ExcelDataBean>() {
@Override
public void invoke(ExcelDataBean bean, AnalysisContext analysisContext) {
excelDataBeanList.add(bean);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
readTranslated("D:\xxx\translated.xlsx");
}
}).sheet().doRead();
}
private static void readTranslated(String s) {
File file = new File(s);
// This read It is actually read by column, not matched by column heading and class attribute name
EasyExcel.read(file, ExcelDataBean.class, new AnalysisEventListener<ExcelDataBean>() {
@Override
public void invoke(ExcelDataBean bean, AnalysisContext analysisContext) {
translatedList.add(bean);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
fillTranslated();
write2Excel();
}
}).sheet().doRead();
}
private static void fillTranslated() {
for (ExcelDataBean bean : translatedList) {
excelDataBeanList.forEach(a -> {
if (a.getValue() != null && a.getValue().equals(bean.getValue())) {
a.setTranslate(bean.getTranslate());
}
});
}
}
private static void write2Excel() {
String dst = "D:\xxx\ Translation field .xlsx";
System.out.println("excel list size: " + excelDataBeanList.size());
EasyExcel.write(dst, ExcelDataBean.class).sheet("value").doWrite(excelDataBeanList);
}
}
Convert excel to xml
A列 | B | C | H | K |
---|---|---|---|---|
name | value | translate | 给name加双引号 | 拼接xml里的string |
detail_up | 收起 | убрать | =""""&A2&"""" | ="<string name="&H2&">"&C2&"</string>" |