Author:
    Creation:2025-03-01Last update:2025-09-20

    рдЖрдкрдХреА рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдкрд░реАрдХреНрд╖рдг

    рдпрд╣ рдорд╛рд░реНрдЧрджрд░реНрд╢рд┐рдХрд╛ рджрд┐рдЦрд╛рддреА рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдЕрдкрдиреЗ рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдХреА рдкреВрд░реНрдгрддрд╛ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░реЗрдВ, рд╢рд┐рдкрд┐рдВрдЧ рд╕реЗ рдкрд╣рд▓реЗ рдЧрд╛рдпрдм рдЕрдиреБрд╡рд╛рдж рдкрдХрдбрд╝реЗрдВ, рдФрд░ рдЕрдкрдиреЗ рдРрдк рдореЗрдВ рд╕реНрдерд╛рдиреАрдпрдХреГрдд UI рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВред

    рдЖрдк рдХреНрдпрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

    • рдЧрд╛рдпрдм рдЕрдиреБрд╡рд╛рдж: рдпрджрд┐ рдХрд┐рд╕реА рднреА рд╢рдмреНрджрдХреЛрд╢ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕реНрдерд╛рдиреАрдп рднрд╛рд╖рд╛рдПрдБ рдЧрд╛рдпрдм рд╣реИрдВ рддреЛ CI рдЕрд╕рдлрд▓ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
    • рд╕реНрдерд╛рдиреАрдпрдХреГрдд UI рд░реЗрдВрдбрд░рд┐рдВрдЧ: рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдерд╛рдиреАрдп рдкреНрд░рджрд╛рддрд╛ рдХреЗ рд╕рд╛рде рдШрдЯрдХреЛрдВ рдХреЛ рд░реЗрдВрдбрд░ рдХрд░реЗрдВ рдФрд░ рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд╡рд╛рд▓реЗ рдЯреЗрдХреНрд╕реНрдЯ/рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдкрд░ рд╕рддреНрдпрд╛рдкрди рдХрд░реЗрдВред
    • рдмрд┐рд▓реНрдб-рдЯрд╛рдЗрдо рдСрдбрд┐рдЯ: CLI рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдПрдХ рддреНрд╡рд░рд┐рдд рдСрдбрд┐рдЯ рдЪрд▓рд╛рдПрдВред

    рддреНрд╡рд░рд┐рдд рдкреНрд░рд╛рд░рдВрдн: CLI рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдСрдбрд┐рдЯ

    рдЕрдкрдиреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд░реВрдЯ рд╕реЗ рдСрдбрд┐рдЯ рдЪрд▓рд╛рдПрдВ:

    bash
    npx intlayer content test
    

    рдЙрдкрдпреЛрдЧреА рдлреНрд▓реИрдЧреНрд╕:

    • --env-file [path]: рдХрд┐рд╕реА рдлрд╝рд╛рдЗрд▓ рд╕реЗ рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рд▓реЛрдб рдХрд░реЗрдВред
    • -e, --env [name]: рдПрдХ рдкрд░реНрдпрд╛рд╡рд░рдг рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдЪреБрдиреЗрдВред
    • --base-dir [path]: рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП рдРрдк рдмреЗрд╕ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рд╕реЗрдЯ рдХрд░реЗрдВред
    • --verbose: рд╡рд┐рд╕реНрддреГрдд рд▓реЙрдЧ рджрд┐рдЦрд╛рдПрдВред
    • --prefix [label]: рд▓реЙрдЧ рд▓рд╛рдЗрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрд╕рд░реНрдЧ рдЬреЛрдбрд╝реЗрдВред

    рдзреНрдпрд╛рди рджреЗрдВ: CLI рдПрдХ рд╡рд┐рд╕реНрддреГрдд рд░рд┐рдкреЛрд░реНрдЯ рдкреНрд░рд┐рдВрдЯ рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рд╡рд┐рдлрд▓рддрд╛рдУрдВ рдкрд░ рдЧреИрд░-рд╢реВрдиреНрдп рдХреЛрдб рдХреЗ рд╕рд╛рде рдмрд╛рд╣рд░ рдирд╣реАрдВ рдирд┐рдХрд▓рддрд╛ред CI рдЧреЗрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП, рдПрдХ рдпреВрдирд┐рдЯ рдЯреЗрд╕реНрдЯ (рдиреАрдЪреЗ) рдЬреЛрдбрд╝реЗрдВ рдЬреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗ рдХрд┐ рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХ рд╕реНрдерд╛рдиреАрдп рднрд╛рд╖рд╛ рдЧрд╛рдпрдм рди рд╣реЛред

    рдкреНрд░реЛрдЧреНрд░рд╛рдореЗрдЯрд┐рдХ рдкрд░реАрдХреНрд╖рдг (Vitest/Jest)

    рдЕрдкрдиреЗ рдЖрд╡рд╢реНрдпрдХ рд╕реНрдерд╛рдиреАрдп рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЧрд╛рдпрдм рдЕрдиреБрд╡рд╛рдж рди рд╣реЛрдиреЗ рдХрд╛ рд╕рддреНрдпрд╛рдкрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Intlayer CLI API рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

    /* @vitest-environment node */
    import { listMissingTranslations } from "intlayer/cli";
    import { describe, expect, it } from "vitest";
    
    describe("рдЕрдиреБрд╡рд╛рдж", () => {
      it("рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХ рд╕реНрдерд╛рдиреАрдп рднрд╛рд╖рд╛ рдЧрд╛рдпрдм рдирд╣реАрдВ рд╣реИ", () => {
        const result = listMissingTranslations();
    
        if (result.missingRequiredLocales.length > 0) {
          // рдЬрдм рдкрд░реАрдХреНрд╖рдг рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдпрд╛ CI рдореЗрдВ рд╡рд┐рдлрд▓ рд╣реЛрддрд╛ рд╣реИ рддреЛ рд╕рд╣рд╛рдпрдХ
          console.log(result.missingTranslations);
        }
    
        expect(result.missingRequiredLocales).toHaveLength(0);
      });
    });
    

    Jest рд╕рдорддреБрд▓реНрдп:

    import { listMissingTranslations } from "intlayer/cli";
    
    test("рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХ рд╕реНрдерд╛рдиреАрдп рднрд╛рд╖рд╛ рдЧрд╛рдпрдм рдирд╣реАрдВ рд╣реИ", () => {
      const result = listMissingTranslations();
    
      if (result.missingRequiredLocales.length > 0) {
        console.log(result.missingTranslations);
      }
    
      expect(result.missingRequiredLocales).toHaveLength(0);
    });
    

    рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

    • Intlayer рдЖрдкрдХреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди (locales, requiredLocales) рдФрд░ рдШреЛрд╖рд┐рдд рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдХреЛ рдкрдврд╝рддрд╛ рд╣реИ, рдлрд┐рд░ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИ:
      • missingTranslations: рдкреНрд░рддрд┐-рдХреБрдВрдЬреА, рдХреМрди-рдХреМрди рд╕реА рд╕реНрдерд╛рдиреАрдп рднрд╛рд╖рд╛рдПрдБ рдЧрд╛рдпрдм рд╣реИрдВ рдФрд░ рдХрд┐рд╕ рдлрд╝рд╛рдЗрд▓ рд╕реЗред
      • missingLocales: рд╕рднреА рдЧрд╛рдпрдм рд╕реНрдерд╛рдиреАрдп рднрд╛рд╖рд╛рдУрдВ рдХрд╛ рд╕рдВрдШред
      • missingRequiredLocales: requiredLocales рддрдХ рд╕реАрдорд┐рдд рдЙрдкрд╕рдореВрд╣ (рдпрд╛ рдпрджрд┐ requiredLocales рд╕реЗрдЯ рдирд╣реАрдВ рд╣реИ рддреЛ рд╕рднреА рд╕реНрдерд╛рдиреАрдп рднрд╛рд╖рд╛рдПрдБ)ред

    рд╕реНрдерд╛рдиреАрдпрдХреГрдд UI рдХрд╛ рдкрд░реАрдХреНрд╖рдг (React / Next.js)

    Intlayer рдкреНрд░рджрд╛рддрд╛ рдХреЗ рдЕрдВрддрд░реНрдЧрдд рдШрдЯрдХреЛрдВ рдХреЛ рд░реЗрдВрдбрд░ рдХрд░реЗрдВ рдФрд░ рджреГрд╢реНрдп рд╕рд╛рдордЧреНрд░реА рдкрд░ рд╕рддреНрдпрд╛рдкрди рдХрд░реЗрдВред

    React рдЙрджрд╛рд╣рд░рдг (Testing Library):

    tsx
    import { IntlayerProvider } from "react-intlayer/client";
    import { render, screen } from "@testing-library/react";
    import { MyComponent } from "./MyComponent";
    
    test("рдЕрдВрдЧреНрд░реЗрдЬрд╝реА рдореЗрдВ рд╕реНрдерд╛рдиреАрдпрдХреГрдд рд╢реАрд░реНрд╖рдХ рд░реЗрдВрдбрд░ рдХрд░рддрд╛ рд╣реИ", () => {
      render(
        <IntlayerProvider locale="en-US">
          <MyComponent />
        </IntlayerProvider>
      );
    
      expect(screen.getByText("рдЕрдкреЗрдХреНрд╖рд┐рдд рдЕрдВрдЧреНрд░реЗрдЬрд╝реА рд╢реАрд░реНрд╖рдХ")).toBeInTheDocument();
    });
    

    Next.js (App Router) рдЙрджрд╛рд╣рд░рдг: рдлреНрд░реЗрдорд╡рд░реНрдХ рд░реИрдкрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:

    tsx
    import { IntlayerClientProvider } from "next-intlayer/client";
    import { render, screen } from "@testing-library/react";
    import { MyPage } from "./MyPage";
    
    test("рдлреНрд░реЗрдВрдЪ рдореЗрдВ рд╕реНрдерд╛рдиреАрдпрдХреГрдд рд╢реАрд░реНрд╖рдХ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ", () => {
      render(
        <IntlayerClientProvider locale="fr-FR">
          <MyPage />
        </IntlayerClientProvider>
      );
      expect(
        screen.getByRole("heading", { name: "Titre attendu" })
      ).toBeInTheDocument();
    });
    

    рдЯрд┐рдкреНрд╕:

    • рдЬрдм рдЖрдкрдХреЛ рдЧреБрдгреЛрдВ рдХреЗ рд▓рд┐рдП рдХрдЪреНрдЪреЗ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдорд╛рдиреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ (рдЬреИрд╕реЗ, aria-label), рддреЛ React рдореЗрдВ useIntlayer рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЧрдП .value рдлрд╝реАрд▓реНрдб рддрдХ рдкрд╣реБрдБрдЪреЗрдВред
    • рдЖрд╕рд╛рди рдпреВрдирд┐рдЯ рдкрд░реАрдХреНрд╖рдг рдФрд░ рд╕рдлрд╛рдИ рдХреЗ рд▓рд┐рдП рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдХреЛ рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд╛рде рд╣реА рд░рдЦреЗрдВред

    рд╕рддрдд рдПрдХреАрдХрд░рдг

    рдПрдХ рдРрд╕рд╛ рдкрд░реАрдХреНрд╖рдг рдЬреЛрдбрд╝реЗрдВ рдЬреЛ рдЖрд╡рд╢реНрдпрдХ рдЕрдиреБрд╡рд╛рджреЛрдВ рдХреЗ рдЧрд╛рдпрдм рд╣реЛрдиреЗ рдкрд░ рдмрд┐рд▓реНрдб рдХреЛ рд╡рд┐рдлрд▓ рдХрд░ рджреЗред

    package.json:

    json
    {
      "scripts": {
        "test:i18n": "vitest run -c"
      }
    }
    

    GitHub Actions рдЙрджрд╛рд╣рд░рдг:

    yaml
    name: CI
    on: [push, pull_request]
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-node@v4
            with:
              node-version: 20
          - run: npm ci
          - run: npm run test:i18n
    

    рд╡реИрдХрд▓реНрдкрд┐рдХ: рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдПрдХ рдорд╛рдирд╡-рдкрдардиреАрдп рд╕рд╛рд░рд╛рдВрд╢ рдХреЗ рд▓рд┐рдП CLI рдСрдбрд┐рдЯ рдЪрд▓рд╛рдПрдВ:

    bash
    npx intlayer content test --verbose
    

    рд╕рдорд╕реНрдпрд╛ рдирд┐рд╡рд╛рд░рдг

    • рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЖрдкрдХрд╛ Intlayer рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди locales рдФрд░ (рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ) requiredLocales рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред
    • рдпрджрд┐ рдЖрдкрдХрд╛ рдРрдк рдбрд╛рдпрдирд╛рдорд┐рдХ рдпрд╛ рд░рд┐рдореЛрдЯ рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдРрд╕реЗ рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдПрдВ рдЬрд╣рд╛рдВ рд╢рдмреНрджрдХреЛрд╢ рдЙрдкрд▓рдмреНрдз рд╣реЛрдВред
    • рдорд┐рд╢реНрд░рд┐рдд рдореЛрдиреЛрд░рд┐рдкреЛрдЬрд╝ рдХреЗ рд▓рд┐рдП, CLI рдХреЛ рд╕рд╣реА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд░реВрдЯ рдкрд░ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП --base-dir рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред