Автор:
    БозданиС:2026-09-23ПослСднСС обновлСниС:2026-09-23

    Intlayer Π»Π΅Π³Ρ‡Π΅, Ρ‡Π΅ΠΌ Paraglide?

    Π”Π°.

    Π£ Paraglide слоТилась отличная рСпутация самого Π»Π΅Π³ΠΊΠΎΠ³ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ для i18n, ΠΈ Π½Π° ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ взгляд Π±Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊ с этим согласСн: Ρ€Π°Π·ΠΌΠ΅Ρ€ Π΅Π³ΠΎ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Π±Π»ΠΈΠ·ΠΎΠΊ ΠΊ Π½ΡƒΠ»ΡŽ. Однако Π½ΡƒΠ»Π΅Π²ΠΎΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ вовсС Π½Π΅ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ количСство ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹Ρ… Π±Π°ΠΉΡ‚ΠΎΠ². Π­Ρ‚ΠΎ лишь Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π±Π°ΠΉΡ‚Ρ‹ находятся Ρ‚Π°ΠΌ, ΠΊΡƒΠ΄Π° эта ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠ° Π½Π΅ заглядываСт.

    ΠšΠ»ΡŽΡ‡Π΅Π²Ρ‹Π΅ Π²Ρ‹Π²ΠΎΠ΄Ρ‹

    Π Π°Π·ΠΌΠ΅Ρ€ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ скрыт, Π° Π½Π΅ устранСн:

    Paraglide Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ€Π°Π½Ρ‚Π°ΠΉΠΌ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ сообщСний нСпосрСдствСнно Π² Π²Π°ΡˆΡƒ ΠΊΠΎΠ΄ΠΎΠ²ΡƒΡŽ Π±Π°Π·Ρƒ. Π­Ρ‚ΠΎΡ‚ ΠΊΠΎΠ΄ отправляСтся Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€, Π½ΠΎ учитываСтся ΠΊΠ°ΠΊ ваш ΠΊΠΎΠ΄, Π° Π½Π΅ ΠΊΠΎΠ΄ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ.

    ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΠΈΠ΅ ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€Π° - это Π½Π΅ бСсплатный Π²Ρ‹ΠΈΠ³Ρ€Ρ‹Ρˆ:

    ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Π²Ρ‹Π·ΠΎΠ² m.my_key() ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ опрСдСляСт локаль, считывая cookie ΠΈΠ»ΠΈ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ отрисованного ΡƒΠ·Π»Π°, вмСсто Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π΅Π΅ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· ΠΈΠ· контСкста.

    НСт динамичСской Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ:

    Paraglide ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ всС Π»ΠΎΠΊΠ°Π»ΠΈ сообщСния Π² клиСнтский Π±Π°Π½Π΄Π». Intlayer с importMode: 'dynamic' ΠΈΠ»ΠΈ 'fetch' Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Ρƒ локаль, которая сСйчас отобраТаСтся.

    Tree shaking Π½Π΅ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½:

    Π’ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π½Π°ΡˆΠΈΡ… тСстах заявлСнный Paraglide tree shaking Π½Π΅ сработал. ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ собствСнный Π±Π°Π½Π΄Π».

    ΠšΡƒΠ΄Π° ΡƒΡ…ΠΎΠ΄ΠΈΡ‚ вСс Paraglide?

    Π’ ΠΎΡ‚Ρ‡Π΅Ρ‚Π°Ρ… Π±Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊΠΎΠ² ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠ° Β«Ρ€Π°Π·ΠΌΠ΅Ρ€ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈΒ» измСряСт ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€ ΠΈ Ρ…ΡƒΠΊΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ i18n Π² пустом ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π΅, Π΄ΠΎ добавлСния ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Π»ΠΈΠ±ΠΎ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°.

    Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° (TanStack Start)Π Π°Π·ΠΌΠ΅Ρ€ Π»ΠΈΠ±Ρ‹ (gz)Π Π°Π·ΠΌΠ΅Ρ€ Π»ΠΈΠ±Ρ‹ (min)
    @inlang/paraglide-js@2.15.11.8 KB4.5 KB
    react-intlayer@9.5.15.0 KB15.2 KB

    Π’ ΠΎΡ‚Ρ€Ρ‹Π²Π΅ ΠΎΡ‚ контСкста Paraglide Π²Ρ‹ΠΈΠ³Ρ€Ρ‹Π²Π°Π΅Ρ‚. Но Paraglide - это компилятор: ΠΎΠ½ Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ ваши Ρ„Π°ΠΉΠ»Ρ‹ messages/*.json ΠΈ записываСт ΠΏΠ°ΠΏΠΊΡƒ paraglide/ Π² ваш Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ. Она содСрТит runtime.js (ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π»ΠΎΠΊΠ°Π»ΠΈ, стратСгии cookie ΠΈ storage, локализация URL) ΠΈ ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΉ JavaScript-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ сообщСниС.

    bash
    src/paraglide/
    β”œβ”€β”€ runtime.js      # ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π»ΠΎΠΊΠ°Π»ΠΈ, стратСгии, URL-Ρ…Π΅Π»ΠΏΠ΅Ρ€Ρ‹
    β”œβ”€β”€ server.js
    β”œβ”€β”€ messages.js     # рСэкспорт всСх сообщСний
    └── messages/
        β”œβ”€β”€ _index.js
        β”œβ”€β”€ en.js
        └── fr.js
    

    ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ этот ΠΊΠΎΠ΄ находится Π² ΠΏΠ°ΠΏΠΊΠ΅ src/ ΠΈ Π²Ρ‹ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚Π΅ Π΅Π³ΠΎ ΠΏΠΎ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΌΡƒ ΠΏΡƒΡ‚ΠΈ, сборщик приписываСт Π΅Π³ΠΎ Π²Π°ΡˆΠ΅ΠΌΡƒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ, Π° Π½Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρƒ ΠΈΠ· node_modules. Колонка Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΏΠΎΡ‡Ρ‚ΠΈ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, хотя Ρ‚Π° ΠΆΠ΅ самая Π»ΠΎΠ³ΠΈΠΊΠ° ΠΏΠΎ-ΠΏΡ€Π΅ΠΆΠ½Π΅ΠΌΡƒ отправляСтся Π² Π±Π°Π½Π΄Π»Π΅ вашСй страницы.

    ГСнСрация ΠΊΠΎΠ΄Π° сама ΠΏΠΎ сСбС Π½Π΅ΠΏΠ»ΠΎΡ…Π°: сгСнСрированный Ρ€Π°Π½Ρ‚Π°ΠΉΠΌ содСрТит Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Ρƒ Π»ΠΎΠ³ΠΈΠΊΡƒ, которая Π½ΡƒΠΆΠ½Π° вашСй ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ (стратСгия прСфиксов, cookie ΠΈΠ»ΠΈ local storage ΠΈ Ρ‚. Π΄.). Intlayer достигаСт Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΈΠ½Π°Ρ‡Π΅, внСдряя ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ окруТСния Π½Π° этапС сборки, благодаря Ρ‡Π΅ΠΌΡƒ Π±Π°Π½Π΄Π»Π΅Ρ€ удаляСт Π²Π΅Ρ‚Π²ΠΈ ΠΊΠΎΠ΄Π°, Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ вашСй ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠ΅ΠΉ. Оба ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° ΠΎΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π² 3–10 Ρ€Π°Π· Π»Π΅Π³Ρ‡Π΅, Ρ‡Π΅ΠΌ i18next ΠΈΠ»ΠΈ next-intl.

    ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ чСстноС сравнСниС - это Π½Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ. Π­Ρ‚ΠΎ JavaScript, фактичСски отправляСмый Π½Π° ΠΊΠ°ΠΆΠ΄ΡƒΡŽ страницу.

    Π˜Π·ΠΌΠ΅Ρ€Π΅Π½Π½Ρ‹ΠΉ вСс страницы

    ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ TanStack Start, 10 страниц, измСрСния Π½Π° ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°Ρ… en ΠΈ fr, сТатиС gzip:

    ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡΠ‘Ρ€Π΅Π΄Π½ΠΈΠΉ JS стр (gz)Π’Ρ‹ΡˆΠ΅ Π±Π°Π·Ρ‹Π£Ρ‚Π΅Ρ‡ΠΊΠ° Π»ΠΎΠΊΠ°Π»ΠΈΠ£Ρ‚Π΅Ρ‡ΠΊΠ° Π΄Ρ€ΡƒΠ³ΠΈΡ… страниц
    Базовая (Π±Π΅Π· i18n)111.0 KB-0.0%0.0%
    paraglide (любая стратСгия)125.1 KB+14.1 KB49.7%0.0%
    intlayer (importMode: static)125.8 KB+14.8 KB50.0%0.0%
    intlayer (importMode: dynamic)118.6 KB+7.6 KB0.0%0.0%

    Next.js 16 App Router, Ρ‚ΠΎ ΠΆΠ΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅:

    ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡΠ‘Ρ€Π΅Π΄Π½ΠΈΠΉ JS стр (gz)Π’Ρ‹ΡˆΠ΅ Π±Π°Π·Ρ‹
    Базовая (Π±Π΅Π· i18n)141.0 KB-
    paraglide-next155.3 KB+14.3 KB
    next-intlayer141.3 KB+0.3 KB

    ДинамичСская Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° JSON

    ЛСнивая Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ² Π²ΠΎ врСмя выполнСния

    ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π½Ρ‹ΠΉ JSON (пространства ΠΈΠΌΠ΅Π½)

    ΠŸΡ€ΠΎΡΡ‚Ρ€Π°Π½ΡΡ‚Π²Π° ΠΈΠΌΠ΅Π½ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ страницы

    Π‘Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ I18n

    Π§Ρ‚ΠΎ это Π·Π° ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠ°?

    ΠžΠ±Ρ‰ΠΈΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΏΠ°ΠΊΠ΅Ρ‚Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΈΠ½Ρ‚Π΅Ρ€Π½Π°Ρ†ΠΈΠΎΠ½Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ gzip. Он Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€ ΠΈ Π»ΠΎΠ³ΠΈΠΊΡƒ извлСчСния ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° послС tree-shaking ΠΈ ΠΌΠΈΠ½ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ.

    ΠŸΠΎΡ‡Π΅ΠΌΡƒ это Π²Π°ΠΆΠ½ΠΎ?

    МСньший Ρ€Π°Π·ΠΌΠ΅Ρ€ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ сниТаСт Π½Π°Ρ‡Π°Π»ΡŒΠ½ΡƒΡŽ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ JavaScript, Ρ‡Ρ‚ΠΎ ускоряСт Π·Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π° Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π΅.

    Π’ΠΈΠ΄

    ΠŸΠΎΠ»Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Ρ‹ Π² ΠΎΡ‚Ρ‡Π΅Ρ‚Π΅ ΠΎ Π±Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊΠ΅ TanStack Start ΠΈ Π² ΠΎΡ‚Ρ‡Π΅Ρ‚Π΅ ΠΎ Π±Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊΠ΅ Next.js. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Π±Π°Π½Π΄Π» ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒ Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ Π±Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊΠ°.

    Π”Π²Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° Π±Ρ€ΠΎΡΠ°ΡŽΡ‚ΡΡ Π² Π³Π»Π°Π·Π°:

    • Π’ Ρ€Π΅ΠΆΠΈΠΌΠ΅ static Intlayer отправляСт практичСски Ρ‚ΠΎΡ‚ ΠΆΠ΅ объСм Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‡Ρ‚ΠΎ ΠΈ Paraglide (125.8 KB ΠΏΡ€ΠΎΡ‚ΠΈΠ² 125.1 KB). Π­Ρ‚ΠΎ ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌΠΎ: ΠΎΠ±Π° Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ всС Π»ΠΎΠΊΠ°Π»ΠΈ сообщСний, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… страницСй.
    • Paraglide остаСтся Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ 125.1 KB ΠΏΡ€ΠΈ любой стратСгии, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² Π½Π΅ΠΌ Π½Π΅Ρ‚ динамичСского Ρ€Π΅ΠΆΠΈΠΌΠ°. КаТдая строка Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅ Π²Ρ‹ΡˆΠ΅ соотвСтствуСт статичСской ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ.

    ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΠΈΠ΅ Provider: идСя, каТущаяся Ρ…ΠΎΡ€ΠΎΡˆΠ΅ΠΉ лишь Π½Π° ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ взгляд

    Π£ Paraglide Π½Π΅Ρ‚ ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€Π°. Π’Ρ‹ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚Π΅ сообщСниС ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚Π΅ Π΅Π³ΠΎ:

    Hero.tsx
    import { m } from "../paraglide/messages.js";
    
    export const Hero = () => (
      <section>
        <h1>{m.hero_title()}</h1>
        <p>{m.hero_description()}</p>
        <button>{m.hero_cta()}</button>
      </section>
    );
    

    Ни контСкста, Π½ΠΈ ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΠΈ, Π½ΠΈ Ρ…ΡƒΠΊΠ°. Π­Ρ‚ΠΎ каТСтся ΠΏΡ€ΠΎΡ‰Π΅. Но локаль всС Ρ€Π°Π²Π½ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡ‚ΠΊΡƒΠ΄Π°-Ρ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ. КаТдая сгСнСрированная функция сообщСния выглядит ΠΏΡ€ΠΈΠ±Π»ΠΈΠ·ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‚Π°ΠΊ (ΡƒΠΏΡ€ΠΎΡ‰Π΅Π½Π½ΠΎ):

    paraglide/messages/_index.js
    export const hero_title = (inputs = {}, options = {}) => {
      const locale = options.locale ?? getLocale(); // вычисляСтся ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π΅
    
      if (locale === "en") return en.hero_title(inputs);
      if (locale === "fr") return fr.hero_title(inputs);
      // ...ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΉ Π²Π΅Ρ‚ΠΊΠ΅ Π½Π° ΠΊΠ°ΠΆΠ΄ΡƒΡŽ локаль
    };
    

    А getLocale() ΠΏΡ€ΠΎΡ…ΠΎΠ΄ΠΈΡ‚ ΠΏΠΎ всСм настроСнным стратСгиям (cookie, local storage, URL, базовая локаль), Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ локаль. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ отрисовываСмый тСкстовый ΡƒΠ·Π΅Π» (<>{m.my_key()}</>) выполняСт собствСнноС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π»ΠΎΠΊΠ°Π»ΠΈ, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ document.cookie Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅. Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° с 200 ΠΏΠ΅Ρ€Π΅Π²Π΅Π΄Π΅Π½Π½Ρ‹ΠΌΠΈ строками вычисляСт локаль 200 Ρ€Π°Π· Π·Π° ΠΎΠ΄ΠΈΠ½ Ρ€Π΅Π½Π΄Π΅Ρ€, ΠΈ Π·Π°Ρ‚Π΅ΠΌ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΏΠ΅Ρ€Π΅Ρ€Π΅Π½Π΄Π΅Ρ€Π΅.

    Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° с ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€ΠΎΠΌ считываСт локаль ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·, сохраняСт Π΅Π΅ Π² контСкстС (ΠΈΠ»ΠΈ сигналС, ΠΈΠ»ΠΈ сторС), ΠΈ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ·Π΅Π» Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΡƒΠΆΠ΅ находящССся Π² ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠΉ памяти. ΠŸΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€ вСсит всСго нСсколько сотСн Π±Π°ΠΉΡ‚. ΠžΡ‚ΠΊΠ°Π· ΠΎΡ‚ Π½Π΅Π³ΠΎ Π½Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ процСссор ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Ρ€Π΅Π½Π΄Π΅Ρ€Π΅, Ρ‡Ρ‚ΠΎ наглядно отраТаСтся Π² Π±Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊΠ΅: врСмя Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ страницы ΠΈ ΡΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ смСны языка Ρƒ Paraglide ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½ΠΎ ΡƒΡΡ‚ΡƒΠΏΠ°ΡŽΡ‚ Intlayer Π½Π° TanStack Start (22.1 мс ΠΏΡ€ΠΎΡ‚ΠΈΠ² 14.6 мс ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ страницы, 4.3 мс ΠΏΡ€ΠΎΡ‚ΠΈΠ² 3.2 мс ΠΏΡ€ΠΈ рСактивности E2E).

    Удобство Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ (DX)

    Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊΠΎΠΌ истины для Paraglide являСтся JSON, Π½ΠΎ Π²Ρ‹ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚Π΅ сам JSON. Π’Ρ‹ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚Π΅ сгСнСрированный Ρ„Π°ΠΉΠ» .js:

    messages/en.json
    {
      "hero_title": "Ship your app in every language"
    }
    
    messages/ru.json
    {
      "hero_title": "ΠŸΡƒΠ±Π»ΠΈΠΊΡƒΠΉΡ‚Π΅ вашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π° всСх языках"
    }
    
    Hero.tsx
    // БущСствуСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС ΠΏΠ΅Ρ€Π΅Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ компилятором ΠΈΠ· JSON
    import { m } from "../paraglide/messages.js";
    
    export const Hero = () => <h1>{m.hero_title()}</h1>;
    
    Hero.content.ts
    import { t, type Dictionary } from "intlayer";
    
    export default {
      key: "hero",
      content: {
        title: t({
          ru: "ΠŸΡƒΠ±Π»ΠΈΠΊΡƒΠΉΡ‚Π΅ вашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π° всСх языках",
          en: "Ship your app in every language",
        }),
      },
    } satisfies Dictionary;
    
    Hero.tsx
    import { useIntlayer } from "react-intlayer";
    
    export const Hero = () => {
      const { title } = useIntlayer("hero");
    
      return <h1>{title}</h1>;
    };
    

    Π’Π°ΠΊΠΎΠΉ Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ процСсс Π²Π»Π΅Ρ‡Π΅Ρ‚ Π·Π° собой ΠΈΠ·Π΄Π΅Ρ€ΠΆΠΊΠΈ:

    • Π›ΡŽΠ±ΠΎΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π² Ρ„Π°ΠΉΠ»Π΅ JSON Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ ΠΈΠΌΠΏΠΎΡ€Ρ‚ Π·Π°Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΈΠ»ΠΈ обновятся Ρ‚ΠΈΠΏΡ‹.
    • Π‘Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Π½Π½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ paraglide/ приходится Π»ΠΈΠ±ΠΎ ΠΊΠΎΠΌΠΌΠΈΡ‚ΠΈΡ‚ΡŒ Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ (Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚Π°ΠΌ слияния ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ PR с ΠΏΡ€Π°Π²ΠΊΠ°ΠΌΠΈ тСкста), Π»ΠΈΠ±ΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ Π² ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ (Ρ‡Ρ‚ΠΎ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ шага Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ ΠΏΠ΅Ρ€Π΅Π΄ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ Ρ‚ΠΈΠΏΠΎΠ², тСстом ΠΈ Π·Π°Π΄Π°Ρ‡Π΅ΠΉ CI).
    • КаТдая строка прСвращаСтся Π² Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. ΠšΠΎΠ½ΡΡ‚Π°Π½Ρ‚Ρ‹ становятся m.key() Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ Π²Π΅Π·Π΄Π΅, Π΄Π°ΠΆΠ΅ Ρ‚Π°ΠΌ, Π³Π΄Π΅ подошло Π±Ρ‹ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ΅ статичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.

    Tree Shaking: ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ свой Π±Π°Π½Π΄Π»

    Π“Π»Π°Π²Π½ΠΎΠ΅ ΠΎΠ±Π΅Ρ‰Π°Π½ΠΈΠ΅ Paraglide Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π½Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ сообщСния ΡƒΠ΄Π°Π»ΡΡŽΡ‚ΡΡ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ tree shaking, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ сообщСниС являСтся ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ экспортом. Π’ Π±Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊΠ΅ Svelte + Vite это Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ‚Π°ΠΊ, ΠΊΠ°ΠΊ заявлСно.

    Π’ Π΄Ρ€ΡƒΠ³ΠΈΡ… окруТСниях этого Π½Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ. Π’ нашСм тСстС Π½Π° Next.js страницы Paraglide вСсят Π½Π° 14 KB большС Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ прилоТСния, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ next-intlayer добавляСт лишь 0.3 KB. ΠŸΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠ΅ тСсты Π½Π° TanStack Start Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Π»ΠΈ, Ρ‡Ρ‚ΠΎ сообщСния с Π΄Ρ€ΡƒΠ³ΠΈΡ… страниц ΠΏΠΎΠΏΠ°Π΄Π°Π»ΠΈ Π² Π±Π°Π½Π΄Π» Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°.

    Tree shaking зависит ΠΎΡ‚ вашСго сборщика (Turbopack, Rolldown, Rollup), способа ΠΈΠΌΠΏΠΎΡ€Ρ‚Π° сообщСний (import { m } ΠΏΡ€ΠΎΡ‚ΠΈΠ² import * as m) ΠΈ Π°Π½Π°Π»ΠΈΠ·Π° сайд-эффСктов. Если Π²Ρ‹ Π²Ρ‹Π±ΠΈΡ€Π°Π΅Ρ‚Π΅ Paraglide ΠΈΠ·-Π·Π° Ρ€Π°Π·ΠΌΠ΅Ρ€Π°, ΠΎΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅ Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ Π±Π°Π½Π΄Π»Π° ΠΈ ΡƒΠ±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ это Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π² вашСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ.

    НСт динамичСской Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ

    Π­Ρ‚ΠΎ Ρ„ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½ΠΎΠ΅ структурноС ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅. Π’ Paraglide Π½Π΅Ρ‚ способа Π·Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΉ Π»ΠΎΠΊΠ°Π»ΠΈ Π·Π° Ρ€Π°Π·: каТдая функция сообщСния статичСски ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ языка, поэтому Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ всС языки ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ Π² ваш клиСнтский Π±Π°Π½Π΄Π».

    ΠŸΡ€ΠΈ 2 языках ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π° Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ° Π½Π° ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ тратится Π²ΠΏΡƒΡΡ‚ΡƒΡŽ, Ρ‡Ρ‚ΠΎ соотвСтствуСт ΡƒΡ‚Π΅Ρ‡ΠΊΠ΅ Π»ΠΎΠΊΠ°Π»ΠΈ ΠΎΠΊΠΎΠ»ΠΎ ~50%, ΠΈΠ·ΠΌΠ΅Ρ€Π΅Π½Π½ΠΎΠΉ Π²Ρ‹ΡˆΠ΅. ΠŸΡ€ΠΈ 10 языках бСсполСзны 90% объСма. ΠŸΡ€ΠΈ 30 языках - 97%.

    ΠŸΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Π½Π° Π΄ΠΈΠ½Π°ΠΌΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ Ρ‚Π°ΠΊΠΆΠ΅ Π½Π΅ Ρ€Π΅ΡˆΠΈΠ» Π±Ρ‹ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ: ΠΏΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ сообщСниС лСнивая Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΈΠ· Π½ΠΈΡ… ΠΏΡ€ΠΈΠ²Π΅Π»Π° Π±Ρ‹ ΠΊ тысячам сСтСвых запросов.

    Intlayer позволяСт Π²Ρ‹Π±ΠΈΡ€Π°Ρ‚ΡŒ ΡΡ‚Ρ€Π°Ρ‚Π΅Π³ΠΈΡŽ ΠΊΠ°ΠΊ глобально, Ρ‚Π°ΠΊ ΠΈ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ словаря ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ:

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";
    
    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      dictionary: {
        importMode: "dynamic", // 'static' | 'dynamic' | 'fetch'
      },
    };
    
    export default config;
    
    importModeΠ§Ρ‚ΠΎ отправляСтся ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒvs. Paraglide
    staticВсС Π»ΠΎΠΊΠ°Π»ΠΈ словарСй, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ страницаВСорСтичСски Ρ‚ΠΎΡ‚ ΠΆΠ΅ объСм
    dynamicВолько активная локаль, лСнивая Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ° для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ словаряВ N Ρ€Π°Π· мСньшС ΠΏΡ€ΠΈ N локалях
    fetchВолько активная локаль, получаСмая Ρ‡Π΅Ρ€Π΅Π· Live Sync APIΠ’ N Ρ€Π°Π· мСньшС ΠΏΡ€ΠΈ N локалях

    Благодаря трансформации Π½Π° этапС сборки ΠΈ Ρ€Π΅ΠΆΠΈΠΌΡƒ importMode: 'static', Intlayer тСорСтичСски Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ Ρ€ΠΎΠ²Π½ΠΎ Ρ‚ΠΎΡ‚ ΠΆΠ΅ объСм Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‡Ρ‚ΠΎ ΠΈ Paraglide. А Π² Ρ€Π΅ΠΆΠΈΠΌΠ°Ρ… 'dynamic' ΠΈΠ»ΠΈ 'fetch' ΠΎΠ½ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ трСбуСтся Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Π»ΠΎΠΊΠ°Π»ΠΈ: для прилоТСния Π½Π° N языках объСм ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Π΅ΠΌΡ‹Ρ… ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ² оказываСтся Π² N Ρ€Π°Π· мСньшС, Ρ‡Π΅ΠΌ Ρƒ Paraglide.

    Π“Π΄Π΅ Paraglide всС Π΅Ρ‰Π΅ умСстСн

    Если ваш стСк - это Svelte с Vite ΠΈ Π²Ρ‹ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚Π΅ Π΄Π²Π° ΠΈΠ»ΠΈ Ρ‚Ρ€ΠΈ языка, tree shaking Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΊΠ°ΠΊ заявлСно, Π° Π½Π°ΠΊΠ»Π°Π΄Π½Ρ‹Π΅ расходы Π½Π° лишниС Π»ΠΎΠΊΠ°Π»ΠΈ ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ Π½Π΅Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ.

    Если ваша ΠΊΠΎΠΌΠ°Π½Π΄Π° ΡƒΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ экосистСму inlang (Fink, Sherlock, ΠΏΠ»Π°Π³ΠΈΠ½Ρ‹ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ² сообщСний), Paraglide Π½Π°Ρ‚ΠΈΠ²Π½ΠΎ интСгрируСтся Π² этот процСсс.

    ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ Π½Π° своСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ

    ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ объСм Π±Π°Π½Π΄Π»Π° ΠΈ ΡƒΡ‚Π΅Ρ‡ΠΊΠΈ Π»ΠΎΠΊΠ°Π»Π΅ΠΉ вашСго Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ прилоТСния с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ бСсплатного инструмСнта i18n SEO Scanner:

    Установка Intlayer:

    bash
    npx intlayer init --interactive
    

    Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹

    ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ

    Пока Π½Π΅Ρ‚ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅Π². Π‘ΡƒΠ΄ΡŒΡ‚Π΅ ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ, ΠΊΡ‚ΠΎ подСлится своими мыслями.

    ΠŸΠΎΡ…ΠΎΠΆΠΈΠ΅ сообщСния

    ПослСдниС сообщСния