{"id":44077760,"url":"https://github.com/jzero-io/protovalidate-translator","last_synced_at":"2026-02-11T10:01:14.239Z","repository":{"id":336772781,"uuid":"1150449610","full_name":"jzero-io/protovalidate-translator","owner":"jzero-io","description":"protovalidate translator","archived":false,"fork":false,"pushed_at":"2026-02-06T06:46:27.000Z","size":71,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-10T13:18:46.614Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jzero-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-05T09:42:42.000Z","updated_at":"2026-02-06T06:46:31.000Z","dependencies_parsed_at":"2026-02-06T12:03:35.671Z","dependency_job_id":null,"html_url":"https://github.com/jzero-io/protovalidate-translator","commit_stats":null,"previous_names":["jzero-io/protovalidate-translator"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jzero-io/protovalidate-translator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jzero-io%2Fprotovalidate-translator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jzero-io%2Fprotovalidate-translator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jzero-io%2Fprotovalidate-translator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jzero-io%2Fprotovalidate-translator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jzero-io","download_url":"https://codeload.github.com/jzero-io/protovalidate-translator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jzero-io%2Fprotovalidate-translator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29331592,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T06:13:03.264Z","status":"ssl_error","status_checked_at":"2026-02-11T06:12:55.843Z","response_time":97,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-08T07:50:42.616Z","updated_at":"2026-02-11T10:01:14.222Z","avatar_url":"https://github.com/jzero-io.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# protovalidate-translator\n\n**Read in:** English | [中文](README.zh.md)\n\nLocalized messages for [protovalidate](https://github.com/bufbuild/protovalidate) rule IDs. Use with [go-i18n](https://github.com/nicksnyder/go-i18n) and template placeholders such as `{{.Value}}`.\n\n## Install\n\n```bash\ngo get github.com/jzero-io/protovalidate-translator/translator\n```\n\n## Quick start\n\nUse the built-in embedded locales (en + zh):\n\n```go\nimport \"github.com/jzero-io/protovalidate-translator/translator\"\n\nmsg, _ := translator.TranslateDefault(\"zh\", \"float.lt\", map[string]any{\"Value\": 100})\n// msg == \"值必须小于 100\"\n\nmsgTW,_ := translator.TranslateDefault(\"zh-TW\", \"float.lt\", map[string]any{\"Value\": 100})\n// msg == \"值必須小於 100\"\n\nmsgEn, _ := translator.TranslateDefault(\"en\", \"float.lt\", map[string]any{\"Value\": 100})\n// msgEn == \"value must be less than 100\"\n```\n\n## Example\n\nRun the example:\n\n```bash\ngo run ./examples/translate/main.go\n```\n\nIt prints sample translations for a few rule IDs in English and Chinese.\n\n## Usage with validation errors\n\nAfter validating with protovalidate, use the violation’s rule ID and value to get a localized message:\n\n```go\nerr := validator.Validate(msg)\nvar valErr *protovalidate.ValidationError\nif errors.As(err, \u0026valErr) {\n    for _, v := range valErr.Violations {\n        ruleID := v.Proto.GetRuleId()\n        data := map[string]any{\"Value\": v.RuleValue.Interface()}\n        message, _ := translator.TranslateDefault(\"zh\", ruleID, data)\n        // message is the localized error string\n    }\n}\n```\n\n## Custom locales\n\nLoad your own locale directory (go-i18n JSON):\n\n```go\nbundle, err := translator.LoadBundleFromDir(\"./locales\")\nmsg, _ := translator.Translate(bundle, \"zh\", \"en\", \"float.lt\", map[string]any{\"Value\": 100})\n```\n\nOr from an embedded FS:\n\n```go\n//go:embed locales/*.json\nvar locales embed.FS\n\nbundle, _ := translator.LoadBundleFromFS(locales, \"locales\")\nmsg, _ := translator.Translate(bundle, \"zh\", \"en\", \"float.lt\", data)\n```\n\n## Extending the default bundle\n\nYou can add locales or single messages to the default bundle (used by `TranslateDefault`). **Register before the first call to `DefaultBundle` or `TranslateDefault`.**\n\nAdd a locale file from disk:\n\n```go\ntranslator.AddDefaultLocaleFile(\"./locales/custom.json\")\nmsg, _ := translator.TranslateDefault(\"zh\", \"float.lt\", data)\n```\n\nAdd a locale file from an `fs.FS` (e.g. embed):\n\n```go\n//go:embed custom.json\nvar customFS embed.FS\n\ntranslator.AddDefaultLocaleFromFS(customFS, \"custom.json\")\n```\n\nAdd a single message (overrides or adds for that language):\n\n```go\ntranslator.AddDefaultMessage(\"zh\", \"my.rule\", \"自訂：{{.Value}}\")\nmsg, _ := translator.TranslateDefault(\"zh\", \"my.rule\", map[string]any{\"Value\": 1})\n```\n\nFor full control, use a customizer:\n\n```go\ntranslator.AddDefaultBundleCustomizer(func(b *i18n.Bundle) error {\n    // e.g. b.LoadMessageFile(path), b.AddMessages(tag, msgs...)\n    return nil\n})\n```\n\n## Supported languages\n\n- **en** (default) – English  \n- **zh** – 简体中文  \n- **zh-TW** – 繁體中文  \n\nMessage IDs follow the rule IDs from `buf/validate` (e.g. `float.lt`, `string.min_len`, `int32.gt`). Add more languages by placing go-i18n JSON files in `translator/locales/` and rebuilding, or by loading your own bundle.\n\n## Development\n\n- **Main module** (repo root): Contains only the importable `translator` package, with no tests and no dependency on generated pb files. `go build ./...` and `go mod tidy` work out of the box.\n- **Tests and examples** live under `examples/`, which has its **own `go.mod`** so the main module never references generated pb code.\n\n```bash\nmake test              # Main module: build only\ncd examples \u0026\u0026 make proto-go \u0026\u0026 go test ./... -v   # Generate pb and run all tests\n# or from repo root:\nmake test-examples     # Same as above\nmake extract           # Regenerate en.json from validate.proto\n```\n\nFrom the `examples` directory, run `go mod tidy` and `go test ./...` as needed. Integration tests require `examples/translate/testdata/pb`; run `make proto-go` in `examples` first.\n\n## License\n\n[LICENSE](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjzero-io%2Fprotovalidate-translator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjzero-io%2Fprotovalidate-translator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjzero-io%2Fprotovalidate-translator/lists"}