From bc784fcc46452b118c82e14a76b04c425592610d Mon Sep 17 00:00:00 2001 From: Rob B Date: Fri, 27 Sep 2024 22:56:02 +0000 Subject: [PATCH] feat: more things translatable, in-context translation setup directions --- .gitignore | 1 + CONTRIBUTING.md | 23 ++++++++++++++- cspell.json | 1 + .../compatibility/CompatibilityGrid.svelte | 17 ++++++----- src/lib/components/utils/TagList.svelte | 29 ++++++++++--------- src/routes/mod/[modId]/+page.svelte | 21 ++++++++------ .../mod/[modId]/new-version/+page.svelte | 5 +++- .../[modId]/version/[versionId]/+page.svelte | 5 +++- src/routes/new-mod/+page.svelte | 7 +++-- 9 files changed, 75 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 4a7b54ec6..3eabfb4a2 100644 --- a/.gitignore +++ b/.gitignore @@ -213,6 +213,7 @@ typings/ .env .env.test .env*.local +.env*.personal # parcel-bundler cache (https://parceljs.org/) .cache diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index da9dac208..b65721be2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,7 +32,7 @@ inside the container. At the highest level you must at least have: * [Bun](https://bun.sh/) -* terminal (Bash is suggested but not required.) +* Bash terminal (others may fail to run some scripts) ### bun installation @@ -107,6 +107,27 @@ export NODE_ENV=staging; set -o allexport; source .env.staging; set +o allexport After running this command, all commands you run in that bash session will have those environment variables loaded. +### Localization + +If you'd like to help translate and localize SMM to different languages, join our [discord server](https://discord.ficsit.app/). + +ficsit.app handles localization through the Tolgee Svelte integration. +This allows for [in-context translation](https://tolgee.io/js-sdk/) - simply alt-click on a translatable element to open the Tolgee interface. +If an element can't be alt-clicked it either doesn't support in-context translation or isn't translatable yet. +You can also edit translations from the [project's webpage](https://translate.ficsit.app/projects/2). + +In order to edit translations in-context, you will need to provide a tolgee API key with edit permissions. +To do this: + +1. Join the Discord and get added to the smr-frontend Tolgee project +2. Create a copy of the env file you wish to use (such as `.env.staging`) and name it `.env.personal` (so it is gitignored and does not upset dev:serve) +3. Visit [the project's integration page](https://translate.ficsit.app/projects/2/integrate) to generate an API key (the "weapon" you select does not matter) +4. Replace the `PUBLIC_TOLGEE_API_KEY` in your new env file with the API key you generated +5. Use your new env name when running commands. + For example, run `fenv personal` to switch to it. + +Using the in-context translation Screenshot feature also requires installing the _Tolgee Tools_ browser extension. + ### Downloading Translations This project uses Tolgee to manage translations. diff --git a/cspell.json b/cspell.json index 4fee56942..7a9e5db61 100644 --- a/cspell.json +++ b/cspell.json @@ -8,6 +8,7 @@ "words": [ "cfworker", "felte", + "fenv", "ficsit", "gpgsign", "pnpx", diff --git a/src/lib/components/mods/compatibility/CompatibilityGrid.svelte b/src/lib/components/mods/compatibility/CompatibilityGrid.svelte index 87eb355c0..62671e080 100644 --- a/src/lib/components/mods/compatibility/CompatibilityGrid.svelte +++ b/src/lib/components/mods/compatibility/CompatibilityGrid.svelte @@ -10,7 +10,7 @@ export let compatibility: CompatibilityInfoInput; export const { t } = getTranslate(); - export const noNotesText = '(No extra notes)'; + export const noNotesText = $t('compatibility-info.no-notes'); const modalStore = getModalStore(); const openCompatibility = () => { @@ -28,26 +28,29 @@
-

Compatibility Information

-

Click the colored text for more details.

+

{$t('compatibility-info.header')}

+

{$t('compatibility-info.subtitle')}

- + diff --git a/src/lib/components/utils/TagList.svelte b/src/lib/components/utils/TagList.svelte index ac88464da..075a81071 100644 --- a/src/lib/components/utils/TagList.svelte +++ b/src/lib/components/utils/TagList.svelte @@ -5,6 +5,9 @@ import { Autocomplete, type AutocompleteOption, InputChip, type PopupSettings, popup } from '@skeletonlabs/skeleton'; import { onMount } from 'svelte'; import TagDisplay from './TagDisplay.svelte'; + import { getTranslate } from '@tolgee/svelte'; + + export const { t } = getTranslate(); const client = getContextClient(); @@ -21,10 +24,10 @@ export let popupTriggerEvent: PopupSettings['event'] = 'click'; $: allTags = - $getAllTags.data?.getTags?.map((t) => ({ - label: `${t.name} - ${t.description}`, - value: t.id, - name: t.name + $getAllTags.data?.getTags?.map((tag) => ({ + label: `${tag.name} - ${tag.description}`, + value: tag.id, + name: tag.name })) || ([] satisfies AutocompleteOption[]); const popupSettings: PopupSettings = { @@ -34,16 +37,16 @@ }; let tagList = []; - const loadTagList = () => (tagList = tags.map((t: Tag) => t.name)); + const loadTagList = () => (tagList = tags.map((tag: Tag) => tag.name)); onMount(loadTagList); - const addTag = (tag: AutocompleteOption) => { - const realTag = $getAllTags.data?.getTags?.find((t) => t.id == tag.value); + const addTag = (tagToAdd: AutocompleteOption) => { + const realTag = $getAllTags.data?.getTags?.find((tag) => tag.id == tagToAdd.value); tags = [ ...tags, { - id: tag.value, + id: tagToAdd.value, name: realTag?.name, description: realTag?.description } @@ -53,7 +56,7 @@ }; const removeTag = (label: string) => { - const idx = tags.findIndex((t) => t.name === label); + const idx = tags.findIndex((tag) => tag.name === label); tags = [...tags.slice(0, idx), ...tags.slice(idx + 1)]; loadTagList(); @@ -72,13 +75,13 @@ {/if} {:else} -
Tags
+
{$t('mod.tags.title')}
removeTag(t.detail.chipValue)} + on:remove={(tag) => removeTag(tag.detail.chipValue)} name="tags" chips="variant-filled-primary" />
@@ -86,8 +89,8 @@
tagList.indexOf(t.name) < 0)} - on:selection={(t) => addTag(t.detail)} /> + options={allTags.filter((tag) => tagList.indexOf(tag.name) < 0)} + on:selection={(tag) => addTag(tag.detail)} />
{/if} diff --git a/src/routes/mod/[modId]/+page.svelte b/src/routes/mod/[modId]/+page.svelte index 14b42f9c6..202f43095 100644 --- a/src/routes/mod/[modId]/+page.svelte +++ b/src/routes/mod/[modId]/+page.svelte @@ -17,9 +17,12 @@ import { getModalStore, getToastStore, type ModalSettings } from '@skeletonlabs/skeleton'; import EditCompatibilityModal from '$lib/modals/EditCompatibilityModal.svelte'; import Page404 from '$lib/components/general/Page404.svelte'; + import { getTranslate } from '@tolgee/svelte'; export let data: PageData; + export const { t } = getTranslate(); + $: ({ modId, mod } = data); const client = getContextClient(); @@ -46,7 +49,7 @@ }); } else { toastStore.trigger({ - message: `Mod deleted`, + message: $t('mod.toast.mod-deleted'), background: 'variant-filled-success', timeout: 5000 }); @@ -57,8 +60,8 @@ const deleteModal: ModalSettings = { type: 'confirm', - title: 'Delete Mod?', - body: 'Are you sure you wish to delete this mod?', + title: $t('mod.modal.delete.title'), + body: $t('mod.modal.delete.text'), response: (r: boolean) => { if (r) { deleteModFn(); @@ -103,27 +106,27 @@ {#if canUserEdit} + {$t('mod.edit')} + {$t('mod.delete')} + {$t('mod.new-version')} {/if} {#if canUserEditCompatibility} + {$t('mod.edit-compatibility')} {/if} diff --git a/src/routes/mod/[modId]/new-version/+page.svelte b/src/routes/mod/[modId]/new-version/+page.svelte index 631c5eb25..16c45af52 100644 --- a/src/routes/mod/[modId]/new-version/+page.svelte +++ b/src/routes/mod/[modId]/new-version/+page.svelte @@ -12,6 +12,9 @@ import type { PageData } from './$types'; import { getModalStore, getToastStore, type ModalSettings } from '@skeletonlabs/skeleton'; import EditCompatibilityForm from '$lib/components/mods/compatibility/EditCompatibilityForm.svelte'; + import { getTranslate } from '@tolgee/svelte'; + + export const { t } = getTranslate(); export let data: PageData; @@ -118,7 +121,7 @@ title="View the description page for this mod" on:click={() => modalStore.trigger(backModal)}> arrow_back - Back to Mod + {$t('version.back')} diff --git a/src/routes/mod/[modId]/version/[versionId]/+page.svelte b/src/routes/mod/[modId]/version/[versionId]/+page.svelte index 18a40d5f9..e29f34c1f 100644 --- a/src/routes/mod/[modId]/version/[versionId]/+page.svelte +++ b/src/routes/mod/[modId]/version/[versionId]/+page.svelte @@ -15,6 +15,9 @@ import type { PageData } from './$types'; import { getModalStore, getToastStore, type ModalSettings, popup } from '@skeletonlabs/skeleton'; import Page404 from '$lib/components/general/Page404.svelte'; + import { getTranslate } from '@tolgee/svelte'; + + export const { t } = getTranslate(); export let data: PageData; @@ -151,7 +154,7 @@ href={base + '/mod/' + modId} title="View the description page for this mod"> extension - Back to Mod + {$t('version.back')} diff --git a/src/routes/new-mod/+page.svelte b/src/routes/new-mod/+page.svelte index 675eb9581..366de9b52 100644 --- a/src/routes/new-mod/+page.svelte +++ b/src/routes/new-mod/+page.svelte @@ -7,6 +7,9 @@ import { base } from '$app/paths'; import MetaDescriptors from '$lib/components/utils/MetaDescriptors.svelte'; import { getToastStore } from '@skeletonlabs/skeleton'; + import { getTranslate } from '@tolgee/svelte'; + + export const { t } = getTranslate(); const toastStore = getToastStore(); @@ -28,7 +31,7 @@ }); } else { toastStore.trigger({ - message: `Mod created`, + message: $t('new-mod.toast.creation-success'), background: 'variant-filled-success', timeout: 5000 }); @@ -42,7 +45,7 @@ -

New Mod

+

{$t('new-mod.title')}

Early Access
- Experimental + {$t('compatibility-info.branch.stable')} +
+ {$t('compatibility-info.branch.unstable')}
- -