Author:
    Creation:2026-09-13Last update:2026-09-13

    next-intl बनाम Intlayer | React और Next.js अंतर्राष्ट्रीयकरण (i18n) बेंचमार्क

    next-intl आज Next.js App Router के लिए डिफ़ॉल्ट विकल्प है: राउटिंग के साथ गहरा एकीकरण, संपूर्ण ICU MessageFormat समर्थन, और क्लासिक i18n सिस्टम का उपयोग करने वाले किसी भी व्यक्ति के लिए एक परिचित डेवलपर अनुभव।

    Intlayer समस्या पर पुनर्विचार करता है: कोई केंद्रीकृत डिक्शनरी नहीं, रूट्स के साथ नेमस्पेस का मिलान करने का कोई मैन्युअल काम नहीं। सामग्री प्रत्येक कंपोनेंट के बगल में घोषित की जाती है, और एक बिल्ड-टाइम कंपाइलर केवल वही बंडल करता है जिसकी प्रत्येक पेज को आवश्यकता होती है।

    यह लेख Benchmark Bloom के डेटा का उपयोग करके दोनों की तुलना करता है, जो एक ओपन-सोर्स टेस्ट सूट है जो प्रत्येक लाइब्रेरी के साथ समान एप्लिकेशन बनाता है और रिकॉर्ड करता है कि ब्राउज़र वास्तव में क्या डाउनलोड और निष्पादित करता है।

    संक्षेप में (tl;dr): next-intl केवल अपने रनटाइम के लिए प्रत्येक पेज पर +12.6 KB gzip जोड़ता है, और अपने सामान्य सेटअप (static और dynamic) में ~90% अन्य पेजों की स्ट्रिंग्स लीक करता है। उस लीकेज को हटाने के लिए कैटलॉग को नेमस्पेस में विभाजित करना और प्रत्येक पेज के लिए मैन्युअल रूप से चुनना पड़ता है, जो एक कठिन काम है। इसके विपरीत, Intlayer का कंपाइलर बिना किसी अतिरिक्त कॉन्फ़िगरेशन के 0% लीकेज, 3 गुना छोटे कंपोनेंट्स, और बेस ऐप से केवल +0.3 KB अधिक साइज़ सुनिश्चित करता है।

    संक्षेप में

    • next-intl - Next.js समुदाय का मानक। प्रति भाषा केंद्रीकृत JSON डिक्शनरी, पूर्ण ICU MessageFormat समर्थन, और Next.js अनुरोध हैंडलिंग और राउटिंग के साथ गहरा एकीकरण।
    • Intlayer - कंपोनेंट-केंद्रित कंटेंट मॉडल। .content.ts फाइलें अपने कंपोनेंट्स के बगल में बैठती हैं, बिल्ड-टाइम कंपाइलर उन्हें प्रति कंपोनेंट और प्रति लोकेल ट्री-शेक और लेज़ी-लोड करता है, और स्वचालित रूप से सख्त TypeScript प्रकार उत्पन्न करता है।
    लाइब्रेरीGitHub स्टार्सकुल कमिट्सअंतिम कमिटपहला संस्करणNPM संस्करणNPM डाउनलोड्स
    aymericzip/intlayerGitHub Repo starsGitHub commit activityLast Commitअप्रैल 2024npmnpm downloads
    amannn/next-intlGitHub Repo starsGitHub commit activityLast Commitमार्च 2021npmnpm downloads
    बैज स्वचालित रूप से अपडेट होते हैं।

    आमने-सामने सुविधा तुलना

    सुविधाIntlayer (react-intlayer / next-intlayer)next-intl (next-intl / use-intl)
    कंपोनेंट के पास अनुवाद✅ हाँ, प्रत्येक कंपोनेंट के बगल में .content.ts मौजूदmessages/ में केंद्रीकृत JSON डिक्शनरी
    TypeScript एकीकरण✅ कंटेंट से ऑटो-जनरेटेड सख्त प्रकार⚠️ संदेश पथों के लिए मैन्युअल global.d.ts सेटअप के माध्यम से समर्थित
    गायब अनुवादों का पता लगाना✅ TypeScript एरर + बिल्ड-टाइम एरर/चेतावनी⚠️ रनटाइम गायब कुंजी लौटाता है या कॉन्फ़िगरेशन के आधार पर त्रुटि फेंकता है
    रिच कंटेंट (JSX / Markdown / कंपोनेंट्स)✅ सीधा समर्थन⚠️ मैपिंग कंपोनेंट्स के साथ t.rich() के माध्यम से
    ICU समर्थन⚠️ कार्य प्रगति पर✅ हाँ, पूर्ण ICU समर्थन
    सिंक्रोनस सर्वर कंपोनेंट्सnext-intlayer/server से useIntlayer किसी भी चाइल्ड सर्वर कंपोनेंट में काम करता है❌ एसिंक्रोनस सर्वर पैरेंट से प्रॉप्स के माध्यम से अनुवाद पास करने की आवश्यकता होती है
    ट्री-शेकिंग (Tree-shaking)✅ कंपाइलर द्वारा स्वचालित (प्रति कंपोनेंट, प्रति लोकेल)⚠️ नेमस्पेस को मैन्युअल रूप से विभाजित करने और pick() का उपयोग करने की आवश्यकता है
    लेज़ी लोडिंग (Lazy loading)✅ कॉन्फ़िगरेशन की एक पंक्ति (importMode: 'dynamic')⚠️ getRequestConfig में मैन्युअल डायनेमिक इम्पोर्ट की आवश्यकता होती है
    विजुअल एडिटर / CMS✅ निःशुल्क विजुअल एडिटर + वैकल्पिक CMS❌ नहीं
    AI-संचालित अनुवाद✅ बिल्ट-इन, आपकी अपनी प्रदाता कुंजियों का उपयोग करता है❌ नहीं
    MCP सर्वर और एजेंट स्किल्स✅ हाँ❌ नहीं

    बेंचमार्क

    क्या मापा गया था

    Benchmark Bloom टेस्ट सुइट प्रत्येक लाइब्रेरी के साथ समान एप्लिकेशन बनाता है: 10 पेज (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10 लोकेल (en, fr, es, de, it, pt, zh, ja, ko, ru), समान कंपोनेंट और समान कंटेंट। पेजों को en और fr में मापा जाता है। प्रत्येक लाइब्रेरी को चार लोडिंग रणनीतियों तक लागू किया गया है:

    रणनीतिविवरणयह कौन करता है
    staticप्रत्येक लोकेल और प्रत्येक पेज को एक साथ बंडल करके लोड किया जाता हैत्वरित प्रोटोटाइप, AI-जनरेटेड कोड
    dynamicकेवल सक्रिय लोकेल लोड किया जाता है, लेकिन सभी पेज एक साथअधिकांश प्रोजेक्ट्स
    scoped-staticप्रति रूट नेमस्पेस, कोई लेज़ी लोडिंग नहींदुर्लभ
    scoped-dynamicप्रति रूट नेमस्पेस + लेज़ी लोडिंग। केवल वर्तमान पेज और वर्तमान लोकेल भेजा जाता हैसख्त प्रदर्शन बजट वाले ऐप्स

    Intlayer में कोई "scoped" संस्करण नहीं है: कंपाइलर स्वचालित रूप से प्रति कंपोनेंट सामग्री को स्कोप करता है, इसलिए इसकी static और dynamic पंक्तियाँ पहले से ही स्कोप्ड हैं।

    प्रत्येक बिल्ड के लिए, सुइट रिकॉर्ड करता है:

    • Lib size: केवल i18n लाइब्रेरी इम्पोर्ट करने वाले खाली कंपोनेंट का gzip आकार।
    • Page JS: प्रति पेज डाउनलोड किया गया gzip जावास्क्रिप्ट।
    • Locale leak %: डाउनलोड किए गए JS में पाए गए अनूदित स्ट्रिंग्स का हिस्सा जो उस लोकेल से संबंधित हैं जिसे उपयोगकर्ता नहीं देख रहा है।
    • Page leak %: डाउनलोड किए गए JS में पाए गए अनूदित स्ट्रिंग्स का हिस्सा जो उस पेज से संबंधित हैं जिस पर उपयोगकर्ता नहीं है।
    • Component avg: अलग से कंपाइल किए गए प्रत्येक कंपोनेंट का औसत gzip आकार।
    • E2E reactivity: नया लोकेल चुनने और DOM में html[lang] अपडेट होने के बीच का समय।
    • Hydration: React हाइड्रेशन चरण की अवधि।
    नीचे दिए गए आंकड़े 2026-09-12 के रन से हैं, जिसमें next-intl 4.14.2 और intlayer 9.5.1 शामिल हैं।

    Next.js (App Router) पर परिणाम

    लाइब्रेरीरणनीतिलाइब्रेरी साइज़ (gz)पेज JS औसत (gz)लोकेल लीकपेज लीककंपोनेंट औसत (gz)E2E प्रतिक्रियाशीलताहाइड्रेशन
    base (बिना i18n)-0.0 KB141.0 KB0.0%0.0%0.9 KB13.4 ms11.8 ms
    next-intlstatic14.7 KB153.6 KB4.2%89.8%21.8 KB16.0 ms14.7 ms
    next-intldynamic14.7 KB153.6 KB9.7%89.9%21.8 KB15.6 ms14.8 ms
    next-intlscoped-static14.7 KB153.6 KB0.0%0.0%80.1 KB17.9 ms17.4 ms
    next-intlscoped-dynamic14.7 KB153.6 KB0.0%0.0%22.9 KB17.8 ms16.8 ms
    next-intlayerstatic5.5 KB141.3 KB0.0%0.0%8.5 KB15.5 ms16.9 ms
    next-intlayerdynamic5.5 KB141.3 KB0.0%0.0%6.9 KB15.3 ms15.9 ms
    @intlayer/next-intl (संगतता)static8.0 KB147.5 KB0.0%0.0%8.1 KB14.5 ms12.8 ms
    @intlayer/next-intl (संगतता)dynamic8.0 KB148.7 KB0.0%0.0%8.1 KB11.7 ms12.8 ms

    परिणामों को कैसे समझें

    • रनटाइम लागत। बेस एप्लिकेशन 141.0 KB प्रति पेज है। next-intl इसे 153.6 KB (प्रत्येक पेज पर +12.6 KB gzip) तक ले जाता है, जबकि Intlayer इसे केवल 141.3 KB (+0.3 KB) तक ले जाता है।
    • लीकेज। सबसे आम सेटअप (static और dynamic) में, next-intl हर पेज पर ~90% अन्य पेजों की सामग्री भेजता है, क्योंकि पूरी en.json क्लाइंट प्रोवाइडर में जाती है। 0% तक पहुँचने के लिए सावधानीपूर्वक मैनुअल विभाजन की आवश्यकता होती है, जबकि Intlayer स्वचालित रूप से 0% पर है।
    • कंपोनेंट साइज़। useTranslations() को कॉल करने वाला कंपोनेंट औसतन 21.8 KB का होता है; useIntlayer() के साथ वही कंपोनेंट केवल 6.9 KB का होता है।

    TanStack Start (use-intl) पर परिणाम

    लाइब्रेरीरणनीतिलाइब्रेरी साइज़ (gz)पेज JS औसत (gz)लोकेल लीकपेज लीककंपोनेंट औसत (gz)E2E प्रतिक्रियाशीलता
    base (बिना i18n)-0.0 KB111.0 KB0.0%0.0%0.7 KB8.1 ms
    use-intlstatic14.1 KB179.8 KB50.0%89.8%76.0 KB6.7 ms
    use-intldynamic14.1 KB119.4 KB0.0%89.8%75.9 KB7.0 ms
    use-intlscoped-static14.1 KB128.7 KB0.0%0.0%87.1 KB20.9 ms
    use-intlscoped-dynamic14.1 KB128.7 KB0.0%0.0%87.1 KB13.3 ms
    intlayerstatic5.0 KB125.8 KB50.0%0.0%8.1 KB3.2 ms
    intlayerdynamic5.0 KB118.6 KB0.0%0.0%6.3 KB3.6 ms
    @intlayer/use-intl (संगतता)dynamic7.3 KB129.7 KB0.0%0.0%9.3 KB8.7 ms

    परिणामों को कैसे समझें

    • सरल use-intl सेटअप बेस ऐप की तुलना में प्रति पेज 68.8 KB अधिक JS भेजता है।
    • dynamic मोड में, use-intl 119.4 KB पर आता है, लेकिन फिर भी 89.8% पेज लीकेज वहन करता है।
    • कंपोनेंट के स्तर पर वास्तुकला का अंतर स्पष्ट है: use-intl के साथ 76-87 KB बनाम Intlayer के साथ 6-8 KB।
    • लोकेल स्विचिंग Intlayer के साथ 2x-4x तेज़ है (3 ms बनाम 7-21 ms)।

    अंतर क्यों है? केंद्रीकृत कैटलॉग बनाम कंपाइल की गई डिक्शनरी

    next-intl क्लासिक मॉडल का पालन करता है: प्रति लोकेल एक JSON, जो getRequestConfig में लोड होता है, NextIntlClientProvider में पास होता है, और t("namespace.key") द्वारा पढ़ा जाता है।

    bash
    .
    ├── messages
       ├── en.json
       └── fr.json
    └── src
        ├── i18n
       ├── request.ts
       └── routing.ts
        ├── middleware.ts
        └── app
            └── [locale]
                ├── layout.tsx
                └── about
                    └── page.tsx
    

    रनटाइम यह नहीं जान सकता कि कोई पेज किन कुंजियों का उपयोग करेगा, इसलिए संपूर्ण कैटलॉग भेजना ही सुरक्षित डिफ़ॉल्ट है।

    Intlayer जिम्मेदारी को बदल देता है। सामग्री सीधे कंपोनेंट के बगल में घोषित की जाती है:

    bash
    .
    ├── intlayer.config.ts
    └── src
        ├── middleware.ts
        └── app
            └── [locale]
                ├── layout.tsx
                └── about
                    ├── page.tsx
                    └── page.content.ts
        └── components
            └── Counter
                ├── index.tsx
                └── index.content.ts
    

    बिल्ड समय पर, कंपाइलर देखता है कि कौन सा कंपोनेंट कौन सी डिक्शनरी इम्पोर्ट करता है, और केवल सक्रिय लोकेल के लिए उन डिक्शनरी को बंडल करता है।

    dynamic पंक्ति के आंकड़े प्राप्त करने के लिए, intlayer.config.ts में dictionary.importMode: 'dynamic' सेट करें। बंडल ऑप्टिमाइज़ेशन दस्तावेज़ देखें।

    डेवलपर अनुभव

    क्लाइंट कंपोनेंट

    next-intl

    messages/en.json
    {
      "counter": {
        "label": "Counter",
        "increment": "Increment"
      }
    }
    
    src/components/Counter.tsx
    "use client";
    
    import { useState } from "react";
    import { useTranslations, useFormatter } from "next-intl";
    
    export const Counter = () => {
      const t = useTranslations("counter");
      const format = useFormatter();
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>{format.number(count)}</p>
          <button aria-label={t("label")} onClick={() => setCount((c) => c + 1)}>
            {t("increment")}
          </button>
        </div>
      );
    };
    

    Intlayer

    src/components/Counter/index.content.ts
    import { t, type Dictionary } from "intlayer";
    
    const counterContent = {
      key: "counter",
      content: {
        label: t({ en: "Counter", fr: "Compteur" }),
        increment: t({ en: "Increment", fr: "Incrémenter" }),
      },
    } satisfies Dictionary;
    
    export default counterContent;
    
    src/components/Counter/index.tsx
    "use client";
    
    import { useState } from "react";
    import { useIntlayer } from "next-intlayer";
    import { useNumber } from "next-intlayer/format";
    
    export const Counter = () => {
      const { label, increment } = useIntlayer("counter");
      const number = useNumber();
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>{number(count)}</p>
          <button aria-label={label} onClick={() => setCount((c) => c + 1)}>
            {increment}
          </button>
        </div>
      );
    };
    

    सिंक्रोनस सर्वर कंपोनेंट

    डिज़ाइन सिस्टम के घटक (जैसे नेवबार, फूटर, कार्ड) अक्सर सर्वर कंपोनेंट होते हैं जिन्हें क्लाइंट कंपोनेंट के चिल्ड्रन के रूप में रेंडर किया जाता है, इसलिए वे async नहीं हो सकते।

    next-intl

    src/components/ServerCounter.tsx
    type ServerCounterProps = {
      t: (key: string) => string;
      formattedCount: string;
    };
    
    export const ServerCounter = ({ t, formattedCount }: ServerCounterProps) => (
      <div>
        <p>{formattedCount}</p>
        <button aria-label={t("label")}>{t("increment")}</button>
      </div>
    );
    

    Intlayer

    src/components/ServerCounter.tsx
    import { useIntlayer } from "next-intlayer/server";
    import { useNumber } from "next-intlayer/server/format";
    
    export const ServerCounter = ({ count }: { count: number }) => {
      const { label, increment } = useIntlayer("counter");
      const number = useNumber();
    
      return (
        <div>
          <p>{number(count)}</p>
          <button aria-label={label}>{increment}</button>
        </div>
      );
    };
    

    मेटाडेटा (Metadata)

    next-intl

    src/app/[locale]/about/page.tsx
    import type { Metadata } from "next";
    import { getTranslations } from "next-intl/server";
    import { routing } from "@/i18n/routing";
    
    const localizedPath = (locale: string, path: string) =>
      locale === routing.defaultLocale ? path : `/${locale}${path}`;
    
    export const generateMetadata = async ({
      params,
    }: {
      params: Promise<{ locale: string }>;
    }): Promise<Metadata> => {
      const { locale } = await params;
      const t = await getTranslations({ locale, namespace: "about" });
    
      const languages = Object.fromEntries(
        routing.locales.map((l) => [l, localizedPath(l, "/about")])
      );
    
      return {
        title: t("title"),
        description: t("description"),
        alternates: {
          canonical: localizedPath(locale, "/about"),
          languages: { ...languages, "x-default": "/about" },
        },
      };
    };
    

    Intlayer

    src/app/[locale]/about/page.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("about-metadata", locale);
      const multilingualUrls = getMultilingualUrls("/about");
    
      return {
        ...metadata,
        alternates: {
          canonical: multilingualUrls[locale as keyof typeof multilingualUrls],
          languages: { ...multilingualUrls, "x-default": "/about" },
        },
      };
    };
    

    next-intl API बनाए रखें, Intlayer का आउटपुट प्राप्त करें

    उपरोक्त बेंचमार्क परिणाम प्राप्त करने के लिए आपको अपने कंपोनेंट्स को दोबारा लिखने की आवश्यकता नहीं है। @intlayer/next-intl एक ड्रॉप-इन एडेप्टर है: यह useTranslations, getTranslations, useFormatter, t.rich() और ICU प्लुरल्स को बनाए रखता है, और उन्हें Intlayer डिक्शनरी से परोसता है।

    next.config.ts
    import type { NextConfig } from "next";
    import { createNextIntlPlugin } from "@intlayer/next-intl/plugin";
    
    const withIntlayer = createNextIntlPlugin();
    
    const nextConfig: NextConfig = {};
    
    export default withIntlayer(nextConfig);
    

    बेंचमार्क में, बिना किसी कोड परिवर्तन के, इसी ऐप का कंपैट बिल्ड प्रति पेज 153.6 KB से घटकर 147.5 KB, कंपोनेंट साइज़ 21.8 KB से घटकर 8.1 KB, और पेज लीकेज ~90% से घटकर 0% हो गया। आपकी मौजूदा messages/{locale}.json फाइलें JSON सिंक प्लगइन के माध्यम से सत्य का स्रोत बनी रह सकती हैं।

    चरण-दर-चरण प्रक्रिया के लिए next-intl माइग्रेशन गाइड देखें।

    कब किसे चुनें?

    • next-intl चुनें यदि आप Next.js समुदाय मानक चाहते हैं, ICU MessageFormat पर बहुत अधिक निर्भर हैं, आपका ऐप छोटा से मध्यम है, या आप केंद्रीकृत JSON आधारित अनुवाद प्लेटफॉर्म (Crowdin, Phrase, Lokalise...) के साथ एकीकृत हैं।
    • Intlayer चुनें यदि आप कंपोनेंट-स्कोप्ड कंटेंट, सख्त TypeScript, बिल्ड-टाइम गायब-कुंजी एरर, शून्य-प्रयास ट्री-शेकिंग और लेज़ी लोडिंग, सिंक्रोनस सर्वर कंपोनेंट्स, और बिल्ट-इन एडिटोरियल टूलिंग (विजुअल एडिटर, CMS, AI अनुवाद, MCP सर्वर) चाहते हैं।
    • @intlayer/next-intl चुनें यदि आप पहले से ही next-intl पर हैं और बिना दोबारा लिखे बंडल लाभ चाहते हैं।

    संबंधित तुलनाएँ

    GitHub STARS

    GitHub स्टार किसी प्रोजेक्ट की लोकप्रियता, सामुदायिक विश्वास और दीर्घकालिक प्रासंगिकता का एक मजबूत संकेतक हैं।

    स्टार हिस्ट्री चार्ट

    निष्कर्ष

    next-intl एक ठोस, अच्छी तरह से अनुरक्षित लाइब्रेरी है, और बेंचमार्क पुष्टि करता है कि यह Next.js पर एक अच्छा विकल्प है। लेकिन इसका केंद्रीकृत कैटलॉग मॉडल हर अनुकूलन का भार डेवलपर पर डालता है: सरल सेटअप लगभग 90% अन्य पेजों की सामग्री लीक करता है, और अकेले रनटाइम की लागत प्रत्येक पेज पर +12.6 KB gzip होती है।

    Intlayer उस काम को कंपाइलर में स्थानांतरित करता है। प्रति-कंपोनेंट डिक्शनरी, प्रति-लोकेल लेज़ी लोडिंग और अप्रयुक्त सामग्री को हटाना बिल्ड आउटपुट हैं। परिणाम: +0.3 KB प्रति पेज, 0% लीकेज, कंपोनेंट्स 3 गुना छोटे, और TanStack Start पर लोकेल स्विचिंग 2x-4x तेज़

    सभी कच्चे डेटा, परीक्षण ऐप्स और स्क्रिप्ट Benchmark Bloom रिपॉजिटरी में उपलब्ध हैं।

    अधिक विवरण के लिए 'Why Intlayer?' दस्तावेज़ देखें।

    टिप्पणियाँ

    अभी तक कोई टिप्पणी नहीं। अपने विचार साझा करने वाले पहले व्यक्ति बनें।

    संबंधित पोस्ट

    नवीनतम पोस्ट