feat: i18n web components

This commit is contained in:
Zack Spear
2023-08-01 14:32:46 -07:00
committed by Zack Spear
parent f12fc1dfa5
commit a1cd954442
20 changed files with 878 additions and 225 deletions
+26 -24
View File
@@ -13,9 +13,10 @@ import { useServerStore } from '~/store/server';
export interface Props {
open?: boolean;
t: any;
}
withDefaults(defineProps<Props>(), {
const props = withDefaults(defineProps<Props>(), {
open: false,
});
@@ -64,33 +65,33 @@ const showSignInCta = computed(() => connectPluginInstalled.value && !registered
const heading = computed(() => {
switch (callbackStatus.value) {
case 'error':
return 'Error';
return props.t('Error');
case 'loading':
return 'Performing actions';
return props.t('Performing actions');
case 'success':
return 'Success!';
return props.t('Success!');
}
});
const subheading = computed(() => {
if (callbackStatus.value === 'error') {
return 'Something went wrong'; /** @todo show actual error messages */
return props.t('Something went wrong'); /** @todo show actual error messages */
}
if (callbackStatus.value === 'loading') { return 'Please keep this window open while we perform some actions'; }
if (callbackStatus.value === 'loading') { return props.t('Please keep this window open while we perform some actions'); }
if (callbackStatus.value === 'success') {
if (accountActionType.value === 'signIn') { return 'You\'re one step closer to enhancing your Unraid experience'; }
if (keyActionType.value === 'purchase') { return `Thank you for purchasing an Unraid ${keyType.value} Key!`; }
if (keyActionType.value === 'replace') { return `Your ${keyType.value} Key has been replaced!`; }
if (keyActionType.value === 'trialExtend') { return 'Your Trial key has been extended!'; }
if (keyActionType.value === 'trialStart') { return 'Your free Trial key provides all the functionality of a Pro Registration key'; }
if (keyActionType.value === 'upgrade') { return `Thank you for upgrading to an Unraid ${keyType.value} Key!`; }
if (accountActionType.value === 'signIn') { return props.t('You\'re one step closer to enhancing your Unraid experience'); }
if (keyActionType.value === 'purchase') { return props.t('Thank you for purchasing an Unraid %{keyType} Key!', { keyType: keyType.value }); }
if (keyActionType.value === 'replace') { return props.t('Your %{keyType} Key has been replaced!', { keyType: keyType.value }); }
if (keyActionType.value === 'trialExtend') { return props.t('Your Trial key has been extended!'); }
if (keyActionType.value === 'trialStart') { return props.t('Your free Trial key provides all the functionality of a Pro Registration key'); }
if (keyActionType.value === 'upgrade') { return props.t('Thank you for upgrading to an Unraid %{keyType} Key!', { keyType: keyType.value }); }
return '';
}
return '';
});
const closeText = computed(() => {
const txt = !connectPluginInstalled.value ? 'No Thanks' : 'Close';
return refreshServerStateStatus.value === 'done' ? txt : 'Reload';
const txt = !connectPluginInstalled.value ? props.t('No thanks') : props.t('Close');
return refreshServerStateStatus.value === 'done' ? txt : props.t('Reload');
});
const close = () => {
if (callbackStatus.value === 'loading') { return console.debug('[close] not allowed'); }
@@ -104,11 +105,12 @@ const promoClick = () => {
close();
};
const { text, copy, copied, isSupported } = useClipboard({ source: keyUrl.value });
const { copy, copied, isSupported } = useClipboard({ source: keyUrl.value });
</script>
<template>
<Modal
:t="t"
:title="heading"
:description="subheading"
:open="open"
@@ -137,14 +139,14 @@ const { text, copy, copied, isSupported } = useClipboard({ source: keyUrl.value
<div v-if="isSupported" class="flex justify-center">
<BrandButton
:icon="ClipboardIcon"
:text="copied ? 'Copied' : 'Copy Key URL'"
:text="copied ? t('Copied') : t('Copy Key URL')"
@click="copy(keyUrl)"
/>
</div>
<p v-else>
{{ 'Copy your Key URL' }}: {{ keyUrl }}
{{ t('Copy your Key URL: %{keyUrl}', { keyUrl }) }}
</p>
<p><a href="/Tools/Registration" class="opacity-75 hover:opacity-100 focus:opacity-100 underline transition">{{ 'Then go to Tools > Registration to manually install it' }}</a></p>
<p><a href="/Tools/Registration" class="opacity-75 hover:opacity-100 focus:opacity-100 underline transition">{{ t('Then go to Tools > Registration to manually install it') }}</a></p>
</template>
</UpcCallbackFeedbackStatus>
@@ -158,13 +160,13 @@ const { text, copy, copied, isSupported } = useClipboard({ source: keyUrl.value
<UpcCallbackFeedbackStatus
v-if="showPromoCta"
:icon="InformationCircleIcon"
:text="'Enhance your experience with Unraid Connect'"
:text="t('Enhance your experience with Unraid Connect')"
/>
<UpcCallbackFeedbackStatus
v-if="showSignInCta"
:icon="InformationCircleIcon"
:text="'Sign In to utilize Unraid Connect'"
:text="t('Sign In to utilize Unraid Connect')"
/>
</div>
</template>
@@ -175,7 +177,7 @@ const { text, copy, copied, isSupported } = useClipboard({ source: keyUrl.value
<BrandButton
v-if="isSettingsPage"
:icon="CogIcon"
:text="'Configure Connect Features'"
:text="t('Configure Connect Features')"
class="grow-0"
@click="close"
/>
@@ -183,14 +185,14 @@ const { text, copy, copied, isSupported } = useClipboard({ source: keyUrl.value
v-else
:href="PLUGIN_SETTINGS"
:icon="CogIcon"
:text="'Configure Connect Features'"
:text="t('Configure Connect Features')"
class="grow-0"
/>
</template>
<BrandButton
v-if="showPromoCta"
:text="'Learn More'"
:text="t('Learn More')"
@click="promoClick"
/>
@@ -198,7 +200,7 @@ const { text, copy, copied, isSupported } = useClipboard({ source: keyUrl.value
v-if="showSignInCta"
:external="authAction?.external"
:icon="authAction?.icon"
:text="authAction?.text"
:text="t(authAction?.text)"
@click="authAction?.click"
/>
+27 -17
View File
@@ -3,6 +3,8 @@
* @todo future idea turn this into a carousel. each feature could have a short video if we ever them
*/
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue';
import { ArrowTopRightOnSquareIcon } from '@heroicons/vue/24/solid';
import useInstallPlugin from '~/composables/installPlugin';
import { usePromoStore } from '~/store/promo';
import type { UserProfilePromoFeature } from '~/types/userProfile';
@@ -11,6 +13,7 @@ import '~/assets/main.css';
export interface Props {
open?: boolean;
t: any;
}
withDefaults(defineProps<Props>(), {
@@ -56,18 +59,17 @@ const features = ref<UserProfilePromoFeature[]>([
const staging = ref(false);
const { install } = useInstallPlugin();
const installButtonClasses = 'text-white text-14px text-center w-full flex flex-row items-center justify-center gap-x-8px px-8px py-8px cursor-pointer rounded-md bg-gradient-to-r from-unraid-red to-orange hover:from-unraid-red/60 hover:to-orange/60 focus:from-unraid-red/60 focus:to-orange/60';
</script>
<template>
<Modal
title="Introducing Unraid Connect"
description="Enhance your Unraid experience"
:t="t"
:title="t('Introducing Unraid Connect')"
:description="t('Enhance your Unraid experience')"
:open="open"
@close="promoStore.promoHide()"
:show-close-x="true"
max-width="max-w-800px"
@close="promoStore.promoHide()"
>
<template #headerTitle>
<span><UpcBeta class="relative -top-1" /></span>
@@ -79,8 +81,8 @@ const installButtonClasses = 'text-white text-14px text-center w-full flex flex-
<UpcPromoFeature
v-for="(feature, index) in features"
:key="index"
:title="feature.title"
:copy="feature.copy"
:title="t(feature.title)"
:copy="t(feature.copy)"
/>
</div>
</div>
@@ -91,27 +93,35 @@ const installButtonClasses = 'text-white text-14px text-center w-full flex flex-
<!-- v-if="devEnv" -->
<SwitchGroup as="div" class="flex items-center justify-center">
<Switch v-model="staging" :class="[staging ? 'bg-indigo-600' : 'bg-gray-200', 'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2']">
<span aria-hidden="true" :class="[staging ? 'translate-x-5' : 'translate-x-0', 'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out']" />
<span aria-hidden="true" :class="[staging ? 't-x-5' : 't-x-0', 'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out']" />
</Switch>
<SwitchLabel as="span" class="ml-3 text-12px">
<span class="font-semibold">Install Staging</span>
</SwitchLabel>
</SwitchGroup>
<button @click="install({ staging, update: false })" :class="installButtonClasses">{{ staging ? 'Install Connect Staging' : 'Install Connect' }}</button>
<button
class="text-white text-14px text-center w-full flex flex-row items-center justify-center gap-x-8px px-8px py-8px cursor-pointer rounded-md bg-gradient-to-r from-unraid-red to-orange hover:from-unraid-red/60 hover:to-orange/60 focus:from-unraid-red/60 focus:to-orange/60"
@click="install({ staging, update: false })"
>
{{ staging ? 'Install Connect Staging' : t('Install Connect') }}
</button>
<div>
<a
href="https://docs.unraid.net/category/unraid-connect"
class="text-12px tracking-wide inline-block mx-8px opacity-60 hover:opacity-100 focus:opacity-100 underline transition"
class="text-12px tracking-wide inline-flex flex-row items-center justify-start gap-8px mx-8px opacity-60 hover:opacity-100 focus:opacity-100 underline transition"
target="_blank"
rel="noopener noreferrer"
:title="'Checkout the Connect Documentation'"
>{{ 'Learn More' }}</a>
<button
@click="promoStore.promoHide()"
class="text-12px tracking-wide inline-block mx-8px opacity-60 hover:opacity-100 focus:opacity-100 underline transition"
:title="'Close Promo'"
:title="t('Checkout the Connect Documentation')"
>
{{ 'No thanks' }}
{{ t('Learn More') }}
<ArrowTopRightOnSquareIcon class="w-16px" />
</a>
<button
class="text-12px tracking-wide inline-block mx-8px opacity-60 hover:opacity-100 focus:opacity-100 underline transition"
:title="t('Close')"
@click="promoStore.promoHide()"
>
{{ t('No thanks') }}
</button>
</div>
</div>
+9 -7
View File
@@ -1,9 +1,10 @@
<script lang="ts" setup>
import { storeToRefs } from "pinia";
import { useTrialStore } from "~/store/trial";
import { storeToRefs } from 'pinia';
import { useTrialStore } from '~/store/trial';
export interface Props {
open?: boolean;
t: any;
}
withDefaults(defineProps<Props>(), {
@@ -14,19 +15,20 @@ const trialStore = useTrialStore();
const { trialModalLoading, trialStatus, trialStatusCopy } = storeToRefs(trialStore);
const close = () => {
if (trialStatus.value === 'trialStart') return console.debug("[close] not allowed");
if (trialStatus.value === 'trialStart') { return console.debug('[close] not allowed'); }
trialStore.setTrialStatus('ready');
};
</script>
<template>
<Modal
@close="close"
:t="t"
:open="open"
:title="trialStatusCopy?.heading"
:description="trialStatusCopy?.subheading"
:show-close-x="!trialModalLoading"
max-width="max-w-640px"
@close="close"
>
<template #main>
<BrandLoading v-if="trialModalLoading" class="w-[150px] mx-auto my-24px" />
@@ -36,11 +38,11 @@ const close = () => {
<div class="w-full max-w-xs flex flex-col items-center gap-y-16px mx-auto">
<div>
<button
@click="close"
class="text-12px tracking-wide inline-block mx-8px opacity-60 hover:opacity-100 focus:opacity-100 underline transition"
:title="'Close Modal'"
:title="t('Close Modal')"
@click="close"
>
{{ "Close" }}
{{ t('Close') }}
</button>
</div>
</div>