BasicCAT开发笔记(十):机器翻译与插件的编写

| 分类 技术随笔  | 标签 CAT 

机器翻译功能的添加是比较简单的一件事情,切换到新的片段时,调用机器翻译API即可。

比如以下是调用谷歌翻译的例子:

Sub googleMT(source As String,sourceLang As String,targetLang As String) As ResumableSub
	Dim target As String
	Dim su As StringUtils
	Dim job As HttpJob
	job.Initialize("job",Me)
	Dim params As String
	params="?key="&Utils.getMap("google",Utils.getMap("mt",Main.preferencesMap)).Get("key")& _ 
	"&q="&su.EncodeUrl(source,"UTF-8")&"&format=text&source="&sourceLang&"&target="&targetLang
	
	job.Download("https://translation.googleapis.com/language/translate/v2"&params)
	wait For (job) JobDone(job As HttpJob)
	If job.Success Then
		Try
			Dim result,data As Map
			Dim json As JSONParser
			json.Initialize(job.GetString)
			result=json.NextObject
			data=result.Get("data")
			Dim translations As List
			translations=data.Get("translations")
			Dim map1 As Map
			map1=translations.Get(0)
			target=map1.Get("translatedText")
		Catch
			target=""
			Log(LastException)
		End Try
	Else
		target=""
	End If
	job.Release
	Return target
End Sub

有些机器翻译可能还要使用md5生成16进制编码的密钥,会复杂一点。

机器翻译的API一般需要设置密钥等信息,我们需要在设置界面里添加设置选项。

因为机器翻译很多,我把它做成了可以用插件来开发的形式。主要使用了ABPlugin这一个库。

在程序开始运行时扫描插件目录里的插件:

Public Sub loadPlugins
	Dim dir As String
	If preferencesMap.ContainsKey("pluginDir") Then
		dir=preferencesMap.Get("pluginDir")
	Else
		dir=File.Combine(File.DirApp,"plugins")
	End If
	plugin.Initialize("plugin",dir, "MyKey")
	plugin.Start(1)
	Log(plugin.GetAvailablePlugins)
End Sub

Sub plugin_PluginsChanged()
	Log("plugins have changed!")
	Log(plugin.GetAvailablePlugins)
	plugin.Stop
End Sub

然后根据插件的名字,判断其功能,将其加入MT列表。如果调用的MT不是内建的MT引擎,则调用对应的插件。

Sub getMTPluginList As List
	Dim mtList As List
	mtList.Initialize
	For Each name As String In Main.plugin.GetAvailablePlugins
		If name.EndsWith("MT") Then
			mtList.Add(name.Replace("MT",""))
		End If
	Next
	Return mtList
End Sub

Sub getMT(source As String,sourceLang As String,targetLang As String,MTEngine As String) As ResumableSub
    ......
	If getMTPluginList.IndexOf(MTEngine)<>-1 Then
		Dim params As Map
		params.Initialize
		params.Put("source",source)
		params.Put("sourceLang",sourceLang)
		params.Put("targetLang",targetLang)
		params.Put("preferencesMap",Main.preferencesMap)
		wait for (Main.plugin.RunPlugin(MTEngine&"MT","translate",params)) complete (result As String)
		Log("pluginMT"&result)
		Return result
	End If
End Sub

以上是主程序需要做的。然后是插件的内容,以下是添加的小牛机器翻译的例子,其中NiceName就是插件的名字,用MT结尾表示其功能,初始化时的key用以保证安全性。

Sub Class_Globals
	Private fx As JFX
End Sub

'Initializes the object. You can NOT add parameters to this method!
Public Sub Initialize() As String
	Log("Initializing plugin " & GetNiceName)
	' Here return a key to prevent running unauthorized plugins
	Return "MyKey"
End Sub

' must be available
public Sub GetNiceName() As String
	Return "niutransMT"
End Sub

' must be available
public Sub Run(Tag As String, Params As Map) As ResumableSub
	Log("run"&Params)
	Select Tag
		Case "getParams"
			Dim paramsList As List
			paramsList.Initialize
			paramsList.Add("key")
			Return paramsList
		Case "translate"
			wait for (translate(Params.Get("source"),Params.Get("sourceLang"),Params.Get("targetLang"),Params.Get("preferencesMap"))) complete (result As String)
			Return result
	End Select
	Return ""
End Sub


Sub translate(source As String, sourceLang As String, targetLang As String,preferencesMap As Map) As ResumableSub
	Dim target As String
	Dim su As StringUtils
	Dim job As HttpJob
	job.Initialize("job",Me)
	Dim params As String
	params="?apikey="&getMap("niutrans",getMap("mt",preferencesMap)).Get("key")&"&src_text="&su.EncodeUrl(source,"UTF-8")&"&from="&sourceLang&"&to="&targetLang
	job.Download("http://api.niutrans.vip/NiuTransServer/translation"&params)
	wait For (job) JobDone(job As HttpJob)
	If job.Success Then
		Log(job.GetString)
		Try
			Dim json As JSONParser
			json.Initialize(job.GetString)
		    target=json.NextObject.Get("tgt_text")
		Catch
			Log(LastException)
		End Try
	Else
		target=""
	End If
	job.Release
	Return target
End Sub


Sub getMap(key As String,parentmap As Map) As Map
	Return parentmap.Get(key)
End Sub

插件需要编译为库来使用。

另外,我在开发亚马逊机器翻译插件时,发现它的签名算法过于复杂,于是直接使用了它提供的java sdk(文档)。但这带来的问题是需要在主程序里包含需要引用的第三方jar。aws translate使用的jar加起来有4MB。插件的话最好是在不改变主程序的情况下就能使用。我采取的解决办法是这样的:写一个命令行工具来调用亚马逊的机器翻译,然后使用插件来运行这个工具,把结果传回主程序。

相关文件:

https://github.com/xulihang/BasicCAT/blob/master/BasicCAT/MT.bas

https://github.com/xulihang/BasicCAT/blob/master/BasicCAT/MTParamsFiller.bas

https://github.com/xulihang/BasicCAT/blob/master/plugins/niutransMT/niuTransMTPlugin.bas


上一篇     下一篇