i18 first steps

pull/28/head
Laurin Weger 6 months ago
parent ce2aeb326f
commit b5542d5406
No known key found for this signature in database
GPG Key ID: 9B372BB0B792770F
  1. 1
      ng-app/package.json
  2. 9
      ng-app/src/App.svelte
  3. 4
      ng-app/src/lib/CenteredLayout.svelte
  4. 44
      ng-app/src/lib/FullLayout.svelte
  5. 25
      ng-app/src/lib/Install.svelte
  6. 10
      ng-app/src/lib/NoWallet.svelte
  7. 18
      ng-app/src/lib/Test.svelte
  8. 377
      ng-app/src/locales/en.json
  9. 10
      ng-app/src/locales/i18n-init.ts
  10. 4
      ng-app/src/routes/Install.svelte
  11. 2
      ng-app/src/routes/Invitation.svelte
  12. 3
      ng-app/src/routes/NURI.svelte
  13. 5
      ng-app/src/routes/NotFound.svelte
  14. 68
      ng-app/src/routes/User.svelte
  15. 25
      ng-app/src/routes/UserRegistered.svelte

@ -24,6 +24,7 @@
"flowbite": "^1.6.5", "flowbite": "^1.6.5",
"flowbite-svelte": "^0.43.3", "flowbite-svelte": "^0.43.3",
"ng-sdk-js": "workspace:^0.1.0-preview.1", "ng-sdk-js": "workspace:^0.1.0-preview.1",
"svelte-i18n": "^4.0.0",
"svelte-spa-router": "^3.3.0", "svelte-spa-router": "^3.3.0",
"vite-plugin-top-level-await": "^1.3.1" "vite-plugin-top-level-await": "^1.3.1"
}, },

@ -11,12 +11,14 @@
<script lang="ts"> <script lang="ts">
import { push, default as Router } from "svelte-spa-router"; import { push, default as Router } from "svelte-spa-router";
import "./locales/i18n-init";
import { isLoading } from "svelte-i18n";
import { onMount, tick, onDestroy } from "svelte"; import { onMount, tick, onDestroy } from "svelte";
import { import {
wallets, wallets,
active_wallet, active_wallet,
opened_wallets, opened_wallets,
active_session,
close_active_session, close_active_session,
disconnections_subscribe, disconnections_subscribe,
select_default_lang, select_default_lang,
@ -276,4 +278,9 @@
{JSON.stringify(Object.keys($opened_wallets))} {JSON.stringify(Object.keys($opened_wallets))}
{JSON.stringify($active_session)} {JSON.stringify($active_session)}
</p> --> </p> -->
{#if $isLoading}
<p>Loading...</p>
{:else}
<Router {routes} /> <Router {routes} />
{/if}

@ -14,6 +14,7 @@
import { onMount, tick } from "svelte"; import { onMount, tick } from "svelte";
import { current_lang, available_languages } from "../store"; import { current_lang, available_languages } from "../store";
import { Language } from "svelte-heros-v2"; import { Language } from "svelte-heros-v2";
import { t } from "svelte-i18n";
export let displayFooter = false; export let displayFooter = false;
@ -72,7 +73,8 @@
<button <button
on:click={displayNextgraphOrg} on:click={displayNextgraphOrg}
class="text-primary-700 bg-[#f6f6f6] bg-none ring-0 hover:bg-primary-100/90 focus:ring-4 focus:ring-primary-100/50 font-medium rounded-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-100/55 mb-2" class="text-primary-700 bg-[#f6f6f6] bg-none ring-0 hover:bg-primary-100/90 focus:ring-4 focus:ring-primary-100/50 font-medium rounded-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-100/55 mb-2"
>About NextGraph >
{$t("common.about_nextgraph")}
</button> </button>
</div> </div>
</div> </div>

@ -19,10 +19,10 @@
import { link, location } from "svelte-spa-router"; import { link, location } from "svelte-spa-router";
import MobileBottomBarItem from "./MobileBottomBarItem.svelte"; import MobileBottomBarItem from "./MobileBottomBarItem.svelte";
import MobileBottomBar from "./MobileBottomBar.svelte"; import MobileBottomBar from "./MobileBottomBar.svelte";
import Logo from "./components/Logo.svelte"; // @ts-ignore
import Logo from "../assets/nextgraph.svg?component";
import { connection_status } from "../store"; // @ts-ignore
import { t } from "svelte-i18n";
import { onMount, tick } from "svelte"; import { onMount, tick } from "svelte";
import { import {
@ -98,7 +98,7 @@
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem <SidebarItem
label="Home" label={$t("pages.full_layout.home")}
href="#/" href="#/"
on:click={scrollToTop} on:click={scrollToTop}
class="py-1 tall-xs:p-2" class="py-1 tall-xs:p-2"
@ -110,7 +110,11 @@
/> />
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem label="Stream" href="#/stream" class="py-1 tall-xs:p-2"> <SidebarItem
label={$t("pages.full_layout.stream")}
href="#/stream"
class="py-1 tall-xs:p-2"
>
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
<Bolt <Bolt
tabindex="-1" tabindex="-1"
@ -118,7 +122,11 @@
/> />
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem label="Search" href="#/search" class="py-1 tall-xs:p-2"> <SidebarItem
label={$t("pages.full_layout.search")}
href="#/search"
class="py-1 tall-xs:p-2"
>
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
<MagnifyingGlass <MagnifyingGlass
tabindex="-1" tabindex="-1"
@ -126,7 +134,11 @@
/> />
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem label="Create" href="#/create" class="py-1 tall-xs:p-2"> <SidebarItem
label={$t("pages.full_layout.create")}
href="#/create"
class="py-1 tall-xs:p-2"
>
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
<PlusCircle <PlusCircle
tabindex="-1" tabindex="-1"
@ -134,7 +146,11 @@
/> />
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem label="Shared" href="#/shared" class="py-1 tall-xs:p-2"> <SidebarItem
label={$t("pages.full_layout.shared")}
href="#/shared"
class="py-1 tall-xs:p-2"
>
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
<Users <Users
tabindex="-1" tabindex="-1"
@ -142,7 +158,11 @@
/> />
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem label="Site" href="#/site" class="py-1 tall-xs:p-2"> <SidebarItem
label={$t("pages.full_layout.site")}
href="#/site"
class="py-1 tall-xs:p-2"
>
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
<User <User
tabindex="-1" tabindex="-1"
@ -151,7 +171,7 @@
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem <SidebarItem
label="Messages" label={$t("pages.full_layout.messages")}
href="#/messages" href="#/messages"
class="py-1 tall-xs:p-2" class="py-1 tall-xs:p-2"
> >
@ -168,7 +188,7 @@
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem <SidebarItem
label="Notifications" label={$t("pages.full_layout.notifications")}
href="#/notifications" href="#/notifications"
class="mt-1 py-1 tall-xs:p-2" class="mt-1 py-1 tall-xs:p-2"
> >

File diff suppressed because one or more lines are too long

@ -19,6 +19,7 @@
import Logo from "../assets/nextgraph.svg?component"; import Logo from "../assets/nextgraph.svg?component";
import { link } from "svelte-spa-router"; import { link } from "svelte-spa-router";
import CenteredLayout from "./CenteredLayout.svelte"; import CenteredLayout from "./CenteredLayout.svelte";
import { t } from "svelte-i18n";
</script> </script>
<CenteredLayout displayFooter={true}> <CenteredLayout displayFooter={true}>
@ -26,11 +27,10 @@
<div class="row"> <div class="row">
<Logo class="logo block h-40" alt="NextGraph Logo" /> <Logo class="logo block h-40" alt="NextGraph Logo" />
</div> </div>
<h1 class="text-2xl mb-10">Welcome to NextGraph</h1> <h1 class="text-2xl mb-10">{$t("pages.no_wallet.welcome")}</h1>
<p class="max-w-sm"> <p class="max-w-sm">
We could not find a wallet saved on this device.<br /> If you already have {$t("pages.no_wallet.description")}
a wallet, select "Log in", otherwise, select "Create Wallet" here below
</p> </p>
<div class="row mt-5"> <div class="row mt-5">
<a href="/wallet/create" use:link> <a href="/wallet/create" use:link>
@ -53,7 +53,7 @@
d="M19 7.5v3m0 0v3m0-3h3m-3 0h-3m-2.25-4.125a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zM4 19.235v-.11a6.375 6.375 0 0112.75 0v.109A12.318 12.318 0 0110.374 21c-2.331 0-4.512-.645-6.374-1.766z" d="M19 7.5v3m0 0v3m0-3h3m-3 0h-3m-2.25-4.125a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zM4 19.235v-.11a6.375 6.375 0 0112.75 0v.109A12.318 12.318 0 0110.374 21c-2.331 0-4.512-.645-6.374-1.766z"
/> />
</svg> </svg>
Create wallet {$t("pages.no_wallet.create_wallet")}
</button> </button>
</a> </a>
</div> </div>
@ -78,7 +78,7 @@
d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z"
/> />
</svg> </svg>
Log in {$t("common.login")}
</button> </button>
</a> </a>
</div> </div>

@ -26,7 +26,7 @@
import { onMount, onDestroy, tick } from "svelte"; import { onMount, onDestroy, tick } from "svelte";
import { Button } from "flowbite-svelte"; import { Button } from "flowbite-svelte";
import DataClassIcon from "./DataClassIcon.svelte"; import DataClassIcon from "./DataClassIcon.svelte";
import { t } from "svelte-i18n";
let is_tauri = import.meta.env.TAURI_PLATFORM; let is_tauri = import.meta.env.TAURI_PLATFORM;
let files = $active_session && branch_subs($active_session.private_store_id); let files = $active_session && branch_subs($active_session.private_store_id);
@ -696,16 +696,8 @@
{#if $cannot_load_offline} {#if $cannot_load_offline}
<div class="row p-4"> <div class="row p-4">
<p> <p>
You are offline and using the web app. You need to connect to the broker {$t("pages.text.cannot_load_offline")}
at least once before you can start using the app locally because the web <a href="#/user">{$t("pages.user_panel.title")}</a>.
app does not keep a local copy of your documents.<br /><br />
Once connected, if you lose connectivity again, you will be able to have
limited access to some functionalities. Sending binary files won't be possible,
because the limit of local storage in your browser is around 5MB.<br
/><br />
All those limitations will be lifted once the "UserStorage for Web" feature
will be released. Stay tuned! <br /><br />
Check your connection status in the <a href="#/user">User panel</a>.
</p> </p>
</div> </div>
{:else} {:else}
@ -745,7 +737,7 @@
d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z"
/> />
</svg> </svg>
Add image {$t("pages.test.add_image")}
</Button> </Button>
<input <input
style="display:none" style="display:none"
@ -757,7 +749,7 @@
</div> </div>
{#if files} {#if files}
{#await files.load()} {#await files.load()}
<p>Currently loading...</p> <p>{$t("connectivity.loading")}...</p>
{:then} {:then}
{#each $files as file} {#each $files as file}
<p> <p>

@ -0,0 +1,377 @@
{
"pages": {
"not_found": {
"title": "Page Not Found",
"message": "The page you are looking for does not exist."
},
"nextgraph_uri": {
"message": "Nextgraph URI {uri}"
},
"user_panel": {
"title": "User Panel",
"personal": "Personal",
"already_registered": "The user is already registered with the selected broker.<br />Try logging in instead.",
"error": "An error occured:<br />{error}"
},
"user_registered": {
"already_exists": "The user is already registered with the selected broker.<br />Try logging in instead.",
"error": "An error occured:<br />{error}",
"back_to_homepage": "Go Back to Homepage",
"success": "You have been successfully registered{invitation_name, select, null {} other { to {invitationName}}}."
},
"wallet": {
"title": "Wallet",
"download": "Download Wallet File",
"download_failed": "Download Failed:<br/>{error}",
"download_in_progress": "Download in progress...",
"download_successful": "You will find the file named \"{wallet_file}\" in your Downloads folder",
"download_file": "Click here to download the wallet file"
},
"settings": {
"title": "Settings"
},
"admin": {
"title": "Admin"
},
"accounts": {
"title": "Accounts"
},
"full_layout": {
"home": "Home",
"stream": "Stream",
"search": "Search",
"create": "Create",
"shared": "Shared",
"site": "Site",
"messages": "Messages",
"notifications": "Notifications"
},
"install": {
"app_availability": "<b>NextGraph App</b> is available for download as a native app for your mobile, tablet, laptop and desktop.<br /> The app supports iOS, Android, Linux, macOS, Windows, or any other platform with a modern browser.",
"has_wallet_warning": "A wallet is saved in this browser. If it is yours,<br /> once the installation of the app will be finished,<br /> choose the option \"Login\" on the app.<br /> (do not create another wallet from the app).",
"android_play_store": "Android Play Store",
"download_apk": "Download APK",
"ios_app_store": "iOS App Store",
"download_mac_os": "Download for MacOS",
"download_linux": "Download Linux Package",
"download_windows": "Download for Windows",
"other_platforms": "Other platforms"
},
"no_wallet": {
"welcome": "Welcome to NextGraph",
"description": "We could not find a wallet saved on this device.<br /> If you already have a wallet, select \"Log in\", otherwise, select \"Create Wallet\" here below.",
"create_wallet": "Create Wallet"
},
"test": {
"cannot_load_offline": "You are offline and using the web app. You need to connect to the broker at least once before you can start using the app locally because the web app does not keep a local copy of your documents.<br /><br /> Once connected, if you lose connectivity again, you will be able to have limited access to some functionalities. Sending binary files won't be possible, because the limit of local storage in your browser is around 5MB.<br /><br /> All those limitations will be lifted once the \"UserStorage for Web\" feature will be released. Stay tuned! <br /><br /> Check your connection status in the ",
"add_image": "Add Image"
},
"login": {
"heading": "How to open your wallet? You have 2 options:",
"with_pazzle": "With your Pazzle",
"pazzle_steps": {
"1": "For each one of the 9 categories of images, you will be presented with the 15 possible image choices. The categories are shuffled at every login. They will not always appear in the same order.",
"2": "At each category, only one of the 15 displayed choices is the correct image that belongs to your pazzle. Find it and tap or click on that one. The 15 images are shuffled too, they will not appear at the same position at each login. On a computer, you can also use the tab key on your keyboard to move to the desired item on the screen, then press the space bar to select each one.",
"3": "Once you completed the last category, you will be presented with all the images you have previously selected. Their order is displayed as it was when you picked them. But this is not the correct order of the images in your pazzle. You now have to order them correctly.",
"4": "You must remember which image should be the first one in your pazzle. Find it on the screen and click or tap on it. It will be greyed out and the number 1 will appear on top of it.",
"5": "Move on to the second image of your pazzle (that you memorized). Find it on the screen and tap on it. Repeat this step until you reached the last image.",
"6": "Finally, your PIN code will be asked. enter it by clicking or tapping on the digits."
},
"with_menmonic": "With your 12 words Mnemonic (passphrase)",
"mnemonic_steps": {
"1": "Enter your twelve words mnemonic in the input field. The words must be separated by spaces.",
"2": "Enter the PIN code that you chose when you created your wallet."
},
"trust_device": "Do you trust this device?",
"trust_device_description": "If you do, if this device is yours or is used by few trusted persons of your family or workplace, and you would like to login again from this device in the future, then you can save your wallet on this device. To the contrary, if this device is public and shared by strangers, do not save your wallet here.",
"trust_device_allow_cookies": "By selecting this option, you agree to saving some cookies on your browser.",
"trust_device_yes": "Yes, save my wallet on this device",
"loading_pazzle": "Loading Pazzle",
"open_with_pazzle": "Open With Pazzle",
"login_cancel": "Cancel Login",
"open_with_mnemonic": "Open with Mnemonic instead",
"enter_mnemonic": "Enter your 12 words mnemonic.",
"select_emoji": "Select your emoji of category:<br />{category}",
"order_emojis": "Select each image in the correct order",
"enter_pin": "Enter your PIN code",
"go_back": "Go Back",
"correct": "Correct",
"opening_wallet": "Opening your wallet...<br /> Please wait",
"error_occured": "An error occured!",
"try_again": "Try Again",
"wallet_opened": "Your wallet is opened! <br />Please wait while the app is loading..."
},
"wallet_create": {}
},
"buttons": {
"back": "Back",
"confirm": "Confirm"
},
"connectivity": {
"stopped": "Stopped",
"personal": "Personal",
"connecting": "Connecting",
"connected": "Connected",
"loading": "Loading",
"connection_error_short": "{error}",
"online": "Online",
"offline": "Offline"
},
"common": {
"version": "Version: {version}",
"logo": "NextGraph Logo",
"support_nextgraph": "Support NextGraph",
"about_nextgraph": "About NextGraph",
"back_to_homepage": "Go Back to Homepage",
"donate_nextgraph": "Donate to NextGraph",
"logout": "Logout",
"login": "Login"
},
"emojis": {
"category": {
"face": "Face",
"face_unwell": "Bad Face",
"face_costume": "Costumed",
"emotion": "Emotion",
"body": "Body",
"sport": "Sport",
"bigger_animal": "Big Animal",
"smaller_animal": "Small Animal",
"plants": "Plants and Instects",
"fruits": "Fruites and Veggies",
"food": "Food and Drinks",
"travel": "Travel",
"sky": "Sky and Weather",
"play": "Leasure",
"house": "Household"
},
"codes": {
"COMMENT": "YOU CAN FIND I18N UNICODE DESCRIPTIONS AT https://github.com/unicode-org/cldr-json",
"happy": "grinning face",
"happy_tears": "face with tears of joy",
"halo": "smiling face with halo",
"three_hearts": "smiling face with hearts",
"with_two_hearts": "smiling face with heart-eyes",
"one_heart": "face blowing a kiss",
"with_tongue": "squinting face with tongue",
"with_two_hands": "smiling face with open hands",
"one_hand": "face with hand over mouth",
"silenced": "zipper-mouth face",
"celebrating": "partying face",
"sunglasses": "smiling face with sunglasses",
"eyes_up": "face with rolling eyes",
"monocole": "face with monocle",
"sleeping": "sleeping face",
"mask": "face with medical mask",
"fever": "face with thermometer",
"bandage": "face with head-bandage",
"vomit": "face vomiting",
"tissue": "sneezing face",
"hot": "face with head-bandage",
"cold": "cold face",
"crossed_eyes": "face with crossed-out eyes",
"exploding": "exploding head",
"sad": "frowning face",
"long_nose": "lying face",
"many_tears": "loudly crying face",
"fear": "face screaming in fear",
"tired": "yawning face",
"annoyed": "face with steam from nose",
"clown": "clown face",
"ghost": "ghost",
"dog": "dog face",
"happy_cat": "grinning cat with smiling eyes",
"scared_cat": "weary cat",
"sad_cat": "crying cat",
"monkey_no_see": "see-no-evil monkey",
"monkey_no_hear": "hear-no-evil monkey",
"monkey_no_talk": "speak-no-evil monkey",
"builder": "construction worker",
"princess": "princess",
"firefighter": "person",
"mage": "mage",
"mermaid": "merperson",
"fairy": "fairy",
"letter_heart": "love letter",
"red_heart": "red heart",
"two_hearts": "two hearts",
"kiss": "kiss mark",
"hundred": "hundred points",
"explosion": "collision",
"drops": "sweat droplets",
"handshake": "handshake",
"hand_five_fingers": "hand with fingers splayed",
"hand_two_fingers": "victory hand",
"thumbs_up": "thumbs up",
"fist": "raised fist",
"two_hands": "open hands",
"writing": "writing hand",
"praying": "folded hands",
"arm": "flexed biceps",
"leg": "leg",
"foot": "foot",
"ear": "ear",
"nose": "nose",
"brain": "brain",
"tooth": "tooth",
"bone": "bone",
"eye": "eye",
"tongue": "tongue",
"mouth": "mouth",
"shirt": "t-shirt",
"pants": "jeans",
"dress": "dress",
"shoe": "running shoe",
"fencing": "person fencing",
"horse_riding": "horse racing",
"ski": "skier",
"rowing_boat": "person rowing boat",
"swim": "person swimming",
"surf": "person surfing",
"gym": "person lifting weights",
"wrestling": "people wrestling",
"bike": "person biking",
"parachute": "parachute",
"football": "soccer ball",
"basketball": "basketball",
"tennis": "tennis",
"ping_pong": "ping pong",
"martial": "martial arts uniform",
"lion": "lion",
"leopard": "leopard",
"horse": "horse face",
"zebra": "zebra",
"pig": "pig",
"goat": "goat",
"sheep": "ewe",
"camel": "camel",
"giraffe": "giraffe",
"elephant": "elephant",
"rhinoceros": "rhinoceros",
"flamingo": "flamingo",
"whale": "spouting whale",
"dolphin": "dolphin",
"bear": "bear",
"rooster": "rooster",
"chick": "hatching chick",
"eagle": "eagle",
"duck": "duck",
"owl": "owl",
"rabbit": "rabbit",
"penguin": "penguin",
"lizard": "lizard",
"turtle": "turtle",
"snake": "snake",
"hedgehog": "hedgehog",
"bat": "bat",
"fish": "fish",
"shell": "spiral shell",
"octopus": "octopus",
"snail": "snail",
"butterfly": "butterfly",
"ant": "ant",
"bee": "honeybee",
"beetle": "lady beetle",
"rose": "rose",
"sunflower": "sunflower",
"fir": "evergreen tree",
"palm_tree": "palm tree",
"cactus": "cactus",
"clover": "four leaf clover",
"potted_plant": "potted plant",
"bouquet": "bouquet",
"three_leaves": "fallen leaf",
"mushroom": "mushroom",
"grapes": "grapes",
"watermelon": "watermelon",
"lemon": "lemon",
"banana": "banana",
"pineapple": "pineapple",
"apple": "red apple",
"cherries": "cherries",
"strawberry": "strawberry",
"three_blueberries": "blueberries",
"kiwi": "kiwi fruit",
"avocado": "avocado",
"eggplant": "eggplant",
"carrot": "carrot",
"corn": "ear of corn",
"pepper": "hot pepper",
"croissant": "croissant",
"bread": "baguette bread",
"pretzel": "pretzel",
"cheese": "cheese wedge",
"pizza": "pizza",
"egg": "cooking",
"ice_cream": "soft ice cream",
"cookie": "cookie",
"cake": "shortcake",
"chocolate": "chocolate bar",
"sweet": "candy",
"coffee": "hot beverage",
"champagne_bottle": "bottle with popping cork",
"glass_wine": "wine glass",
"two_glasses": "clinking glasses",
"mountain": "snow-capped mountain",
"camping": "camping",
"beach": "beach with umbrella",
"compass": "compass",
"museum": "classical building",
"house": "house with garden",
"fountain": "fountain",
"circus": "circus tent",
"train": "locomotive",
"taxi": "taxi",
"motorcycle": "motorcycle",
"sailboat": "sailboat",
"airplane": "airplane",
"helicopter": "helicopter",
"rocket": "rocket",
"sun": "sun",
"moon": "crescent moon",
"planet": "ringed planet",
"star": "star",
"night_sky": "milky way",
"cloud": "cloud with rain",
"umbrella": "umbrella with rain drops",
"lightning": "high voltage",
"snowflake": "snowflake",
"snowman": "snowman without snow",
"thermometer": "thermometer",
"fire": "fire",
"balloon": "balloon",
"kite": "kite",
"rainbow": "rainbow",
"guitar": "guitar",
"saxophone": "saxophone",
"music": "musical note",
"painting": "artist palette",
"chess": "chess pawn",
"gift": "wrapped gift",
"die": "game die",
"puzzle": "puzzle piece",
"teddy_bear": "teddy bear",
"firecracker": "firecracker",
"bullseye": "bullseye",
"roller_skate": "roller skate",
"kick_scooter": "kick scooter",
"anchor": "anchor",
"scuba_diving": "diving mask",
"broom": "broom",
"magnifying_glass": "magnifying glass tilted left",
"bulb": "light bulb",
"three_books": "books",
"package": "package",
"pencil": "pencil",
"pin": "pushpin",
"paperclip": "paperclip",
"scissors": "scissors",
"key": "key",
"lock": "unlocked",
"chair": "chair",
"bathtub": "bathtub",
"sponge": "sponge",
"shopping_cart": "shopping cart"
}
}
}

@ -0,0 +1,10 @@
import { register, init, getLocaleFromNavigator } from "svelte-i18n";
register("en", () => import("./en.json"));
// register('de', () => import('./de.json'));
// register('fr', () => import('./fr.json'));
init({
fallbackLocale: "en",
initialLocale: getLocaleFromNavigator(),
});

@ -10,16 +10,12 @@
--> -->
<script type="ts"> <script type="ts">
import { Button } from "flowbite-svelte";
import { link } from "svelte-spa-router";
import Install from "../lib/Install.svelte"; import Install from "../lib/Install.svelte";
import { push } from "svelte-spa-router";
import { onMount, onDestroy } from "svelte"; import { onMount, onDestroy } from "svelte";
import CenteredLayout from "../lib/CenteredLayout.svelte"; import CenteredLayout from "../lib/CenteredLayout.svelte";
import { has_wallets } from "../store"; import { has_wallets } from "../store";
let display_has_wallets_warning = $has_wallets != 0; let display_has_wallets_warning = $has_wallets != 0;
let unsubscribe;
onMount(() => {}); onMount(() => {});
onDestroy(() => {}); onDestroy(() => {});

@ -10,7 +10,7 @@
--> -->
<script lang="ts"> <script lang="ts">
export let params = {}; export let params: { invitation: string } = { invitation: "" };
import { onMount } from "svelte"; import { onMount } from "svelte";
onMount( onMount(
() => (window.location.href = "/#/wallet/create?i=" + params.invitation) () => (window.location.href = "/#/wallet/create?i=" + params.invitation)

@ -9,6 +9,7 @@
// according to those terms. // according to those terms.
--> -->
<script> <script>
import { t } from "svelte-i18n";
// The params prop contains values matched from the URL // The params prop contains values matched from the URL
export let params = {}; export let params = {};
@ -19,6 +20,6 @@
<div <div
class="h-screen aspect-[3/5] pazzleline max-w-[720px] bg-yellow-300 inner" class="h-screen aspect-[3/5] pazzleline max-w-[720px] bg-yellow-300 inner"
> >
<p>Nextgraph URI {params[1]}</p> <p>{$t("pages.nextgraph_uri.message", { values: { uri: params[1] } })}</p>
</div> </div>
</div> </div>

@ -12,12 +12,15 @@
<script> <script>
import { Alert } from "flowbite-svelte"; import { Alert } from "flowbite-svelte";
import CenteredLayout from "../lib/CenteredLayout.svelte"; import CenteredLayout from "../lib/CenteredLayout.svelte";
import { t } from "svelte-i18n";
</script> </script>
<CenteredLayout displayFooter={true}> <CenteredLayout displayFooter={true}>
<div class="p-8"> <div class="p-8">
<Alert color="red"> <Alert color="red">
<span class="font-medium">404</span> Page not found. <span class="font-medium">404</span>{$t("pages.not_found.title")}
<br />
<span class="text-sm">{$t("pages.not_found.message")}</span>
</Alert> </Alert>
</div> </div>
</CenteredLayout> </CenteredLayout>

@ -23,6 +23,7 @@
import CenteredLayout from "../lib/CenteredLayout.svelte"; import CenteredLayout from "../lib/CenteredLayout.svelte";
import { version } from "../../package.json"; import { version } from "../../package.json";
import Time from "svelte-time"; import Time from "svelte-time";
import { t } from "svelte-i18n";
// @ts-ignore // @ts-ignore
import Logo from "../assets/nextgraph.svg?component"; import Logo from "../assets/nextgraph.svg?component";
import { import {
@ -109,10 +110,13 @@
} }
}; };
const donate = async () => { const donate = async () => {
await displayPopup("https://nextgraph.org/donate", "Support NextGraph"); await displayPopup(
"https://nextgraph.org/donate",
$t("common.support_nextgraph")
);
}; };
const about = async () => { const about = async () => {
await displayPopup("https://nextgraph.org", "About NextGraph"); await displayPopup("https://nextgraph.org", $t("common.about_nextgraph"));
}; };
</script> </script>
@ -125,7 +129,7 @@
> >
<SidebarGroup ulClass="space-y-2" role="menu"> <SidebarGroup ulClass="space-y-2" role="menu">
<li> <li>
<h2 class="text-xl mb-6">User panel</h2> <h2 class="text-xl mb-6">{$t("pages.user_panel.title")}</h2>
</li> </li>
<li <li
tabindex="0" tabindex="0"
@ -138,7 +142,7 @@
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
/> />
<span class="ml-3">Back</span> <span class="ml-3">{$t("buttons.back")}</span>
</li> </li>
<li <li
@ -150,14 +154,16 @@
class="w-7 h-7 text-green-600 transition duration-75 focus:outline-none dark:text-green-400 " class="w-7 h-7 text-green-600 transition duration-75 focus:outline-none dark:text-green-400 "
/> />
<span class="ml-3 text-green-600 dark:text-green-400" <span class="ml-3 text-green-600 dark:text-green-400"
>Online</span >{$t("pages.user_panel.online")}</span
> >
{:else} {:else}
<SignalSlash <SignalSlash
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-red-600 transition duration-75 focus:outline-none dark:text-red-400 " class="w-7 h-7 text-red-600 transition duration-75 focus:outline-none dark:text-red-400 "
/> />
<span class="ml-3 text-red-600 dark:text-red-400">Offline</span> <span class="ml-3 text-red-600 dark:text-red-400"
>{$t("pages.user_panel.offline")}</span
>
{/if} {/if}
</li> </li>
@ -172,7 +178,7 @@
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
/> />
<span class="ml-3">Logout</span> <span class="ml-3">{$t("common.logout")}</span>
</li> </li>
<!-- <li <!-- <li
tabindex="0" tabindex="0"
@ -199,7 +205,11 @@
/> />
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem label="Wallet" href="#/wallet" class="p-2"> <SidebarItem
label={$t("pages.wallet.title")}
href="#/wallet"
class="p-2"
>
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
<PuzzlePiece <PuzzlePiece
tabindex="-1" tabindex="-1"
@ -208,7 +218,7 @@
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem <SidebarItem
label="Admin" label={$t("pages.admin.title")}
href="#/user/admin" href="#/user/admin"
class="p-2 opacity-50 pointer-events-none" class="p-2 opacity-50 pointer-events-none"
> >
@ -219,7 +229,11 @@
/> />
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem label="Accounts" href="#/user/account" class="p-2"> <SidebarItem
label={$t("pages.accounts.title")}
href="#/user/accounts"
class="p-2"
>
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
<User <User
tabindex="-1" tabindex="-1"
@ -233,7 +247,7 @@
personal_site_status.server_ip + personal_site_status.server_ip +
" " + " " +
personal_site_status.server_id) || personal_site_status.server_id) ||
"offline"} $t("pages.user_panel.offline")}
> >
<Toggle <Toggle
on:change={async () => { on:change={async () => {
@ -241,14 +255,17 @@
$connections[personal_site].connecting = true; $connections[personal_site].connecting = true;
await reconnect(); await reconnect();
} else { } else {
$connections[personal_site].error = "Stopped"; $connections[personal_site].error = $t(
"connectivity.stopped"
);
personal_site_status.since = new Date(); personal_site_status.since = new Date();
await ng.user_disconnect(personal_site); await ng.user_disconnect(personal_site);
} }
}} }}
checked={personal_site_status && checked={personal_site_status &&
(personal_site_status.connecting || (personal_site_status.connecting ||
!personal_site_status.error)}>Personal</Toggle !personal_site_status.error)}
>{$t("connectivity.personal")}</Toggle
> >
</li> </li>
{#if personal_site_status} {#if personal_site_status}
@ -256,12 +273,14 @@
class="site-cnx-details flex items-center px-2 text-sm text-left font-normal text-gray-600" class="site-cnx-details flex items-center px-2 text-sm text-left font-normal text-gray-600"
> >
{#if personal_site_status.connecting} {#if personal_site_status.connecting}
Connecting... {$t("connectivity.connecting")}...
{:else} {:else}
{#if !personal_site_status.error} {#if !personal_site_status.error}
Connected {$t("connectivity.connected")}
{:else} {:else}
{personal_site_status.error} {$t("connectivity.connection_error_short", {
values: { error: personal_site_status.error },
})}
{/if} {/if}
<Time <Time
style="display:contents;" style="display:contents;"
@ -286,7 +305,7 @@
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
/> />
<span class="ml-3">Donate to NextGraph</span> <span class="ml-3">{$t("common.donate_nextgraph")}</span>
</li> </li>
<li <li
@ -300,13 +319,15 @@
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white" class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
/> />
<span class="ml-3">About NextGraph</span> <span class="ml-3">
{$t("common.about_nextgraph")}
</span>
</li> </li>
<li <li
class="flex items-center p-2 text-base font-normal text-gray-900" class="flex items-center p-2 text-base font-normal text-gray-900"
> >
Version: {version} {$t("common.version", { values: { version } })}
</li> </li>
</SidebarGroup> </SidebarGroup>
</SidebarWrapper> </SidebarWrapper>
@ -331,27 +352,26 @@
</svg> </svg>
{#if error == "AlreadyExists"} {#if error == "AlreadyExists"}
<p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5"> <p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5">
The user is already registered with the selected broker.<br /> Try logging {$t("pages.user_panel.already_registered")}
in instead
</p> </p>
<a use:link href="/"> <a use:link href="/">
<button <button
tabindex="-1" tabindex="-1"
class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2" class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2"
> >
Login {$t("common.login")}
</button> </button>
</a> </a>
{:else} {:else}
<p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5"> <p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5">
An error occurred:<br />{error} {$t("pages.user_panel.error", { values: { error } })}
</p> </p>
<a use:link href="/"> <a use:link href="/">
<button <button
tabindex="-1" tabindex="-1"
class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2" class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2"
> >
Go back to homepage {$t("common.back_to_homepage")}
</button> </button>
</a> </a>
{/if} {/if}

@ -10,7 +10,7 @@
--> -->
<script> <script>
import { Button, Alert, Dropzone, Toggle } from "flowbite-svelte"; import { t } from "svelte-i18n";
import { link, querystring } from "svelte-spa-router"; import { link, querystring } from "svelte-spa-router";
import CenteredLayout from "../lib/CenteredLayout.svelte"; import CenteredLayout from "../lib/CenteredLayout.svelte";
// @ts-ignore // @ts-ignore
@ -18,12 +18,7 @@
import { onMount, tick } from "svelte"; import { onMount, tick } from "svelte";
import { import { default as ng } from "../api";
NG_EU_BSP,
NG_NET_BSP,
APP_ACCOUNT_REGISTERED_SUFFIX,
default as ng,
} from "../api";
const param = new URLSearchParams($querystring); const param = new URLSearchParams($querystring);
@ -49,7 +44,7 @@
<div class="container3"> <div class="container3">
<div class="row"> <div class="row">
<a href="#/"> <a href="#/">
<Logo class="logo block h-40" alt="NextGraph Logo" /> <Logo class="logo block h-40" alt={$t("common.logo")} />
</a> </a>
</div> </div>
{#if error} {#if error}
@ -71,27 +66,26 @@
</svg> </svg>
{#if error == "AlreadyExists"} {#if error == "AlreadyExists"}
<p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5"> <p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5">
The user is already registered with the selected broker.<br /> Try logging {$t("pages.user_registered.already_exists")}
in instead
</p> </p>
<a use:link href="/"> <a use:link href="/">
<button <button
tabindex="-1" tabindex="-1"
class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2" class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2"
> >
Login {$t("common.login")}
</button> </button>
</a> </a>
{:else} {:else}
<p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5"> <p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5">
An error occurred:<br />{error} {$t("pages.user_registered.error", { values: { error } })}
</p> </p>
<a use:link href="/"> <a use:link href="/">
<button <button
tabindex="-1" tabindex="-1"
class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2" class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2"
> >
Go back to homepage {$t("common.back_to_homepage")}
</button> </button>
</a> </a>
{/if} {/if}
@ -114,8 +108,9 @@
/> />
</svg> </svg>
<p class="max-w-xl md:mx-auto lg:max-w-2xl"> <p class="max-w-xl md:mx-auto lg:max-w-2xl">
You have been successfully <br />registered {#if invitation?.V0?.name} {$t("pages.user_registered.success", {
to {invitation?.V0?.name}{/if} values: { invitation_name: invitation?.V0?.name },
})}
</p> </p>
</div> </div>
{/if} {/if}

Loading…
Cancel
Save