From ac868ecbeb1638c8d7bc868208fbdf6df04b1a5d Mon Sep 17 00:00:00 2001 From: Christian Melgarejo Date: Wed, 25 Feb 2026 20:39:59 -0300 Subject: [PATCH 1/2] refactor: use consistent sentinel codes 999999001/999999002 for missing language/message (#2) - CodeMissingLanguage: 99999999 -> 999999001 - CodeMissingMessage: 999999998 -> 999999002 - Keeps sentinels in same namespace for docs and future use Made-with: Cursor --- README.md | 4 ++-- docs/CONTEXT7.md | 4 ++-- docs/CONTEXT7_RETRIEVAL.md | 4 ++-- msgcat.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2ae5703..9c352bc 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,8 @@ fmt.Println(err.Error()) // localized short message - `SystemMessageMinCode = 9000` - `SystemMessageMaxCode = 9999` -- `CodeMissingMessage = 999999998` -- `CodeMissingLanguage = 99999999` +- `CodeMissingMessage = 999999002` +- `CodeMissingLanguage = 999999001` ## Observability diff --git a/docs/CONTEXT7.md b/docs/CONTEXT7.md index 9335261..e20f14c 100644 --- a/docs/CONTEXT7.md +++ b/docs/CONTEXT7.md @@ -165,8 +165,8 @@ Notes: const ( SystemMessageMinCode = 9000 SystemMessageMaxCode = 9999 - CodeMissingMessage = 999999998 - CodeMissingLanguage = 99999999 + CodeMissingMessage = 999999002 + CodeMissingLanguage = 999999001 ) ``` diff --git a/docs/CONTEXT7_RETRIEVAL.md b/docs/CONTEXT7_RETRIEVAL.md index e8c7b01..d891d73 100644 --- a/docs/CONTEXT7_RETRIEVAL.md +++ b/docs/CONTEXT7_RETRIEVAL.md @@ -130,8 +130,8 @@ func Close(catalog MessageCatalog) error const ( SystemMessageMinCode = 9000 SystemMessageMaxCode = 9999 - CodeMissingMessage = 999999998 - CodeMissingLanguage = 99999999 + CodeMissingMessage = 999999002 + CodeMissingLanguage = 999999001 ) ``` diff --git a/msgcat.go b/msgcat.go index 59a96c1..5490e69 100644 --- a/msgcat.go +++ b/msgcat.go @@ -20,8 +20,8 @@ const MessageCatalogNotFound = "Unexpected error in message catalog, language [% const ( SystemMessageMinCode = 9000 SystemMessageMaxCode = 9999 - CodeMissingMessage = 999999998 - CodeMissingLanguage = 99999999 + CodeMissingMessage = 999999002 + CodeMissingLanguage = 999999001 overflowStatKey = "__overflow__" ) From 59036d2d1a55390ef62602ca54aced3ec285f6f2 Mon Sep 17 00:00:00 2001 From: Christian Melgarejo Date: Wed, 25 Feb 2026 20:42:01 -0300 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20release=20prep=20v1.0.8=20?= =?UTF-8?q?=E2=80=94=20CI,=20SECURITY,=20README,=20docs,=20Go=201.26,=20os?= =?UTF-8?q?/ioutil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add GitHub Actions CI (test, race, vet, examples build) with Go 1.23 - Add SECURITY.md for vulnerability reporting - Rename .golanci.yml to .golangci.yml - Update README with full current API, config, and observability - CHANGELOG/MIGRATION/RELEASE docs for v1.0.8 - go.mod: Go 1.26; msgcat: use os instead of deprecated ioutil Made-with: Cursor --- .github/workflows/ci.yml | 30 +++++ .golanci.yml => .golangci.yml | 2 +- README.md | 225 ++++++++++++++++++++++++---------- SECURITY.md | 17 +++ docs/CHANGELOG.md | 7 ++ docs/MIGRATION.md | 4 + docs/RELEASE.md | 16 +++ go.mod | 16 ++- go.sum | 6 - msgcat.go | 6 +- 10 files changed, 252 insertions(+), 77 deletions(-) create mode 100644 .github/workflows/ci.yml rename .golanci.yml => .golangci.yml (95%) create mode 100644 SECURITY.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..13aee0d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: CI + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.23' + + - name: Run tests + run: go test ./... + + - name: Run tests with race detector + run: go test -race ./... + + - name: Run go vet + run: go vet ./... + + - name: Build examples + run: go build ./examples/... diff --git a/.golanci.yml b/.golangci.yml similarity index 95% rename from .golanci.yml rename to .golangci.yml index fae0b7c..fc2655a 100644 --- a/.golanci.yml +++ b/.golangci.yml @@ -20,4 +20,4 @@ issues: - source: '^//go:generate ' path: / linters: - - lll \ No newline at end of file + - lll diff --git a/README.md b/README.md index 9c352bc..db31cb7 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,13 @@ `msgcat` is a lightweight i18n message catalog for Go focused on APIs and error handling. -It loads messages from YAML by language, resolves language from `context.Context`, supports runtime message loading for system codes, and can wrap domain errors with localized short/long messages. +It loads messages from YAML by language, resolves language from `context.Context`, supports runtime message loading for system codes (9000–9999), and can wrap domain errors with localized short/long messages. -Maturity: production-ready (`v1.x`) with SemVer and release/migration docs in `docs/`. +**Maturity:** production-ready (`v1.x`) with SemVer and release/migration docs in `docs/`. + +**Requirements:** Go 1.26 or later. + +--- ## Installation @@ -12,16 +16,26 @@ Maturity: production-ready (`v1.x`) with SemVer and release/migration docs in `d go get github.com/loopcontext/msgcat ``` +--- + ## Quick Start ### 1. Create message files -Default path: +Default directory (when `ResourcePath` is empty): ```text ./resources/messages ``` +One YAML file per language (e.g. `en.yaml`, `es.yaml`). Structure: + +| Field | Description | +|----------|-------------| +| `group` | Optional numeric group (e.g. `0`). | +| `default`| Used when a message code is missing: `short` and `long` templates. | +| `set` | Map of message code → `short` / `long` template strings. | + Example `en.yaml`: ```yaml @@ -73,71 +87,150 @@ if err != nil { } ``` -### 3. Resolve messages/errors from context +### 3. Resolve messages and errors from context ```go ctx := context.WithValue(context.Background(), "language", "es-AR") msg := catalog.GetMessageWithCtx(ctx, 1, "juan") fmt.Println(msg.ShortText) // "Usuario creado" +fmt.Println(msg.LongText) // "Usuario juan fue creado correctamente" +fmt.Println(msg.Code) // 1 err := catalog.WrapErrorWithCtx(ctx, errors.New("db timeout"), 2, 3, 12345.5, time.Now()) fmt.Println(err.Error()) // localized short message + +if catErr, ok := err.(msgcat.Error); ok { + fmt.Println(catErr.ErrorCode()) // 2 + fmt.Println(catErr.GetShortMessage()) + fmt.Println(catErr.GetLongMessage()) + fmt.Println(catErr.Unwrap()) // original "db timeout" +} ``` +--- + +## Configuration + +All fields of `msgcat.Config`: + +| Field | Type | Description | +|---------------------|----------------|-------------| +| `ResourcePath` | `string` | Directory containing `*.yaml` message files. Default: `./resources/messages`. | +| `CtxLanguageKey` | `ContextKey` | Context key to read language (e.g. `"language"`). Supports typed key and string key lookup. | +| `DefaultLanguage` | `string` | Language used when context has no key or catalog has no match. Recommended: `"en"`. | +| `FallbackLanguages` | `[]string` | Optional fallback list after requested/base (e.g. `[]string{"es"}`). | +| `StrictTemplates` | `bool` | If true, missing template params render as ``. Recommended `true` in production. | +| `Observer` | `Observer` | Optional; receives async events (fallback, missing lang, missing message, template issue). | +| `ObserverBuffer` | `int` | Size of observer event queue. Use ≥ 1 to avoid blocking the request path (e.g. 1024). | +| `StatsMaxKeys` | `int` | Max keys per stats map; overflow goes to `__overflow__`. Use to cap cardinality (e.g. 512). | +| `ReloadRetries` | `int` | Retries on reload parse/read failure (e.g. 2). | +| `ReloadRetryDelay` | `time.Duration`| Delay between retries (e.g. 50ms). | +| `NowFn` | `func() time.Time` | Optional; used for date formatting. Default: `time.Now`. | + +--- + ## Features -- Language resolution from context (typed key and string key compatibility). -- Language fallback chain: requested -> base (`es-ar` -> `es`) -> configured fallbacks -> default -> `en`. -- YAML + runtime-loaded system messages (`9000-9999`). -- Template tokens: - - `{{0}}`, `{{1}}`, ... positional - - `{{plural:i|singular|plural}}` - - `{{num:i}}` localized number format - - `{{date:i}}` localized date format -- Strict template mode (`StrictTemplates`) for missing parameters. -- Error wrapping with localized short/long messages and error code. -- Concurrency-safe reads/writes. -- Runtime reload (`msgcat.Reload`) preserving runtime-loaded messages. -- Observability hooks and counters (`SnapshotStats`). +- **Language from context** + Language is read from `context.Context` using `CtxLanguageKey` (typed or string key). + +- **Fallback chain** + Order: requested language → base tag (`es-ar` → `es`) → `FallbackLanguages` → `DefaultLanguage` → `"en"`. First language that exists in the catalog is used. + +- **YAML + runtime messages** + Messages from YAML plus runtime-loaded entries via `LoadMessages` for codes **9000–9999** (system range). + +- **Template tokens** + - `{{0}}`, `{{1}}`, … — positional parameters. + - `{{plural:i|singular|plural}}` — plural form by parameter at index `i`. + - `{{num:i}}` — localized number for parameter at index `i`. + - `{{date:i}}` — localized date for parameter at index `i` (`time.Time` or `*time.Time`). + +- **Strict template mode** + With `StrictTemplates: true`, missing or invalid params produce `` and observer events. + +- **Error wrapping** + `WrapErrorWithCtx` and `GetErrorWithCtx` return errors implementing `msgcat.Error`: `ErrorCode()`, `GetShortMessage()`, `GetLongMessage()`, `Unwrap()`. + +- **Concurrency** + Safe for concurrent reads; `LoadMessages` and `Reload` are safe to use concurrently with reads. + +- **Reload** + `msgcat.Reload(catalog)` reloads YAML from disk with optional retries; runtime-loaded messages (9000–9999) are preserved. On failure, last in-memory state is kept. + +- **Observability** + Optional `Observer` plus stats via `SnapshotStats` / `ResetStats`. Observer runs asynchronously and is panic-safe; queue overflow is counted in stats. + +--- ## API -### Core interface +### Core interface (`MessageCatalog`) + +| Method | Description | +|--------|-------------| +| `LoadMessages(lang string, messages []RawMessage) error` | Add or replace messages for a language. Only codes in 9000–9999 are allowed. | +| `GetMessageWithCtx(ctx context.Context, msgCode int, msgParams ...interface{}) *Message` | Resolve message for the context language; never nil. | +| `WrapErrorWithCtx(ctx context.Context, err error, msgCode int, msgParams ...interface{}) error` | Wrap an error with localized short/long text and message code. | +| `GetErrorWithCtx(ctx context.Context, msgCode int, msgParams ...interface{}) error` | Build an error with localized short/long text (no inner error). | -- `LoadMessages(lang string, messages []RawMessage) error` -- `GetMessageWithCtx(ctx context.Context, msgCode int, msgParams ...interface{}) *Message` -- `WrapErrorWithCtx(ctx context.Context, err error, msgCode int, msgParams ...interface{}) error` -- `GetErrorWithCtx(ctx context.Context, msgCode int, msgParams ...interface{}) error` +### Types -### Helpers +- **`Message`** — `Code int`, `ShortText string`, `LongText string`. +- **`RawMessage`** — `ShortTpl`, `LongTpl` (YAML: `short`, `long`); used in YAML and `LoadMessages`. +- **`msgcat.Error`** — `Error() string`, `Unwrap() error`, `ErrorCode() int`, `GetShortMessage() string`, `GetLongMessage() string`. -- `msgcat.Reload(catalog MessageCatalog) error` -- `msgcat.SnapshotStats(catalog MessageCatalog) (MessageCatalogStats, error)` -- `msgcat.ResetStats(catalog MessageCatalog) error` -- `msgcat.Close(catalog MessageCatalog) error` +### Package-level helpers + +| Function | Description | +|----------|-------------| +| `msgcat.NewMessageCatalog(cfg Config) (MessageCatalog, error)` | Build catalog and load YAML from `ResourcePath`. | +| `msgcat.Reload(catalog MessageCatalog) error` | Reload YAML from disk (with retries if configured). | +| `msgcat.SnapshotStats(catalog MessageCatalog) (MessageCatalogStats, error)` | Copy of current stats. | +| `msgcat.ResetStats(catalog MessageCatalog) error` | Reset all stats counters. | +| `msgcat.Close(catalog MessageCatalog) error` | Stop observer worker and flush; call on shutdown if using an observer. | ### Constants -- `SystemMessageMinCode = 9000` -- `SystemMessageMaxCode = 9999` -- `CodeMissingMessage = 999999002` -- `CodeMissingLanguage = 999999001` +| Constant | Value | Description | +|----------|--------|-------------| +| `SystemMessageMinCode` | 9000 | Min code for runtime-loaded system messages. | +| `SystemMessageMaxCode` | 9999 | Max code for runtime-loaded system messages. | +| `CodeMissingMessage` | 999999002 | Code used when a message is missing in the catalog. | +| `CodeMissingLanguage` | 999999001 | Code used when the language is missing. | ## Observability -Provide an observer in config: +### Observer + +Implement `msgcat.Observer` and pass it in `Config.Observer`: ```go type Observer struct{} func (Observer) OnLanguageFallback(requested, resolved string) {} -func (Observer) OnLanguageMissing(lang string) {} -func (Observer) OnMessageMissing(lang string, msgCode int) {} +func (Observer) OnLanguageMissing(lang string) {} +func (Observer) OnMessageMissing(lang string, msgCode int) {} func (Observer) OnTemplateIssue(lang string, msgCode int, issue string) {} ``` -Snapshot counters at runtime: +Callbacks are invoked **asynchronously** and are panic-protected. If the observer queue is full, events are dropped and counted in `MessageCatalogStats.DroppedEvents`. Call `msgcat.Close(catalog)` on shutdown when using an observer. + +### Stats (`MessageCatalogStats`) + +| Field | Description | +|-------|-------------| +| `LanguageFallbacks` | Counts per `"requested->resolved"` language fallback. | +| `MissingLanguages` | Counts per missing language. | +| `MissingMessages` | Counts per `"lang:code"` missing message. | +| `TemplateIssues` | Counts per template issue key (e.g. `"lang:code:issue"`). | +| `DroppedEvents` | Counts per drop reason (e.g. `observer_queue_full`, `observer_closed`). | +| `LastReloadAt` | Time of last successful reload. | + +When `StatsMaxKeys` is set, each map is capped; extra keys are aggregated under `"__overflow__"`. + +Example: ```go stats, err := msgcat.SnapshotStats(catalog) @@ -151,46 +244,52 @@ if err == nil { } ``` -## Production Notes +--- -- Keep `DefaultLanguage` explicit (`en` recommended). -- Define `FallbackLanguages` intentionally (for example for regional traffic). -- Use `StrictTemplates: true` in production to detect bad template usage early. -- Set `ObserverBuffer` to avoid request-path pressure from slow observers. -- Set `StatsMaxKeys` to cap cardinality (`__overflow__` key holds overflow counts). -- Use `go test -race ./...` in CI. -- For periodic YAML refresh, call `msgcat.Reload(catalog)` in a controlled goroutine and prefer atomic file replacement (`write temp + rename`). -- Use `ReloadRetries` and `ReloadRetryDelay` to reduce transient parse/read errors during rollout windows. -- If observer is configured, call `msgcat.Close(catalog)` on service shutdown. +## Production notes -### Runtime Contract +- Set `DefaultLanguage` explicitly (e.g. `"en"`). +- Set `FallbackLanguages` to match your traffic (e.g. regional defaults). +- Use `StrictTemplates: true` to catch bad template usage early. +- Set `ObserverBuffer` (e.g. 1024) so slow observers do not block the request path. +- Set `StatsMaxKeys` (e.g. 512) to avoid unbounded memory; watch `__overflow__` in dashboards. +- Run `go test -race ./...` in CI. +- For periodic YAML updates, call `msgcat.Reload(catalog)` (e.g. from a goroutine) and deploy files atomically (write to temp, then rename). +- Use `ReloadRetries` and `ReloadRetryDelay` to tolerate transient read/parse errors. +- If an observer is configured, call `msgcat.Close(catalog)` on service shutdown. -- `GetMessageWithCtx` / `GetErrorWithCtx` / `WrapErrorWithCtx` are safe for concurrent use. -- `LoadMessages` and `Reload` are safe concurrently with reads. -- `Reload` keeps the last in-memory state if reload fails. -- Observer callbacks are async and panic-protected; overflow is counted in `DroppedEvents`. +### Runtime contract -## Benchmarks +- `GetMessageWithCtx`, `GetErrorWithCtx`, `WrapErrorWithCtx` are safe for concurrent use. +- `LoadMessages` and `Reload` are safe concurrently with these reads. +- `Reload` keeps the previous in-memory state if the reload fails. +- Observer callbacks are async and panic-protected; overflow is reflected in `DroppedEvents`. + +--- -Run: +## Benchmarks ```bash go test -run ^$ -bench . -benchmem ./... ``` -## Integration Examples +--- -- HTTP language middleware sample: `examples/http/main.go` -- Metrics/observer sample (expvar style): `examples/metrics/main.go` +## Examples -## Context7 / LLM Docs +- HTTP language middleware: `examples/http/main.go` +- Metrics/observer (expvar-style): `examples/metrics/main.go` -For full machine-friendly docs, see `docs/CONTEXT7.md`. -For retrieval-optimized chunks, see `docs/CONTEXT7_RETRIEVAL.md`. +--- -## Release + Migration +## Docs and release -- Changelog: `docs/CHANGELOG.md` -- Migration guide: `docs/MIGRATION.md` -- Release playbook: `docs/RELEASE.md` -- Support policy: `docs/SUPPORT.md` +| Doc | Description | +|-----|-------------| +| [Changelog](docs/CHANGELOG.md) | Version history. | +| [Migration guide](docs/MIGRATION.md) | Upgrading and config changes. | +| [Release playbook](docs/RELEASE.md) | How to cut a release. | +| [Support policy](docs/SUPPORT.md) | Supported versions and compatibility. | +| [SECURITY.md](SECURITY.md) | How to report vulnerabilities. | +| [Context7](docs/CONTEXT7.md) | Machine-friendly API docs. | +| [Context7 retrieval](docs/CONTEXT7_RETRIEVAL.md) | Retrieval-oriented chunks. | diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..f873bd1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,17 @@ +# Security Policy + +## Supported Versions + +Security updates are applied to the latest minor within the current major version. Critical fixes may be backported to the previous minor when practical (see [Support Policy](docs/SUPPORT.md)). + +## Reporting a Vulnerability + +Please **do not** open a public issue for security vulnerabilities. + +To report a vulnerability: + +1. Email the maintainers or open a private security advisory on GitHub if the repo supports it. +2. Include a clear description, steps to reproduce, and impact. +3. Allow reasonable time for a fix before any public disclosure. + +We will acknowledge receipt and aim to respond with next steps promptly. diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 15a6b6b..0469a80 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,6 +6,8 @@ This project follows Semantic Versioning. ## [Unreleased] +## [1.0.8] - 2026-02-25 + ### Added - Async, panic-safe observer pipeline with bounded queue (`ObserverBuffer`). - Bounded stats cardinality (`StatsMaxKeys`) with `__overflow__` bucket. @@ -15,11 +17,16 @@ This project follows Semantic Versioning. - Production-oriented docs for Context7 + retrieval-friendly docs. - Additional tests: observer behavior, stats capping/reset, reload retry behavior. - Benchmarks and fuzz test entrypoints. +- GitHub Actions CI workflow (test, race, vet, examples build). +- `SECURITY.md` for vulnerability reporting. +- `.golangci.yml` for lint configuration (replaces misspelled `.golanci.yml`). ### Changed - `Reload` now supports transient read/parse retries. - Observer callbacks are no longer executed inline on request path. - Stats now enforce key caps to avoid unbounded memory growth. +- Go module requires Go 1.26. +- Replaced deprecated `io/ioutil` with `os` (`ReadDir`, `ReadFile`). ### Fixed - Updated docs links to `docs/` layout. diff --git a/docs/MIGRATION.md b/docs/MIGRATION.md index 7d0499a..0b348de 100644 --- a/docs/MIGRATION.md +++ b/docs/MIGRATION.md @@ -74,3 +74,7 @@ If you configured an observer, call `msgcat.Close(catalog)` on shutdown to flush - Context key lookup remains compatible with both typed key and plain string key. - Existing template syntax remains valid. - `LoadMessages` system-code constraint (`9000-9999`) is unchanged. + +## 8) Go version (v1.0.8+) + +Module requires **Go 1.26** or later. If you are on an older toolchain, upgrade before updating to msgcat v1.0.8. diff --git a/docs/RELEASE.md b/docs/RELEASE.md index a13d9ac..abb8f95 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -39,6 +39,22 @@ git push origin v1.0.0 - Performance notes: benchmark deltas. - Operational notes: observer/stats/reload caveats. +### Example (v1.0.8) + +```markdown +## Summary +Production hardening: async observer, bounded stats, reload retries, CI, SECURITY.md, Go 1.26, and lint config. + +## Breaking changes +None. Go 1.26+ required (see migration guide). + +## Migration +[Migration guide](docs/MIGRATION.md) — sections 3–6 and 8 (Go version). + +## Operational +Observer is async and panic-safe; call `msgcat.Close(catalog)` on shutdown if using an observer. +``` + ## Post-release checks - Validate tag visible in remote. diff --git a/go.mod b/go.mod index c1925ae..f86fd0d 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,23 @@ module github.com/loopcontext/msgcat -go 1.15 +go 1.26 require ( github.com/golang/mock v1.4.4 - github.com/google/go-cmp v0.5.2 // indirect - github.com/kr/pretty v0.1.0 // indirect github.com/onsi/ginkgo v1.14.2 github.com/onsi/gomega v1.10.4 + gopkg.in/yaml.v2 v2.4.0 +) + +require ( + github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/kr/pretty v0.1.0 // indirect + github.com/nxadm/tail v1.4.4 // indirect + golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb // indirect + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect + golang.org/x/text v0.3.3 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/protobuf v1.25.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/yaml.v2 v2.4.0 + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect ) diff --git a/go.sum b/go.sum index ad3f35f..a5f97a9 100644 --- a/go.sum +++ b/go.sum @@ -24,11 +24,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -86,7 +83,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -104,12 +100,10 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/msgcat.go b/msgcat.go index 5490e69..2044653 100644 --- a/msgcat.go +++ b/msgcat.go @@ -3,7 +3,7 @@ package msgcat import ( "context" "fmt" - "io/ioutil" + "os" "regexp" "strconv" "strings" @@ -180,7 +180,7 @@ func (dmc *DefaultMessageCatalog) readMessagesFromYaml() (map[string]Messages, e resourcePath = "./resources/messages" } - messageFiles, err := ioutil.ReadDir(resourcePath) + messageFiles, err := os.ReadDir(resourcePath) if err != nil { return nil, fmt.Errorf("failed to find messages %v", err) } @@ -194,7 +194,7 @@ func (dmc *DefaultMessageCatalog) readMessagesFromYaml() (map[string]Messages, e } var messages Messages lang := normalizeLangTag(strings.TrimSuffix(fileName, ".yaml")) - yamlFile, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", resourcePath, fileName)) + yamlFile, err := os.ReadFile(fmt.Sprintf("%s/%s", resourcePath, fileName)) if err != nil { return nil, fmt.Errorf("failed to read message file: %v", err) }