astro-intl 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +140 -2
  2. package/package.json +7 -2
package/README.md CHANGED
@@ -13,6 +13,9 @@ Sistema de internacionalización simple y type-safe para Astro, inspirado en nex
13
13
  - 🛡️ **Concurrency-safe**: Usa `AsyncLocalStorage` en SSR para aislar requests concurrentes
14
14
  - 🌍 **Multi-runtime**: Compatible con Node.js, Cloudflare Workers y Deno
15
15
  - ⚙️ **Default locale configurable**: Define tu locale por defecto desde las opciones
16
+ - 🗺️ **Routing localizado**: Define URLs traducidas por locale (`/es/sobre-nosotros` en vez de `/es/about`)
17
+ - 🔄 **Rewrites automáticos**: El middleware reescribe URLs traducidas a rutas canónicas del filesystem
18
+ - 🔗 **Generación de URLs**: `path()` y `switchLocalePath()` para construir y transformar URLs localizadas
16
19
 
17
20
  ## 📦 Instalación
18
21
 
@@ -249,7 +252,104 @@ const t = getTranslations<Messages>('nav');
249
252
  </nav>
250
253
  ```
251
254
 
252
- ## 📚 API Reference
255
+ ## �️ Routing Localizado
256
+
257
+ ### Definir rutas traducidas
258
+
259
+ Crea un mapa de rutas con URLs traducidas por locale:
260
+
261
+ ```ts
262
+ // src/i18n/routing.ts
263
+ export const routing = {
264
+ locales: ["en", "es"],
265
+ defaultLocale: "en",
266
+ routes: {
267
+ home: { en: "/", es: "/" },
268
+ about: { en: "/about", es: "/sobre-nosotros" },
269
+ blog: { en: "/blog/[slug]", es: "/blog/[slug]" },
270
+ shop: { en: "/shop/[category]/[id]", es: "/tienda/[category]/[id]" },
271
+ },
272
+ } as const;
273
+ ```
274
+
275
+ ### Con Middleware (recomendado)
276
+
277
+ Pasa las rutas al middleware. Este reescribe automáticamente URLs traducidas a las rutas canónicas del filesystem:
278
+
279
+ ```ts
280
+ // src/middleware.ts
281
+ import "@/i18n/request";
282
+ import { createIntlMiddleware } from "astro-intl/middleware";
283
+ import { routing } from "@/i18n/routing";
284
+
285
+ export const onRequest = createIntlMiddleware(routing);
286
+ ```
287
+
288
+ Cuando un usuario visita `/es/sobre-nosotros`, el middleware lo reescribe a `/es/about` — que mapea a tu archivo `[lang]/about.astro`. Sin páginas duplicadas.
289
+
290
+ ### Sin Middleware
291
+
292
+ Configura las rutas via las opciones de la integración:
293
+
294
+ ```js
295
+ // astro.config.mjs
296
+ import { defineConfig } from "astro/config";
297
+ import astroIntl from "astro-intl";
298
+
299
+ export default defineConfig({
300
+ integrations: [
301
+ astroIntl({
302
+ defaultLocale: "en",
303
+ locales: ["en", "es"],
304
+ routes: {
305
+ about: { en: "/about", es: "/sobre-nosotros" },
306
+ },
307
+ }),
308
+ ],
309
+ });
310
+ ```
311
+
312
+ Sin middleware no hay rewrites automáticos. Crea wrappers ligeros para cada ruta traducida:
313
+
314
+ ```astro
315
+ ---
316
+ // src/pages/[lang]/sobre-nosotros.astro
317
+ export { default } from "./about.astro";
318
+ export { getStaticPaths } from "./about.astro";
319
+ ---
320
+ ```
321
+
322
+ ### Generar URLs con `path()`
323
+
324
+ ```astro
325
+ ---
326
+ import { path } from "astro-intl/routing";
327
+ ---
328
+
329
+ <a href={path("about")}>About</a>
330
+ <!-- locale "en" → /en/about -->
331
+ <!-- locale "es" → /es/sobre-nosotros -->
332
+
333
+ <a href={path("shop", { locale: "es", params: { category: "ropa", id: "42" } })}>
334
+ Ver producto
335
+ </a>
336
+ <!-- → /es/tienda/ropa/42 -->
337
+ ```
338
+
339
+ ### Cambiar locale con `switchLocalePath()`
340
+
341
+ ```astro
342
+ ---
343
+ import { switchLocalePath } from "astro-intl/routing";
344
+ ---
345
+
346
+ <a href={switchLocalePath(Astro.url.pathname, "en")}>English</a>
347
+ <a href={switchLocalePath(Astro.url.pathname, "es")}>Español</a>
348
+ <!-- En /en/about → /es/sobre-nosotros -->
349
+ <!-- En /es/tienda/ropa/42 → /en/shop/ropa/42 -->
350
+ ```
351
+
352
+ ## � API Reference
253
353
 
254
354
  ### `astroIntl(options?)`
255
355
 
@@ -260,6 +360,8 @@ Configura la integración en `astro.config.mjs`.
260
360
  - `defaultLocale?: string` - Locale por defecto cuando la URL no tiene prefijo de idioma (default: `"en"`)
261
361
  - `enabled?: boolean` - Habilitar/deshabilitar la integración (default: `true`)
262
362
  - `messages?: MessagesConfig` - Mensajes de traducción estáticos o dinámicos
363
+ - `locales?: string[]` - Lista de locales soportados
364
+ - `routes?: RoutesMap` - Mapa de rutas traducidas por locale
263
365
 
264
366
  ### `setRequestLocale(url, getConfig?)`
265
367
 
@@ -345,6 +447,40 @@ Obtiene el locale actual configurado.
345
447
 
346
448
  **Retorna:** `string` - El código del locale (ej: `'es'`, `'en'`)
347
449
 
450
+ ### `createIntlMiddleware(options)`
451
+
452
+ Crea un middleware de Astro que llama automáticamente a `setRequestLocale` en cada request. Importar desde `astro-intl/middleware`.
453
+
454
+ **Opciones:**
455
+
456
+ - `locales: string[]` - Lista de locales soportados
457
+ - `defaultLocale?: string` - Locale por defecto (default: `"en"`)
458
+ - `routes?: RoutesMap` - Mapa de rutas traducidas. Cuando se proporciona, el middleware reescribe URLs traducidas a sus rutas canónicas del filesystem
459
+
460
+ ### `path(routeKey, options?)`
461
+
462
+ Genera una URL localizada para una ruta nombrada. Importar desde `astro-intl/routing`.
463
+
464
+ **Parámetros:**
465
+
466
+ - `routeKey: string` - Nombre de la ruta (clave del mapa de `routes`)
467
+ - `options?.locale` - Locale destino (default: locale actual)
468
+ - `options?.params` - `Record<string, string>` para sustituir `[param]` en el template
469
+ - `options?.encode` - Codificar params con `encodeURIComponent` (default: `true`)
470
+
471
+ **Retorna:** `string` - URL localizada (ej: `"/es/sobre-nosotros"`)
472
+
473
+ ### `switchLocalePath(currentPath, nextLocale)`
474
+
475
+ Convierte la URL actual a su equivalente en otro locale. Importar desde `astro-intl/routing`.
476
+
477
+ **Parámetros:**
478
+
479
+ - `currentPath: string | URL` - Ruta actual (pathname, URL string o URL object)
480
+ - `nextLocale: string` - Locale destino
481
+
482
+ **Retorna:** `string` - URL equivalente en el nuevo locale. Preserva query strings y hashes. Si no matchea ningún template, hace fallback a intercambiar el prefijo del locale.
483
+
348
484
  ---
349
485
 
350
486
  ## 🚀 Desarrollo (para contribuidores)
@@ -388,9 +524,11 @@ packages/integration/
388
524
  │ ├── store.ts # Estado por request (AsyncLocalStorage + fallback)
389
525
  │ ├── translations.ts # getTranslations y getTranslationsReact
390
526
  │ ├── react.ts # Factory de t.rich() para React
527
+ │ ├── routing.ts # path(), switchLocalePath() — generación de URLs localizadas
528
+ │ ├── middleware.ts # createIntlMiddleware() con rewrites de rutas traducidas
391
529
  │ ├── index.ts # Entry point público + integración de Astro
392
530
  │ └── types/
393
- │ └── index.ts # Tipos TypeScript
531
+ │ └── index.ts # Tipos TypeScript (incluye RoutesMap)
394
532
  ├── dist/ # Archivos compilados (generados)
395
533
  │ ├── *.js # JavaScript compilado
396
534
  │ └── *.d.ts # Declaraciones de tipos
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-intl",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "description": "Sistema de internacionalización simple y type-safe para Astro, inspirado en next-intl",
6
6
  "keywords": [
@@ -12,7 +12,8 @@
12
12
  "internationalization",
13
13
  "intl",
14
14
  "translations",
15
- "typescript"
15
+ "typescript",
16
+ "accessibility"
16
17
  ],
17
18
  "author": "Erick Cruz <erickj.cruzs@gmail.com>",
18
19
  "license": "MIT",
@@ -41,6 +42,10 @@
41
42
  "./middleware": {
42
43
  "types": "./dist/middleware.d.ts",
43
44
  "import": "./dist/middleware.js"
45
+ },
46
+ "./routing": {
47
+ "types": "./dist/routing.d.ts",
48
+ "import": "./dist/routing.js"
44
49
  }
45
50
  },
46
51
  "peerDependencies": {