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

    АвтоматичСская гСнСрация ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ² Π² CI/CD ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π΅

    Intlayer позволяСт автоматичСски Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ для Π²Π°ΡˆΠΈΡ… Ρ„Π°ΠΉΠ»ΠΎΠ² Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°. БущСствуСт нСсколько способов Π΄ΠΎΡΡ‚ΠΈΡ‡ΡŒ этого Π² зависимости ΠΎΡ‚ вашСго Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ процСсса.

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

    ИспользованиС CMS

    Π‘ Intlayer Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ процСсс, ΠΏΡ€ΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ локально ΠΎΠ±ΡŠΡΠ²Π»ΡΠ΅Ρ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄Π½Π° локаль, Π° всС ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ΡΡ ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎ Ρ‡Π΅Ρ€Π΅Π· CMS. Π­Ρ‚ΠΎ позволяСт ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ ΠΎΡ‚Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ ΠΈ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ ΠΎΡ‚ ΠΊΠΎΠ΄ΠΎΠ²ΠΎΠΉ Π±Π°Π·Ρ‹, обСспСчивая Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ Π³ΠΈΠ±ΠΊΠΎΡΡ‚ΡŒ для Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΎΡ€ΠΎΠ² ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° ΠΈ позволяя Π³ΠΎΡ€ΡΡ‡ΡƒΡŽ ΠΏΠ΅Ρ€Π΅Π·Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° (Π½Π΅Ρ‚ нСобходимости ΠΏΠ΅Ρ€Π΅ΡΠΎΠ±ΠΈΡ€Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ для примСнСния ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ).

    ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";
    
    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.SPANISH, Locales.FRENCH],
        requiredLocales: [Locales.ENGLISH], // ΠΠ΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Π»ΠΎΠΊΠ°Π»ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒΡΡ ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎ
        defaultLocale: Locales.ENGLISH,
      },
      editor: {
        dictionaryPriorityStrategy: "distant_first", // Π£Π΄Π°Π»Ρ‘Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚
    
        applicationURL: process.env.APPLICATION_URL, // URL прилоТСния, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ CMS
    
        clientId: process.env.INTLAYER_CLIENT_ID, // Π£Ρ‡Π΅Ρ‚Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ CMS
        clientSecret: process.env.INTLAYER_CLIENT_SECRET,
      },
      ai: {
        applicationContext: "This is a test application", // ΠŸΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ согласованноС созданиС ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ²
      },
    };
    
    export default config;
    

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

    ИспользованиС Husky

    Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΡŽ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ² Π² ваш Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ Git-Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ процСсс с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Husky.

    ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";
    
    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.SPANISH, Locales.FRENCH],
        requiredLocales: [Locales.ENGLISH], // ΠΠ΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Π»ΠΎΠΊΠ°Π»ΠΈ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ ΡƒΠ΄Π°Π»Ρ‘Π½Π½ΠΎ
        defaultLocale: Locales.ENGLISH,
      },
      editor: {
        clientId: process.env.INTLAYER_CLIENT_ID,
        clientSecret: process.env.INTLAYER_CLIENT_SECRET,
      },
      ai: {
        provider: "openai",
        apiKey: process.env.OPENAI_API_KEY, // Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ свой собствСнный API-ΠΊΠ»ΡŽΡ‡
    
        applicationContext: "This is a test application", // ΠŸΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ согласованноС созданиС ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ²
      },
    };
    
    export default config;
    
    .husky/pre-push
    npx intlayer build                          # Π§Ρ‚ΠΎΠ±Ρ‹ словари Π±Ρ‹Π»ΠΈ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΌΠΈ
    npx intlayer fill --unpushed --mode fill    # ЗаполняСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚, Π½Π΅ обновляСт ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ
    
    Для получСния Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ… Intlayer CLI ΠΈ ΠΈΡ… использовании ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ΡΡŒ ΠΊ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ CLI.
    Если Ρƒ вас нСсколько ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΡ… ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ экзСмпляры intlayer, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ --base-dir ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:
    .husky/pre-push
    # ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ 1
    npx intlayer build --base-dir ./app1
    npx intlayer fill --base-dir ./app1 --unpushed --mode fill
    
    # ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ 2
    npx intlayer build --base-dir ./app2
    npx intlayer fill --base-dir ./app2 --unpushed --mode fill
    

    ИспользованиС GitHub Actions

    Intlayer прСдоставляСт ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ CLI для автоматичСского заполнСния ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ содСрТимого словаря. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² ваш CI/CD процСсс с использованиСм GitHub Actions.

    .github/workflows/intlayer-translate.yml
    name: Intlayer АвтозаполнСниС
    # Условия запуска этого workflow
    on:
      pull_request:
        branches:
          - "main"
    
    permissions:
      contents: write
      pull-requests: write
    
    concurrency:
      group: "autofill-${{ github.ref }}"
      cancel-in-progress: true
    
    jobs:
      autofill:
        runs-on: ubuntu-latest
        env:
          # OpenAI
          AI_MODEL: openai
          AI_PROVIDER: gpt-5-mini
          AI_API_KEY: ${{ secrets.AI_API_KEY }}
    
        steps:
          # Π¨Π°Π³ 1: ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ послСдний ΠΊΠΎΠ΄ ΠΈΠ· рСпозитория
          - name: ⬇️ ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° рСпозитория
            uses: actions/checkout@v4
            with:
              persist-credentials: true # Π‘ΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ ΡƒΡ‡Π΅Ρ‚Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ для создания PR
              fetch-depth: 0 # ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΠΎΠ»Π½ΡƒΡŽ ΠΈΡΡ‚ΠΎΡ€ΠΈΡŽ git для Π°Π½Π°Π»ΠΈΠ·Π° ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ
    
          # Π¨Π°Π³ 2: ΠΠ°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ Node.js
          - name: 🟒 ΠΠ°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ Node.js
            uses: actions/setup-node@v4
            with:
              node-version: 20 # Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Node.js 20 LTS для ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½ΠΎΡΡ‚ΠΈ
    
          # Π¨Π°Π³ 3: Π£ΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ зависимости ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°
          - name: πŸ“¦ Π£ΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ зависимости
            run: npm install
    
          # Π¨Π°Π³ 4: Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Intlayer CLI для управлСния ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π°ΠΌΠΈ
          - name: πŸ“¦ Π£ΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Intlayer
            run: npm install -g intlayer-cli
    
          # Π¨Π°Π³ 5: Π‘ΠΎΠ±Ρ€Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Intlayer для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ² ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π°
          - name: βš™οΈ Π‘ΠΎΠ±Ρ€Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Intlayer
            run: npx intlayer build
    
          # Π¨Π°Π³ 6: Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ИИ для автоматичСского заполнСния ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ²
          - name: πŸ€– АвтоматичСскоС Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ²
            run: npx intlayer fill --git-diff --mode fill --provider $AI_PROVIDER --model $AI_MODEL --api-key $AI_API_KEY
    
          # Π¨Π°Π³ 7: ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ ΠΈ Π·Π°Ρ„ΠΈΠΊΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ…
          - name: οΏ½ ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ измСнСния
            id: check-changes
            run: |
              if [ -n "$(git status --porcelain)" ]; then
                echo "has-changes=true" >> $GITHUB_OUTPUT
              else
                echo "has-changes=false" >> $GITHUB_OUTPUT
              fi
    
          # Π¨Π°Π³ 8: Π—Π°Ρ„ΠΈΠΊΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ измСнСния, Ссли ΠΎΠ½ΠΈ Π΅ΡΡ‚ΡŒ
          - name: πŸ“€ Π—Π°Ρ„ΠΈΠΊΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ измСнСния
            if: steps.check-changes.outputs.has-changes == 'true'
            run: |
              git config --local user.email "action@github.com"
              git config --local user.name "GitHub Action"
              git add .
              git commit -m "chore: автоматичСскоС Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ² [skip ci]"
              git push origin HEAD:${{ github.head_ref }}
    

    Π§Ρ‚ΠΎΠ±Ρ‹ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ окруТСния, ΠΏΠ΅Ρ€Π΅ΠΉΠ΄ΠΈΡ‚Π΅ Π² GitHub β†’ Settings β†’ Secrets and variables β†’ Actions ΠΈ Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ сСкрСт .

    Аналогично Husky, Π² случаС монорСпозитория Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ --base-dir для ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ прилоТСния.
    По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ --git-diff Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΡƒΠ΅Ρ‚ словари, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ содСрТат измСнСния ΠΎΡ‚ Π±Π°Π·Ρ‹ (ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ origin/main) Π΄ΠΎ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Π²Π΅Ρ‚ΠΊΠΈ (ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ: HEAD).
    Для получСния Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ… Intlayer CLI ΠΈ ΠΈΡ… использовании ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ΡΡŒ ΠΊ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ CLI.