# Release v1.3.0 — REPS-Compliant Hot Reload + Full API Documentation
**Date:** 2026-05-20
**Compare:** `v1.2.0...v1.3.0`
## Summary
Two things land in `1.3.0`:
1. **Hot reload is now genuinely REPS-compliant on memory.** The
append-only interner growth caveat shipped with `1.2.0` is gone.
Reloading `<locale>.toml` files no longer leaks string values
into a permanent pool.
2. **The documentation deficit is closed.** `docs/API.md` and
`docs/PROJECT-GUIDELINES.md` were empty; both are now complete
references with examples for every public item.
The public API is source-compatible with `1.2.0`. Bump the version
and you're done.
## The memory-safety fix
The zero-allocation read path in `1.1.0` / `1.2.0` works by handing
out `Cow::Borrowed(&'static str)` references that point into a
process-wide interner. In the default build that's perfectly safe:
locale files are loaded at startup and the interner stops growing.
But under the `hot-reload` feature, every reload that introduced
fresh string values would leak them — the interner is append-only.
`1.3.0` resolves this by **making the value-storage strategy
compile-time conditional** on the `hot-reload` feature:
| Default | Interned `&'static str` | `Cow::Borrowed(&'static str)` — 0 alloc | N/A (no reloads) |
| `hot-reload` | `Arc<str>` | `Cow::Owned(String)` — 1 alloc | **Yes.** |
The feature flag now genuinely encodes its trade-off:
- "I load locales at startup, then serve traffic" → default build,
zero-allocation reads, leak doesn't matter because growth is
impossible.
- "My service reloads files at runtime" → `hot-reload` build, pay
one allocation per read, get clean memory lifecycle.
Both modes remain lock-free and `Send + Sync`. Concurrent translate
calls never contend on a lock in either build.
## New: `Lang::translate_arc` opt-in (hot-reload only)
For `hot-reload` users who want to avoid the per-call `String`
allocation on the hit path, `1.3.0` adds:
```rust,ignore
let value: Arc<str> = Lang::translate_arc("greeting", Some("en"), None);
println!("{value}");
```
This is zero-allocation on hit (just a refcount bump on the
underlying `Arc<str>`) and one allocation on miss paths (constructs
a fresh `Arc<str>` from the inline fallback or the key).
`Translator` gets the matching methods:
```rust,ignore
let t = Translator::new("en");
let value = t.translate_arc("greeting");
let value_or_default = t.translate_arc_with_fallback("missing", "Default");
```
**Trade-off:** many threads cloning the same `Arc<str>`
simultaneously contend on its refcount cache line. If your service
has 64+ threads all hitting the same hot key (like a homepage
title), the default `Cow::Owned` path is actually more consistent
under load. Use `translate_arc` when you've measured the
allocation cost as a hot spot and your access pattern spreads
across many keys.
## Documentation overhaul
### `docs/API.md` (new)
Full API reference written from scratch. Every public item is
documented with parameters, return types, the feature gate it lives
under, and at least one worked example. Sections:
- Crate root (item table)
- `Lang` (configuration / loading / querying / translation /
registry / watcher subsections)
- `Translator`
- `LangError`
- `t!` macro
- Request helpers (`resolve_accept_language` /
`resolve_accept_language_owned`)
- `LangChangeEvent` / `ChangeKind` / `HandlerId` (registry feature)
- `WatchError` (hot-reload feature)
- Feature flags matrix
- MSRV, runtime dependencies, stability contract
- Memory model (the dual-storage explanation)
- Performance pointers
- Quick example + hot-reload example
### `docs/PROJECT-GUIDELINES.md` (new)
Operational guidelines: loading model, per-request locale handling,
feature-flag selection, fallback chain policy, contribution flow,
CI gates, engineering discipline. Pairs with `docs/API.md` so users
can find both "what's the surface?" and "how do I use it well?"
without reading the source.
### Other updates
- `README.md` — install snippets bumped to `1.3.0`; clarified
storage trade-off in optional-features section; new Documentation
section pointing at `docs/API.md` and `docs/PROJECT-GUIDELINES.md`;
added `examples/hot_reload.rs` to the example list with its
feature requirement.
- `BENCHMARKS.md` — documents the `translate_hit_concurrent`
benchmark and the concurrency stress tests added in `1.1.0` /
`1.2.0`.
- `CHANGELOG.md` — full `[1.3.0]` section.
## Added
- `Lang::translate_arc(key, locale, fallback) -> Arc<str>` (hot-reload feature)
- `Translator::translate_arc(&self, key) -> Arc<str>` (hot-reload feature)
- `Translator::translate_arc_with_fallback(&self, key, fallback) -> Arc<str>` (hot-reload feature)
- `tests/watch.rs::hot_reload_storage_drops_arc_str_on_reload` — explicit refcount-probe reclaim test
- `docs/API.md` — authoritative public API reference
- `docs/PROJECT-GUIDELINES.md` — production patterns + contributor flow
## Changed
- Internal value-storage strategy now compile-time conditional on
`hot-reload`. Public API shape unchanged.
- `src/loader.rs` produces `FxHashMap<&'static str, StoredValue>`,
where `StoredValue` is `&'static str` in default builds and
`Arc<str>` in `hot-reload` builds.
- README, BENCHMARKS, and CHANGELOG aligned with the actual
`1.3.0` surface and behavior.
## Removed
- Nothing.
## Fixed
- **Append-only interner growth under `hot-reload`.** The headline
caveat of `1.2.0` is closed.
## Compatibility
No breakage. The public API is source-compatible with `1.2.0`:
```toml
[dependencies]
lang-lib = "1.3.0"
```
`Lang::translate` still returns `Cow<'a, str>`. Anything that
worked on a `Cow<'_, str>` in `1.2.0` continues to work in `1.3.0`.
`Translator` is still `Copy`. All `1.2.0` feature flags retain
their behavior. The new `translate_arc` methods are additive and
gated on `hot-reload`.
## Migration from 1.2.0
Just bump the version. If you opt into `hot-reload` and want to
keep zero-allocation reads, switch to the new `translate_arc` API
(and read the trade-off in the API doc first).
## Next
Open backlog:
- Capture criterion + dhat baseline numbers on representative
hardware and commit them under `benches/baseline/`.
- String interpolation / placeholders (`t!("welcome", name: "John")`).
- Multiple locale directories with priority-ordered search.
---
**Full Changelog:** https://github.com/jamesgober/lang-lib/compare/v1.2.0...v1.3.0