@intlayer/docs 6.1.5 → 6.1.6-canary.0

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 (53) hide show
  1. package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +404 -173
  2. package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +262 -113
  3. package/blog/en/intlayer_with_next-i18next.mdx +431 -0
  4. package/blog/en/intlayer_with_next-intl.mdx +335 -0
  5. package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +403 -140
  6. package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +38 -28
  7. package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +185 -71
  8. package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +38 -28
  9. package/blog/it/next-i18next_vs_next-intl_vs_intlayer.md +38 -28
  10. package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +38 -28
  11. package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +38 -28
  12. package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +38 -28
  13. package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +36 -28
  14. package/blog/tr/next-i18next_vs_next-intl_vs_intlayer.md +2 -0
  15. package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +38 -28
  16. package/dist/cjs/generated/docs.entry.cjs +16 -0
  17. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  18. package/dist/esm/generated/docs.entry.mjs +16 -0
  19. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  20. package/dist/types/generated/docs.entry.d.ts +1 -0
  21. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  22. package/docs/ar/component_i18n.md +186 -0
  23. package/docs/ar/vs_code_extension.md +48 -109
  24. package/docs/de/component_i18n.md +186 -0
  25. package/docs/de/vs_code_extension.md +46 -107
  26. package/docs/en/component_i18n.md +186 -0
  27. package/docs/en/intlayer_with_nextjs_14.md +18 -1
  28. package/docs/en/intlayer_with_nextjs_15.md +18 -1
  29. package/docs/en/vs_code_extension.md +24 -114
  30. package/docs/en-GB/component_i18n.md +186 -0
  31. package/docs/en-GB/vs_code_extension.md +42 -103
  32. package/docs/es/component_i18n.md +182 -0
  33. package/docs/es/vs_code_extension.md +53 -114
  34. package/docs/fr/component_i18n.md +186 -0
  35. package/docs/fr/vs_code_extension.md +50 -111
  36. package/docs/hi/component_i18n.md +186 -0
  37. package/docs/hi/vs_code_extension.md +49 -110
  38. package/docs/it/component_i18n.md +186 -0
  39. package/docs/it/vs_code_extension.md +50 -111
  40. package/docs/ja/component_i18n.md +186 -0
  41. package/docs/ja/vs_code_extension.md +50 -111
  42. package/docs/ko/component_i18n.md +186 -0
  43. package/docs/ko/vs_code_extension.md +48 -109
  44. package/docs/pt/component_i18n.md +186 -0
  45. package/docs/pt/vs_code_extension.md +46 -107
  46. package/docs/ru/component_i18n.md +186 -0
  47. package/docs/ru/vs_code_extension.md +48 -109
  48. package/docs/tr/component_i18n.md +186 -0
  49. package/docs/tr/vs_code_extension.md +54 -115
  50. package/docs/zh/component_i18n.md +186 -0
  51. package/docs/zh/vs_code_extension.md +51 -105
  52. package/package.json +11 -11
  53. package/src/generated/docs.entry.ts +16 -0
@@ -19,6 +19,8 @@ slugs:
19
19
 
20
20
  # next-i18next VS next-intl VS intlayer | Next.js Internationalisation (i18n)
21
21
 
22
+ ![next-i18next VS next-intl VS intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/assets/i18next-next-intl-intlayer.png?raw=true)
23
+
22
24
  Let’s take a look into the similarities and differences between three i18n options for Next.js: next-i18next, next-intl, and Intlayer.
23
25
 
24
26
  This is not a full tutorial. It’s a comparison to help you pick.
@@ -165,9 +167,9 @@ In the case of `next-intl` and `next-i18next`, the library requires loading the
165
167
 
166
168
  Here is an example of the impact of bundle size optimisation using `intlayer` in a vite + react application:
167
169
 
168
- | Optimised bundle | Bundle not optimised |
169
- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
170
- | ![optimised bundle](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png) | ![no optimised bundle](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle_no_optimization.png) |
170
+ | Optimised bundle | Bundle not optimised |
171
+ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
172
+ | ![optimised bundle](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true) | ![no optimised bundle](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle_no_optimization.png?raw=true) |
171
173
 
172
174
  ---
173
175
 
@@ -369,25 +371,25 @@ The app structure is important to ensure good maintainability of your codebase.
369
371
 
370
372
  ```bash
371
373
  .
372
- ├── public
373
- │ └── locales
374
- │ ├── en
375
- │ │ ├── home.json
376
- │ │ └── navbar.json
377
- │ ├── fr
378
- │ │ ├── home.json
379
- │ │ └── navbar.json
380
- │ └── es
381
- │ ├── home.json
382
- │ └── navbar.json
383
- ├── next-i18next.config.js
374
+ ├── i18n.config.ts
384
375
  └── src
385
- ├── middleware.ts
376
+ ├── locales
377
+ │ ├── en
378
+ │ │ ├── common.json
379
+ │ │ └── about.json
380
+ │ └── fr
381
+ │ ├── common.json
382
+ │ └── about.json
386
383
  ├── app
387
- └── home.tsx
384
+ ├── i18n
385
+ │ │ └── server.ts
386
+ │ └── [locale]
387
+ │ ├── layout.tsx
388
+ │ └── about.tsx
388
389
  └── components
389
- └── Navbar
390
- └── index.tsx
390
+ ├── I18nProvider.tsx
391
+ ├── ClientComponent.tsx
392
+ └── ServerComponent.tsx
391
393
  ```
392
394
 
393
395
  </TabItem>
@@ -395,6 +397,7 @@ The app structure is important to ensure good maintainability of your codebase.
395
397
 
396
398
  ```bash
397
399
  .
400
+ ├── i18n.ts
398
401
  ├── locales
399
402
  │ ├── en
400
403
  │ │ ├── home.json
@@ -405,11 +408,13 @@ The app structure is important to ensure good maintainability of your codebase.
405
408
  │ └── es
406
409
  │ ├── home.json
407
410
  │ └── navbar.json
408
- ├── i18n.ts
409
411
  └── src
410
412
  ├── middleware.ts
411
413
  ├── app
412
- └── home.tsx
414
+ ├── i18n
415
+ │ │ └── server.ts
416
+ │ └── [locale]
417
+ │ └── home.tsx
413
418
  └── components
414
419
  └── Navbar
415
420
  └── index.tsx
@@ -424,9 +429,11 @@ The app structure is important to ensure good maintainability of your codebase.
424
429
  └── src
425
430
  ├── middleware.ts
426
431
  ├── app
427
- │ └── home
428
- └── index.tsx
429
- │ └── index.content.ts
432
+ │ └── [locale]
433
+ ├── layout.tsx
434
+ │ └── home
435
+ │ ├── index.tsx
436
+ │ └── index.content.ts
430
437
  └── components
431
438
  └── Navbar
432
439
  ├── index.tsx
@@ -554,8 +561,10 @@ export default async function LocaleLayout({
554
561
  const messages = await getMessages();
555
562
  const clientMessages = pick(messages, ["common", "about"]);
556
563
 
564
+ const rtlLocales = ["ar", "he", "fa", "ur"];
565
+
557
566
  return (
558
- <html lang={locale}>
567
+ <html lang={locale} dir={rtlLocales.includes(locale) ? "rtl" : "ltr"}>
559
568
  <body>
560
569
  <NextIntlClientProvider locale={locale} messages={clientMessages}>
561
570
  {children}
@@ -872,10 +881,11 @@ const ServerComponent = ({ count }: ServerComponentProps) => {
872
881
  type ServerComponentProps = {
873
882
  count: number;
874
883
  t: (key: string) => string;
884
+ formatter: Intl.NumberFormat;
875
885
  };
876
886
 
877
- const ServerComponent = ({ t, count }: ServerComponentProps) => {
878
- const formatted = new Intl.NumberFormat(i18n.language).format(count);
887
+ const ServerComponent = ({ t, count, formatter }: ServerComponentProps) => {
888
+ const formatted = formatter.format(count);
879
889
 
880
890
  return (
881
891
  <div>
@@ -889,7 +899,7 @@ const ServerComponent = ({ t, count }: ServerComponentProps) => {
889
899
  > As the server component cannot be async, you need to pass the translations and formatter function as props.
890
900
  >
891
901
  > - `const t = await getTranslations("about.counter");`
892
- > - `const format = await getFormatter();`
902
+ > - `const formatter = await getFormatter().then((formatter) => formatter.number());`
893
903
 
894
904
  </TabItem>
895
905
  <TabItem label="intlayer" value="intlayer">
@@ -19,6 +19,8 @@ slugs:
19
19
 
20
20
  # next-i18next VS next-intl VS intlayer | Internacionalización (i18n) en Next.js
21
21
 
22
+ ![next-i18next VS next-intl VS intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/assets/i18next-next-intl-intlayer.png?raw=true)
23
+
22
24
  Veamos las similitudes y diferencias entre tres opciones de i18n para Next.js: next-i18next, next-intl e Intlayer.
23
25
 
24
26
  Esto no es un tutorial completo. Es una comparación para ayudarte a elegir.
@@ -165,9 +167,9 @@ En el caso de `next-intl` y `next-i18next`, la biblioteca requiere cargar el JSO
165
167
 
166
168
  Aquí un ejemplo del impacto de la optimización del tamaño del paquete usando `intlayer` en una aplicación vite + react:
167
169
 
168
- | Paquete optimizado | Paquete no optimizado |
169
- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
170
- | ![paquete optimizado](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png) | ![paquete no optimizado](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle_no_optimization.png) |
170
+ | Paquete optimizado | Paquete no optimizado |
171
+ | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
172
+ | ![paquete optimizado](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true) | ![paquete no optimizado](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle_no_optimization.png?raw=true) |
171
173
 
172
174
  ---
173
175
 
@@ -340,25 +342,25 @@ La estructura de la aplicación es importante para asegurar un buen mantenimient
340
342
 
341
343
  ```bash
342
344
  .
343
- ├── public
344
- │ └── locales
345
- │ ├── en
346
- │ │ ├── home.json
347
- │ │ └── navbar.json
348
- │ ├── fr
349
- │ │ ├── home.json
350
- │ │ └── navbar.json
351
- │ └── es
352
- │ ├── home.json
353
- │ └── navbar.json
354
- ├── next-i18next.config.js
345
+ ├── i18n.config.ts
355
346
  └── src
356
- ├── middleware.ts
347
+ ├── locales
348
+ │ ├── en
349
+ │ │ ├── common.json
350
+ │ │ └── about.json
351
+ │ └── fr
352
+ │ ├── common.json
353
+ │ └── about.json
357
354
  ├── app
358
- └── home.tsx
355
+ ├── i18n
356
+ │ │ └── server.ts
357
+ │ └── [locale]
358
+ │ ├── layout.tsx
359
+ │ └── about.tsx
359
360
  └── components
360
- └── Navbar
361
- └── index.tsx
361
+ ├── I18nProvider.tsx
362
+ ├── ClientComponent.tsx
363
+ └── ServerComponent.tsx
362
364
  ```
363
365
 
364
366
  </TabItem>
@@ -366,6 +368,7 @@ La estructura de la aplicación es importante para asegurar un buen mantenimient
366
368
 
367
369
  ```bash
368
370
  .
371
+ ├── i18n.ts
369
372
  ├── locales
370
373
  │ ├── en
371
374
  │ │ ├── home.json
@@ -376,11 +379,13 @@ La estructura de la aplicación es importante para asegurar un buen mantenimient
376
379
  │ └── es
377
380
  │ ├── home.json
378
381
  │ └── navbar.json
379
- ├── i18n.ts
380
382
  └── src
381
383
  ├── middleware.ts
382
384
  ├── app
383
- └── home.tsx
385
+ ├── i18n
386
+ │ │ └── server.ts
387
+ │ └── [locale]
388
+ │ └── home.tsx
384
389
  └── components
385
390
  └── Navbar
386
391
  └── index.tsx
@@ -395,9 +400,11 @@ La estructura de la aplicación es importante para asegurar un buen mantenimient
395
400
  └── src
396
401
  ├── middleware.ts
397
402
  ├── app
398
- │ └── home
399
- └── index.tsx
400
- │ └── index.content.ts
403
+ │ └── [locale]
404
+ ├── layout.tsx
405
+ │ └── home
406
+ │ ├── index.tsx
407
+ │ └── index.content.ts
401
408
  └── components
402
409
  └── Navbar
403
410
  ├── index.tsx
@@ -420,66 +427,170 @@ Cómo la biblioteca maneja la carga de contenido es importante.
420
427
  <Tab defaultTab="next-intl" group='techno'>
421
428
  <TabItem label="next-i18next" value="next-i18next">
422
429
 
423
- ```tsx fileName="next-i18next.config.js"
424
- module.exports = {
425
- i18n: {
426
- locales: ["en", "fr", "es"],
427
- defaultLocale: "en",
428
- },
429
- };
430
- ```
430
+ ```ts fileName="i18n.config.ts"
431
+ export const locales = ["en", "fr"] as const;
432
+ export type Locale = (typeof locales)[number];
431
433
 
432
- ```tsx fileName="src/app/_app.tsx"
433
- import { appWithTranslation } from "next-i18next";
434
+ export const defaultLocale: Locale = "en";
434
435
 
435
- const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />;
436
+ export const rtlLocales = ["ar", "he", "fa", "ur"] as const;
437
+ export const isRtl = (locale: string) =>
438
+ (rtlLocales as readonly string[]).includes(locale);
439
+
440
+ export function localizedPath(locale: string, path: string) {
441
+ return locale === defaultLocale ? path : "/" + locale + path;
442
+ }
436
443
 
437
- export default appWithTranslation(MyApp);
444
+ const ORIGIN = "https://example.com";
445
+ export function abs(locale: string, path: string) {
446
+ return ORIGIN + localizedPath(locale, path);
447
+ }
438
448
  ```
439
449
 
440
- ```tsx fileName="src/app/[locale]/about/page.tsx"
441
- import type { GetStaticProps } from "next";
442
- import { serverSideTranslations } from "next-i18next/serverSideTranslations";
443
- import { useTranslation } from "next-i18next";
444
- import { I18nextProvider, initReactI18next } from "react-i18next";
450
+ ```ts fileName="src/app/i18n/server.ts"
445
451
  import { createInstance } from "i18next";
446
- import { ClientComponent, ServerComponent } from "@components";
452
+ import { initReactI18next } from "react-i18next/initReactI18next";
453
+ import resourcesToBackend from "i18next-resources-to-backend";
454
+ import { defaultLocale } from "@/i18n.config";
455
+
456
+ // Load JSON resources from src/locales/<locale>/<namespace>.json
457
+ const backend = resourcesToBackend(
458
+ (locale: string, namespace: string) =>
459
+ import(`../../locales/${locale}/${namespace}.json`)
460
+ );
461
+
462
+ export async function initI18next(
463
+ locale: string,
464
+ namespaces: string[] = ["common"]
465
+ ) {
466
+ const i18n = createInstance();
467
+ await i18n
468
+ .use(initReactI18next)
469
+ .use(backend)
470
+ .init({
471
+ lng: locale,
472
+ fallbackLng: defaultLocale,
473
+ ns: namespaces,
474
+ defaultNS: "common",
475
+ interpolation: { escapeValue: false },
476
+ react: { useSuspense: false },
477
+ });
478
+ return i18n;
479
+ }
480
+ ```
447
481
 
448
- export default function HomePage({ locale }: { locale: string }) {
449
- // Declare explícitamente el namespace utilizado por este componente
450
- const resources = await loadMessagesFor(locale); // tu cargador (JSON, etc.)
482
+ ```tsx fileName="src/components/I18nProvider.tsx"
483
+ "use client";
451
484
 
452
- const i18n = createInstance();
453
- i18n.use(initReactI18next).init({
454
- lng: locale,
455
- fallbackLng: "en",
456
- resources,
457
- ns: ["common", "about"],
458
- defaultNS: "common",
459
- interpolation: { escapeValue: false },
485
+ import * as React from "react";
486
+ import { I18nextProvider } from "react-i18next";
487
+ import { createInstance } from "i18next";
488
+ import { initReactI18next } from "react-i18next/initReactI18next";
489
+ import resourcesToBackend from "i18next-resources-to-backend";
490
+ import { defaultLocale } from "@/i18n.config";
491
+
492
+ const backend = resourcesToBackend(
493
+ (locale: string, namespace: string) =>
494
+ import(`../../locales/${locale}/${namespace}.json`)
495
+ );
496
+
497
+ type Props = {
498
+ locale: string;
499
+ namespaces?: string[];
500
+ resources?: Record<string, any>; // { ns: bundle }
501
+ children: React.ReactNode;
502
+ };
503
+
504
+ export default function I18nProvider({
505
+ locale,
506
+ namespaces = ["common"],
507
+ resources,
508
+ children,
509
+ }: Props) {
510
+ const [i18n] = React.useState(() => {
511
+ const i = createInstance();
512
+
513
+ i.use(initReactI18next)
514
+ .use(backend)
515
+ .init({
516
+ lng: locale,
517
+ fallbackLng: defaultLocale,
518
+ ns: namespaces,
519
+ resources: resources ? { [locale]: resources } : undefined,
520
+ defaultNS: "common",
521
+ interpolation: { escapeValue: false },
522
+ react: { useSuspense: false },
523
+ });
524
+
525
+ return i;
460
526
  });
461
527
 
462
- const { t } = useTranslation("about");
528
+ return <I18nextProvider i18n={i18n}>{children}</I18nextProvider>;
529
+ }
530
+ ```
531
+
532
+ ```tsx fileName="src/app/[locale]/layout.tsx"
533
+ import type { ReactNode } from "react";
534
+ import { locales, defaultLocale, isRtl, type Locale } from "@/i18n.config";
535
+
536
+ export const dynamicParams = false;
537
+
538
+ export function generateStaticParams() {
539
+ return locales.map((locale) => ({ locale }));
540
+ }
541
+
542
+ export default function LocaleLayout({
543
+ children,
544
+ params,
545
+ }: {
546
+ children: ReactNode;
547
+ params: { locale: string };
548
+ }) {
549
+ const locale: Locale = (locales as readonly string[]).includes(params.locale)
550
+ ? (params.locale as any)
551
+ : defaultLocale;
552
+
553
+ const dir = isRtl(locale) ? "rtl" : "ltr";
554
+
555
+ return (
556
+ <html lang={locale} dir={dir}>
557
+ <body>{children}</body>
558
+ </html>
559
+ );
560
+ }
561
+ ```
562
+
563
+ ```tsx fileName="src/app/[locale]/about.tsx"
564
+ import I18nProvider from "@/components/I18nProvider";
565
+ import { initI18next } from "@/app/i18n/server";
566
+ import type { Locale } from "@/i18n.config";
567
+ import ClientComponent from "@/components/ClientComponent";
568
+ import ServerComponent from "@/components/ServerComponent";
569
+
570
+ // Force static rendering for the page
571
+ export const dynamic = "force-static";
572
+
573
+ export default async function AboutPage({
574
+ params: { locale },
575
+ }: {
576
+ params: { locale: Locale };
577
+ }) {
578
+ const namespaces = ["common", "about"] as const;
579
+
580
+ const i18n = await initI18next(locale, [...namespaces]);
581
+ const tAbout = i18n.getFixedT(locale, "about");
463
582
 
464
583
  return (
465
- <I18nextProvider i18n={i18n}>
584
+ <I18nProvider locale={locale} namespaces={[...namespaces]}>
466
585
  <main>
467
- <h1>{t("title")}</h1>
586
+ <h1>{tAbout("title")}</h1>
587
+
468
588
  <ClientComponent />
469
- <ServerComponent />
589
+ <ServerComponent t={tAbout} locale={locale} count={0} />
470
590
  </main>
471
- </I18nextProvider>
591
+ </I18nProvider>
472
592
  );
473
593
  }
474
-
475
- export const getStaticProps: GetStaticProps = async ({ locale }) => {
476
- // Solo precargar los namespaces necesarios para ESTA página
477
- return {
478
- props: {
479
- ...(await serverSideTranslations(locale ?? "en", ["common", "about"])),
480
- },
481
- };
482
- };
483
594
  ```
484
595
 
485
596
  </TabItem>
@@ -525,8 +636,10 @@ export default async function LocaleLayout({
525
636
  const messages = await getMessages();
526
637
  const clientMessages = pick(messages, ["common", "about"]);
527
638
 
639
+ const rtlLocales = ["ar", "he", "fa", "ur"];
640
+
528
641
  return (
529
- <html lang={locale}>
642
+ <html lang={locale} dir={rtlLocales.includes(locale) ? "rtl" : "ltr"}>
530
643
  <body>
531
644
  <NextIntlClientProvider locale={locale} messages={clientMessages}>
532
645
  {children}
@@ -843,10 +956,11 @@ const ServerComponent = ({ count }: ServerComponentProps) => {
843
956
  type ServerComponentProps = {
844
957
  count: number;
845
958
  t: (key: string) => string;
959
+ formatter: Intl.NumberFormat;
846
960
  };
847
961
 
848
- const ServerComponent = ({ t, count }: ServerComponentProps) => {
849
- const formatted = new Intl.NumberFormat(i18n.language).format(count);
962
+ const ServerComponent = ({ t, count, formatter }: ServerComponentProps) => {
963
+ const formatted = formatter.format(count);
850
964
 
851
965
  return (
852
966
  <div>
@@ -860,7 +974,7 @@ const ServerComponent = ({ t, count }: ServerComponentProps) => {
860
974
  > Como el componente del servidor no puede ser async, necesitas pasar las traducciones y la función formateadora como props.
861
975
  >
862
976
  > - `const t = await getTranslations("about.counter");`
863
- > - `const format = await getFormatter();`
977
+ > - `const formatter = await getFormatter().then((formatter) => formatter.number());`
864
978
 
865
979
  </TabItem>
866
980
  <TabItem label="intlayer" value="intlayer">
@@ -19,6 +19,8 @@ slugs:
19
19
 
20
20
  # next-i18next VS next-intl VS intlayer | Internationalisation (i18n) Next.js
21
21
 
22
+ ![next-i18next VS next-intl VS intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/assets/i18next-next-intl-intlayer.png?raw=true)
23
+
22
24
  Examinons les similitudes et différences entre trois options i18n pour Next.js : next-i18next, next-intl, et Intlayer.
23
25
 
24
26
  Ce n’est pas un tutoriel complet. C’est une comparaison pour vous aider à choisir.
@@ -165,9 +167,9 @@ Dans le cas de `next-intl` et `next-i18next`, la bibliothèque nécessite de cha
165
167
 
166
168
  Voici un exemple de l'impact de l'optimisation de la taille du bundle en utilisant `intlayer` dans une application vite + react :
167
169
 
168
- | Bundle optimisé | Bundle non optimisé |
169
- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
170
- | ![bundle optimisé](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png) | ![bundle non optimisé](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle_no_optimization.png) |
170
+ | Bundle optimisé | Bundle non optimisé |
171
+ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
172
+ | ![bundle optimisé](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true) | ![bundle non optimisé](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle_no_optimization.png?raw=true) |
171
173
 
172
174
  ---
173
175
 
@@ -340,25 +342,25 @@ La structure de l'application est importante pour assurer une bonne maintenabili
340
342
 
341
343
  ```bash
342
344
  .
343
- ├── public
344
- │ └── locales
345
- │ ├── en
346
- │ │ ├── home.json
347
- │ │ └── navbar.json
348
- │ ├── fr
349
- │ │ ├── home.json
350
- │ │ └── navbar.json
351
- │ └── es
352
- │ ├── home.json
353
- │ └── navbar.json
354
- ├── next-i18next.config.js
345
+ ├── i18n.config.ts
355
346
  └── src
356
- ├── middleware.ts
347
+ ├── locales
348
+ │ ├── en
349
+ │ │ ├── common.json
350
+ │ │ └── about.json
351
+ │ └── fr
352
+ │ ├── common.json
353
+ │ └── about.json
357
354
  ├── app
358
- └── home.tsx
355
+ ├── i18n
356
+ │ │ └── server.ts
357
+ │ └── [locale]
358
+ │ ├── layout.tsx
359
+ │ └── about.tsx
359
360
  └── components
360
- └── Navbar
361
- └── index.tsx
361
+ ├── I18nProvider.tsx
362
+ ├── ClientComponent.tsx
363
+ └── ServerComponent.tsx
362
364
  ```
363
365
 
364
366
  </TabItem>
@@ -366,6 +368,7 @@ La structure de l'application est importante pour assurer une bonne maintenabili
366
368
 
367
369
  ```bash
368
370
  .
371
+ ├── i18n.ts
369
372
  ├── locales
370
373
  │ ├── en
371
374
  │ │ ├── home.json
@@ -376,11 +379,13 @@ La structure de l'application est importante pour assurer une bonne maintenabili
376
379
  │ └── es
377
380
  │ ├── home.json
378
381
  │ └── navbar.json
379
- ├── i18n.ts
380
382
  └── src
381
383
  ├── middleware.ts
382
384
  ├── app
383
- └── home.tsx
385
+ ├── i18n
386
+ │ │ └── server.ts
387
+ │ └── [locale]
388
+ │ └── home.tsx
384
389
  └── components
385
390
  └── Navbar
386
391
  └── index.tsx
@@ -395,9 +400,11 @@ La structure de l'application est importante pour assurer une bonne maintenabili
395
400
  └── src
396
401
  ├── middleware.ts
397
402
  ├── app
398
- │ └── home
399
- └── index.tsx
400
- │ └── index.content.ts
403
+ │ └── [locale]
404
+ ├── layout.tsx
405
+ │ └── home
406
+ │ ├── index.tsx
407
+ │ └── index.content.ts
401
408
  └── components
402
409
  └── Navbar
403
410
  ├── index.tsx
@@ -525,8 +532,10 @@ export default async function LocaleLayout({
525
532
  const messages = await getMessages();
526
533
  const clientMessages = pick(messages, ["common", "about"]);
527
534
 
535
+ const rtlLocales = ["ar", "he", "fa", "ur"];
536
+
528
537
  return (
529
- <html lang={locale}>
538
+ <html lang={locale} dir={rtlLocales.includes(locale) ? "rtl" : "ltr"}>
530
539
  <body>
531
540
  <NextIntlClientProvider locale={locale} messages={clientMessages}>
532
541
  {children}
@@ -843,10 +852,11 @@ const ServerComponent = ({ count }: ServerComponentProps) => {
843
852
  type ServerComponentProps = {
844
853
  count: number;
845
854
  t: (key: string) => string;
855
+ formatter: Intl.NumberFormat;
846
856
  };
847
857
 
848
- const ServerComponent = ({ t, count }: ServerComponentProps) => {
849
- const formatted = new Intl.NumberFormat(i18n.language).format(count);
858
+ const ServerComponent = ({ t, count, formatter }: ServerComponentProps) => {
859
+ const formatted = formatter.format(count);
850
860
 
851
861
  return (
852
862
  <div>
@@ -860,7 +870,7 @@ const ServerComponent = ({ t, count }: ServerComponentProps) => {
860
870
  > Comme le composant serveur ne peut pas être asynchrone, vous devez passer les traductions et la fonction de formatage en tant que props.
861
871
  >
862
872
  > - `const t = await getTranslations("about.counter");`
863
- > - `const format = await getFormatter();`
873
+ > - `const formatter = await getFormatter().then((formatter) => formatter.number());`
864
874
 
865
875
  </TabItem>
866
876
  <TabItem label="intlayer" value="intlayer">