Skip to content

Commit

Permalink
Merge pull request #107 from ssciwr/combine_localization
Browse files Browse the repository at this point in the history
Refactor localisation
  • Loading branch information
MaHaWo authored Oct 15, 2024
2 parents 1fbb03d + 2c14765 commit 41acbad
Show file tree
Hide file tree
Showing 23 changed files with 714 additions and 579 deletions.
28 changes: 14 additions & 14 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,31 @@
"@hey-api/openapi-ts": "0.53.5",
"@sveltejs/adapter-auto": "^3.2.5",
"@sveltejs/adapter-static": "^3.0.5",
"@sveltejs/kit": "^2.5.28",
"@sveltejs/kit": "^2.6.4",
"@sveltejs/vite-plugin-svelte": "4.0.0-next.7",
"@tailwindcss/typography": "^0.5.15",
"@testing-library/svelte": "^5.2.1",
"@testing-library/svelte": "^5.2.3",
"@types/eslint": "^9.6.1",
"@vitest/coverage-v8": "^2.1.1",
"@vitest/coverage-v8": "^2.1.2",
"autoprefixer": "^10.4.20",
"eslint": "^9.11.1",
"eslint": "^9.12.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.44.0",
"flowbite": "^2.5.1",
"flowbite-svelte": "^0.46.17",
"eslint-plugin-svelte": "^2.44.1",
"flowbite": "^2.5.2",
"flowbite-svelte": "^0.46.23",
"flowbite-svelte-icons": "2.0.0-next.16",
"globals": "^15.9.0",
"globals": "^15.11.0",
"jsdom": "^25.0.1",
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.6",
"prettier-plugin-tailwindcss": "^0.6.6",
"prettier-plugin-svelte": "^3.2.7",
"prettier-plugin-tailwindcss": "^0.6.8",
"svelte": "5.0.0-next.263",
"svelte-check": "^3.8.6",
"tailwindcss": "^3.4.13",
"typescript": "^5.6.2",
"typescript-eslint": "^8.7.0",
"vite": "^5.4.7",
"vitest": "^2.1.1"
"typescript": "^5.6.3",
"typescript-eslint": "^8.8.1",
"vite": "^5.4.8",
"vitest": "^2.1.2"
},
"type": "module",
"dependencies": {
Expand Down
916 changes: 456 additions & 460 deletions frontend/pnpm-lock.yaml

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion frontend/src/lib/admin.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ function AdminUser() {
return user;
},
login: async function (loginData: Body_auth_cookie_login_auth_login_post) {
console.log(loginData);
const { data, error } = await authCookieLogin({ body: loginData });
if (error) {
return error?.detail as string;
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/lib/client/services.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import type {
DeleteLanguageData,
DeleteLanguageError,
DeleteLanguageResponse,
UpdateI18NData,
UpdateI18NError,
UpdateI18NResponse,
GetMilestoneGroupsAdminError,
GetMilestoneGroupsAdminResponse,
CreateMilestoneGroupAdminError,
Expand Down Expand Up @@ -219,6 +222,18 @@ export const deleteLanguage = <ThrowOnError extends boolean = false>(
});
};

/**
* Update I18N
*/
export const updateI18N = <ThrowOnError extends boolean = false>(
options: Options<UpdateI18NData, ThrowOnError>
) => {
return (options?.client ?? client).put<UpdateI18NResponse, UpdateI18NError, ThrowOnError>({
...options,
url: '/admin/i18n/{language_id}'
});
};

/**
* Get Milestone Groups Admin
*/
Expand Down
17 changes: 16 additions & 1 deletion frontend/src/lib/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export type ValidationError = {
};

export type GetLanguagesResponse = {
[key: string]: string;
[key: string]: number;
};

export type GetLanguagesError = unknown;
Expand Down Expand Up @@ -251,6 +251,21 @@ export type DeleteLanguageResponse = unknown;

export type DeleteLanguageError = HTTPValidationError;

export type UpdateI18NData = {
body: {
[key: string]: {
[key: string]: string;
};
};
path: {
language_id: number;
};
};

export type UpdateI18NResponse = unknown;

export type UpdateI18NError = HTTPValidationError;

export type GetMilestoneGroupsAdminResponse = Array<MilestoneGroupAdmin>;

export type GetMilestoneGroupsAdminError = unknown;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
{@const title = $_(`admin.${textKey}`)}
<div class="mb-5">
<Label class="mb-2">{title}</Label>
{#each Object.entries($languages) as [lang_id, lang]}
{#each Object.entries($languages) as [lang, lang_id]}
<div class="mb-1">
<ButtonGroup class="w-full">
<InputAddon>{lang}</InputAddon>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
{@const title = $_(`admin.${textKey}`)}
<div class="mb-5">
<Label class="mb-2">{title}</Label>
{#each Object.entries($languages) as [lang_id, lang]}
{#each Object.entries($languages) as [lang, lang_id]}
<div class="mb-1">
<ButtonGroup class="w-full">
<InputAddon>{lang}</InputAddon>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
<Label class="mb-2">Preview</Label>
<div class="flex flex-row">
<ButtonGroup class="mb-2 mr-2">
{#each Object.entries($languages) as [lang_id, lang]}
{#each Object.entries($languages) as [lang, lang_id]}
<Button
checked={preview_lang_id === lang_id}
on:click={(e) => {
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/lib/components/Admin/Languages.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import ISO6391 from 'iso-639-1';
import { _ } from 'svelte-i18n';
import type { SelectOptionType } from 'flowbite-svelte';
import { updateLanguages } from '$lib/i18n';
import { getTranslations } from '$lib/i18n';
import { languages } from '$lib/stores/langStore';
import DeleteModal from '$lib/components/Admin/DeleteModal.svelte';
import AddButton from '$lib/components/Admin/AddButton.svelte';
Expand All @@ -37,7 +37,7 @@
console.log(error);
} else {
console.log(data);
await updateLanguages();
await getTranslations();
}
}
Expand All @@ -49,7 +49,7 @@
console.log(error);
} else {
console.log(data);
await updateLanguages();
await getTranslations();
}
}
</script>
Expand All @@ -63,7 +63,7 @@
<TableHeadCell>Actions</TableHeadCell>
</TableHead>
<TableBody>
{#each Object.entries($languages) as [id, lang]}
{#each Object.entries($languages) as [lang, lang_id]}
<TableBodyRow>
<TableBodyCell>
{lang}
Expand All @@ -74,7 +74,7 @@
<TableBodyCell>
<DeleteButton
onclick={() => {
currentLanguageId = id;
currentLanguageId = lang_id;
showDeleteModal = true;
}}
/>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/components/Admin/Login.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
</div>
<Button type="submit" class="mb-6">Login</Button>
{#if errorCode !== ''}
<Alert>{$_(errorCode)}</Alert>
<Alert>{$_(`login.${errorCode}`)}</Alert>
{/if}
</form>
</div>
Expand Down
93 changes: 93 additions & 0 deletions frontend/src/lib/components/Admin/Translations.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<svelte:options runes={true} />

<script lang="ts">
import {
Accordion,
AccordionItem,
ButtonGroup,
Card,
Input,
InputAddon,
Label,
P,
Table,
TableBody,
TableBodyCell,
TableBodyRow,
TableHead,
TableHeadCell
} from 'flowbite-svelte';
import { onMount } from 'svelte';
import { _ } from 'svelte-i18n';
import { getI18nJson, getTranslations } from '$lib/i18n';
import { languages } from '$lib/stores/langStore';
import { updateI18N } from '$lib/client/services.gen';
import SaveButton from '$lib/components/Admin/SaveButton.svelte';
import de from '../../../locales/de.json';
type Translation = Record<string, Record<string, string>>;
let translations = $state({} as Record<string, Translation>);
async function refreshTranslations() {
for (const [lang, lang_id] of Object.entries($languages)) {
if (lang !== 'de') {
translations[lang] = await getI18nJson(lang_id);
}
}
}
async function saveChanges() {
for (const lang of Object.keys(translations)) {
const { data, error } = await updateI18N({
body: translations[lang],
path: {
language_id: $languages[lang]
}
});
if (error) {
console.log(error);
return;
} else {
console.log(data);
}
}
await getTranslations();
}
onMount(() => refreshTranslations());
</script>

<Card size="xl" class="m-5">
<h3 class="mb-3 text-xl font-medium text-gray-900 dark:text-white">{$_('admin.translations')}</h3>
<Accordion flush>
{#each Object.entries(de) as [section_key, section]}
<AccordionItem>
<span slot="header" class="flex gap-2 text-base">
{section_key}
</span>
{#each Object.entries(section) as [item_key, item]}
<div class="m-2 mb-4 rounded-md border p-2">
<Label class="mb-2">{item_key}</Label>
<div class="mb-1">
<ButtonGroup class="w-full">
<InputAddon>de</InputAddon>
<p class="w-full rounded-r-md border px-2">{item}</p>
</ButtonGroup>
</div>
{#each Object.keys(translations) as lang}
<div class="mb-1">
<ButtonGroup class="w-full">
<InputAddon>{lang}</InputAddon>
<Input bind:value={translations[lang][section_key][item_key]} />
</ButtonGroup>
</div>
{/each}
</div>
{/each}
<div class="my-2 content-center">
<SaveButton onclick={saveChanges} />
</div>
</AccordionItem>
{/each}
</Accordion>
</Card>
2 changes: 1 addition & 1 deletion frontend/src/lib/components/LocaleChooser.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
class="flex items-center"
on:click={() => {
locale.set(loc);
lang_id.set(`${Object.keys($languages).find((key) => $languages[key] === loc)}`);
lang_id.set($languages[loc]);
dropdownOpen = false;
}}
>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/lib/components/Milestone.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@
onClick={() => {
selectAnswer(answerIndex);
}}
tooltip={$_(`milestone.answer${answerIndex}.description`)}
tooltip={$_(`milestone.answer${answerIndex}-desc`)}
>
{$_(`milestone.answer${answerIndex}.text`)}
{$_(`milestone.answer${answerIndex}-text`)}
</MilestoneButton>
{/each}
<div class="flex flex-row justify-center">
Expand Down
41 changes: 33 additions & 8 deletions frontend/src/lib/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,43 @@
import { register, init } from 'svelte-i18n';
import { init, addMessages } from 'svelte-i18n';
import { languages } from '$lib/stores/langStore';
import { getLanguages } from '$lib/client';
import de from '../locales/de.json';

register('de', () => import('../locales/de.json'));
register('en', () => import('../locales/en.json'));
export async function getI18nJson(lang_id: number) {
try {
const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/static/i18n/${lang_id}.json`);
if (!res.ok) {
console.log(
`getI18nJson failed for lang_id ${lang_id} with status ${res.status}, returning de translations`
);
return de;
}
return await res.json();
} catch {
console.log(`getI18nJson failed for lang_id ${lang_id}, returning de translations`);
return de;
}
}

init({
fallbackLocale: 'de',
initialLocale: 'de'
});
async function getTranslation(lang: string, lang_id: number) {
const json = await getI18nJson(lang_id);
addMessages(lang, json);
}

export async function updateLanguages() {
export async function getTranslations() {
const { data, error } = await getLanguages();
if (!error && data) {
languages.set(data);
Object.entries(data).forEach(([lang, lang_id]) => {
if (lang_id !== 1) {
getTranslation(lang, lang_id);
}
});
}
}

addMessages('de', de);
init({
fallbackLocale: 'de',
initialLocale: 'de'
});
Loading

0 comments on commit 41acbad

Please sign in to comment.