{"action":"created","issue":{"url":"https://api.github.com/repos/go-playground/validator/issues/230","labels_url":"https://api.github.com/repos/go-playground/validator/issues/230/labels{/name}","comments_url":"https://api.github.com/repos/go-playground/validator/issues/230/comments","events_url":"https://api.github.com/repos/go-playground/validator/issues/230/events","html_url":"https://github.com/go-playground/validator/issues/230","id":125609746,"number":230,"title":"when will i18n support? as the error message need to local freqeuently","user":{"login":"whidbey","id":2766777,"avatar_url":"https://avatars.githubusercontent.com/u/2766777?v=3","gravatar_id":"","url":"https://api.github.com/users/whidbey","html_url":"https://github.com/whidbey","followers_url":"https://api.github.com/users/whidbey/followers","following_url":"https://api.github.com/users/whidbey/following{/other_user}","gists_url":"https://api.github.com/users/whidbey/gists{/gist_id}","starred_url":"https://api.github.com/users/whidbey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whidbey/subscriptions","organizations_url":"https://api.github.com/users/whidbey/orgs","repos_url":"https://api.github.com/users/whidbey/repos","events_url":"https://api.github.com/users/whidbey/events{/privacy}","received_events_url":"https://api.github.com/users/whidbey/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/go-playground/validator/labels/question","name":"question","color":"cc317c"}],"state":"open","locked":false,"assignee":{"login":"joeybloggs","id":8068371,"avatar_url":"https://avatars.githubusercontent.com/u/8068371?v=3","gravatar_id":"","url":"https://api.github.com/users/joeybloggs","html_url":"https://github.com/joeybloggs","followers_url":"https://api.github.com/users/joeybloggs/followers","following_url":"https://api.github.com/users/joeybloggs/following{/other_user}","gists_url":"https://api.github.com/users/joeybloggs/gists{/gist_id}","starred_url":"https://api.github.com/users/joeybloggs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joeybloggs/subscriptions","organizations_url":"https://api.github.com/users/joeybloggs/orgs","repos_url":"https://api.github.com/users/joeybloggs/repos","events_url":"https://api.github.com/users/joeybloggs/events{/privacy}","received_events_url":"https://api.github.com/users/joeybloggs/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/go-playground/validator/milestones/14","html_url":"https://github.com/go-playground/validator/milestones/v8","labels_url":"https://api.github.com/repos/go-playground/validator/milestones/14/labels","id":1287522,"number":14,"title":"v8","description":null,"creator":{"login":"joeybloggs","id":8068371,"avatar_url":"https://avatars.githubusercontent.com/u/8068371?v=3","gravatar_id":"","url":"https://api.github.com/users/joeybloggs","html_url":"https://github.com/joeybloggs","followers_url":"https://api.github.com/users/joeybloggs/followers","following_url":"https://api.github.com/users/joeybloggs/following{/other_user}","gists_url":"https://api.github.com/users/joeybloggs/gists{/gist_id}","starred_url":"https://api.github.com/users/joeybloggs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joeybloggs/subscriptions","organizations_url":"https://api.github.com/users/joeybloggs/orgs","repos_url":"https://api.github.com/users/joeybloggs/repos","events_url":"https://api.github.com/users/joeybloggs/events{/privacy}","received_events_url":"https://api.github.com/users/joeybloggs/received_events","type":"User","site_admin":false},"open_issues":3,"closed_issues":35,"state":"open","created_at":"2015-09-03T01:14:02Z","updated_at":"2016-01-08T13:37:57Z","due_on":null,"closed_at":null},"comments":1,"created_at":"2016-01-08T13:11:41Z","updated_at":"2016-01-08T13:49:50Z","closed_at":null,"body":"thax"},"comment":{"url":"https://api.github.com/repos/go-playground/validator/issues/comments/170008304","html_url":"https://github.com/go-playground/validator/issues/230#issuecomment-170008304","issue_url":"https://api.github.com/repos/go-playground/validator/issues/230","id":170008304,"user":{"login":"joeybloggs","id":8068371,"avatar_url":"https://avatars.githubusercontent.com/u/8068371?v=3","gravatar_id":"","url":"https://api.github.com/users/joeybloggs","html_url":"https://github.com/joeybloggs","followers_url":"https://api.github.com/users/joeybloggs/followers","following_url":"https://api.github.com/users/joeybloggs/following{/other_user}","gists_url":"https://api.github.com/users/joeybloggs/gists{/gist_id}","starred_url":"https://api.github.com/users/joeybloggs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joeybloggs/subscriptions","organizations_url":"https://api.github.com/users/joeybloggs/orgs","repos_url":"https://api.github.com/users/joeybloggs/repos","events_url":"https://api.github.com/users/joeybloggs/events{/privacy}","received_events_url":"https://api.github.com/users/joeybloggs/received_events","type":"User","site_admin":false},"created_at":"2016-01-08T13:49:50Z","updated_at":"2016-01-08T13:49:50Z","body":"I think you are essentially asking the same thing as in issue https://github.com/go-playground/validator/issues/174#issuecomment-142464644\r\n\r\nAlthough it is about custom messages this directly applies to i18n.\r\n\r\nTo summarize, and this is exactly how I use validator myself, after validating if there are errors I range over them and use the FieldError properties to:\r\n* Create my own error message\r\n* Apply i18n translations\r\n\r\nhere is a quick snippet of how I do it ( it could be greatly refined, but just haven't found time )\r\n```go\r\n// TranslateValidationErrors returns a map of translated error\r\n// key = field, value = translation\r\nfunc TranslateValidationErrors(errs validator.ValidationErrors, t *i18n.Translator) map[string]string {\r\n\r\n    translatedErrs := map[string]string{}\r\n\r\n    for k, v := range errs {\r\n        translatedErrs[k] = TranslateValidationError(v, t)\r\n    }\r\n\r\n    return translatedErrs\r\n}\r\n\r\n// TranslateValidationError determines the translation type based off of the ErrorTag and call appropriate translation methods\r\nfunc TranslateValidationError(err *validator.FieldError, t *i18n.Translator) string {\r\n\r\n    switch err.Tag {\r\n    case \"required\":\r\n        return translateRequiredValidationError(t, err)\r\n    case \"len\":\r\n        return translateLenValidationError(t, err)\r\n    case \"min\":\r\n        return translateMinValidationError(t, err)\r\n    case \"max\":\r\n        return translateMaxValidationError(t, err)\r\n    case \"gt\":\r\n        return translateGtValidationError(t, err)\r\n    case \"lt\":\r\n        return translateLtValidationError(t, err)\r\n    case \"gte\":\r\n        return translateGteValidationError(t, err)\r\n    case \"lte\":\r\n        return translateLteValidationError(t, err)\r\n    case \"gtfield\":\r\n        return translateGtFieldValidationError(t, err)\r\n    case \"gtefield\":\r\n        return translateGteFieldValidationError(t, err)\r\n    case \"ltfield\":\r\n        return translateLtFieldValidationError(t, err)\r\n    case \"ltefield\":\r\n        return translateLteFieldValidationError(t, err)\r\n    case \"alpha\":\r\n        return translateAlphaValidationError(t, err)\r\n    case \"alphanum\":\r\n        return translateAlphanumValidationError(t, err)\r\n    case \"numeric\":\r\n        return translateNumericValidationError(t, err)\r\n    case \"hexadecimal\":\r\n        return translateHexadecimalValidationError(t, err)\r\n    case \"hexcolor\":\r\n        return translateHexColorValidationError(t, err)\r\n    case \"rgb\":\r\n        return translateRGBColorValidationError(t, err)\r\n    case \"rgba\":\r\n        return translateRGBAColorValidationError(t, err)\r\n    case \"rgb|rgba\":\r\n        return translateRGBOrRGBAColorValidationError(t, err)\r\n    case \"hsl\":\r\n        return translateHSLColorValidationError(t, err)\r\n    case \"hsla\":\r\n        return translateHSLAColorValidationError(t, err)\r\n    case \"hsl|hsla\":\r\n        return translateHSLOrHSLAColorValidationError(t, err)\r\n    case \"email\":\r\n        return translateEmailValidationError(t, err)\r\n    case \"url\":\r\n        return translateURLValidationError(t, err)\r\n    case \"uri\":\r\n        return translateURIValidationError(t, err)\r\n    case \"base64\":\r\n        return translateBase64ValidationError(t, err)\r\n    case \"eq\":\r\n        return translateEqValidationError(t, err)\r\n    case \"eqfield\":\r\n        return translateEqFieldValidationError(t, err)\r\n    case \"ne\":\r\n        return translateNeValidationError(t, err)\r\n    case \"nefield\":\r\n        return translateNeFieldValidationError(t, err)\r\n    case \"uniqueuserusername\":\r\n        return translateUniqueUserUsernameValidationError(t, err)\r\n    case \"uniqueuseremail\":\r\n        return translateUniqueUserEmailValidationError(t, err)\r\n    case \"uniquewpname\":\r\n        return translateUniqueWeeklPreferenceNameValidationError(t, err)\r\n    case \"contains\":\r\n        return translateContainsValidationError(t, err)\r\n    case \"containsany\":\r\n        return translateContainsAnyValidationError(t, err)\r\n    case \"containsrune\":\r\n        return translateContainsRuneValidationError(t, err)\r\n    case \"excludes\":\r\n        return translateExcludesValidationError(t, err)\r\n    case \"excludesall\":\r\n        return translateExcludesAllValidationError(t, err)\r\n    case \"excludesrune\":\r\n        return translateExcludesRuneValidationError(t, err)\r\n    }\r\n\r\n    return \"\"\r\n}\r\n\r\n// translateExcludesRuneValidationError translates the excludesrune validation error based off of the fields data type\r\nfunc translateExcludesRuneValidationError(t *i18n.Translator, err *validator.FieldError) string {\r\n\r\n    return Translate(t, \"Validation_ExcludesRune\", map[string]string{\r\n        \"rune\": \"\\\"\" + err.Param + \"\\\"\",\r\n    })\r\n}\r\n\r\n// translateExcludesAllValidationError translates the excludesall validation error based off of the fields data type\r\nfunc translateExcludesAllValidationError(t *i18n.Translator, err *validator.FieldError) string {\r\n\r\n    buff := bytes.NewBufferString(\"\")\r\n\r\n    for i := range err.Param {\r\n        buff.WriteString(\",\\\"\")\r\n        buff.WriteString(err.Param[i : i+1])\r\n        buff.WriteString(\"\\\"\")\r\n    }\r\n\r\n    return Translate(t, \"Validation_ExcludesAll\", map[string]string{\r\n        \"chars\":\r\n...\r\n```"}}