- Transacted books
+ {t('transactedBooks')}
- Title
- Copies
+ {t('title')}
+ {t('copies')}
diff --git a/src/i18n.js b/src/i18n.js
new file mode 100644
index 0000000..bf0cbd7
--- /dev/null
+++ b/src/i18n.js
@@ -0,0 +1,23 @@
+import i18n from 'i18next';
+import { initReactI18next } from 'react-i18next';
+import LanguageDetector from 'i18next-browser-languagedetector';
+import Backend from 'i18next-http-backend';
+
+i18n
+ .use(initReactI18next)
+ .use(LanguageDetector)
+ .use(Backend)
+ .init({
+ fallbackLang: 'en',
+ defaultNS: 'common',
+ fallbackNS: 'common',
+ ns: ['common'],
+ interpolation: {
+ // Escaping is handled by React:
+ escapeValue: false
+ },
+ react: {
+ transSupportBasicHtmlNodes: true,
+ transKeepBasicHtmlNodesFor: ['strong', 'b']
+ }
+ });
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index 2b5bb3e..46a1cd3 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,12 +6,15 @@ import './assets/sb-admin/theme.css';
import './assets/sb-admin/custom.css';
import './assets/sb-admin/theme.js';
import './assets/datatables/dataTables.bootstrap4.min.css';
+import './i18n';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(
-
+
+
+
);
diff --git a/src/pages/Books/AddBook.js b/src/pages/Books/AddBook.js
index c542daa..a472582 100644
--- a/src/pages/Books/AddBook.js
+++ b/src/pages/Books/AddBook.js
@@ -5,8 +5,11 @@ import Header from '../../components/Header';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
function AddBook() {
+ const { t } = useTranslation('books');
+
return (
@@ -14,7 +17,7 @@ function AddBook() {
-
+
diff --git a/src/pages/Books/BookBatchUpload.js b/src/pages/Books/BookBatchUpload.js
index 4bb2c82..bd3a84f 100644
--- a/src/pages/Books/BookBatchUpload.js
+++ b/src/pages/Books/BookBatchUpload.js
@@ -5,8 +5,10 @@ import Header from '../../components/Header';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
const BookBatchUpload = () => {
+ const { t } = useTranslation('dashboard');
return (
@@ -14,7 +16,7 @@ const BookBatchUpload = () => {
-
+
diff --git a/src/pages/Books/EditBook.js b/src/pages/Books/EditBook.js
index a2b52c5..fd87086 100644
--- a/src/pages/Books/EditBook.js
+++ b/src/pages/Books/EditBook.js
@@ -5,8 +5,11 @@ import Header from '../../components/Header';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
function EditBook() {
+ const { t } = useTranslation('books');
+
return (
@@ -14,7 +17,7 @@ function EditBook() {
-
+
diff --git a/src/pages/Books/SearchBooks.js b/src/pages/Books/SearchBooks.js
index ef55b74..84c7e0b 100644
--- a/src/pages/Books/SearchBooks.js
+++ b/src/pages/Books/SearchBooks.js
@@ -6,8 +6,10 @@ import Header from '../../components/Header';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
function SearchBooks() {
+ const { t } = useTranslation('books');
const [psearchBy, setSearchBy] = useState(['', '']);
return (
@@ -17,7 +19,7 @@ function SearchBooks() {
-
+
diff --git a/src/pages/Books/ViewBook.js b/src/pages/Books/ViewBook.js
index eee6d00..e24f644 100644
--- a/src/pages/Books/ViewBook.js
+++ b/src/pages/Books/ViewBook.js
@@ -9,8 +9,10 @@ import ViewBookDetailsCard from '../../components/ViewBookDetailsCard';
import ViewBookLoansCard from '../../components/ViewBookLoansCard';
import { deleteCall } from '../../helpers/deleteCall';
import { useFetch } from '../../helpers/useFetch';
+import { useTranslation } from 'react-i18next';
const ViewBook = () => {
+ const { t } = useTranslation('books');
const { id } = useParams();
let bookDetailUrl = `/api/books/${id}`;
@@ -23,9 +25,13 @@ const ViewBook = () => {
function handleDelete(e) {
deleteCall(bookDetailUrl).then((result) => {
- window.alert(result['data']['message']);
+ const status = result['status'];
+ window.alert(t(
+ [`deleteResp.${status}`, 'deleteResp.unspecific'],
+ {errorMessage: result['data']['message']}
+ ));
- if (result['status'] === 200) {
+ if (status === 200) {
let path = `/books/search`;
navigate(path);
}
@@ -54,10 +60,10 @@ const ViewBook = () => {
- Edit details
+ {t('edit')}
- Delete Book
+ {t('delete')}
diff --git a/src/pages/Dashboard.js b/src/pages/Dashboard.js
index 5f05148..9f56cc9 100644
--- a/src/pages/Dashboard.js
+++ b/src/pages/Dashboard.js
@@ -7,8 +7,10 @@ import ModalLogout from '../components/ModalLogout';
import ScrollTop from '../components/ScrollTop';
import Sidebar from '../components/Sidebar';
import { useFetch } from '../helpers/useFetch';
+import { useTranslation } from 'react-i18next';
const Dashboard = () => {
+ const { t } = useTranslation('dashboard');
const statsUrl = '/api/dashboard/stats';
const { data: statsData } = useFetch(statsUrl);
@@ -32,7 +34,7 @@ const Dashboard = () => {
-
+
@@ -40,7 +42,7 @@ const Dashboard = () => {
-
Unique titles
+
{t('uniqueTitles')}
{statsData['uniqueTitles']}
@@ -56,7 +58,7 @@ const Dashboard = () => {
-
Total loaners
+
{t('totalLoaners')}
{statsData['totalLoaners']}
@@ -72,7 +74,7 @@ const Dashboard = () => {
-
Total copies of all titles
+
{t('totalCopies')}
{statsData['totalCopies']}
@@ -88,7 +90,7 @@ const Dashboard = () => {
-
Total outstanding copies
+
{t('totalOutstanding')}
{percentageOutstanding + '%'}
@@ -128,8 +130,8 @@ const Dashboard = () => {
-
Librarian management
-
Add or update librarian or faculty
+
{t('librarianManagement')}
+
{t('librarianManagementDesc')}
@@ -138,8 +140,8 @@ const Dashboard = () => {
-
Import books
-
Import books from CSV
+
{t('importBooks')}
+
{t('importBooksDesc')}
@@ -148,8 +150,8 @@ const Dashboard = () => {
-
Import loaners
-
Import loaners from CSV
+
{t('importLoaners')}
+
{t('importLoanersDesc')}
@@ -161,20 +163,20 @@ const Dashboard = () => {
-
Overdue loans
+ {t('overdueLoans')}
{overdueData.length === 0 ? (
- 'No overdue loans'
+ t('noOverdueLoans')
) : (
- Loaner
- Book
- Copies
- Due date
+ {t('loaner')}
+ {t('book')}
+ {t('copies')}
+ {t('dueDate')}
@@ -231,20 +233,20 @@ const Dashboard = () => {
-
Upcoming due dates
+ {t('upcomingDueDates')}
{upcomingdueData.length === 0 ? (
- 'No upcoming due date until next week'
+ t('noUpcomingDueDates')
) : (
- Loaner
- Book
- Copies
- Due date
+ {t('loaner')}
+ {t('book')}
+ {t('copies')}
+ {t('dueDate')}
diff --git a/src/pages/Error.js b/src/pages/Error.js
index 2302a9c..d9ecf9f 100644
--- a/src/pages/Error.js
+++ b/src/pages/Error.js
@@ -5,8 +5,10 @@ import Header from '../components/Header';
import ModalLogout from '../components/ModalLogout.js';
import ScrollTop from '../components/ScrollTop';
import Sidebar from '../components/Sidebar';
+import { useTranslation } from 'react-i18next';
const Error = () => {
+ const { t } = useTranslation();
let notFoundPic = '/images/not_found.svg';
return (
@@ -16,7 +18,7 @@ const Error = () => {
-
+
{/*
@@ -30,7 +32,7 @@ const Error = () => {
- Back to home
+ {t('backToHome')}
diff --git a/src/pages/Home.js b/src/pages/Home.js
index 119e17f..a206474 100644
--- a/src/pages/Home.js
+++ b/src/pages/Home.js
@@ -5,8 +5,10 @@ import MenuCard from '../components/MenuCard';
import ModalLogout from '../components/ModalLogout';
import ScrollTop from '../components/ScrollTop';
import Sidebar from '../components/Sidebar';
+import { useTranslation } from 'react-i18next';
const Home = () => {
+ const { t } = useTranslation();
const loggedRole = window.localStorage.getItem('role');
return (
@@ -16,7 +18,7 @@ const Home = () => {
-
+
{loggedRole === 'ADMIN' ? (
@@ -29,13 +31,13 @@ const Home = () => {
}}
className='pt-3'
>
- Transact
+ {t('transact')}
-
-
-
-
+
+
+
+
{
}}
className='pt-3'
>
- Database
+ {t('database')}
-
-
-
-
+
+
+
+
{
}}
className='pt-3'
>
- Dashboard
+ {t('dashboard')}
-
-
+
+
) : (
-
+
)}
diff --git a/src/pages/Librarian/AddLibrarian.js b/src/pages/Librarian/AddLibrarian.js
index 2250083..1e5f9b7 100644
--- a/src/pages/Librarian/AddLibrarian.js
+++ b/src/pages/Librarian/AddLibrarian.js
@@ -5,8 +5,11 @@ import LibrarianAddForm from '../../components/LibrarianAddForm';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
function AddLibrarian() {
+ const { t } = useTranslation('librarians');
+
return (
@@ -14,7 +17,7 @@ function AddLibrarian() {
-
+
diff --git a/src/pages/Librarian/ChangePasswordLibrarian.js b/src/pages/Librarian/ChangePasswordLibrarian.js
index 8b1055f..4a935f1 100644
--- a/src/pages/Librarian/ChangePasswordLibrarian.js
+++ b/src/pages/Librarian/ChangePasswordLibrarian.js
@@ -5,8 +5,11 @@ import LibrarianPasswordChangeForm from '../../components/LibrarianPasswordChang
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
function EditLibrarian() {
+ const { t } = useTranslation('librarians');
+
return (
@@ -14,7 +17,7 @@ function EditLibrarian() {
-
+
diff --git a/src/pages/Librarian/EditLibrarian.js b/src/pages/Librarian/EditLibrarian.js
index a21d439..20db4e5 100644
--- a/src/pages/Librarian/EditLibrarian.js
+++ b/src/pages/Librarian/EditLibrarian.js
@@ -5,8 +5,11 @@ import LibrarianEditForm from '../../components/LibrarianEditForm';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
function EditLibrarian() {
+ const { t } = useTranslation('librarians');
+
return (
@@ -14,7 +17,7 @@ function EditLibrarian() {
-
+
diff --git a/src/pages/Librarian/SearchLibrarians.js b/src/pages/Librarian/SearchLibrarians.js
index 3e908a1..5899e95 100644
--- a/src/pages/Librarian/SearchLibrarians.js
+++ b/src/pages/Librarian/SearchLibrarians.js
@@ -6,8 +6,10 @@ import LibrarianList from '../../components/LibrarianList';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
const SearchLibrarians = () => {
+ const { t } = useTranslation('librarians');
let navigate = useNavigate();
return (
@@ -29,7 +31,7 @@ const SearchLibrarians = () => {
navigate(path);
}}
>
- Add new librarian
+ {t('addLibrarian')}
{
navigate(path);
}}
>
- Back to dashboard
+ {t('backToDashboard')}
diff --git a/src/pages/Librarian/ViewLibrarian.js b/src/pages/Librarian/ViewLibrarian.js
index 599c08d..d227e5b 100644
--- a/src/pages/Librarian/ViewLibrarian.js
+++ b/src/pages/Librarian/ViewLibrarian.js
@@ -8,8 +8,10 @@ import Sidebar from '../../components/Sidebar';
import ViewLibrarianDetailsCard from '../../components/ViewLibrarianDetailsCard';
import { deleteCall } from '../../helpers/deleteCall';
import { useFetch } from '../../helpers/useFetch';
+import { useTranslation } from 'react-i18next';
const ViewLibrarian = () => {
+ const { t } = useTranslation('librarians');
const { id } = useParams();
let librarianDetailUrl = `/api/librarian/${id}`;
@@ -21,9 +23,13 @@ const ViewLibrarian = () => {
let librarianDeleteUrl = `${librarianDetailUrl}?deleteBy=${window.localStorage.getItem('id')}`;
deleteCall(librarianDeleteUrl).then((result) => {
- window.alert(result['data']['message']);
+ const status = result['status'];
+ window.alert(t(
+ [`deleteResp.${status}`, 'deleteResp.unspecific'],
+ {errorMessage: result['data']['message']}
+ ));
- if (result['status'] === 200) {
+ if (status === 200) {
navigate(`/dashboard/librarian/search`);
}
});
@@ -61,10 +67,10 @@ const ViewLibrarian = () => {
- Edit details
+ {t('editDetails')}
- Change password
+ {t('changePassword')}
@@ -72,7 +78,7 @@ const ViewLibrarian = () => {
diff --git a/src/pages/Loaners/AddLoaner.js b/src/pages/Loaners/AddLoaner.js
index 6dfb930..38cda1f 100644
--- a/src/pages/Loaners/AddLoaner.js
+++ b/src/pages/Loaners/AddLoaner.js
@@ -5,8 +5,11 @@ import LoanerAddForm from '../../components/LoanerAddForm';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
function AddLoaner() {
+ const { t } = useTranslation('loaners');
+
return (
@@ -14,7 +17,7 @@ function AddLoaner() {
-
+
diff --git a/src/pages/Loaners/EditLoaner.js b/src/pages/Loaners/EditLoaner.js
index e213790..9ce9437 100644
--- a/src/pages/Loaners/EditLoaner.js
+++ b/src/pages/Loaners/EditLoaner.js
@@ -5,8 +5,11 @@ import LoanerEditForm from '../../components/LoanerEditForm';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
function EditLoaner() {
+ const { t } = useTranslation('loaners');
+
return (
@@ -14,7 +17,7 @@ function EditLoaner() {
-
+
diff --git a/src/pages/Loaners/LoanerBatchUpload.js b/src/pages/Loaners/LoanerBatchUpload.js
index 3ea5043..930595a 100644
--- a/src/pages/Loaners/LoanerBatchUpload.js
+++ b/src/pages/Loaners/LoanerBatchUpload.js
@@ -5,8 +5,10 @@ import LoanerBatchLoad from '../../components/LoanerBatchLoad';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
const LoanerBatchUpload = () => {
+ const { t } = useTranslation('dashboard');
return (
@@ -14,7 +16,7 @@ const LoanerBatchUpload = () => {
-
+
diff --git a/src/pages/Loaners/SearchLoaners.js b/src/pages/Loaners/SearchLoaners.js
index 6f1c3d4..8efaa69 100644
--- a/src/pages/Loaners/SearchLoaners.js
+++ b/src/pages/Loaners/SearchLoaners.js
@@ -6,8 +6,10 @@ import LoanerSearchBar from '../../components/LoanerSearchBar';
import ModalLogout from '../../components/ModalLogout';
import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
+import { useTranslation } from 'react-i18next';
const SearchLoaners = () => {
+ const { t } = useTranslation('loaners');
const [psearchBy, setSearchBy] = useState(['', '']);
return (
@@ -17,7 +19,7 @@ const SearchLoaners = () => {
-
+
diff --git a/src/pages/Loaners/ViewLoaner.js b/src/pages/Loaners/ViewLoaner.js
index 1c88cbd..23c0d62 100644
--- a/src/pages/Loaners/ViewLoaner.js
+++ b/src/pages/Loaners/ViewLoaner.js
@@ -10,8 +10,10 @@ import ViewLoanerDetailsCard from '../../components/ViewLoanerDetailsCard';
import ViewLoanerHistoryCard from '../../components/ViewLoanerHistoryCard';
import { deleteCall } from '../../helpers/deleteCall';
import { useFetch } from '../../helpers/useFetch';
+import { useTranslation } from 'react-i18next';
const ViewLoaner = () => {
+ const { t } = useTranslation('loaners');
const { id } = useParams();
let loanerDetailUrl = `/api/loaners/${id}`;
@@ -24,9 +26,13 @@ const ViewLoaner = () => {
function handleDelete(e) {
deleteCall(loanerDetailUrl).then((result) => {
- window.alert(result['data']['message']);
+ const status = result['status'];
+ window.alert(t(
+ [`deleteResp.${status}`, 'deleteResp.unspecific'],
+ {errorMessage: result['data']['message']}
+ ));
- if (result['status'] === 200) {
+ if (status === 200) {
let path = `/loaners/search`;
navigate(path);
}
@@ -54,10 +60,10 @@ const ViewLoaner = () => {
- Edit details
+ {t('editDetails')}
- Delete loaner
+ {t('deleteLoaner')}
diff --git a/src/pages/Login.js b/src/pages/Login.js
index ac10f34..f90505a 100644
--- a/src/pages/Login.js
+++ b/src/pages/Login.js
@@ -1,9 +1,11 @@
-import React, { useState } from 'react';
+import React, { useState, useTransition } from 'react';
import { useNavigate } from 'react-router-dom';
import { postCall } from '../helpers/postCall';
import { useAuth } from '../helpers/useAuth';
+import { useTranslation } from 'react-i18next';
const Login = () => {
+ const { t } = useTranslation();
const navigate = useNavigate();
const { login } = useAuth();
@@ -53,7 +55,7 @@ const Login = () => {
-
Login to BudLib
+ {t('loginHeader')}
diff --git a/src/pages/Transactions/BorrowCart.js b/src/pages/Transactions/BorrowCart.js
index d42cc02..0e5ca41 100644
--- a/src/pages/Transactions/BorrowCart.js
+++ b/src/pages/Transactions/BorrowCart.js
@@ -8,6 +8,7 @@ import ScrollTop from '../../components/ScrollTop';
import Sidebar from '../../components/Sidebar';
import { postCall } from '../../helpers/postCall';
import { useFetch } from '../../helpers/useFetch';
+import { useTranslation } from 'react-i18next';
function todayDate() {
let today = new Date();
@@ -32,6 +33,7 @@ function defaultDueDate() {
}
const BorrowCart = () => {
+ const { t } = useTranslation('transactions');
let navigate = useNavigate();
const currTransactionType = 'BORROW';
@@ -68,7 +70,7 @@ const BorrowCart = () => {
if (newCart.length === 0) {
if (parseInt(st[2]) < 1) {
- window.alert('No copies availabile');
+ window.alert(t('noCopies'));
} else {
newCart.push({
book: {
@@ -82,7 +84,7 @@ const BorrowCart = () => {
}
} else {
if (parseInt(st[2]) < 1) {
- window.alert('No copies availabile');
+ window.alert(t('noCopies'));
} else {
for (let i = 0; i < newCart.length; i++) {
if (newCart[i]['book']['bookId'] === parseInt(st[0])) {
@@ -91,7 +93,7 @@ const BorrowCart = () => {
setCartBookCopies([...newCart]);
} else {
- window.alert('No more copies availabile');
+ window.alert(t('noMoreCopies'));
}
flag = true;
@@ -140,7 +142,7 @@ const BorrowCart = () => {
newCart[i]['copies'] = parseInt(newCart[i]['copies']) + 1;
setCartBookCopies([...newCart]);
} else {
- window.alert('No more copies availabile');
+ window.alert(t('noMoreCopies'));
}
}
}
@@ -150,7 +152,7 @@ const BorrowCart = () => {
e.preventDefault();
if (cartBookCopies.length === 0) {
- window.alert('No books in cart to borrow');
+ window.alert(t('noBooksInCart'));
return;
}
@@ -160,9 +162,13 @@ const BorrowCart = () => {
let sendDetails = { ...trnPayload, bookCopies: cartBookCopies };
postCall(`/api/transactions?borrowDate=${sendBorrowDate}&dueDate=${sendDueDate}`, sendDetails).then((result) => {
- window.alert(result['data']['message']);
+ const status = result['status'];
+ window.alert(t(
+ [`completeRes.${status}`, 'completeRes.unspecific'],
+ {errorMessage: result['data']['message']}
+ ));
- if (result['status'] === 200) {
+ if (status === 200) {
navigate(`/loaners/${loanerId}/view`);
}
});
@@ -175,7 +181,7 @@ const BorrowCart = () => {
-
+
@@ -185,18 +191,18 @@ const BorrowCart = () => {