Implemented english, hindi and bangla language integration through i18next

This commit is contained in:
2024-09-29 15:40:10 +05:30
parent dc36a9c094
commit 59fa16cf2d
17 changed files with 401 additions and 47 deletions

View File

@@ -1,5 +1,6 @@
import { Outlet } from "react-router-dom"
import Header from "./components/Header"
import Footer from "./components/Footer"
function App() {
return <div className="flex flex-col min-h-screen">
@@ -7,6 +8,7 @@ function App() {
<main className="transition-color-mode px-7 flex-grow bg-surface dark:bg-surface-dark">
<Outlet />
</main>
<Footer />
</div>
}

View File

@@ -1,14 +1,21 @@
import IpksLogo from '../assets/ipks_logo.svg';
import DarkModeToggle from './DarkModeToggle';
import LanguageSelector from './LanguageSelector';
import { useTranslation } from 'react-i18next';
function AppTitle() {
const { t } = useTranslation();
return (
<div className='flex items-center justify-between pt-3 pb-5'>
<div className='flex gap-5 items-center'>
<img src={IpksLogo} alt="IPKS Logo" className="h-16" />
<h1 className="text-title font-display font-bold">Integrated PACS Kisan Solution</h1>
<h1 className="text-title font-display font-bold">{t('appName')}</h1>
</div>
<div className='flex items-center gap-2'>
<DarkModeToggle />
<LanguageSelector />
</div>
<DarkModeToggle />
</div>
);
}

View File

@@ -1,12 +1,22 @@
import PropTypes from "prop-types";
import BannerInfoElement from "./BannerInfoElement";
import { useTranslation } from "react-i18next";
function BannerInfo({info}) {
const date = new Date().toLocaleDateString('en-IN', {month: 'long', day: '2-digit', year: 'numeric'}).split(" ");
const {t} = useTranslation();
const infoElements = Object.keys(info).map((key) => (
<BannerInfoElement key={key} title={key} description={info[key]} />
<BannerInfoElement key={key} title={t(key)} description={t(info[key])} />
))
infoElements.push(<BannerInfoElement key="date" title="Date" description={date.join(" ")} />);
infoElements.push(
<BannerInfoElement
key="date"
title={t('date')}
description={t('currentDate',{val: new Date(), formatParams: {
val: { month: 'long', day: '2-digit', year: 'numeric'},
},})}
/>
);
return (
<div className="flex justify-between pb-1">
{infoElements}

View File

@@ -0,0 +1,9 @@
function Footer() {
return (
<footer>
<p>© 2021</p>
</footer>
);
}
export default Footer;

View File

@@ -7,48 +7,38 @@ import Separator from "./Separator";
function Header() {
const userInfo = getUserInfoFromSession();
const menuItems = [
{ name: "Home", submenu: [], path: "/" },
{ name: "home", submenu: [], path: "/" },
{
name: "Module List",
name: "moduleList",
submenu: [
{name: "KCC", path: "kcc"},
{name: "Trading", path: "trading"},
{name: "Asset", path: "asset"},
{name: "Self Help Group", path: "shg"},
{name: "Deposit", path: "deposit"},
{name: "Loan", path: "loan"},
{name: "Share", path: "share"},
{name: "kcc", path: "kcc"},
{name: "trading", path: "trading"},
{name: "asset", path: "asset"},
{name: "selfHelpGroup", path: "shg"},
{name: "deposit", path: "deposit"},
{name: "loan", path: "loan"},
{name: "share", path: "share"},
],
},
{ name: "Enquiry", submenu: [{name: "Locker Enquiry", path: "locker-enquiry"}, {name: "Account Enquiry", path: "account-enquiry"}] },
{ name: "enquiry", submenu: [{name: "lockerEnquiry", path: "locker-enquiry"}, {name: "accountEnquiry", path: "account-enquiry"}] },
{
name: "Locker Operation",
name: "lockerOperation",
submenu: [
{name: "Account Creation", path: "account-creation"},
{name: "Cabinet Maintenance", path: "cabinet-maintenance"},
{name: "Locker Maintenance", path: "locker-maintenance"},
{name: "Rent/Penalty Collection", path: "rent-collection"},
{name: "Charge Management", path: "charge-management"},
{name: "Check in/out Management", path: "check-in-out"},
{name: "Account Surrender", path: "account-surrender"}
{name: "accountCreation", path: "account-creation"},
{name: "cabinetMaintenance", path: "cabinet-maintenance"},
{name: "lockerMaintenance", path: "locker-maintenance"},
{name: "rentPenaltyCollection", path: "rent-collection"},
{name: "chargeManagement", path: "charge-management"},
{name: "checkInOutManagement", path: "check-in-out"},
{name: "accountSurrender", path: "account-surrender"}
],
},
{ name: "worklist", submenu: [{name:"myIntimation", path: "my-intimation"}] },
{
name: "Reports",
submenu: [
{name: "Deposit Report", path: "deposit-report"},
{name: "Trial Balance Report", path: "trial-report"},
{name: "Deposit Return Report", path: "deposit-return-report"},
{name: "Account Statement Reports", path: "account-statement-report"},
{name: "Audit Reports", path: "audit-reports"}
],
name: "userManagement",
submenu: [{name: "resetLogin", path: "reset-login"}, {name: "changePassword", path: "change-password"}],
},
{ name: "Worklist", submenu: [{name:"My Intimation", path: "my-intimation"}] },
{
name: "User Management",
submenu: [{name: "Reset Loggen In Status", path: "reset-login"}, {name: "Change Password", path: "change-password"}],
},
{ name: "Log Out", submenu: [] },
{ name: "logout", submenu: [] },
];
return (

View File

@@ -0,0 +1,21 @@
import { useTranslation } from 'react-i18next';
const LanguageSelector = () => {
const { i18n } = useTranslation();
const changeLanguage = (event) => {
i18n.changeLanguage(event.target.value);
};
return (
<div>
<select className='rounded-md bg-secondary dark:bg-secondary-dark focus:outline-none' id="language-select" onChange={changeLanguage} value={i18n.language}>
<option value="en">English</option>
<option value="bn"></option>
<option value="hi">ि</option>
</select>
</div>
);
};
export default LanguageSelector;

View File

@@ -1,15 +1,17 @@
import { Link } from "react-router-dom";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
const SubMenu = ({ items }) => {
const {t} = useTranslation();
return (
<div className="
hidden absolute top-full left-0 border-t-3 border-primary dark:border-primary-dark bg-secondary
dark:bg-secondary-dark rounded-2xl shadow-sm shadow-surface-variant-dark dark:shadow-primary group-hover:block z-10"
>
{items.map((subItem, index) => (
<div key={index} className="px-6 py-2 text-nowrap hover:bg-white dark:hover:bg-secondary-variant-dark cursor-pointer first:rounded-t-2xl last:rounded-b-2xl first:pt-4 last:pb-4">
<Link to={subItem.path}>{subItem.name}</Link>
<div key={index} className="px-6 py-2 text-nowrap hover:bg-white dark:hover:bg-secondary-variant-dark cursor-pointer first:rounded-t-2xl second-last:rounded-b-2xl first:pt-4 last:pb-4">
<Link to={subItem.path}>{t(subItem.name)}</Link>
</div>
))}
<svg className="absolute top-0 left-6 mt-[-13px] fill-primary dark:fill-primary-dark" width="16" height="13" viewBox="0 0 16 13" xmlns="http://www.w3.org/2000/svg">
@@ -20,11 +22,12 @@ const SubMenu = ({ items }) => {
};
function MenuBar({ menuItems }) {
const {t} = useTranslation();
return (
<div className="flex justify-between text-base pt-5 pb-2 font-body">
{menuItems.map((item, index) =>
<div key={index} className="group relative pb-3 cursor-pointer">
{item.name}
{t(item.name)}
{item.submenu.length > 0 && <SubMenu items={item.submenu} />}
</div>
)}

19
src/i18n.js Normal file
View File

@@ -0,0 +1,19 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
fallbackLng: 'en',
interpolation: { escapeValue: false},
debug: true,
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
},
});
export default i18n;

View File

@@ -1,4 +1,5 @@
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&family=Rubik:ital,wght@0,300..900;1,300..900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Bengali:wght@100..900&family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -17,4 +18,10 @@
transition-property: background-color, color, border-color;
transition-duration: var(--transition-duration);
}
}
}
@layer utilities {
.second-last-child {
@apply nth-last-child(2);
}
}

View File

@@ -2,6 +2,7 @@ import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'
import './i18n'
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Placeholder from './pages/Placeholder.jsx';

View File

@@ -1,9 +1,9 @@
const getUserInfoFromSession = () => {
return {
"User Name": "Rajesh Kumar",
"PACS / Bank Name": "Demo SKUS Ltd.",
"User Type": "PACS Teller",
"Module Name": "Locker",
username: "Rajesh Kumar",
pacsName: "Demo SKUS Ltd.",
userType: "pacsTeller",
moduleName: "locker",
}
}