init commit for iPAL-kit plugin
This commit is contained in:
+105
@@ -0,0 +1,105 @@
|
||||
# i18n
|
||||
|
||||
Lokalizacja: konfiguracja locali dla Payload, negocjacja języka
|
||||
(cookie / Accept-Language / default), budowanie ścieżek locale-aware,
|
||||
przełączanie języka bez 404.
|
||||
|
||||
## Config (payload.config.ts)
|
||||
|
||||
```ts
|
||||
ipalKit({
|
||||
i18n: {
|
||||
defaultLocale: 'pl',
|
||||
locales: [
|
||||
{ code: 'pl', label: 'Polski' },
|
||||
{ code: 'en', label: 'English' },
|
||||
// { code: 'ar', label: 'العربية', rtl: true },
|
||||
],
|
||||
// fallback: true, // domyślnie true
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Plugin ustawia `config.localization` z tego. Walidacja jest eager (fail-fast
|
||||
przy starcie): pusta lista, duplikaty kodów, `defaultLocale` spoza listy,
|
||||
zły format kodu → błąd `[ipal] i18n: ...`.
|
||||
|
||||
## Front — helpery
|
||||
|
||||
Wszystkie helpery są czyste (przyjmują config jako argument). Trzymaj swój
|
||||
`i18nConfig` w jednym miejscu i importuj gdzie trzeba.
|
||||
|
||||
```ts
|
||||
import {
|
||||
getLocaleCodes, getDefaultLocale, isValidLocale, getLocaleDefinition,
|
||||
negotiateLocale, buildLocalizedPath, switchLocalePath,
|
||||
getLocalizedSlugs, LOCALE_COOKIE_NAME,
|
||||
} from 'ipal-kit'
|
||||
|
||||
const config = { defaultLocale: 'pl', locales: [{code:'pl',label:'Polski'},{code:'en',label:'English'}] }
|
||||
|
||||
getLocaleCodes(config) // ['pl', 'en']
|
||||
isValidLocale('de', config) // false
|
||||
```
|
||||
|
||||
### Budowanie ścieżek
|
||||
|
||||
```ts
|
||||
// dokument pobrany z locale:'all' → slug to mapa { pl, en }
|
||||
const doc = await payload.findByID({ collection: 'pages', id, locale: 'all' })
|
||||
const slugs = getLocalizedSlugs({ slugField: doc.slug, config })
|
||||
// { pl: 'o-nas', en: 'about' }
|
||||
|
||||
buildLocalizedPath({ slugs, locale: 'en', config }) // '/en/about'
|
||||
// home slug ('home') zwija się do roota:
|
||||
buildLocalizedPath({ slugs: { en: 'home' }, locale: 'en', config }) // '/en'
|
||||
```
|
||||
|
||||
### Przełącznik języka (bez 404)
|
||||
|
||||
```ts
|
||||
// /pl/strona-glowna → klik EN → /en/home (albo /en jeśli brak tłumaczenia)
|
||||
const href = switchLocalePath({ slugs, targetLocale: 'en', config })
|
||||
router.push(href)
|
||||
```
|
||||
|
||||
`switchLocalePath` nigdy nie zwraca undefined — brak slug w danym locale →
|
||||
fallback na `/{locale}` (root), zamiast dead-endu na 404.
|
||||
|
||||
## Middleware — patrz osobno
|
||||
|
||||
Negocjacja locale + redirect na wejściu (`domena.com` → `/pl`) jest w
|
||||
`ipal-kit/next/middleware`. Zobacz [middleware w tej sekcji](#middleware)
|
||||
niżej.
|
||||
|
||||
## Middleware
|
||||
|
||||
```ts
|
||||
// next-middleware.ts (projekt klienta) — jedyna logika to podłączenie
|
||||
import { NextResponse } from 'next/server'
|
||||
import { createLocaleMiddleware, DEFAULT_MIDDLEWARE_MATCHER } from 'ipal-kit/next/middleware'
|
||||
|
||||
const i18nConfig = {
|
||||
defaultLocale: 'pl',
|
||||
locales: [{ code: 'pl', label: 'Polski' }, { code: 'en', label: 'English' }],
|
||||
}
|
||||
const localeMiddleware = createLocaleMiddleware({ config: i18nConfig })
|
||||
|
||||
export function middleware(req) {
|
||||
const r = localeMiddleware(req)
|
||||
if (r.type === 'next') return NextResponse.next()
|
||||
const res = NextResponse.redirect(r.location)
|
||||
res.cookies.set(r.cookie.name, r.cookie.value)
|
||||
return res
|
||||
}
|
||||
|
||||
export const config = { matcher: DEFAULT_MIDDLEWARE_MATCHER }
|
||||
```
|
||||
|
||||
Zachowanie:
|
||||
- ścieżka z locale (`/pl/...`) → przepuść
|
||||
- root albo ścieżka bez locale (`/`, `/o-nas`) → redirect na `/{locale}...`,
|
||||
locale z: cookie → Accept-Language → default
|
||||
- wybrany locale zapisany w cookie (`LOCALE_COOKIE_NAME`)
|
||||
|
||||
`DEFAULT_MIDDLEWARE_MATCHER` wyklucza `api`, `admin`, `_next`, pliki statyczne.
|
||||
Reference in New Issue
Block a user