Skip to content

Commit 42bae73

Browse files
authored
feat: more things translatable, in-context translation setup directions (#188)
1 parent a831783 commit 42bae73

File tree

9 files changed

+75
-34
lines changed

9 files changed

+75
-34
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ typings/
213213
.env
214214
.env.test
215215
.env*.local
216+
.env*.personal
216217

217218
# parcel-bundler cache (https://parceljs.org/)
218219
.cache

CONTRIBUTING.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ inside the container.
3232
At the highest level you must at least have:
3333

3434
* [Bun](https://bun.sh/)
35-
* terminal (Bash is suggested but not required.)
35+
* Bash terminal (others may fail to run some scripts)
3636

3737
### bun installation
3838

@@ -107,6 +107,27 @@ export NODE_ENV=staging; set -o allexport; source .env.staging; set +o allexport
107107

108108
After running this command, all commands you run in that bash session will have those environment variables loaded.
109109

110+
### Localization
111+
112+
If you'd like to help translate and localize SMM to different languages, join our [discord server](https://discord.ficsit.app/).
113+
114+
ficsit.app handles localization through the Tolgee Svelte integration.
115+
This allows for [in-context translation](https://tolgee.io/js-sdk/) - simply alt-click on a translatable element to open the Tolgee interface.
116+
If an element can't be alt-clicked it either doesn't support in-context translation or isn't translatable yet.
117+
You can also edit translations from the [project's webpage](https://translate.ficsit.app/projects/2).
118+
119+
In order to edit translations in-context, you will need to provide a tolgee API key with edit permissions.
120+
To do this:
121+
122+
1. Join the Discord and get added to the smr-frontend Tolgee project
123+
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)
124+
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)
125+
4. Replace the `PUBLIC_TOLGEE_API_KEY` in your new env file with the API key you generated
126+
5. Use your new env name when running commands.
127+
For example, run `fenv personal` to switch to it.
128+
129+
Using the in-context translation Screenshot feature also requires installing the _Tolgee Tools_ browser extension.
130+
110131
### Downloading Translations
111132

112133
This project uses Tolgee to manage translations.

cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"words": [
99
"cfworker",
1010
"felte",
11+
"fenv",
1112
"ficsit",
1213
"gpgsign",
1314
"pnpx",

src/lib/components/mods/compatibility/CompatibilityGrid.svelte

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
export let compatibility: CompatibilityInfoInput;
1111
1212
export const { t } = getTranslate();
13-
export const noNotesText = '(No extra notes)';
13+
export const noNotesText = $t('compatibility-info.no-notes');
1414
1515
const modalStore = getModalStore();
1616
const openCompatibility = () => {
@@ -28,26 +28,29 @@
2828

2929
<div class="card p-4">
3030
<div class="grid grid-flow-row gap-y-2">
31-
<h3 class="my-4 text-2xl font-bold">Compatibility Information</h3>
32-
<p>Click the colored text for more details.</p>
31+
<h3 class="my-4 text-2xl font-bold">{$t('compatibility-info.header')}</h3>
32+
<p>{$t('compatibility-info.subtitle')}</p>
3333
<div class="grid grid-flow-row">
3434
<table aria-label="Available Releases" class="max-w-auto table table-hover !overflow-visible">
3535
<tbody>
3636
<tr class="rounded border !border-surface-500">
37-
<td><div class="flex items-center justify-center"><CompatibilityIcon /> Early Access</div></td>
3837
<td
3938
><div class="flex items-center justify-center">
40-
<CompatibilityIcon EXP={true} /> Experimental
39+
<CompatibilityIcon />{$t('compatibility-info.branch.stable')}
40+
</div></td>
41+
<td
42+
><div class="flex items-center justify-center">
43+
<CompatibilityIcon EXP={true} />{$t('compatibility-info.branch.unstable')}
4144
</div></td>
4245
</tr>
4346
<tr class="rounded border !border-surface-500">
4447
<td class="text-center">
45-
<button class="m-0 min-w-0" title="Click for more information" on:click={openCompatibility}>
48+
<button class="m-0 min-w-0" title={$t('tooltip.click-for-info')} on:click={openCompatibility}>
4649
<CompatibilityStateText state={compatibility?.EA?.state} />
4750
</button>
4851
</td>
4952
<td class="text-center">
50-
<button class="m-0 min-w-0" title="Click for more information" on:click={openCompatibility}>
53+
<button class="m-0 min-w-0" title={$t('tooltip.click-for-info')} on:click={openCompatibility}>
5154
<CompatibilityStateText state={compatibility?.EXP?.state} />
5255
</button>
5356
</td>

src/lib/components/utils/TagList.svelte

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import { Autocomplete, type AutocompleteOption, InputChip, type PopupSettings, popup } from '@skeletonlabs/skeleton';
66
import { onMount } from 'svelte';
77
import TagDisplay from './TagDisplay.svelte';
8+
import { getTranslate } from '@tolgee/svelte';
9+
10+
export const { t } = getTranslate();
811
912
const client = getContextClient();
1013
@@ -21,10 +24,10 @@
2124
export let popupTriggerEvent: PopupSettings['event'] = 'click';
2225
2326
$: allTags =
24-
$getAllTags.data?.getTags?.map((t) => ({
25-
label: `${t.name} - ${t.description}`,
26-
value: t.id,
27-
name: t.name
27+
$getAllTags.data?.getTags?.map((tag) => ({
28+
label: `${tag.name} - ${tag.description}`,
29+
value: tag.id,
30+
name: tag.name
2831
})) || ([] satisfies AutocompleteOption[]);
2932
3033
const popupSettings: PopupSettings = {
@@ -34,16 +37,16 @@
3437
};
3538
3639
let tagList = [];
37-
const loadTagList = () => (tagList = tags.map((t: Tag) => t.name));
40+
const loadTagList = () => (tagList = tags.map((tag: Tag) => tag.name));
3841
3942
onMount(loadTagList);
4043
41-
const addTag = (tag: AutocompleteOption) => {
42-
const realTag = $getAllTags.data?.getTags?.find((t) => t.id == tag.value);
44+
const addTag = (tagToAdd: AutocompleteOption) => {
45+
const realTag = $getAllTags.data?.getTags?.find((tag) => tag.id == tagToAdd.value);
4346
tags = [
4447
...tags,
4548
{
46-
id: tag.value,
49+
id: tagToAdd.value,
4750
name: realTag?.name,
4851
description: realTag?.description
4952
}
@@ -53,7 +56,7 @@
5356
};
5457
5558
const removeTag = (label: string) => {
56-
const idx = tags.findIndex((t) => t.name === label);
59+
const idx = tags.findIndex((tag) => tag.name === label);
5760
tags = [...tags.slice(0, idx), ...tags.slice(idx + 1)];
5861
5962
loadTagList();
@@ -72,22 +75,22 @@
7275
</div>
7376
{/if}
7477
{:else}
75-
<div class="mb-2">Tags</div>
78+
<div class="mb-2">{$t('mod.tags.title')}</div>
7679

7780
<div use:popup={popupSettings}>
7881
<InputChip
7982
bind:input={inputTag}
8083
bind:value={tagList}
81-
on:remove={(t) => removeTag(t.detail.chipValue)}
84+
on:remove={(tag) => removeTag(tag.detail.chipValue)}
8285
name="tags"
8386
chips="variant-filled-primary" />
8487
</div>
8588

8689
<div class="card max-h-48 w-max max-w-full overflow-y-auto p-4" tabindex="-1" data-popup="popupAutocomplete">
8790
<Autocomplete
8891
bind:input={inputTag}
89-
options={allTags.filter((t) => tagList.indexOf(t.name) < 0)}
90-
on:selection={(t) => addTag(t.detail)} />
92+
options={allTags.filter((tag) => tagList.indexOf(tag.name) < 0)}
93+
on:selection={(tag) => addTag(tag.detail)} />
9194
</div>
9295
{/if}
9396
</div>

src/routes/mod/[modId]/+page.svelte

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
import { getModalStore, getToastStore, type ModalSettings } from '@skeletonlabs/skeleton';
1818
import EditCompatibilityModal from '$lib/modals/EditCompatibilityModal.svelte';
1919
import Page404 from '$lib/components/general/Page404.svelte';
20+
import { getTranslate } from '@tolgee/svelte';
2021
2122
export let data: PageData;
2223
24+
export const { t } = getTranslate();
25+
2326
$: ({ modId, mod } = data);
2427
2528
const client = getContextClient();
@@ -46,7 +49,7 @@
4649
});
4750
} else {
4851
toastStore.trigger({
49-
message: `Mod deleted`,
52+
message: $t('mod.toast.mod-deleted'),
5053
background: 'variant-filled-success',
5154
timeout: 5000
5255
});
@@ -57,8 +60,8 @@
5760
5861
const deleteModal: ModalSettings = {
5962
type: 'confirm',
60-
title: 'Delete Mod?',
61-
body: 'Are you sure you wish to delete this mod?',
63+
title: $t('mod.modal.delete.title'),
64+
body: $t('mod.modal.delete.text'),
6265
response: (r: boolean) => {
6366
if (r) {
6467
deleteModFn();
@@ -103,27 +106,27 @@
103106
{#if canUserEdit}
104107
<button class="variant-ghost-primary btn" on:click={() => goto(base + '/mod/' + modId + '/edit')}>
105108
<span class="material-icons pr-2">edit</span>
106-
Edit</button>
109+
{$t('mod.edit')}</button>
107110
<button class="variant-ghost-primary btn" on:click={() => modalStore.trigger(deleteModal)}>
108111
<span class="material-icons pr-2">delete_forever</span>
109-
Delete</button>
112+
{$t('mod.delete')}</button>
110113
<button class="variant-ghost-primary btn" on:click={() => goto(base + '/mod/' + modId + '/new-version')}>
111114
<span class="material-icons pr-2">upload_file</span>
112-
New Version</button>
115+
{$t('mod.new-version')}</button>
113116
{/if}
114117
{#if canUserEditCompatibility}
115118
<button class="variant-ghost-primary btn" on:click={() => modalStore.trigger(editCompatibilityModal)}>
116119
<span class="material-icons">rocket_launch</span>
117120
<span class="material-icons pr-2">science</span>
118-
Edit Compatibility</button>
121+
{$t('mod.edit-compatibility')}</button>
119122
{/if}
120123
<button class="variant-ghost-primary btn" on:click={() => (versionsTab = !versionsTab)}>
121124
{#if !versionsTab}
122125
<span class="material-icons pr-2" title="Browse all uploaded versions of this mod">view_list</span>
123-
View Versions
126+
{$t('mod.view-versions')}
124127
{:else}
125128
<span class="material-icons pr-2" title="View the description page for this mod">description</span>
126-
View Description
129+
{$t('mod.view-description')}
127130
{/if}
128131
</button>
129132
</div>

src/routes/mod/[modId]/new-version/+page.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
import type { PageData } from './$types';
1313
import { getModalStore, getToastStore, type ModalSettings } from '@skeletonlabs/skeleton';
1414
import EditCompatibilityForm from '$lib/components/mods/compatibility/EditCompatibilityForm.svelte';
15+
import { getTranslate } from '@tolgee/svelte';
16+
17+
export const { t } = getTranslate();
1518
1619
export let data: PageData;
1720
@@ -118,7 +121,7 @@
118121
title="View the description page for this mod"
119122
on:click={() => modalStore.trigger(backModal)}>
120123
<span class="material-icons pr-2">arrow_back</span>
121-
Back to Mod
124+
{$t('version.back')}
122125
</button>
123126
</div>
124127
</div>

src/routes/mod/[modId]/version/[versionId]/+page.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
import type { PageData } from './$types';
1616
import { getModalStore, getToastStore, type ModalSettings, popup } from '@skeletonlabs/skeleton';
1717
import Page404 from '$lib/components/general/Page404.svelte';
18+
import { getTranslate } from '@tolgee/svelte';
19+
20+
export const { t } = getTranslate();
1821
1922
export let data: PageData;
2023
@@ -151,7 +154,7 @@
151154
href={base + '/mod/' + modId}
152155
title="View the description page for this mod">
153156
<span class="material-icons">extension</span>
154-
<span>Back to Mod</span>
157+
<span>{$t('version.back')}</span>
155158
</a>
156159
</div>
157160
</div>

src/routes/new-mod/+page.svelte

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
import { base } from '$app/paths';
88
import MetaDescriptors from '$lib/components/utils/MetaDescriptors.svelte';
99
import { getToastStore } from '@skeletonlabs/skeleton';
10+
import { getTranslate } from '@tolgee/svelte';
11+
12+
export const { t } = getTranslate();
1013
1114
const toastStore = getToastStore();
1215
@@ -28,7 +31,7 @@
2831
});
2932
} else {
3033
toastStore.trigger({
31-
message: `Mod created`,
34+
message: $t('new-mod.toast.creation-success'),
3235
background: 'variant-filled-success',
3336
timeout: 5000
3437
});
@@ -42,7 +45,7 @@
4245
<MetaDescriptors description="Adding a new mod in the Satisfactory Mod Repository" title="New mod" />
4346
</svelte:head>
4447

45-
<h1 class="my-4 text-4xl font-bold">New Mod</h1>
48+
<h1 class="my-4 text-4xl font-bold">{$t('new-mod.title')}</h1>
4649

4750
<div class="card p-4">
4851
<section>

0 commit comments

Comments
 (0)