Author:
    Creation:2025-08-23Last update:2026-05-31

    next-i18next рдмрдирд╛рдо next-intl рдмрдирд╛рдо intlayer | Next.js рдЕрдВрддрд░рд░рд╛рд╖реНрдЯреНрд░реАрдпрдХрд░рдг (i18n)

    рдпрд╣ рдЧрд╛рдЗрдб Next.js рдХреЗ рд▓рд┐рдП рддреАрди рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ i18n рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИ: next-intl, next-i18next, рдФрд░ Intlayerред рд╣рдо Next.js 13+ App Router (рдЬрд┐рд╕рдореЗрдВ React Server Components рд╢рд╛рдорд┐рд▓ рд╣реИрдВ) рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рддреЗ рд╣реИрдВ:

    1. рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдФрд░ рд╕рд╛рдордЧреНрд░реА рд╕рдВрдЧрдарди
    2. TypeScript рдФрд░ рд╕реБрд░рдХреНрд╖рд╛
    3. рдЕрдиреБрд╡рд╛рдж рдХреА рдХрдореА рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛
    4. рд░реВрдЯрд┐рдВрдЧ рдФрд░ рдорд┐рдбрд▓рд╡реЗрдпрд░
    5. рдкреНрд░рджрд░реНрд╢рди рдФрд░ рд▓реЛрдбрд┐рдВрдЧ рд╡реНрдпрд╡рд╣рд╛рд░
    6. рдбреЗрд╡рд▓рдкрд░ рдЕрдиреБрднрд╡ (DX), рдЯреВрд▓рд┐рдВрдЧ рдФрд░ рд░рдЦрд░рдЦрд╛рд╡
    7. SEO рдФрд░ рдмрдбрд╝реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреА рд╕реНрдХреЗрд▓реЗрдмрд┐рд▓рд┐рдЯреА
    рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ: рдпреЗ рд╕рднреА рддреАрдиреЛрдВ Next.js рдРрдк рдХреЛ рд╕реНрдерд╛рдиреАрдпрдХреГрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрдВрдкреЛрдиреЗрдВрдЯ-рд╕реНрдХреЛрдкреНрдб рдХрдВрдЯреЗрдВрдЯ, рдХрдареЛрд░ TypeScript рдкреНрд░рдХрд╛рд░, рдмрд┐рд▓реНрдб-рдЯрд╛рдЗрдо рдорд┐рд╕рд┐рдВрдЧ-рдХреА рдЬрд╛рдВрдЪ, рдЯреНрд░реА-рд╢реЗрдХреНрдб рдбрд┐рдХреНрд╢рдирд░реАрдЬрд╝, рдФрд░ рдлрд░реНрд╕реНрдЯ-рдХреНрд▓рд╛рд╕ App Router + SEO рд╣реЗрд▓реНрдкрд░реНрд╕, рддреЛ Intlayer рд╕рдмрд╕реЗ рдкреВрд░реНрдг, рдЖрдзреБрдирд┐рдХ рд╡рд┐рдХрд▓реНрдк рд╣реИред

    рдЙрдЪреНрдЪ рд╕реНрддрд░реАрдп рд╕реНрдерд┐рддрд┐

    • next-intl - рд╣рд▓реНрдХрд╛, рд╕рд░рд▓ рд╕рдВрджреЗрд╢ рд╕реНрд╡рд░реВрдкрдг рдЬреЛ рдордЬрдмреВрдд Next.js рд╕рдорд░реНрдерди рдХреЗ рд╕рд╛рде рдЖрддрд╛ рд╣реИред рдХреЗрдВрджреНрд░реАрдХреГрдд рдХреИрдЯрд▓реЙрдЧ рдЖрдо рд╣реИрдВ; DX рд╕рд░рд▓ рд╣реИ, рд▓реЗрдХрд┐рди рд╕реБрд░рдХреНрд╖рд╛ рдФрд░ рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рд░рдЦрд░рдЦрд╛рд╡ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдЖрдкрдХреА рдЬрд┐рдореНрдореЗрджрд╛рд░реА рдмрдиреА рд░рд╣рддреА рд╣реИред
    • next-i18next - Next.js рдХреЗ рд▓рд┐рдП i18next рдХрд╛ рд░реВрдкред рдкрд░рд┐рдкрдХреНрд╡ рдЗрдХреЛрд╕рд┐рд╕реНрдЯрдо рдФрд░ рдкреНрд▓рдЧрдЗрдиреНрд╕ (рдЬреИрд╕реЗ ICU) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдлреАрдЪрд░реНрд╕, рд▓реЗрдХрд┐рди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд▓рдВрдмрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЬреИрд╕реЗ-рдЬреИрд╕реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдврд╝рддреЗ рд╣реИрдВ рдХреИрдЯрд▓реЙрдЧ рдХреЗрдВрджреНрд░реАрдХреГрдд рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред
    • Intlayer - Next.js рдХреЗ рд▓рд┐рдП рдХрдВрдкреЛрдиреЗрдВрдЯ-рдХреЗрдВрджреНрд░рд┐рдд рдХрдВрдЯреЗрдВрдЯ рдореЙрдбрд▓, рдХрдареЛрд░ TS рдЯрд╛рдЗрдкрд┐рдВрдЧ, рдмрд┐рд▓реНрдб-рдЯрд╛рдЗрдо рдЪреЗрдХреНрд╕, рдЯреНрд░реА-рд╢реЗрдХрд┐рдВрдЧ, рдЗрди-рдмрд┐рд▓реНрдЯ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдФрд░ SEO рд╣реЗрд▓реНрдкрд░реНрд╕, рд╡реИрдХрд▓реНрдкрд┐рдХ рд╡рд┐рдЬрд╝реБрдЕрд▓ рдПрдбрд┐рдЯрд░/CMS, рдФрд░ AI-рд╕рд╣рд╛рдпрддрд╛ рдкреНрд░рд╛рдкреНрдд рдЕрдиреБрд╡рд╛рджред

    рд╕рд╛рдЗрдб-рдмрд╛рдп-рд╕рд╛рдЗрдб рдлреАрдЪрд░ рддреБрд▓рдирд╛ (Next.js рдХреЗрдВрджреНрд░рд┐рдд)

    рдлреАрдЪрд░next-intlayer (Intlayer)next-intlnext-i18next
    рдХрдВрдкреЛрдиреЗрдВрдЯ рдХреЗ рдкрд╛рд╕ рдЕрдиреБрд╡рд╛рджтЬЕ рд╣рд╛рдБ, рдкреНрд░рддреНрдпреЗрдХ рдХрдВрдкреЛрдиреЗрдВрдЯ рдХреЗ рд╕рд╛рде рд╕рд╛рдордЧреНрд░реА рд╕рд╣-рд╕реНрдерд┐рддтЭМ рдирд╣реАрдВтЭМ рдирд╣реАрдВ
    рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдПрдХреАрдХрд░рдгтЬЕ рдЙрдиреНрдирдд, рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рд╕рдЦреНрдд рдкреНрд░рдХрд╛рд░тЬЕ рдЕрдЪреНрдЫрд╛тЪая╕П рдмреБрдирд┐рдпрд╛рджреА
    рдЕрдиреБрд╡рд╛рдж рдХреА рдХрдореА рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдирд╛тЬЕ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рддреНрд░реБрдЯрд┐ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдФрд░ рдмрд┐рд▓реНрдб-рдЯрд╛рдЗрдо рддреНрд░реБрдЯрд┐/рдЪреЗрддрд╛рд╡рдиреАтЪая╕П рд░рдирдЯрд╛рдЗрдо рдлреЙрд▓рдмреИрдХтЪая╕П рд░рдирдЯрд╛рдЗрдо рдлреЙрд▓рдмреИрдХ
    рд╕рдореГрджреНрдз рд╕рд╛рдордЧреНрд░реА (JSX/рдорд╛рд░реНрдХрдбрд╛рдЙрди/рдХрдВрдкреЛрдиреЗрдВрдЯреНрд╕)тЬЕ рд╕реАрдзреЗ рд╕рдорд░реНрдердитЭМ рд╕рдореГрджреНрдз рдиреЛрдбреНрд╕ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛тЪая╕П рд╕реАрдорд┐рдд
    рдПрдЖрдИ-рд╕рдВрдЪрд╛рд▓рд┐рдд рдЕрдиреБрд╡рд╛рджтЬЕ рд╣рд╛рдБ, рдХрдИ рдПрдЖрдИ рдкреНрд░рджрд╛рддрд╛рдУрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ API рдХреБрдВрдЬреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЖрдкрдХреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдФрд░ рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рдВрджрд░реНрдн рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддрд╛ рд╣реИтЭМ рдирд╣реАрдВтЭМ рдирд╣реАрдВ
    рд╡рд┐рдЬрд╝реБрдЕрд▓ рдПрдбрд┐рдЯрд░тЬЕ рд╣рд╛рдБ, рд╕реНрдерд╛рдиреАрдп рд╡рд┐рдЬрд╝реБрдЕрд▓ рдПрдбрд┐рдЯрд░ + рд╡реИрдХрд▓реНрдкрд┐рдХ CMS; рдХреЛрдбрдмреЗрд╕ рд╕рд╛рдордЧреНрд░реА рдХреЛ рдмрд╛рд╣рд░реА рд░реВрдк рд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ; рдПрдореНрдмреЗрдб рдХрд░рдиреЗ рдпреЛрдЧреНрдптЭМ рдирд╣реАрдВ / рдмрд╛рд╣рд░реА рд╕реНрдерд╛рдиреАрдпрдХрд░рдг рдкреНрд▓реЗрдЯрдлрд╛рд░реНрдореЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдкрд▓рдмреНрдзтЭМ рдирд╣реАрдВ / рдмрд╛рд╣рд░реА рд╕реНрдерд╛рдиреАрдпрдХрд░рдг рдкреНрд▓реЗрдЯрдлрд╛рд░реНрдореЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдкрд▓рдмреНрдз
    рд╕реНрдерд╛рдиреАрдпрдХреГрдд рд░реВрдЯрд┐рдВрдЧтЬЕ рд╣рд╛рдБ, рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рд╕реНрдерд╛рдиреАрдпрдХреГрдд рдкрдереЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ (Next.js рдФрд░ Vite рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ)тЬЕ рдЕрдВрддрд░реНрдирд┐рд░реНрдорд┐рдд, рдРрдк рд░рд╛рдЙрдЯрд░ [locale] рд╕реЗрдЧрдореЗрдВрдЯ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИтЬЕ рдЕрдВрддрд░реНрдирд┐рд░реНрдорд┐рдд
    рдбрд╛рдпрдирд╛рдорд┐рдХ рд░реВрдЯ рдЬрдирд░реЗрд╢рдитЬЕ рд╣рд╛рдБтЬЕ рд╣рд╛рдБтЬЕ рд╣рд╛рдБ
    рдмрд╣реБрд╡рдЪрдитЬЕ рдПрдиреЗрдорд░реЗрд╢рди-рдЖрдзрд╛рд░рд┐рдд рдкреИрдЯрд░реНрдитЬЕ рдЕрдЪреНрдЫрд╛тЬЕ рдЕрдЪреНрдЫрд╛
    рд╕реНрд╡рд░реВрдкрдг (рддрд┐рдерд┐рдпрд╛рдБ, рд╕рдВрдЦреНрдпрд╛рдПрдБ, рдореБрджреНрд░рд╛рдПрдБ)тЬЕ рдЕрдиреБрдХреВрд▓рд┐рдд рд╕реНрд╡рд░реВрдкрдХ (рдЕрдВрджрд░ рд╕реЗ Intl)тЬЕ рдЕрдЪреНрдЫрд╛ (Intl рд╕рд╣рд╛рдпрдХ)тЬЕ рдЕрдЪреНрдЫрд╛ (Intl рд╕рд╣рд╛рдпрдХ)
    рд╕рд╛рдордЧреНрд░реА рд╕реНрд╡рд░реВрдктЬЕ .tsx, .ts, .js, .json, .md, .txt, (.yaml WIP)тЬЕ .json, .js, .tsтЪая╕П .json
    ICU рд╕рдорд░реНрдердитЪая╕П рдкреНрд░рдЧрддрд┐ рдкрд░тЬЕ рд╣рд╛рдБтЪая╕П рдкреНрд▓рдЧрдЗрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ (i18next-icu)
    SEO рд╕рд╣рд╛рдпрдХ (hreflang, рд╕рд╛рдЗрдЯрдореИрдк)тЬЕ рдЕрдВрддрд░реНрдирд┐рд░реНрдорд┐рдд рдЙрдкрдХрд░рдг: рд╕рд╛рдЗрдЯрдореИрдк, robots.txt, рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рд╕рд╣рд╛рдпрдХтЬЕ рдЕрдЪреНрдЫрд╛тЬЕ рдЕрдЪреНрдЫрд╛
    рдЗрдХреЛрд╕рд┐рд╕реНрдЯрдо / рд╕рдореБрджрд╛рдптЪая╕П рдЫреЛрдЯрд╛ рд▓реЗрдХрд┐рди рддреЗрдЬреА рд╕реЗ рдмрдврд╝ рд░рд╣рд╛ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓тЬЕ рдордзреНрдпрдо рдЖрдХрд╛рд░, Next.js-рдХреЗрдВрджреНрд░рд┐рддтЬЕ рдордзреНрдпрдо рдЖрдХрд╛рд░, Next.js-рдХреЗрдВрджреНрд░рд┐рдд
    рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд░реЗрдВрдбрд░рд┐рдВрдЧ рдФрд░ рд╕рд░реНрд╡рд░ рдХрдВрдкреЛрдиреЗрдВрдЯреНрд╕тЬЕ рд╣рд╛рдБ, SSR / React рд╕рд░реНрд╡рд░ рдХрдВрдкреЛрдиреЗрдВрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рд╕реБрд╡реНрдпрд╡рд╕реНрдерд┐рддтЪая╕П рдкреЗрдЬ рд╕реНрддрд░ рдкрд░ рд╕рдорд░реНрдерд┐рдд рд▓реЗрдХрд┐рди рдЪрд╛рдЗрд▓реНрдб рд╕рд░реНрд╡рд░ рдХрдВрдкреЛрдиреЗрдВрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдХрдВрдкреЛрдиреЗрдВрдЯ рдЯреНрд░реА рдореЗрдВ t-рдлрдВрдХреНрд╢рдВрд╕ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИтЪая╕П рдкреЗрдЬ рд╕реНрддрд░ рдкрд░ рд╕рдорд░реНрдерд┐рдд рд▓реЗрдХрд┐рди рдЪрд╛рдЗрд▓реНрдб рд╕рд░реНрд╡рд░ рдХрдВрдкреЛрдиреЗрдВрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдХрдВрдкреЛрдиреЗрдВрдЯ рдЯреНрд░реА рдореЗрдВ t-рдлрдВрдХреНрд╢рдВрд╕ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
    рдЯреНрд░реА-рд╢реЗрдХрд┐рдВрдЧ (рдХреЗрд╡рд▓ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдХрдВрдЯреЗрдВрдЯ рдХреЛ рд▓реЛрдб рдХрд░рдирд╛)тЬЕ рд╣рд╛рдБ, Babel/SWC рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрд┐рд▓реНрдб рд╕рдордп рдкрд░ рдкреНрд░рддрд┐-рдХрдВрдкреЛрдиреЗрдВрдЯтЪая╕П рдЖрдВрд╢рд┐рдХтЪая╕П рдЖрдВрд╢рд┐рдХ
    рд▓реЗрдЬрд╝реА рд▓реЛрдбрд┐рдВрдЧтЬЕ рд╣рд╛рдБ, рдкреНрд░рддрд┐-рд▓реЛрдХрд▓ / рдкреНрд░рддрд┐-рдбрд┐рдХреНрд╢рдирд░реАтЬЕ рд╣рд╛рдБ (рдкреНрд░рддрд┐-рд░реВрдЯ/рдкреНрд░рддрд┐-рд▓реЛрдХрд▓), рдиреЗрдорд╕реНрдкреЗрд╕ рдкреНрд░рдмрдВрдзрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛тЬЕ рд╣рд╛рдБ (рдкреНрд░рддрд┐-рд░реВрдЯ/рдкреНрд░рддрд┐-рд▓реЛрдХрд▓), рдиреЗрдорд╕реНрдкреЗрд╕ рдкреНрд░рдмрдВрдзрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛
    рдЕрдкреНрд░рдпреБрдХреНрдд рдХрдВрдЯреЗрдВрдЯ рдХреЛ рд╣рдЯрд╛рдирд╛тЬЕ рд╣рд╛рдБ, рдмрд┐рд▓реНрдб рд╕рдордп рдкрд░ рдкреНрд░рддрд┐-рдбрд┐рдХреНрд╢рдирд░реАтЭМ рдирд╣реАрдВ, рдиреЗрдорд╕реНрдкреЗрд╕ рдкреНрд░рдмрдВрдзрди рдХреЗ рд╕рд╛рде рдореИрдиреНрдпреБрдЕрд▓реА рдкреНрд░рдмрдВрдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИтЭМ рдирд╣реАрдВ, рдиреЗрдорд╕реНрдкреЗрд╕ рдкреНрд░рдмрдВрдзрди рдХреЗ рд╕рд╛рде рдореИрдиреНрдпреБрдЕрд▓реА рдкреНрд░рдмрдВрдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
    рдмрдбрд╝реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ рдХрд╛ рдкреНрд░рдмрдВрдзрдитЬЕ рдореЙрдбреНрдпреВрд▓рд░ рдХреЛ рдкреНрд░реЛрддреНрд╕рд╛рд╣рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдбрд┐рдЬрд╝рд╛рдЗрди-рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрддтЬЕ рд╕реЗрдЯрдЕрдк рдХреЗ рд╕рд╛рде рдореЙрдбреНрдпреВрд▓рд░тЬЕ рд╕реЗрдЯрдЕрдк рдХреЗ рд╕рд╛рде рдореЙрдбреНрдпреВрд▓рд░

    рдкрд░рд┐рдЪрдп

    Next.js рдЖрдкрдХреЛ рдЕрдВрддрд░реНрд░рд╛рд╖реНрдЯреНрд░реАрдпрдХреГрдд routing (рдЬреИрд╕реЗ locale segments) рдХреЗ рд▓рд┐рдП built-in support рджреЗрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣ feature рдЕрдкрдиреЗ рдЖрдк translations рдирд╣реАрдВ рдХрд░рддрд╛ред рдЖрдкрдХреЛ рдЕрдкрдиреЗ users рдХреЛ localized content render рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ library рдХреА рдЬрд░реВрд░рдд рд╣реИред

    рдХрдИ i18n libraries рдореМрдЬреВрдж рд╣реИрдВ, рд▓реЗрдХрд┐рди Next.js рдХреА рджреБрдирд┐рдпрд╛ рдореЗрдВ рдЖрдЬ, рддреАрди рдХреЛ рдзреНрдпрд╛рди рдорд┐рд▓ рд░рд╣рд╛ рд╣реИ: next-i18next, next-intl, рдФрд░ Intlayerред

    рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдФрд░ рд╕реНрдХреЗрд▓реЗрдмрд┐рд▓рд┐рдЯреА

    • next-intl / next-i18next: рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдХреЗрдВрджреНрд░реАрдХреГрдд рдХреИрдЯрд▓реЙрдЧ рдкреНрд░рддрд┐ locale (рд╕рд╛рде рд╣реА i18next рдореЗрдВ namespaces)ред рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЕрдЪреНрдЫреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдХреНрд╕рд░ рдмрдврд╝рддреЗ coupling рдФрд░ key churn рдХреЗ рд╕рд╛рде рдПрдХ рдмрдбрд╝реА рд╕рд╛рдЭрд╛ рд╕рддрд╣ рдмрди рдЬрд╛рддрд╛ рд╣реИред
    • Intlayer: per-component (рдпрд╛ per-feature) dictionaries рдХреЛ co-located рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрддреНрд╕рд╛рд╣рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЙрд╕ рдХреЛрдб рдХреЗ рд╕рд╛рде рд╣реИрдВ рдЬрд┐рд╕рдХреА рд╡реЗ рд╕реЗрд╡рд╛ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рд╕рдВрдЬреНрдЮрд╛рдирд╛рддреНрдордХ рднрд╛рд░ рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИ, UI pieces рдХреЗ duplication/migration рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИ, рдФрд░ cross-team conflicts рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИред рдЕрдкреНрд░рдпреБрдХреНрдд content рдХреЛ рдЦреЛрдЬрдирд╛ рдФрд░ рд╣рдЯрд╛рдирд╛ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЖрд╕рд╛рди рд╣реИред

    рдпрд╣ рдХреНрдпреЛрдВ рдорд╛рдпрдиреЗ рд░рдЦрддрд╛ рд╣реИ: рдмрдбрд╝реЗ codebases рдпрд╛ design-system setups рдореЗрдВ, modular content monolithic catalogs рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмреЗрд╣рддрд░ рд╕реНрдХреЗрд▓ рдХрд░рддрд╛ рд╣реИред

    Bundle рдЖрдХрд╛рд░ рдФрд░ dependencies

    рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, bundle рд╡рд╣ JavaScript рд╣реИ рдЬреЛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдкреГрд╖реНрда рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓реЛрдб рдХрд░реЗрдЧрд╛ред рдЗрд╕рд▓рд┐рдП bundle рдХрд╛ рдЖрдХрд╛рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред

    рдмрд╣реБ-рднрд╛рд╖рд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ bundle рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рджреЛ рдШрдЯрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИрдВ:

    • рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЛрдб
    • рдмреНрд░рд╛рдЙрдЬрд╝рд░ рджреНрд╡рд╛рд░рд╛ рд▓реЛрдб рдХреА рдЧрдИ рд╕рд╛рдордЧреНрд░реА

    рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛрдб

    рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛрдб рдХрд╛ рдорд╣рддреНрд╡ рдиреНрдпреВрдирддрдо рд╣реИред рддреАрдиреЛрдВ рд╕рдорд╛рдзрд╛рди tree-shakable рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдХреЛрдб рдХреЗ рдЕрдкреНрд░рдпреБрдХреНрдд рд╣рд┐рд╕реНрд╕реЗ bundle рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВред

    рдпрд╣рд╛рдБ рддреАрдиреЛрдВ рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдорд▓реНрдЯреА-рд▓реИрдВрдЧреНрд╡реЗрдЬ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдмреНрд░рд╛рдЙрдЬрд╝рд░ рджреНрд╡рд╛рд░рд╛ рд▓реЛрдб рдХрд┐рдП рдЧрдП JavaScript bundle size рдХреА рддреБрд▓рдирд╛ рджреА рдЧрдИ рд╣реИред

    рдпрджрд┐ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рд╣рдореЗрдВ рдХрд┐рд╕реА formatter рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рддреЛ tree-shaking рдХреЗ рдмрд╛рдж рдирд┐рд░реНрдпрд╛рдд рдХрд┐рдП рдЧрдП рдлрд╝рдВрдХреНрд╢рди рдХреА рд╕реВрдЪреА рд╣реЛрдЧреА:

    • next-intlayer: useIntlayer, useLocale, NextIntlClientProvider, (Bundle size 180.6 kB -> 15.24 kB (gzip))
    • next-intl: useTranslations, useLocale, NextIntlClientProvider, (Bundle size 101.3 kB -> 31.4 kB (gzip))
    • next-i18next: useTranslation, useI18n, I18nextProvider, (Bundle size 80.7 kB -> 25.5 kB (gzip))

    рдпреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗрд╡рд▓ React context/state рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ wrappers рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП bundle size рдкрд░ i18n library рдХрд╛ рдХреБрд▓ рдкреНрд░рднрд╛рд╡ рдиреНрдпреВрдирддрдо рд╣реИред

    рд╕рд╛рдордЧреНрд░реА рдФрд░ рдЕрдиреБрд╡рд╛рдж

    рдпрд╣ рднрд╛рдЧ рдЕрдХреНрд╕рд░ developers рджреНрд╡рд╛рд░рд╛ рдирдЬрд╝рд░рдЕрдВрджрд╛рдЬрд╝ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдЗрдП 10 рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ 10 рдкреГрд╖реНрдареЛрдВ рд╕реЗ рдмрдиреЗ рдПрдХ application рдХреЗ рдорд╛рдорд▓реЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдЧрдгрдирд╛ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП 100% рдЕрджреНрд╡рд┐рддреАрдп рд╕рд╛рдордЧреНрд░реА рдХреЛ рдПрдХреАрдХреГрдд рдХрд░рддрд╛ рд╣реИ (рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдкреГрд╖реНрдареЛрдВ рдХреЗ рдмреАрдЪ рдмрд╣реБрдд рд╕реА рд╕рд╛рдордЧреНрд░реА redundant рд╣реЛрддреА рд╣реИ, рдЬреИрд╕реЗ page title, header, footer, рдЖрджрд┐)ред

    рдПрдХ user рдЬреЛ /fr/about рдкреГрд╖реНрда рдкрд░ рдЬрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рджрд┐рдП рдЧрдП language рдореЗрдВ рдПрдХ рдкреГрд╖реНрда рдХреА рд╕рд╛рдордЧреНрд░реА load рдХрд░реЗрдЧрд╛ред рд╕рд╛рдордЧреНрд░реА optimization рдХреЛ ignore рдХрд░рдиреЗ рдХрд╛ рдорддрд▓рдм рд╣реЛрдЧрд╛ 8,200% ((1 + (((10 pages - 1) ├Ч (10 languages - 1)))) ├Ч 100) application рд╕рд╛рдордЧреНрд░реА рдХреЛ unnecessarily load рдХрд░рдирд╛ред рдХреНрдпрд╛ рдЖрдк рд╕рдорд╕реНрдпрд╛ рджреЗрдЦрддреЗ рд╣реИрдВ? рднрд▓реЗ рд╣реА рдпрд╣ рд╕рд╛рдордЧреНрд░реА text рд░рд╣реЗ, рдФрд░ рдЬрдмрдХрд┐ рдЖрдк рд╢рд╛рдпрдж рдЕрдкрдиреА site рдХреА images рдХреЛ optimize рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдирд╛ рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ, рдЖрдк рджреБрдирд┐рдпрд╛ рднрд░ рдореЗрдВ useless рд╕рд╛рдордЧреНрд░реА рднреЗрдЬ рд░рд╣реЗ рд╣реИрдВ рдФрд░ users рдХреЗ computers рдХреЛ рдЗрд╕реЗ рдХреБрдЫ рдирд╣реАрдВ рдХреЗ рд▓рд┐рдП process рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВред

    рджреЛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рдорд╕реНрдпрд╛рдПрдВ:

    • Route рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд┐рднрд╛рдЬрди:

      рдпрджрд┐ рдореИрдВ /about рдкреГрд╖реНрда рдкрд░ рд╣реВрдВ, рддреЛ рдореБрдЭреЗ /home рдкреГрд╖реНрда рдХреА рд╕рд╛рдордЧреНрд░реА load рдирд╣реАрдВ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП
    • Locale рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд┐рднрд╛рдЬрди:

      рдпрджрд┐ рдореИрдВ /fr/about рдкреГрд╖реНрда рдкрд░ рд╣реВрдВ, рддреЛ рдореБрдЭреЗ /en/about рдкреГрд╖реНрда рдХреА рд╕рд╛рдордЧреНрд░реА load рдирд╣реАрдВ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП

    рдлрд┐рд░ рд╕реЗ, рддреАрдиреЛрдВ solutions рдЗрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ рдФрд░ рдЗрди optimizations рдХреЛ manage рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред рддреАрдиреЛрдВ solutions рдХреЗ рдмреАрдЪ рдЕрдВрддрд░ DX (Developer Experience) рдореЗрдВ рд╣реИред

    next-intl рдФрд░ next-i18next translations рдХреЛ manage рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ centralized approach рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ locale рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдФрд░ sub-files рдХреЗ рдЖрдзрд╛рд░ рдкрд░ JSON рдХреЛ split рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред next-i18next рдореЗрдВ, рд╣рдо JSON files рдХреЛ 'namespaces' рдХрд╣рддреЗ рд╣реИрдВ; next-intl messages рдХреЛ declare рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред intlayer рдореЗрдВ, рд╣рдо JSON files рдХреЛ 'dictionaries' рдХрд╣рддреЗ рд╣реИрдВред

    • next-intl рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, next-i18next рдХреА рддрд░рд╣, content рдХреЛ page/layout level рдкрд░ load рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдлрд┐рд░ рдЗрд╕ content рдХреЛ рдПрдХ context provider рдореЗрдВ load рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ developer рдХреЛ manually JSON files рдХреЛ manage рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдП load рд╣реЛрдВрдЧреАред
    рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рдЗрд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ developers рдЕрдХреНрд╕рд░ рдЗрд╕ optimization рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ, рд╕рд░рд▓рддрд╛ рдХреЗ рд▓рд┐рдП page рдХреЗ context provider рдореЗрдВ рд╕рднреА content рдХреЛ load рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВред
    • intlayer рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рднреА content рдХреЛ application рдореЗрдВ load рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдлрд┐рд░ рдПрдХ plugin (@intlayer/babel / @intlayer/swc) bundle рдХреЛ optimize рдХрд░рдиреЗ рдХрд╛ рдзреНрдпрд╛рди рд░рдЦрддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рдкреГрд╖реНрда рдкрд░ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА content рдХреЛ load рдХрд░рдХреЗред рдЗрд╕рд▓рд┐рдП developer рдХреЛ manually dictionaries рдХреЛ manage рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рдирд╣реАрдВ рд╣реИ рдЬреЛ load рд╣реЛрдВрдЧреАред рдпрд╣ рдмреЗрд╣рддрд░ optimization, рдмреЗрд╣рддрд░ maintainability, рдФрд░ development time рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

    рдЬреИрд╕реЗ-рдЬреИрд╕реЗ application рдмрдврд╝рддрд╛ рд╣реИ (рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЬрдм multiple developers application рдкрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ), рдпрд╣ common рд╣реИ рдХрд┐ JSON files рд╕реЗ рдРрд╕реА рд╕рд╛рдордЧреНрд░реА рдХреЛ remove рдХрд░рдирд╛ рднреВрд▓ рдЬрд╛рдПрдВ рдЬреЛ рдЕрдм рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХреА рдЬрд╛рддреА рд╣реИред

    рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕рднреА JSON рд╕рднреА cases рдореЗрдВ load рд╣реЛрддреЗ рд╣реИрдВ (next-intl, next-i18next, intlayer)ред

    рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ Intlayer рдХрд╛ approach рдЕрдзрд┐рдХ performant рд╣реИ: рдпрджрд┐ рдПрдХ component рдЕрдм рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХреА dictionary bundle рдореЗрдВ load рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред

    рдХреИрд╕реЗ library fallbacks рдХреЛ handle рдХрд░рддреА рд╣реИ рдпрд╣ рднреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдЖрдЗрдП рдорд╛рди рд▓реЗрдВ рдХрд┐ application default рд░реВрдк рд╕реЗ English рдореЗрдВ рд╣реИ, рдФрд░ user /fr/about рдкреГрд╖реНрда рдкрд░ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ French рдореЗрдВ translations missing рд╣реИрдВ, рддреЛ рд╣рдо English fallback рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред

    next-intl рдФрд░ next-i18next рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, library рдХреЛ current locale рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд JSON рдХреЛ load рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ, рд▓реЗрдХрд┐рди fallback locale рд╕реЗ рднреАред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдпрд╣ рдорд╛рдирддреЗ рд╣реБрдП рдХрд┐ рд╕рднреА content рдХрд╛ translation рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда 100% unnecessary рд╕рд╛рдордЧреНрд░реА рдХреЛ load рдХрд░реЗрдЧрд╛ред рддреБрд▓рдирд╛ рдореЗрдВ, intlayer dictionary build time рдкрд░ fallback рдХреЛ process рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдХреЗрд╡рд▓ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рд╕рд╛рдордЧреНрд░реА рдХреЛ load рдХрд░реЗрдЧрд╛ред

    рдзреНрдпрд╛рди рджреЗрдВ: intlayer рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ bundle рдХреЛ optimize рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЕрдкрдиреА intlayer.config.ts file рдореЗрдВ importMode: 'dynamic' option рдХреЛ set рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ plugin @intlayer/babel / @intlayer/swc installed рд╣реИрдВ (default рд░реВрдк рд╕реЗ vite-intlayer рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ installed)ред

    рдпрд╣рд╛рдВ рдПрдХ vite + react application рдореЗрдВ intlayer рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ bundle size optimization рдХреЗ рдкреНрд░рднрд╛рд╡ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

    Optimized bundleBundle not optimized
    optimized bundleno optimized bundle

    TypeScript рдФрд░ рд╕реБрд░рдХреНрд╖рд╛

    next-i18next

    • Hooks рдХреЗ рд▓рд┐рдП рдмреЗрд╕ typingsред strict key typing рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд tooling/config рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

    next-intl

    • рдареЛрд╕ TypeScript support, рд▓реЗрдХрд┐рди keys рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ strictly typed рдирд╣реАрдВ рд╣реИрдВред рдЖрдк рд╕реБрд░рдХреНрд╖рд╛ patterns рдХреЛ manually maintain рдХрд░реЗрдВрдЧреЗред

    intlayer

    • рдЖрдкрдХреА content рд╕реЗ strict types generate рдХрд░рддрд╛ рд╣реИред IDE autocompletion рдФрд░ compile-time errors deploy рд╕реЗ рдкрд╣рд▓реЗ typos рдФрд░ missing keys рдХреЛ catch рдХрд░рддреЗ рд╣реИрдВред

    рдпрд╣ рдХреНрдпреЛрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ: Strong typing failures рдХреЛ left (CI/build) рдХреА рдУрд░ shift рдХрд░рддрд╛ рд╣реИ right (runtime) рдХреА рдмрдЬрд╛рдпред

    рдЕрдиреБрдкрд▓рдмреНрдз рдЕрдиреБрд╡рд╛рдж рд╣реИрдВрдбрд▓рд┐рдВрдЧ

    next-i18next

    • runtime fallbacks рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред Build рд╡рд┐рдлрд▓ рдирд╣реАрдВ рд╣реЛрддрд╛ред

    next-intl

    • runtime fallbacks рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред Build рд╡рд┐рдлрд▓ рдирд╣реАрдВ рд╣реЛрддрд╛ред

    intlayer

    • Build-time detection with warnings/errors for missing locales or keysред

    Why it matters: Build рдХреЗ рджреМрд░рд╛рди gaps рдХреЛ рдкрдХрдбрд╝рдирд╛ production рдореЗрдВ 'undefined' strings рдХреЛ рд░реЛрдХрддрд╛ рд╣реИред

    рд░рд╛рдЙрдЯрд┐рдВрдЧ, рдорд┐рдбрд▓рд╡реЗрдпрд░ рдФрд░ рдпреВрдЖрд░рдПрд▓ рд░рдгрдиреАрддрд┐

    next-i18next

    • рд╕реНрдерд╛рдиреАрдпрдХреГрдд рд░рд╛рдЙрдЯрд┐рдВрдЧ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдорд┐рдбрд▓рд╡реЗрдпрд░ рдмрд┐рд▓реНрдЯ-рдЗрди рдирд╣реАрдВ рд╣реИред

    next-intl

    • рд╕реНрдерд╛рдиреАрдпрдХреГрдд рд░рд╛рдЙрдЯрд┐рдВрдЧ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
    • рдорд┐рдбрд▓рд╡реЗрдпрд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

    intlayer

    • рд╕реНрдерд╛рдиреАрдпрдХреГрдд рд░рд╛рдЙрдЯрд┐рдВрдЧ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
    • рдорд┐рдбрд▓рд╡реЗрдпрд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

    рдпрд╣ рдХреНрдпреЛрдВ рдорд╛рдпрдиреЗ рд░рдЦрддрд╛ рд╣реИ: SEO рдФрд░ рдЦреЛрдЬ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдиреБрднрд╡ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред

    Server Components (RSC) рд╕рдВрд░реЗрдЦрдг

    next-i18next

    • рдкреГрд╖реНрда рдФрд░ рд▓реЗрдЖрдЙрдЯ server components рдХреЛ рд╕рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИред
    • рдмрд╛рд▓ server components рдХреЗ рд▓рд┐рдП synchronous API рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

    next-intl

    • рдкреГрд╖реНрда рдФрд░ рд▓реЗрдЖрдЙрдЯ server components рдХреЛ рд╕рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИред
    • рдмрд╛рд▓ server components рдХреЗ рд▓рд┐рдП synchronous API рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

    intlayer

    • рдкреГрд╖реНрда рдФрд░ рд▓реЗрдЖрдЙрдЯ server components рдХреЛ рд╕рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИред
    • рдмрд╛рд▓ server components рдХреЗ рд▓рд┐рдП synchronous API рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

    рдпрд╣ рдХреНрдпреЛрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ: Server component рд╕рдкреЛрд░реНрдЯ Next.js 13+ рдХреА рдПрдХ рдореБрдЦреНрдп рд╕реБрд╡рд┐рдзрд╛ рд╣реИ, рдЬреЛ performance рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рддреА рд╣реИред parent рд╕реЗ рдмрд╛рд▓ server components рдореЗрдВ locale рдпрд╛ t рдлрд╝рдВрдХреНрд╢рди рдХреЛ props рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░рдиреЗ рд╕реЗ рдЖрдкрдХреЗ components рдХрдо reusable рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред

    рд╕реНрдерд╛рдиреАрдпрдХрд░рдг рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо (TMS) рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг

    рдмрдбрд╝реА рд╕рдВрдЧрдардиреЗрдВ рдЕрдХреНрд╕рд░ Crowdin, Phrase, Lokalise, Localizely, рдпрд╛ Localazy рдЬреИрд╕реА Translation Management Systems (TMS) рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреА рд╣реИрдВред

    • рдХрдВрдкрдирд┐рдпреЛрдВ рдХреЛ рдХреНрдпреЛрдВ рдкрд░рд╡рд╛рд╣ рд╣реИ

      • рд╕рд╣рдпреЛрдЧ рдФрд░ рднреВрдорд┐рдХрд╛рдПрдБ: рдХрдИ actors рд╢рд╛рдорд┐рд▓ рд╣реИрдВ: developers, product managers, translators, reviewers, marketing teamsред
      • рд╕реНрдХреЗрд▓ рдФрд░ рджрдХреНрд╖рддрд╛: continuous localization, in-context reviewред
    • next-intl / next-i18next

      • рдЖрдорддреМрд░ рдкрд░ centralized JSON catalogs рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП TMS рдХреЗ рд╕рд╛рде export/import рд╕реАрдзрд╛ рд╣реИред
      • рдкрд░рд┐рдкрдХреНрд╡ ecosystems рдФрд░ рдЙрдкрд░реЛрдХреНрдд рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдХреЗ рд▓рд┐рдП examples/integrationsред
    • Intlayer

      • decentralized, per-component dictionaries рдХреЛ рдкреНрд░реЛрддреНрд╕рд╛рд╣рд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ TypeScript/TSX/JS/JSON/MD content рдХреЛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред
      • рдпрд╣ code рдореЗрдВ modularity рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрдм рдХреЛрдИ tool centralized, flat JSON files рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИ рддреЛ plug-and-play TMS integration рдХреЛ рдХрдард┐рди рдмрдирд╛ рд╕рдХрддрд╛ рд╣реИред
      • Intlayer рд╡рд┐рдХрд▓реНрдк рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ: AI-assisted translations (рдЕрдкрдиреА provider keys рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ), рдПрдХ Visual Editor/CMS, рдФрд░ CLI/CI workflows рдХреЛ catch рдФрд░ prefill gaps рдХреЗ рд▓рд┐рдПред
    рдиреЛрдЯ: next-intl рдФрд░ i18next TypeScript catalogs рдХреЛ рднреА рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдкрдХреА team .ts files рдореЗрдВ messages рдХреЛ store рдХрд░рддреА рд╣реИ рдпрд╛ рдЙрдиреНрд╣реЗрдВ feature рджреНрд╡рд╛рд░рд╛ decentralize рдХрд░рддреА рд╣реИ, рддреЛ рдЖрдк рд╕рдорд╛рди TMS friction рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдХрдИ next-intl setups locales/ folder рдореЗрдВ centralized рд░рд╣рддреЗ рд╣реИрдВ, рдЬреЛ TMS рдХреЗ рд▓рд┐рдП JSON рдореЗрдВ refactor рдХрд░рдирд╛ рдереЛрдбрд╝рд╛ рдЖрд╕рд╛рди рд╣реИред

    рдбреЗрд╡рд▓рдкрд░ рдЕрдиреБрднрд╡

    рдпрд╣ рднрд╛рдЧ рддреАрдиреЛрдВ рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рдЧрд╣рди рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рд╕рдорд╛рдзрд╛рди рдХреЗ 'getting started' рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╕рд░рд▓ cases рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ use case рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ project рдХреЗ рдЕрдзрд┐рдХ рд╕рдорд╛рди рд╣реИред

    рдРрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рдВрд░рдЪрдирд╛

    рдРрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рдВрд░рдЪрдирд╛ рдЖрдкрдХреЗ codebase рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫреА maintainability рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред

    bash
    .
    тФЬтФАтФА i18n.config.ts
    тФФтФАтФА src
        тФЬтФАтФА locales
        тФВ   тФЬтФАтФА en
        тФВ   тФВ  тФЬтФАтФА common.json
        тФВ   тФВ  тФФтФАтФА about.json
        тФВ   тФФтФАтФА fr
        тФВ      тФЬтФАтФА common.json
        тФВ      тФФтФАтФА about.json
        тФЬтФАтФА app
        тФВ   тФЬтФАтФА i18n
        тФВ   тФВ   тФФтФАтФА server.ts
        тФВ   тФФтФАтФА [locale]
        тФВ       тФЬтФАтФА layout.tsx
        тФВ       тФФтФАтФА about.tsx
        тФФтФАтФА components
            тФЬтФАтФА I18nProvider.tsx
            тФЬтФАтФА ClientComponent.tsx
            тФФтФАтФА ServerComponent.tsx
    
    bash
    .
    тФЬтФАтФА i18n.ts
    тФЬтФАтФА locales
    тФВ   тФЬтФАтФА en
        тФВ   тФВ  тФЬтФАтФА home.json
        тФВ   тФВ  тФФтФАтФА navbar.json
        тФВ   тФЬтФАтФА fr
        тФВ   тФВ  тФЬтФАтФА home.json
        тФВ   тФВ  тФФтФАтФА navbar.json
        тФВ   тФФтФАтФА es
        тФВ      тФЬтФАтФА home.json
        тФВ      тФФтФАтФА navbar.json
    тФФтФАтФА src
        тФЬтФАтФА middleware.ts
        тФЬтФАтФА app
        тФВ   тФЬтФАтФА i18n
        тФВ   тФВ   тФФтФАтФА server.ts
        тФВ   тФФтФАтФА [locale]
        тФВ       тФФтФАтФА home.tsx
        тФФтФАтФА components
            тФФтФАтФА Navbar
                тФФтФАтФА index.tsx
    
    bash
    .
    тФЬтФАтФА intlayer.config.ts
    тФФтФАтФА src
        тФЬтФАтФА middleware.ts
        тФЬтФАтФА app
        тФВ   тФФтФАтФА [locale]
        тФВ       тФЬтФАтФА layout.tsx
        тФВ       тФФтФАтФА home
        тФВ           тФЬтФАтФА index.tsx
        тФВ           тФФтФАтФА index.content.ts
        тФФтФАтФА components
            тФФтФАтФА Navbar
                тФЬтФАтФА index.tsx
                тФФтФАтФА index.content.ts
    

    рддреБрд▓рдирд╛

    • next-intl / next-i18next: рдХреЗрдВрджреНрд░реАрдХреГрдд рдХреИрдЯрд▓реЙрдЧ (JSON; рдиреЗрдорд╕реНрдкреЗрд╕/рд╕рдВрджреЗрд╢)ред рд╕реНрдкрд╖реНрдЯ рд╕рдВрд░рдЪрдирд╛, рдЕрдиреБрд╡рд╛рдж рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдХреЗ рд╕рд╛рде рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдПрдХреАрдХреГрдд, рд▓реЗрдХрд┐рди рдЬреИрд╕реЗ-рдЬреИрд╕реЗ рдРрдкреНрд╕ рдмрдврд╝рддреЗ рд╣реИрдВ, рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдмреАрдЪ рдЕрдзрд┐рдХ рд╕рдВрдкрд╛рджрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред
    • Intlayer: рдкреНрд░рддрд┐-рдШрдЯрдХ .content.{ts|js|json} рд╢рдмреНрджрдХреЛрд╢ рдЬреЛ рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╣-рд╕реНрдерд┐рдд рд╣реИрдВред рдЖрд╕рд╛рди рдШрдЯрдХ рдкреБрдирдГ рдЙрдкрдпреЛрдЧ рдФрд░ рд╕реНрдерд╛рдиреАрдп рддрд░реНрдХ; рдлрд╝рд╛рдЗрд▓реЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдФрд░ рдмрд┐рд▓реНрдб-рд╕рдордп рдЙрдкрдХрд░рдг рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред

    рд╕реЗрдЯрдЕрдк рдФрд░ рдХрдВрдЯреЗрдВрдЯ рд▓реЛрдбрд┐рдВрдЧ

    рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ JSON рдлрд╛рдЗрд▓ рдХреЛ рдХреИрд╕реЗ import рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЗрд╕реЗ optimize рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ library рдХрдВрдЯреЗрдВрдЯ рд▓реЛрдбрд┐рдВрдЧ рдХреЛ рдХреИрд╕реЗ handle рдХрд░рддреА рд╣реИред

    i18n.config.ts
    export const locales = ["en", "fr"] as const;
    export type Locale = (typeof locales)[number];
    
    export const defaultLocale: Locale = "en";
    
    export const rtlLocales = ["ar", "he", "fa", "ur"] as const;
    export const isRtl = (locale: string) =>
      (rtlLocales as readonly string[]).includes(locale);
    
    export function localizedPath(locale: string, path: string) {
      return locale === defaultLocale ? path : "/" + locale + path;
    }
    
    const ORIGIN = "https://example.com";
    export function abs(locale: string, path: string) {
      return ORIGIN + localizedPath(locale, path);
    }
    
    src/app/i18n/server.ts
    import { createInstance } from "i18next";
    import { initReactI18next } from "react-i18next/initReactI18next";
    import resourcesToBackend from "i18next-resources-to-backend";
    import { defaultLocale } from "@/i18n.config";
    
    // src/locales/<locale>/<namespace>.json рд╕реЗ JSON resources рдХреЛ рд▓реЛрдб рдХрд░реЗрдВ
    const backend = resourcesToBackend(
      (locale: string, namespace: string) =>
        import(`../../locales/${locale}/${namespace}.json`)
    );
    
    export async function initI18next(
      locale: string,
      namespaces: string[] = ["common"]
    ) {
      const i18n = createInstance();
      await i18n
        .use(initReactI18next)
        .use(backend)
        .init({
          lng: locale,
          fallbackLng: defaultLocale,
          ns: namespaces,
          defaultNS: "common",
          interpolation: { escapeValue: false },
          react: { useSuspense: false },
        });
      return i18n;
    }
    
    src/components/I18nProvider.tsx
    "use client";
    
    import * as React from "react";
    import { I18nextProvider } from "react-i18next";
    import { createInstance } from "i18next";
    import { initReactI18next } from "react-i18next/initReactI18next";
    import resourcesToBackend from "i18next-resources-to-backend";
    import { defaultLocale } from "@/i18n.config";
    
    const backend = resourcesToBackend(
      (locale: string, namespace: string) =>
        import(`../../locales/${locale}/${namespace}.json`)
    );
    
    type Props = {
      locale: string;
      namespaces?: string[];
      resources?: Record<string, any>; // { ns: bundle }
      children: React.ReactNode;
    };
    
    export default function I18nProvider({
      locale,
      namespaces = ["common"],
      resources,
      children,
    }: Props) {
      const [i18n] = React.useState(() => {
        const i = createInstance();
    
        i.use(initReactI18next)
          .use(backend)
          .init({
            lng: locale,
            fallbackLng: defaultLocale,
            ns: namespaces,
            resources: resources ? { [locale]: resources } : undefined,
            defaultNS: "common",
            interpolation: { escapeValue: false },
            react: { useSuspense: false },
          });
    
        return i;
      });
    
      return <I18nextProvider i18n={i18n}>{children}</I18nextProvider>;
    }
    
    src/app/[locale]/layout.tsx
    import type { ReactNode } from "react";
    import { locales, defaultLocale, isRtl, type Locale } from "@/i18n.config";
    
    export const dynamicParams = false;
    
    export function generateStaticParams() {
      return locales.map((locale) => ({ locale }));
    }
    
    export default function LocaleLayout({
      children,
      params,
    }: {
      children: ReactNode;
      params: { locale: string };
    }) {
      const locale: Locale = (locales as readonly string[]).includes(params.locale)
        ? params.locale
        : defaultLocale;
    
      const dir = isRtl(locale) ? "rtl" : "ltr";
    
      return (
        <html lang={locale} dir={dir}>
          <body>{children}</body>
        </html>
      );
    }
    
    src/app/[locale]/about.tsx
    import I18nProvider from "@/components/I18nProvider";
    import { initI18next } from "@/app/i18n/server";
    import type { Locale } from "@/i18n.config";
    import ClientComponent from "@/components/ClientComponent";
    import ServerComponent from "@/components/ServerComponent";
    
    // рдкреЗрдЬ рдХреЗ рд▓рд┐рдП static rendering рдХреЛ force рдХрд░реЗрдВ
    export const dynamic = "force-static";
    
    export default async function AboutPage({
      params: { locale },
    }: {
      params: { locale: Locale };
    }) {
      const namespaces = ["common", "about"] as const;
    
      const i18n = await initI18next(locale, [...namespaces]);
      const tAbout = i18n.getFixedT(locale, "about");
    
      return (
        <I18nProvider locale={locale} namespaces={[...namespaces]}>
          <main>
            <h1>{tAbout("title")}</h1>
    
            <ClientComponent />
            <ServerComponent t={tAbout} locale={locale} count={0} />
          </main>
        </I18nProvider>
      );
    }
    

    рддреБрд▓рдирд╛

    рддреАрдиреЛрдВ per-locale content loading рдФрд░ providers рдХреЛ support рдХрд░рддреЗ рд╣реИрдВред

    • next-intl/next-i18next рдХреЗ рд╕рд╛рде, рдЖрдк рдЖрдорддреМрд░ рдкрд░ selected messages/namespaces рдХреЛ per route load рдХрд░рддреЗ рд╣реИрдВ рдФрд░ providers рдХреЛ рдЬрд╣рд╛рдБ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рд╡рд╣рд╛рдБ place рдХрд░рддреЗ рд╣реИрдВред

    • Intlayer рдХреЗ рд╕рд╛рде, build-time analysis рдХреЛ add рдХрд░рддрд╛ рд╣реИ usage рдХреЛ infer рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬреЛ manual wiring рдХреЛ reduce рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдПрдХ single root provider рдХреА рдЕрдиреБрдорддрд┐ рджреЗ рд╕рдХрддрд╛ рд╣реИред

    Team preference рдХреЗ рдЖрдзрд╛рд░ рдкрд░ explicit control рдФрд░ automation рдХреЗ рдмреАрдЪ рдЪреБрдиреЗрдВред

    рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдВрдкреЛрдиреЗрдВрдЯ рдореЗрдВ рдЙрдкрдпреЛрдЧ

    рдЖрдЗрдП рдПрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдВрдкреЛрдиреЗрдВрдЯ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд▓реЗрдВ рдЬреЛ рдПрдХ рдХрд╛рдЙрдВрдЯрд░ рд░реЗрдВрдбрд░ рдХрд░рддрд╛ рд╣реИред

    рдЕрдиреБрд╡рд╛рдж (рдПрдХ JSON рдкреНрд░рддрд┐ namespace src/locales/... рдХреЗ рддрд╣рдд)

    src/locales/en/about.json
    {
      "title": "About",
      "description": "About page description",
      "counter": {
        "label": "Counter",
        "increment": "Increment"
      }
    }
    
    src/locales/fr/about.json
    {
      "title": "├А propos",
      "description": "Description de la page ├А propos",
      "counter": {
        "label": "Compteur",
        "increment": "Incr├йmenter"
      }
    }
    

    рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдВрдкреЛрдиреЗрдВрдЯ (рдХреЗрд╡рд▓ рдЖрд╡рд╢реНрдпрдХ namespace рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ)

    src/components/ClientComponent.tsx
    "use client";
    
    import React, { useState } from "react";
    import { useTranslation } from "react-i18next";
    
    const ClientComponent = () => {
      const { t, i18n } = useTranslation("about");
      const [count, setCount] = useState(0);
    
      const numberFormat = new Intl.NumberFormat(i18n.language);
    
      return (
        <div>
          <p>{numberFormat.format(count)}</p>
          <button
            aria-label={t("counter.label")}
            onClick={() => setCount((c) => c + 1)}
          >
            {t("counter.increment")}
          </button>
        </div>
      );
    };
    
    export default ClientComponent;
    

    рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдкреЗрдЬ/рдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рдХреЗрд╡рд▓ рдЖрд╡рд╢реНрдпрдХ namespaces рд╢рд╛рдорд┐рд▓ рдХрд░рддрд╛ рд╣реИ (рдЬреИрд╕реЗ about)ред рдпрджрд┐ рдЖрдк React < 19 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рднрд╛рд░реА formatters рдЬреИрд╕реЗ Intl.NumberFormat рдХреЛ memoize рдХрд░реЗрдВред

    рдЕрдиреБрд╡рд╛рдж (рдЖрдХреГрддрд┐ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ; рдЙрдиреНрд╣реЗрдВ next-intl рд╕рдВрджреЗрд╢реЛрдВ рдореЗрдВ рдЕрдкрдиреА рдкрд╕рдВрдж рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд▓реЛрдб рдХрд░реЗрдВ)

    locales/en/about.json
    {
      "counter": {
        "label": "Counter",
        "increment": "Increment"
      }
    }
    
    locales/fr/about.json
    {
      "counter": {
        "label": "Compteur",
        "increment": "Incr├йmenter"
      }
    }
    

    рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдВрдкреЛрдиреЗрдВрдЯ

    src/components/ClientComponentExample.tsx
    "use client";
    
    import React, { useState } from "react";
    import { useTranslations, useFormatter } from "next-intl";
    
    const ClientComponentExample = () => {
      // рдиреЗрд╕реНрдЯреЗрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рд╕реАрдзреЗ рд╕реНрдХреЛрдк рдХрд░реЗрдВ
      const t = useTranslations("about.counter");
      const format = useFormatter();
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>{format.number(count)}</p>
          <button
            aria-label={t("label")}
            onClick={() => setCount((count) => count + 1)}
          >
            {t("increment")}
          </button>
        </div>
      );
    };
    
    рдкреЗрдЬ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рдВрджреЗрд╢ рдкрд░ "about" рд╕рдВрджреЗрд╢ рдЬреЛрдбрд╝рдирд╛ рди рднреВрд▓реЗрдВ

    рд╕рд╛рдордЧреНрд░реА

    src/components/ClientComponentExample/index.content.ts
    import { t, type Dictionary } from "intlayer";
    
    const counterContent = {
      key: "counter",
      content: {
        label: t({ hi: "рдХрд╛рдЙрдВрдЯрд░", en: "Counter", fr: "Compteur" }),
        increment: t({ hi: "рд╡реГрджреНрдзрд┐", en: "Increment", fr: "Incr├йmenter" }),
      },
    } satisfies Dictionary;
    
    export default counterContent;
    

    рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдВрдкреЛрдиреЗрдВрдЯ

    src/components/ClientComponentExample/index.tsx
    "use client";
    
    import React, { useState } from "react";
    import { useNumber, useIntlayer } from "next-intlayer";
    
    const ClientComponentExample = () => {
      const [count, setCount] = useState(0);
      const { label, increment } = useIntlayer("counter"); // strings return рдХрд░рддрд╛ рд╣реИ
      const { number } = useNumber();
    
      return (
        <div>
          <p>{number(count)}</p>
          <button aria-label={label} onClick={() => setCount((count) => count + 1)}>
            {increment}
          </button>
        </div>
      );
    };
    

    рддреБрд▓рдирд╛

    • рд╕рдВрдЦреНрдпрд╛ рд╕реНрд╡рд░реВрдкрдг

      • next-i18next: рдХреЛрдИ useNumber рдирд╣реАрдВ; Intl.NumberFormat (рдпрд╛ i18next-icu) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
      • next-intl: useFormatter().number(value)ред
      • Intlayer: useNumber() built-inред
    • Keys

      • рдПрдХ nested structure (about.counter.label) рд░рдЦреЗрдВ рдФрд░ рдЕрдкрдиреЗ hook рдХреЛ accordingly scope рдХрд░реЗрдВ (useTranslation("about") + t("counter.label") рдпрд╛ useTranslations("about.counter") + t("label"))ред
    • рдлрд╝рд╛рдЗрд▓ рд╕реНрдерд╛рди

      • next-i18next рдХреЛ public/locales/{lng}/{ns}.json рдореЗрдВ JSON рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рд╣реИред
      • next-intl рд▓рдЪреАрд▓рд╛ рд╣реИ; рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рдЕрдкрдиреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд▓реЛрдб рдХрд░реЗрдВред
      • Intlayer TS/JS dictionaries рдореЗрдВ content store рдХрд░рддрд╛ рд╣реИ рдФрд░ key рдХреЗ рдЖрдзрд╛рд░ рдкрд░ resolve рдХрд░рддрд╛ рд╣реИред

    рд╕рд░реНрд╡рд░ рдХрдВрдкреЛрдиреЗрдВрдЯ рдореЗрдВ рдЙрдкрдпреЛрдЧ

    рд╣рдо рдПрдХ UI рдХрдВрдкреЛрдиреЗрдВрдЯ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рд▓реЗрдВрдЧреЗред рдпрд╣ рдХрдВрдкреЛрдиреЗрдВрдЯ рдПрдХ рд╕рд░реНрд╡рд░ рдХрдВрдкреЛрдиреЗрдВрдЯ рд╣реИ, рдФрд░ рдПрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдВрдкреЛрдиреЗрдВрдЯ рдХреЗ рдЪрд╛рдЗрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдбрд╛рд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред (page (server component) -> client component -> server component)ред рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдХрдВрдкреЛрдиреЗрдВрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдВрдкреЛрдиреЗрдВрдЯ рдХреЗ рдЪрд╛рдЗрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдбрд╛рд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдпрд╣ async рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

    src/components/ServerComponent.tsx
    type ServerComponentProps = {
      t: (key: string) => string;
      locale: string;
      count: number;
    };
    
    const ServerComponent = ({ t, locale, count }: ServerComponentProps) => {
      // рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдлреЙрд░реНрдореЗрдЯ рдХрд░реЗрдВ
      const formatted = new Intl.NumberFormat(locale).format(count);
    
      return (
        <div>
          <p>{formatted}</p>
          <button aria-label={t("counter.label")}>{t("counter.increment")}</button>
        </div>
      );
    };
    
    export default ServerComponent;
    
    src/components/ServerComponent.tsx
    type ServerComponentProps = {
      t: (key: string) => string;
      locale: string;
      count: number;
      formatter: Intl.NumberFormat;
    };
    
    const ServerComponent = ({
      t,
      locale,
      count,
      formatter,
    }: ServerComponentProps) => {
      // рдлреЙрд░реНрдореЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдлреЙрд░реНрдореЗрдЯ рдХрд░реЗрдВ
      const formatted = formatter.format(count);
    
      return (
        <div>
          <p>{formatted}</p>
          <button aria-label={t("counter.label")}>{t("counter.increment")}</button>
        </div>
      );
    };
    
    export default ServerComponent;
    

    рдЬреИрд╕рд╛ рдХрд┐ рд╕рд░реНрд╡рд░ рдХрдВрдкреЛрдиреЗрдВрдЯ async рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЖрдкрдХреЛ translations рдФрд░ formatter рдлрд╝рдВрдХреНрд╢рди рдХреЛ props рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

    рдЖрдкрдХреЗ page / layout рдореЗрдВ:

    • import { getTranslations, getFormatter } from "next-intl/server";
    • const t = await getTranslations("about.counter");
    • const formatter = await getFormatter().then((formatter) => formatter.number());
    src/components/ServerComponent.tsx
    import { useIntlayer, useNumber } from "next-intlayer/server";
    
    type ServerComponentProps = {
      count: number;
    };
    
    const ServerComponent = ({ count }: ServerComponentProps) => {
      // counter рд╕реЗ translations рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ
      const { label, increment } = useIntlayer("counter");
      // number рдлреЙрд░реНрдореЗрдЯрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ
      const { number } = useNumber();
    
      return (
        <div>
          <p>{number(count)}</p>
          <button aria-label={label}>{increment}</button>
        </div>
      );
    };
    
    Intlayer next-intlayer/server рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ server-safe hooks рдХреЛ expose рдХрд░рддрд╛ рд╣реИред рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, useIntlayer рдФрд░ useNumber hooks-like syntax рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ hooks рдХреЗ рд╕рдорд╛рди рд╣реИрдВ, рд▓реЗрдХрд┐рди server context (IntlayerServerProvider) рдкрд░ рдирд┐рд░реНрднрд░ рд╣реИрдВред

    рдореЗрдЯрд╛рдбреЗрдЯрд╛ / рд╕рд╛рдЗрдЯрдореИрдк / рд░реЛрдмреЛрдЯреНрд╕

    content рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдХрд░рдирд╛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд▓реЛрдЧ рдЕрдХреНрд╕рд░ рднреВрд▓ рдЬрд╛рддреЗ рд╣реИрдВ рдХрд┐ internationalization рдХрд╛ рдореБрдЦреНрдп рд▓рдХреНрд╖реНрдп рдЖрдкрдХреА website рдХреЛ рджреБрдирд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рджреГрд╢реНрдпрдорд╛рди рдмрдирд╛рдирд╛ рд╣реИред I18n рдЖрдкрдХреА website visibility рдореЗрдВ рд╕реБрдзрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрджреНрднреБрдд рд╕рд╛рдзрди рд╣реИред

    рдпрд╣рд╛рдБ рдмрд╣реБрднрд╛рд╖реА SEO рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдЕрдЪреНрдЫреА practices рдХреА рдПрдХ рд╕реВрдЪреА рджреА рдЧрдИ рд╣реИред

    • <head> tag рдореЗрдВ hreflang рдореЗрдЯрд╛ tags рд╕реЗрдЯ рдХрд░реЗрдВ > рдпрд╣ search engines рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдкреГрд╖реНрда рдкрд░ рдХреМрди рд╕реА рднрд╛рд╖рд╛рдПрдВ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ
    • http://www.w3.org/1999/xhtml XML schema рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ sitemap.xml рдореЗрдВ рд╕рднреА рдкреГрд╖реНрдареЛрдВ рдХреЗ рдЕрдиреБрд╡рд╛рдж рд╕реВрдЪреАрдмрджреНрдз рдХрд░реЗрдВ >
    • robots.txt рд╕реЗ prefixed pages рдХреЛ exclude рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ (рдЙрджрд╛. /dashboard, /fr/dashboard, /es/dashboard) >
    • рд╕рдмрд╕реЗ localized page рдкрд░ redirect рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП custom Link component рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ (рдЙрджрд╛. рдлреНрд░реЗрдВрдЪ рдореЗрдВ <a href="/fr/about">A propos</a> ) >

    Developers рдЕрдХреНрд╕рд░ locales рдХреЗ across рдЕрдкрдиреЗ рдкреГрд╖реНрдареЛрдВ рдХреЛ рдареАрдХ рд╕реЗ reference рдХрд░рдирд╛ рднреВрд▓ рдЬрд╛рддреЗ рд╣реИрдВред

    i18n.config.ts
    export const locales = ["en", "fr"] as const;
    export type Locale = (typeof locales)[number];
    export const defaultLocale: Locale = "en";
    
    export function localizedPath(locale: string, path: string) {
      return locale === defaultLocale ? path : "/" + locale + path;
    }
    
    const ORIGIN = "https://example.com";
    export function abs(locale: string, path: string) {
      return ORIGIN + localizedPath(locale, path);
    }
    
    src/app/[locale]/about/layout.tsx
    import type { Metadata } from "next";
    import { locales, defaultLocale, localizedPath } from "@/i18n.config";
    
    type GenerateMetadataParams = {
      params: Promise<{
        locale: string;
      }>;
    };
    
    export const generateMetadata = async ({
      params,
    }: GenerateMetadataParams): Promise<Metadata> => {
      const { locale } = await params;
    
      // src/locales рд╕реЗ рд╕рд╣реА JSON bundle import рдХрд░реЗрдВ
      const messages = (await import("@/locales/" + locale + "/about.json"))
        .default;
    
      const languages = Object.fromEntries(
        locales.map((locale) => [locale, localizedPath(locale, "/about")])
      );
    
      return {
        title: messages.title,
        description: messages.description,
        alternates: {
          canonical: localizedPath(locale, "/about"),
          languages: { ...languages, "x-default": "/about" },
        },
      };
    };
    
    export default async function AboutPage() {
      return <h1>About</h1>;
    }
    
    src/app/sitemap.ts
    import type { MetadataRoute } from "next";
    import { locales, defaultLocale, abs } from "@/i18n.config";
    
    export const sitemap = (): MetadataRoute.Sitemap => {
      const languages = Object.fromEntries(
        locales.map((locale) => [locale, abs(locale, "/about")])
      );
      return [
        {
          url: abs(defaultLocale, "/about"),
          lastModified: new Date(),
          changeFrequency: "monthly",
          priority: 0.7,
          alternates: { languages },
        },
      ];
    };
    
    src/app/robots.ts
    import type { MetadataRoute } from "next";
    import { locales, defaultLocale, localizedPath } from "@/i18n.config";
    
    const ORIGIN = "https://example.com";
    
    const expandAllLocales = (path: string) => [
      localizedPath(defaultLocale, path),
      ...locales
        .filter((locale) => locale !== defaultLocale)
        .map((locale) => localizedPath(locale, path)),
    ];
    
    export const robots = (): MetadataRoute.Robots => {
      const disallow = [
        ...expandAllLocales("/dashboard"),
        ...expandAllLocales("/admin"),
      ];
    
      return {
        rules: { userAgent: "*", allow: ["/"], disallow },
        host: ORIGIN,
        sitemap: ORIGIN + "/sitemap.xml",
      };
    };
    
    src/app/[locale]/about/layout.tsx
    import type { Metadata } from "next";
    import { locales, defaultLocale } from "@/i18n";
    import { getTranslations } from "next-intl/server";
    
    const localizedPath = (locale: string, path: string) => {
      return locale === defaultLocale ? path : "/" + locale + path;
    };
    
    type GenerateMetadataParams = {
      params: Promise<{
        locale: string;
      }>;
    };
    
    export const generateMetadata = async ({
      params,
    }: GenerateMetadataParams): Promise<Metadata> => {
      const { locale } = await params;
      const t = await getTranslations({ locale, namespace: "about" });
    
      const url = "/about";
      const languages = Object.fromEntries(
        locales.map((locale) => [locale, localizedPath(locale, url)])
      );
    
      return {
        title: t("title"),
        description: t("description"),
        alternates: {
          canonical: localizedPath(locale, url),
          languages: { ...languages, "x-default": url },
        },
      };
    };
    
    // ... рдмрд╛рдХреА page code
    
    src/app/sitemap.ts
    import type { MetadataRoute } from "next";
    import { locales, defaultLocale } from "@/i18n";
    
    const origin = "https://example.com";
    
    const formatterLocalizedPath = (locale: string, path: string) =>
      locale === defaultLocale ? origin + path : origin + "/" + locale + path;
    
    export const sitemap = (): MetadataRoute.Sitemap => {
      const aboutLanguages = Object.fromEntries(
        locales.map((l) => [l, formatterLocalizedPath(l, "/about")])
      );
    
      return [
        {
          url: formatterLocalizedPath(defaultLocale, "/about"),
          lastModified: new Date(),
          changeFrequency: "monthly",
          priority: 0.7,
          alternates: { languages: aboutLanguages },
        },
      ];
    };
    
    src/app/robots.ts
    import type { MetadataRoute } from "next";
    import { locales, defaultLocale } from "@/i18n";
    
    const origin = "https://example.com";
    const withAllLocales = (path: string) => [
      path,
      ...locales
        .filter((locale) => locale !== defaultLocale)
        .map((locale) => "/" + locale + path),
    ];
    
    export const robots = (): MetadataRoute.Robots => {
      const disallow = [
        ...withAllLocales("/dashboard"),
        ...withAllLocales("/admin"),
      ];
    
      return {
        rules: { userAgent: "*", allow: ["/"], disallow },
        host: origin,
        sitemap: origin + "/sitemap.xml",
      };
    };
    
    src/app/[locale]/about/layout.tsx
    import { getIntlayer, getMultilingualUrls } from "intlayer";
    import type { Metadata } from "next";
    import type { LocalPromiseParams } from "next-intlayer";
    
    export const generateMetadata = async ({
      params,
    }: LocalPromiseParams): Promise<Metadata> => {
      const { locale } = await params;
    
      const metadata = getIntlayer("page-metadata", locale);
    
      const multilingualUrls = getMultilingualUrls("/about");
    
      return {
        ...metadata,
        alternates: {
          canonical: multilingualUrls[locale as keyof typeof multilingualUrls],
          languages: { ...multilingualUrls, "x-default": "/about" },
        },
      };
    };
    
    // ... рдмрд╛рдХреА page code
    
    src/app/sitemap.ts
    import { getMultilingualUrls } from "intlayer";
    import type { MetadataRoute } from "next";
    
    const sitemap = (): MetadataRoute.Sitemap => [
      {
        url: "https://example.com/about",
        alternates: {
          languages: { ...getMultilingualUrls("https://example.com/about") },
        },
      },
    ];
    
    src/app/robots.ts
    import { getMultilingualUrls } from "intlayer";
    import type { MetadataRoute } from "next";
    
    const getAllMultilingualUrls = (urls: string[]) =>
      urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);
    
    const robots = (): MetadataRoute.Robots => ({
      rules: {
        userAgent: "*",
        allow: ["/"],
        disallow: getAllMultilingualUrls(["/dashboard"]),
      },
      host: "https://example.com",
      sitemap: "https://example.com/sitemap.xml",
    });
    
    export default robots;
    
    Intlayer рдЖрдкрдХреЗ sitemap рдХреЗ рд▓рд┐рдП рдмрд╣реБрднрд╛рд╖реА URLs рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ getMultilingualUrls function рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

    рд▓реЛрдХреЗрд▓ рд░реВрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП Middleware

    рд▓реЛрдХреЗрд▓ рдбрд┐рдЯреЗрдХреНрд╢рди рдФрд░ рд░реВрдЯрд┐рдВрдЧ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ middleware рдЬреЛрдбрд╝реЗрдВ:

    src/middleware.ts
    import { NextResponse, type NextRequest } from "next/server";
    import { defaultLocale, locales } from "@/i18n.config";
    
    const PUBLIC_FILE = /\.[^/]+$/; // рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╡рд╛рд▓реА рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдмрд╛рд╣рд░ рдХрд░реЗрдВ
    
    export function middleware(request: NextRequest) {
      const { pathname } = request.nextUrl;
    
      if (
        pathname.startsWith("/_next") ||
        pathname.startsWith("/api") ||
        pathname.startsWith("/static") ||
        PUBLIC_FILE.test(pathname)
      ) {
        return;
      }
    
      const hasLocale = locales.some(
        (l) => pathname === "/" + l || pathname.startsWith("/" + l + "/")
      );
      if (!hasLocale) {
        const locale = defaultLocale;
        const url = request.nextUrl.clone();
        url.pathname = "/" + locale + (pathname === "/" ? "" : pathname);
        return NextResponse.redirect(url);
      }
    }
    
    export const config = {
      matcher: [
        // рдЗрди рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдкрд╛рде рдФрд░ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╡рд╛рд▓реА рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рд╕рднреА рдкрд╛рде рд╕реЗ рдореЗрд▓ рдЦрд╛рдПрдВ
        "/((?!api|_next|static|.*\\..*).*)",
      ],
    };
    

    рд▓реЛрдХреЗрд▓ рдбрд┐рдЯреЗрдХреНрд╢рди рдФрд░ рд░реВрдЯрд┐рдВрдЧ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ middleware рдЬреЛрдбрд╝реЗрдВ:

    src/middleware.ts
    import createMiddleware from "next-intl/middleware";
    import { locales, defaultLocale } from "@/i18n";
    
    export default createMiddleware({
      locales: [...locales],
      defaultLocale,
      localeDetection: true,
    });
    
    export const config = {
      // API, Next internals рдФрд░ static assets рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВ
      matcher: ["/((?!api|_next|.*\\..*).*)"],
    };
    

    Intlayer next-intlayer package рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ built-in middleware рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

    src/middleware.ts
    import { intlayerProxy } from "next-intlayer/proxy";
    
    export const middleware = intlayerProxy();
    
    // рдпрд╣ middleware рдХреЗрд╡рд▓ app рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ рдлрд╛рдЗрд▓реЛрдВ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ
    export const config = {
      matcher: "/((?!api|_next|static|.*\\..*).*)",
    };
    

    Middleware рдХреА рд╕реЗрдЯрдЕрдк intlayer.config.ts рдлрд╛рдЗрд▓ рдореЗрдВ рдХреЗрдВрджреНрд░реАрдХреГрдд рд╣реИред

    рд╕реЗрдЯрдЕрдк рдЪреЗрдХрд▓рд┐рд╕реНрдЯ рдФрд░ рд╕рд░реНрд╡реЛрддреНрддрдо рдкреНрд░рдерд╛рдПрдВ

    • рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ lang рдФрд░ dir рдХреЛ src/app/[locale]/layout.tsx рдореЗрдВ рд░реВрдЯ <html> рдкрд░ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
    • рдЕрдиреБрд╡рд╛рджреЛрдВ рдХреЛ рдиреЗрдорд╕реНрдкреЗрд╕ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП common.json, about.json) src/locales/<locale>/ рдХреЗ рдЕрдВрддрд░реНрдЧрддред
    • рдХреНрд▓рд╛рдЗрдВрдЯ рдШрдЯрдХреЛрдВ рдореЗрдВ useTranslation('<ns>') рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдФрд░ I18nProvider рдХреЛ рд╕рдорд╛рди рдиреЗрдорд╕реНрдкреЗрд╕ рдХреЗ рд╕рд╛рде рд╕реНрдХреЛрдк рдХрд░рдХреЗ рдХреЗрд╡рд▓ рдЖрд╡рд╢реНрдпрдХ рдиреЗрдорд╕реНрдкреЗрд╕ рд▓реЛрдб рдХрд░реЗрдВред
    • рдкреЗрдЬреЛрдВ рдХреЛ рдЬрд╣рд╛рдВ рд╕рдВрднрд╡ рд╣реЛ рд╕реНрдЯреИрдЯрд┐рдХ рд░рдЦреЗрдВ: рдкреЗрдЬреЛрдВ рдкрд░ export const dynamic = 'force-static' рдирд┐рд░реНрдпрд╛рдд рдХрд░реЗрдВ; dynamicParams = false рд╕реЗрдЯ рдХрд░реЗрдВ рдФрд░ generateStaticParams рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВред
    • рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реАрдорд╛рдУрдВ рдХреЗ рддрд╣рдд рдиреЗрд╕реНрдЯреЗрдб рд╕рд┐рдВрдХ рд╕рд░реНрд╡рд░ рдШрдЯрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рдЧрдгрдирд╛ рдХреА рдЧрдИ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдпрд╛ t рдлрд╝рдВрдХреНрд╢рди рдФрд░ locale рдХреЛ рдкрд╛рд╕ рдХрд░рдХреЗред
    • SEO рдХреЗ рд▓рд┐рдП, рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдореЗрдВ alternates.languages рд╕реЗрдЯ рдХрд░реЗрдВ, sitemap.ts рдореЗрдВ рд╕реНрдерд╛рдиреАрдпрдХреГрдд URLs рдХреА рд╕реВрдЪреА рдмрдирд╛рдПрдВ, рдФрд░ robots.ts рдореЗрдВ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╕реНрдерд╛рдиреАрдпрдХреГрдд рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдЕрдиреБрдорддрд┐ рди рджреЗрдВред
    • рд▓реЛрдХреЗрд▓-рдЬрд╛рдЧрд░реВрдХ рдлреЙрд░реНрдореЗрдЯрд░реНрд╕ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Intl.NumberFormat(locale)) рдХреЛ рд╡рд░реАрдпрддрд╛ рджреЗрдВ рдФрд░ рдпрджрд┐ React < 19 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдЙрдиреНрд╣реЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рдореЗрдореЛрдЗрдЬрд╝ рдХрд░реЗрдВред
    • HTML lang рдФрд░ dir рд╕реЗрдЯ рдХрд░реЗрдВ: src/app/[locale]/layout.tsx рдореЗрдВ, getLocaleDirection(locale) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ dir рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВ рдФрд░ <html lang={locale} dir={dir}> рд╕реЗрдЯ рдХрд░реЗрдВред
    • рдиреЗрдорд╕реНрдкреЗрд╕ рджреНрд╡рд╛рд░рд╛ рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдВ: рдкреНрд░рддрд┐ рд▓реЛрдХреЗрд▓ рдФрд░ рдиреЗрдорд╕реНрдкреЗрд╕ JSON рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░реЗрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, common.json, about.json)ред
    • рдХреНрд▓рд╛рдЗрдВрдЯ рдкреЗрд▓реЛрдб рдХреЛ рдХрдо рдХрд░реЗрдВ: рдкреЗрдЬреЛрдВ рдкрд░, рдХреЗрд╡рд▓ рдЖрд╡рд╢реНрдпрдХ рдиреЗрдорд╕реНрдкреЗрд╕ рдХреЛ NextIntlClientProvider рдХреЛ рднреЗрдЬреЗрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, pick(messages, ['common', 'about']))ред
    • рд╕реНрдЯреИрдЯрд┐рдХ рдкреЗрдЬреЛрдВ рдХреЛ рд╡рд░реАрдпрддрд╛ рджреЗрдВ: export const dynamic = 'force-static' рдирд┐рд░реНрдпрд╛рдд рдХрд░реЗрдВ рдФрд░ рд╕рднреА locales рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдЯрд┐рдХ params рдЬреЗрдирд░реЗрдЯ рдХрд░реЗрдВред
    • рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╕рд░реНрд╡рд░ рдШрдЯрдХ: рдкреВрд░реНрд╡-рдЧрдгрдирд╛ рдХреА рдЧрдИ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ (рдЕрдиреБрд╡рд╛рджрд┐рдд рд▓реЗрдмрд▓, рд╕реНрд╡рд░реВрдкрд┐рдд рд╕рдВрдЦреНрдпрд╛рдПрдВ) рдХреЛ рдкрд╛рд╕ рдХрд░рдХреЗ рд╕рд░реНрд╡рд░ рдШрдЯрдХреЛрдВ рдХреЛ рд╕рд┐рдВрдХ рд░рдЦреЗрдВ рди рдХрд┐ async рдХреЙрд▓ рдпрд╛ рдЧреИрд░-рд╕реАрд░рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрдмрд▓ рдлрд╝рдВрдХреНрд╢рдиред
    • рдореЙрдбреНрдпреВрд▓рд░ рд╕рд╛рдордЧреНрд░реА: .content.{ts|js|json} рдлрд╛рдЗрд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд╛рдордЧреНрд░реА рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдХреЛ рдШрдЯрдХреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╣-рд╕реНрдерд┐рдд рдХрд░реЗрдВред
    • рдкреНрд░рдХрд╛рд░ рд╕реБрд░рдХреНрд╖рд╛: рдХрдВрдкрд╛рдЗрд▓-рд╕рдордп рд╕рд╛рдордЧреНрд░реА рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП TypeScript рдПрдХреАрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
    • рдмрд┐рд▓реНрдб-рд╕рдордп рдЕрдиреБрдХреВрд▓рди: рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдЯреНрд░реА-рд╢реЗрдХрд┐рдВрдЧ рдФрд░ рдмрдВрдбрд▓ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП Intlayer рдХреЗ рдмрд┐рд▓реНрдб рдЯреВрд▓реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
    • рдПрдХреАрдХреГрдд рдЯреВрд▓рд┐рдВрдЧ: рдмрд┐рд▓реНрдЯ-рдЗрди рд░реВрдЯрд┐рдВрдЧ, SEO рд╕рд╣рд╛рдпрдХреЛрдВ рдФрд░ рд╡рд┐рдЬреБрдЕрд▓ рдПрдбрд┐рдЯрд░ рд╕рдорд░реНрдерди рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдПрдВред

    рдФрд░ рд╡рд┐рдЬреЗрддрд╛ рд╣реИтАж

    рдпрд╣ рд╕рд░рд▓ рдирд╣реАрдВ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рдХрд▓реНрдк рдХреЗ рдЕрдкрдиреЗ trade-offs рд╣реИрдВред рдпрд╣рд╛рдБ рдореЗрд░рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИ:

    next-i18next

    • рдкрд░рд┐рдкрдХреНрд╡, рд╕реБрд╡рд┐рдзрд╛рдУрдВ рд╕реЗ рднрд░рдкреВрд░, рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХрдореНрдпреБрдирд┐рдЯреА рдкреНрд▓рдЧрдЗрди, рд▓реЗрдХрд┐рди рдЙрдЪреНрдЪ рд╕реЗрдЯрдЕрдк рд▓рд╛рдЧрддред рдпрджрд┐ рдЖрдкрдХреЛ i18next рдХреЗ рдкреНрд▓рдЧрдЗрди рдЗрдХреЛрд╕рд┐рд╕реНрдЯрдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреНрд▓рдЧрдЗрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдиреНрдирдд ICU рдирд┐рдпрдо) рдФрд░ рдЖрдкрдХреА рдЯреАрдо рдкрд╣рд▓реЗ рд╕реЗ i18next рдХреЛ рдЬрд╛рдирддреА рд╣реИ, рддреЛ рд▓рдЪреАрд▓реЗрдкрди рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдВред

    next-intl

    • рд╕рдмрд╕реЗ рд╕рд░рд▓, рд╣рд▓реНрдХрд╛-рдлреБрд▓реНрдХрд╛, рдХрдо рдирд┐рд░реНрдгрдп рдЖрдк рдкрд░ рдереЛрдкреЗ рдЧрдПред рдпрджрд┐ рдЖрдк рдПрдХ рдиреНрдпреВрдирддрдо рд╕рдорд╛рдзрд╛рди рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдХреЗрдВрджреНрд░реАрднреВрдд рдХреИрдЯрд▓реЙрдЧ рдХреЗ рд╕рд╛рде рд╕рд╣рдЬ рд╣реИрдВ, рдФрд░ рдЖрдкрдХрд╛ рдРрдкреНрд▓рд┐рдХреЗрд╢рди рдЫреЛрдЯрд╛ рд╕реЗ рдордзреНрдпрдо рдЖрдХрд╛рд░ рдХрд╛ рд╣реИред

    Intlayer

    • рдЖрдзреБрдирд┐рдХ Next.js рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрдорд┐рдд, рдореЙрдбреНрдпреВрд▓рд░ рдХрдВрдЯреЗрдВрдЯ, type safety, tooling, рдФрд░ рдХрдо boilerplate рдХреЗ рд╕рд╛рдеред рдпрджрд┐ рдЖрдк component-scoped content, strict TypeScript, build-time guarantees, tree-shaking, рдФрд░ batteries-included routing/SEO/editor tooling рдХреЛ рдорд╣рддреНрд╡ рджреЗрддреЗ рд╣реИрдВ - рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ Next.js App Router, design-systems рдФрд░ рдмрдбрд╝реЗ, рдореЙрдбреНрдпреВрд▓рд░ codebases рдХреЗ рд▓рд┐рдПред

    рдпрджрд┐ рдЖрдк рдиреНрдпреВрдирддрдо рд╕реЗрдЯрдЕрдк рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдХреБрдЫ рдореИрдиреБрдЕрд▓ wiring рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ next-intl рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИред рдпрджрд┐ рдЖрдкрдХреЛ рд╕рднреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рдЬрдЯрд┐рд▓рддрд╛ рдореЗрдВ рдХреЛрдИ рдмреБрд░рд╛рдИ рдирд╣реАрдВ рд╣реИ, рддреЛ next-i18next рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рдПрдХ рдЖрдзреБрдирд┐рдХ, рд╕реНрдХреЗрд▓реЗрдмрд▓, рдореЙрдбреНрдпреВрд▓рд░ рд╕рдорд╛рдзрд╛рди рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рдирд┐рд░реНрдорд┐рдд tools рд╣реИрдВ, рддреЛ Intlayer рдЗрд╕реЗ рдЖрдкрдХреЛ рд╕реАрдзреЗ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХрд╛ рд▓рдХреНрд╖реНрдп рд░рдЦрддрд╛ рд╣реИред

    рдПрдВрдЯрд░рдкреНрд░рд╛рдЗрдЬ рдЯреАрдореЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд▓реНрдк: рдпрджрд┐ рдЖрдкрдХреЛ рдПрдХ well-proven рд╕рдорд╛рдзрд╛рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ Crowdin, Phrase, рдпрд╛ рдЕрдиреНрдп рдкреЗрд╢реЗрд╡рд░ translation management systems рдЬреИрд╕реЗ рд╕реНрдерд╛рдкрд┐рдд localization platforms рдХреЗ рд╕рд╛рде рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЕрдкрдиреЗ mature ecosystem рдФрд░ proven integrations рдХреЗ рд▓рд┐рдП next-intl рдпрд╛ next-i18next рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
    Future roadmap: Intlayer i18next рдФрд░ next-intl рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЗ рдКрдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ plugins рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреА рднреА рдпреЛрдЬрдирд╛ рдмрдирд╛ рд░рд╣рд╛ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ automation, syntax, рдФрд░ content management рдХреЗ рд▓рд┐рдП Intlayer рдХреЗ рдлрд╛рдпрджреЗ рджреЗрдЧрд╛ рдЬрдмрдХрд┐ рдЖрдкрдХреЗ application code рдореЗрдВ рдЗрди рд╕реНрдерд╛рдкрд┐рдд рд╕рдорд╛рдзрд╛рдиреЛрдВ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ security рдФрд░ stability рдХреЛ рдмрдирд╛рдП рд░рдЦреЗрдЧрд╛ред

    рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдиреЛрдЯреНрд╕ (next-intl / next-i18next тЖТ Intlayer)

    • рдкреНрд░рддреНрдпреЗрдХ рдлреАрдЪрд░ рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ: рдПрдХ рдмрд╛рд░ рдореЗрдВ рдПрдХ рд░реВрдЯ рдпрд╛ рдХрдВрдкреЛрдиреЗрдВрдЯ рдХреЛ рд╕реНрдерд╛рдиреАрдп рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВред
    • рдкреБрд░рд╛рдиреЗ рдХреИрдЯрд▓реЙрдЧреНрд╕ рдХреЛ рд╕рдорд╛рдирд╛рдВрддрд░ рд░рдЦреЗрдВ: рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдкреБрд▓ рдХрд╛ рдХрд╛рдо рдХрд░реЗрдВ; рдПрдХ рдмрдбрд╝рд╛ рдмрджрд▓рд╛рд╡ рдХрд░рдиреЗ рд╕реЗ рдмрдЪреЗрдВред
    • рд╕рдЦреНрдд рдЬрд╛рдВрдЪреЗрдВ рдЪрд╛рд▓реВ рдХрд░реЗрдВ: рдмрд┐рд▓реНрдб-рдЯрд╛рдЗрдо рдкрд░ рдЕрдВрддрд░рд╛рд▓ рдЬрд▓реНрджреА рдкрддрд╛ рдЪрд▓рдиреЗ рджреЗрдВред
    • рдорд┐рдбрд▓рд╡реЗрдпрд░ рдФрд░ рд╣реЗрд▓реНрдкрд░реНрд╕ рдЕрдкрдирд╛рдПрдВ: рд╕рд╛рдЗрдЯ-рд╡рд╛рдЗрдб рд▓реЛрдХрд▓ рдбрд┐рдЯреЗрдХреНрд╢рди рдФрд░ SEO рдЯреИрдЧреНрд╕ рдХреЛ рдорд╛рдирдХреАрдХреГрдд рдХрд░реЗрдВред
    • рдмрдВрдбрд▓реНрд╕ рдХреЛ рдорд╛рдкреЗрдВ: рдЬрдм рдЕрдкреНрд░рдпреБрдХреНрдд рд╕рд╛рдордЧреНрд░реА рд╣рдЯрд╛рдИ рдЬрд╛рддреА рд╣реИ рддреЛ рдмрдВрдбрд▓ рдЖрдХрд╛рд░ рдореЗрдВ рдХрдореА рдХреА рдЙрдореНрдореАрдж рдХрд░реЗрдВред

    рдирд┐рд╖реНрдХрд░реНрд╖

    рддреАрдиреЛрдВ рд▓рд╛рдЗрдмреНрд░реЗрд░реАрдЬрд╝ рдореВрд▓ рд╕реНрдерд╛рдиреАрдпрдХрд░рдг рдореЗрдВ рд╕рдлрд▓ рд╣реИрдВред рдлрд░реНрдХ рдпрд╣ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдХрд┐рддрдирд╛ рдХрд╛рдо рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдПрдХ рдордЬрдмреВрдд, рд╕реНрдХреЗрд▓реЗрдмрд▓ рд╕реЗрдЯрдЕрдк рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдзреБрдирд┐рдХ Next.js рдореЗрдВ:

    • Intlayer рдХреЗ рд╕рд╛рде, рдореЙрдбреНрдпреВрд▓рд░ рдХрдВрдЯреЗрдВрдЯ, рд╕рдЦреНрдд TS, рдмрд┐рд▓реНрдб-рдЯрд╛рдЗрдо рд╕реБрд░рдХреНрд╖рд╛, рдЯреНрд░реА-рд╢реЗрдХреНрдб рдмрдВрдбрд▓, рдФрд░ рдкреНрд░рдердо рд╢реНрд░реЗрдгреА рдХрд╛ App Router + SEO рдЯреВрд▓рд┐рдВрдЧ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╣реИрдВ, рди рдХрд┐ рдмреЛрдЭред
    • рдпрджрд┐ рдЖрдкрдХреА рдЯреАрдо рдПрдХ рдорд▓реНрдЯреА-рд▓реЛрдХрд▓, рдХрдВрдкреЛрдиреЗрдВрдЯ-рдЪрд╛рд▓рд┐рдд рдРрдк рдореЗрдВ рд░рдЦрд░рдЦрд╛рд╡ рдФрд░ рдЧрддрд┐ рдХреЛ рдорд╣рддреНрд╡ рджреЗрддреА рд╣реИ, рддреЛ Intlayer рдЖрдЬ рд╕рдмрд╕реЗ рдкреВрд░реНрдг рдЕрдиреБрднрд╡ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

    рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП 'Why Intlayer?' рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рджреЗрдЦреЗрдВред

    рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

    рдЕрднреА рддрдХ рдХреЛрдИ рдЯрд┐рдкреНрдкрдгреА рдирд╣реАрдВред рдЕрдкрдиреЗ рд╡рд┐рдЪрд╛рд░ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдкрд╣рд▓реЗ рд╡реНрдпрдХреНрддрд┐ рдмрдиреЗрдВред

    рд╕рдВрдмрдВрдзрд┐рдд рдкреЛрд╕реНрдЯ

    рдирд╡реАрдирддрдо рдкреЛрд╕реНрдЯ