first commit
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# querystringDetector
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`querystringDetector` is a `LocaleDetector` that reads the active locale
|
||||
from a URL search parameter. It runs in both browser and server
|
||||
environments, making it the canonical first link in the default detector
|
||||
chain — explicit user intent expressed through `?lang=fr-FR` always
|
||||
overrides every other source (cookie, localStorage, geo lookup, …) per
|
||||
the spec scenario "querystring overrides cookie".
|
||||
|
||||
The detector is intentionally minimal: it never persists a value (so
|
||||
sharing a `?lang=…` link does not pollute the user's stored preference),
|
||||
it does not throw when the param is absent, and it never reaches into
|
||||
window-level globals when a server-side `request` context is supplied.
|
||||
|
||||
## Features
|
||||
|
||||
- Configurable parameter name via `opts.paramName` (default `"lang"`)
|
||||
- Server input via `ctx.request.url.searchParams`
|
||||
- Browser input via `window.location.search`
|
||||
- Returns `null` for missing params, empty values, or environments
|
||||
where neither input source exists
|
||||
- `environment: "both"` — eligible on every chain run
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { querystringDetector } from "@suaveplan/react-i18n/detector/querystring/querystring";
|
||||
import { createDetectorChain } from "@suaveplan/i18n/detector";
|
||||
|
||||
const chain = createDetectorChain([querystringDetector()]);
|
||||
const result = await chain.detect({
|
||||
request: {
|
||||
headers: new Headers(),
|
||||
url: new URL("https://example.com/?lang=fr-FR"),
|
||||
},
|
||||
responseHeaders: new Headers(),
|
||||
supportedLocales: ["en-GB", "fr-FR"],
|
||||
fallbackLocale: "en-GB",
|
||||
});
|
||||
// → { locale: "fr-FR", detector: "querystring", rawValue: "fr-FR" }
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { querystringDetector } from "@suaveplan/react-i18n/detector/querystring/querystring";
|
||||
import { defaultDetectorChain } from "@suaveplan/react-i18n/detector/default-chain/default-chain";
|
||||
|
||||
// Replace the default `?lang=` entry with `?locale=` for a host app
|
||||
// that already uses that parameter, while keeping every other detector.
|
||||
const chain = defaultDetectorChain({ fallback: "en-GB" }).map((d) =>
|
||||
d.name === "querystring" ? querystringDetector({ paramName: "locale" }) : d
|
||||
);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `querystringDetector(options?: QuerystringDetectorOptions): LocaleDetector`
|
||||
|
||||
| Param | Type | Default | Description |
|
||||
| ------- | ----------------------------- | ------- | -------------------------------------------- |
|
||||
| options | `QuerystringDetectorOptions?` | `{}` | Optional `{ paramName?: string }` overrides. |
|
||||
|
||||
Returns a `LocaleDetector` with `name: "querystring"` and
|
||||
`environment: "both"`. The detector exposes only `detect(ctx)`; it does
|
||||
not implement `cache(...)` (the URL is never written).
|
||||
|
||||
### `QuerystringDetectorOptions`
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
| --------- | -------- | -------- | ---------------------------------------- |
|
||||
| paramName | `string` | `"lang"` | Search-parameter name the detector reads |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The detector strictly prefers `ctx.request` over `window.location` so
|
||||
SSR contexts that happen to leak a `globalThis.location` (e.g. test
|
||||
harnesses) do not override the request the application is rendering.
|
||||
- An empty string value (e.g. `?lang=`) is treated as "no preference"
|
||||
per the chain contract — the detector falls through, never wins.
|
||||
- The implementation is allocation-light (one `URLSearchParams` on the
|
||||
browser path) and synchronous so the chain runner picks it up in the
|
||||
initial sync pass before any async detector is dispatched.
|
||||
Reference in New Issue
Block a user