i18n: questions in all langs

minor: readme tweaks
This commit is contained in:
NetMan 2025-12-16 20:59:36 +01:00
parent 6f87d74c34
commit 36c8115bb6
4 changed files with 58 additions and 29 deletions

View file

@ -35,19 +35,18 @@ The newest at the moment of me writing this (December 16th 2025) are the (visual
- [x] en
- [ ] de
- [ ] ua
- [ ] db: examstore add language field, api handle languages
- [ ] db: (revise) script for processing, (revise and) share appropriate files
- [x] db: examstore add language field, api handle languages (questions lang)
- [ ] clean up js code in exam.vue and result.vue (currently a little bit of a mess)
## Some information about the project
My intention is, to share access to test exams free of charge, you don't have to pay me - although you can, I greatly appreciate if you donate!
In the future I will host this project publicly `aaS`, and will probably put non-invasive, privacy friendly ads if it gains enough traction
I'm planning to host this project publicly and to put non-invasive ads if it gains enough traction
All data used by this software is public information by definition provided in the Polish Constitution - (article 61.)[https://www.sejm.gov.pl/prawo/konst/polski/kon1.htm], and can be acquired by either checking above links on the gov website, or by writing to the Ministry ((if something happened to be missing))[placeholder_for_post_about_missing_points_column]
All data used by this software is public information by definition provided in the Polish Constitution - [article 61.](https://www.sejm.gov.pl/prawo/konst/polski/kon1.htm), and can be acquired by either checking above links on the gov website, or by writing to the Ministry [(if something happened to be missing)](placeholder_for_post_about_missing_points_column) ==> (blog post to write in the future)
This project is a website mimicking an official driver's license theoritical exam (for different license categories) with a seperate media server, connected using drizzle ORM to a SQLite database
This project is a website mimicking an official driver's license theoritical exam (for all license categories provided by the Ministry: A, A1, A2, AM, B, B1, C, C1, D, D1, T, PT) with a seperate media http server (not included here), connected using drizzle ORM to a SQLite database
## Setup
@ -57,7 +56,11 @@ This project utilizes `pnpm`, thus it is recommended
pnpm install
```
## Development Server
Check out `.env.example`, mainly CDN_URL for media http url
As of Dec. 16 2025 a test database is included at `./db/database.db`
### Development Server
Start the development server on `http://localhost:3000`:
@ -65,7 +68,7 @@ Start the development server on `http://localhost:3000`:
pnpm run dev
```
## Production
### Production
Build the application for production:

View file

@ -116,6 +116,7 @@ const {
} = await useLazyFetch<BasicQuestion[]>(`/api/basic`, {
query: {
category: examStore.category,
lang: examStore.lang,
},
});
@ -126,6 +127,7 @@ const {
} = await useLazyFetch<AdvancedQuestion[]>(`/api/advanced`, {
query: {
category: examStore.category,
lang: examStore.lang,
},
});

View file

@ -9,22 +9,34 @@ import categories from '~/categories';
export default defineEventHandler(async (event) => {
const query = getQuery(event);
const category = query.category;
const lang = query.lang;
if (category === '' || typeof category !== 'string') {
throw createError({
statusCode: 400,
statusMessage:
'category argument has to be string (or not to be defined at all)',
});
}
if (!categories.includes(`${category.toUpperCase()}`)) {
if (
typeof category !== 'string' ||
!categories.includes(`${category.toUpperCase()}`)
) {
throw createError({
statusCode: 400,
statusMessage: `category argument has to be equal to either: ${categories}`,
});
}
async function getFromDb(points: number, limit: number, category: string) {
if (
typeof lang !== 'string' ||
!['PL', 'EN', 'DE', 'UA'].includes(`${lang.toUpperCase()}`)
) {
throw createError({
statusCode: 400,
statusMessage: `lang argument has to be equal to either: pl, en, de, ua`,
});
}
async function getFromDb(
points: number,
limit: number,
category: string,
lang: string,
) {
return await db
.select({
id: tasks_advanced.id,
@ -45,7 +57,7 @@ export default defineEventHandler(async (event) => {
.where(
and(
eq(categories_db.name, category.toUpperCase()),
eq(questions_advanced.lang, 'PL'),
eq(questions_advanced.lang, lang.toUpperCase()),
eq(tasks_advanced.weight, points),
),
)
@ -57,7 +69,7 @@ export default defineEventHandler(async (event) => {
const randomizedQuestions: AdvancedQuestion[] = [];
for (const [key, value] of Object.entries({ 1: 2, 2: 4, 3: 6 })) {
randomizedQuestions.push(...(await getFromDb(+key, value, category)));
randomizedQuestions.push(...(await getFromDb(+key, value, category, lang)));
}
return arrayShuffle(randomizedQuestions);
});

View file

@ -9,22 +9,34 @@ import categories from '~/categories';
export default defineEventHandler(async (event) => {
const query = getQuery(event);
const category = query.category;
const lang = query.lang;
if (category === '' || typeof category !== 'string') {
throw createError({
statusCode: 400,
statusMessage:
'category argument has to be string (or not to be defined at all)',
});
}
if (!categories.includes(`${category.toUpperCase()}`)) {
if (
typeof category !== 'string' ||
!categories.includes(`${category.toUpperCase()}`)
) {
throw createError({
statusCode: 400,
statusMessage: `category argument has to be equal to either: ${categories}`,
});
}
async function getFromDb(points: number, limit: number, category: string) {
if (
typeof lang !== 'string' ||
!['PL', 'EN', 'DE', 'UA'].includes(`${lang.toUpperCase()}`)
) {
throw createError({
statusCode: 400,
statusMessage: `lang argument has to be equal to either: pl, en, de, ua`,
});
}
async function getFromDb(
points: number,
limit: number,
category: string,
lang: string,
) {
return await db
.select({
id: tasks.id,
@ -39,7 +51,7 @@ export default defineEventHandler(async (event) => {
.where(
and(
eq(categories_db.name, category.toUpperCase()),
eq(questions.lang, 'PL'),
eq(questions.lang, lang.toUpperCase()),
eq(tasks.weight, points),
),
)
@ -51,7 +63,7 @@ export default defineEventHandler(async (event) => {
const randomizedQuestions: BasicQuestion[] = [];
for (const [key, value] of Object.entries({ 1: 4, 2: 6, 3: 10 })) {
randomizedQuestions.push(...(await getFromDb(+key, value, category)));
randomizedQuestions.push(...(await getFromDb(+key, value, category, lang)));
}
return arrayShuffle(randomizedQuestions);
});