Android整理需要翻譯的strings資源詳情
1、問(wèn)題描述
項(xiàng)目需要做俄語(yǔ)國(guó)際化,歷史代碼里有的字段有俄語(yǔ)翻譯、有的沒(méi)有,需要把沒(méi)翻譯的中文整理出來(lái)翻譯成俄文。 (因?yàn)轫?xiàng)目組件化module太多了所以覺(jué)得一個(gè)一個(gè)整理很麻煩,如果module不多的話(huà)就可以直接手動(dòng)處理不用整下面這些了)
2、大概思路
- 列出所有
res目錄,根據(jù)是否包含values-ru分成兩組(半自動(dòng)) - 在“不包含”分組里把需要翻譯的中文文件復(fù)制出來(lái)(半自動(dòng))
- 在“包含”組里把需要補(bǔ)充翻譯的字段復(fù)制出來(lái)(純手動(dòng))
- 把復(fù)制出來(lái)需要翻譯的
xml文件轉(zhuǎn)換成excel用于翻譯(自動(dòng)) - 把翻譯好的文件通過(guò)
excel的公式轉(zhuǎn)換成xml,根據(jù)之前記錄的res目錄放到項(xiàng)目里(半自動(dòng))
3、代碼解析
列出所有string.xml文件路徑
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());
}
}
}
手工找出不包含ru的模塊,然后在項(xiàng)目里看一下應(yīng)該翻譯哪個(gè)文件,把需要翻譯的文件路徑放到一個(gè)txt里,例如:
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
復(fù)制這些文件到translate文件夾
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());
}
}
}
手工找出包含ru的模塊,在項(xiàng)目里看一下需要補(bǔ)充翻譯哪些字段,復(fù)制這些字段到新建的xml文件里,把這些xml文件也放在translate文件夾。
把translate文件夾里的文件讀取到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("源路徑不存在");
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;
}
需要引入的依賴(lài):
<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>
因?yàn)椴煌K可能會(huì)有重復(fù)的中文字段,翻譯的同事是去重了翻譯的,所以拿到翻譯好了的excel之后,要把重復(fù)的翻譯填充一下。思路是讀取翻譯前的文件到excelDataBeanList、讀取翻譯后的文件到translatedList,根據(jù)兩個(gè)列表中相同的中文字段填充excelDataBeanList的俄文字段然后輸出到新文件。
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);
//這個(gè)read其實(shí)是按列讀的,并不是根據(jù)列標(biāo)題和類(lèi)屬性名稱(chēng)匹配的
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\翻譯字段.xlsx";
System.out.println("excel list size: " + excelDataBeanList.size());
EasyExcel.write(dst, ExcelDataBean.class).sheet("value").doWrite(excelDataBeanList);
}
}
把excel轉(zhuǎn)換成xml
| A列 | B | C | H | K |
|---|---|---|---|---|
| name | value | translate | 給name加雙引號(hào) | 拼接xml里的string |
| detail_up | 收起 | убрать | =""""&A2&"""" | ="<string name="&H2&">"&C2&"</string>" |
到此這篇關(guān)于Android整理需要翻譯的strings資源詳情的文章就介紹到這了,更多相關(guān)Android整理需要翻譯的strings資源內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android開(kāi)發(fā)導(dǎo)入項(xiàng)目報(bào)錯(cuò)Ignoring InnerClasses attribute for an anonym
今天小編就為大家分享一篇關(guān)于Android開(kāi)發(fā)導(dǎo)入項(xiàng)目報(bào)錯(cuò)Ignoring InnerClasses attribute for an anonymous inner class的解決辦法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
Android實(shí)現(xiàn)基于滑動(dòng)的SQLite數(shù)據(jù)分頁(yè)加載技術(shù)(附demo源碼下載)
這篇文章主要介紹了Android實(shí)現(xiàn)基于滑動(dòng)的SQLite數(shù)據(jù)分頁(yè)加載技術(shù),涉及Android針對(duì)SQLite數(shù)據(jù)的讀取及查詢(xún)結(jié)果的分頁(yè)顯示功能相關(guān)實(shí)現(xiàn)技巧,末尾還附帶demo源碼供讀者下載參考,需要的朋友可以參考下2016-07-07
Android利用MediaRecorder實(shí)現(xiàn)錄音功能
這篇文章主要為大家詳細(xì)介紹了Android利用MediaRecorder實(shí)現(xiàn)錄音功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Android 給RecyclerView添加分割線(xiàn)的具體步驟(分享)
下面小編就為大家?guī)?lái)一篇Android 給RecyclerView添加分割線(xiàn)的具體步驟(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Android實(shí)現(xiàn)探探圖片滑動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)探探圖片滑動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
利用 kotlin 的方式自定義回調(diào)事件(kotlin函數(shù)參數(shù))
這篇文章主要介紹了利用 kotlin 的方式自定義回調(diào)事件(kotlin函數(shù)參數(shù)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
解決 INSTALL FAILED CONFLICTING PROVIDER的問(wèn)題方法
這篇文章主要介紹了解決 INSTALL FAILED CONFLICTING PROVIDER的問(wèn)題方法的相關(guān)資料,需要的朋友可以參考下2017-02-02
詳細(xì)講解AsyncTask使用說(shuō)明(值得收藏)
AsyncTask就相當(dāng)于Android給我們提供了一個(gè)多線(xiàn)程編程的一個(gè)框架,其介于Thread和Handler之間,我們?nèi)绻x一個(gè)AsyncTask,就需要定義一個(gè)類(lèi)來(lái)繼承AsyncTask這個(gè)抽象類(lèi),并實(shí)現(xiàn)其唯一的一doInBackgroud 抽象方法,這篇文章主要介紹了AsyncTask詳解,需要的朋友可以參考下2024-01-01

