- {getSuggestions(standard).map((s) => (
+
+ {getSuggestions(standard, t).map((s) => (
@@ -199,17 +202,17 @@ export default function StandardModal({ standard, onClose }) {
);
}
-function getSuggestions(standard) {
+function getSuggestions(standard, t) {
const base = [
- `What are the key requirements of ${standard.standard_id}?`,
- "What materials or tests are specified?",
- "What are the delivery or packaging specifications?",
+ t("modal.suggestion_keyReq", { id: standard.standard_id }),
+ t("modal.suggestion_materials"),
+ t("modal.suggestion_delivery"),
];
if (standard.key_sections?.["Chemical Requirements"]) {
- base.splice(1, 0, "Summarise the chemical requirements.");
+ base.splice(1, 0, t("modal.suggestion_chemical"));
}
if (standard.key_sections?.["Physical Requirements"] || standard.key_sections?.["Physical Requirement"]) {
- base.splice(1, 0, "What are the physical requirements?");
+ base.splice(1, 0, t("modal.suggestion_physical"));
}
return base.slice(0, 3);
}
diff --git a/web/client/src/i18n.js b/web/client/src/i18n.js
new file mode 100644
index 0000000..6e87ce0
--- /dev/null
+++ b/web/client/src/i18n.js
@@ -0,0 +1,25 @@
+import i18n from "i18next";
+import { initReactI18next } from "react-i18next";
+import LanguageDetector from "i18next-browser-languagedetector";
+
+import enTranslation from "./locales/en/translation.json";
+import hiTranslation from "./locales/hi/translation.json";
+
+i18n
+ .use(LanguageDetector)
+ .use(initReactI18next)
+ .init({
+ resources: {
+ en: { translation: enTranslation },
+ hi: { translation: hiTranslation },
+ },
+ fallbackLng: "en",
+ supportedLngs: ["en", "hi"],
+ interpolation: { escapeValue: false }, // React handles XSS
+ detection: {
+ order: ["localStorage", "navigator"],
+ caches: ["localStorage"],
+ },
+ });
+
+export default i18n;
diff --git a/web/client/src/index.css b/web/client/src/index.css
index 3d6ee52..05505a5 100644
--- a/web/client/src/index.css
+++ b/web/client/src/index.css
@@ -1,3 +1,28 @@
+/* ── Skip navigation (accessibility) ── */
+.skip-nav {
+ position: absolute;
+ left: -9999px;
+ top: auto;
+ width: 1px;
+ height: 1px;
+ overflow: hidden;
+ z-index: 9999;
+}
+.skip-nav:focus {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: auto;
+ height: auto;
+ padding: 0.75rem 1.5rem;
+ background: var(--accent, #d4530a);
+ color: #fff;
+ font-weight: 600;
+ text-decoration: none;
+ border-radius: 0 0 4px 0;
+ outline: 3px solid #fff;
+}
+
/* ── BIS SP-21 Design Tokens ── */
:root {
--accent: #d4530a;
diff --git a/web/client/src/locales/en/translation.json b/web/client/src/locales/en/translation.json
new file mode 100644
index 0000000..b658810
--- /dev/null
+++ b/web/client/src/locales/en/translation.json
@@ -0,0 +1,183 @@
+{
+ "nav": {
+ "brand": "BIS SP\u201121",
+ "standards": "Standards",
+ "categories": "Categories",
+ "recommend": "\u2746 AI Recommend",
+ "about": "About",
+ "bisPortal": "BIS Portal \u2197",
+ "openMenu": "Open menu",
+ "closeMenu": "Close menu"
+ },
+ "footer": {
+ "brand": "BIS SP\u201121",
+ "tagline": "Handbook on Building Materials\nSpecial Publication 21 : 2005",
+ "portal": "Portal",
+ "searchStandards": "Search Standards",
+ "browseCategories": "Browse Categories",
+ "about": "About",
+ "bis": "Bureau of Indian Standards",
+ "bisWebsite": "BIS Official Website",
+ "manakOnline": "Manak Online",
+ "standardsPortal": "Standards Portal",
+ "ministry": "Ministry",
+ "dpiit": "DPIIT",
+ "nationalPortal": "National Portal",
+ "copyright": "\u00a9 Bureau of Indian Standards, Ministry of Commerce & Industry, Government of India. All rights reserved.",
+ "sourceNote": "Content sourced from BIS Special Publication 21 : 2005. For official standards, refer to"
+ },
+ "home": {
+ "eyebrow": "Special Publication 21 \u00b7 2005",
+ "heroTitle": "Handbook of\nBuilding Materials",
+ "heroLead": "Indian Standards across 25 material categories \u2014 searchable, categorised, and ready to reference.",
+ "searchPlaceholder": "Search standards, e.g. Portland Cement, IS 269\u2026",
+ "searchLabel": "Search standards",
+ "searchBtn": "Search",
+ "statsLabel": "Key statistics",
+ "statStandards": "IS Standards",
+ "statCategories": "Categories",
+ "statPages": "Pages Indexed",
+ "categoriesHeading": "25 Material Categories",
+ "categoriesLead": "Every building material section from SP\u201121, indexed and searchable.",
+ "aboutEyebrow": "About SP\u201121",
+ "aboutHeading": "India\u2019s Reference for Building Material Standards",
+ "aboutBody": "BIS Special Publication 21 consolidates all Indian Standards relevant to building and construction materials \u2014 from Portland cement to wire ropes, sanitary fittings to structural steels. Published by the Bureau of Indian Standards, it is the authoritative handbook used by architects, structural engineers, contractors, and quality inspectors across India.",
+ "visitBIS": "Visit BIS Portal \u2197",
+ "pillar_instantRetrieval_title": "Instant Retrieval",
+ "pillar_instantRetrieval_body": "Full-text search across all 573 standards with ranked results.",
+ "pillar_sectionDetail_title": "Section-Level Detail",
+ "pillar_sectionDetail_body": "Scope, requirements, delivery conditions \u2014 all structured fields.",
+ "pillar_categories_title": "25 Categories",
+ "pillar_categories_body": "Organised by BIS material sections, mirroring SP\u201121\u2019s own structure.",
+ "pillar_officialSource_title": "Official Source",
+ "pillar_officialSource_body": "Parsed directly from the BIS SP\u201121 : 2005 authoritative edition.",
+ "standardCount_one": "{{count}} standard",
+ "standardCount_other": "{{count}} standards"
+ },
+ "standards": {
+ "heading": "Find an IS Standard",
+ "lead": "Search by standard number, title, material, or keyword.",
+ "searchPlaceholder": "e.g. Ordinary Portland Cement, IS 269, aggregates\u2026",
+ "searchLabel": "Search standards",
+ "clearSearch": "Clear search",
+ "allCategories": "All Categories",
+ "categoryFilter": "Filter by category",
+ "searching": "Searching\u2026",
+ "found_one": "{{count}} standard found",
+ "found_other": "{{count}} standards found",
+ "page": "page {{page}} of {{total}}",
+ "noResultsTitle": "No standards found",
+ "noResultsSub": "Try a different keyword or clear the category filter.",
+ "pagination": "Results pagination",
+ "prevPage": "Previous page",
+ "nextPage": "Next page",
+ "pageLabel": "Page {{page}}",
+ "serverError": "Could not load standards. Is the server running?"
+ },
+ "categories": {
+ "eyebrow": "SP\u201121 : 2005",
+ "heading": "Material Categories",
+ "lead_one": "{{total}} standards across {{count}} building material section.",
+ "lead_other": "{{total}} standards across {{count}} building material sections.",
+ "standardCount": "{{count}} standards",
+ "allLabel": "All categories"
+ },
+ "recommend": {
+ "eyebrow": "Hybrid Retrieval \u00b7 AI Explanation",
+ "heading": "Find & Understand Standards",
+ "lead": "Ask a natural language question \u2014 the system retrieves the most relevant IS standards using dense + sparse search, then explains each in plain English.",
+ "searchPlaceholder": "e.g. What standard covers tensile strength of structural steel?",
+ "searchLabel": "Search query",
+ "clearBtn": "Clear",
+ "rewriteLabel": "Smart query rewrite",
+ "rewriteHint": "AI refines your query before searching",
+ "submitBtn": "Find Standards",
+ "submitting": "Searching\u2026",
+ "exampleLabel": "Try an example:",
+ "loadingRetrieval": "Running hybrid retrieval (FAISS + BM25)\u2026",
+ "loadingAI": "Generating AI explanations\u2026",
+ "resultsFound_one": "{{count}} Standard Found",
+ "resultsFound_other": "{{count}} Standards Found",
+ "resultsFor": "for:",
+ "timingLabel": "Timing breakdown",
+ "retrieval": "Retrieval",
+ "ai": "AI",
+ "total": "Total",
+ "rankLabel": "Rank {{rank}}: {{id}}",
+ "section": "\u00a7 {{section}}",
+ "aiExplanation": "AI explanation",
+ "keywords": "Keywords",
+ "relevanceScore": "Relevance score {{score}}",
+ "viewStandard": "View standard details",
+ "error_prefix": "Error:"
+ },
+ "about": {
+ "eyebrow": "Bureau of Indian Standards",
+ "heading": "About BIS SP\u201121",
+ "lead": "India\u2019s authoritative handbook on building and construction material standards.",
+ "aboutLabel": "About the publication",
+ "whatTitle": "What is SP\u201121?",
+ "whatBody1": "BIS Special Publication 21 \u2014 Handbook on Building Materials \u2014 is a consolidated reference published by the Bureau of Indian Standards. It brings together all Indian Standards relevant to construction and building materials into a single, organised document.",
+ "whatBody2": "The 2005 edition (the basis of this portal) spans 929 pages across 25 material sections, covering everything from cement and structural steel to timber, paints, sanitary fittings, wire ropes, and thermal insulation.",
+ "whoTitle": "Who uses it?",
+ "whoBody": "SP\u201121 is used daily by structural engineers specifying materials, architects selecting finishes, contractors verifying supplier compliance, quality inspectors conducting audits, and procurement officers evaluating bids. It is the single source of truth for which IS standard governs a given building product.",
+ "portalTitle": "About this portal",
+ "portalBody1": "This portal parses the SP\u201121 : 2005 source document into 573 discrete IS standards with structured fields \u2014 standard ID, title, material category, scope summary, key sections (Requirements, Delivery, Manufacture, etc.), and TF-IDF keywords. Every record is full-text searchable and filterable by category.",
+ "portalBody2": "The parser uses a two-pass boundary detection algorithm to split the PDF\u2019s continuous text into individual standards, with deduplication, section normalisation, and contamination detection to ensure clean, reliable data.",
+ "sidebarPubDetails": "Publication Details",
+ "publisher": "Publisher",
+ "publisherValue": "Bureau of Indian Standards",
+ "edition": "Edition",
+ "editionValue": "SP 21 : 2005",
+ "pages": "Pages",
+ "pagesValue": "929",
+ "standardsIndexed": "Standards indexed",
+ "standardsIndexedValue": "573",
+ "categoriesLabel": "Categories",
+ "categoriesValue": "25",
+ "ministry": "Ministry",
+ "ministryValue": "DPIIT, Govt. of India",
+ "officialLinks": "Official Links",
+ "bisWebsite": "BIS Official Website",
+ "manakOnline": "Manak Online",
+ "standardsPortal": "Standards Portal",
+ "dpiit": "DPIIT"
+ },
+ "modal": {
+ "closeLabel": "Close standard detail",
+ "summary": "Summary",
+ "keywords": "Keywords",
+ "keySections": "Key Sections",
+ "askAI": "Ask AI about this standard",
+ "conversation": "Conversation",
+ "aiResponse": "AI response",
+ "aiThinking": "AI is thinking",
+ "suggestionsLabel": "Suggested questions",
+ "chatPlaceholder": "Ask a question about this standard\u2026",
+ "questionLabel": "Your question",
+ "sendLabel": "Send question",
+ "sending": "\u2026",
+ "askBtn": "Ask",
+ "notFound": "No content found for this standard.",
+ "suggestion_keyReq": "What are the key requirements of {{id}}?",
+ "suggestion_materials": "What materials or tests are specified?",
+ "suggestion_delivery": "What are the delivery or packaging specifications?",
+ "suggestion_chemical": "Summarise the chemical requirements.",
+ "suggestion_physical": "What are the physical requirements?"
+ },
+ "card": {
+ "viewDetails": "View details for {{id}}",
+ "section_one": "{{count}} section",
+ "section_other": "{{count}} sections",
+ "keywords": "Keywords"
+ },
+ "common": {
+ "serverError": "Could not connect to the server.",
+ "loading": "Loading\u2026"
+ },
+ "lang": {
+ "en": "English",
+ "hi": "\u0939\u093f\u0928\u094d\u0926\u0940",
+ "switchTo": "Switch language"
+ }
+}
diff --git a/web/client/src/locales/hi/translation.json b/web/client/src/locales/hi/translation.json
new file mode 100644
index 0000000..52318c0
--- /dev/null
+++ b/web/client/src/locales/hi/translation.json
@@ -0,0 +1,183 @@
+{
+ "nav": {
+ "brand": "BIS SP\u201121",
+ "standards": "\u092e\u093e\u0928\u0915",
+ "categories": "\u0936\u094d\u0930\u0947\u0923\u093f\u092f\u093e\u0901",
+ "recommend": "\u2746 AI \u0905\u0928\u0941\u0936\u0902\u0938\u093e",
+ "about": "\u0939\u092e\u093e\u0930\u0947 \u092c\u093e\u0930\u0947 \u092e\u0947\u0902",
+ "bisPortal": "BIS \u092a\u094b\u0930\u094d\u091f\u0932 \u2197",
+ "openMenu": "\u092e\u0947\u0928\u0942 \u0916\u094b\u0932\u0947\u0902",
+ "closeMenu": "\u092e\u0947\u0928\u0942 \u092c\u0902\u0926 \u0915\u0930\u0947\u0902"
+ },
+ "footer": {
+ "brand": "BIS SP\u201121",
+ "tagline": "\u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u092a\u0941\u0938\u094d\u0924\u093f\u0915\u093e\nSP 21 : 2005",
+ "portal": "\u092a\u094b\u0930\u094d\u091f\u0932",
+ "searchStandards": "\u092e\u093e\u0928\u0915 \u0916\u094b\u091c\u0947\u0902",
+ "browseCategories": "\u0936\u094d\u0930\u0947\u0923\u093f\u092f\u093e\u0901 \u0926\u0947\u0916\u0947\u0902",
+ "about": "\u0939\u092e\u093e\u0930\u0947 \u092c\u093e\u0930\u0947 \u092e\u0947\u0902",
+ "bis": "\u092d\u093e\u0930\u0924\u0940\u092f \u092e\u093e\u0928\u0915 \u092c\u094d\u092f\u0942\u0930\u094b",
+ "bisWebsite": "BIS \u0906\u0927\u093f\u0915\u093e\u0930\u093f\u0915 \u0935\u0947\u092c\u0938\u093e\u0907\u091f",
+ "manakOnline": "\u092e\u093e\u0928\u0915 \u0911\u0928\u0932\u093e\u0907\u0928",
+ "standardsPortal": "\u092e\u093e\u0928\u0915 \u092a\u094b\u0930\u094d\u091f\u0932",
+ "ministry": "\u092e\u0902\u0924\u094d\u0930\u093e\u0932\u092f",
+ "dpiit": "DPIIT",
+ "nationalPortal": "\u0930\u093e\u0937\u094d\u091f\u094d\u0930\u0940\u092f \u092a\u094b\u0930\u094d\u091f\u0932",
+ "copyright": "\u00a9 \u092d\u093e\u0930\u0924\u0940\u092f \u092e\u093e\u0928\u0915 \u092c\u094d\u092f\u0942\u0930\u094b, \u0935\u093e\u0923\u093f\u091c\u094d\u092f \u090f\u0935\u0902 \u0909\u0926\u094d\u092f\u094b\u0917 \u092e\u0902\u0924\u094d\u0930\u093e\u0932\u092f, \u092d\u093e\u0930\u0924 \u0938\u0930\u0915\u093e\u0930\u0964 \u0938\u0930\u094d\u0935\u093e\u0927\u093f\u0915\u093e\u0930 \u0938\u0941\u0930\u0915\u094d\u0937\u093f\u0924\u0964",
+ "sourceNote": "BIS SP 21 : 2005 \u0938\u0947 \u0938\u0902\u0915\u0932\u093f\u0924\u0964 \u0906\u0927\u093f\u0915\u093e\u0930\u093f\u0915 \u092e\u093e\u0928\u0915\u094b\u0902 \u0915\u0947 \u0932\u093f\u090f \u0926\u0947\u0916\u0947\u0902"
+ },
+ "home": {
+ "eyebrow": "\u0935\u093f\u0936\u0947\u0937 \u092a\u094d\u0930\u0915\u093e\u0936\u0928 21 \u00b7 2005",
+ "heroTitle": "\u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0938\u093e\u092e\u0917\u094d\u0930\u0940\u0915\u093e \u0939\u0938\u094d\u0924\u092a\u0941\u0938\u094d\u0924\u093f\u0915\u093e",
+ "heroLead": "25 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u0936\u094d\u0930\u0947\u0923\u093f\u092f\u094b\u0902 \u092e\u0947\u0902 \u092d\u093e\u0930\u0924\u0940\u092f \u092e\u093e\u0928\u0915 \u2014 \u0916\u094b\u091c\u092f\u094b\u0917\u094d\u092f, \u0935\u0930\u094d\u0917\u0940\u0915\u0943\u0924 \u0914\u0930 \u0938\u0902\u0926\u0930\u094d\u092d \u0915\u0947 \u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930\u0964",
+ "searchPlaceholder": "\u092e\u093e\u0928\u0915 \u0916\u094b\u091c\u0947\u0902, \u091c\u0948\u0938\u0947 Portland Cement, IS 269\u2026",
+ "searchLabel": "\u092e\u093e\u0928\u0915 \u0916\u094b\u091c\u0947\u0902",
+ "searchBtn": "\u0916\u094b\u091c\u0947\u0902",
+ "statsLabel": "\u092e\u0941\u0916\u094d\u092f \u0906\u0902\u0915\u095c\u0947",
+ "statStandards": "IS \u092e\u093e\u0928\u0915",
+ "statCategories": "\u0936\u094d\u0930\u0947\u0923\u093f\u092f\u093e\u0901",
+ "statPages": "\u0938\u0942\u091a\u0940\u092c\u0926\u094d\u0927 \u092a\u0943\u0937\u094d\u0920",
+ "categoriesHeading": "25 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u0936\u094d\u0930\u0947\u0923\u093f\u092f\u093e\u0901",
+ "categoriesLead": "SP\u201121 \u0915\u0940 \u0939\u0930 \u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u0936\u094d\u0930\u0947\u0923\u0940, \u0938\u0942\u091a\u0940\u092c\u0926\u094d\u0927 \u0914\u0930 \u0916\u094b\u091c\u092f\u094b\u0917\u094d\u092f\u0964",
+ "aboutEyebrow": "SP\u201121 \u0915\u0947 \u092c\u093e\u0930\u0947 \u092e\u0947\u0902",
+ "aboutHeading": "\u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u092e\u093e\u0928\u0915\u094b\u0902 \u0915\u093e \u092d\u093e\u0930\u0924\u0940\u092f \u0938\u0902\u0926\u0930\u094d\u092d",
+ "aboutBody": "BIS \u0935\u093f\u0936\u0947\u0937 \u092a\u094d\u0930\u0915\u093e\u0936\u0928 21 \u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0914\u0930 \u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0938\u093e\u092e\u0917\u094d\u0930\u093f\u092f\u094b\u0902 \u0938\u0947 \u0938\u0902\u092c\u0902\u0927\u093f\u0924 \u0938\u092d\u0940 IS \u092e\u093e\u0928\u0915\u094b\u0902 \u0915\u094b \u090f\u0915\u0924\u094d\u0930 \u0915\u0930\u0924\u093e \u0939\u0948\u0964",
+ "visitBIS": "BIS \u092a\u094b\u0930\u094d\u091f\u0932 \u0926\u0947\u0916\u0947\u0902 \u2197",
+ "pillar_instantRetrieval_title": "\u0924\u0924\u094d\u0915\u093e\u0932 \u0916\u094b\u091c",
+ "pillar_instantRetrieval_body": "\u0938\u092d\u0940 573 \u092e\u093e\u0928\u0915\u094b\u0902 \u092e\u0947\u0902 \u092a\u0942\u0930\u094d\u0923-\u092a\u093e\u0920 \u0916\u094b\u091c \u0930\u0948\u0902\u0915\u093f\u0902\u0917 \u092a\u0930\u093f\u0923\u093e\u092e\u094b\u0902 \u0915\u0947 \u0938\u093e\u0925\u0964",
+ "pillar_sectionDetail_title": "\u0927\u093e\u0930\u093e-\u0938\u094d\u0924\u0930\u0940\u092f \u0935\u093f\u0935\u0930\u0923",
+ "pillar_sectionDetail_body": "\u0915\u094d\u0937\u0947\u0924\u094d\u0930, \u0906\u0935\u0936\u094d\u092f\u0915\u0924\u093e\u090f\u0901, \u0921\u093f\u0932\u0940\u0935\u0930\u0940 \u0936\u0930\u094d\u0924\u0947\u0902 \u2014 \u0938\u092d\u0940 \u0938\u0902\u0930\u091a\u093f\u0924 \u092b\u093c\u0940\u0932\u094d\u0921\u0964",
+ "pillar_categories_title": "25 \u0936\u094d\u0930\u0947\u0923\u093f\u092f\u093e\u0901",
+ "pillar_categories_body": "BIS \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u0916\u0902\u0921\u094b\u0902 \u0926\u094d\u0935\u093e\u0930\u093e \u0935\u094d\u092f\u0935\u0938\u094d\u0925\u093f\u0924, SP\u201121 \u0915\u0940 \u0905\u092a\u0928\u0940 \u0938\u0902\u0930\u091a\u0928\u093e \u0915\u093e \u0905\u0928\u0941\u0938\u0930\u0923\u0964",
+ "pillar_officialSource_title": "\u0906\u0927\u093f\u0915\u093e\u0930\u093f\u0915 \u0938\u094d\u0930\u094b\u0924",
+ "pillar_officialSource_body": "BIS SP\u201121 : 2005 \u0938\u0947 \u0938\u0940\u0927\u0947 \u092a\u093e\u0930\u094d\u0938 \u0915\u093f\u092f\u093e \u0917\u092f\u093e\u0964",
+ "standardCount_one": "{{count}} \u092e\u093e\u0928\u0915",
+ "standardCount_other": "{{count}} \u092e\u093e\u0928\u0915"
+ },
+ "standards": {
+ "heading": "IS \u092e\u093e\u0928\u0915 \u0916\u094b\u091c\u0947\u0902",
+ "lead": "\u092e\u093e\u0928\u0915 \u0938\u0902\u0916\u094d\u092f\u093e, \u0936\u0940\u0930\u094d\u0937\u0915, \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u092f\u093e \u0915\u0940\u0935\u0930\u094d\u0921 \u0926\u094d\u0935\u093e\u0930\u093e \u0916\u094b\u091c\u0947\u0902\u0964",
+ "searchPlaceholder": "\u091c\u0948\u0938\u0947 Ordinary Portland Cement, IS 269\u2026",
+ "searchLabel": "\u092e\u093e\u0928\u0915 \u0916\u094b\u091c\u0947\u0902",
+ "clearSearch": "\u0916\u094b\u091c \u0938\u093e\u092b\u093c \u0915\u0930\u0947\u0902",
+ "allCategories": "\u0938\u092d\u0940 \u0936\u094d\u0930\u0947\u0923\u093f\u092f\u093e\u0901",
+ "categoryFilter": "\u0936\u094d\u0930\u0947\u0923\u0940 \u0938\u0947 \u092b\u093c\u093f\u0932\u094d\u091f\u0930 \u0915\u0930\u0947\u0902",
+ "searching": "\u0916\u094b\u091c \u091c\u093e\u0930\u0940\u2026",
+ "found_one": "{{count}} \u092e\u093e\u0928\u0915 \u092e\u093f\u0932\u093e",
+ "found_other": "{{count}} \u092e\u093e\u0928\u0915 \u092e\u093f\u0932\u0947",
+ "page": "\u092a\u0943\u0937\u094d\u0920 {{page}} / {{total}}",
+ "noResultsTitle": "\u0915\u094b\u0908 \u092e\u093e\u0928\u0915 \u0928\u0939\u0940\u0902 \u092e\u093f\u0932\u093e",
+ "noResultsSub": "\u0905\u0932\u0917 \u0915\u0940\u0935\u0930\u094d\u0921 \u0906\u091c\u093c\u092e\u093e\u090f\u0901 \u092f\u093e \u0936\u094d\u0930\u0947\u0923\u0940 \u092b\u093c\u093f\u0932\u094d\u091f\u0930 \u0939\u091f\u093e\u090f\u0902\u0964",
+ "pagination": "\u092a\u0930\u093f\u0923\u093e\u092e \u092a\u0943\u0937\u094d\u0920\u093e\u0902\u0915\u0928",
+ "prevPage": "\u092a\u093f\u091b\u0932\u093e \u092a\u0943\u0937\u094d\u0920",
+ "nextPage": "\u0905\u0917\u0932\u093e \u092a\u0943\u0937\u094d\u0920",
+ "pageLabel": "\u092a\u0943\u0937\u094d\u0920 {{page}}",
+ "serverError": "\u092e\u093e\u0928\u0915 \u0932\u094b\u0921 \u0928\u0939\u0940\u0902 \u0939\u094b \u0938\u0915\u0947\u0964 \u0915\u094d\u092f\u093e \u0938\u0930\u094d\u0935\u0930 \u091a\u0932 \u0930\u0939\u093e \u0939\u0948?"
+ },
+ "categories": {
+ "eyebrow": "SP\u201121 : 2005",
+ "heading": "\u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u0936\u094d\u0930\u0947\u0923\u093f\u092f\u093e\u0901",
+ "lead_one": "{{count}} \u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u0916\u0902\u0921 \u092e\u0947\u0902 {{total}} \u092e\u093e\u0928\u0915\u0964",
+ "lead_other": "{{count}} \u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u0916\u0902\u0921\u094b\u0902 \u092e\u0947\u0902 {{total}} \u092e\u093e\u0928\u0915\u0964",
+ "standardCount": "{{count}} \u092e\u093e\u0928\u0915",
+ "allLabel": "\u0938\u092d\u0940 \u0936\u094d\u0930\u0947\u0923\u093f\u092f\u093e\u0901"
+ },
+ "recommend": {
+ "eyebrow": "\u0939\u093e\u0907\u092c\u094d\u0930\u093f\u0921 \u092a\u0941\u0928\u0930\u094d\u092a\u094d\u0930\u093e\u092a\u094d\u0924\u093f \u00b7 AI \u0935\u094d\u092f\u093e\u0916\u094d\u092f\u093e",
+ "heading": "\u092e\u093e\u0928\u0915 \u0916\u094b\u091c\u0947\u0902 \u0914\u0930 \u0938\u092e\u091d\u0947\u0902",
+ "lead": "\u092a\u094d\u0930\u093e\u0915\u0943\u0924\u093f\u0915 \u092d\u093e\u0937\u093e \u092e\u0947\u0902 \u092a\u0942\u091b\u0947\u0902 \u2014 \u0938\u093f\u0938\u094d\u091f\u092e dense + sparse \u0916\u094b\u091c \u0938\u0947 \u0938\u092c\u0938\u0947 \u092a\u094d\u0930\u093e\u0938\u0902\u0917\u093f\u0915 IS \u092e\u093e\u0928\u0915 \u0922\u0942\u0902\u0922\u0924\u093e \u0939\u0948\u0964",
+ "searchPlaceholder": "\u091c\u0948\u0938\u0947: \u0938\u0902\u0930\u091a\u0928\u093e\u0924\u094d\u092e\u0915 \u0938\u094d\u091f\u0940\u0932 \u0915\u0940 \u0924\u0928\u094d\u092f \u0936\u0915\u094d\u0924\u093f \u0915\u093e \u092e\u093e\u0928\u0915 \u0915\u094c\u0928 \u0938\u093e \u0939\u0948?",
+ "searchLabel": "\u0916\u094b\u091c \u092a\u094d\u0930\u0936\u094d\u0928",
+ "clearBtn": "\u0938\u093e\u092b\u093c \u0915\u0930\u0947\u0902",
+ "rewriteLabel": "\u0938\u094d\u092e\u093e\u0930\u094d\u091f \u0915\u094d\u0935\u0947\u0930\u0940 \u0930\u093f\u0930\u093e\u0907\u091f",
+ "rewriteHint": "AI \u0916\u094b\u091c \u0938\u0947 \u092a\u0939\u0932\u0947 \u0906\u092a\u0915\u0940 \u0915\u094d\u0935\u0947\u0930\u0940 \u0938\u0941\u0927\u093e\u0930\u0924\u093e \u0939\u0948",
+ "submitBtn": "\u092e\u093e\u0928\u0915 \u0916\u094b\u091c\u0947\u0902",
+ "submitting": "\u0916\u094b\u091c \u091c\u093e\u0930\u0940\u2026",
+ "exampleLabel": "\u0909\u0926\u093e\u0939\u0930\u0923 \u0906\u091c\u093c\u092e\u093e\u090f\u0901:",
+ "loadingRetrieval": "\u0939\u093e\u0907\u092c\u094d\u0930\u093f\u0921 \u0916\u094b\u091c \u091a\u0932 \u0930\u0939\u0940 \u0939\u0948 (FAISS + BM25)\u2026",
+ "loadingAI": "AI \u0935\u094d\u092f\u093e\u0916\u094d\u092f\u093e \u0924\u0948\u092f\u093e\u0930 \u0939\u094b \u0930\u0939\u0940 \u0939\u0948\u2026",
+ "resultsFound_one": "{{count}} \u092e\u093e\u0928\u0915 \u092e\u093f\u0932\u093e",
+ "resultsFound_other": "{{count}} \u092e\u093e\u0928\u0915 \u092e\u093f\u0932\u0947",
+ "resultsFor": "\u0916\u094b\u091c:",
+ "timingLabel": "\u0938\u092e\u092f \u0935\u093f\u0935\u0930\u0923",
+ "retrieval": "\u0916\u094b\u091c",
+ "ai": "AI",
+ "total": "\u0915\u0941\u0932",
+ "rankLabel": "\u0930\u0948\u0902\u0915 {{rank}}: {{id}}",
+ "section": "\u00a7 {{section}}",
+ "aiExplanation": "AI \u0935\u094d\u092f\u093e\u0916\u094d\u092f\u093e",
+ "keywords": "\u0915\u0940\u0935\u0930\u094d\u0921",
+ "relevanceScore": "\u092a\u094d\u0930\u093e\u0938\u0902\u0917\u093f\u0915\u0924\u093e \u0938\u094d\u0915\u094b\u0930 {{score}}",
+ "viewStandard": "\u092e\u093e\u0928\u0915 \u0935\u093f\u0935\u0930\u0923 \u0926\u0947\u0916\u0947\u0902",
+ "error_prefix": "\u0924\u094d\u0930\u0941\u091f\u093f:"
+ },
+ "about": {
+ "eyebrow": "\u092d\u093e\u0930\u0924\u0940\u092f \u092e\u093e\u0928\u0915 \u092c\u094d\u092f\u0942\u0930\u094b",
+ "heading": "BIS SP\u201121 \u0915\u0947 \u092c\u093e\u0930\u0947 \u092e\u0947\u0902",
+ "lead": "\u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u092e\u093e\u0928\u0915\u094b\u0902 \u092a\u0930 \u092d\u093e\u0930\u0924 \u0915\u0940 \u0906\u0927\u093f\u0915\u093e\u0930\u093f\u0915 \u092a\u0941\u0938\u094d\u0924\u093f\u0915\u093e\u0964",
+ "aboutLabel": "\u092a\u094d\u0930\u0915\u093e\u0936\u0928 \u0915\u0947 \u092c\u093e\u0930\u0947 \u092e\u0947\u0902",
+ "whatTitle": "SP\u201121 \u0915\u094d\u092f\u093e \u0939\u0948?",
+ "whatBody1": "BIS \u0935\u093f\u0936\u0947\u0937 \u092a\u094d\u0930\u0915\u093e\u0936\u0928 21 \u2014 \u0928\u093f\u0930\u094d\u092e\u093e\u0923 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u092a\u0941\u0938\u094d\u0924\u093f\u0915\u093e \u2014 \u092d\u093e\u0930\u0924\u0940\u092f \u092e\u093e\u0928\u0915 \u092c\u094d\u092f\u0942\u0930\u094b \u0926\u094d\u0935\u093e\u0930\u093e \u092a\u094d\u0930\u0915\u093e\u0936\u093f\u0924 \u090f\u0915 \u0938\u0902\u092f\u0941\u0915\u094d\u0924 \u0938\u0902\u0926\u0930\u094d\u092d \u0939\u0948\u0964",
+ "whatBody2": "2005 \u0938\u0902\u0938\u094d\u0915\u0930\u0923 25 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u0916\u0902\u0921\u094b\u0902 \u092e\u0947\u0902 929 \u092a\u0943\u0937\u094d\u0920 \u0915\u0935\u0930 \u0915\u0930\u0924\u093e \u0939\u0948\u0964",
+ "whoTitle": "\u0907\u0938\u0947 \u0915\u094c\u0928 \u0909\u092a\u092f\u094b\u0917 \u0915\u0930\u0924\u093e \u0939\u0948?",
+ "whoBody": "SP\u201121 \u0915\u093e \u0909\u092a\u092f\u094b\u0917 \u0938\u0902\u0930\u091a\u0928\u093e\u0924\u094d\u092e\u0915 \u0907\u0902\u091c\u0940\u0928\u093f\u092f\u0930, \u0935\u093e\u0938\u094d\u0924\u0941\u0915\u093e\u0930, \u0920\u0947\u0915\u0947\u0926\u093e\u0930, \u0917\u0941\u0923\u0935\u0924\u094d\u0924\u093e \u0928\u093f\u0930\u0940\u0915\u094d\u0937\u0915 \u0914\u0930 \u0916\u0930\u0940\u0926 \u0905\u0927\u093f\u0915\u093e\u0930\u0940 \u0915\u0930\u0924\u0947 \u0939\u0948\u0902\u0964",
+ "portalTitle": "\u0907\u0938 \u092a\u094b\u0930\u094d\u091f\u0932 \u0915\u0947 \u092c\u093e\u0930\u0947 \u092e\u0947\u0902",
+ "portalBody1": "\u092f\u0939 \u092a\u094b\u0930\u094d\u091f\u0932 SP\u201121 : 2005 \u0915\u094b 573 IS \u092e\u093e\u0928\u0915\u094b\u0902 \u092e\u0947\u0902 \u092a\u093e\u0930\u094d\u0938 \u0915\u0930\u0924\u093e \u0939\u0948\u0964",
+ "portalBody2": "\u092a\u093e\u0930\u094d\u0938\u0930 \u0926\u094b-\u092a\u093e\u0938 \u0938\u0940\u092e\u093e \u0928\u093f\u0930\u094d\u0927\u093e\u0930\u0923 \u090f\u0932\u094d\u0917\u094b\u0930\u093f\u0926\u092e \u0915\u093e \u0909\u092a\u092f\u094b\u0917 \u0915\u0930\u0924\u093e \u0939\u0948\u0964",
+ "sidebarPubDetails": "\u092a\u094d\u0930\u0915\u093e\u0936\u0928 \u0935\u093f\u0935\u0930\u0923",
+ "publisher": "\u092a\u094d\u0930\u0915\u093e\u0936\u0915",
+ "publisherValue": "\u092d\u093e\u0930\u0924\u0940\u092f \u092e\u093e\u0928\u0915 \u092c\u094d\u092f\u0942\u0930\u094b",
+ "edition": "\u0938\u0902\u0938\u094d\u0915\u0930\u0923",
+ "editionValue": "SP 21 : 2005",
+ "pages": "\u092a\u0943\u0937\u094d\u0920",
+ "pagesValue": "929",
+ "standardsIndexed": "\u0938\u0942\u091a\u0940\u092c\u0926\u094d\u0927 \u092e\u093e\u0928\u0915",
+ "standardsIndexedValue": "573",
+ "categoriesLabel": "\u0936\u094d\u0930\u0947\u0923\u093f\u092f\u093e\u0901",
+ "categoriesValue": "25",
+ "ministry": "\u092e\u0902\u0924\u094d\u0930\u093e\u0932\u092f",
+ "ministryValue": "DPIIT, \u092d\u093e\u0930\u0924 \u0938\u0930\u0915\u093e\u0930",
+ "officialLinks": "\u0906\u0927\u093f\u0915\u093e\u0930\u093f\u0915 \u0932\u093f\u0902\u0915",
+ "bisWebsite": "BIS \u0906\u0927\u093f\u0915\u093e\u0930\u093f\u0915 \u0935\u0947\u092c\u0938\u093e\u0907\u091f",
+ "manakOnline": "\u092e\u093e\u0928\u0915 \u0911\u0928\u0932\u093e\u0907\u0928",
+ "standardsPortal": "\u092e\u093e\u0928\u0915 \u092a\u094b\u0930\u094d\u091f\u0932",
+ "dpiit": "DPIIT"
+ },
+ "modal": {
+ "closeLabel": "\u092e\u093e\u0928\u0915 \u0935\u093f\u0935\u0930\u0923 \u092c\u0902\u0926 \u0915\u0930\u0947\u0902",
+ "summary": "\u0938\u093e\u0930\u093e\u0902\u0936",
+ "keywords": "\u0915\u0940\u0935\u0930\u094d\u0921",
+ "keySections": "\u092e\u0941\u0916\u094d\u092f \u0927\u093e\u0930\u093e\u090f\u0901",
+ "askAI": "\u0907\u0938 \u092e\u093e\u0928\u0915 \u0915\u0947 \u092c\u093e\u0930\u0947 \u092e\u0947\u0902 AI \u0938\u0947 \u092a\u0942\u091b\u0947\u0902",
+ "conversation": "\u0935\u093e\u0930\u094d\u0924\u093e\u0932\u093e\u092a",
+ "aiResponse": "AI \u0909\u0924\u094d\u0924\u0930",
+ "aiThinking": "AI \u0938\u094b\u091a \u0930\u0939\u093e \u0939\u0948",
+ "suggestionsLabel": "\u0938\u0941\u091d\u093e\u090f \u0917\u090f \u092a\u094d\u0930\u0936\u094d\u0928",
+ "chatPlaceholder": "\u0907\u0938 \u092e\u093e\u0928\u0915 \u0915\u0947 \u092c\u093e\u0930\u0947 \u092e\u0947\u0902 \u092a\u094d\u0930\u0936\u094d\u0928 \u092a\u0942\u091b\u0947\u0902\u2026",
+ "questionLabel": "\u0906\u092a\u0915\u093e \u092a\u094d\u0930\u0936\u094d\u0928",
+ "sendLabel": "\u092a\u094d\u0930\u0936\u094d\u0928 \u092d\u0947\u091c\u0947\u0902",
+ "sending": "\u2026",
+ "askBtn": "\u092a\u0942\u091b\u0947\u0902",
+ "notFound": "\u0907\u0938 \u092e\u093e\u0928\u0915 \u092e\u0947\u0902 \u0938\u093e\u092e\u0917\u094d\u0930\u0940 \u0928\u0939\u0940\u0902 \u092e\u093f\u0932\u0940\u0964",
+ "suggestion_keyReq": "{{id}} \u0915\u0940 \u092e\u0941\u0916\u094d\u092f \u0906\u0935\u0936\u094d\u092f\u0915\u0924\u093e\u090f\u0901 \u0915\u094d\u092f\u093e \u0939\u0948\u0902?",
+ "suggestion_materials": "\u0915\u094c\u0928 \u0938\u0940 \u0938\u093e\u092e\u0917\u094d\u0930\u093f\u092f\u093e\u0901 \u092f\u093e \u092a\u0930\u0940\u0915\u094d\u0937\u0923 \u0928\u093f\u0930\u094d\u0926\u093f\u0937\u094d\u091f \u0939\u0948\u0902?",
+ "suggestion_delivery": "\u0921\u093f\u0932\u0940\u0935\u0930\u0940 \u092f\u093e \u092a\u0948\u0915\u0947\u091c\u093f\u0902\u0917 \u0935\u093f\u0936\u093f\u0937\u094d\u091f\u0924\u093e\u090f\u0901 \u0915\u094d\u092f\u093e \u0939\u0948\u0902?",
+ "suggestion_chemical": "\u0930\u093e\u0938\u093e\u092f\u0928\u093f\u0915 \u0906\u0935\u0936\u094d\u092f\u0915\u0924\u093e\u0913\u0902 \u0915\u093e \u0938\u093e\u0930\u093e\u0902\u0936 \u0926\u0947\u0902\u0964",
+ "suggestion_physical": "\u092d\u094c\u0924\u093f\u0915 \u0906\u0935\u0936\u094d\u092f\u0915\u0924\u093e\u090f\u0901 \u0915\u094d\u092f\u093a \u0939\u0948\u0902?"
+ },
+ "card": {
+ "viewDetails": "{{id}} \u0915\u093e \u0935\u093f\u0935\u0930\u0923 \u0926\u0947\u0916\u0947\u0902",
+ "section_one": "{{count}} \u0927\u093e\u0930\u093e",
+ "section_other": "{{count}} \u0927\u093e\u0930\u093e\u090f\u0901",
+ "keywords": "\u0915\u0940\u0935\u0930\u094d\u0921"
+ },
+ "common": {
+ "serverError": "\u0938\u0930\u094d\u0935\u0930 \u0938\u0947 \u0915\u0928\u0947\u0915\u094d\u091f \u0928\u0939\u0940\u0902 \u0939\u094b \u0938\u0915\u093e\u0964",
+ "loading": "\u0932\u094b\u0921 \u0939\u094b \u0930\u0939\u093e \u0939\u0948\u2026"
+ },
+ "lang": {
+ "en": "English",
+ "hi": "\u0939\u093f\u0928\u094d\u0926\u0940",
+ "switchTo": "\u092d\u093e\u0937\u093e \u092c\u0926\u0932\u0947\u0902"
+ }
+}
diff --git a/web/client/src/main.jsx b/web/client/src/main.jsx
index 7aed83e..400c2d2 100644
--- a/web/client/src/main.jsx
+++ b/web/client/src/main.jsx
@@ -1,6 +1,7 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
+import "./i18n.js";
import "./index.css";
import App from "./App.jsx";
diff --git a/web/client/src/pages/About.jsx b/web/client/src/pages/About.jsx
index 7787419..4a79a57 100644
--- a/web/client/src/pages/About.jsx
+++ b/web/client/src/pages/About.jsx
@@ -1,80 +1,59 @@
+import { useTranslation } from "react-i18next";
import "./About.css";
export default function About() {
+ const { t } = useTranslation();
+
return (
-
Bureau of Indian Standards
-
About BIS SP‑21
-
- India's authoritative handbook on building and construction material standards.
-
+
{t("about.eyebrow")}
+
{t("about.heading")}
+
{t("about.lead")}
-
+
-
What is SP‑21?
-
- BIS Special Publication 21 — Handbook on Building Materials — is a consolidated
- reference published by the Bureau of Indian Standards. It brings together all Indian
- Standards relevant to construction and building materials into a single, organised document.
-
-
- The 2005 edition (the basis of this portal) spans 929 pages across 25 material sections,
- covering everything from cement and structural steel to timber, paints, sanitary fittings,
- wire ropes, and thermal insulation.
-
+
{t("about.whatTitle")}
+
{t("about.whatBody1")}
+
{t("about.whatBody2")}
-
Who uses it?
-
- SP‑21 is used daily by structural engineers specifying materials, architects selecting
- finishes, contractors verifying supplier compliance, quality inspectors conducting audits,
- and procurement officers evaluating bids. It is the single source of truth for which IS
- standard governs a given building product.
-
+
{t("about.whoTitle")}
+
{t("about.whoBody")}
-
About this portal
-
- This portal parses the SP‑21 : 2005 source document into 573 discrete IS standards with
- structured fields — standard ID, title, material category, scope summary, key sections
- (Requirements, Delivery, Manufacture, etc.), and TF-IDF keywords. Every record is
- full-text searchable and filterable by category.
-
-
- The parser uses a two-pass boundary detection algorithm to split the PDF's continuous
- text into individual standards, with deduplication, section normalisation, and
- contamination detection to ensure clean, reliable data.
-
+
{t("about.portalTitle")}
+
{t("about.portalBody1")}
+
{t("about.portalBody2")}
diff --git a/web/client/src/pages/Categories.jsx b/web/client/src/pages/Categories.jsx
index 81361f4..6eb4012 100644
--- a/web/client/src/pages/Categories.jsx
+++ b/web/client/src/pages/Categories.jsx
@@ -1,5 +1,6 @@
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
+import { useTranslation } from "react-i18next";
import { fetchCategories } from "../api/standards";
import "./Categories.css";
@@ -32,6 +33,7 @@ const CATEGORY_ICONS = {
};
export default function Categories() {
+ const { t } = useTranslation();
const [categories, setCategories] = useState([]);
const [loading, setLoading] = useState(true);
const navigate = useNavigate();
@@ -49,15 +51,15 @@ export default function Categories() {
-
SP‑21 : 2005
-
Material Categories
+
{t("categories.eyebrow")}
+
{t("categories.heading")}
- {total} standards across {categories.length} building material sections.
+ {t("categories.lead", { count: categories.length, total })}
-
+
{loading ? (
@@ -78,7 +80,7 @@ export default function Categories() {
{CATEGORY_ICONS[cat.name] || "📋"}
{cat.name}
-
{cat.count} standards
+
{t("categories.standardCount", { count: cat.count })}
→
))}
diff --git a/web/client/src/pages/Home.jsx b/web/client/src/pages/Home.jsx
index 3369275..5cd8a0c 100644
--- a/web/client/src/pages/Home.jsx
+++ b/web/client/src/pages/Home.jsx
@@ -1,9 +1,11 @@
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
+import { useTranslation } from "react-i18next";
import { fetchStats, fetchCategories } from "../api/standards";
import "./Home.css";
export default function Home() {
+ const { t } = useTranslation();
const [stats, setStats] = useState(null);
const [categories, setCategories] = useState([]);
const [query, setQuery] = useState("");
@@ -20,19 +22,24 @@ export default function Home() {
else navigate("/standards");
};
+ const PILLARS = [
+ { icon: "⚡", titleKey: "home.pillar_instantRetrieval_title", bodyKey: "home.pillar_instantRetrieval_body" },
+ { icon: "📐", titleKey: "home.pillar_sectionDetail_title", bodyKey: "home.pillar_sectionDetail_body" },
+ { icon: "🗂", titleKey: "home.pillar_categories_title", bodyKey: "home.pillar_categories_body" },
+ { icon: "🔒", titleKey: "home.pillar_officialSource_title", bodyKey: "home.pillar_officialSource_body" },
+ ];
+
return (
- {/* Hero */}
-
Special Publication 21 · 2005
+
{t("home.eyebrow")}
- Handbook of
Building Materials
+ {t("home.heroTitle").split("\n").map((line, i, arr) => (
+ {line}{i < arr.length - 1 &&
}
+ ))}
-
- Indian Standards across 25 material categories —
- searchable, categorised, and ready to reference.
-
+
{t("home.heroLead")}
{stats && (
-
+
{stats.totalStandards}
- IS Standards
+ {t("home.statStandards")}
{stats.totalCategories}
- Categories
+ {t("home.statCategories")}
929
- Pages Indexed
+ {t("home.statPages")}
)}
- {/* Categories */}
-
25 Material Categories
-
Every building material section from SP‑21, indexed and searchable.
+
{t("home.categoriesHeading")}
+
{t("home.categoriesLead")}
{categories.map((cat) => (
@@ -86,43 +92,35 @@ export default function Home() {
onClick={() => navigate(`/standards?category=${encodeURIComponent(cat.name)}`)}
>
{cat.name}
- {cat.count} standard{cat.count !== 1 ? "s" : ""}
+ {t("home.standardCount", { count: cat.count })}
))}
- {/* About strip */}
-
+
-
About SP‑21
-
- India's Reference for Building Material Standards
-
-
- BIS Special Publication 21 consolidates all Indian Standards relevant to building and
- construction materials — from Portland cement to wire ropes, sanitary fittings to structural
- steels. Published by the Bureau of Indian Standards, it is the authoritative handbook used
- by architects, structural engineers, contractors, and quality inspectors across India.
-
+
{t("home.aboutEyebrow")}
+
{t("home.aboutHeading")}
+
{t("home.aboutBody")}
- Visit BIS Portal ↗
+ {t("home.visitBIS")}
- {PILLARS.map(({ icon, title, body }) => (
-
+ {PILLARS.map(({ icon, titleKey, bodyKey }) => (
+
{icon}
-
{title}
-
{body}
+
{t(titleKey)}
+
{t(bodyKey)}
))}
@@ -133,13 +131,6 @@ export default function Home() {
);
}
-const PILLARS = [
- { icon: "⚡", title: "Instant Retrieval", body: "Full-text search across all 573 standards with ranked results." },
- { icon: "📐", title: "Section-Level Detail", body: "Scope, requirements, delivery conditions — all structured fields." },
- { icon: "🗂", title: "25 Categories", body: "Organised by BIS material sections, mirroring SP‑21's own structure." },
- { icon: "🔒", title: "Official Source", body: "Parsed directly from the BIS SP‑21 : 2005 authoritative edition." },
-];
-
function SearchIcon() {
return (