@intlayer/docs 5.7.6 → 5.7.7

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 (73) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +44 -238
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +44 -238
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +1 -2
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/intlayer_with_tanstack.md +457 -0
  8. package/docs/ar/packages/next-intlayer/index.md +0 -1
  9. package/docs/ar/packages/react-intlayer/index.md +0 -1
  10. package/docs/de/intlayer_with_tanstack.md +458 -0
  11. package/docs/de/packages/next-intlayer/index.md +0 -1
  12. package/docs/de/packages/react-intlayer/index.md +0 -1
  13. package/docs/en/intlayer_with_tanstack.md +452 -0
  14. package/docs/en/packages/next-intlayer/index.md +0 -1
  15. package/docs/en/packages/react-intlayer/index.md +0 -1
  16. package/docs/en-GB/intlayer_with_tanstack.md +457 -0
  17. package/docs/en-GB/packages/next-intlayer/index.md +0 -1
  18. package/docs/en-GB/packages/react-intlayer/index.md +0 -1
  19. package/docs/es/intlayer_with_tanstack.md +435 -0
  20. package/docs/es/packages/next-intlayer/index.md +0 -1
  21. package/docs/es/packages/react-intlayer/index.md +0 -1
  22. package/docs/fr/intlayer_with_tanstack.md +435 -0
  23. package/docs/fr/packages/next-intlayer/index.md +0 -1
  24. package/docs/fr/packages/react-intlayer/index.md +0 -1
  25. package/docs/hi/intlayer_with_tanstack.md +438 -0
  26. package/docs/hi/packages/next-intlayer/index.md +0 -1
  27. package/docs/hi/packages/react-intlayer/index.md +0 -1
  28. package/docs/it/intlayer_with_tanstack.md +457 -0
  29. package/docs/it/packages/next-intlayer/index.md +0 -1
  30. package/docs/it/packages/react-intlayer/index.md +0 -1
  31. package/docs/ja/intlayer_with_tanstack.md +457 -0
  32. package/docs/ja/packages/next-intlayer/index.md +0 -1
  33. package/docs/ja/packages/react-intlayer/index.md +0 -1
  34. package/docs/ko/intlayer_with_tanstack.md +457 -0
  35. package/docs/ko/packages/next-intlayer/index.md +0 -1
  36. package/docs/ko/packages/react-intlayer/index.md +0 -1
  37. package/docs/pt/intlayer_with_tanstack.md +457 -0
  38. package/docs/pt/packages/next-intlayer/index.md +0 -1
  39. package/docs/pt/packages/react-intlayer/index.md +0 -1
  40. package/docs/ru/intlayer_with_tanstack.md +458 -0
  41. package/docs/ru/packages/next-intlayer/index.md +0 -1
  42. package/docs/ru/packages/react-intlayer/index.md +0 -1
  43. package/docs/zh/intlayer_with_tanstack.md +435 -0
  44. package/docs/zh/packages/next-intlayer/index.md +0 -1
  45. package/docs/zh/packages/react-intlayer/index.md +0 -1
  46. package/package.json +9 -9
  47. package/src/generated/docs.entry.ts +44 -238
  48. package/docs/ar/packages/next-intlayer/useIntlayerAsync.md +0 -237
  49. package/docs/ar/packages/react-intlayer/useIntlayerAsync.md +0 -252
  50. package/docs/de/packages/next-intlayer/useIntlayerAsync.md +0 -262
  51. package/docs/de/packages/react-intlayer/useIntlayerAsync.md +0 -256
  52. package/docs/en/packages/next-intlayer/useIntlayerAsync.md +0 -239
  53. package/docs/en/packages/react-intlayer/useIntlayerAsync.md +0 -254
  54. package/docs/en-GB/packages/next-intlayer/useIntlayerAsync.md +0 -237
  55. package/docs/en-GB/packages/react-intlayer/useIntlayerAsync.md +0 -257
  56. package/docs/es/packages/next-intlayer/useIntlayerAsync.md +0 -240
  57. package/docs/es/packages/react-intlayer/useIntlayerAsync.md +0 -276
  58. package/docs/fr/packages/next-intlayer/useIntlayerAsync.md +0 -238
  59. package/docs/fr/packages/react-intlayer/useIntlayerAsync.md +0 -252
  60. package/docs/hi/packages/next-intlayer/useIntlayerAsync.md +0 -237
  61. package/docs/hi/packages/react-intlayer/useIntlayerAsync.md +0 -252
  62. package/docs/it/packages/next-intlayer/useIntlayerAsync.md +0 -237
  63. package/docs/it/packages/react-intlayer/useIntlayerAsync.md +0 -252
  64. package/docs/ja/packages/next-intlayer/useIntlayerAsync.md +0 -237
  65. package/docs/ja/packages/react-intlayer/useIntlayerAsync.md +0 -268
  66. package/docs/ko/packages/next-intlayer/useIntlayerAsync.md +0 -260
  67. package/docs/ko/packages/react-intlayer/useIntlayerAsync.md +0 -271
  68. package/docs/pt/packages/next-intlayer/useIntlayerAsync.md +0 -238
  69. package/docs/pt/packages/react-intlayer/useIntlayerAsync.md +0 -252
  70. package/docs/ru/packages/next-intlayer/useIntlayerAsync.md +0 -237
  71. package/docs/ru/packages/react-intlayer/useIntlayerAsync.md +0 -252
  72. package/docs/zh/packages/next-intlayer/useIntlayerAsync.md +0 -239
  73. package/docs/zh/packages/react-intlayer/useIntlayerAsync.md +0 -257
@@ -0,0 +1,457 @@
1
+ ---
2
+ createdAt: 2025-08-11
3
+ updatedAt: 2025-08-11
4
+ title: Iniziare con Intlayer in TanStack Start (React)
5
+ description: Aggiungi l'internazionalizzazione alla tua app TanStack Start usando Intlayer—dizionari a livello di componente, URL localizzati e metadati ottimizzati per SEO.
6
+ keywords:
7
+ - Internazionalizzazione
8
+ - Documentazione
9
+ - Intlayer
10
+ - TanStack Start
11
+ - TanStack Router
12
+ - React
13
+ - i18n
14
+ - JavaScript
15
+ slugs:
16
+ - doc
17
+ - environment
18
+ - tanstack-start
19
+ ---
20
+
21
+ # Iniziare con l'internazionalizzazione (i18n) usando Intlayer e TanStack Start (React)
22
+
23
+ ## Cos'è Intlayer?
24
+
25
+ **Intlayer** è un toolkit open-source per l'internazionalizzazione (i18n) di app React. Ti offre:
26
+
27
+ - **Dizionari locali al componente** con sicurezza TypeScript.
28
+ - **Metadati e rotte dinamiche** (pronte per SEO).
29
+ - **Cambio della lingua a runtime** (e helper per rilevare/persistere le lingue).
30
+ - **Plugin Vite** per trasformazioni in fase di build + esperienza di sviluppo (DX).
31
+
32
+ Questa guida mostra come integrare Intlayer in un progetto **TanStack Start** (che utilizza Vite sotto il cofano e TanStack Router per il routing/SSR).
33
+
34
+ ---
35
+
36
+ ## Passo 1: Installare le dipendenze
37
+
38
+ ```bash
39
+ # npm
40
+ npm i intlayer react-intlayer
41
+ npm i -D vite-intlayer
42
+
43
+ # pnpm
44
+ pnpm add intlayer react-intlayer
45
+ pnpm add -D vite-intlayer
46
+
47
+ # yarn
48
+ yarn add intlayer react-intlayer
49
+ yarn add -D vite-intlayer
50
+ ```
51
+
52
+ - **intlayer**: core (configurazione, dizionari, CLI/trasformazioni).
53
+ - **react-intlayer**: `<IntlayerProvider>` + hook per React.
54
+ - **vite-intlayer**: plugin Vite, più middleware opzionale per il rilevamento/reindirizzamento della lingua (funziona in dev e SSR/preview; spostare in `dependencies` per SSR in produzione).
55
+
56
+ ---
57
+
58
+ ## Passo 2: Configurare Intlayer
59
+
60
+ Crea `intlayer.config.ts` nella root del tuo progetto:
61
+
62
+ ```ts fileName="intlayer.config.ts"
63
+ import { Locales, type IntlayerConfig } from "intlayer";
64
+
65
+ const config: IntlayerConfig = {
66
+ internationalization: {
67
+ locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
68
+ defaultLocale: Locales.ENGLISH,
69
+ },
70
+ // Puoi anche modificare: contentDir, contentFileExtensions, opzioni del middleware, ecc.
71
+ };
72
+
73
+ export default config;
74
+ ```
75
+
76
+ Le varianti CommonJS/ESM sono identiche al tuo documento originale se preferisci `cjs`/`mjs`.
77
+
78
+ > Riferimento completo alla configurazione: vedi la documentazione di configurazione di Intlayer.
79
+
80
+ ---
81
+
82
+ ## Passo 3: Aggiungere il Plugin Vite (e middleware opzionale)
83
+
84
+ **TanStack Start usa Vite**, quindi aggiungi il/i plugin di Intlayer al tuo `vite.config.ts`:
85
+
86
+ ```ts fileName="vite.config.ts"
87
+ import { defineConfig } from "vite";
88
+ import react from "@vitejs/plugin-react-swc";
89
+ import { intlayerPlugin, intLayerMiddlewarePlugin } from "vite-intlayer";
90
+
91
+ export default defineConfig({
92
+ plugins: [
93
+ react(),
94
+ intlayerPlugin(),
95
+ // Opzionale ma consigliato per il rilevamento della lingua, cookie e reindirizzamenti:
96
+ intLayerMiddlewarePlugin(),
97
+ ],
98
+ });
99
+ ```
100
+
101
+ > Se distribuisci SSR, sposta `vite-intlayer` nelle `dependencies` affinché il middleware funzioni in produzione.
102
+
103
+ ---
104
+
105
+ ## Passo 4: Dichiara il tuo contenuto
106
+
107
+ Posiziona i tuoi dizionari ovunque sotto `./src` (default `contentDir`). Esempio:
108
+
109
+ ```tsx fileName="src/app.content.tsx"
110
+ import { t, type Dictionary } from "intlayer";
111
+ import type { ReactNode } from "react";
112
+
113
+ const appContent = {
114
+ key: "app",
115
+ content: {
116
+ viteLogo: t({
117
+ it: "Logo Vite",
118
+ en: "Vite logo",
119
+ fr: "Logo Vite",
120
+ es: "Logo Vite",
121
+ }),
122
+ reactLogo: t({
123
+ it: "Logo React",
124
+ en: "React logo",
125
+ fr: "Logo React",
126
+ es: "Logo React",
127
+ }),
128
+ title: t({
129
+ it: "TanStack Start + React",
130
+ en: "TanStack Start + React",
131
+ fr: "TanStack Start + React",
132
+ es: "TanStack Start + React",
133
+ }),
134
+ count: t({
135
+ it: "il conteggio è ",
136
+ en: "count is ",
137
+ fr: "le compte est ",
138
+ es: "el recuento es ",
139
+ }),
140
+ edit: t<ReactNode>({
141
+ it: (
142
+ <>
143
+ Modifica <code>src/routes/index.tsx</code> e salva per testare HMR
144
+ </>
145
+ ),
146
+ en: (
147
+ <>
148
+ Edit <code>src/routes/index.tsx</code> and save to test HMR
149
+ </>
150
+ ),
151
+ fr: (
152
+ <>
153
+ Éditez <code>src/routes/index.tsx</code> et enregistrez pour tester
154
+ HMR
155
+ </>
156
+ ),
157
+ es: (
158
+ <>
159
+ Edita <code>src/routes/index.tsx</code> y guarda para probar HMR
160
+ </>
161
+ ),
162
+ }),
163
+ readTheDocs: t({
164
+ it: "Clicca sui loghi per saperne di più",
165
+ en: "Click the logos to learn more",
166
+ fr: "Cliquez sur les logos pour en savoir plus",
167
+ es: "Haz clic en los logotipos para saber más",
168
+ }),
169
+ },
170
+ } satisfies Dictionary;
171
+
172
+ export default appContent;
173
+ ```
174
+
175
+ Le varianti JSON/ESM/CJS funzionano allo stesso modo del tuo documento originale.
176
+
177
+ > Contenuto TSX? Non dimenticare `import React from "react"` se la tua configurazione lo richiede.
178
+
179
+ ---
180
+
181
+ ## Passo 5: Avvolgi TanStack Start con Intlayer
182
+
183
+ Con TanStack Start, la tua **root route** è il posto giusto per impostare i provider.
184
+
185
+ ```tsx fileName="src/routes/__root.tsx"
186
+ import {
187
+ Outlet,
188
+ createRootRoute,
189
+ Link as RouterLink,
190
+ } from "@tanstack/react-router";
191
+ import { IntlayerProvider, useIntlayer } from "react-intlayer";
192
+
193
+ function AppShell() {
194
+ // Esempio di utilizzo di un dizionario a livello superiore:
195
+ const content = useIntlayer("app");
196
+
197
+ return (
198
+ <div>
199
+ <nav className="flex gap-3 p-3">
200
+ <RouterLink to="/">Home</RouterLink>
201
+ <RouterLink to="/about">Informazioni</RouterLink>
202
+ </nav>
203
+ <main className="p-6">
204
+ <h1>{content.title}</h1>
205
+ <Outlet />
206
+ </main>
207
+ </div>
208
+ );
209
+ }
210
+
211
+ export const Route = createRootRoute({
212
+ component: () => (
213
+ <IntlayerProvider>
214
+ <AppShell />
215
+ </IntlayerProvider>
216
+ ),
217
+ });
218
+ ```
219
+
220
+ Quindi usa i tuoi contenuti nelle pagine:
221
+
222
+ ```tsx fileName="src/routes/index.tsx"
223
+ import { createFileRoute } from "@tanstack/react-router";
224
+ import { useIntlayer } from "react-intlayer";
225
+ import reactLogo from "../assets/react.svg";
226
+
227
+ export const Route = createFileRoute("/")({
228
+ component: () => {
229
+ const content = useIntlayer("app");
230
+ return (
231
+ <>
232
+ <button>{content.count}0</button>
233
+ <p>{content.edit}</p>
234
+ <img
235
+ src={reactLogo}
236
+ alt={content.reactLogo.value}
237
+ width={48}
238
+ height={48}
239
+ />
240
+ <p className="opacity-70">{content.readTheDocs}</p>
241
+ </>
242
+ );
243
+ },
244
+ });
245
+ ```
246
+
247
+ > Gli attributi stringa (`alt`, `title`, `aria-label`, …) necessitano di `.value`:
248
+ >
249
+ > ```jsx
250
+ > <img alt={c.reactLogo.value} />
251
+ > ```
252
+
253
+ ---
254
+
255
+ ## (Opzionale) Passo 6: Cambio della lingua (Client)
256
+
257
+ ```tsx fileName="src/components/LocaleSwitcher.tsx"
258
+ import { Locales } from "intlayer";
259
+ import { useLocale } from "react-intlayer";
260
+
261
+ export function LocaleSwitcher() {
262
+ const { setLocale } = useLocale();
263
+ return (
264
+ <div className="flex gap-2">
265
+ <button onClick={() => setLocale(Locales.ENGLISH)}>Inglese</button>
266
+ <button onClick={() => setLocale(Locales.FRENCH)}>Francese</button>
267
+ <button onClick={() => setLocale(Locales.SPANISH)}>Spagnolo</button>
268
+ </div>
269
+ );
270
+ }
271
+ ```
272
+
273
+ ---
274
+
275
+ ## (Opzionale) Passo 7: Routing Localizzato (URL SEO-friendly)
276
+
277
+ Hai **due buoni modelli** con TanStack Start. Scegline uno.
278
+
279
+ Crea una cartella segmento dinamico `src/routes/$locale/` così i tuoi URL saranno `/:locale/...`. Nel layout `$locale`, valida `params.locale`, imposta `<IntlayerProvider locale=...>`, e renderizza un `<Outlet />`. Questo approccio è semplice, ma monterai il resto delle tue rotte sotto `$locale`, e avrai bisogno di un albero extra senza prefisso se _non_ vuoi il prefisso della locale di default.
280
+
281
+ ---
282
+
283
+ ## (Opzionale) Passo 8: Aggiornare l'URL quando si cambia lingua
284
+
285
+ Con il Pattern A (basepath), cambiare lingua significa **navigare verso un basepath differente**:
286
+
287
+ ```tsx fileName="src/components/LocaleSwitcherNavigate.tsx"
288
+ import { useRouter } from "@tanstack/react-router";
289
+ import { Locales, getLocalizedUrl } from "intlayer";
290
+ import { useLocale } from "react-intlayer";
291
+
292
+ export function LocaleSwitcherNavigate() {
293
+ const router = useRouter();
294
+ const { locale, setLocale } = useLocale();
295
+
296
+ const change = async (next: Locales) => {
297
+ if (next === locale) return;
298
+ const nextPath = getLocalizedUrl(
299
+ window.location.pathname + window.location.search,
300
+ next
301
+ );
302
+ await router.navigate({ to: nextPath }); // preserva la cronologia
303
+ setLocale(next);
304
+ };
305
+
306
+ return (
307
+ <div className="flex gap-2">
308
+ <button onClick={() => change(Locales.ENGLISH)}>English</button>
309
+ <button onClick={() => change(Locales.FRENCH)}>Français</button>
310
+ <button onClick={() => change(Locales.SPANISH)}>Español</button>
311
+ </div>
312
+ );
313
+ }
314
+ ```
315
+
316
+ ---
317
+
318
+ ## (Opzionale) Passo 9: `<html lang>` e `dir` (TanStack Start Document)
319
+
320
+ TanStack Start espone un **Document** (shell HTML radice) che puoi personalizzare. Imposta `lang` e `dir` per accessibilità/SEO:
321
+
322
+ ```tsx fileName="src/routes/__root.tsx" {4,15}
323
+ import { Outlet, createRootRoute } from "@tanstack/react-router";
324
+ import { IntlayerProvider } from "react-intlayer";
325
+ import { getHTMLTextDir } from "intlayer";
326
+
327
+ function Document({
328
+ locale,
329
+ children,
330
+ }: {
331
+ locale: string;
332
+ children: React.ReactNode;
333
+ }) {
334
+ return (
335
+ <html lang={locale} dir={getHTMLTextDir(locale)}>
336
+ <head>
337
+ <meta charSet="utf-8" />
338
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
339
+ {/* ... */}
340
+ </head>
341
+ <body>{children}</body>
342
+ </html>
343
+ );
344
+ }
345
+
346
+ export const Route = createRootRoute({
347
+ component: () => (
348
+ <IntlayerProvider>
349
+ {/* Se calcoli la locale sul server, passala a Document; altrimenti il client correggerà dopo l'idratazione */}
350
+ <Document locale={document?.documentElement?.lang || "en"}>
351
+ <Outlet />
352
+ </Document>
353
+ </IntlayerProvider>
354
+ ),
355
+ });
356
+ ```
357
+
358
+ Per la correzione lato client, puoi anche mantenere il tuo piccolo hook:
359
+
360
+ ```tsx fileName="src/hooks/useI18nHTMLAttributes.tsx"
361
+ import { useEffect } from "react";
362
+ import { useLocale } from "react-intlayer";
363
+ import { getHTMLTextDir } from "intlayer";
364
+
365
+ export const useI18nHTMLAttributes = () => {
366
+ const { locale } = useLocale();
367
+ useEffect(() => {
368
+ document.documentElement.lang = locale;
369
+ document.documentElement.dir = getHTMLTextDir(locale);
370
+ }, [locale]);
371
+ };
372
+ ```
373
+
374
+ ---
375
+
376
+ ## (Opzionale) Passo 10: Componente Link localizzato
377
+
378
+ TanStack Router fornisce un `<Link/>`, ma se mai avessi bisogno di un semplice `<a>` che aggiunge automaticamente il prefisso alle URL interne:
379
+
380
+ ```tsx fileName="src/components/Link.tsx"
381
+ import { getLocalizedUrl } from "intlayer";
382
+ import {
383
+ forwardRef,
384
+ type AnchorHTMLAttributes,
385
+ type DetailedHTMLProps,
386
+ } from "react";
387
+ import { useLocale } from "react-intlayer";
388
+
389
+ export interface LinkProps
390
+ extends DetailedHTMLProps<
391
+ AnchorHTMLAttributes<HTMLAnchorElement>,
392
+ HTMLAnchorElement
393
+ > {}
394
+
395
+ const isExternal = (href?: string) => /^https?:\/\//.test(href ?? "");
396
+
397
+ export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
398
+ ({ href, children, ...props }, ref) => {
399
+ const { locale } = useLocale();
400
+ const hrefI18n =
401
+ href && !isExternal(href) ? getLocalizedUrl(href, locale) : href;
402
+ return (
403
+ <a href={hrefI18n} ref={ref} {...props}>
404
+ {children}
405
+ </a>
406
+ );
407
+ }
408
+ );
409
+ Link.displayName = "Link";
410
+ ```
411
+
412
+ > Se usi il Pattern A (basepath), il `<Link to="/about" />` di TanStack risolve già in `/fr/about` tramite `basepath`, quindi un link personalizzato è opzionale.
413
+
414
+ ---
415
+
416
+ ## TypeScript
417
+
418
+ Includi i tipi generati da Intlayer:
419
+
420
+ ```json5 fileName="tsconfig.json"
421
+ {
422
+ "include": ["src", ".intlayer/**/*.ts"],
423
+ }
424
+ ```
425
+
426
+ ---
427
+
428
+ ## Git
429
+
430
+ Ignora gli artefatti generati da Intlayer:
431
+
432
+ ```gitignore
433
+ .intlayer
434
+ ```
435
+
436
+ ---
437
+
438
+ ## Estensione VS Code
439
+
440
+ - **Estensione Intlayer per VS Code** → completamento automatico, errori, anteprime inline, azioni rapide.
441
+ Marketplace: `intlayer.intlayer-vs-code-extension`
442
+
443
+ ---
444
+
445
+ ## Approfondimenti
446
+
447
+ - Editor Visuale
448
+ - Modalità CMS
449
+ - Rilevamento della lingua al confine / adattatori
450
+
451
+ ---
452
+
453
+ ## Cronologia Documentazione
454
+
455
+ | Versione | Data | Modifiche |
456
+ | -------- | ---------- | ------------------------------------- |
457
+ | 1.0.0 | 2025-08-11 | Aggiunta l'adattamento TanStack Start |
@@ -279,7 +279,6 @@ Il pacchetto `next-intlayer` fornisce anche alcune funzioni per aiutarti a inter
279
279
  - [`useIntlayer()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/next-intlayer/useIntlayer.md)
280
280
  - [`useDictionary()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/next-intlayer/useDictionary.md)
281
281
  - [`useLocale()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/next-intlayer/useLocale.md)
282
- - [`useIntlayerAsync()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/next-intlayer/useIntlayerAsync.md)
283
282
 
284
283
  ## Cronologia della documentazione
285
284
 
@@ -274,7 +274,6 @@ Il pacchetto `react-intlayer` fornisce anche alcune funzioni per aiutarti a inte
274
274
  - [`useIntlayer()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/react-intlayer/useIntlayer.md)
275
275
  - [`useDictionary()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/react-intlayer/useDictionary.md)
276
276
  - [`useLocale()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/react-intlayer/useLocale.md)
277
- - [`useIntlayerAsync()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/react-intlayer/useIntlayerAsync.md)
278
277
 
279
278
  ## Cronologia della documentazione
280
279