forked from blisstown/campfire
add localisation support
currently only en_GB (TODO: dynamic language pack imports)
This commit is contained in:
parent
970590497f
commit
e326ac858e
17 changed files with 263 additions and 90 deletions
88
src/lang/en_GB.json
Normal file
88
src/lang/en_GB.json
Normal file
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"compose_placeholders": [
|
||||
"What's cooking, $1?",
|
||||
"Speak your mind!",
|
||||
"Federate something...",
|
||||
"I sure love posting!",
|
||||
"Another day, another $1 post!"
|
||||
],
|
||||
|
||||
"login": {
|
||||
"welcome": "Welcome, fediverse user!",
|
||||
"enter_domain": "Please enter your server domain to log in.",
|
||||
"experimental": "Please note this is\n<strong><em>extremely experimental software</em></strong>;\nthings are likely to break!\n<br>\nIf that's all cool with you, welcome aboard!",
|
||||
"button": "Log in",
|
||||
"error": {
|
||||
"no_domain": "Please enter an server domain.",
|
||||
"connection_failed": "Failed to connect to the server.\nCheck the browser console for details!",
|
||||
"create_app": "Failed to create an application for this server."
|
||||
},
|
||||
"made_with_tagline": "made with ❤ by <a href=\"https://bliss.town\">bliss town</a>"
|
||||
},
|
||||
|
||||
"navigation": {
|
||||
"timeline": "Timeline",
|
||||
"notifications": "Notifications",
|
||||
"explore": "Explore",
|
||||
"lists": "Lists",
|
||||
|
||||
"favourites": "Favourites",
|
||||
"bookmarks": "Bookmarks",
|
||||
"hashtags": "Hashtags",
|
||||
|
||||
"profile_information": "Profile information",
|
||||
"settings": "Settings",
|
||||
"log_out": "Log out"
|
||||
},
|
||||
|
||||
"timeline": {
|
||||
"home": "Home",
|
||||
"local": "Local",
|
||||
"federated": "Federated",
|
||||
"fetching": "getting the feed..."
|
||||
},
|
||||
|
||||
"notification": {
|
||||
"and_others": "and <strong>%1</strong> others",
|
||||
"mention": "%1 mentioned you.",
|
||||
"reblog": "%1 boosted your post.",
|
||||
"reaction": "%1 reacted to your post.",
|
||||
"follow": "%1 followed you.",
|
||||
"follow_request": "%1 requested to follow you.",
|
||||
"favourite": "%1 favourited your post.",
|
||||
"poll": "%1's poll as ended.",
|
||||
"update": "%1 updated their post.",
|
||||
"default": "%1 poked you!",
|
||||
"fetching": "fetching notifications..."
|
||||
},
|
||||
|
||||
"post": {
|
||||
"time": "%1 ago",
|
||||
"boosted": "%1 boosted this post.",
|
||||
"actions": {
|
||||
"reply": "Reply",
|
||||
"boost": "Boost",
|
||||
"favourite": "Favourite",
|
||||
"quote": "Quote",
|
||||
"react": "React",
|
||||
"more": "More",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"warning": {
|
||||
"show": "(click to reveal)",
|
||||
"hide": "(click to hide)"
|
||||
},
|
||||
"visibility": {
|
||||
"public": "public",
|
||||
"unlisted": "unlisted",
|
||||
"private": "private",
|
||||
"direct": "direct"
|
||||
}
|
||||
},
|
||||
|
||||
"compose": "Post",
|
||||
"search": "Search",
|
||||
|
||||
"source": "source",
|
||||
"issues": "issues"
|
||||
}
|
60
src/lib/lang.js
Normal file
60
src/lib/lang.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
import * as en_GB from '@cf/lang/en_GB.json';
|
||||
|
||||
/**
|
||||
* @param {string} lang IETH language tag (i.e. en_GB)
|
||||
* @returns Map<string, string | string[]>
|
||||
*/
|
||||
export default function init(lang) {
|
||||
let i18n = new Object();
|
||||
let language;
|
||||
|
||||
// TODO: dynamic imports seem to fail here; it can't find the file.
|
||||
// try {
|
||||
// language = import(`../lang/${lang}.json`);
|
||||
// } catch (error) {
|
||||
// throw error;
|
||||
// }
|
||||
|
||||
language = en_GB;
|
||||
|
||||
i18n.lang = language;
|
||||
i18n.lang_code = lang;
|
||||
i18n.string = function(/* @type string */ key) {
|
||||
const tokens = key.split('.');
|
||||
|
||||
let i = 0;
|
||||
let token = tokens[i];
|
||||
let res = this.lang;
|
||||
while (true) {
|
||||
res = res[token];
|
||||
if (res === undefined) {
|
||||
console.warn(`${key} not found for language ${this.lang_code}`);
|
||||
return key;
|
||||
}
|
||||
if (typeof res === 'string' || res instanceof String)
|
||||
return res;
|
||||
i++;
|
||||
token = tokens[i];
|
||||
}
|
||||
}
|
||||
i18n.stringArray = function(/* @type string */ key) {
|
||||
const tokens = key.split('.');
|
||||
|
||||
let i = 0;
|
||||
let token = tokens[i];
|
||||
let res = this.lang;
|
||||
while (true) {
|
||||
res = res[token];
|
||||
if (res === undefined) {
|
||||
console.warn(`${key} not found for language ${this.lang_code}`);
|
||||
return key;
|
||||
}
|
||||
if (Array.isArray(res))
|
||||
return res;
|
||||
i++;
|
||||
token = tokens[i];
|
||||
}
|
||||
}
|
||||
|
||||
return i18n;
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
import Lang from '$lib/lang.js';
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
const denoms = [
|
||||
{ unit: 's', min: 0 },
|
||||
{ unit: 'm', min: 60 },
|
||||
|
@ -18,6 +21,6 @@ export function shorthand(date) {
|
|||
unit = denoms[index].unit;
|
||||
}
|
||||
if (value > 0)
|
||||
return Math.floor(value) + unit + " ago";
|
||||
return lang.string('post.time').replaceAll('%1', Math.floor(value) + unit);
|
||||
return "in " + Math.floor(value) + unit;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { timeline } from '$lib/timeline.js';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { playSound } from '$lib/sound';
|
||||
import Lang from '$lib/lang.js'
|
||||
|
||||
import Button from '@cf/ui/Button.svelte';
|
||||
import PostIcon from '@cf/icons/post.svg';
|
||||
|
@ -19,6 +20,8 @@
|
|||
import FollowersVisIcon from '@cf/icons/followers.svg';
|
||||
import PrivateVisIcon from '@cf/icons/dm.svg';
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
export let reply_id;
|
||||
|
||||
let content_warning = ""
|
||||
|
@ -27,15 +30,9 @@
|
|||
let show_cw = false;
|
||||
let visibility = "Public";
|
||||
|
||||
const placeholders = [
|
||||
"What's cooking, $1?",
|
||||
"Speak your mind!",
|
||||
"Federate something...",
|
||||
"I sure love posting!",
|
||||
"Another day, another $1 post!",
|
||||
];
|
||||
let placeholder = placeholders[Math.floor(placeholders.length * Math.random())]
|
||||
.replaceAll("$1", $account.username);
|
||||
const placeholders = lang.stringArray('compose_placeholders');
|
||||
let placeholder = Array.isArray(placeholders) ? placeholders[Math.floor(placeholders.length * Math.random())]
|
||||
.replaceAll("$1", $account.username) : placeholders;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
import { server, createServer } from '$lib/client/server.js';
|
||||
import { app } from '$lib/client/app.js';
|
||||
import { get } from 'svelte/store';
|
||||
import Lang from '$lib/lang.js';
|
||||
|
||||
import Logo from '$lib/../img/campfire-logo.svg';
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
let display_error = false;
|
||||
let logging_in = false;
|
||||
|
||||
|
@ -17,21 +20,21 @@
|
|||
const host = event.target.host.value;
|
||||
|
||||
if (!host || host === "") {
|
||||
display_error = "Please enter an server domain.";
|
||||
display_error = lang.string('login.error.no_domain');
|
||||
logging_in = false;
|
||||
return;
|
||||
}
|
||||
|
||||
server.set(await createServer(host));
|
||||
if (!get(server)) {
|
||||
display_error = "Failed to connect to the server.\nCheck the browser console for details!"
|
||||
display_error = lang.string('login.error.connection_failed');
|
||||
logging_in = false;
|
||||
return;
|
||||
}
|
||||
|
||||
app.set(await api.createApp(get(server).host));
|
||||
if (!get(app)) {
|
||||
display_error = "Failed to create an application for this server."
|
||||
display_error = lang.string('login.error.create_app');
|
||||
logging_in = false;
|
||||
return;
|
||||
}
|
||||
|
@ -44,8 +47,8 @@
|
|||
<div class="app-logo">
|
||||
<Logo />
|
||||
</div>
|
||||
<p>Welcome, fediverse user!</p>
|
||||
<p>Please enter your server domain to log in.</p>
|
||||
<p>{lang.string('login.welcome')}</p>
|
||||
<p>{lang.string('login.enter_domain')}</p>
|
||||
<div class="input-wrapper">
|
||||
<input type="text" id="host" aria-label="server domain" class={logging_in ? "throb" : ""}>
|
||||
{#if display_error}
|
||||
|
@ -53,16 +56,10 @@
|
|||
{/if}
|
||||
</div>
|
||||
<br>
|
||||
<button type="submit" id="login" class={logging_in ? "disabled" : ""}>Log in</button>
|
||||
<p><small>
|
||||
Please note this is
|
||||
<strong><em>extremely experimental software</em></strong>;
|
||||
things are likely to break!
|
||||
<br>
|
||||
If that's all cool with you, welcome aboard!
|
||||
</small></p>
|
||||
<button type="submit" id="login" class={logging_in ? "disabled" : ""}>{lang.string('login.button')}</button>
|
||||
<p><small>{@html lang.string('login.experimental')}</small></p>
|
||||
|
||||
<p class="form-footer">made with ❤ by <a href="https://bliss.town">bliss town</a>, 2024</p>
|
||||
<p class="form-footer">{@html lang.string('login.made_with_tagline')}</p>
|
||||
</form>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
import { page } from '$app/stores';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { notifications, unread_notif_count } from '$lib/notifications.js';
|
||||
import Lang from '$lib/lang.js';
|
||||
|
||||
import Logo from '$lib/../img/campfire-logo.svg';
|
||||
import Button from './Button.svelte';
|
||||
|
@ -27,6 +28,7 @@
|
|||
import LogoutIcon from '../../img/icons/logout.svg';
|
||||
|
||||
const VERSION = APP_VERSION;
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
|
@ -95,7 +97,7 @@
|
|||
<svelte:fragment slot="icon">
|
||||
<TimelineIcon/>
|
||||
</svelte:fragment>
|
||||
Timeline
|
||||
{lang.string('navigation.timeline')}
|
||||
</Button>
|
||||
<Button label="Notifications"
|
||||
on:click={() => handle_btn("notifications")}
|
||||
|
@ -103,7 +105,7 @@
|
|||
<svelte:fragment slot="icon">
|
||||
<NotificationsIcon/>
|
||||
</svelte:fragment>
|
||||
Notifications
|
||||
{lang.string('navigation.notifications')}
|
||||
{#if $unread_notif_count}
|
||||
<span class="notification-count">
|
||||
{$unread_notif_count <= 99 ? $unread_notif_count : "99+"}
|
||||
|
@ -114,54 +116,54 @@
|
|||
<svelte:fragment slot="icon">
|
||||
<ExploreIcon height="auto"/>
|
||||
</svelte:fragment>
|
||||
Explore
|
||||
{lang.string('navigation.explore')}
|
||||
</Button>
|
||||
<Button label="Lists" disabled>
|
||||
<svelte:fragment slot="icon">
|
||||
<ListIcon/>
|
||||
</svelte:fragment>
|
||||
Lists
|
||||
{lang.string('navigation.lists')}
|
||||
</Button>
|
||||
|
||||
<div class="flex-row">
|
||||
<Button centered label="Favourites" disabled>
|
||||
<Button centered label="{lang.string('navigation.favourites')}" disabled>
|
||||
<svelte:fragment slot="icon">
|
||||
<FavouritesIcon/>
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
<Button centered label="Bookmarks" disabled>
|
||||
<Button centered label="{lang.string('navigation.bookmarks')}" disabled>
|
||||
<svelte:fragment slot="icon">
|
||||
<BookmarkIcon/>
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
<Button centered label="Hashtags" disabled>
|
||||
<Button centered label="{lang.string('navigation.hashtags')}" disabled>
|
||||
<svelte:fragment slot="icon">
|
||||
<HashtagIcon/>
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Button filled label="Post" on:click={() => dispatch("compose")}>
|
||||
<Button filled label="{lang.string('compose')}" on:click={() => dispatch("compose")}>
|
||||
<svelte:fragment slot="icon">
|
||||
<PostIcon/>
|
||||
</svelte:fragment>
|
||||
Post
|
||||
{lang.string('compose')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div id="account-items">
|
||||
<div class="flex-row">
|
||||
<Button centered label="Profile information" disabled>
|
||||
<Button centered label="{lang.string('navigation.profile_information')}" disabled>
|
||||
<svelte:fragment slot="icon">
|
||||
<InfoIcon/>
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
<Button centered label="Settings" disabled>
|
||||
<Button centered label="{lang.string('navigation.settings')}" disabled>
|
||||
<svelte:fragment slot="icon">
|
||||
<SettingsIcon/>
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
<Button centered label="Log out" on:click={() => log_out()}>
|
||||
<Button centered label="{lang.string('navigation.log_out')}" on:click={() => log_out()}>
|
||||
<svelte:fragment slot="icon">
|
||||
<LogoutIcon/>
|
||||
</svelte:fragment>
|
||||
|
@ -184,8 +186,8 @@
|
|||
campfire v{VERSION}
|
||||
<br>
|
||||
<ul>
|
||||
<li><a href="https://git.arimelody.me/blisstown/campfire">source</a></li>
|
||||
<li><a href="https://codeberg.org/arimelody/campfire/issues">issues</a></li>
|
||||
<li><a href="https://git.arimelody.me/blisstown/campfire">{lang.string('source')}</a></li>
|
||||
<li><a href="https://codeberg.org/arimelody/campfire/issues">{lang.string('issues')}</a></li>
|
||||
</ul>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -9,10 +9,13 @@
|
|||
// import QuoteIcon from '$lib/../img/icons/quote.svg';
|
||||
import ReactionBar from '$lib/ui/post/ReactionBar.svelte';
|
||||
import ActionBar from '$lib/ui/post/ActionBar.svelte';
|
||||
import Lang from '$lib/lang.js';
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
let mention = (accounts) => {
|
||||
let res = `<a href=${account.url}>${account.rich_name}</a>`;
|
||||
if (accounts.length > 1) res += ` and <strong>${accounts.length - 1}</strong> others`;
|
||||
if (accounts.length > 1) res += ' ' + lang.string('notification.and_others').replaceAll('%1', accounts.length - 1);
|
||||
return res;
|
||||
};
|
||||
|
||||
|
@ -20,23 +23,23 @@
|
|||
let activity_text = function (type) {
|
||||
switch (type) {
|
||||
case "mention":
|
||||
return `%1 mentioned you.`;
|
||||
return lang.string('notification.mention');
|
||||
case "reblog":
|
||||
return `%1 boosted your post.`;
|
||||
return lang.string('notification.reblog');
|
||||
case "reaction":
|
||||
return `%1 reacted to your post.`;
|
||||
return lang.string('notification.reaction');
|
||||
case "follow":
|
||||
return `%1 followed you.`;
|
||||
return lang.string('notification.follow');
|
||||
case "follow_request":
|
||||
return `%1 requested to follow you.`;
|
||||
return lang.string('notification.follow.request');
|
||||
case "favourite":
|
||||
return `%1 favourited your post.`;
|
||||
return lang.string('notification.favourite');
|
||||
case "poll":
|
||||
return `%1's poll as ended.`;
|
||||
return lang.string('notification.poll');
|
||||
case "update":
|
||||
return `%1 updated their post.`;
|
||||
return lang.string('notification.update');
|
||||
default:
|
||||
return `%1 poked you!`;
|
||||
return lang.string('notification.default');
|
||||
}
|
||||
}(data.type);
|
||||
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<script>
|
||||
import Lang from '$lib/lang.js';
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
</script>
|
||||
|
||||
<div id="widgets">
|
||||
<input type="text" id="search" placeholder="Search">
|
||||
<input type="text" id="search" placeholder="{lang.string('search')}">
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import { timeline } from '$lib/timeline';
|
||||
import { parseReactions } from '$lib/post';
|
||||
import { playSound } from '$lib/sound';
|
||||
import Lang from '$lib/lang';
|
||||
|
||||
import ActionButton from './ActionButton.svelte';
|
||||
|
||||
|
@ -19,6 +20,8 @@
|
|||
|
||||
export let post;
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
async function toggleBoost() {
|
||||
if (!$app || !$app.token) return;
|
||||
|
||||
|
@ -74,29 +77,29 @@
|
|||
</script>
|
||||
|
||||
<div class="post-actions" aria-label="Post actions" role="toolbar" tabindex="0" on:mouseup|stopPropagation on:keydown|stopPropagation>
|
||||
<ActionButton type="reply" label="Reply" bind:count={post.reply_count} sound="post" disabled>
|
||||
<ActionButton type="reply" label="{lang.string('post.actions.reply')}" bind:count={post.reply_count} sound="post" disabled>
|
||||
<ReplyIcon/>
|
||||
</ActionButton>
|
||||
<ActionButton type="boost" label="Boost" on:click={toggleBoost} bind:active={post.boosted} bind:count={post.boost_count} disabled={!$account}>
|
||||
<ActionButton type="boost" label="{lang.string('post.actions.boost')}" on:click={toggleBoost} bind:active={post.boosted} bind:count={post.boost_count} disabled={!$account}>
|
||||
<RepostIcon/>
|
||||
<svelte:fragment slot="activeIcon">
|
||||
<RepostIcon/>
|
||||
</svelte:fragment>
|
||||
</ActionButton>
|
||||
<ActionButton type="favourite" label="Favourite" on:click={toggleFavourite} bind:active={post.favourited} bind:count={post.favourite_count} disabled={!$account}>
|
||||
<ActionButton type="favourite" label="{lang.string('post.actions.favourite')}" on:click={toggleFavourite} bind:active={post.favourited} bind:count={post.favourite_count} disabled={!$account}>
|
||||
<FavouriteIcon/>
|
||||
<svelte:fragment slot="activeIcon">
|
||||
<FavouriteIconFill/>
|
||||
</svelte:fragment>
|
||||
</ActionButton>
|
||||
<ActionButton type="quote" label="Quote" disabled>
|
||||
<ActionButton type="quote" label="{lang.string('post.actions.quote')}" disabled>
|
||||
<QuoteIcon/>
|
||||
</ActionButton>
|
||||
<ActionButton type="more" label="More" disabled>
|
||||
<ActionButton type="more" label="{lang.string('post.actions.more')}" disabled>
|
||||
<MoreIcon/>
|
||||
</ActionButton>
|
||||
{#if $account && post.account.id === $account.id}
|
||||
<ActionButton type="delete" label="Delete" on:click={deletePost}>
|
||||
<ActionButton type="delete" label="{lang.string('post.actions.delete')}" on:click={deletePost}>
|
||||
<DeleteIcon/>
|
||||
</ActionButton>
|
||||
{/if}
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
<script>
|
||||
import Lang from '$lib/lang';
|
||||
|
||||
export let post;
|
||||
|
||||
let open_warned = false;
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
let open = false;
|
||||
</script>
|
||||
|
||||
<div class="post-body">
|
||||
{#if post.warning}
|
||||
<button class="post-warning" on:click|stopPropagation={() => { open_warned = !open_warned }} on:mouseup|stopPropagation>
|
||||
<button class="post-warning" on:click|stopPropagation={() => { open = !open }} on:mouseup|stopPropagation>
|
||||
<strong>
|
||||
{post.warning}
|
||||
<span class="warning-instructions">
|
||||
{#if !open_warned}
|
||||
(click to reveal)
|
||||
<span class="instructions">
|
||||
{#if !open}
|
||||
{lang.string('post.warning.show')}
|
||||
{:else}
|
||||
(click to hide)
|
||||
{lang.string('post.warning.hide')}
|
||||
{/if}
|
||||
</span>
|
||||
</strong>
|
||||
</button>
|
||||
{/if}
|
||||
{#if !post.warning || open_warned}
|
||||
{#if !post.warning || open}
|
||||
{#if post.rich_text}
|
||||
<span class="post-text">{@html post.rich_text}</span>
|
||||
{:else if post.html}
|
||||
|
@ -78,7 +82,7 @@
|
|||
box-shadow: 0 0 8px var(--warn-bg);
|
||||
}
|
||||
|
||||
.post-warning .warning-instructions {
|
||||
.post-warning .instructions {
|
||||
font-weight: normal;
|
||||
opacity: .5;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<script>
|
||||
import { shorthand as short_time } from '$lib/time.js';
|
||||
import Lang from '$lib/lang.js';
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
export let post;
|
||||
|
||||
|
@ -9,10 +12,10 @@
|
|||
<div class="post-context">
|
||||
<span class="post-context-icon">🔁</span>
|
||||
<span class="post-context-action">
|
||||
<a href={post.account.url} target="_blank"><span class="name">
|
||||
{@html post.account.rich_name}</span>
|
||||
</a>
|
||||
boosted this post.
|
||||
{ @html
|
||||
lang.string('post.boosted').replaceAll('%1',
|
||||
`<a href={${post.account.url}} target="_blank"><span class="name">${post.account.rich_name}</span></a>`)
|
||||
}
|
||||
</span>
|
||||
<span class="post-context-time">
|
||||
<time title="{time_string}">{short_time(post.created_at)}</time>
|
||||
|
@ -41,8 +44,8 @@
|
|||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.post-context a,
|
||||
.post-context a:visited {
|
||||
:global(.post-context a),
|
||||
:global(.post-context a:visited) {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<script>
|
||||
import { shorthand as short_time } from '$lib/time.js';
|
||||
import Lang from '$lib/lang.js';
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
export let post;
|
||||
export let reply = undefined;
|
||||
|
@ -19,10 +22,8 @@
|
|||
<div class="post-info" on:mouseup|stopPropagation>
|
||||
<a href={post.url} target="_blank" class="created-at">
|
||||
<time title={time_string}>{short_time(post.created_at)}</time>
|
||||
{#if post.visibility !== "public"}
|
||||
<br>
|
||||
<span class="post-visibility">{post.visibility}</span>
|
||||
{/if}
|
||||
<br>
|
||||
<span class="post-visibility">{lang.string('post.visibility.' + post.visibility)}</span>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
@ -51,11 +51,7 @@
|
|||
{/if}
|
||||
</ReactionButton>
|
||||
{/each}
|
||||
<ReactionButton
|
||||
type="reaction"
|
||||
title="react"
|
||||
label="React"
|
||||
disabled>
|
||||
<ReactionButton disabled>
|
||||
<ReactIcon/>
|
||||
</ReactionButton>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
<script>
|
||||
import { playSound } from '../../sound.js';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import Lang from '$lib/lang';
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
export let type = "react";
|
||||
export let label = "React";
|
||||
export let title = label;
|
||||
export let label = lang.string('post.actions.react');
|
||||
export let title = lang.string('post.actions.react');
|
||||
export let count = 0;
|
||||
export let active = false;
|
||||
export let disabled = false;
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
import { page } from '$app/stores';
|
||||
import { account } from '$lib/stores/account.js';
|
||||
import { timeline, getTimeline } from '$lib/timeline.js';
|
||||
import Lang from '$lib/lang.js';
|
||||
|
||||
import LoginForm from '$lib/ui/LoginForm.svelte';
|
||||
import Button from '$lib/ui/Button.svelte';
|
||||
import Post from '$lib/ui/post/Post.svelte';
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
account.subscribe(account => {
|
||||
if (account) getTimeline();
|
||||
});
|
||||
|
@ -21,18 +24,18 @@
|
|||
|
||||
{#if $account}
|
||||
<header>
|
||||
<h1>Home</h1>
|
||||
<h1>{lang.string('timeline.home')}</h1>
|
||||
<nav>
|
||||
<Button centered active>Home</Button>
|
||||
<Button centered disabled>Local</Button>
|
||||
<Button centered disabled>Federated</Button>
|
||||
<Button centered active>{lang.string('timeline.home')}</Button>
|
||||
<Button centered disabled>{lang.string('timeline.local')}</Button>
|
||||
<Button centered disabled>{lang.string('timeline.federated')}</Button>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<div id="feed" role="feed">
|
||||
{#if $timeline.length <= 0}
|
||||
<div class="loading throb">
|
||||
<span>getting the feed...</span>
|
||||
<span>{lang.string('timeline.fetching')}</span>
|
||||
</div>
|
||||
{/if}
|
||||
{#each $timeline as post}
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import Notification from '$lib/ui/Notification.svelte';
|
||||
import Lang from '$lib/lang.js';
|
||||
|
||||
const lang = Lang('en_GB');
|
||||
|
||||
if (!$account) goto("/");
|
||||
|
||||
|
@ -31,13 +34,13 @@
|
|||
</script>
|
||||
|
||||
<header>
|
||||
<h1>Notifications</h1>
|
||||
<h1>{lang.string('navigation.notifications')}</h1>
|
||||
</header>
|
||||
|
||||
<div class="notifications">
|
||||
{#if $notifications.length === 0}
|
||||
<div class="loading throb">
|
||||
<span>fetching notifications...</span>
|
||||
<span>{lang.string('notification.fetching')}</span>
|
||||
</div>
|
||||
{:else}
|
||||
{#each $notifications as notif}
|
||||
|
|
|
@ -19,9 +19,10 @@ const config = {
|
|||
name: child_process.execSync('git rev-parse HEAD').toString().trim()
|
||||
},
|
||||
alias: {
|
||||
'@cf/ui/*': "./src/lib/ui",
|
||||
'@cf/icons/*': "./src/img/icons",
|
||||
'@cf/store/*': "./src/lib/stores"
|
||||
'@cf/ui/*': './src/lib/ui',
|
||||
'@cf/icons/*': './src/img/icons',
|
||||
'@cf/store/*': './src/lib/stores',
|
||||
'@cf/lang/*': './src/lang'
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue