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

    ΠŸΠ΅Ρ€Π΅Π²Π΅Π΄ΠΈΡ‚Π΅ ваш сайт Π½Π° Tanstack Start с Solid.js, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Intlayer

    Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠ°Π½ΠΈΠ΅

    Π­Ρ‚ΠΎ руководство дСмонстрируСт, ΠΊΠ°ΠΊ ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Intlayer для бСсшовной ΠΈΠ½Ρ‚Π΅Ρ€Π½Π°Ρ†ΠΈΠΎΠ½Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ… Tanstack Start с Solid.js, ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ с ΡƒΡ‡Π΅Ρ‚ΠΎΠΌ Π»ΠΎΠΊΠ°Π»ΠΈ, ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ TypeScript ΠΈ соврСмСнными ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ°ΠΌΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ.

    ΠŸΠΎΡ‡Π΅ΠΌΡƒ Intlayer Π»ΡƒΡ‡ΡˆΠ΅ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²?

    По ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с основными Ρ€Π΅ΡˆΠ΅Π½ΠΈΡΠΌΠΈ, Ρ‚Π°ΠΊΠΈΠΌΠΈ ΠΊΠ°ΠΊ Β«react-i18nextΒ» ΠΈΠ»ΠΈ Β«i18nextΒ», Intlayer ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя встроСнныС ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ:

    Intlayer ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½ для идСальной Ρ€Π°Π±ΠΎΡ‚Ρ‹ с TanStack Start ΠΈ Solid, прСдлагая ΠΌΠ½ΠΎΠ³ΠΎΡΠ·Ρ‹Ρ‡Π½ΡƒΡŽ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΡŽ, ΠΊΠ°Ρ€Ρ‚Ρƒ сайта ΠΈ всС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ для ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ ΠΈΠ½Ρ‚Π΅Ρ€Π½Π°Ρ†ΠΈΠΎΠ½Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ (i18n).

    ВмСсто Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΎΠ³Ρ€ΠΎΠΌΠ½Ρ‹Ρ… Ρ„Π°ΠΉΠ»ΠΎΠ² JSON Π½Π° свои страницы Π·Π°Π³Ρ€ΡƒΠΆΠ°ΠΉΡ‚Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΉ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚. Intlayer ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΡ‚ΡŒ Ρ€Π°Π·ΠΌΠ΅Ρ€ Π±Π°Π½Π΄Π»Π° ΠΈ страниц Π΄ΠΎ 50Β %.

    ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ области содСрТимого вашСго прилоТСния ΠΎΠ±Π»Π΅Π³Ρ‡Π°Π΅Ρ‚ обслуТиваниС ΠΊΡ€ΡƒΠΏΠ½ΠΎΠΌΠ°ΡΡˆΡ‚Π°Π±Π½Ρ‹Ρ… ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄ΡƒΠ±Π»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠ»ΠΈ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, Π½Π΅ ΡƒΡ‚Ρ€ΡƒΠΆΠ΄Π°Π² сСбя мыслСнным Π±Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ всСй ΠΊΠΎΠ΄ΠΎΠ²ΠΎΠΉ Π±Π°Π·Ρ‹ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, Intlayer ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½, Ρ‡Ρ‚ΠΎ обСспСчиваСт Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ вашСго ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°.

    БовмСстноС Ρ€Π°Π·ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ контСкст, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΉ для ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ большого языка (LLM). Intlayer Ρ‚Π°ΠΊΠΆΠ΅ поставляСтся с Π½Π°Π±ΠΎΡ€ΠΎΠΌ инструмСнтов, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ CLI для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ отсутствия ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ²,LSP, MCP, ΠΈ agent skills, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° (DX) Π΅Ρ‰Π΅ Π±ΠΎΠ»Π΅Π΅ ΡƒΠ΄ΠΎΠ±Π½ΠΎΠΉ для Π°Π³Π΅Π½Ρ‚ΠΎΠ² ИИ.

    Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·Π°Ρ†ΠΈΡŽ для ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° Π² своСм ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π΅ CI/CD, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ LLM ΠΏΠΎ Π²Π°ΡˆΠ΅ΠΌΡƒ Π²Ρ‹Π±ΠΎΡ€Ρƒ Π·Π° счСт вашСго поставщика ИИ. Intlayer Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ компилятор для Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ извлСчСния ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π²Π΅Π±-ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡƒ, которая ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΈΡ‚ΡŒ Π² Ρ„ΠΎΠ½ΠΎΠ²ΠΎΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅.

    ΠŸΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π±ΠΎΠ»ΡŒΡˆΠΈΡ… Ρ„Π°ΠΉΠ»ΠΎΠ² JSON ΠΊ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°ΠΌ с ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒΡŽ ΠΈ Ρ€Π΅Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒΡŽ. Intlayer ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° Π²ΠΎ врСмя сборки (build time).

    Intlayer ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ большС, Ρ‡Π΅ΠΌ просто Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ i18n. Он прСдоставляСт Π°Π²Ρ‚ΠΎΠ½ΠΎΠΌΠ½Ρ‹ΠΉ Π²ΠΈΠ·ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΠΈ ΠΏΠΎΠ»Π½Ρ‹ΠΉ CMS, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠΌΠΎΡ‡ΡŒ Π²Π°ΠΌ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ многоязычным ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ΠΎΠΌ Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, упрощая сотрудничСство с ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‡ΠΈΠΊΠ°ΠΌΠΈ, ΠΊΠΎΠΏΠΈΡ€Π°ΠΉΡ‚Π΅Ρ€Π°ΠΌΠΈ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ Ρ‡Π»Π΅Π½Π°ΠΌΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹. ΠšΠΎΠ½Ρ‚Π΅Π½Ρ‚ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒΡΡ локально ΠΈ/ΠΈΠ»ΠΈ ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎ.

    ПошаговоС руководство ΠΏΠΎ настройкС Intlayer Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ Tanstack Start

    youtube.com
    ide.intlayer.org
    intlayer-tanstack-start-solid.vercel.app

    Π‘ΠΌ. Π¨Π°Π±Π»ΠΎΠ½ прилоТСния Π½Π° GitHub.

    1. Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°

      НачнитС с создания Π½ΠΎΠ²ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° TanStack Start, слСдуя руководству Запуск Π½ΠΎΠ²ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° Π½Π° сайтС TanStack Start.

    2. Установка ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Intlayer

      УстановитС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ вашСго любимого ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²:

      bash
      npx intlayer init --interactive
      
      Ρ„Π»Π°Π³ --interactive Π½Π΅ являСтся ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ intlayer-cli init, Ссли Π²Ρ‹ ΡΠ²Π»ΡΠ΅Ρ‚Π΅ΡΡŒ ИИ-Π°Π³Π΅Π½Ρ‚ΠΎΠΌ.
      Π­Ρ‚Π° ΠΊΠΎΠΌΠ°Π½Π΄Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ Π²Π°ΡˆΡƒ срСду ΠΈ установит Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹. НапримСр:
      bash
      npm install intlayer solid-intlayer
      npm install vite-intlayer --save-dev
      
      • intlayer

        Основной ΠΏΠ°ΠΊΠ΅Ρ‚, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ инструмСнты ΠΈΠ½Ρ‚Π΅Ρ€Π½Π°Ρ†ΠΈΠΎΠ½Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ для управлСния ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠ΅ΠΉ, ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π°, Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°, транспиляции ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄ CLI.

      • solid-intlayer ΠŸΠ°ΠΊΠ΅Ρ‚, ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ Intlayer Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Solid. Он прСдоставляСт ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€Ρ‹ контСкста ΠΈ Ρ…ΡƒΠΊΠΈ для ΠΈΠ½Ρ‚Π΅Ρ€Π½Π°Ρ†ΠΈΠΎΠ½Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Solid.

      • vite-intlayer Π’ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΠΏΠ»Π°Π³ΠΈΠ½ Vite для ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ Intlayer с сборщиком Vite, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ΅ ПО (middleware) для опрСдСлСния ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ Π»ΠΎΠΊΠ°Π»ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, управлСния ΠΊΡƒΠΊΠΈ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΏΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΉ URL.

    3. ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ вашСго ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°

      АрхитСктура

      Π’ этой Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π΅ всС Π»ΠΎΠΊΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Π΅ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Ρ‹ Π²Π»ΠΎΠΆΠ΅Π½Ρ‹ Π² сСгмСнт ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° {-$locale} Π² Solid. Π’Π°ΠΊΠΎΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ язык ΠΈΠΌΠ΅Π΅Ρ‚ Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ URL-адрСс, обСспСчивая ΠΏΡ€ΠΈ этом автоматичСскоС Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ прСфикса Π»ΠΎΠΊΠ°Π»ΠΈ, Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΡŽ ΠΈ SEO-ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΡŽ.

      bash
      .
      β”œβ”€β”€ src
      β”‚   β”œβ”€β”€ components
      β”‚   β”‚   β”œβ”€β”€ Header.content.ts
      β”‚   β”‚   β”œβ”€β”€ Header.tsx
      β”‚   β”‚   β”œβ”€β”€ LocaleSwitcher.content.ts
      β”‚   β”‚   β”œβ”€β”€ LocaleSwitcher.tsx
      β”‚   β”‚   └── LocalizedLink.tsx
      β”‚   β”œβ”€β”€ routes
      β”‚   β”‚   β”œβ”€β”€ {-$locale}
      β”‚   β”‚   β”‚   β”œβ”€β”€ 404.content.ts
      β”‚   β”‚   β”‚   β”œβ”€β”€ 404.tsx
      β”‚   β”‚   β”‚   β”œβ”€β”€ about.content.ts
      β”‚   β”‚   β”‚   β”œβ”€β”€ about.tsx
      β”‚   β”‚   β”‚   β”œβ”€β”€ index.content.tsx
      β”‚   β”‚   β”‚   β”œβ”€β”€ index.tsx
      β”‚   β”‚   β”‚   └── route.tsx             # Locale layout & prefix validation
      β”‚   β”‚   β”œβ”€β”€ __root.tsx                # Root route with IntlayerProvider
      β”‚   β”‚   └── sitemap[.]xml.ts
      β”‚   β”œβ”€β”€ router.tsx
      β”‚   └── styles.css
      β”œβ”€β”€ intlayer.config.ts
      β”œβ”€β”€ package.json
      β”œβ”€β”€ tsconfig.json
      └── vite.config.ts
      

      ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ

      Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Ρ„Π°ΠΉΠ» ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ для настройки языков вашСго прилоТСния:

      intlayer.config.ts
      import type { IntlayerConfig } from "intlayer";
      
      import { Locales } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          defaultLocale: Locales.ENGLISH,
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        },
      };
      
      export default config;
      
      Π§Π΅Ρ€Π΅Π· этот Ρ„Π°ΠΉΠ» ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ Π»ΠΎΠΊΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Π΅ URL-адрСса, ΠΏΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ middleware, ΠΈΠΌΠ΅Π½Π° ΠΊΡƒΠΊΠΈ, мСстополоТСниС ΠΈ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ Π²Π°ΡˆΠΈΡ… Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΠΉ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°, ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Π»ΠΎΠ³ΠΈ Intlayer Π² консоли ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠ΅ Π΄Ρ€ΡƒΠ³ΠΎΠ΅. ΠŸΠΎΠ»Π½Ρ‹ΠΉ список доступных ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² см. Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ ΠΏΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ.
    4. Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ Intlayer Π² ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ Vite

      Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΠΏΠ»Π°Π³ΠΈΠ½ intlayer Π² Π²Π°ΡˆΡƒ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ:

      vite.config.ts
      import { intlayer } from "vite-intlayer";
      import { defineConfig } from "vite";
      import { devtools } from "@tanstack/devtools-vite";
      import { tanstackStart } from "@tanstack/solid-start/plugin/vite";
      import solidPlugin from "vite-plugin-solid";
      
      export default defineConfig({
        plugins: [
          devtools(),
          tanstackStart({
            router: {
              routeFileIgnorePattern:
                ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5|md|mdx|yaml|yml)$",
            },
          }),
          solidPlugin({ ssr: true }),
          intlayer({
            proxy: {
              ignore: (req) => req.url?.startsWith("/api"),
            },
          }),
        ],
      });
      
      Плагин Vite intlayer() ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ Intlayer с Vite. Он обСспСчиваСт сборку Ρ„Π°ΠΉΠ»ΠΎΠ² Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° ΠΈ отслСТиваСт ΠΈΡ… измСнСния Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. Он опрСдСляСт ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ окруТСния Intlayer Π²Π½ΡƒΡ‚Ρ€ΠΈ прилоТСния Vite. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, ΠΎΠ½ прСдоставляСт псСвдонимы (aliases) для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ.
    5. Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠ³ΠΎ ΠΌΠ°ΠΊΠ΅Ρ‚Π°

      НастройтС ваш ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠΉ ΠΌΠ°ΠΊΠ΅Ρ‚ для ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ ΠΈΠ½Ρ‚Π΅Ρ€Π½Π°Ρ†ΠΈΠΎΠ½Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ useParams для опрСдСлСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Π»ΠΎΠΊΠ°Π»ΠΈ ΠΈ устанавливая Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Ρ‹ lang ΠΈ dir для Ρ‚Π΅Π³Π° html.

      src/routes/__root.tsx
      import {
        HeadContent,
        Scripts,
        createRootRouteWithContext,
        getRouteApi,
      } from "@tanstack/solid-router";
      import { HydrationScript } from "solid-js/web";
      import { Suspense, type ParentComponent } from "solid-js";
      import { IntlayerProvider } from "solid-intlayer";
      import { defaultLocale, getHTMLTextDir } from "intlayer";
      
      const localeRoute = getRouteApi("/{-$locale}");
      
      export const Route = createRootRouteWithContext()({
        shellComponent: RootComponent,
      });
      
      const RootComponent: ParentComponent = (props) => {
        const params = localeRoute.useParams();
        const locale = params()?.locale ?? defaultLocale;
      
        return (
          <html dir={getHTMLTextDir(locale)} lang={locale}>
            <head>
              <HydrationScript />
              <HeadContent />
            </head>
            <body>
              <IntlayerProvider locale={locale}>
                <Suspense>{props.children}</Suspense>
              </IntlayerProvider>
              <Scripts />
            </body>
          </html>
        );
      };
      
    6. Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΌΠ°ΠΊΠ΅Ρ‚Π° Π»ΠΎΠΊΠ°Π»ΠΈ

      Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΌΠ°ΠΊΠ΅Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ прСфикс Π»ΠΎΠΊΠ°Π»ΠΈ ΠΈ выполняСт Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΡŽ. Π­Ρ‚ΠΎΡ‚ ΠΌΠ°ΠΊΠ΅Ρ‚ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ допустимыС Π»ΠΎΠΊΠ°Π»ΠΈ.

      Π­Ρ‚ΠΎΡ‚ шаг являСтся Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ, Ссли Π²Π°ΠΌ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ прСфикс Π»ΠΎΠΊΠ°Π»ΠΈ Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°.
      src/routes/{-$locale}/route.tsx
      import { createFileRoute, Outlet, redirect } from "@tanstack/solid-router";
      import { validatePrefix } from "intlayer";
      
      export const Route = createFileRoute("/{-$locale}")({
        beforeLoad: ({ params }) => {
          const localeParam = params.locale;
      
          // Валидация прСфикса Π»ΠΎΠΊΠ°Π»ΠΈ
          const { isValid, localePrefix } = validatePrefix(localeParam);
      
          if (!isValid) {
            throw redirect({
              to: "/{-$locale}/404",
              params: { locale: localePrefix },
              replace: true,
            });
          }
        },
        component: Outlet,
      });
      
      Π—Π΄Π΅ΡΡŒ {-$locale} - это динамичСский ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ замСняСтся Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ локалью. Вакая нотация Π΄Π΅Π»Π°Π΅Ρ‚ сСгмСнт Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ, позволяя Π΅ΠΌΡƒ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Ρ‚Π°ΠΊΠΈΠΌΠΈ Ρ€Π΅ΠΆΠΈΠΌΠ°ΠΌΠΈ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ, ΠΊΠ°ΠΊ 'prefix-no-default' ΠΈ Ρ‚.Π΄.

      Π˜ΠΌΠ΅ΠΉΡ‚Π΅ Π² Π²ΠΈΠ΄Ρƒ, Ρ‡Ρ‚ΠΎ этот сСгмСнт ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, Ссли Π²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚Π΅ нСсколько динамичСских сСгмСнтов Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π΅ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, /{-$locale}/other-path/$anotherDynamicPath/...). Для Ρ€Π΅ΠΆΠΈΠΌΠ° 'prefix-all' Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Π΅ΡΡ‚ΡŒ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ сСгмСнт Π½Π° $locale. Для Ρ€Π΅ΠΆΠΈΠΌΠ° 'no-prefix' ΠΈΠ»ΠΈ 'search-params' Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ сСгмСнт.

    7. ДСкларация вашСго ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°

      Π‘ΠΎΠ·Π΄Π°Π²Π°ΠΉΡ‚Π΅ ΠΈ управляйтС дСкларациями ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° для хранСния ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ²:

      src/contents/page.content.ts
      import type { Dictionary } from "intlayer";
      
      import { t } from "intlayer";
      
      const appContent = {
        content: {
          links: {
            about: t({
              en: "About",
              es: "Acerca de",
              fr: "Γ€ propos",
            }),
            home: t({
              en: "Home",
              es: "Inicio",
              fr: "Accueil",
            }),
          },
          meta: {
            title: t({
              en: "Welcome to Intlayer + TanStack Router",
              es: "Bienvenido a Intlayer + TanStack Router",
              fr: "Bienvenue Γ  Intlayer + TanStack Router",
            }),
            description: t({
              en: "This is an example of using Intlayer with TanStack Router",
              es: "Este es un ejemplo de uso de Intlayer con TanStack Router",
              fr: "Ceci est un exemple d'utilisation d'Intlayer avec TanStack Router",
            }),
          },
        },
        key: "app",
      } satisfies Dictionary;
      
      export default appContent;
      
      Π’Π°ΡˆΠΈ Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ Π² любом мСстС вашСго прилоТСния, ΠΏΡ€ΠΈ условии, Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΈ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ Π² ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ contentDir (ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ./app). И ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡŽ Ρ„Π°ΠΉΠ»ΠΎΠ² Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° (ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ .content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml}).
      ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ см. Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ ΠΏΠΎ Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°.
    8. ИспользованиС локально-зависимых ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ Ρ…ΡƒΠΊΠΎΠ²

      Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ LocalizedLink для Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΠΈ с ΡƒΡ‡Π΅Ρ‚ΠΎΠΌ Π»ΠΎΠΊΠ°Π»ΠΈ:

      src/components/LocalizedLink.tsx
      import { Link, type LinkProps } from "@tanstack/solid-router";
      import { getPrefix } from "intlayer";
      import { useLocale } from "solid-intlayer";
      import type { JSX } from "solid-js";
      
      export const LOCALE_ROUTE = "{-$locale}" as const;
      
      export type RemoveLocaleParam<TVal> = TVal extends string
        ? RemoveLocaleFromString<TVal>
        : TVal;
      
      export type To = RemoveLocaleParam<LinkProps["to"]>;
      
      type CollapseDoubleSlashes<TString extends string> =
        TString extends `${infer THead}//${infer TTail}`
          ? CollapseDoubleSlashes<`${THead}/${TTail}`>
          : TString;
      
      export type LocalizedLinkProps = Omit<LinkProps, "to"> & {
        to?: To;
      } & JSX.AnchorHTMLAttributes<HTMLAnchorElement>;
      
      type RemoveAll<
        TString extends string,
        TSub extends string,
      > = TString extends `${infer THead}${TSub}${infer TTail}`
        ? RemoveAll<`${THead}${TTail}`, TSub>
        : TString;
      
      type RemoveLocaleFromString<TString extends string> = CollapseDoubleSlashes<
        RemoveAll<TString, typeof LOCALE_ROUTE>
      >;
      
      export const LocalizedLink = (props: LocalizedLinkProps) => {
        const { locale } = useLocale();
      
        return (
          <Link
            {...props}
            params={{
              locale: getPrefix(locale()).localePrefix,
              ...(typeof props.params === "object" ? props.params : {}),
            }}
            to={`/${LOCALE_ROUTE}${props.to ?? ""}` as LinkProps["to"]}
          />
        );
      };
      

      Π­Ρ‚ΠΎΡ‚ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ прСслСдуСт Π΄Π²Π΅ Ρ†Π΅Π»ΠΈ:

      • Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ Π½Π΅Π½ΡƒΠΆΠ½ΠΎΠ³ΠΎ прСфикса {-$locale} ΠΈΠ· URL.
      • Π’Π½Π΅Π΄Ρ€Π΅Π½ΠΈΠ΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° Π»ΠΎΠΊΠ°Π»ΠΈ Π² URL, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π±Ρ‹Π» Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ ΠΏΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ Π½Π° Π»ΠΎΠΊΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚.

      Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Ρ…ΡƒΠΊ useLocalizedNavigate для ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠΉ Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΠΈ:

      src/hooks/useLocalizedNavigate.tsx
      import { useNavigate } from "@tanstack/solid-router";
      import { getLocalizedUrl } from "intlayer";
      import { useLocale } from "solid-intlayer";
      
      export const useLocalizedNavigate = () => {
        const navigate = useNavigate();
        const { locale } = useLocale();
      
        const localizedNavigate = (to: string) => {
          const localizedTo = getLocalizedUrl(to, locale());
          return navigate({ to: localizedTo });
        };
      
        return localizedNavigate;
      };
      
    9. ИспользованиС Intlayer Π½Π° Π²Π°ΡˆΠΈΡ… страницах

      Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ useIntlayer ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ: это Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌΡ‹ΠΉ способ Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΈ компилятор Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ Π΅Π³ΠΎ Π² ΠΎΡ‚Ρ€ΠΈΡΠΎΠ²Ρ‹Π²Π°Π΅ΠΌΡƒΡŽ локаль. ΠžΠ±Ρ€Π°Ρ‰Π°ΠΉΡ‚Π΅ΡΡŒ ΠΊ getIntlayer / getIntlayerAsync Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Π½Π΅ Π΄Π΅Ρ€Π΅Π²Π° Solid: Π² head ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΎΠ², Π·Π°Π³Ρ€ΡƒΠ·Ρ‡ΠΈΠΊΠ°Ρ… ΠΈ сСрвСрных функциях.

      ΠŸΠΎΠ»ΡƒΡ‡Π°ΠΉΡ‚Π΅ доступ ΠΊ вашим словарям ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° Π²ΠΎ всСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ:

      Локализованная домашняя страница

      src/routes/{-$locale}/index.tsx
      import { createFileRoute } from "@tanstack/solid-router";
      import { useIntlayer } from "solid-intlayer";
      import { LocalizedLink } from "@/components/LocalizedLink";
      
      export const Route = createFileRoute("/{-$locale}/")({
        component: RouteComponent,
      });
      
      function RouteComponent() {
        const content = useIntlayer("index-page");
      
        return (
          <main>
            <h1>{content.heroTitle}</h1>
            <p>{content.heroDesc}</p>
            <div>
              <LocalizedLink to="/">{content.navHome}</LocalizedLink>
              <LocalizedLink to="/about">{content.navAbout}</LocalizedLink>
            </div>
          </main>
        );
      }
      
      tsx
      <img src={content.image.src.value} alt={content.image.value} />
      <img src={content.image.src.toString()} alt={content.image.toString()} />
      <img src={String(content.image.src)} alt={String(content.image)} />
      

      Π’ Solid useIntlayer Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π΅Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, content). Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ ΠΊ Π΅Π³ΠΎ свойствам Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ.

      Π§Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ·Π½Π°Ρ‚ΡŒ большС ΠΎ Ρ…ΡƒΠΊΠ΅ useIntlayer, ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ΡΡŒ ΠΊ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ.

    10. Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π»ΠΎΠΊΠ°Π»ΠΈ

      Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌ ΠΌΠ΅Π½ΡΡ‚ΡŒ языки:

      src/components/LocaleSwitcher.tsx
      import { useLocation } from "@tanstack/solid-router";
      import { getLocaleName, getPathWithoutLocale, getPrefix } from "intlayer";
      import { For } from "solid-js";
      import { useIntlayer, useLocale } from "solid-intlayer";
      import { LocalizedLink, type To } from "./LocalizedLink";
      
      export const LocaleSwitcher = () => {
        const content = useIntlayer("locale-switcher");
        const location = useLocation();
      
        const { availableLocales, locale, setLocale } = useLocale();
      
        const pathWithoutLocale = () => getPathWithoutLocale(location().pathname);
      
        return (
          <div class="flex flex-row gap-2">
            <For each={availableLocales}>
              {(localeEl) => (
                <LocalizedLink
                  aria-current={localeEl === locale() ? "page" : undefined}
                  onClick={() => setLocale(localeEl)}
                  params={{ locale: getPrefix(localeEl).localePrefix }}
                  to={pathWithoutLocale() as To}
                >
                  {getLocaleName(localeEl)}
                </LocalizedLink>
              )}
            </For>
          </div>
        );
      };
      
      export default LocaleSwitcher;
      

      Π’ Solid locale ΠΈΠ· useLocale - это аксСссор сигнала. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ locale() (со скобками) для Ρ€Π΅Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ чтСния Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ значСния.

      Π§Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ·Π½Π°Ρ‚ΡŒ большС ΠΎ Ρ…ΡƒΠΊΠ΅ useLocale, ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ΡΡŒ ΠΊ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ.

    11. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ HTML-Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°ΠΌΠΈ

      Как ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½Π° шагС 5, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°ΠΌΠΈ lang ΠΈ dir Ρ‚Π΅Π³Π° html, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ useParams Π² вашСм ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π΅. Π­Ρ‚ΠΎ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΡƒΡŽ установку Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠ² ΠΊΠ°ΠΊ Π½Π° сСрвСрС, Ρ‚Π°ΠΊ ΠΈ Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π΅.

      src/routes/__root.tsx
      const RootComponent: ParentComponent = (props) => {
        const params = localeRoute.useParams();
        const locale = params()?.locale ?? defaultLocale;
      
        return (
          <html dir={getHTMLTextDir(locale)} lang={locale}>
            {/* ... */}
          </html>
        );
      };
      
    12. Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ³ΠΎ ПО

      Π’Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ intlayerProxy для добавлСния сСрвСрной ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ Π² вашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅. Π­Ρ‚ΠΎΡ‚ ΠΏΠ»Π°Π³ΠΈΠ½ Π±ΡƒΠ΄Π΅Ρ‚ автоматичСски ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ локаль Π½Π° основС URL ΠΈ ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ локаль Π² ΠΊΡƒΠΊΠΈ. Если локаль Π½Π΅ ΡƒΠΊΠ°Π·Π°Π½Π°, ΠΏΠ»Π°Π³ΠΈΠ½ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΡΡ‰ΡƒΡŽ локаль Π½Π° основС языковых ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚Π΅Π½ΠΈΠΉ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. Если локаль Π½Π΅ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π°, ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° локаль ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ.

      ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ для использования intlayerProxy Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ production Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ пСрСнСсти ΠΏΠ°ΠΊΠ΅Ρ‚ vite-intlayer ΠΈΠ· devDependencies Π² dependencies.
      Начиная с Intlayer v9, intlayerProxy() встроСн нСпосрСдствСнно Π² ΠΏΠ»Π°Π³ΠΈΠ½ intlayer() ΠΈ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Ρ‡Π΅Ρ€Π΅Π· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ routing.enableProxy (true ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ). РСгистрация Π΅Π³ΠΎ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½ΠΈΠΆΠ΅, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Π°: ΠΎΠ½Π° сохранСна для ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΉ совмСстимости ΠΈ для ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ порядок ΠΏΠ»Π°Π³ΠΈΠ½ΠΎΠ². УстановитС routing.enableProxy: false, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ эту Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ. Π‘ΠΌ. примСчания ΠΊ выпуску v9.
      vite.config.ts
      import { tanstackStart } from "@tanstack/solid-start/plugin/vite";
      import solid from "vite-plugin-solid";
      import { nitro } from "nitro/vite";
      import { defineConfig } from "vite";
      import { intlayer } from "vite-intlayer";
      
      export default defineConfig({
        plugins: [
          nitro(),
          intlayer({
            proxy: {
              ignore: (req) => req.url?.startsWith("/api"),
            },
          }),
          tanstackStart({
            router: {
              routeFileIgnorePattern:
                ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5|md|mdx|yaml|yml)$",
            },
          }),
          solid(),
        ],
      });
      
    13. Π˜Π½Ρ‚Π΅Ρ€Π½Π°Ρ†ΠΈΠΎΠ½Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡ Π²Π°ΡˆΠΈΡ… ΠΌΠ΅Ρ‚Π°Π΄Π°Π½Π½Ρ‹Ρ…

      getIntlayer Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ΡΡ синхронно ΠΏΠΎ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½Ρ‘Π½Π½ΠΎΠΌΡƒ ΡΠ»ΠΎΠ²Π°Ρ€ΡŽ, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Ρ‚ΠΎΠΌΡƒ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ содСрТит всС ΠΎΠ±ΡŠΡΠ²Π»Π΅Π½Π½Ρ‹Π΅ Π»ΠΎΠΊΠ°Π»ΠΈ. head остаётся синхронным, Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ оТидаСтся, Π½ΠΎ вСсь многоязычный ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² Ρ‡Π°Π½ΠΊ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°, отправляСмый Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€.

      src/routes/{-$locale}/index.tsx
      import { createFileRoute } from "@tanstack/solid-router";
      import {
        defaultLocale,
        getIntlayer,
        getLocalizedUrl,
        localeMap,
      } from "intlayer";
      
      export const Route = createFileRoute("/{-$locale}/")({
        component: RouteComponent,
        head: ({ params }) => {
          const { locale = defaultLocale } = params;
          const path = "/"; // The path for this route
      
          const metaContent = getIntlayer("app", locale);
      
          return {
            links: [
              // Canonical link: Points to the current localized page
              { rel: "canonical", href: getLocalizedUrl(path, locale) },
      
              // Hreflang: Tell Google about all localized versions
              ...localeMap(({ locale: mapLocale }) => ({
                rel: "alternate",
                hrefLang: mapLocale,
                href: getLocalizedUrl(path, mapLocale),
              })),
      
              // x-default: For users in unmatched languages
              // Define the default fallback locale (usually your primary language)
              {
                rel: "alternate",
                hrefLang: "x-default",
                href: getLocalizedUrl(path, defaultLocale),
              },
            ],
            meta: [
              { title: metaContent.title },
              { name: "description", content: metaContent.meta.description },
            ],
          };
        },
      });
      

      ΠŸΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ для Π½Π΅Π±ΠΎΠ»ΡŒΡˆΠΈΡ… словарСй ΠΌΠ΅Ρ‚Π°Π΄Π°Π½Π½Ρ‹Ρ…, ΠΌΠ°Π»ΠΎΠ³ΠΎ числа Π»ΠΎΠΊΠ°Π»Π΅ΠΉ ΠΈΠ»ΠΈ Π½Π° этапС прототипирования.

      getIntlayerAsync (доступСн начиная с v9.4) Π²Π΅Π΄Ρ‘Ρ‚ сСбя ΠΊΠ°ΠΊ getIntlayer, Π½ΠΎ ΠΏΠ»Π°Π³ΠΈΠ½ сборки направляСт Π΅Π³ΠΎ Π½Π° ΠΏΠ΅Ρ€-Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ‡Π°Π½ΠΊ Π² .intlayer/dynamic_dictionaries/ вмСсто ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½Ρ‘Π½Π½ΠΎΠ³ΠΎ словаря. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ страница ΠΎΡ‚Π΄Π°Ρ‘Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Ρƒ локаль, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΡ‚. Π’Π°ΠΊ ΠΊΠ°ΠΊ этот Ρ‡Π°Π½ΠΊ загруТаСтся ΠΏΠΎ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΡŽ, head становится async:

      src/routes/{-$locale}/index.tsx
      import { createFileRoute } from "@tanstack/solid-router";
      import {
        defaultLocale,
        getIntlayerAsync,
        getLocalizedUrl,
        localeMap,
      } from "intlayer";
      
      export const Route = createFileRoute("/{-$locale}/")({
        component: RouteComponent,
        head: async ({ params }) => {
          const { locale = defaultLocale } = params;
          const path = "/"; // The path for this route
      
          const metaContent = await getIntlayerAsync("app", locale);
      
          return {
            links: [
              // Canonical link: Points to the current localized page
              { rel: "canonical", href: getLocalizedUrl(path, locale) },
      
              // Hreflang: Tell Google about all localized versions
              ...localeMap(({ locale: mapLocale }) => ({
                rel: "alternate",
                hrefLang: mapLocale,
                href: getLocalizedUrl(path, mapLocale),
              })),
      
              // x-default: For users in unmatched languages
              // Define the default fallback locale (usually your primary language)
              {
                rel: "alternate",
                hrefLang: "x-default",
                href: getLocalizedUrl(path, defaultLocale),
              },
            ],
            meta: [
              { title: metaContent.title },
              { name: "description", content: metaContent.meta.description },
            ],
          };
        },
      });
      
      Если head Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ нСсколько словарСй, Ρ€Π°Π·Ρ€Π΅ΡˆΠ°ΠΉΡ‚Π΅ ΠΈΡ… Ρ‡Π΅Ρ€Π΅Π· Promise.all: ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ getIntlayerAsync ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ строкой выстраиваСт запросы Π² Ρ†Π΅ΠΏΠΎΡ‡ΠΊΡƒ вмСсто ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ выполнСния.

      ΠšΠΎΠΌΠΏΡ€ΠΎΠΌΠΈΡΡ: динамичСский ΠΈΠΌΠΏΠΎΡ€Ρ‚ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ΡΡ Π²ΠΎ врСмя выполнСния head, Π½Π° критичСском ΠΏΡƒΡ‚ΠΈ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π° Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°. На Β«Ρ…ΠΎΠ»ΠΎΠ΄Π½ΠΎΠΌΒ» ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π΅ это Π·Π°Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ head Π½Π° нСсколько миллисСкунд ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΡƒΡ…ΡƒΠ΄ΡˆΠΈΡ‚ΡŒ LCP.

      Π Π°Π·Ρ€Π΅ΡˆΠΈΡ‚Π΅ ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ Π² loader ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° ΠΈ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°ΠΉΡ‚Π΅ Π΅Π³ΠΎ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΈΠ· loaderData Π² head. Π—Π°Π³Ρ€ΡƒΠ·Ρ‡ΠΈΠΊΠΈ ΡΠΎΠ²ΠΏΠ°Π²ΡˆΠΈΡ… ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΎΠ² Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ, Π° staleTime: Infinity сообщаСт TanStack Router, Ρ‡Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ устарСваСт, поэтому ΠΏΠ΅Ρ€-Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ‡Π°Π½ΠΊ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ΡΡ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·, Π° Π·Π°Ρ‚Π΅ΠΌ отдаётся ΠΈΠ· кэша Ρ€ΠΎΡƒΡ‚Π΅Ρ€Π°, оставляя head синхронным.

      src/routes/{-$locale}/index.tsx
      import { createFileRoute } from "@tanstack/solid-router";
      import {
        defaultLocale,
        getIntlayerAsync,
        getLocalizedUrl,
        localeMap,
      } from "intlayer";
      
      export const Route = createFileRoute("/{-$locale}/")({
        component: RouteComponent,
        // Resolved in parallel with the other matched routes, off the head critical path
        loader: async ({ params }) => {
          const { locale = defaultLocale } = params;
      
          return { metaContent: await getIntlayerAsync("app", locale) };
        },
        // The dictionary never changes for a given locale: resolve the chunk once
        staleTime: Infinity,
        head: ({ params, loaderData }) => {
          const { locale = defaultLocale } = params;
          const path = "/"; // The path for this route
      
          return {
            links: [
              // Canonical link: Points to the current localized page
              { rel: "canonical", href: getLocalizedUrl(path, locale) },
      
              // Hreflang: Tell Google about all localized versions
              ...localeMap(({ locale: mapLocale }) => ({
                rel: "alternate",
                hrefLang: mapLocale,
                href: getLocalizedUrl(path, mapLocale),
              })),
      
              // x-default: For users in unmatched languages
              // Define the default fallback locale (usually your primary language)
              {
                rel: "alternate",
                hrefLang: "x-default",
                href: getLocalizedUrl(path, defaultLocale),
              },
            ],
            meta: [
              { title: loaderData?.metaContent.title },
              {
                name: "description",
                content: loaderData?.metaContent.meta.description,
              },
            ],
          };
        },
      });
      
      head ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π²Ρ‹Π·Π²Π°Π½ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Π·Π°Π³Ρ€ΡƒΠ·Ρ‡ΠΈΠΊ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ, поэтому loaderData Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½ ΠΊΠ°ΠΊ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ undefined. Π‘ΠΎΡ…Ρ€Π°Π½ΠΈΡ‚Π΅ ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΡƒΡŽ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΡƒ Π»ΠΈΠ±ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΠΉΡ‚Π΅ запасной Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ.

      Π’Ρ‹ сохраняСтС ΠΏΠ΅Ρ€-Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ‡Π°Π½ΠΊ, Π½Π΅ оплачивая Π΅Π³ΠΎ ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ Π½Π° критичСском ΠΏΡƒΡ‚ΠΈ head. ΠŸΠ»Π°Ρ‚ΠΎΠΉ становится DX: ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ приходится явно ΠΏΡ€ΠΎΠΊΠΈΠ΄Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΠ· Π·Π°Π³Ρ€ΡƒΠ·Ρ‡ΠΈΠΊΠ° Π² head Ρ‡Π΅Ρ€Π΅Π· loaderData.

      КакоС Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ?

      БтатичСскоС Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Π”ΠΈΠ½Π°ΠΌΠΈΡ‡Π΅ΡΠΊΠΎΠ΅ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ΠšΡΡˆΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ динамичСскоС Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅
      APIgetIntlayergetIntlayerAsync (v9.4+)getIntlayerAsync Π² loader (v9.4+)
      Π‘ΠΈΠ³Π½Π°Ρ‚ΡƒΡ€Π° headсинхроннаяasyncсинхронная, Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ loaderData
      ΠžΡ‚ΠΏΡ€Π°Π²Π»ΡΠ΅ΠΌΡ‹Π΅ локаливсС ΠΎΠ±ΡŠΡΠ²Π»Π΅Π½Π½Ρ‹Π΅ Π»ΠΎΠΊΠ°Π»ΠΈΡ‚ΠΎΠ»ΡŒΠΊΠΎ Π·Π°ΠΏΡ€ΠΎΡˆΠ΅Π½Π½Π°Ρ Π»ΠΎΠΊΠ°Π»ΡŒΡ‚ΠΎΠ»ΡŒΠΊΠΎ Π·Π°ΠΏΡ€ΠΎΡˆΠ΅Π½Π½Π°Ρ локаль
      ΠšΠ»ΠΈΠ΅Π½Ρ‚ΡΠΊΠΈΠ΅ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Ρ‹Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Ρ‚ΡŒ нСчСговыполняСтся Π·Π°Π½ΠΎΠ²ΠΎ ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ совпадСнииотдаётся ΠΈΠ· кэша Ρ€ΠΎΡƒΡ‚Π΅Ρ€Π°
      DXсамый простойодин awaitΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ прокидываСтся Ρ‡Π΅Ρ€Π΅Π· loaderData
    14. ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Π»ΠΎΠΊΠ°Π»ΠΈ Π² Π²Π°ΡˆΠΈΡ… сСрвСрных дСйствиях

      Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π²Ρ‹ Π·Π°Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Π»ΠΎΠΊΠ°Π»ΠΈ Π²Π½ΡƒΡ‚Ρ€ΠΈ Π²Π°ΡˆΠΈΡ… сСрвСрных дСйствий (server actions) ΠΈΠ»ΠΈ ΠΊΠΎΠ½Π΅Ρ‡Π½Ρ‹Ρ… Ρ‚ΠΎΡ‡Π΅ΠΊ API. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΠΊΠ° getLocale ΠΈΠ· intlayer.

      Π’ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ использования сСрвСрных Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ TanStack Start:

      src/routes/{-$locale}/index.tsx
      import { createServerFn } from "@tanstack/solid-start";
      import {
        getRequestHeader,
        getRequestHeaders,
      } from "@tanstack/solid-start/server";
      import { getCookie, getIntlayer, getLocale } from "intlayer";
      
      export const getLocaleServer = createServerFn().handler(async () => {
        const locale = await getLocale({
          // ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΊΡƒΠΊΠΈ ΠΈΠ· запроса (ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ: 'INTLAYER_LOCALE')
          getCookie: (name) => {
            const cookieString = getRequestHeader("cookie");
      
            return getCookie(name, cookieString);
          },
          // ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° ΠΈΠ· запроса (ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ: 'x-intlayer-locale')
          // Запасной Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ с использованиСм согласования Accept-Language
          getHeader: (name) => getRequestHeader(name),
        });
      
        // ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ getIntlayer()
        const content = getIntlayer("app", locale);
      
        return { locale, content };
      });
      
    15. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ страницами 404

      Когда ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ посСщаСт Π½Π΅ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ страницу, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°Π·ΠΈΡ‚ΡŒ ΠΊΠ°ΡΡ‚ΠΎΠΌΠ½ΡƒΡŽ страницу 404. ΠŸΡ€Π΅Ρ„ΠΈΠΊΡ Π»ΠΎΠΊΠ°Π»ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π²Π»ΠΈΡΡ‚ΡŒ Π½Π° Ρ‚ΠΎ, ΠΊΠ°ΠΊ срабатываСт страница "Π—Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΡ‹ΠΉ рСсурс Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½".

      ПониманиС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ 404 Π² TanStack Router с прСфиксами Π»ΠΎΠΊΠ°Π»Π΅ΠΉ

      Π’ TanStack Router ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° страниц 404 с Π»ΠΎΠΊΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹ΠΌΠΈ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°ΠΌΠΈ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ ΠΌΠ½ΠΎΠ³ΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π°:

      1. Π’Ρ‹Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ 404: Π‘ΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ для отобраТСния интСрфСйса 404.
      2. Валидация Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°: ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅Ρ‚ прСфиксы Π»ΠΎΠΊΠ°Π»Π΅ΠΉ ΠΈ пСрСнаправляСт Π½Π΅Π²Π°Π»ΠΈΠ΄Π½Ρ‹Π΅ Π½Π° 404.
      3. Π£Π½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ (Catch-all): ΠŸΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π»ΡŽΠ±Ρ‹Π΅ Π½Π΅ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΡƒΡ‚ΠΈ Π²Π½ΡƒΡ‚Ρ€ΠΈ сСгмСнта Π»ΠΎΠΊΠ°Π»ΠΈ.
      src/routes/{-$locale}/404.tsx
      import { createFileRoute } from "@tanstack/solid-router";
      
      // Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ /[locale]/404
      // Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΊΠ°ΠΊ прямой ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ ΠΈ импортируСтся ΠΊΠ°ΠΊ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π² Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Ρ„Π°ΠΉΠ»Ρ‹
      export const Route = createFileRoute("/{-$locale}/404")({
        component: NotFoundComponent,
      });
      
      // ЭкспортируСтся ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² notFoundComponent ΠΈ catch-all ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°Ρ…
      export function NotFoundComponent() {
        return (
          <div>
            <h1>404</h1>
          </div>
        );
      }
      
      src/routes/{-$locale}/route.tsx
      import { createFileRoute, Outlet, redirect } from "@tanstack/solid-router";
      import { validatePrefix } from "intlayer";
      import { NotFoundComponent } from "./404";
      
      export const Route = createFileRoute("/{-$locale}")({
        // beforeLoad выполняСтся ΠΏΠ΅Ρ€Π΅Π΄ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³ΠΎΠΌ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π° (Π½Π° сСрвСрС ΠΈ Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π΅)
        // Π­Ρ‚ΠΎ идСальноС мСсто для Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ прСфикса Π»ΠΎΠΊΠ°Π»ΠΈ
        beforeLoad: ({ params }) => {
          const localeParam = params.locale;
      
          // validatePrefix провСряСт, Π²Π°Π»ΠΈΠ΄Π½Π° Π»ΠΈ локаль согласно Π²Π°ΡˆΠ΅ΠΌΡƒ ΠΊΠΎΠ½Ρ„ΠΈΠ³Ρƒ intlayer
          const { isValid, localePrefix } = validatePrefix(localeParam);
      
          if (!isValid) {
            // НСвалидный прСфикс Π»ΠΎΠΊΠ°Π»ΠΈ - ΠΏΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° страницу 404 с Π²Π°Π»ΠΈΠ΄Π½Ρ‹ΠΌ прСфиксом
            throw redirect({
              to: "/{-$locale}/404",
              params: { locale: localePrefix },
            });
          }
        },
        component: Outlet,
        // notFoundComponent вызываСтся, ΠΊΠΎΠ³Π΄Π° Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ Π½Π΅ сущСствуСт
        // Π½Π°ΠΏΡ€., /en/non-existent-page Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ это Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΌΠ°ΠΊΠ΅Ρ‚Π° /en
        notFoundComponent: NotFoundComponent,
      });
      
      src/routes/{-$locale}/$.tsx
      import { createFileRoute } from "@tanstack/solid-router";
      
      import { NotFoundComponent } from "./404";
      
      // ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚ $ (splat/catch-all) совпадаСт с Π»ΡŽΠ±Ρ‹ΠΌ ΠΏΡƒΡ‚Π΅ΠΌ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½Π΅ подошСл ΠΏΠΎΠ΄ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Ρ‹
      // Π½Π°ΠΏΡ€., /en/some/deeply/nested/invalid/path
      // Π­Ρ‚ΠΎ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ Π’Π‘Π• Π½Π΅ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΡƒΡ‚ΠΈ Π²Π½ΡƒΡ‚Ρ€ΠΈ Π»ΠΎΠΊΠ°Π»ΠΈ ΠΏΠΎΠΊΠ°ΠΆΡƒΡ‚ страницу 404
      // Π‘Π΅Π· этого Π³Π»ΡƒΠ±ΠΎΠΊΠΈΠ΅ Π½Π΅ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΡƒΡ‚ΠΈ ΠΌΠΎΠ³Π»ΠΈ Π±Ρ‹ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΏΡƒΡΡ‚ΡƒΡŽ страницу ΠΈΠ»ΠΈ ΠΎΡˆΠΈΠ±ΠΊΡƒ
      export const Route = createFileRoute("/{-$locale}/$")({
        component: NotFoundComponent,
      });
      
    16. Π˜Π·Π²Π»Π΅Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° ΠΈΠ· Π²Π°ΡˆΠΈΡ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²

      ΠΠ΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ

      Если Ρƒ вас Π΅ΡΡ‚ΡŒ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π°Ρ кодовая Π±Π°Π·Π°, трансформация тысяч Ρ„Π°ΠΉΠ»ΠΎΠ² ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Π½ΡΡ‚ΡŒ ΠΌΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ.

      Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π»Π΅Π³Ρ‡ΠΈΡ‚ΡŒ этот процСсс, Intlayer ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ компилятор / экстрактор для трансформации Π²Π°ΡˆΠΈΡ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ извлСчСния ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°.

      Для настройки Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Ρ€Π°Π·Π΄Π΅Π» compiler Π² ваш Ρ„Π°ΠΉΠ» intlayer.config.ts:

      intlayer.config.ts
      import { type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        // ... ΠžΡΡ‚Π°Π»ΡŒΠ½Π°Ρ Ρ‡Π°ΡΡ‚ΡŒ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π°
        compiler: {
          /**
           * Π£ΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Π΄ΠΎΠ»ΠΆΠ΅Π½ Π»ΠΈ компилятор Π±Ρ‹Ρ‚ΡŒ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½.
           */
          enabled: true,
      
          /**
           * ΠžΠΏΡ€Π΅Π΄Π΅Π»ΡΠ΅Ρ‚ ΠΏΡƒΡ‚ΡŒ ΠΊ Π²Ρ‹Ρ…ΠΎΠ΄Π½Ρ‹ΠΌ Ρ„Π°ΠΉΠ»Π°ΠΌ
           */
          output: ({ fileName, extension }) => `./${fileName}${extension}`,
      
          /**
           * Π£ΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π»ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒΡΡ послС трансформации.
           *
           * - Если `true`, компилятор ΠΏΠ΅Ρ€Π΅Π·Π°ΠΏΠΈΡˆΠ΅Ρ‚ Ρ„Π°ΠΉΠ» ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Π½Π° дискС. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, трансформация станСт постоянной, ΠΈ компилятор пропустит Π΅Π΅ ΠΏΡ€ΠΈ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ запускС. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, компилятор ΠΌΠΎΠΆΠ΅Ρ‚ Ρ‚Ρ€Π°Π½ΡΡ„ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π° Π·Π°Ρ‚Π΅ΠΌ Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ.
           *
           * - Если `false`, компилятор Π±ΡƒΠ΄Π΅Ρ‚ Π²Π½Π΅Π΄Ρ€ΡΡ‚ΡŒ Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ `useIntlayer()` Π² ΠΊΠΎΠ΄ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Π²Ρ‹Ρ…ΠΎΠ΄Π½Ρ‹Ρ… Ρ„Π°ΠΉΠ»Π°Ρ… сборки, оставляя ΠΎΡΠ½ΠΎΠ²Π½ΡƒΡŽ Π±Π°Π·Ρƒ ΠΊΠΎΠ΄Π° Π½Π΅Ρ‚Ρ€ΠΎΠ½ΡƒΡ‚ΠΎΠΉ. Врансформация Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² памяти.
           */
          saveComponents: false,
      
          /**
           * ΠŸΡ€Π΅Ρ„ΠΈΠΊΡ ΠΊΠ»ΡŽΡ‡Π΅ΠΉ словаря
           */
          dictionaryKeyPrefix: "",
        },
      };
      
      export default config;
      

      ЗапуститС экстрактор для трансформации Π²Π°ΡˆΠΈΡ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ извлСчСния ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°:

      bash
      npx intlayer extract
      
      Since v9, the intlayerCompiler is included in the intlayer plugin. So you don't need to add it manually.

      ΠžΠ±Π½ΠΎΠ²ΠΈΡ‚Π΅ ваш vite.config.ts, Π²ΠΊΠ»ΡŽΡ‡ΠΈΠ² ΠΏΠ»Π°Π³ΠΈΠ½ intlayerCompiler:

      vite.config.ts
      import { intlayer, intlayerCompiler } from "vite-intlayer";
      import { defineConfig } from "vite";
      import { devtools } from "@tanstack/devtools-vite";
      import { tanstackStart } from "@tanstack/solid-start/plugin/vite";
      import solidPlugin from "vite-plugin-solid";
      
      export default defineConfig({
        plugins: [
          devtools(),
          tanstackStart({
            router: {
              routeFileIgnorePattern:
                ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5|md|mdx|yaml|yml)$",
            },
          }),
          solidPlugin({ ssr: true }),
          intlayer(),
          intlayerCompiler(), // Adds the compiler plugin
        ],
      });
      

      Π‘ΠΎΠ±Π΅Ρ€ΠΈΡ‚Π΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ ваши ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈ ΠΈΠ·Π²Π»Π΅Ρ‡ΡŒ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚

      bash
      npm run build # Или npm run dev
      
    17. ГСнСрация ΠΊΠ°Ρ€Ρ‚Ρ‹ сайта (Sitemap)

      ΠΠ΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ

      Intlayer поставляСтся со встроСнным Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ ΠΊΠ°Ρ€Ρ‚Ρ‹ сайта, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Π²Π°ΠΌ Π»Π΅Π³ΠΊΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΊΠ°Ρ€Ρ‚Ρƒ сайта для вашСго прилоТСния. Он ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ Π»ΠΎΠΊΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Π΅ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Ρ‹ ΠΈ добавляСт Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΌΠ΅Ρ‚Π°Π΄Π°Π½Π½Ρ‹Π΅ для поисковых систСм.

      БоздаваСмая Intlayer ΠΊΠ°Ρ€Ρ‚Π° сайта ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ пространство ΠΈΠΌΠ΅Π½ xhtml:link (Hreflang XML Extensions). Π’ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ стандартных Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠ² ΠΊΠ°Ρ€Ρ‚ сайта, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ просто ΠΏΠ΅Ρ€Π΅Ρ‡ΠΈΡΠ»ΡΡŽΡ‚ прямыС URL-адрСса, Intlayer автоматичСски создаСт Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ двусторонниС связи ΠΌΠ΅ΠΆΠ΄Ρƒ всСми языковыми вСрсиями страницы (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, /about, /about?lang=fr ΠΈ /about?lang=es). Π­Ρ‚ΠΎ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ поисковыС систСмы Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ ΠΈΠ½Π΄Π΅ΠΊΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ Π½ΡƒΠΆΠ½ΡƒΡŽ ΡΠ·Ρ‹ΠΊΠΎΠ²ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ Π°ΡƒΠ΄ΠΈΡ‚ΠΎΡ€ΠΈΠΈ.

      Π§Ρ‚ΠΎΠ±Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π³ΠΎ, Π²Π°ΠΌ сначала Π½ΡƒΠΆΠ½ΠΎ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ваш Ρ„Π°ΠΉΠ» vite.config.ts, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³ (pre-rendering) для Π²Π°ΡˆΠΈΡ… Π»ΠΎΠΊΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΎΠ² ΠΈ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ ΠΊΠ°Ρ€Ρ‚Ρ‹ сайта ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π² TanStack Start.

      vite.config.ts
      import { localeMap, localeFlatMap } from "intlayer";
      // ... Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΈΠΌΠΏΠΎΡ€Ρ‚Ρ‹
      
      export const pathList = ["", "/about", "/404"];
      
      const localizedPages = localeFlatMap(({ urlPrefix }) =>
        pathList.map((path) => ({
          path: `${urlPrefix}${path}`,
          prerender: {
            enabled: true,
          },
        }))
      );
      
      export default defineConfig({
        plugins: [
          // ... Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΏΠ»Π°Π³ΠΈΠ½Ρ‹
          tanstackStart({
            // ... Π΄Ρ€ΡƒΠ³ΠΈΠ΅ настройки
            sitemap: {
              enabled: false,
            },
            prerender: {
              enabled: true,
              crawlLinks: false,
              concurrency: 10,
            },
            pages: localizedPages,
          }),
        ],
      });
      

      Π—Π°Ρ‚Π΅ΠΌ создайтС ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ src/routes/sitemap[.]xml.ts, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ generateSitemap:

      src/routes/sitemap[.]xml.ts
      import { createFileRoute } from "@tanstack/solid-router";
      import { generateSitemap } from "intlayer";
      
      const SITE_URL = "http://localhost:3000";
      
      export const Route = createFileRoute("/sitemap.xml")({
        server: {
          handlers: {
            GET: async () => {
              const sitemap = generateSitemap(
                [
                  { path: "/", changefreq: "daily", priority: 1.0 },
                  { path: "/about", changefreq: "monthly", priority: 0.8 },
                ],
                { siteUrl: "https://example.com" }
              );
      
              return new Response(sitemap, {
                headers: { "Content-Type": "application/xml" },
              });
            },
          },
        },
      });
      
    18. Настройка TypeScript

      Intlayer ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ (module augmentation), Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π·Π°Π΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ прСимущСства TypeScript ΠΈ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π²Π°ΡˆΡƒ ΠΊΠΎΠ΄ΠΎΠ²ΡƒΡŽ Π±Π°Π·Ρƒ Π±ΠΎΠ»Π΅Π΅ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠΉ.

      Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ ваша конфигурация TypeScript Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π°Π²Ρ‚ΠΎΠ³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Π΅ Ρ‚ΠΈΠΏΡ‹:

      tsconfig.json
      {
        // ... ваши ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ настройки
        include: [
          // ... ваши ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΡƒΡ‚ΠΈ
          ".intlayer/**/*.ts", // Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ автоматичСски Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ²
        ],
      }
      

    ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ Git

    РСкомСндуСтся ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ»Ρ‹, Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Π΅ Intlayer. Π­Ρ‚ΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ ΠΈΡ… ΠΊΠΎΠΌΠΌΠΈΡ‚Π° Π² ваш Git-Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ.

    Для этого Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ инструкции Π² ваш Ρ„Π°ΠΉΠ» .gitignore:

    .gitignore
    # Π˜Π³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ»Ρ‹, Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Π΅ Intlayer
    .intlayer
    

    Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ VS Code

    Для ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΡ процСсса Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ с Intlayer Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠ΅ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ Intlayer для VS Code.

    Π­Ρ‚ΠΎ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ прСдоставляСт:

    • АвтодополнСниС для ΠΊΠ»ΡŽΡ‡Π΅ΠΉ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π°.
    • ΠžΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ошибок Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ для ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ².
    • ВстроСнная ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ просмотр ΠΏΠ΅Ρ€Π΅Π²Π΅Π΄Π΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°.
    • БыстрыС дСйствия для Π»Π΅Π³ΠΊΠΎΠ³ΠΎ создания ΠΈ обновлСния ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ².

    Для получСния Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅, ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ΡΡŒ ΠΊ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ Intlayer VS Code.

    Π§Ρ‚ΠΎ дальшС?

    Для дальнСйшСго развития Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Π½Π΅Π΄Ρ€ΠΈΡ‚ΡŒ Π²ΠΈΠ·ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ ΠΈΠ»ΠΈ вынСсти ваш ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ Π²ΠΎ внСшнюю систСму, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ CMS.

    Бсылки Π½Π° Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ

    Часто Π·Π°Π΄Π°Π²Π°Π΅ΠΌΡ‹Π΅ вопросы

    TanStack Start Π½Π΅ поставляСтся со слоСм i18n, Π° Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Ρ‹ Π² экосистСмС Solid скудны:

    • @solid-primitives/i18n: плоский ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²Ρ‹ собираСтС ΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚Π΅ ΠΊ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ‚ΠΎΡ€Ρƒ сами.
    • i18next с ΠΎΠ±Ρ‘Ρ€Ρ‚ΠΊΠΎΠΉ для Solid: Π·Ρ€Π΅Π»Ρ‹Π΅ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΈ, Π½ΠΎ Π±Π΅Π· ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ с ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ‚ΠΎΡ€ΠΎΠΌ TanStack, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ head ΠΈΠ»ΠΈ этапом ΠΏΡ€Π΅-Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°.
    • Intlayer: ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚, ΠΎΠ±ΡŠΡΠ²Π»Π΅Π½Π½Ρ‹ΠΉ рядом с ΠΊΠ°ΠΆΠ΄Ρ‹ΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠΌ ΠΈ скомпилированный Π²ΠΎ врСмя сборки, с ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ с ΡƒΡ‡Ρ‘Ρ‚ΠΎΠΌ Π»ΠΎΠΊΠ°Π»ΠΈ, Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ ΠΊΠ°Ρ€Ρ‚Ρ‹ сайта, ИИ-ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠΌ, Π²ΠΈΠ·ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΌ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ΠΎΠΌ ΠΈ CMS.

    Π‘ΠΌ. ΠΏΠΎΡ‡Π΅ΠΌΡƒ Intlayer ΠΈ Π±Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊ i18n для TanStack Start.

    Π“ΠΎΡ€Π°Π·Π΄ΠΎ мСньшС, Ρ‡Π΅ΠΌ ΠΏΡ€ΠΈ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π΅ Π½Π° основС пространств ΠΈΠΌΡ‘Π½, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ страница Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½Π΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚. Π Π°Π·ΠΌΠ΅Ρ‚ΠΊΠ°, отрСндСрСнная Π½Π° сСрвСрС, Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ свой ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ Π½Π° сСрвСрС, ΠΈ компилятор Π²ΠΎ врСмя сборки замСняСт Π²Ρ‹Π·ΠΎΠ²Ρ‹ useIntlayer Ρ‚ΠΎΡ‡Π½Ρ‹ΠΌΠΈ записями словаря, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚, поэтому Π½Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ ΠΊΠ»ΡŽΡ‡ΠΈ ΠΈ Π½Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ языки ΠΎΡ‚Π±Ρ€Π°ΡΡ‹Π²Π°ΡŽΡ‚ΡΡ, Π° динамичСскиС словари Ρ€Π°Π·Π΄Π΅Π»ΡΡŽΡ‚ ΠΎΡΡ‚Π°Π»ΡŒΠ½ΠΎΠ΅ ΠΏΠΎ локалям. По ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΌΠΈ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π°ΠΌΠΈ Intlayer сокращаСт Ρ€Π°Π·ΠΌΠ΅Ρ€ Π±Π°Π½Π΄Π»Π° ΠΈ страницы Π΄ΠΎ 50%. Π‘ΠΌ. ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΡŽ Π±Π°Π½Π΄Π»Π° ΠΈ Π±Π΅Π½Ρ‡ΠΌΠ°Ρ€ΠΊ.

    Π’ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ стСпСни. Π‘Π»Π΅Π΄ΡƒΠΉΡ‚Π΅ руководству ΠΏΠΎ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ с i18next, Ρ‡Ρ‚ΠΎΠ±Ρ‹ пСрСнСсти ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚. Π’Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΌΠΈΠ³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ постСпСнно: ΠΏΠ»Π°Π³ΠΈΠ½ синхронизации JSON сохраняСт ваши ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΈ JSON ΠΊΠ°ΠΊ источник истины ΠΈ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΠ· Π½ΠΈΡ… словари Intlayer, поэтому ΠΎΠ±Π° слоя ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ синхронизированными, ΠΏΠΎΠΊΠ° Π²Ρ‹ пСрСноситС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ.

    Π”Π°. Плагин синхронизации JSON сохраняСт ваши Ρ„Π°ΠΉΠ»Ρ‹ /messages/{locale}/{namespace}.json ΠΊΠ°ΠΊ источник истины ΠΈ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΠ· Π½ΠΈΡ… словари Intlayer, Π² ΠΎΠ±ΠΎΠΈΡ… направлСниях. Плагин синхронизации PO Π΄Π΅Π»Π°Π΅Ρ‚ Ρ‚ΠΎ ΠΆΠ΅ самоС для ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΠ² gettext, Π° Ρ„Π°ΠΉΠ»Ρ‹ ΠΏΠΎ Π»ΠΎΠΊΠ°Π»ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ ΠΏΠΎ языкам вмСсто Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²ΠΊΠΈ Π»ΠΎΠΊΠ°Π»Π΅ΠΉ Π² ΠΎΠ΄Π½ΠΎΠΌ Ρ„Π°ΠΉΠ»Π΅.

    НСт. ЗапуститС npx intlayer extract, ΠΈ Intlayer ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Π΅Ρ‚ ваши ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, ΠΈΠ·Π²Π»Π΅Ρ‡Ρ‘Ρ‚ строки, Π²ΠΈΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ, ΠΈ Π·Π°ΠΏΠΈΡˆΠ΅Ρ‚ Ρ„Π°ΠΉΠ» .content рядом с ΠΊΠ°ΠΆΠ΄Ρ‹ΠΌ ΠΈΠ· Π½ΠΈΡ…, Ρ‚Π°ΠΊ Ρ‡Ρ‚ΠΎ Π²Ρ‹ просматриваСтС diff вмСсто копирования строк Π² ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΉ. Π¨Π°Π³ 15 этого руководства ΠΏΡ€ΠΎΠ²ΠΎΠ΄ΠΈΡ‚ вас Ρ‡Π΅Ρ€Π΅Π· это.

    Для ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π° ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ Intlayer Π΄Π΅Π»Π°Π΅Ρ‚ Ρ‚ΠΎ ΠΆΠ΅ самоС Π²ΠΎ врСмя сборки: ΠΎΠ½ сканируСт исходный ΠΊΠΎΠ΄ JSX, TSX, Vue ΠΈ Svelte ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ, Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ словари ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΈΡ… ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·Π°Ρ†ΠΈΡŽ Ρ‡Π΅Ρ€Π΅Π· Π³ΠΎΡ€ΡΡ‡ΡƒΡŽ Π·Π°ΠΌΠ΅Π½Ρƒ ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ, поэтому Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ ΠΊΠ»ΡŽΡ‡ΠΈ Π²ΠΎΠΎΠ±Ρ‰Π΅ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ.

    Π‘Ρ‚ΠΎΠΈΡ‚ Π·Π½Π°Ρ‚ΡŒ ΠΎ Π΄Π²ΡƒΡ… ограничСниях, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ Π²ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ компилятор. Он Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‡Π΅Ρ€Π΅Π· статичСский Π°Π½Π°Π»ΠΈΠ·, поэтому строки, ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²ΠΎ врСмя выполнСния, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ ΠΊΠΎΠ΄Ρ‹ ошибок API ΠΈΠ»ΠΈ поля CMS, ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ нСдоступными. И Π΅ΠΌΡƒ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡ‚Π»ΠΈΡ‡Π°Ρ‚ΡŒ тСкст, Π²ΠΈΠ΄ΠΈΠΌΡ‹ΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ, ΠΎΡ‚ Π»ΠΎΠ³ΠΈΠΊΠΈ прилоТСния Π²Ρ€ΠΎΠ΄Π΅ className="active" ΠΈΠ»ΠΈ ΠΊΠΎΠ΄Π° статуса, Ρ‡Ρ‚ΠΎ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Π°Π½Π½ΠΎΡ‚Π°Ρ†ΠΈΠΉ Π² большой ΠΊΠΎΠ΄ΠΎΠ²ΠΎΠΉ Π±Π°Π·Π΅. Команда extract ΠΈΠ·Π±Π΅Π³Π°Π΅Ρ‚ ΠΎΠ±ΠΎΠΈΡ… ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ, оставляя вас Π² процСссС.

    ΠŸΡΡ‚ΡŒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², всС ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Π΅:

    • Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ для VS Code: ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ ΠΎΡ‚ ΠΊΠ»ΡŽΡ‡Π° useIntlayer ΠΊ Ρ„Π°ΠΉΠ»Ρƒ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π΅Π³ΠΎ ΠΎΠ±ΡŠΡΠ²Π»ΡΠ΅Ρ‚, ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° ΠΈΠ· ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΈ запуск build, fill, test, push ΠΈ pull ΠΈΠ· ΠΏΠ°Π»ΠΈΡ‚Ρ€Ρ‹ ΠΊΠΎΠΌΠ°Π½Π΄ ΠΈΠ»ΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ Π²ΠΊΠ»Π°Π΄ΠΊΠΈ Intlayer.
    • LSP-сСрвСр: Ρ‚Π° ΠΆΠ΅ ΠΎΡΠ²Π΅Π΄ΠΎΠΌΠ»Ρ‘Π½Π½ΠΎΡΡ‚ΡŒ Π² любом Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ Π½Π° LSP, с ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΎΠΌ ΠΊ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΡŽ, поиском всСх ссылок, прСдпросмотром ΠΏΠ΅Ρ€Π΅Π²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ значСния ΠΏΡ€ΠΈ Π½Π°Π²Π΅Π΄Π΅Π½ΠΈΠΈ, Π°Π²Ρ‚ΠΎΠ΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠ»ΡŽΡ‡Π΅ΠΉ ΠΈ ΠΏΠΎΠ»Π΅ΠΉ ΠΈ ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ΠΌ, ΠΊΠΎΠ³Π΄Π° ΠΊΠ»ΡŽΡ‡ Π½ΠΈΠ³Π΄Π΅ Π½Π΅ объявлСн. Он Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ Π²Ρ‹Π·ΠΎΠ²Ρ‹ i18next, react-i18next, next-intl ΠΈ use-intl, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΏΡ€ΠΈ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ.
    • MCP-сСрвСр: прСдоставляСт Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ ΠΈ CLI Intlayer для Cursor, VS Code, Claude Desktop, Claude Code ΠΈ ChatGPT, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ассистСнт ΠΎΡ‚Π²Π΅Ρ‡Π°Π» ΠΏΠΎ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ, Π° Π½Π΅ Π³Π°Π΄Π°Π», ΠΈ ΠΌΠΎΠ³ сам Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Π²Ρ€ΠΎΠ΄Π΅ intlayer fill.
    • Навыки Π°Π³Π΅Π½Ρ‚ΠΎΠ²: сфокусированныС Π½Π°Π²Ρ‹ΠΊΠΈ, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ intlayer-config, intlayer-cli ΠΈ intlayer-content, плюс ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ Π½Π° Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠ±ΡƒΡ‡Π°ΡŽΡ‚ Π°Π³Π΅Π½Ρ‚Π° вашСй настройкС ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΈ Ρ‚ΠΈΠΏΠ°ΠΌ ΡƒΠ·Π»ΠΎΠ² ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°.
    • Плагин ESLint: no-raw-text ΠΏΠΎΠΌΠ΅Ρ‡Π°Π΅Ρ‚ Тёстко Π·Π°ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ строки, с Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ ΠΏΡ€Π°Π²ΠΈΠ»Π°ΠΌΠΈ для статичСских ΠΊΠ»ΡŽΡ‡Π΅ΠΉ словаря ΠΈ Π½Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠ³ΠΎ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°.