Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Localization #239

Merged
merged 54 commits into from
Jun 6, 2024
Merged
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
64107e5
i18n: localize frontpage's layout
Xyphyn Jun 3, 2024
c4236fa
i18n: localize posts
Xyphyn Jun 3, 2024
0f0e34d
i18n: localize profile menu
Xyphyn Jun 3, 2024
f9935ce
i18n: localize post badges
Xyphyn Jun 3, 2024
ae0800b
i18n: localize profile page
Xyphyn Jun 3, 2024
8278cff
i18n: localize accounts page
Xyphyn Jun 3, 2024
3d76bb7
i18n: localize login page
Xyphyn Jun 3, 2024
b626ea3
i18n: localize post layout
Xyphyn Jun 3, 2024
1d5b4d4
i18n: localize community card
Xyphyn Jun 3, 2024
a421093
i18n: localize comments
Xyphyn Jun 3, 2024
2aaacf0
i18n: localize comment form
Xyphyn Jun 3, 2024
9089dd9
i18n: localize explore and search pages
Xyphyn Jun 3, 2024
4441896
i18n: localize post form
Xyphyn Jun 4, 2024
92c57db
i18n: localize inbox
Xyphyn Jun 4, 2024
a488b8b
i18n: localize saved page
Xyphyn Jun 4, 2024
88956bb
i18n: localize community card
Xyphyn Jun 4, 2024
f727193
i18n: localize subscribe button
Xyphyn Jun 4, 2024
bcc007a
i18n: localize blocks
Xyphyn Jun 4, 2024
96d4e5d
i18n: localize profile pages
Xyphyn Jun 4, 2024
a785a52
i18n: localize signup
Xyphyn Jun 4, 2024
c6c5309
i18n: localize moderation
Xyphyn Jun 4, 2024
0cad346
i18n: remove test translations
Xyphyn Jun 4, 2024
53d4e4b
i18n: localize verify email page
Xyphyn Jun 4, 2024
9998042
i18n: localize account pages
Xyphyn Jun 4, 2024
bf94ff6
misc: remove about button
Xyphyn Jun 4, 2024
0493c44
misc: remove node workflow
Xyphyn Jun 4, 2024
6290108
i18n: localize admin config page
Xyphyn Jun 4, 2024
f960062
i18n: Localize applications page
Xyphyn Jun 4, 2024
c3b90d5
i18n: localize taglines and team page
Xyphyn Jun 4, 2024
0066e2d
i18n: localize federation page
Xyphyn Jun 4, 2024
76a0fa0
i18n: localize ban modal
Xyphyn Jun 4, 2024
7d0a060
i18n: localize moderation menu
Xyphyn Jun 4, 2024
13437c8
i18n: localize remove modal
Xyphyn Jun 4, 2024
f6d56ad
i18n: localize report modal
Xyphyn Jun 4, 2024
b57baa3
i18n: localize ocmment moderation menu
Xyphyn Jun 4, 2024
e89d2aa
i18n: localize toasts
Xyphyn Jun 4, 2024
00f70d6
i18n: localize settings page
Xyphyn Jun 4, 2024
3fd36cf
i18n: fix broken english
Xyphyn Jun 4, 2024
d0fe030
i18n: add server-side language selection
Xyphyn Jun 5, 2024
c5aa151
fix: ssr bug in markdown editor
Xyphyn Jun 5, 2024
7c257dc
i18n: fix routes.legal
Xyphyn Jun 5, 2024
d7a4c0e
i18n: localize community page
Xyphyn Jun 5, 2024
7b5f575
fix: broken sessionstorage
Xyphyn Jun 5, 2024
fa1d2e6
misc: update error page
Xyphyn Jun 5, 2024
05e0d58
misc: update version
Xyphyn Jun 5, 2024
9bb98ac
fix: use $locale for relative date
Xyphyn Jun 5, 2024
e7d1291
misc: remove keying on comments
Xyphyn Jun 5, 2024
990f073
feat: add post and comment translation
Xyphyn Jun 5, 2024
6ac44d2
misc: make default translation language your locale
Xyphyn Jun 5, 2024
6664666
misc: improve error handling for translator
Xyphyn Jun 6, 2024
4dd44a8
misc: add translators credits
Xyphyn Jun 6, 2024
fe98c02
i18n: add estonian translation (beta)
Xyphyn Jun 6, 2024
b5657d3
i18n: localize theme page
Xyphyn Jun 6, 2024
afc727a
misc: prepare for merge
Xyphyn Jun 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions src/lib/i18n/en.json
Original file line number Diff line number Diff line change
@@ -507,5 +507,146 @@
"blockUser": "Blocked that user.",
"unblockUser": "Unblocked that user.",
"purgeUser": "Purged that user."
},
"settings": {
"title": "Settings",
"navigation": {
"title": "Navigation",
"dockPos": {
"title": "Dock position",
"description": "Where the dock should be positioned on the screen.",
"top": "Top",
"bottom": "Bottom",
"adaptive": "Adaptive"
},
"panel": {
"title": "Panel mode",
"description": "Extend the dock to the screen edges, similar to a panel.",
"on": "On",
"off": "Off",
"adaptive": "Adaptive"
}
},
"app": {
"title": "Photon",
"theming": {
"title": "Theming",
"description": "Customize Photon's colors.",
"link": "Go to themes"
},
"lang": {
"title": "Language",
"description": "The language used for Photon's UI.",
"note": "Languages other than English and Hebrew are community translated, and may be incomplete.",
"": "Dont translate the below!",
"en": "English",
"en-US": "English",
"he": "Hebrew",
"auto": "Auto"
},
"view": {
"title": "Post style",
"list": "Show posts in a list, with post bodies and compact media.",
"cozy": "Show posts with large images, rich embeds, and longer post bodies.",
"compact": "Show posts in a list, without post bodies and with tighter spacing.",
"legacy": "The old look of Photon."
},
"sort": {
"title": "Default sort",
"description": "The default sorting to use in feeds."
},
"postsInNewTab": {
"title": "Open posts in new tab",
"description": "Open posts in a separate tab instead of the current."
},
"displayName": {
"title": "Use display name",
"description": "Show users' display names instead of their actual usernames."
},
"limitLayoutWidth": {
"title": "Limit layout width",
"description": "Improve readability by limiting the main content width."
},
"placeholders": {
"title": "Random placeholders",
"description": "Show random placeholders for certain text inputs."
},
"expandImages": {
"title": "Expand images",
"description": "Clicking on a post's image brings you to an expanded view rather than the post page."
},
"duplicateTitles": {
"title": "Hide duplicate titles/bodies",
"description": "Hides the post title and body if they are identical to the embed."
},
"thumbnailSide": {
"title": "Thumbnail alignment",
"description": "Where thumbnails should be on the post in list/compact mode",
"left": "Left",
"right": "Right"
},
"font": {
"title": "Font",
"description": "What font Photon uses in the UI."
}
},
"embeds": {
"title": "Embeds",
"clickToView": {
"title": "Click to view",
"description": "Only load embeds once you click on them."
},
"youtube": {
"description": "The website to embed YouTube content in."
}
},
"lemmy": {
"title": "Lemmy",
"compactFeatured": {
"title": "Compact featured posts",
"description": "Make featured posts more compact"
},
"markReadPosts": {
"title": "Mark read posts",
"description": "Mark a post as read when you click on it"
},
"fadeReadPosts": {
"title": "Fade read posts",
"description": "Fade the title of posts you've already read"
},
"crosspostMarker": {
"title": "Mark crossposts",
"description": "Show 'crossposted from' when crossposting."
},
"hideSubmissions": {
"title": "Hide submissions",
"description": "Hide certain types of submissions.",
"deleted": "Deleted by user",
"removed": "Removed by moderator"
},
"nsfwBlur": {
"title": "NSFW blur",
"description": "Blur images and remove post bodies of NSFW posts."
},
"instances": {
"title": "Show instances",
"description": "Show the instances where certain content is from."
}
},
"moderation": {
"title": "Moderation",
"replyPresets": {
"title": "Removal reply presets",
"description": "Presets to use for 'reply reason' in the submission removal dialog.",
"syntax": "Syntax"
}
},
"other": {
"title": "Other",
"debug": {
"title": "Debug info",
"description": "Display debug information"
}
}
}
}
228 changes: 113 additions & 115 deletions src/routes/settings/+page.svelte
Original file line number Diff line number Diff line change
@@ -36,11 +36,13 @@
</script>

<svelte:head>
<title>Settings</title>
<title>{$t('settings.title')}</title>
</svelte:head>

<h1 class="text-3xl font-bold flex justify-between">
Settings <Button
{$t('settings.title')}
<Button
size="square-md"
on:click={() => {
toast({
content: $t('toast.resetSettings'),
@@ -50,98 +52,100 @@
class="font-normal"
>
<Icon src={ArrowPath} mini size="16" slot="prefix" />
Reset
</Button>
</h1>

<div class="flex flex-col gap-4" style="scroll-behavior: smooth;">
<Section title="Navigation">
<div>
<Button
color="ghost"
on:click={() => {
$userSettings.dock.noGap = true
$userSettings.dock.top = true
}}
disabled={$userSettings.dock.noGap && $userSettings.dock.top}
>
Legacy Navigation Style
</Button>
</div>
<Section title={$t('settings.navigation.title')}>
<Setting>
<span slot="title">Dock position</span>
<span slot="description">Where the dock should be put</span>
<span slot="title">{$t('settings.navigation.dockPos.title')}</span>
<span slot="description">
{$t('settings.navigation.dockPos.description')}
</span>
<MultiSelect
options={[true, false, null]}
optionNames={['Top', 'Bottom', 'Adaptive']}
optionNames={[
$t('settings.navigation.dockPos.top'),
$t('settings.navigation.dockPos.bottom'),
$t('settings.navigation.dockPos.adaptive'),
]}
bind:selected={$userSettings.dock.top}
/>
</Setting>
<Setting>
<span slot="title">Panel mode</span>
<span slot="title">{$t('settings.navigation.panel.title')}</span>
<span slot="description">
Extend the dock to screen edges, similar to a panel.
{$t('settings.navigation.panel.description')}
</span>
<MultiSelect
options={[true, false, null]}
optionNames={['On', 'Off', 'Adaptive']}
optionNames={[
$t('settings.navigation.panel.on'),
$t('settings.navigation.panel.off'),
$t('settings.navigation.panel.adaptive'),
]}
bind:selected={$userSettings.dock.noGap}
/>
</Setting>
</Section>

<Section title="Photon">
<Section title={$t('settings.app.title')}>
<Setting>
<span slot="title">Theming</span>
<span slot="description">Customize Photon's colors.</span>
<span slot="title">{$t('settings.app.theming.title')}</span>
<span slot="description">{$t('settings.app.theming.description')}</span>
<Button href="/theme">
Go to themes <Icon src={ArrowRight} size="16" mini slot="suffix" />
{$t('settings.app.theming.link')}
<Icon src={ArrowRight} size="16" mini slot="suffix" />
</Button>
</Setting>
<Setting>
<span slot="title">Language</span>
<span slot="title">{$t('settings.app.lang.title')}</span>
<p slot="description">
The language used for Photon's UI.
{$t('settings.app.lang.description')}
<Note>
All languages other than US English and Hebrew are community
translated, and may be incomplete!
{$t('settings.app.lang.note')}
</Note>
</p>
<Select bind:value={$userSettings.language}>
<option value={null}>Auto-Detect</option>
<option value={null}>{$t('settings.app.lang.auto')}</option>
{#each $locales as locale}
<option value={locale}>{locale}</option>
<option value={locale}>
{$t(`settings.app.lang.${locale}`, { default: locale })}
</option>
{/each}
</Select>
</Setting>
<Setting>
<span slot="title">Post style</span>
<span slot="title">{$t('settings.app.view.title')}</span>
<ViewSelect showLabel={false} />
<p slot="description">
{#if $userSettings.view == 'list'}
Show posts in a list, with post bodies and compact images.
{$t('settings.app.view.list')}
{:else if $userSettings.view == 'cozy'}
Show posts with large images, rich embeds and longer post bodies.
{$t('settings.app.view.cozy')}
{:else if $userSettings.view == 'compact'}
Show posts in a list, without post bodies and with tighter spacing.
{$t('settings.app.view.compact')}
{:else if $userSettings.view == 'card'}
Photon's old post style.
{$t('settings.app.view.legacy')}
{/if}
</p>
</Setting>
<Setting optionClass="flex-[2] max-w-full flex-wrap min-w-0">
<span slot="title">Default sort</span>
<span slot="description">The default sort to use for feeds.</span>
<span slot="title">{$t('settings.app.sort.title')}</span>
<span slot="description">{$t('settings.app.sort.description')}</span>
<div class="flex max-[500px]:flex-col flex-wrap gap-2 w-max max-w-full">
<div class="max-w-full">
<Select bind:value={$userSettings.defaultSort.feed}>
<span slot="label" class="flex items-center gap-1">
<Icon src={GlobeAmericas} size="16" mini />
Location
{$t('filter.location.label')}
</span>
<option value="All">All</option>
<option value="Local">Local</option>
<option value="Subscribed">Subscribed</option>
<option value="All">{$t('filter.location.all')}</option>
<option value="Local">{$t('filter.location.local')}</option>
<option value="Subscribed">
{$t('filter.location.subscribed')}
</option>
<option value="Moderator">{$t('filter.location.moderator')}</option>
</Select>
</div>
<div class="max-w-full">
@@ -154,173 +158,167 @@
<Select bind:value={$userSettings.defaultSort.comments}>
<span slot="label" class="flex items-center gap-1">
<Icon src={ChatBubbleOvalLeftEllipsis} size="14" mini />
Comments
{$t('content.comments')}
</span>

<option value="Hot">Hot</option>
<option value="Top">Top</option>
<option value="New">New</option>
<option value="Hot">{$t('filter.sort.hot')}</option>
<option value="Top">{$t('filter.sort.top.label')}</option>
<option value="New">{$t('filter.sort.new')}</option>
</Select>
</div>
</div>
</Setting>
<ToggleSetting
bind:checked={$userSettings.openLinksInNewTab}
title="Open posts in new tab"
description="Rather than opening posts in the same tab, open a separate one."
title={$t('settings.app.postsInNewTab.title')}
description={$t('settings.app.postsInNewTab.description')}
/>
<ToggleSetting
bind:checked={$userSettings.displayNames}
title="Use display name"
description="Show a user's display name instead of their account username."
title={$t('settings.app.displayName.title')}
description={$t('settings.app.displayName.description')}
/>
<ToggleSetting
bind:checked={$userSettings.newWidth}
title="Limit layout width"
description="Improve readability by limiting main content width."
title={$t('settings.app.limitLayoutWidth.title')}
description={$t('settings.app.limitLayoutWidth.description')}
/>
<ToggleSetting
bind:checked={$userSettings.randomPlaceholders}
title="Random placeholders"
description="Show a random placeholder for forms for comments, posts, etc."
title={$t('settings.app.placeholders.title')}
description={$t('settings.app.placeholders.description')}
/>
<ToggleSetting
bind:checked={$userSettings.expandImages}
title="Expand images"
description="Clicking on a post's image brings you to an expanded view rather than
sending you to the post page."
title={$t('settings.app.expandImages.title')}
description={$t('settings.app.expandImages.description')}
/>
<ToggleSetting
bind:checked={$userSettings.posts.deduplicateEmbed}
title="Hide duplicate titles/bodies"
description="Hides the post title and body if they're the same as the embed."
title={$t('settings.app.duplicateTitles.title')}
description={$t('settings.app.duplicateTitles.description')}
/>
<Setting>
<span slot="title">Thumbnail alignment</span>
<span slot="title">{$t('settings.app.thumbnailSide.title')}</span>
<span slot="description">
Where thumbnails should be on the post in list/compact view.
{$t('settings.app.thumbnailSide.title')}
</span>
<MultiSelect
options={[true, false]}
optionNames={['Left', 'Right']}
optionNames={[
$t('settings.app.thumbnailSide.left'),
$t('settings.app.thumbnailSide.right'),
]}
bind:selected={$userSettings.leftAlign}
/>
</Setting>
<Setting vertical>
<span slot="title">{$t('settings.app.font.title')}</span>
<span slot="description">{$t('settings.app.font.description')}</span>
<MultiSelect
options={['inter', 'satoshi/nunito', 'system', 'browser']}
optionNames={['Inter', 'Satoshi/Nunito', 'System UI', 'Browser Font']}
bind:selected={$userSettings.font}
/>
</Setting>
</Section>

<Section title="Embeds">
<Section title={$t('settings.embeds.title')}>
<ToggleSetting
title="Click to view"
description="Don't load an embed until you click it. (It is recommended to leave this on, to not load a video you don't want to load.)"
title={$t('settings.embeds.clickToView.title')}
description={$t('settings.embeds.clickToView.description')}
bind:checked={$userSettings.embeds.clickToView}
/>
<Setting>
<span slot="title">YouTube</span>
<span slot="description">
The website to use to embed YouTube content.
{$t('settings.embeds.youtube.description')}
</span>
<Select bind:value={$userSettings.embeds.youtube}>
<option value="youtube">YouTube</option>
<option value="invidious">Invidious</option>
<option value="piped">Piped</option>
</Select>
</Setting>
<Setting vertical>
<span slot="title">Font</span>
<span slot="description">What font Photon should use.</span>
<MultiSelect
options={['inter', 'satoshi/nunito', 'system', 'browser']}
optionNames={['Inter', 'Satoshi/Nunito', 'System UI', 'Browser Font']}
bind:selected={$userSettings.font}
/>
</Setting>
</Section>

<Section title="Lemmy">
<Section title={$t('settings.lemmy.title')}>
<ToggleSetting
bind:checked={$userSettings.posts.compactFeatured}
title="Compact featured posts"
description="Make featured posts more compact."
title={$t('settings.lemmy.compactFeatured.title')}
description={$t('settings.lemmy.compactFeatured.description')}
/>
<ToggleSetting
bind:checked={$userSettings.markPostsAsRead}
title="Mark read posts"
description="Mark a post as read when you click on it."
title={$t('settings.lemmy.markReadPosts.title')}
description={$t('settings.lemmy.markReadPosts.description')}
/>
<ToggleSetting
bind:checked={$userSettings.markReadPosts}
title="Fade read posts"
description="Fade the title of posts you've already read."
title={$t('settings.lemmy.fadeReadPosts.title')}
description={$t('settings.lemmy.fadeReadPosts.title')}
/>
<ToggleSetting
bind:checked={$userSettings.crosspostOriginalLink}
title="'Crossposted from' when crossposting"
description="If enabled, crossposts will include a link to the original post."
title={$t('settings.lemmy.crosspostMarker.title')}
description={$t('settings.lemmy.crosspostMarker.description')}
/>
<Setting>
<span slot="title">Hide Submissions</span>
<span slot="title">{$t('settings.lemmy.hideSubmissions.title')}</span>
<span slot="description">
<p>Hide certain types of submissions.</p>
<p>
Looking to hide read posts? That was moved to your <Link
href="/profile/settings"
highlight
>
profile settings.
</Link>
</p>
<p>{$t('settings.lemmy.hideSubmissions.description')}</p>
</span>
<div class="flex flex-col items-start gap-4 flex-wrap">
<Switch bind:checked={$userSettings.hidePosts.deleted}>Deleted</Switch>
<Switch bind:checked={$userSettings.hidePosts.deleted}>
{$t('settings.lemmy.hideSubmissions.deleted')}
</Switch>
<Switch bind:checked={$userSettings.hidePosts.removed}>
Removed by Moderator
{$t('settings.lemmy.hideSubmissions.removed')}
</Switch>
</div>
</Setting>
<ToggleSetting
bind:checked={$userSettings.nsfwBlur}
title="NSFW blur"
description="Blur images and remove post bodies of content tagged NSFW."
title={$t('settings.lemmy.nsfwBlur.title')}
description={$t('settings.lemmy.nsfwBlur.description')}
/>
<Setting>
<span slot="title">Show instances</span>
<span slot="description">Show items' instances.</span>
<span slot="title">{$t('settings.lemmy.instances.title')}</span>
<span slot="description">
{$t('settings.lemmy.instances.description')}
</span>
<div class="flex flex-row flex-wrap items-center gap-4">
<Checkbox bind:checked={$userSettings.showInstances.user}>
Users
{$t('content.users')}
</Checkbox>
<Checkbox bind:checked={$userSettings.showInstances.comments}>
Comments
{$t('content.comments')}
</Checkbox>
<Checkbox bind:checked={$userSettings.showInstances.community}>
Communities
{$t('content.communities')}
</Checkbox>
</div>
</Setting>
</Section>

<Section title="Moderation">
<Section title={$t('settings.moderation.title')}>
<Setting mainClass="md:flex-row flex-col !items-start">
<span slot="title">Removal reply presets</span>
<span slot="title">{$t('settings.moderation.replyPresets.title')}</span>
<span slot="description">
<p>Presets to use for "Reply reason" in a submission removal.</p>
<p>{$t('settings.moderation.replyPresets.description')}</p>
<ul class="leading-6">
<li>Syntax:</li>
<li>{$t('settings.moderation.replyPresets.syntax')}</li>
<li>
<code>{'{{reason}}'}</code>
: The provided reason
</li>
<li>
<code>{'{{post}}'}</code>
: The title of the post
</li>
<li>
<code>{'{{community}}'}</code>
: The community the submission was removed in.
</li>
<li>
<code>{'{{username}}'}</code>
: The username of the creator of the submission.
</li>
</ul>
</span>
@@ -395,11 +393,11 @@
</Setting>
</Section>

<Section title="Other">
<Section title={$t('settings.other.title')}>
<ToggleSetting
bind:checked={$userSettings.debugInfo}
title="Debug info"
description="Display debug information"
title={$t('settings.other.debug.title')}
description={$t('settings.other.debug.description')}
/>
</Section>
</div>