Quellcode durchsuchen

feat():Support multiple languages (#554)

* feat():Support multiple languages

Temporarily save

feat():multi language ui msg

feat():uiMsg

* feat():Support ini file format

* feat():Support ini file format

* feat: r.URL.Query().Get(language)

Co-authored-by: EMqmyd <mayuedong@emx.io>
EMQmyd vor 4 Jahren
Ursprung
Commit
e8200157ab

+ 11 - 0
etc/multilingual/en_US.ini

@@ -0,0 +1,11 @@
+[sink]
+not_found_plugin=This plugin was not found:
+type_conversion_fail=Type conversion failed:
+[source]
+not_found_plugin=This plugin was not found:
+not_found_confkey=This confkey was not found:
+confkey_already_exist=This confkey already exists:
+json_marshal_fail=Failed to format json data:
+type_conversion_fail=Type conversion failed:
+not_found_file=Can't find this file:
+write_data_fail=Failed to write data to file:

+ 11 - 0
etc/multilingual/zh_CN.ini

@@ -0,0 +1,11 @@
+[sink]
+not_found_plugin=没有找到这个插件:
+type_conversion_fail=类型转换错误:
+[source]
+not_found_plugin=没有找到这个插件:
+not_found_confkey=没有找到这个配置项:
+confkey_already_exist=这个配置项已经存在:
+json_marshal_fail=格式化 json 错误:
+type_conversion_fail=类型转换错误:
+not_found_file=找不到这个文件:
+write_data_fail=数据写入文件失败:

+ 1 - 0
go.mod

@@ -20,6 +20,7 @@ require (
 	github.com/sirupsen/logrus v1.4.2
 	github.com/urfave/cli v1.22.0
 	golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553
+	gopkg.in/ini.v1 v1.62.0
 )
 
 go 1.15

+ 3 - 0
plugins/manager.go

@@ -222,6 +222,9 @@ func NewPluginManager() (*Manager, error) {
 		if err := singleton.readFuncMetaDir(); nil != err {
 			common.Log.Errorf("readFuncMetaDir:%v", err)
 		}
+		if err := singleton.readUiMsgDir(); nil != err {
+			common.Log.Errorf("readUiMsgDir:%v", err)
+		}
 	})
 	return singleton, outerErr
 }

+ 46 - 0
plugins/msg_util.go

@@ -0,0 +1,46 @@
+package plugins
+
+import (
+	"github.com/emqx/kuiper/common"
+	ini "gopkg.in/ini.v1"
+	"io/ioutil"
+	"path"
+)
+
+var g_uiMsg map[string]*ini.File
+
+func getMsg(language, section, key string) string {
+	language += ".ini"
+	if conf, ok := g_uiMsg[language]; ok {
+		s := conf.Section(section)
+		if s != nil {
+			return s.Key(key).String()
+		}
+	}
+	return ""
+}
+func (m *Manager) readUiMsgDir() error {
+	g_uiMsg = make(map[string]*ini.File)
+	confDir, err := common.GetConfLoc()
+	if nil != err {
+		return err
+	}
+
+	dir := path.Join(confDir, "multilingual")
+	infos, err := ioutil.ReadDir(dir)
+	if nil != err {
+		return err
+	}
+
+	for _, info := range infos {
+		fName := info.Name()
+		common.Log.Infof("uiMsg file : %s", fName)
+		fPath := path.Join(dir, fName)
+		if conf, err := ini.Load(fPath); nil != err {
+			return err
+		} else {
+			g_uiMsg[fName] = conf
+		}
+	}
+	return nil
+}

+ 20 - 17
plugins/sinkMeta.go

@@ -13,6 +13,8 @@ import (
 const (
 	baseProperty = `properties`
 	baseOption   = `options`
+	sink         = `sink`
+	source       = `source`
 )
 
 type (
@@ -80,6 +82,7 @@ type (
 		CustomProperty map[string]*uiSink `json:"customProperty"`
 		BaseProperty   map[string]*uiSink `json:"baseProperty"`
 		BaseOption     *uiSink            `json:"baseOption"`
+		language       string
 	}
 )
 
@@ -219,7 +222,7 @@ func (this *uiSinks) setCustomProperty(pluginName string) error {
 	sinkMetadata := g_sinkMetadata
 	data := sinkMetadata[fileName]
 	if nil == data {
-		return fmt.Errorf(`not found pligin:%s`, fileName)
+		return fmt.Errorf(`%s%s`, getMsg(this.language, sink, "not_found_plugin"), pluginName)
 	}
 	if 0 == len(this.CustomProperty) {
 		this.CustomProperty = make(map[string]*uiSink)
@@ -232,7 +235,7 @@ func (this *uiSinks) setBasePropertry(pluginName string) error {
 	sinkMetadata := g_sinkMetadata
 	data := sinkMetadata[baseProperty+".json"]
 	if nil == data {
-		return fmt.Errorf(`not found pligin:%s`, baseProperty)
+		return fmt.Errorf(`%s%s`, getMsg(this.language, sink, "not_found_plugin"), baseProperty)
 	}
 	if 0 == len(this.BaseProperty) {
 		this.BaseProperty = make(map[string]*uiSink)
@@ -245,7 +248,7 @@ func (this *uiSinks) setBaseOption() error {
 	sinkMetadata := g_sinkMetadata
 	data := sinkMetadata[baseOption+".json"]
 	if nil == data {
-		return fmt.Errorf(`not found pligin:%s`, baseOption)
+		return fmt.Errorf(`%s%s`, getMsg(this.language, sink, "not_found_plugin"), baseOption)
 	}
 	this.BaseOption = data
 	return nil
@@ -264,7 +267,7 @@ func (this *uiSinks) hintWhenNewSink(pluginName string) (err error) {
 	return err
 }
 
-func modifyCustom(uiFields []*field, ruleFields map[string]interface{}) (err error) {
+func (this *uiSinks) modifyCustom(uiFields []*field, ruleFields map[string]interface{}) (err error) {
 	for i, ui := range uiFields {
 		ruleVal := ruleFields[ui.Name]
 		if nil == ruleVal {
@@ -273,14 +276,14 @@ func modifyCustom(uiFields []*field, ruleFields map[string]interface{}) (err err
 		if reflect.Map == reflect.TypeOf(ruleVal).Kind() {
 			var auxRuleFields map[string]interface{}
 			if err := common.MapToStruct(ruleVal, &auxRuleFields); nil != err {
-				return fmt.Errorf("%s:%v", ui.Name, err)
+				return fmt.Errorf(`%s%v %s`, getMsg(this.language, sink, "type_conversion_fail"), err, ui.Name)
 			}
 			var auxUiFields []*field
 			if err := common.MapToStruct(ui.Default, &auxUiFields); nil != err {
-				return fmt.Errorf("%s:%v", ui.Name, err)
+				return fmt.Errorf(`%s%v %s`, getMsg(this.language, sink, "type_conversion_fail"), err, ui.Name)
 			}
 			uiFields[i].Default = auxUiFields
-			if err := modifyCustom(auxUiFields, auxRuleFields); nil != err {
+			if err := this.modifyCustom(auxUiFields, auxRuleFields); nil != err {
 				return err
 			}
 		} else {
@@ -289,32 +292,29 @@ func modifyCustom(uiFields []*field, ruleFields map[string]interface{}) (err err
 	}
 	return nil
 }
-func (this *uiSink) modifyBase(mapFields map[string]interface{}) (err error) {
+func (this *uiSink) modifyBase(mapFields map[string]interface{}) {
 	for i, field := range this.Fields {
 		fieldVal := mapFields[field.Name]
 		if nil != fieldVal {
 			this.Fields[i].Default = fieldVal
 		}
 	}
-	return nil
 }
 
 func (this *uiSinks) modifyProperty(pluginName string, mapFields map[string]interface{}) (err error) {
 	custom := this.CustomProperty[pluginName]
 	if nil == custom {
-		return fmt.Errorf(`not found pligin:%s`, pluginName)
+		return fmt.Errorf(`%s%s`, getMsg(this.language, sink, "not_found_plugin"), pluginName)
 	}
-	if err = modifyCustom(custom.Fields, mapFields); nil != err {
+	if err = this.modifyCustom(custom.Fields, mapFields); nil != err {
 		return err
 	}
 
 	base := this.BaseProperty[pluginName]
 	if nil == base {
-		return fmt.Errorf(`not found pligin:%s`, pluginName)
-	}
-	if err = base.modifyBase(mapFields); nil != err {
-		return err
+		return fmt.Errorf(`%s%s`, getMsg(this.language, sink, "not_found_plugin"), pluginName)
 	}
+	base.modifyBase(mapFields)
 	return nil
 }
 
@@ -351,15 +351,18 @@ func (this *uiSinks) hintWhenModifySink(rule *api.Rule) (err error) {
 			if nil != err {
 				return err
 			}
-			this.modifyProperty(pluginName, mapFields)
+			if err := this.modifyProperty(pluginName, mapFields); nil != err {
+				return err
+			}
 		}
 	}
 	this.modifyOption(rule.Options)
 	return nil
 }
 
-func GetSinkMeta(pluginName string, rule *api.Rule) (ptrSinkProperty *uiSinks, err error) {
+func GetSinkMeta(pluginName, language string, rule *api.Rule) (ptrSinkProperty *uiSinks, err error) {
 	ptrSinkProperty = new(uiSinks)
+	ptrSinkProperty.language = language
 	if nil == rule {
 		err = ptrSinkProperty.hintWhenNewSink(pluginName)
 	} else {

+ 43 - 35
plugins/sourceMeta.go

@@ -138,7 +138,7 @@ func (m *Manager) readSourceMetaDir() error {
 	return nil
 }
 
-func GetSourceConf(pluginName string) (b []byte, err error) {
+func GetSourceConf(pluginName, language string) (b []byte, err error) {
 	property, ok := g_sourceProperty[pluginName+".json"]
 	if ok {
 		cf := make(map[string]map[string]interface{})
@@ -149,17 +149,21 @@ func GetSourceConf(pluginName string) (b []byte, err error) {
 			}
 			cf[key] = common.ConvertMap(aux)
 		}
-		return json.Marshal(cf)
+		if b, err = json.Marshal(cf); nil != err {
+			return nil, fmt.Errorf(`%s%v`, getMsg(language, source, "json_marshal_fail"), cf)
+		} else {
+			return b, err
+		}
 	}
-	return nil, fmt.Errorf("not found plugin %s", pluginName)
+	return nil, fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_plugin"), pluginName)
 }
 
-func GetSourceMeta(pluginName string) (ptrSourceProperty *uiSource, err error) {
+func GetSourceMeta(pluginName, language string) (ptrSourceProperty *uiSource, err error) {
 	property, ok := g_sourceProperty[pluginName+".json"]
 	if ok {
-		return property.cfToMeta()
+		return property.cfToMeta(language)
 	}
-	return nil, fmt.Errorf("not found plugin %s", pluginName)
+	return nil, fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_plugin"), pluginName)
 }
 
 func GetSources() (sources []*pluginfo) {
@@ -200,19 +204,19 @@ func GetSourceConfKeys(pluginName string) (keys []string) {
 	return keys
 }
 
-func DelSourceConfKey(pluginName, confKey string) error {
+func DelSourceConfKey(pluginName, confKey, language string) error {
 	property := g_sourceProperty[pluginName+".json"]
 	if nil == property {
-		return fmt.Errorf("not found plugin %s", pluginName)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_plugin"), pluginName)
 	}
 	if nil == property.cf {
-		return fmt.Errorf("not found confKey %s", confKey)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_confkey"), confKey)
 	}
 	delete(property.cf, confKey)
-	return property.saveCf(pluginName)
+	return property.saveCf(pluginName, language)
 }
 
-func AddSourceConfKey(pluginName, confKey string, content []byte) error {
+func AddSourceConfKey(pluginName, confKey, language string, content []byte) error {
 	reqField := make(map[string]interface{})
 	err := json.Unmarshal(content, &reqField)
 	if nil != err {
@@ -221,7 +225,7 @@ func AddSourceConfKey(pluginName, confKey string, content []byte) error {
 
 	property := g_sourceProperty[pluginName+".json"]
 	if nil == property {
-		return fmt.Errorf("not found plugin %s", pluginName)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_plugin"), pluginName)
 	}
 
 	if nil == property.cf {
@@ -229,15 +233,15 @@ func AddSourceConfKey(pluginName, confKey string, content []byte) error {
 	}
 
 	if 0 != len(property.cf[confKey]) {
-		return fmt.Errorf("exist confKey %s", confKey)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "confkey_already_exist"), pluginName)
 	}
 
 	property.cf[confKey] = reqField
 	g_sourceProperty[pluginName+".json"] = property
-	return property.saveCf(pluginName)
+	return property.saveCf(pluginName, language)
 }
 
-func AddSourceConfKeyField(pluginName, confKey string, content []byte) error {
+func AddSourceConfKeyField(pluginName, confKey, language string, content []byte) error {
 	reqField := make(map[string]interface{})
 	err := json.Unmarshal(content, &reqField)
 	if nil != err {
@@ -246,24 +250,24 @@ func AddSourceConfKeyField(pluginName, confKey string, content []byte) error {
 
 	property := g_sourceProperty[pluginName+".json"]
 	if nil == property {
-		return fmt.Errorf("not found plugin %s", pluginName)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_plugin"), pluginName)
 	}
 
 	if nil == property.cf {
-		return fmt.Errorf("not found confKey %s", confKey)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_confkey"), confKey)
 	}
 
 	if nil == property.cf[confKey] {
-		return fmt.Errorf("not found confKey %s", confKey)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_confkey"), confKey)
 	}
 
 	for k, v := range reqField {
 		property.cf[confKey][k] = v
 	}
-	return property.saveCf(pluginName)
+	return property.saveCf(pluginName, language)
 }
 
-func recursionDelMap(cf, fields map[string]interface{}) error {
+func recursionDelMap(cf, fields map[string]interface{}, language string) error {
 	for k, v := range fields {
 		if nil == v {
 			delete(cf, k)
@@ -278,7 +282,7 @@ func recursionDelMap(cf, fields map[string]interface{}) error {
 
 			var auxCf map[string]interface{}
 			if err := common.MapToStruct(cf[k], &auxCf); nil != err {
-				return fmt.Errorf("not found second key:%s.%s", k, delKey)
+				return fmt.Errorf(`%s%s.%s`, getMsg(language, source, "type_conversion_fail"), k, delKey)
 			}
 			cf[k] = auxCf
 			delete(auxCf, delKey)
@@ -287,13 +291,13 @@ func recursionDelMap(cf, fields map[string]interface{}) error {
 		if reflect.Map == reflect.TypeOf(v).Kind() {
 			var auxCf, auxFields map[string]interface{}
 			if err := common.MapToStruct(cf[k], &auxCf); nil != err {
-				return fmt.Errorf("not found second key:%s.%v", k, v)
+				return fmt.Errorf(`%s%s.%v`, getMsg(language, source, "type_conversion_fail"), k, v)
 			}
 			cf[k] = auxCf
 			if err := common.MapToStruct(v, &auxFields); nil != err {
-				return fmt.Errorf("requestef format err:%s.%v", k, v)
+				return fmt.Errorf(`%s%s.%v`, getMsg(language, source, "type_conversion_fail"), k, v)
 			}
-			if err := recursionDelMap(auxCf, auxFields); nil != err {
+			if err := recursionDelMap(auxCf, auxFields, language); nil != err {
 				return err
 			}
 		}
@@ -301,7 +305,7 @@ func recursionDelMap(cf, fields map[string]interface{}) error {
 	return nil
 }
 
-func DelSourceConfKeyField(pluginName, confKey string, content []byte) error {
+func DelSourceConfKeyField(pluginName, confKey, language string, content []byte) error {
 	reqField := make(map[string]interface{})
 	err := json.Unmarshal(content, &reqField)
 	if nil != err {
@@ -310,22 +314,22 @@ func DelSourceConfKeyField(pluginName, confKey string, content []byte) error {
 
 	property := g_sourceProperty[pluginName+".json"]
 	if nil == property {
-		return fmt.Errorf("not found plugin %s", pluginName)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_plugin"), pluginName)
 	}
 
 	if nil == property.cf {
-		return fmt.Errorf("not found confKey %s", confKey)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_confkey"), confKey)
 	}
 
 	if nil == property.cf[confKey] {
-		return fmt.Errorf("not found confKey %s", confKey)
+		return fmt.Errorf(`%s%s`, getMsg(language, source, "not_found_confkey"), confKey)
 	}
 
-	err = recursionDelMap(property.cf[confKey], reqField)
+	err = recursionDelMap(property.cf[confKey], reqField, language)
 	if nil != err {
 		return err
 	}
-	return property.saveCf(pluginName)
+	return property.saveCf(pluginName, language)
 }
 
 func recursionNewFields(template []*field, conf map[string]interface{}, ret *[]*field) error {
@@ -369,14 +373,14 @@ func recursionNewFields(template []*field, conf map[string]interface{}, ret *[]*
 	return nil
 }
 
-func (this *sourceProperty) cfToMeta() (*uiSource, error) {
+func (this *sourceProperty) cfToMeta(language string) (*uiSource, error) {
 	fields := this.meta.ConfKeys["default"]
 	ret := make(map[string][]*field)
 	for k, kvs := range this.cf {
 		var sli []*field
 		err := recursionNewFields(fields, kvs, &sli)
 		if nil != err {
-			return nil, err
+			return nil, fmt.Errorf(`%s%v`, getMsg(language, "source", "type_conversion_fail"), err)
 		}
 		ret[k] = sli
 	}
@@ -386,10 +390,10 @@ func (this *sourceProperty) cfToMeta() (*uiSource, error) {
 	return meta, nil
 }
 
-func (this *sourceProperty) saveCf(pluginName string) error {
+func (this *sourceProperty) saveCf(pluginName, language string) error {
 	confDir, err := common.GetConfLoc()
 	if nil != err {
-		return err
+		return fmt.Errorf(`%s%v`, getMsg(language, source, "not_found_file"), err)
 	}
 
 	dir := path.Join(confDir, "sources")
@@ -398,5 +402,9 @@ func (this *sourceProperty) saveCf(pluginName string) error {
 		dir = confDir
 	}
 	filePath := path.Join(dir, pluginName+".yaml")
-	return common.WriteYamlMarshal(filePath, this.cf)
+	err = common.WriteYamlMarshal(filePath, this.cf)
+	if nil != err {
+		return fmt.Errorf(`%s%v`, getMsg(language, "source", "write_data_fail"), err)
+	}
+	return nil
 }

+ 3 - 3
plugins/sourceMeta_test.go

@@ -37,7 +37,7 @@ func TestGetSourceMeta(t *testing.T) {
 	g_sourceProperty = make(map[string]*sourceProperty)
 	g_sourceProperty[g_file] = source
 
-	showMeta, err := GetSourceMeta(g_plugin)
+	showMeta, err := GetSourceMeta(g_plugin, "zh_CN")
 	if nil != err {
 		t.Error(err)
 	}
@@ -47,14 +47,14 @@ func TestGetSourceMeta(t *testing.T) {
 	addData := `{"url":"127.0.0.1","method":"post","headers":{"Accept":"json"}}`
 	delData := `{"method":"","headers":{"Accept":""}}`
 
-	if err := AddSourceConfKey(g_plugin, "new", []byte(addData)); nil != err {
+	if err := AddSourceConfKey(g_plugin, "new", "zh_CN", []byte(addData)); nil != err {
 		t.Error(err)
 	}
 	if err := isAddData(addData, cf[`new`]); nil != err {
 		t.Error(err)
 	}
 
-	if err := DelSourceConfKeyField(g_plugin, "new", []byte(delData)); nil != err {
+	if err := DelSourceConfKeyField(g_plugin, "new", "zh_CN", []byte(delData)); nil != err {
 		t.Error(err)
 	}
 	if err := isDelData(delData, cf[`new`]); nil != err {

+ 48 - 14
xstream/server/server/rest.go

@@ -569,9 +569,14 @@ func newSinkMetaHandler(w http.ResponseWriter, r *http.Request) {
 	vars := mux.Vars(r)
 	pluginName := vars["name"]
 
-	ptrMetadata, err := plugins.GetSinkMeta(pluginName, nil)
+	v := r.URL.Query()
+	language := v.Get("language")
+	if 0 == len(language) {
+		language = "en_US"
+	}
+	ptrMetadata, err := plugins.GetSinkMeta(pluginName, language, nil)
 	if err != nil {
-		handleError(w, err, "metadata error", logger)
+		handleError(w, err, "", logger)
 		return
 	}
 	jsonResponse(ptrMetadata, w, logger)
@@ -589,9 +594,14 @@ func showSinkMetaHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	ptrMetadata, err := plugins.GetSinkMeta("", rule)
+	v := r.URL.Query()
+	language := v.Get("language")
+	if 0 == len(language) {
+		language = "en_US"
+	}
+	ptrMetadata, err := plugins.GetSinkMeta("", language, rule)
 	if err != nil {
-		handleError(w, err, "metadata error", logger)
+		handleError(w, err, "", logger)
 		return
 	}
 	jsonResponse(ptrMetadata, w, logger)
@@ -620,9 +630,14 @@ func sourceMetaHandler(w http.ResponseWriter, r *http.Request) {
 	defer r.Body.Close()
 	vars := mux.Vars(r)
 	pluginName := vars["name"]
-	ret, err := plugins.GetSourceMeta(pluginName)
+	v := r.URL.Query()
+	language := v.Get("language")
+	if 0 == len(language) {
+		language = "en_US"
+	}
+	ret, err := plugins.GetSourceMeta(pluginName, language)
 	if err != nil {
-		handleError(w, err, "metadata error", logger)
+		handleError(w, err, "", logger)
 		return
 	}
 	if nil != ret {
@@ -636,9 +651,14 @@ func sourceConfHandler(w http.ResponseWriter, r *http.Request) {
 	defer r.Body.Close()
 	vars := mux.Vars(r)
 	pluginName := vars["name"]
-	ret, err := plugins.GetSourceConf(pluginName)
+	v := r.URL.Query()
+	language := v.Get("language")
+	if 0 == len(language) {
+		language = "en_US"
+	}
+	ret, err := plugins.GetSourceConf(pluginName, language)
 	if err != nil {
-		handleError(w, err, "metadata error", logger)
+		handleError(w, err, "", logger)
 		return
 	} else {
 		w.Write(ret)
@@ -666,19 +686,26 @@ func sourceConfKeyHandler(w http.ResponseWriter, r *http.Request) {
 	vars := mux.Vars(r)
 	pluginName := vars["name"]
 	confKey := vars["confKey"]
+
+	v := r.URL.Query()
+	language := v.Get("language")
+	if 0 == len(language) {
+		language = "en_US"
+	}
+
 	switch r.Method {
 	case http.MethodDelete:
-		err = plugins.DelSourceConfKey(pluginName, confKey)
+		err = plugins.DelSourceConfKey(pluginName, confKey, language)
 	case http.MethodPost:
 		v, err := ioutil.ReadAll(r.Body)
 		if err != nil {
 			handleError(w, err, "Invalid body", logger)
 			return
 		}
-		err = plugins.AddSourceConfKey(pluginName, confKey, v)
+		err = plugins.AddSourceConfKey(pluginName, confKey, language, v)
 	}
 	if err != nil {
-		handleError(w, err, "metadata error", logger)
+		handleError(w, err, "", logger)
 		return
 	}
 	if nil != ret {
@@ -700,14 +727,21 @@ func sourceConfKeyFieldsHandler(w http.ResponseWriter, r *http.Request) {
 		handleError(w, err, "Invalid body", logger)
 		return
 	}
+
+	val := r.URL.Query()
+	language := val.Get("language")
+	if 0 == len(language) {
+		language = "en_US"
+	}
+
 	switch r.Method {
 	case http.MethodDelete:
-		err = plugins.DelSourceConfKeyField(pluginName, confKey, v)
+		err = plugins.DelSourceConfKeyField(pluginName, confKey, language, v)
 	case http.MethodPost:
-		err = plugins.AddSourceConfKeyField(pluginName, confKey, v)
+		err = plugins.AddSourceConfKeyField(pluginName, confKey, language, v)
 	}
 	if err != nil {
-		handleError(w, err, "metadata error", logger)
+		handleError(w, err, "", logger)
 		return
 	}
 	if nil != ret {