Add services i18n

This commit is contained in:
Restray 2022-04-03 00:18:48 +02:00
parent 13891110ce
commit 360fb5ea37
No known key found for this signature in database
GPG Key ID: 67C6DEF95A4DC812
16 changed files with 114 additions and 73 deletions

View File

@ -18,7 +18,8 @@
"databases": "Databases",
"services": "Services",
"teams": "Teams",
"not_implemented_yet": "Not implemented yet"
"not_implemented_yet": "Not implemented yet",
"database": "Database"
},
"login": {
"already_logged_in": "Already logged in...",
@ -27,7 +28,7 @@
},
"forms": {
"password": "Password",
"email": "Email",
"email": "Email address",
"passwords_not_match": "Passwords do not match.",
"password_again": "Password again",
"save": "Save",
@ -66,7 +67,18 @@
"organization": "Organization",
"new_password": "New password",
"super_secure_new_password": "Super secure new password",
"submit": "Submit"
"submit": "Submit",
"default_email_address": "Default Email Address",
"default_password": "Default Password",
"username": "Username",
"root_db_user": "Root DB User",
"root_db_password": "Root DB Password",
"api_port": "API Port",
"verifying": "Verifying",
"verify_emails_without_smtp": "Verify emails without SMTP",
"extra_config": "Extra Config",
"select_a_service": "Select a Service",
"select_a_service_version": "Select a Service version"
},
"register": {
"register": "Register",
@ -137,7 +149,7 @@
"persistent_storage_explainer": "You can specify any folder that you want to be persistent across deployments. <br>This is useful for storing data such as a database (SQLite) or a cache."
},
"deployment_queued": "Deployment queued.",
"confirm_to_delete": "Are you sure you would like to delete '{0}'?",
"confirm_to_delete": "Are you sure you would like to delete '{name}'?",
"stop_application": "Stop application",
"permission_denied_stop_application": "You do not have permission to stop the application.",
"rebuild_application": "Rebuild application",
@ -232,5 +244,17 @@
"git_source": "Add New Git Source",
"official_providers": "Official providers"
}
},
"services": {
"all_email_verified": "All email verified. You can login now.",
"generate_www_non_www_ssl": "It will generate certificates for both www and non-www. <br>You need to have <span class='font-bold text-pink-600'>both DNS entries</span> set in advance.<br><br>Service needs to be restarted."
},
"service": {
"stop_service": "Stop Service",
"permission_denied_stop_service": "You do not have permission to stop the service.",
"start_service": "Start Service",
"permission_denied_start_service": "You do not have permission to start the service.",
"delete_service": "Delete Service",
"permission_denied_delete_service": "You do not have permission to delete a service."
}
}

View File

@ -62,7 +62,7 @@
<input
type="password"
name="password"
placeholder={$t('index.password')}
placeholder={$t('forms.password')}
bind:value={password}
required
/>

View File

@ -1,5 +1,6 @@
<script lang="ts">
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { t } from '$lib/translations';
export let readOnly;
export let service;
</script>
@ -8,19 +9,19 @@
<div class="title">Ghost</div>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="email">Default Email Address</label>
<label for="email">{$t('forms.default_email_address')}</label>
<input
name="email"
id="email"
disabled
readonly
placeholder="Email address"
placeholder={$t('forms.email')}
value={service.ghost.defaultEmail}
required
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="defaultPassword">Default Password</label>
<label for="defaultPassword">{$t('forms.default_password')}</label>
<CopyPasswordField
id="defaultPassword"
isPasswordField
@ -34,7 +35,7 @@
<div class="title">MariaDB</div>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="mariadbUser">Username</label>
<label for="mariadbUser">{$t('forms.username')}</label>
<CopyPasswordField
name="mariadbUser"
id="mariadbUser"
@ -44,7 +45,7 @@
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="mariadbPassword">Password</label>
<label for="mariadbPassword">{$t('forms.password')}</label>
<CopyPasswordField
id="mariadbPassword"
isPasswordField
@ -55,7 +56,7 @@
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="mariadbDatabase">Database</label>
<label for="mariadbDatabase">{$t('index.database')}</label>
<input
name="mariadbDatabase"
id="mariadbDatabase"
@ -63,11 +64,11 @@
readonly={readOnly}
disabled={readOnly}
bind:value={service.ghost.mariadbDatabase}
placeholder="eg: ghost_db"
placeholder="{$t('forms.eg')}: ghost_db"
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="mariadbRootUser">Root DB User</label>
<label for="mariadbRootUser">{$t('forms.root_db_user')}</label>
<CopyPasswordField
id="mariadbRootUser"
isPasswordField
@ -78,7 +79,7 @@
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="mariadbRootUserPassword">Root DB Password</label>
<label for="mariadbRootUserPassword">{$t('forms.root_db_password')}</label>
<CopyPasswordField
id="mariadbRootUserPassword"
isPasswordField

View File

@ -1,18 +1,19 @@
<script lang="ts">
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { t } from '$lib/translations';
export let service;
</script>
<div class="flex space-x-1 py-5 font-bold">
<div class="title">MinIO Server</div>
<div class="title">MinIO</div>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="rootUser">{$t('forms.root_user')}</label>
<input
name="rootUser"
id="rootUser"
placeholder="User to login"
placeholder={$t('forms.username')}
value={service.minio.rootUser}
disabled
readonly
@ -30,7 +31,7 @@
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="publicPort">API Port</label>
<label for="publicPort">{$t('forms.api_port')}</label>
<input
name="publicPort"
id="publicPort"

View File

@ -1,5 +1,6 @@
<script lang="ts">
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { t } from '$lib/translations';
export let service;
export let readOnly;
</script>
@ -8,31 +9,31 @@
<div class="title">Plausible Analytics</div>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="email">Email Address</label>
<label for="email">{$t('forms.email')}</label>
<input
name="email"
id="email"
disabled={readOnly}
readonly={readOnly}
placeholder="Email address"
placeholder={$t('forms.email')}
bind:value={service.plausibleAnalytics.email}
required
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="username">Username</label>
<label for="username">{$t('forms.username')}</label>
<CopyPasswordField
name="username"
id="username"
disabled={readOnly}
readonly={readOnly}
placeholder="User to login"
placeholder={$t('forms.username')}
bind:value={service.plausibleAnalytics.username}
required
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="password">Password</label>
<label for="password">{$t('forms.password')}</label>
<CopyPasswordField
id="password"
isPasswordField
@ -46,7 +47,7 @@
<div class="title">PostgreSQL</div>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="postgresqlUser">Username</label>
<label for="postgresqlUser">{$t('forms.username')}</label>
<CopyPasswordField
name="postgresqlUser"
id="postgresqlUser"
@ -56,7 +57,7 @@
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="postgresqlPassword">Password</label>
<label for="postgresqlPassword">{$t('forms.password')}</label>
<CopyPasswordField
id="postgresqlPassword"
isPasswordField
@ -67,7 +68,7 @@
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="postgresqlDatabase">Database</label>
<label for="postgresqlDatabase">{$t('index.database')}</label>
<CopyPasswordField
name="postgresqlDatabase"
id="postgresqlDatabase"

View File

@ -9,6 +9,7 @@
import Explainer from '$lib/components/Explainer.svelte';
import Setting from '$lib/components/Setting.svelte';
import { errorNotification } from '$lib/form';
import { t } from '$lib/translations';
import { toast } from '@zerodevx/svelte-toast';
import Ghost from './_Ghost.svelte';
import MinIo from './_MinIO.svelte';
@ -38,7 +39,7 @@
loadingVerification = true;
try {
await post(`/services/${id}/${service.type}/activate.json`, { id: service.id });
toast.push('All email verified. You can login now.');
toast.push(t.get('services.all_email_verified'));
} catch ({ error }) {
return errorNotification(error);
} finally {
@ -51,7 +52,7 @@
dualCerts = !dualCerts;
}
await post(`/services/${id}/settings.json`, { dualCerts });
return toast.push('Settings saved.');
return toast.push(t.get('application.settings_saved'));
} catch ({ error }) {
return errorNotification(error);
}
@ -61,25 +62,27 @@
<div class="mx-auto max-w-4xl px-6 pb-12">
<form on:submit|preventDefault={handleSubmit} class="py-4">
<div class="flex space-x-1 pb-5 font-bold">
<div class="title">General</div>
<div class="title">{$t('general')}</div>
{#if $session.isAdmin}
<button
type="submit"
class:bg-pink-600={!loading}
class:hover:bg-pink-500={!loading}
disabled={loading}>{loading ? 'Saving...' : 'Save'}</button
disabled={loading}>{loading ? $t('forms.saving') : $t('forms.save')}</button
>
{/if}
{#if service.type === 'plausibleanalytics' && isRunning}
<button on:click|preventDefault={setEmailsToVerified} disabled={loadingVerification}
>{loadingVerification ? 'Verifying' : 'Verify emails without SMTP'}</button
>{loadingVerification
? $t('forms.verifying')
: $t('forms.verify_emails_without_smtp')}</button
>
{/if}
</div>
<div class="grid grid-flow-row gap-2">
<div class="mt-2 grid grid-cols-2 items-center px-10">
<label for="name" class="text-base font-bold text-stone-100">Name</label>
<label for="name" class="text-base font-bold text-stone-100">{$t('forms.name')}</label>
<div>
<input
readonly={!$session.isAdmin}
@ -92,7 +95,9 @@
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="destination" class="text-base font-bold text-stone-100">Destination</label>
<label for="destination" class="text-base font-bold text-stone-100"
>{$t('application.destination')}</label
>
<div>
{#if service.destinationDockerId}
<div class="no-underline">
@ -108,10 +113,10 @@
</div>
<div class="grid grid-cols-2 px-10">
<div class="flex-col ">
<label for="fqdn" class="pt-2 text-base font-bold text-stone-100">Domain (FQDN)</label>
<Explainer
text="If you specify <span class='text-pink-600 font-bold'>https</span>, the application will be accessible only over https. SSL certificate will be generated for you.<br>If you specify <span class='text-pink-600 font-bold'>www</span>, the application will be redirected (302) from non-www and vice versa.<br><br>To modify the domain, you must first stop the application."
/>
<label for="fqdn" class="pt-2 text-base font-bold text-stone-100"
>{$t('application.domain_fqdn')}</label
>
<Explainer text={$t('application.https_explainer')} />
</div>
<CopyPasswordField
@ -128,10 +133,10 @@
<div class="grid grid-cols-2 items-center px-10">
<Setting
disabled={isRunning}
dataTooltip="Must be stopped to modify."
dataTooltip={$t('forms.must_be_stopped_to_modify')}
bind:setting={dualCerts}
title="Generate SSL for www and non-www?"
description="It will generate certificates for both www and non-www. <br>You need to have <span class='font-bold text-pink-600'>both DNS entries</span> set in advance.<br><br>Service needs to be restarted."
title={$t('application.ssl_www_and_non_www')}
description={$t('services.generate_www_non_www_ssl')}
on:click={() => !isRunning && changeSettings('dualCerts')}
/>
</div>

View File

@ -1,5 +1,6 @@
<script lang="ts">
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { t } from '$lib/translations';
export let service;
</script>
@ -8,7 +9,7 @@
<div class="title">VSCode Server</div>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="password">Password</label>
<label for="password">{$t('forms.password')}</label>
<CopyPasswordField
id="password"
isPasswordField

View File

@ -1,5 +1,6 @@
<script lang="ts">
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
import { t } from '$lib/translations';
export let service;
export let isRunning;
@ -11,7 +12,7 @@
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="extraConfig">Extra Config</label>
<label for="extraConfig">{$t('forms.extra_config')}</label>
<textarea
disabled={isRunning}
readonly={isRunning}
@ -20,7 +21,7 @@
name="extraConfig"
id="extraConfig"
placeholder={!isRunning
? `eg:
? `${$t('forms.eg')}:
define('WP_ALLOW_MULTISITE', true);
define('MULTISITE', true);
@ -32,7 +33,7 @@ define('SUBDOMAIN_INSTALL', false);`
<div class="title">MySQL</div>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="mysqlDatabase">Database</label>
<label for="mysqlDatabase">{$t('index.database')}</label>
<input
name="mysqlDatabase"
id="mysqlDatabase"
@ -40,7 +41,7 @@ define('SUBDOMAIN_INSTALL', false);`
readonly={readOnly}
disabled={readOnly}
bind:value={service.wordpress.mysqlDatabase}
placeholder="eg: wordpress_db"
placeholder="{$t('forms.eg')}: wordpress_db"
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
@ -48,7 +49,7 @@ define('SUBDOMAIN_INSTALL', false);`
<input
name="mysqlRootUser"
id="mysqlRootUser"
placeholder="MySQL Root User"
placeholder="MySQL {$t('forms.root_user')}"
value={service.wordpress.mysqlRootUser}
disabled
readonly
@ -66,11 +67,11 @@ define('SUBDOMAIN_INSTALL', false);`
/>
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="mysqlUser">User</label>
<label for="mysqlUser">{$t('forms.user')}</label>
<input name="mysqlUser" id="mysqlUser" value={service.wordpress.mysqlUser} disabled readonly />
</div>
<div class="grid grid-cols-2 items-center px-10">
<label for="mysqlPassword">Password</label>
<label for="mysqlPassword">{$t('forms.password')}</label>
<CopyPasswordField
id="mysqlPassword"
isPasswordField

View File

@ -64,6 +64,7 @@
import Loading from '$lib/components/Loading.svelte';
import { del, post } from '$lib/api';
import { goto } from '$app/navigation';
import { t } from '$lib/translations';
const { id } = $page.params;
export let service;
@ -72,7 +73,7 @@
let loading = false;
async function deleteService() {
const sure = confirm(`Are you sure you would like to delete '${service.name}'?`);
const sure = confirm(t.get('application.confirm_to_delete', { name: service.name }));
if (sure) {
loading = true;
try {
@ -87,7 +88,7 @@
}
}
async function stopService() {
const sure = confirm(`Are you sure you would like to stop '${service.name}'?`);
const sure = confirm(t.get('application.confirm_stop', { name: service.name }));
if (sure) {
loading = true;
try {
@ -121,13 +122,13 @@
{#if isRunning}
<button
on:click={stopService}
title="Stop Service"
title={$t('service.stop_service')}
type="submit"
disabled={!$session.isAdmin}
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-red-500"
data-tooltip={$session.isAdmin
? 'Stop Service'
: 'You do not have permission to stop the service.'}
? $t('service.stop_service')
: $t('service.permission_denied_stop_service')}
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -147,13 +148,13 @@
{:else}
<button
on:click={startService}
title="Start Service"
title={$t('service.start_service')}
type="submit"
disabled={!$session.isAdmin}
class="icons bg-transparent tooltip-bottom text-sm flex items-center space-x-2 text-green-500"
data-tooltip={$session.isAdmin
? 'Start Service'
: 'You do not have permission to start the service.'}
? $t('service.start_service')
: $t('service.permission_denied_start_service')}
><svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
@ -180,9 +181,9 @@
class:bg-coolgray-500={$page.url.pathname === `/services/${id}`}
>
<button
title="Configurations"
title={$t('application.configurations')}
class="icons bg-transparent tooltip-bottom text-sm disabled:text-red-500"
data-tooltip="Configurations"
data-tooltip={$t('application.configurations')}
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -215,9 +216,9 @@
class:bg-coolgray-500={$page.url.pathname === `/services/${id}/secrets`}
>
<button
title="Secrets"
title={$t('application.secret')}
class="icons bg-transparent tooltip-bottom text-sm disabled:text-red-500"
data-tooltip="Secrets"
data-tooltip={$t('application.secret')}
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -242,14 +243,14 @@
{/if}
<button
on:click={deleteService}
title="Delete Service"
title={$t('service.delete_service')}
type="submit"
disabled={!$session.isAdmin}
class:hover:text-red-500={$session.isAdmin}
class="icons bg-transparent tooltip-bottom text-sm"
data-tooltip={$session.isAdmin
? 'Delete Service'
: 'You do not have permission to delete a service.'}><DeleteIcon /></button
? $t('service.delete_service')
: $t('service.permission_denied_delete_service')}><DeleteIcon /></button
>
{/if}
</nav>

View File

@ -34,6 +34,7 @@
import { enhance, errorNotification } from '$lib/form';
import { goto } from '$app/navigation';
import { post } from '$lib/api';
import { t } from '$lib/translations';
const { id } = $page.params;
const from = $page.url.searchParams.get('from');
@ -50,12 +51,14 @@
</script>
<div class="flex space-x-1 p-6 font-bold">
<div class="mr-4 text-2xl tracking-tight">Configure Destination</div>
<div class="mr-4 text-2xl tracking-tight">
{$t('application.configuration.configure_destination')}
</div>
</div>
<div class="flex justify-center">
{#if !destinations || destinations.length === 0}
<div class="flex-col">
<div class="pb-2">No configurable Destination found</div>
<div class="pb-2">{$t('application.configuration.no_configurable_destination')}</div>
<div class="flex justify-center">
<a href="/new/destination" sveltekit:prefetch class="add-icon bg-sky-600 hover:bg-sky-500">
<svg

View File

@ -41,6 +41,7 @@
import N8n from '$lib/components/svg/services/N8n.svelte';
import UptimeKuma from '$lib/components/svg/services/UptimeKuma.svelte';
import Ghost from '$lib/components/svg/services/Ghost.svelte';
import { t } from '$lib/translations';
const { id } = $page.params;
const from = $page.url.searchParams.get('from');
@ -58,7 +59,7 @@
</script>
<div class="flex space-x-1 p-6 font-bold">
<div class="mr-4 text-2xl tracking-tight">Select a Service</div>
<div class="mr-4 text-2xl tracking-tight">{$t('forms.select_a_service')}</div>
</div>
<div class="flex flex-wrap justify-center">

View File

@ -47,7 +47,7 @@
</script>
<div class="flex space-x-1 p-6 font-bold">
<div class="mr-4 text-2xl tracking-tight">Select a Service version</div>
<div class="mr-4 text-2xl tracking-tight">{$t('forms.select_a_service_version')}</div>
</div>
<div class="flex flex-wrap justify-center">

View File

@ -26,6 +26,7 @@
import { getDomain } from '$lib/components/common';
import { page } from '$app/stores';
import { get } from '$lib/api';
import { t } from '$lib/translations';
const { id } = $page.params;
@ -37,7 +38,8 @@
<div class="flex space-x-1 p-6 font-bold">
<div class="mr-4 text-2xl tracking-tight">
Secrets {#if service.fqdn}
{$t('application.secret')}
{#if service.fqdn}
<a href={service.fqdn} target="_blank">{getDomain(service.fqdn)}</a>
{/if}
</div>
@ -46,9 +48,9 @@
<table class="mx-auto border-separate text-left">
<thead>
<tr class="h-12">
<th scope="col">Name</th>
<th scope="col">Value</th>
<th scope="col" class="w-96 text-center">Action</th>
<th scope="col">{$t('forms.name')}</th>
<th scope="col">{$t('forms.value')}</th>
<th scope="col" class="w-96 text-center">{$t('forms.action')}</th>
</tr>
</thead>
<tbody>

View File

@ -79,7 +79,7 @@
</div>
<div class="grid grid-flow-row gap-2 px-10">
<div class="grid grid-cols-2 items-center mt-2">
<label for="name" class="text-base font-bold text-stone-100">Name</label>
<label for="name" class="text-base font-bold text-stone-100">{$t('forms.name')}</label>
<input name="name" id="name" required bind:value={source.name} />
</div>
</div>

View File

@ -195,7 +195,7 @@
</div>
<div class="grid grid-flow-row gap-2 px-10">
<div class="mt-2 grid grid-cols-2 items-center">
<label for="name" class="text-base font-bold text-stone-100">Name</label>
<label for="name" class="text-base font-bold text-stone-100">{$t('forms.name')}</label>
<input name="name" id="name" required bind:value={source.name} />
</div>
</div>

View File

@ -107,7 +107,7 @@
<div class="grid grid-flow-row gap-2 px-10">
<div class="mt-2 grid grid-cols-2">
<div class="flex-col">
<label for="name" class="text-base font-bold text-stone-100">Name</label>
<label for="name" class="text-base font-bold text-stone-100">{$t('forms.name')}</label>
{#if team.id === '0'}
<Explainer
customClass="w-full"