1
0

Add language selector.

This commit is contained in:
PA4KEV 2024-02-11 17:40:16 +01:00
parent aaa343cb9f
commit e5787bd3cb
23 changed files with 508 additions and 417 deletions

View File

@ -10,7 +10,7 @@ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './Pages/Home'; import Home from './Pages/Home';
import Software from './Pages/Software/Software'; import SoftwareMain from './Pages/Software/SoftwareMain';
import DXPDevelopment from './Pages/Software/Projects/DXPDevelopment'; import DXPDevelopment from './Pages/Software/Projects/DXPDevelopment';
import ConfigAutomation from './Pages/Software/Projects/ConfigAutomation'; import ConfigAutomation from './Pages/Software/Projects/ConfigAutomation';
import KanjiApplication from './Pages/Software/Projects/KanjiApplication'; import KanjiApplication from './Pages/Software/Projects/KanjiApplication';
@ -29,12 +29,7 @@ import MetroidShooter from './Pages/Software/Projects/MetroidShooter';
import Books from './Pages/Books/Books'; import Books from './Pages/Books/Books';
import booksdata from './Pages/Books/books.json' import booksdata from './Pages/Books/books.json'
import Radio from './Pages/Radio/Radio'; import RadioMain from './Pages/Radio/RadioMain';
import Components from './Pages/Radio/Components';
import Balkon from './Pages/Radio/Balkon';
import Fielddays from './Pages/Radio/fielddays/fielddays';
import fielddaysdata from './Pages/Radio/fielddays/fielddays.json';
import MarkdownPage from './Pages/markdownPage'; import MarkdownPage from './Pages/markdownPage';
@ -43,53 +38,137 @@ import Footer from './UI/Footer';
import BasicPage from './Pages/BasicPage'; import BasicPage from './Pages/BasicPage';
import Japan from './Japan/Japan'; import Japan from './Japan/Japan';
import Japanese from './Pages/Japanese/Japan'; import JapaneseMain from './Pages/Japan/JapaneseMain';
const languages = ['en', 'nl'];
export function getLanguage() {
const currentPath = window.location.pathname;
let language;
try {
const result = currentPath.split('/')[1];
if (languages.includes(result)) {
language = result;
} else {
throw new Error('Invalid language detected');
}
}
catch (error) {
language = 'en';
}
return language;
}
const languageStrings = {
en: {
// Common
and: 'and',
on: 'on',
// Titles
japanese: 'Japanese',
radio_amateur: 'Radio amateur',
software: 'Software',
// Navigation
portal: 'Portal',
language: 'Language',
// Radio
fielddays: 'Field days',
// Footer
footer_madewith: 'This site was made with',
footer_contentparsed: 'Content is parsed by',
},
nl: {
// Common
and: 'en',
on: 'op',
// Titles
japanese: 'Japans',
radio_amateur: 'Radiozendamateur',
software: 'Software',
// Navigation
portal: 'Portaal',
language: 'Taal',
// Radio
fielddays: 'Velddagen',
// Footer
footer_madewith: 'Deze website is gemaakt met',
footer_contentparsed: 'Inhoud is verwerkt door',
},
};
export function getString(language, key) {
return languageStrings[language][key] || `{${key}}`;
}
function App() { function App() {
const language = getLanguage();
const dates = ['20231111', '20231230', '20240121'];
const paths = {
'japan': <JapaneseMain />,
'radio': <RadioMain />,
'software': <SoftwareMain />,
};
const fieldDaysRoutes = languages.map(lang => {
return dates.map(date => {
const path = `/${lang}/radio/fielddays/${date}`;
const mdPath = `Radio/fielddays/${lang}/${date}.md`;
return <Route key={`${lang}-${date}`} exact path={path} element={<MarkdownPage md={mdPath} />} />;
});
}).flat();
function generateRoutes(languages, paths) {
const routes = [];
languages.forEach(language => {
Object.keys(paths).forEach(path => {
const fullPath = `/${language}/${path}`;
routes.push(
<Route key={`${language}-${path}`} exact path={fullPath} element={paths[path]} />
);
});
});
return routes;
}
const generatedRoutes = generateRoutes(languages, paths);
return ( return (
<Router> <Router>
<div className="row"> <div className='row'>
<Navigation /> <Navigation language={language} />
<Routes> <Routes>
<Route exact path='/' element={<Home />}></Route> <Route exact path='/' element={<Home language={"en"} />}></Route>
<Route exact path='/pages/software' element={<Software />}></Route> <Route exact path='/en' element={<Home language={language} />}></Route>
<Route exact path='/pages/software/dxp-development' element={<DXPDevelopment />}></Route> <Route exact path='/nl' element={<Home language={language} />}></Route>
<Route exact path='/pages/software/configuration-automation' element={<ConfigAutomation />}></Route>
<Route exact path='/pages/software/wifi-prototype' element={<WifiPrototype />}></Route>
<Route exact path='/pages/software/embedded-game' element={<SwivForPi />}></Route>
<Route exact path='/pages/software/raspberry-pi-jukebox' element={<RaspberryJukebox />}></Route>
<Route exact path='/pages/software/kanji-application' element={<KanjiApplication />}></Route>
<Route exact path='/pages/software/attachment-module' element={<AttachmentModule />}></Route>
<Route exact path='/pages/software/teslamaze' element={<TeslaMaze />}></Route>
<Route exact path='/pages/software/embedded-internet-radio' element={<EmbeddedInternetRadio />}></Route>
<Route exact path='/pages/software/windows10-cookbook' element={<Windows10Cookbook />}></Route>
<Route exact path='/pages/software/ios-airports' element={<IOSAirports />}></Route>
<Route exact path='/pages/software/festival-simulator' element={<FestivalSimulator />}></Route>
<Route exact path='/pages/software/boebot' element={<BoardOfEducationBot />}></Route>
<Route exact path='/pages/software/metroid-horizontal-shooter' element={<MetroidShooter />}></Route>
<Route exact path='/pages/radio' element={<Radio />}></Route>
<Route exact path='/pages/radio/components' element={<Components />}></Route>
<Route exact path='/pages/radio/balcony' element={<Balkon />}></Route>
<Route exact path='/pages/radio/fielddays' element={<Fielddays fieldDays={fielddaysdata.fielddays} />}></Route>
<Route exact path='/pages/books' element={<Books books={booksdata.books} />}></Route>
<Route exact path='/pages/linux' element={<Linux />}></Route>
<Route exact path='/pages/japanese' element={<Japanese />}></Route>
<Route exact path='/pages/books' element={<Books />}></Route>
<Route exact path='/pages/basic' element={<BasicPage id="1" />}></Route> {fieldDaysRoutes}
{generatedRoutes}
<Route exact path='/software/dxp-development' element={<DXPDevelopment />}></Route>
<Route exact path='/software/configuration-automation' element={<ConfigAutomation />}></Route>
<Route exact path='/software/wifi-prototype' element={<WifiPrototype />}></Route>
<Route exact path='/software/embedded-game' element={<SwivForPi />}></Route>
<Route exact path='/software/raspberry-pi-jukebox' element={<RaspberryJukebox />}></Route>
<Route exact path='/software/kanji-application' element={<KanjiApplication />}></Route>
<Route exact path='/software/attachment-module' element={<AttachmentModule />}></Route>
<Route exact path='/software/teslamaze' element={<TeslaMaze />}></Route>
<Route exact path='/software/embedded-internet-radio' element={<EmbeddedInternetRadio />}></Route>
<Route exact path='/software/windows10-cookbook' element={<Windows10Cookbook />}></Route>
<Route exact path='/software/ios-airports' element={<IOSAirports />}></Route>
<Route exact path='/software/festival-simulator' element={<FestivalSimulator />}></Route>
<Route exact path='/software/boebot' element={<BoardOfEducationBot />}></Route>
<Route exact path='/software/metroid-horizontal-shooter' element={<MetroidShooter />}></Route>
<Route exact path='/books' element={<Books books={booksdata.books} />}></Route>
<Route exact path='/linux' element={<Linux />}></Route>
<Route exact path='/books' element={<Books />}></Route>
<Route exact path='/basic' element={<BasicPage id="1" />}></Route>
<Route exact path='/wine' element={<BasicPage id="4" />}></Route> <Route exact path='/wine' element={<BasicPage id="4" />}></Route>
<Route exact path='/en/pages/radio/fielddays/20231111' element={<MarkdownPage md='Radio/fielddays/en/20231111.md' />}></Route> <Route exact path='/japanMap' element={<Japan />}></Route>
<Route exact path='/en/pages/radio/fielddays/20231230' element={<MarkdownPage md='Radio/fielddays/en/20231230.md' />}></Route>
<Route exact path='/en/pages/radio/fielddays/20240121' element={<MarkdownPage md='Radio/fielddays/en/20240121.md' />}></Route>
<Route exact path='/nl/pages/radio/fielddays/20231111' element={<MarkdownPage md='Radio/fielddays/nl/20231111.md' />}></Route>
<Route exact path='/nl/pages/radio/fielddays/20231230' element={<MarkdownPage md='Radio/fielddays/nl/20231230.md' />}></Route>
<Route exact path='/nl/pages/radio/fielddays/20240121' element={<MarkdownPage md='Radio/fielddays/nl/20240121.md' />}></Route>
<Route exact path='/japan' element={<Japan />}></Route>
</Routes> </Routes>
<Footer /> <Footer />

View File

@ -1,51 +1,15 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import MarkdownPage from './markdownPage';
const Home = ({ language }) => {
const pathHome = 'home-' + language + '.md';
console.log(pathHome);
const Home = () => {
return ( return (
<div className='row'> <article className="main-page">
<div className="col-6 offset-3"> <MarkdownPage md={pathHome} />
<section className="content-section"> </article>
<p>I am a programmer as profession.</p>
<p>I worked on:</p>
<ul>
<li><Link reloadDocument to="/pages/software/configuration-automation">configuration automation</Link></li>
<li><Link reloadDocument to="/pages/software/dxp-development">DXP development</Link></li>
<li><Link reloadDocument to="/pages/software#list-projects">Other software projects</Link></li>
</ul>
<p>My interests are:</p>
<ul>
<li><Link reloadDocument to="/pages/software">Software development</Link></li>
<li><Link reloadDocument to="/pages/japanese">Japanese language</Link></li>
<li><Link reloadDocument to="/pages/radio">Amateur radio</Link></li>
<li>Linux</li>
<li>Electronics</li>
<li>Woodworking</li>
<li>Yoga</li>
<li>synthesize music</li>
</ul>
<p>I am based in Helmond, the Netherlands.</p>
<p>
<a href="https://github.com/PA4KEV" target="_blank" rel="noopener noreferrer">
<img src={`${process.env.PUBLIC_URL}/icons/github.webp`} alt="github icon" />
</a>
&nbsp;&nbsp;
<a href="https://www.linkedin.com/in/kevin-van-der-vleuten-b190b032/" target="_blank" rel="noopener noreferrer">
<img src={`${process.env.PUBLIC_URL}/icons/linkedin.webp`} alt="linkedin icon" />
</a>
&nbsp;&nbsp;
<a href="https://exercism.io/profiles/PA4KEV" target="_blank" rel="noopener noreferrer">
<img src={`${process.env.PUBLIC_URL}/icons/exercism.webp`} alt="exercism icon" />
</a>
&nbsp;&nbsp;
<a href="https://stackoverflow.com/users/6340687/pa4kev" target="_blank" rel="noopener noreferrer">
<img src={`${process.env.PUBLIC_URL}/icons/stackoverflow.webp`} alt="stackoverflow icon" />
</a>
</p>
</section>
</div>
</div>
) )
} }

View File

@ -0,0 +1,17 @@
import React from 'react';
import Emoji from '../../Content/Emoji';
import MarkdownPage from '../markdownPage';
import { getLanguage } from '../../App';
const JapaneseMain = () => {
const language = getLanguage();
return (
<article className="main-page">
<h1 id="list-intro" className="text-primary">Japanese <Emoji symbol="🇯🇵" /></h1>
<MarkdownPage md={'Japan/' + language + '/main.md'} />
</article>
)
}
export default JapaneseMain;

View File

@ -0,0 +1,3 @@
The Japanase language has facinated me for many years now, for I am married with a Japanese. To become fluent means practice every single day, no exceptions.
* [Wani Kani](https://www.wanikani.com/users/PA4KEV)

View File

@ -0,0 +1,3 @@
De Japanse taal heeft mij al jaren gefacineerd. Ik ben ook getrouwd met een Japanse. Om de taal vloeiend te kunnen beheersen, moet je elke dag oefenen. Geen uitzonderingen.
* [Wani Kani](https://www.wanikani.com/users/PA4KEV)

View File

@ -1,24 +0,0 @@
import React from 'react';
import Emoji from '../../Content/Emoji';
const Japanese = () => {
return (
<div className='row'>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section className="content-section">
<div className='content-item'>
<h1 id="list-intro" className="text-primary">Japanese <Emoji symbol="🇯🇵" /></h1>
<p>The Japanase language has facinated me for many years now, for I am married with a Japanese. To become fluent means practice every single day, no exceptions.</p>
<ul>
<li><a href="https://www.wanikani.com/users/PA4KEV" target="_blank" rel="noopener noreferrer">Wani Kani</a></li>
</ul>
</div>
</section>
</div>
</div>
)
}
export default Japanese;

View File

@ -1,88 +0,0 @@
import React from 'react';
import Emoji from '../../Content/Emoji';
const Radio = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-intro">intro</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-links">links</a>
</div>
</div>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section className="content-section">
<div className='content-item'>
<h1 id="list-intro" className="text-primary">Radio amateur <Emoji symbol="📻" /></h1>
<p>I am a (beginner) ham radio amateur. My callsign is: <b>PA4KEV</b></p>
<p>This hobby involves experimenting with wireless communication and electronics.</p>
<p>Here I post my notes on the hobby.</p>
<ul>
<li><a href="https://www.qrz.com/db/PA4KEV" target="_blank" rel="noopener noreferrer">https://www.qrz.com/db/PA4KEV</a></li>
<li><a href="https://www.eqsl.cc/" target="_blank" rel="noopener noreferrer">https://www.eqsl.cc/</a></li>
<li><a href="http://www.hamqsl.com/" target="_blank" rel="noopener noreferrer">http://www.hamqsl.com/</a></li>
<li><a href="http://www.hrdlog.net/" target="_blank" rel="noopener noreferrer">http://www.hrdlog.net/</a></li>
</ul>
</div>
</section>
<section className="content-section">
<div className='content-item'>
<h2 id="list-links" className="text-primary">Links</h2>
<p>Some links I found of websites to other amateurs and information sources.</p>
<ul>
<li><a href="https://www.dj0ip.de/" target="_blank" rel="noopener noreferrer">https://www.dj0ip.de/</a></li>
<li><a href="http://pa0ebc.nl/pe1kqp/s-match-tuner.html" target="_blank" rel="noopener noreferrer">http://pa0ebc.nl/pe1kqp/s-match-tuner.html</a></li>
<li><a href="https://www.pc5e.nl/" target="_blank" rel="noopener noreferrer">https://www.pc5e.nl/</a></li>
<li><a href="http://www.pd0cq.nl/" target="_blank" rel="noopener noreferrer">http://www.pd0cq.nl/</a></li>
<li><a href="https://www.qsl.net/on7px/" target="_blank" rel="noopener noreferrer">https://www.qsl.net/on7px/</a></li>
<li><a href="https://vk2pad.com/" target="_blank" rel="noopener noreferrer">https://vk2pad.com/</a></li>
<li><a href="https://www.qrz.com/db/vk0pd/" target="_blank" rel="noopener noreferrer">https://www.qrz.com/db/vk0pd (Antarctica)</a></li>
<li><a href="http://www.waponline.it/antarctic-info-for-ham-radio/" target="_blank" rel="noopener noreferrer">http://www.waponline.it/antarctic-info-for-ham-radio/ (Antarctica)</a></li>
</ul>
<ul>
<li><a href="https://www.signalintegrityjournal.com/" target="_blank" rel="noopener noreferrer">https://www.signalintegrityjournal.com/</a></li>
<li><a href="https://www.dspguide.com/" target="_blank" rel="noopener noreferrer">https://www.dspguide.com/</a></li>
<li><a href="https://fieldradio.org/best-ham-radio-antenna-for-apartments/" target="_blank" rel="noopener noreferrer">https://fieldradio.org/best-ham-radio-antenna-for-apartments/</a></li>
<li><a href="https://en.wikipedia.org/wiki/J-pole_antenna" target="_blank" rel="noopener noreferrer">https://en.wikipedia.org/wiki/J-pole_antenna</a></li>
<li><a href="https://www.amateurradio.com/w5olf-website/" target="_blank" rel="noopener noreferrer">https://www.amateurradio.com/w5olf-website/</a></li>
<li><a href="https://www.qrp-labs.com/clockn.html" target="_blank" rel="noopener noreferrer">https://www.qrp-labs.com/clockn.html</a></li>
</ul>
<ul>
<li><a href="http://sdr.shbrg.nl:8074/" target="_blank" rel="noopener noreferrer">http://sdr.shbrg.nl:8074/</a></li>
<li><a href="http://websdr.ewi.utwente.nl:8901/" target="_blank" rel="noopener noreferrer">http://websdr.ewi.utwente.nl:8901/</a></li>
</ul>
<ul>
<li><a href="https://pa-11019.blogspot.com/2016/02/wall-loop-20m.html?m=1" target="_blank" rel="noopener noreferrer">https://pa-11019.blogspot.com/2016/02/wall-loop-20m.html?m=1</a></li>
</ul>
<hr />
<h2>Morse links</h2>
<ul>
<li><a href="https://morsecode.world/" target="_blank" rel="noopener noreferrer">https://morsecode.world/</a></li>
<li><a href="https://morsecode.ninja/" target="_blank" rel="noopener noreferrer">https://morsecode.ninja/</a></li>
<li><a href="http://www.morserino.info/" target="_blank" rel="noopener noreferrer">http://www.morserino.info/</a></li>
</ul>
<hr />
<h2>Loggers</h2>
<ul>
<li><a href="https://www.n3fjp.com/" target="_blank" rel="noopener noreferrer">https://www.n3fjp.com/</a></li>
<li><a href="https://www.hamradiodeluxe.com/" target="_blank" rel="noopener noreferrer">https://www.hamradiodeluxe.com/</a></li>
<li><a href="https://n1mmwp.hamdocs.com/" target="_blank" rel="noopener noreferrer">https://n1mmwp.hamdocs.com/</a></li>
</ul>
</div>
</section>
</div>
</div>
)
}
export default Radio;

View File

@ -0,0 +1,70 @@
import React from 'react';
import Emoji from '../../Content/Emoji';
import MarkdownPage from '../markdownPage';
import { getLanguage, getString } from '../../App';
import FielddaysTable from './fielddays/fielddays';
const RadioMain = () => {
const language = getLanguage();
return (
<article className="main-page">
<h1 id="list-intro" className="text-primary">Radio amateur <Emoji symbol="📻" /></h1>
<MarkdownPage md={'Radio/' + language + '/main.md'} />
<h2>{getString(language, 'fielddays')}</h2>
<FielddaysTable />
<h2>Links</h2>
<ul>
<li><a href="https://www.qrz.com/db/PA4KEV" target="_blank" rel="noopener noreferrer">https://www.qrz.com/db/PA4KEV</a></li>
<li><a href="https://www.eqsl.cc/" target="_blank" rel="noopener noreferrer">https://www.eqsl.cc/</a></li>
<li><a href="http://www.hamqsl.com/" target="_blank" rel="noopener noreferrer">http://www.hamqsl.com/</a></li>
<li><a href="http://www.hrdlog.net/" target="_blank" rel="noopener noreferrer">http://www.hrdlog.net/</a></li>
</ul>
<ul>
<li><a href="https://www.dj0ip.de/" target="_blank" rel="noopener noreferrer">https://www.dj0ip.de/</a></li>
<li><a href="http://pa0ebc.nl/pe1kqp/s-match-tuner.html" target="_blank" rel="noopener noreferrer">http://pa0ebc.nl/pe1kqp/s-match-tuner.html</a></li>
<li><a href="https://www.pc5e.nl/" target="_blank" rel="noopener noreferrer">https://www.pc5e.nl/</a></li>
<li><a href="http://www.pd0cq.nl/" target="_blank" rel="noopener noreferrer">http://www.pd0cq.nl/</a></li>
<li><a href="https://www.qsl.net/on7px/" target="_blank" rel="noopener noreferrer">https://www.qsl.net/on7px/</a></li>
<li><a href="https://vk2pad.com/" target="_blank" rel="noopener noreferrer">https://vk2pad.com/</a></li>
<li><a href="https://www.qrz.com/db/vk0pd/" target="_blank" rel="noopener noreferrer">https://www.qrz.com/db/vk0pd (Antarctica)</a></li>
<li><a href="http://www.waponline.it/antarctic-info-for-ham-radio/" target="_blank" rel="noopener noreferrer">http://www.waponline.it/antarctic-info-for-ham-radio/ (Antarctica)</a></li>
</ul>
<ul>
<li><a href="https://www.signalintegrityjournal.com/" target="_blank" rel="noopener noreferrer">https://www.signalintegrityjournal.com/</a></li>
<li><a href="https://www.dspguide.com/" target="_blank" rel="noopener noreferrer">https://www.dspguide.com/</a></li>
<li><a href="https://fieldradio.org/best-ham-radio-antenna-for-apartments/" target="_blank" rel="noopener noreferrer">https://fieldradio.org/best-ham-radio-antenna-for-apartments/</a></li>
<li><a href="https://en.wikipedia.org/wiki/J-pole_antenna" target="_blank" rel="noopener noreferrer">https://en.wikipedia.org/wiki/J-pole_antenna</a></li>
<li><a href="https://www.amateurradio.com/w5olf-website/" target="_blank" rel="noopener noreferrer">https://www.amateurradio.com/w5olf-website/</a></li>
<li><a href="https://www.qrp-labs.com/clockn.html" target="_blank" rel="noopener noreferrer">https://www.qrp-labs.com/clockn.html</a></li>
</ul>
<ul>
<li><a href="http://sdr.shbrg.nl:8074/" target="_blank" rel="noopener noreferrer">http://sdr.shbrg.nl:8074/</a></li>
<li><a href="http://websdr.ewi.utwente.nl:8901/" target="_blank" rel="noopener noreferrer">http://websdr.ewi.utwente.nl:8901/</a></li>
</ul>
<ul>
<li><a href="https://pa-11019.blogspot.com/2016/02/wall-loop-20m.html?m=1" target="_blank" rel="noopener noreferrer">https://pa-11019.blogspot.com/2016/02/wall-loop-20m.html?m=1</a></li>
</ul>
<ul>
<li><a href="https://morsecode.world/" target="_blank" rel="noopener noreferrer">https://morsecode.world/</a></li>
<li><a href="https://morsecode.ninja/" target="_blank" rel="noopener noreferrer">https://morsecode.ninja/</a></li>
<li><a href="http://www.morserino.info/" target="_blank" rel="noopener noreferrer">http://www.morserino.info/</a></li>
</ul>
<ul>
<li><a href="https://www.n3fjp.com/" target="_blank" rel="noopener noreferrer">https://www.n3fjp.com/</a></li>
<li><a href="https://www.hamradiodeluxe.com/" target="_blank" rel="noopener noreferrer">https://www.hamradiodeluxe.com/</a></li>
<li><a href="https://n1mmwp.hamdocs.com/" target="_blank" rel="noopener noreferrer">https://n1mmwp.hamdocs.com/</a></li>
</ul>
</article>
)
}
export default RadioMain;

View File

@ -0,0 +1,5 @@
I am a (beginner) ham radio amateur. My callsign is: **PA4KEV**
This hobby involves experimenting with wireless communication and electronics.
Here I post my notes on the hobby.

View File

@ -1,8 +1,10 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import Emoji from '../../../Content/Emoji'; import Emoji from '../../../Content/Emoji';
import fielddaysdata from './fielddays.json';
const FielddaysTable = () => {
const Fielddays = ({ fieldDays }) => {
function generatePath(dateString, language) { function generatePath(dateString, language) {
// Assuming dateString is in the format "YYYY-MM-DD" // Assuming dateString is in the format "YYYY-MM-DD"
const parts = dateString.split('-'); const parts = dateString.split('-');
@ -11,7 +13,7 @@ const Fielddays = ({ fieldDays }) => {
const day = parts[2]; const day = parts[2];
// Construct the path // Construct the path
const path = `/${language}/pages/radio/fielddays/${year}${month}${day}`; const path = `/${language}/radio/fielddays/${year}${month}${day}`;
// Return JSX with the path inside an <a> tag // Return JSX with the path inside an <a> tag
return ( return (
@ -21,48 +23,44 @@ const Fielddays = ({ fieldDays }) => {
); );
} }
// Optimize to only show link column for the current language.
// This also eliminates a column.
return ( return (
<div className='row'> <table className='table-fielddays'>
<section className="content-section"> <thead>
<p></p> <tr>
<table className='table-fielddays'> <th>Date</th>
<thead> <th><Emoji symbol="🇬🇧" /></th>
<tr> <th><Emoji symbol="🇳🇱" /></th>
<th>Date</th> <th>Name</th>
<th><Emoji symbol="🇬🇧" /></th> <th>POTA Locator</th>
<th><Emoji symbol="🇳🇱" /></th> <th>WW-FF Locator</th>
<th>Name</th> <th>Bands</th>
<th>POTA Locator</th> <th>Mode</th>
<th>WW-FF Locator</th> <th>Transceiver</th>
<th>Bands</th> <th>Total unique QSO</th>
<th>Mode</th> <th>Antenna</th>
<th>Transceiver</th> </tr>
<th>Total unique QSO</th> </thead>
<th>Antenna</th> <tbody>
</tr> {fielddaysdata.fielddays.map((fieldDay, index) => (
</thead> <tr key={index}>
<tbody> <td>{fieldDay.date}</td>
{fieldDays.map((fieldDay, index) => ( <td>{generatePath(fieldDay.date, 'en')}</td>
<tr key={index}> <td>{generatePath(fieldDay.date, 'nl')}</td>
<td>{fieldDay.date}</td> <td>{fieldDay.name}</td>
<td>{generatePath(fieldDay.date, 'en')}</td> <td>{fieldDay['identifier-pota']}</td>
<td>{generatePath(fieldDay.date, 'nl')}</td> <td>{fieldDay['identifier-wwff']}</td>
<td>{fieldDay.name}</td> <td>{fieldDay.bands}</td>
<td>{fieldDay['identifier-pota']}</td> <td>{fieldDay.modes}</td>
<td>{fieldDay['identifier-wwff']}</td> <td>{fieldDay.transceiver}</td>
<td>{fieldDay.bands}</td> <td>{fieldDay['total-unique-qso']}</td>
<td>{fieldDay.modes}</td> <td>{fieldDay.antenna}</td>
<td>{fieldDay.transceiver}</td> </tr>
<td>{fieldDay['total-unique-qso']}</td> ))}
<td>{fieldDay.antenna}</td> </tbody>
</tr> </table>
))}
</tbody>
</table>
</section>
</div>
) )
} }
export default Fielddays; export default FielddaysTable;

View File

@ -0,0 +1,5 @@
Ik ben een (beginnend) radiozendamateur. Mijn callsign is: **PA4KEV**
Deze hobby gaat over experimenteren met electronica en draadloze communicatie.
Hier plaats ik mijn notities over de hobby.

View File

@ -1,131 +0,0 @@
import React from 'react';
import {Link} from 'react-router-dom';
const Software = () => {
return (
<div className='row'>
<div className="sidebar col-3 position-fixed">
<div id="list-example" className="list-group">
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-skills">Skills</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-projects">Projects</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-education">Education</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-certification">Certification</a>
<a className="list-group-item list-group-item-action list-group-item-primary" href="#list-courses">Courses</a>
</div>
</div>
<div className="scrollspy-example col-6 offset-3" data-bs-spy="scroll" data-bs-target="#list-example" data-bs-smooth-scroll="true" tabIndex="0">
<section id="list-skills" className="content-section">
<h2 className="text-primary">Skills</h2>
<hr/>
<h4>Programming languages & Tools</h4>
<ul>
<li>Python</li>
<li>PHP</li>
<li>Docker</li>
<li>C#</li>
<li>JavaScript</li>
<li>Node JS</li>
<li>Git</li>
<li>Jenkins</li>
</ul>
</section>
<section id="list-projects" className="content-section">
<h2 className="text-primary">Projects</h2>
<hr/>
<p>Projects I have worked on:</p>
<ul>
<li><Link reloadDocument to="/pages/software/dxp-development">DXP development- OPPLE catalog generator</Link></li>
<li><Link reloadDocument to="/pages/software/configuration-automation">Configuration automation</Link></li>
<li><Link reloadDocument to="/pages/software/wifi-prototype">Wi-Fi prototype</Link></li>
<li><Link reloadDocument to="/pages/software/embedded-game">Embedded Game</Link></li>
<li><Link reloadDocument to="/pages/software/kanji-application">Kanji flashcard Android application</Link></li>
<li><Link reloadDocument to="/pages/software/raspberry-pi-jukebox">Raspberry Pi Jukebox</Link></li>
<li><Link reloadDocument to="/pages/software/attachment-module">Attachment Module</Link></li>
<li><Link reloadDocument to="/pages/software/teslamaze">TeslaMaze</Link></li>
<li><Link reloadDocument to="/pages/software/embedded-internet-radio">Embedded Internet Radio</Link></li>
<li><Link reloadDocument to="/pages/software/windows10-cookbook">Windows 10 Cookbook</Link></li>
<li><Link reloadDocument to="/pages/software/ios-airports">iOS Airports mobile application</Link></li>
<li><Link reloadDocument to="/pages/software/festival-simulator">Java festival crowd simulator</Link></li>
<li><Link reloadDocument to="/pages/software/boebot">Board of Education bot</Link></li>
<li><Link reloadDocument to="/pages/software/metroid-horizontal-shooter">Metroid horizontal shooter</Link></li>
</ul>
</section>
<section id="list-education" className="content-section">
<div className='content-item'>
<h2 className="text-primary">Education</h2>
<hr/>
<h4 className="mb-0">Computer engineering of applied computer science</h4>
<h6>Bachelor of computer science</h6>
<p className="mb-3">Avans Hogeschool - Breda, Netherlands</p>
<span className="text-primary">2012 - 2016</span>
</div>
<div className='content-item'>
<h4 className="mb-0">Interactive media design</h4>
<h6>MBO diploma</h6>
<p className="mb-3">Eindhovenseschool / Sint Lucas - Eindhoven, Netherlands</p>
<span className="text-primary">2009 - 2012</span>
</div>
</section>
<section id="list-certification" className="content-section">
<h2 className="text-primary">Certification</h2>
<hr/>
<div className='content-item'>
<h4 className="mb-0">LPIC-1</h4>
<h6>Linux professional institute certification</h6>
<p><a target="_blank" rel="noreferrer" href="https://www.lpi.org/our-certifications/lpic-1-overview">lpi.org</a></p>
<span className="text-primary">2022 (expires in 2027)</span>
</div>
<div className='content-item'>
<h4 className="mb-0">Drupal 9 Site Builder</h4>
<p><a target="_blank" rel="noreferrer" href="https://certification.acquia.com/user/18196">acquia.com</a></p>
<span className="text-primary">2022</span>
</div>
</section>
<section id="list-courses" className="content-section">
<h2 className="text-primary">Courses</h2>
<hr/>
<div className='content-item'>
<h6 className="mb-0">Docker Mastery: Kubernetes + Swarm from a Docker Captain</h6>
<p>
<a target="_blank" rel="noreferrer" href="https://www.udemy.com/course/docker-mastery/">udemy.com</a>
&nbsp;|&nbsp;
<a href={`${process.env.PUBLIC_URL}/udemy-certs/UC-19ac22fe-70fa-47bd-804c-83f3aa4ac218.jpg`}>certificate</a>
</p>
<span className="text-primary">2021</span>
</div>
<div className='content-item'>
<h6 className="mb-0">Beginning C++ Programming From Beginner to Beyond</h6>
<p>
<a target="_blank" rel="noreferrer" href="https://www.udemy.com/course/beginning-c-plus-plus-programming/">udemy.com</a>
&nbsp;|&nbsp;
<a href={`${process.env.PUBLIC_URL}/udemy-certs/UC-9f15ebd2-2a9a-489f-b8ca-7e8b175bc12f.pdf`}>certificate</a>
</p>
<span className="text-primary">2020</span>
</div>
<div className='content-item'>
<h6 className="mb-0">Learn Linux in 5 Days and Level Up Your Career</h6>
<p>
<a target="_blank" rel="noreferrer" href="https://www.udemy.com/course/learn-linux-in-5-days/">udemy.com</a>
&nbsp;|&nbsp;
<a href={`${process.env.PUBLIC_URL}/udemy-certs/UC-0BB6GYJ1.pdf`}>certificate</a>
</p>
<span className="text-primary">2019</span>
</div>
</section>
</div>
</div>
)
}
export default Software;

View File

@ -0,0 +1,17 @@
import React from 'react';
import Emoji from '../../Content/Emoji';
import MarkdownPage from '../markdownPage';
import { getLanguage } from '../../App';
const SoftwareMain = () => {
const language = getLanguage();
return (
<article className="main-page">
<h1 id="list-intro" className="text-primary">Software <Emoji symbol="🖥️" /></h1>
<MarkdownPage md={'Software/' + language + '/main.md'} />
</article>
)
}
export default SoftwareMain;

View File

@ -0,0 +1,72 @@
Skills
------
#### Programming languages & Tools
* Python
* PHP
* Docker
* C#
* JavaScript
* Node JS
* Git
* Jenkins
Education
---------
#### Computer engineering of applied computer science
###### Bachelor of computer science
Avans Hogeschool - Breda, Netherlands
2012 - 2016
#### Interactive media design
###### MBO diploma
Eindhovenseschool / Sint Lucas - Eindhoven, Netherlands
2009 - 2012
Certification
-------------
#### LPIC-1
###### Linux professional institute certification
[lpi.org](https://www.lpi.org/our-certifications/lpic-1-overview)
2022 (expires in 2027)
#### Drupal 9 Site Builder
[acquia.com](https://certification.acquia.com/user/18196)
2022
Courses
-------
###### Docker Mastery: Kubernetes + Swarm from a Docker Captain
[udemy.com](https://www.udemy.com/course/docker-mastery/)  |  [certificate]({`${process.env.PUBLIC_URL}/udemy-certs/UC-19ac22fe-70fa-47bd-804c-83f3aa4ac218.jpg`})
2021
###### Beginning C++ Programming From Beginner to Beyond
[udemy.com](https://www.udemy.com/course/beginning-c-plus-plus-programming/)  |  [certificate]({`${process.env.PUBLIC_URL}/udemy-certs/UC-9f15ebd2-2a9a-489f-b8ca-7e8b175bc12f.pdf`})
2020
###### Learn Linux in 5 Days and Level Up Your Career
[udemy.com](https://www.udemy.com/course/learn-linux-in-5-days/)  |  [certificate]({`${process.env.PUBLIC_URL}/udemy-certs/UC-0BB6GYJ1.pdf`})
2019

View File

@ -0,0 +1,72 @@
Vaardigheden
------------
#### Programmeertalen en tools
* Python
* PHP
* Docker
* C#
* JavaScript
* Node JS
* Git
* Jenkins
Opleiding
---------
#### Computer engineering of applied computer science
###### Bachelor of computer science
Avans Hogeschool - Breda
2012 - 2016
#### Interactieve media design
###### MBO diploma
Eindhovenseschool / Sint Lucas - Eindhoven
2009 - 2012
Certificering
-------------
#### LPIC-1
###### Linux professional institute certification
[lpi.org](https://www.lpi.org/our-certifications/lpic-1-overview)
2022 (verloopt 2027)
#### Drupal 9 Site Builder
[acquia.com](https://certification.acquia.com/user/18196)
2022
Cursussen
---------
###### Docker Mastery: Kubernetes + Swarm from a Docker Captain
[udemy.com](https://www.udemy.com/course/docker-mastery/)  |  [certificate]({`${process.env.PUBLIC_URL}/udemy-certs/UC-19ac22fe-70fa-47bd-804c-83f3aa4ac218.jpg`})
2021
###### Beginning C++ Programming From Beginner to Beyond
[udemy.com](https://www.udemy.com/course/beginning-c-plus-plus-programming/)  |  [certificate]({`${process.env.PUBLIC_URL}/udemy-certs/UC-9f15ebd2-2a9a-489f-b8ca-7e8b175bc12f.pdf`})
2020
###### Learn Linux in 5 Days and Level Up Your Career
[udemy.com](https://www.udemy.com/course/learn-linux-in-5-days/)  |  [certificate]({`${process.env.PUBLIC_URL}/udemy-certs/UC-0BB6GYJ1.pdf`})
2019

20
src/Pages/home-en.md Normal file
View File

@ -0,0 +1,20 @@
I am a programmer as profession.
I worked on:
* Configuration automation
* Product lifecycle management
* DXP development
My interests are:
* Software development
* Japanese language
* Amateur radio
* Linux
* Electronics
* Woodworking
* Yoga
* Synthesize music
I am based in Helmond, the Netherlands.

20
src/Pages/home-nl.md Normal file
View File

@ -0,0 +1,20 @@
Ik ben een programmeur van beroep.
Ik heb gewerkt aan:
* Configuration automatisering
* Product lifecycle management
* DXP ontwikkeling
Mijn andere interesses:
* Software ontwikkeling
* Japanse taal
* Radiozendamateurisme
* Linux
* Electronica
* Houtbewerking
* Yoga
* Synthesizer muziek
Ik woon in Helmond.

View File

@ -16,7 +16,7 @@ const MarkdownPage = ({ md }) => {
.catch(err => console.log(err)); .catch(err => console.log(err));
}); });
const MyArticle = ({ children }) => <article className="main-page">{children}</article> const MySection = ({ children }) => <section>{children}</section>
const MyParagraph = ({ children, ...props }) => <h1 {...props}>{children}</h1> const MyParagraph = ({ children, ...props }) => <h1 {...props}>{children}</h1>
@ -32,7 +32,7 @@ const MarkdownPage = ({ md }) => {
return ( return (
<Markdown options={{ <Markdown options={{
wrapper: MyArticle, wrapper: MySection,
overrides: { overrides: {
h1: { h1: {
component: MyParagraph, component: MyParagraph,

View File

@ -1,15 +1,17 @@
import React from 'react'; import React from 'react';
import { useTheme } from '../ThemeContext'; import { useTheme } from '../ThemeContext';
import './Footer.css'; import './Footer.css';
import { getLanguage, getString } from '../App';
const Footer = () => { const Footer = () => {
const { theme } = useTheme(); const { theme } = useTheme();
const language = getLanguage();
return ( return (
<footer className={`bg-${theme} text-center text-lg-start text-${theme}`}> <footer className={`bg-${theme} text-center text-lg-start text-${theme}`}>
<p className="small">This site was made with: <a className={`link-${theme}`} href="https://reactjs.org/" target="_blank" rel="noopener noreferrer">React</a>, <a className={`link-${theme}`} href="https://fsharp.org/" target="_blank" rel="noopener noreferrer">F#</a>, <a className={`link-${theme}`} href="https://github.com/giraffe-fsharp/Giraffe" target="_blank" rel="noopener noreferrer">Giraffe</a>, <a className={`link-${theme}`} href="https://getbootstrap.com/" target="_blank" rel="noopener noreferrer">Bootstrap</a>, <a className={`link-${theme}`} href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer">Nginx</a> and <a className={`link-${theme}`} href="https://www.docker.com/" target="_blank" rel="noopener noreferrer">Docker</a> on <a className={`link-${theme}`} href="https://www.digitalocean.com/" target="_blank" rel="noopener noreferrer">DigitalOcean</a> cloud droplets.</p> <p className="small">{getString(language, 'footer_madewith')}: <a className={`link-${theme}`} href="https://reactjs.org/" target="_blank" rel="noopener noreferrer">React</a>, <a className={`link-${theme}`} href="https://fsharp.org/" target="_blank" rel="noopener noreferrer">F#</a>, <a className={`link-${theme}`} href="https://github.com/giraffe-fsharp/Giraffe" target="_blank" rel="noopener noreferrer">Giraffe</a>, <a className={`link-${theme}`} href="https://getbootstrap.com/" target="_blank" rel="noopener noreferrer">Bootstrap</a>, <a className={`link-${theme}`} href="https://www.nginx.com/" target="_blank" rel="noopener noreferrer">Nginx</a> {getString(language, 'and')} <a className={`link-${theme}`} href="https://www.docker.com/" target="_blank" rel="noopener noreferrer">Docker</a> {getString(language, 'on')} <a className={`link-${theme}`} href="https://www.digitalocean.com/" target="_blank" rel="noopener noreferrer">DigitalOcean</a> cloud droplets.</p>
<p className="small">Content is parsed by: <a className={`link-${theme}`} href="https://github.com/quantizor/markdown-to-jsx" target="_blank" rel="noopener noreferrer">markdown-to-jsx</a></p> <p className="small">{getString(language, 'footer_contentparsed')}: <a className={`link-${theme}`} href="https://github.com/quantizor/markdown-to-jsx" target="_blank" rel="noopener noreferrer">markdown-to-jsx</a></p>
</footer> </footer>
) )
} }

View File

@ -1,20 +1,24 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useTheme } from '../ThemeContext'; import { useTheme } from '../ThemeContext';
import { getString, getLanguage } from '../App';
import './Navigation.css'; import './Navigation.css';
// Cheating, but it works until I know better. function generatePath(language) {
let section = window.location.pathname.split('/')[2]; const currentPath = window.location.pathname;
let chapter = window.location.pathname.split('/')[3]; return `/${language}${currentPath.substring(currentPath.indexOf('/', 1))}`;
}
const Navigation = () => { const Navigation = ({ language }) => {
const { theme, updateTheme } = useTheme(); const { theme, updateTheme } = useTheme();
const toggleTheme = () => { const toggleTheme = () => {
updateTheme((theme === 'light') ? 'dark' : 'light'); updateTheme((theme === 'light') ? 'dark' : 'light');
} }
const currentLanguage = getLanguage();
return ( return (
<nav className={`navbar navbar-expand-lg fixed-top text-${theme} navbar-${theme} bg-${theme}`}> <nav className={`navbar navbar-expand-lg fixed-top text-${theme} navbar-${theme} bg-${theme}`}>
<div className="container-fluid"> <div className="container-fluid">
@ -26,45 +30,29 @@ const Navigation = () => {
<ul className="navbar-nav me-auto mb-2 mb-lg-0"> <ul className="navbar-nav me-auto mb-2 mb-lg-0">
<li className="nav-item dropdown"> <li className="nav-item dropdown">
<a className="nav-link dropdown-toggle active" href="#!" role="button" data-bs-toggle="dropdown" aria-expanded="false"> <a className="nav-link dropdown-toggle active" href="#!" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Portal {getString(language, 'portal')}
</a> </a>
<ul className="dropdown-menu"> <ul className="dropdown-menu">
<li><Link reloadDocument to="/pages/japanese" className="dropdown-item">Japanese</Link></li> <li><Link reloadDocument to={currentLanguage + '/japan'} className="dropdown-item">{getString(language, 'japanese')}</Link></li>
<li><hr className="dropdown-divider" /></li> <li><hr className="dropdown-divider" /></li>
<li><Link reloadDocument to="/pages/radio" className="dropdown-item">Radio Amateur</Link></li> <li><Link reloadDocument to={currentLanguage + '/radio'} className="dropdown-item">{getString(language, 'radio_amateur')}</Link></li>
<li><hr className="dropdown-divider" /></li> <li><hr className="dropdown-divider" /></li>
<li><Link reloadDocument to="/pages/software" className="dropdown-item">Software</Link></li> <li><Link reloadDocument to={currentLanguage + '/software'} className="dropdown-item">{getString(language, 'software')}</Link></li>
{/* <li><hr className="dropdown-divider"/></li> </ul>
<li><Link reloadDocument to="/pages/linux" className="dropdown-item">Linux</Link></li> */} </li>
<li className="nav-item dropdown">
<a className="nav-link dropdown-toggle active" href="#!" role="button" data-bs-toggle="dropdown" aria-expanded="false">
{getString(language, 'language')}
</a>
<ul className="dropdown-menu">
<li><Link reloadDocument to={generatePath("en")} className="dropdown-item">English</Link></li>
<li><hr className="dropdown-divider" /></li>
<li><Link reloadDocument to={generatePath("nl")} className="dropdown-item">Nederlands</Link></li>
</ul> </ul>
</li> </li>
{section === 'software' &&
<li className="nav-item">
<Link reloadDocument to="/pages/software#list-projects" className="nav-link">Projects</Link>
</li>
}
{section === 'radio' &&
<li className="nav-item">
<Link reloadDocument to="/pages/radio/components" className={`nav-link ${chapter === "components" ? "active" : ""}`}>Components</Link>
</li>
}
{section === 'radio' &&
<li className="nav-item">
<Link reloadDocument to="/pages/radio/balcony" className={`nav-link ${chapter === "balcony" ? "active" : ""}`}>Balcony</Link>
</li>
}
{section === 'radio' &&
<li className="nav-item">
<Link reloadDocument to="/pages/radio/fielddays" className={`nav-link ${chapter === "fielddays" ? "active" : ""}`}>Field days</Link>
</li>
}
</ul> </ul>
{/* style={{display: 'none'}} */}
<button onClick={toggleTheme} type="button" className={`btn btn-${theme}`}>Toggle Theme</button> <button onClick={toggleTheme} type="button" className={`btn btn-${theme}`}>Toggle Theme</button>
{/* <form className="d-flex" role="search">
<input className="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
<button className="btn btn-outline-success" type="submit">Search</button>
</form> */}
</div> </div>
</div> </div>
</nav> </nav>

View File

@ -66,7 +66,6 @@ body.light {
.table-fielddays { .table-fielddays {
font-size: small; font-size: small;
white-space: nowrap; white-space: nowrap;
margin: auto;
margin-bottom: 10px; margin-bottom: 10px;
} }