原文章:https://blog.csdn.net/pifutan/article/details/78554691。结合原文按照自己需求,实现功能。效果如下:
功能实现:
使用Android自带Spinner
<LinearLayout
android:id="@+id/ll_top_translate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/vv_top_translate_trans">
<Spinner
android:layout_marginLeft="10dp"
android:spinnerMode="dropdown"
android:id="@+id/sp_untranslated"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"></Spinner>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_switch_translate" />
<Spinner
android:layout_marginRight="10dp"
android:layout_weight="1"
android:id="@+id/sp_translated"
android:layout_width="0dp"
android:layout_height="wrap_content"></Spinner>
</LinearLayout>
activity里面使用固定两组数组为Spinner绑定数据,一组负责显示,另一组负责根据选择的位置获取语言代码,两个数组是一一对应的
final String[] languageArr = {"Automatic", "Afrikaans", "Albanian", "Arabic", "Armenian", "Azerbaijani", "Basque", "Belarusian", "Bengali", "Bosnian", "Bulgarian", "Catalan", "Cebuano", "Chichewa", "Chinese Simplified", "Chinese Traditional", "Corsican", "Croatian", "Czech", "Danish", "Dutch", "English", "Esperanto", "Estonian", "Filipino", "Finnish", "French", "Frisian", "Galician", "Georgian", "German", "Greek", "Gujarati", "Haitian Creole", "Hausa", "Hawaiian", "Hebrew", "Hindi", "Hmong", "Hungarian", "Icelandic", "Igbo", "Indonesian", "Irish", "Italian", "Japanese", "Javanese", "Kannada", "Kazakh", "Khmer", "Korean", "Kurdish (Kurmanji)", "Kyrgyz", "Lao", "Latin", "Latvian", "Lithuanian", "Luxembourgish", "Macedonian", "Malagasy", "Malay", "Malayalam", "Maltese", "Maori", "Marathi", "Mongolian", "Myanmar (Burmese)", "Nepali", "Norwegian", "Pashto", "Persian", "Polish", "Portuguese", "Punjabi", "Romanian", "Russian", "Samoan", "Scots Gaelic", "Serbian", "Sesotho", "Shona", "Sindhi", "Sinhala", "Slovak", "Slovenian", "Somali", "Spanish","Sudanese", "Swahili", "Swedish", "Tajik", "Tamil", "Telugu", "Thai", "Turkish", "Ukrainian", "Urdu", "Uzbek", "Vietnamese", "Welsh", "Xhosa", "Yiddish", "Yoruba", "Zulu"
};
final String[] languageCode = {"auto", "af", "sq", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "ny", "zh-cn", "zh-tw", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "tl", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "iw", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jw", "kn", "kk", "km", "ko", "ku", "ky", "lo", "la", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ps", "fa", "pl", "pt", "ma", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tg", "ta", "te", "th", "tr", "uk", "ur", "uz", "vi", "cy", "xh", "yi", "yo", "zu"};
Spinner sp_untranslated = findViewById(R.id.sp_untranslated);
Spinner sp_translated = findViewById(R.id.sp_translated);
给Spinner设置adapter,adapter条目的布局是自己定义的
//创建ArrayAdapter对象
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.spinner_checked_text, languageArr) {
@Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
View view = inflate(getContext(), R.layout.spinner_item_layout,
null);
TextView label = (TextView) view
.findViewById(R.id.spinner_item_label);
label.setText(languageArr[position]);
return view;
}
};
adapter.setDropDownViewResource(R.layout.spinner_item_layout);
sp_untranslated.setAdapter(adapter);
sp_translated.setAdapter(adapter);
/**输入选项监听*/
sp_untranslated.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (languageCode[position] != null) {
selectTranslatedCode = languageCode[position];//翻译的输入语言,定义的全局变量
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
/**输出选项监听*/
sp_translated.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (languageCode[position] != null) {
targetTranslatedCode = languageCode[position];//翻译的目标语言,定义的全局变量
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
条目布局:spinner_item_layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:padding="15dp" >
<TextView
android:gravity="center_horizontal"
android:id="@+id/spinner_item_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
请求代码(拷贝原文的):
/**
* 翻译回调
*/
public interface TranslateCallback{
public void onTranslateDone(String result);
}
/**
* 翻译工具类
*/
public class TranslateUtil {
public static final String TRANSLATE_BASE_URL = "https://translate.google.cn/"; // 不需要翻墙即可使用
// public static final String TRANSLATE_SINGLE_URL = "https://translate.google.cn/translate_a/single?client=gtx&sl=en&tl=zh&dt=t&q=Do%20not%20work%20overtime%20tonight";
public static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
private static String LAN_AUTO = "auto";
/**
* 翻译,包含http请求,需要异步,返回""则为翻译失败
* @param sourceLan 源语言,如en,自动检测为auto
* @param targetLan 目标语言如zh
* @param content 翻译文本
* @return ""为翻译失败,其余成功
*/
public void translate(Context context, String sourceLan, String targetLan, String content, TranslateCallback callback) {
TranslateTask task = new TranslateTask(context, sourceLan, targetLan, content, callback);
task.executeOnExecutor(Executors.newCachedThreadPool());
}
/**
* 使用异步任务来翻译,翻译完成后回调callback
*/
class TranslateTask extends AsyncTask<Void, Void, String> {
String sourceLan;
String targetLan;
String content;
Context context;
TranslateCallback callback;
private LoadingDalog loadingDalog = null; // 这个请自己定义加载中对话框,或者干脆不使用
TranslateTask(Context context, String sourceLan, String targetLan, String content, TranslateCallback callback){
this.context = context;
this.content = content;
this.callback = callback;
this.sourceLan = sourceLan;
this.targetLan = targetLan;
}
@Override
protected String doInBackground(Void... params) {
String result = "";
if (content == null || content.equals("")) {
return result;
}
try {
String googleResult = "";
// 新建一个URL对象
URL url = new URL(getTranslateUrl(sourceLan, targetLan, content));
// 打开一个HttpURLConnection连接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
// 设置连接主机超时时间
urlConn.setConnectTimeout(5 * 1000);
//设置从主机读取数据超时
urlConn.setReadTimeout(5 * 1000);
// 设置是否使用缓存 默认是true
urlConn.setUseCaches(false);
// 设置为Post请求
urlConn.setRequestMethod("GET");
//urlConn设置请求头信息
urlConn.setRequestProperty("User-Agent", USER_AGENT);
//设置请求中的媒体类型信息。
// urlConn.setRequestProperty("Content-Type", "application/json");
//设置客户端与服务连接类型
// urlConn.addRequestProperty("Connection", "Keep-Alive");
// 开始连接
urlConn.connect();
// 判断请求是否成功
int statusCode = urlConn.getResponseCode();
if (statusCode == 200) {
// 获取返回的数据
googleResult = streamToString(urlConn.getInputStream());
}
// 关闭连接
urlConn.disconnect();
// 处理返回结果,拼接
JSONArray jsonArray = new JSONArray(googleResult).getJSONArray(0);
for (int i = 0; i < jsonArray.length(); i++) {
result += jsonArray.getJSONArray(i).getString(0);
}
} catch (Exception e) {
// result = "翻译失败";
e.printStackTrace();
result = "";
}
Log.d("TAG", "翻译结果:" + result);
return result;
}
@Override
protected void onPostExecute(String result) {
if (loadingDalog != null && loadingDalog.isShowing()) {
loadingDalog.cancel();
}
if (callback != null){
callback.onTranslateDone(result);
}
super.onPostExecute(result);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
String str = context.getString(R.string.translating);
try {
loadingDalog = new LoadingDalog(context);// Dialog使用、初始化
loadingDalog.setMessage(str);
loadingDalog.show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 将输入流转换成字符串
*
* @param is 从网络获取的输入流
* @return 字符串
*/
public static String streamToString(InputStream is) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
is.close();
byte[] byteArray = out.toByteArray();
return new String(byteArray);
} catch (Exception e) {
return null;
}
}
public void translate(Context context, String targetLan, String content, TranslateCallback callback) {
translate(context, LAN_AUTO, targetLan, content, callback);
}
private static String getTranslateUrl(String sourceLan, String targetLan, String content) {
try {
return TRANSLATE_BASE_URL + "translate_a/single?client=gtx&sl=" + sourceLan + "&tl=" + targetLan + "&dt=t&q=" + URLEncoder.encode(content, "UTF-8");
} catch (Exception e) {
return TRANSLATE_BASE_URL + "translate_a/single?client=gtx&sl=" + sourceLan + "&tl=" + targetLan + "&dt=t&q=" + content;
}
}
// 使用
TranslateCallback translateCallback = new TranslateCallback() {
@Override
public void onTranslateDone(String result) {
// result是翻译结果,在这里使用翻译结果,比如使用对话框显示翻译结果
}
}
调用时:
new TranslateUtil().translate(this, this.selectTranslatedCode, this.targetTranslatedCode, untranslatedText, translateCallback);
在上方TranslateCallback的onTranslateDone里面获取翻译结果显示到页面
-------------------------------------------------------------------------------------------------------------------------------------------
原文讲解:
例子:
https://translate.google.cn/translate_a/single?client=gtx&sl=en&tl=zh&dt=t&q=Do%20not%20work%20overtime%20tonight
在浏览器打开会下载一个f.txt的文件,内容为:
[[[“今晚不要加班”,”Do not work overtime tonight”,null,null,3]],null,”en”]。
在android中使用流的方式接收,转化为json进行相应处理即可。
如果翻译很长比如:
https://translate.google.cn/translate_a/single?client=gtx&sl=en&tl=zh&dt=t&q=The%20world%27s%20first%20railless%20train%20is%20tested%20in%20Zhuzhou,%20Central%20China%27s%20Hunan%20province,%20on%20Oct%2023,%202017.%20The%2030-meter%20train%20has%20three%20carriages%20and%20is%20developed%20by%20CRRC%20Zhuzhou%20Locomotive%20Co%20Ltd.%20The%20train%20can%20move%20at%20a%20speed%20of%2070%20km/h%20and%20can%20carry%20up%20to%20500%20passengers.
返回内容会是这个样子的:
[[[“2017年10月23日,中国中部湖南省株洲市测试了世界上第一列无轨列车.30米长的列车有三个车厢,由中国中车株洲机车有限公司开发,列车时速可达70公里/”,”The world’s first railless train is tested in Zhuzhou, Central China’s Hunan province, on Oct 23, 2017. The 30-meter train has three carriages and is developed by CRRC Zhuzhou Locomotive Co Ltd. The train can move at a speed of 70 km/”,null,null,3],[“小时,可载500名乘客。”,”h and can carry up to 500 passengers.”,null,null,3]],null,”en”]
只要进行相应处理与拼接即可。
sl=en 为source language,可设置为auto。
tl=zh 为target language,设置为目标语言。
注意在android中使用HttpURLConnection的话,需要设置User-Agent如:HttpURLConnection.setRequestProperty(“User-Agent”, “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36”);
支持的语言:
“auto”:””Automatic”,
“af”:”Afrikaans”,
“sq”:”Albanian”,
“ar”:”Arabic”,
“hy”:”Armenian”,
“az”:”Azerbaijani”,
“eu”:”Basque”,
“be”:”Belarusian”,
“bn”:”Bengali”,
“bs”:”Bosnian”,
“bg”:”Bulgarian”,
“ca”:”Catalan”,
“ceb”:”Cebuano”,
“ny”:”Chichewa”,
“zh-cn”:”Chinese Simplified”,
“zh-tw”:”Chinese Traditional”,
“co”:”Corsican”,
“hr”:”Croatian”,
“cs”:”Czech”,
“da”:”Danish”,
“nl”:”Dutch”,
“en”:”English”,
“eo”:”Esperanto”,
“et”:”Estonian”,
“tl”:”Filipino”,
“fi”:”Finnish”,
“fr”:”French”,
“fy”:”Frisian”,
“gl”:”Galician”,
“ka”:”Georgian”,
“de”:”German”,
“el”:”Greek”,
“gu”:”Gujarati”,
“ht”:”Haitian Creole”,
“ha”:”Hausa”,
“haw”:”Hawaiian”,
“iw”:”Hebrew”,
“hi”:”Hindi”,
“hmn”:”Hmong”,
“hu”:”Hungarian”,
“is”:”Icelandic”,
“ig”:”Igbo”,
“id”:”Indonesian”,
“ga”:”Irish”,
“it”:”Italian”,
“ja”:”Japanese”,
“jw”:”Javanese”,
“kn”:”Kannada”,
“kk”:”Kazakh”,
“km”:”Khmer”,
“ko”:”Korean”,
“ku”:”Kurdish (Kurmanji)”,
“ky”:”Kyrgyz”,
“lo”:”Lao”,
“la”:”Latin”,
“lv”:”Latvian”,
“lt”:”Lithuanian”,
“lb”:”Luxembourgish”,
“mk”:”Macedonian”,
“mg”:”Malagasy”,
“ms”:”Malay”,
“ml”:”Malayalam”,
“mt”:”Maltese”,
“mi”:”Maori”,
“mr”:”Marathi”,
“mn”:”Mongolian”,
“my”:”Myanmar (Burmese)”,
“ne”:”Nepali”,
“no”:”Norwegian”,
“ps”:”Pashto”,
“fa”:”Persian”,
“pl”:”Polish”,
“pt”:”Portuguese”,
“ma”:”Punjabi”,
“ro”:”Romanian”,
“ru”:”Russian”,
“sm”:”Samoan”,
“gd”:”Scots Gaelic”,
“sr”:”Serbian”,
“st”:”Sesotho”,
“sn”:”Shona”,
“sd”:”Sindhi”,
“si”:”Sinhala”,
“sk”:”Slovak”,
“sl”:”Slovenian”,
“so”:”Somali”,
“es”:”Spanish”,
“su”:”Sudanese”,
“sw”:”Swahili”,
“sv”:”Swedish”,
“tg”:”Tajik”,
“ta”:”Tamil”,
“te”:”Telugu”,
“th”:”Thai”,
“tr”:”Turkish”,
“uk”:”Ukrainian”,
“ur”:”Urdu”,
“uz”:”Uzbek”,
“vi”:”Vietnamese”,
“cy”:”Welsh”,
“xh”:”Xhosa”,
“yi”:”Yiddish”,
“yo”:”Yoruba”,
“zu”:”Zulu”