Skip to content

Commit

Permalink
Merge pull request #52 from pkolt/46-standardize-page-template
Browse files Browse the repository at this point in the history
46-standardize-page-template
  • Loading branch information
pkolt authored Jul 5, 2024
2 parents 9041c40 + 292d1f1 commit ff14a81
Show file tree
Hide file tree
Showing 17 changed files with 831 additions and 812 deletions.
1,084 changes: 544 additions & 540 deletions package-lock.json

Large diffs are not rendered by default.

40 changes: 19 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"pre-commit": "node --run lint-all && node --run test && node --run bench"
},
"dependencies": {
"@hookform/resolvers": "^3.6.0",
"@hookform/resolvers": "^3.8.0",
"bootstrap": "^5.3.3",
"bootstrap-icons": "^1.11.3",
"classnames": "^2.5.1",
Expand All @@ -42,50 +42,48 @@
"i18next-browser-languagedetector": "^8.0.0",
"luxon": "^3.4.4",
"react": "^18.3.1",
"react-bootstrap": "^2.10.2",
"react-bootstrap": "^2.10.4",
"react-dom": "^18.3.1",
"react-hook-form": "^7.51.5",
"react-hook-form": "^7.52.1",
"react-hotkeys-hook": "^4.5.0",
"react-i18next": "^14.1.2",
"react-router-dom": "^6.23.1",
"uuid": "^9.0.1",
"react-router-dom": "^6.24.1",
"workbox-cacheable-response": "^7.1.0",
"workbox-core": "^7.1.0",
"workbox-routing": "^7.1.0",
"workbox-strategies": "^7.1.0",
"workbox-window": "^7.1.0",
"zod": "^3.23.8",
"zustand": "^4.5.2"
"zustand": "^4.5.4"
},
"devDependencies": {
"@eslint/compat": "^1.0.3",
"@eslint/compat": "^1.1.0",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.4.0",
"@eslint/js": "^9.6.0",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"@types/bootstrap": "^5.2.10",
"@types/file-saver": "^2.0.7",
"@types/luxon": "^3.4.2",
"@types/node": "^20.14.2",
"@types/node": "^20.14.9",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^7.12.0",
"@typescript-eslint/parser": "^7.12.0",
"@vitejs/plugin-react": "^4.3.0",
"@typescript-eslint/eslint-plugin": "^7.15.0",
"@typescript-eslint/parser": "^7.15.0",
"@vitejs/plugin-react": "^4.3.1",
"@vitest/coverage-v8": "^1.6.0",
"esbuild": "^0.21.4",
"esbuild": "^0.23.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.2",
"eslint-plugin-react": "^7.34.3",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"happy-dom": "^14.12.0",
"knip": "^5.18.0",
"happy-dom": "^14.12.3",
"knip": "^5.24.1",
"msw": "^2.3.1",
"prettier": "^3.3.1",
"sass": "^1.77.4",
"typescript": "^5.4.5",
"vite": "^5.2.13",
"prettier": "^3.3.2",
"sass": "^1.77.6",
"typescript": "^5.5.3",
"vite": "^5.3.3",
"vitest": "^1.5.0"
}
}
109 changes: 70 additions & 39 deletions scripts/find_i18n.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/* eslint-disable no-undef */
/* eslint-disable no-console */
import fs from 'node:fs';
import path from 'node:path';

const main = ({ locales, srcDir, ext, transDir }) => {
const findTokens = (srcDir, ext) => {
const tokens = new Set();
const source = path.resolve(srcDir);
const paths = fs.readdirSync(source, { recursive: true });

const SrcFullPath = path.join(import.meta.dirname, '../', srcDir);
const paths = fs.readdirSync(SrcFullPath, { recursive: true });
for (const relPath of paths) {
const absPath = path.join(source, relPath);
const absPath = path.join(SrcFullPath, relPath);
const stat = fs.statSync(absPath);
if (stat.isFile() && ext.some((it) => relPath.endsWith(it))) {
const content = fs.readFileSync(absPath, 'utf-8');
Expand All @@ -18,50 +19,80 @@ const main = ({ locales, srcDir, ext, transDir }) => {
}
}
}
return tokens;
};

const updateTranslates = (locale, fileFullPath, tokens) => {
let data = {};
try {
const content = fs.readFileSync(fileFullPath, 'utf-8');
data = JSON.parse(content);
} catch {
// ignore error
}

for (const locale of locales) {
let data = {};
const jsonFile = path.resolve(transDir, `${locale}.json`);
try {
const content = fs.readFileSync(jsonFile, 'utf-8');
data = JSON.parse(content);
} catch (err) {
// ignore error
if (!data.translation) {
data.translation = {};
}

const unknownTokens = [];
const addedTokens = [];
const noTranslatedTokens = [];
const translation = { ...data.translation };

for (const token of Object.keys(translation)) {
if (!tokens.has(token)) {
unknownTokens.push(token);
}
if (translation[token] === '' && translation[token] === token && locale !== 'en') {
noTranslatedTokens.push(token);
}
}

if (!data.translation) {
data.translation = {};
for (const token of tokens) {
if (translation[token] === undefined) {
addedTokens.push(token);
translation[token] = token;
}
}

const jsonData = data.translation;
const isUnknownTokens = unknownTokens.length > 0;
const isAddedTokens = addedTokens.length > 0;
const isNoTranslatedTokens = noTranslatedTokens.length > 0;

let showHeader = false;
for (const key of Object.keys(jsonData)) {
if (!tokens.has(key)) {
if (!showHeader) {
// eslint-disable-next-line no-console, no-undef
console.log(`Unknown tokens in file: ${jsonFile}`);
showHeader = true;
}
// eslint-disable-next-line no-console, no-undef
console.log(`"${key}"`);
}
if (isUnknownTokens || isAddedTokens || isNoTranslatedTokens) {
const separator = '-'.repeat(80);
console.log(separator);
console.log(`File: ${fileFullPath}`);
console.log(separator);
if (isUnknownTokens) {
console.log(`Unknown tokens: ${unknownTokens.join(', ')}`);
}
if (isAddedTokens) {
console.log(`Added tokens: ${addedTokens.join(', ')}`);
}
if (isNoTranslatedTokens) {
console.log(`No translated tokens: ${noTranslatedTokens.join(', ')}`);
}
}

let addedCount = 0;
if (isAddedTokens) {
data.translation = Object.keys(translation)
.sort()
.reduce((accum, key) => {
accum[key] = translation[key];
return accum;
}, {});

for (const key of tokens) {
if (!jsonData[key]) {
jsonData[key] = key;
addedCount++;
}
}
fs.writeFileSync(fileFullPath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
}
};

if (addedCount > 0) {
fs.writeFileSync(jsonFile, JSON.stringify(data, null, 2) + '\n', 'utf-8');
// eslint-disable-next-line no-console, no-undef
console.log(`Change file "${jsonFile}" - ${addedCount} added`);
}
const main = ({ locales, srcDir, ext, transDir }) => {
const tokens = findTokens(srcDir, ext);
for (const locale of locales) {
const fullPath = path.resolve(transDir, `${locale}.json`);
updateTranslates(locale, fullPath, tokens);
}
};

Expand Down
10 changes: 8 additions & 2 deletions src/components/Page/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,23 @@ import { ErrorBoundary } from './ErrorBoundary';

interface PageProps extends React.PropsWithChildren {
title: string;
hideTitle?: boolean;
}

export const Page = ({ title, children }: PageProps) => {
export const Page = ({ title, hideTitle, children }: PageProps) => {
useEffect(() => {
document.title = title;
}, [title]);

return (
<div className="container d-flex flex-column gap-4 min-vh-100">
<Header />
<ErrorBoundary>{children}</ErrorBoundary>
<ErrorBoundary>
<main className="d-flex flex-column flex-grow-1 justify-content-center align-items-center gap-3">
{!hideTitle && <h1 className="text-center">{title}</h1>}
{children}
</main>
</ErrorBoundary>
<Footer />
<UpdatePwaDialog />
</div>
Expand Down
1 change: 1 addition & 0 deletions src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ i18n
ru: transRu,
},
debug: import.meta.env.MODE === 'development',
supportedLngs: ['en', 'ru'],
fallbackLng: 'en',
});
Loading

0 comments on commit ff14a81

Please sign in to comment.