docs: how to translate dashboard (#292)
* add cloud translation api package * feat: Script that auto generates translations for other languages * add comments * fix: broken translation * improve translation * update locck file * clean up * all round trasnlations check * checkpoint * finish up * move to dev dependencies * fix vercel build error * translations fix * - add documentation - translation bug fix * quick adjust * PR Fixes * add new line * update docs --------- Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
co-authored by
Rotimi Best
parent
96cbff675d
commit
3a5d13ea41
@@ -22,7 +22,7 @@ const languageFiles = {
|
||||
pt: path.resolve(__dirname, '../src/lib/utils/translations/pt.json'),
|
||||
de: path.resolve(__dirname, '../src/lib/utils/translations/de.json'),
|
||||
vi: path.resolve(__dirname, '../src/lib/utils/translations/vi.json'),
|
||||
ru: path.resolve(__dirname, '../src/lib/utils/translations/re.json'),
|
||||
ru: path.resolve(__dirname, '../src/lib/utils/translations/ru.json'),
|
||||
es: path.resolve(__dirname, '../src/lib/utils/translations/es.json')
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import IconButton from '$lib/components/IconButton/index.svelte';
|
||||
import { Loading } from 'carbon-components-svelte';
|
||||
import HtmlRender from '$lib/components/HTMLRender/HTMLRender.svelte';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
export let className = '';
|
||||
export let handleInsert = (v: string) => {};
|
||||
@@ -39,7 +40,7 @@
|
||||
function callAI(prompt: string, rephrase: boolean) {
|
||||
isSubmitted = true;
|
||||
|
||||
$input = rephrase ? `Can you please rephrase this: ${plainText}` : prompt;
|
||||
$input = rephrase ? `${$t('ai.can_you')}: ${plainText}` : prompt;
|
||||
|
||||
setTimeout(() => {
|
||||
handleSubmit({ preventDefault: () => {} });
|
||||
@@ -91,7 +92,7 @@
|
||||
{#if $isLoading}
|
||||
<Loading withOverlay={false} small />
|
||||
{:else}
|
||||
Insert
|
||||
{$t('ai.insert')}
|
||||
{/if}
|
||||
</button>
|
||||
<button
|
||||
@@ -101,7 +102,7 @@
|
||||
type="button"
|
||||
disabled={$isLoading}
|
||||
>
|
||||
Rephrase
|
||||
{$t('ai.rephrase')}
|
||||
</button>
|
||||
{#if !$isLoading}
|
||||
<button
|
||||
@@ -109,25 +110,25 @@
|
||||
on:click|preventDefault={restart}
|
||||
type="button"
|
||||
>
|
||||
Reset
|
||||
{$t('ai.reset')}
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="h-full">
|
||||
<p class="text-sm font-medium mb-2 ml-1">Help me write</p>
|
||||
<p class="text-sm font-medium mb-2 ml-1">{$t('ai.help_me')}</p>
|
||||
<textarea
|
||||
bind:value={prompt}
|
||||
class="w-full border-0 rounded-lg h-[65%] text-sm m-0 dark:text-black"
|
||||
placeholder="Help me write a short description"
|
||||
placeholder={$t('ai.placeholder')}
|
||||
/>
|
||||
<button
|
||||
class="flex text-xs px-4 py-2 m-0 border rounded-md font-medium"
|
||||
on:click|preventDefault={() => callAI(prompt, false)}
|
||||
type="button"
|
||||
>
|
||||
Start typing...
|
||||
{$t('ai.text')}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<UpgradeBanner>Upgrade your plan to generate certificates</UpgradeBanner>
|
||||
<UpgradeBanner>{$t('upgrade.certificate')}</UpgradeBanner>
|
||||
|
||||
<main class="md:-ml-3 md:-mr-3 px-2 mt-2">
|
||||
<div class="flex-1 flex flex-col lg:flex-row justify-between gap-3 w-full mb-3 h-4/5">
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@
|
||||
{$t('course.navItem.certificates.locked_certificate')}
|
||||
</p>
|
||||
<p class="text-sm font-normal text-center">
|
||||
{$t('course.navItem.certificates.locked_certificate_body_1')} <br />
|
||||
{$t('course.navItem.certificates.locked_certificate_body_2')}
|
||||
{$t('course.navItem.certificates.instructor_unlock')} <br />
|
||||
{$t('course.navItem.certificates.contact_instructor')}
|
||||
</p>
|
||||
</div>
|
||||
</Box>
|
||||
|
||||
+10
-6
@@ -41,20 +41,24 @@
|
||||
|
||||
const options = [
|
||||
{
|
||||
title: $t('course.navItem.lessons.exercises.new_exercise_modal.options.1'),
|
||||
subtitle: $t('course.navItem.lessons.exercises.new_exercise_modal.options.subtitle_1'),
|
||||
title: $t('course.navItem.lessons.exercises.new_exercise_modal.options.from_scratch'),
|
||||
subtitle: $t(
|
||||
'course.navItem.lessons.exercises.new_exercise_modal.options.from_scratch_subtitle'
|
||||
),
|
||||
type: Type.SCRATCH,
|
||||
isDisabled: false
|
||||
},
|
||||
{
|
||||
title: $t('course.navItem.lessons.exercises.new_exercise_modal.options.2'),
|
||||
subtitle: $t('course.navItem.lessons.exercises.new_exercise_modal.options.subtitle_2'),
|
||||
title: $t('course.navItem.lessons.exercises.new_exercise_modal.options.use_template'),
|
||||
subtitle: $t(
|
||||
'course.navItem.lessons.exercises.new_exercise_modal.options.use_template_subtitle'
|
||||
),
|
||||
type: Type.TEMPLATE,
|
||||
isDisabled: false
|
||||
},
|
||||
{
|
||||
title: $t('course.navItem.lessons.exercises.new_exercise_modal.options.3'),
|
||||
subtitle: $t('course.navItem.lessons.exercises.new_exercise_modal.options.subtitle_3'),
|
||||
title: $t('course.navItem.lessons.exercises.new_exercise_modal.options.use_ai'),
|
||||
subtitle: $t('course.navItem.lessons.exercises.new_exercise_modal.options.use_ai_subtitle'),
|
||||
type: Type.AI,
|
||||
isDisabled: false
|
||||
}
|
||||
|
||||
+4
-4
@@ -177,8 +177,8 @@
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.oops')}
|
||||
</h3>
|
||||
<p class="text-center text-xs font-normal text-[#ADADAD]">
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.sorry')}<br />
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.sorry_2')}
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.big_file')}<br />
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.maximum_size')}
|
||||
</p>
|
||||
</span>
|
||||
<PrimaryButton
|
||||
@@ -194,8 +194,8 @@
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.oops')}
|
||||
</h3>
|
||||
<p class="text-center text-xs font-normal text-[#ADADAD]">
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.sorry_3')}<br />
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.sorry_4')}
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.unsupported_format')}<br />
|
||||
{$t('course.navItem.lessons.materials.tabs.video.add_video.format')}
|
||||
</p>
|
||||
</span>
|
||||
<PrimaryButton
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
|
||||
if (updateError) {
|
||||
console.error('Error updating translation:', updateError.message);
|
||||
snackbar.error('Updating translations failed');
|
||||
snackbar.error('snackbar.materials.update_translations');
|
||||
}
|
||||
} else {
|
||||
const { error: insertError } = await supabase.from('lesson_language').insert({
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
if (insertError) {
|
||||
console.error('Error inserting translation:', insertError.message);
|
||||
snackbar.error('Creating new translations failed');
|
||||
snackbar.error('snackbar.materials.creating_new');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,13 +138,13 @@
|
||||
$: {
|
||||
navItems = [
|
||||
{
|
||||
label: $t('course.navItems.1'),
|
||||
label: $t('course.navItems.nav_news_feed'),
|
||||
to: getNavItemRoute($course.id),
|
||||
hideSortIcon: true,
|
||||
isPaidFeature: false
|
||||
},
|
||||
{
|
||||
label: $t('course.navItems.2'),
|
||||
label: $t('course.navItems.nav_lessons'),
|
||||
to: getLessonsRoute($course.id),
|
||||
hideSortIcon: false,
|
||||
isPaidFeature: false,
|
||||
@@ -152,13 +152,13 @@
|
||||
isExpanded: isStudent ? true : $page.url.pathname.includes('/lessons')
|
||||
},
|
||||
{
|
||||
label: $t('course.navItems.3'),
|
||||
label: $t('course.navItems.nav_attendance'),
|
||||
to: getNavItemRoute($course.id, 'attendance'),
|
||||
isPaidFeature: false,
|
||||
hideSortIcon: true
|
||||
},
|
||||
{
|
||||
label: $t('course.navItems.4'),
|
||||
label: $t('course.navItems.nav_submissions'),
|
||||
to: getNavItemRoute($course.id, 'submissions'),
|
||||
hideSortIcon: true,
|
||||
isPaidFeature: false,
|
||||
@@ -167,13 +167,13 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
label: $t('course.navItems.5'),
|
||||
label: $t('course.navItems.nav_marks'),
|
||||
to: getNavItemRoute($course.id, 'marks'),
|
||||
isPaidFeature: false,
|
||||
hideSortIcon: true
|
||||
},
|
||||
{
|
||||
label: $t('course.navItems.6'),
|
||||
label: $t('course.navItems.nav_people'),
|
||||
to: getNavItemRoute($course.id, 'people'),
|
||||
isPaidFeature: false,
|
||||
hideSortIcon: true,
|
||||
@@ -182,7 +182,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
label: $t('course.navItems.7'),
|
||||
label: $t('course.navItems.nav_certificates'),
|
||||
to: getNavItemRoute($course.id, 'certificates'),
|
||||
hideSortIcon: true,
|
||||
isPaidFeature: true,
|
||||
@@ -195,7 +195,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
label: $t('course.navItems.8'),
|
||||
label: $t('course.navItems.nav_landing_page'),
|
||||
to: getNavItemRoute($course.id, 'landingpage'),
|
||||
hideSortIcon: true,
|
||||
isPaidFeature: false,
|
||||
@@ -204,7 +204,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
label: $t('course.navItems.9'),
|
||||
label: $t('course.navItems.nav_settings'),
|
||||
to: getNavItemRoute($course.id, 'settings'),
|
||||
hideSortIcon: true,
|
||||
isPaidFeature: false,
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
</Column>
|
||||
<Column sm={8} md={8} lg={8}>
|
||||
{#if $isFreePlan}
|
||||
<UpgradeBanner>Upgrade to download lessons</UpgradeBanner>
|
||||
<UpgradeBanner>{$t('upgrade.download_lessons')}</UpgradeBanner>
|
||||
{:else}
|
||||
<Toggle size="sm" bind:toggled={$settings.lesson_download}>
|
||||
<span slot="labelA" style="color: gray">{$t('course.navItem.settings.disabled')}</span>
|
||||
@@ -304,7 +304,7 @@
|
||||
</Column>
|
||||
<Column sm={8} md={8} lg={8}>
|
||||
{#if $isFreePlan}
|
||||
<UpgradeBanner>Upgrade to download course</UpgradeBanner>
|
||||
<UpgradeBanner>{$t('upgrade.download_course')}</UpgradeBanner>
|
||||
{:else}
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@
|
||||
labelClassName="font-bold"
|
||||
label={$t('course.navItem.landing_page.editor.header_form.short_video')}
|
||||
placeholder="www.youtube.com/watch?v=uYRq60G5XTk"
|
||||
helperMessage="Enter a link to a youtube video"
|
||||
helperMessage={$t('course.navItem.landing_page.editor.header_form.helper')}
|
||||
type="text"
|
||||
bind:value={course.metadata.videoUrl}
|
||||
/>
|
||||
|
||||
+7
-7
@@ -62,7 +62,7 @@
|
||||
|
||||
<div class="mt-5">
|
||||
<label for="upload" class="font-bold"
|
||||
>{$t('course.navItem.landing_page.editor.instructure_form.upload')}</label
|
||||
>{$t('course.navItem.landing_page.editor.instructor_form.upload')}</label
|
||||
>
|
||||
<UploadImage bind:avatar src={imgUrl} />
|
||||
</div>
|
||||
@@ -70,22 +70,22 @@
|
||||
<TextField
|
||||
className="mt-5"
|
||||
labelClassName="font-bold"
|
||||
label={$t('course.navItem.landing_page.editor.instructure_form.name')}
|
||||
placeholder={$t('course.navItem.landing_page.editor.instructure_form.name_placeholder')}
|
||||
label={$t('course.navItem.landing_page.editor.instructor_form.name')}
|
||||
placeholder={$t('course.navItem.landing_page.editor.instructor_form.name_placeholder')}
|
||||
bind:value={name}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
className="mt-5"
|
||||
labelClassName="font-bold"
|
||||
label={$t('course.navItem.landing_page.editor.instructure_form.role')}
|
||||
label={$t('course.navItem.landing_page.editor.instructor_form.role')}
|
||||
placeholder="e.g Software developer"
|
||||
bind:value={role}
|
||||
/>
|
||||
|
||||
<TextArea
|
||||
label={$t('course.navItem.landing_page.editor.instructure_form.about')}
|
||||
placeholder={$t('course.navItem.landing_page.editor.instructure_form.about_placeholder')}
|
||||
label={$t('course.navItem.landing_page.editor.instructor_form.about')}
|
||||
placeholder={$t('course.navItem.landing_page.editor.instructor_form.about_placeholder')}
|
||||
rows={6}
|
||||
className="mt-5"
|
||||
labelClassName="font-bold"
|
||||
@@ -95,7 +95,7 @@
|
||||
<TextField
|
||||
className="mt-5"
|
||||
labelClassName="font-bold"
|
||||
label={$t('course.navItem.landing_page.editor.instructure_form.total')}
|
||||
label={$t('course.navItem.landing_page.editor.instructor_form.total')}
|
||||
type="number"
|
||||
bind:value={courseNo}
|
||||
/>
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@
|
||||
import ReviewFormEditor from './ReviewFormEditor.svelte';
|
||||
import Avatar from '$lib/components/Avatar/index.svelte';
|
||||
import { processErrors } from '$lib/utils/functions/validator';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
export let course = {};
|
||||
|
||||
@@ -125,7 +126,7 @@
|
||||
|
||||
<!-- create reviews button -->
|
||||
<PrimaryButton
|
||||
label="Add Reviews"
|
||||
label={$t('course.navItem.landing_page.editor.reviews_form.add_reviews')}
|
||||
variant={VARIANTS.CONTAINED}
|
||||
onClick={addReviewForm}
|
||||
className="w-5 rounded-md mt-8"
|
||||
|
||||
@@ -47,43 +47,43 @@
|
||||
{
|
||||
key: 1,
|
||||
path: '',
|
||||
title: $t('course.navItem.landing_page.editor.title.1')
|
||||
title: $t('course.navItem.landing_page.editor.title.header')
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
path: 'metadata.requirements',
|
||||
title: $t('course.navItem.landing_page.editor.title.2'),
|
||||
title: $t('course.navItem.landing_page.editor.title.requirement'),
|
||||
enableAIWriter: true,
|
||||
initPrompt: 'Please write few requirements needed to take this course:'
|
||||
initPrompt: $t('course.navItem.landing_page.editor.title.requirement')
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
path: 'metadata.description',
|
||||
title: $t('course.navItem.landing_page.editor.title.3'),
|
||||
title: $t('course.navItem.landing_page.editor.title.description'),
|
||||
enableAIWriter: true,
|
||||
initPrompt: 'Please write a detailed course description for this course:'
|
||||
},
|
||||
{
|
||||
key: 4,
|
||||
path: 'metadata.goals',
|
||||
title: $t('course.navItem.landing_page.editor.title.4'),
|
||||
title: $t('course.navItem.landing_page.editor.title.goals'),
|
||||
enableAIWriter: true,
|
||||
initPrompt: 'What should a student expect to learn from this course:'
|
||||
},
|
||||
{
|
||||
key: 5,
|
||||
path: '',
|
||||
title: $t('course.navItem.landing_page.editor.title.5')
|
||||
title: $t('course.navItem.landing_page.editor.title.reviews')
|
||||
},
|
||||
{
|
||||
key: 6,
|
||||
path: '',
|
||||
title: $t('course.navItem.landing_page.editor.title.6')
|
||||
title: $t('course.navItem.landing_page.editor.title.instructor')
|
||||
},
|
||||
{
|
||||
key: 7,
|
||||
path: '',
|
||||
title: $t('course.navItem.landing_page.editor.title.7')
|
||||
title: $t('course.navItem.landing_page.editor.title.pricing')
|
||||
}
|
||||
];
|
||||
let selectedSection: Section | null = null;
|
||||
|
||||
@@ -13,26 +13,26 @@ export const SECTION_KEYS = {
|
||||
export const NAV_ITEMS = [
|
||||
{
|
||||
key: SECTION_KEYS.REQUIREMENT,
|
||||
label: 'course.navItem.landing_page.editor.title.2'
|
||||
label: 'course.navItem.landing_page.editor.title.requirement'
|
||||
},
|
||||
{
|
||||
key: SECTION_KEYS.DESCRIPTION,
|
||||
label: 'course.navItem.landing_page.editor.title.3'
|
||||
label: 'course.navItem.landing_page.editor.title.description'
|
||||
},
|
||||
{
|
||||
key: SECTION_KEYS.GOALS,
|
||||
label: 'course.navItem.landing_page.editor.title.4'
|
||||
label: 'course.navItem.landing_page.editor.title.goals'
|
||||
},
|
||||
{
|
||||
key: SECTION_KEYS.LESSONS,
|
||||
label: 'course.navItems.2'
|
||||
label: 'course.navItems.nav_lessons'
|
||||
},
|
||||
{
|
||||
key: SECTION_KEYS.REVIEWS,
|
||||
label: 'course.navItem.landing_page.editor.title.5'
|
||||
label: 'course.navItem.landing_page.editor.title.reviews'
|
||||
},
|
||||
{
|
||||
key: SECTION_KEYS.INSTRUCTOR,
|
||||
label: 'course.navItem.landing_page.editor.title.6'
|
||||
label: 'course.navItem.landing_page.editor.title.instructor'
|
||||
}
|
||||
];
|
||||
|
||||
@@ -125,7 +125,11 @@
|
||||
</p>
|
||||
<p class="text-xs py-2">
|
||||
{#if isOnLandingPage}
|
||||
<span class="px-2">{!cost ? 'Free' : formatter.format(cost)}</span>
|
||||
<span class="px-2"
|
||||
>{!cost
|
||||
? $t('course.navItem.landing_page.pricing_section')
|
||||
: formatter.format(cost)}</span
|
||||
>
|
||||
{:else if isLMS}
|
||||
<div class="flex items-center gap-2">
|
||||
<div class=" relative bg-[#EAEAEA] w-[50px] h-1">
|
||||
|
||||
@@ -72,15 +72,15 @@
|
||||
<h3 class="font-normal text-lg">
|
||||
{$t('settings.integrations.sub_heading')}
|
||||
</h3>
|
||||
<h4 class="font-normal">{$t('settings.integrations.step_1')}</h4>
|
||||
<h4 class="font-normal">{$t('settings.integrations.step_authenticate')}</h4>
|
||||
<PrimaryButton
|
||||
className="mb-5"
|
||||
variant={VARIANTS.OUTLINED}
|
||||
onClick={() => window.open('https://t.me/classroomio_bot', '_blank')}
|
||||
><span class="mr-2">{$t('settings.integrations.button_1')}</span>
|
||||
><span class="mr-2">{$t('settings.integrations.open_bot_button')}</span>
|
||||
<ArrowUpRightIcon /></PrimaryButton
|
||||
>
|
||||
<h4 class="font-normal">{$t('settings.integrations.step_2')}</h4>
|
||||
<h4 class="font-normal">{$t('settings.integrations.step_chatId')}</h4>
|
||||
<TextField
|
||||
bind:value={chatId}
|
||||
placeholder="360111"
|
||||
@@ -88,7 +88,9 @@
|
||||
type="number"
|
||||
isRequired
|
||||
/>
|
||||
<PrimaryButton onClick={addChatId}>{$t('settings.integrations.button_2')}</PrimaryButton>
|
||||
<PrimaryButton onClick={addChatId}
|
||||
>{$t('settings.integrations.connect_button')}</PrimaryButton
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
</Column>
|
||||
|
||||
@@ -45,35 +45,35 @@
|
||||
tabs = [
|
||||
{
|
||||
key: 0,
|
||||
label: $t('settings.tabs.1'),
|
||||
label: $t('settings.tabs.profile_tab'),
|
||||
tabKey: '',
|
||||
href: $page.url.pathname,
|
||||
disabled: false
|
||||
},
|
||||
{
|
||||
key: 1,
|
||||
label: $t('settings.tabs.2'),
|
||||
label: $t('settings.tabs.organization_tab'),
|
||||
tabKey: 'org',
|
||||
href: `${$page.url.pathname}?tab=org`,
|
||||
disabled: !$isOrgAdmin
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
label: $t('settings.tabs.3'),
|
||||
label: $t('settings.tabs.landing_page_tab'),
|
||||
tabKey: 'landingpage',
|
||||
href: `${$page.url.pathname}?tab=landingpage`,
|
||||
disabled: !$isOrgAdmin
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
label: $t('settings.tabs.4'),
|
||||
label: $t('settings.tabs.billing_tab'),
|
||||
tabKey: 'billing',
|
||||
href: `${$page.url.pathname}?tab=billing`,
|
||||
disabled: !$isOrgAdmin
|
||||
},
|
||||
{
|
||||
key: 4,
|
||||
label: $t('settings.tabs.5'),
|
||||
label: $t('settings.tabs.integrations_tab'),
|
||||
tabKey: 'integrations',
|
||||
href: `${$page.url.pathname}?tab=integrations`,
|
||||
disabled: false
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
import TextChip from '$lib/components/Chip/Text.svelte';
|
||||
import Plan from '$lib/components/Chip/Plan.svelte';
|
||||
import { PLAN_NAMES } from 'shared/src/plans/constants';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
export let canAddOrg = true;
|
||||
|
||||
@@ -90,7 +91,12 @@
|
||||
/>
|
||||
{/each}
|
||||
|
||||
<OrgSelectorItem disabled={true} size="" text=" + Add Organization" onClick={handleAddOrg} />
|
||||
<OrgSelectorItem
|
||||
disabled={true}
|
||||
size=""
|
||||
text={$t('navigation.add_organization')}
|
||||
onClick={handleAddOrg}
|
||||
/>
|
||||
</Popover>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
});
|
||||
|
||||
if (!checkoutURL) {
|
||||
snackbar.error('upgrade.generate_fail');
|
||||
snackbar.error('snackbar.upgrade.generate_fail');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
} catch (error) {
|
||||
console.error('Error subscribing', error);
|
||||
|
||||
snackbar.error('upgrade.failed');
|
||||
snackbar.error('snackbar.upgrade.failed');
|
||||
}
|
||||
|
||||
isLoadingPlan = null;
|
||||
@@ -158,7 +158,7 @@
|
||||
? 'text-white'
|
||||
: 'text-gray-900'} dark:text-white lg:text-xl"
|
||||
>
|
||||
{$t(PLANS[planName].NAME)}
|
||||
{PLANS[planName].NAME}
|
||||
</p>
|
||||
<p
|
||||
class="text-baseline flex items-baseline gap-x-1 font-medium {planName ===
|
||||
@@ -167,9 +167,9 @@
|
||||
: 'text-black'} dark:text-gray-300"
|
||||
>
|
||||
{PLANS[planName].PRICE.CURRENCY}
|
||||
{$t(PLANS[planName].PRICE.MONTHLY)}
|
||||
{PLANS[planName].PRICE.MONTHLY}
|
||||
{#if !PLANS[planName].PRICE.IS_PREMIUM}
|
||||
/{$t('pricing.modal.month')}
|
||||
/month
|
||||
{/if}
|
||||
</p>
|
||||
<p
|
||||
@@ -177,7 +177,7 @@
|
||||
? 'text-white'
|
||||
: 'text-black'} dark:text-gray-300 lg:leading-6"
|
||||
>
|
||||
{$t(PLANS[planName].DESCRIPTION)}
|
||||
{PLANS[planName].DESCRIPTION}
|
||||
</p>
|
||||
|
||||
<button
|
||||
@@ -196,7 +196,7 @@
|
||||
{#if isLoadingPlan === planName}
|
||||
<Loading withOverlay={false} small />
|
||||
{:else}
|
||||
{$t(PLANS[planName].CTA.DASHBOARD_LABEL)}
|
||||
{PLANS[planName].CTA.DASHBOARD_LABEL}
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
/>
|
||||
</div>
|
||||
<p class="text-sm">
|
||||
{$t(features)}
|
||||
{features}
|
||||
</p>
|
||||
</li>
|
||||
{/each}
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
<a href="https://app.classroomio.com/" class="text-primary-700 no-underline hover:no-underline"
|
||||
>ClassroomIO</a
|
||||
>
|
||||
{$t('welcome_modal.content_1')}
|
||||
<span class="text-primary-700">{$t('welcome_modal.content_2')};</span>
|
||||
{$t('welcome_modal.content_3')}
|
||||
{$t('welcome_modal.small_team')}
|
||||
<span class="text-primary-700">{$t('welcome_modal.thank_you')};</span>
|
||||
{$t('welcome_modal.deeply_appreciate')}
|
||||
</p>
|
||||
<img src="/images/welcome-img.svg" alt="A welcome banner" class="w-full my-6" />
|
||||
</Modal>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,9 +30,9 @@
|
||||
|
||||
"welcome_modal": {
|
||||
"we_at": "We at",
|
||||
"content_1": "are a small team with a large mission to empower educators with great technology to help them train the future generation. Education is the most powerful gift you can give anyone, and it makes so much sense to give you all the tools you need to give more people this GIFT.",
|
||||
"content_2": "Thank you for choosing us",
|
||||
"content_3": "we deeply appreciate it and are at your service."
|
||||
"small_team": "are a small team with a large mission to empower educators with great technology to help them train the future generation. Education is the most powerful gift you can give anyone, and it makes so much sense to give you all the tools you need to give more people this GIFT.",
|
||||
"thank_you": "Thank you for choosing us",
|
||||
"deeply_appreciate": "we deeply appreciate it and are at your service."
|
||||
},
|
||||
|
||||
"login": {
|
||||
@@ -49,12 +49,12 @@
|
||||
"view_site": "View site"
|
||||
},
|
||||
"tabs": {
|
||||
"1": "Profile",
|
||||
"2": "Organization",
|
||||
"3": "Landing Page",
|
||||
"4": "Billing",
|
||||
"5": "Integrations",
|
||||
"6": "Language"
|
||||
"profile_tab": "Profile",
|
||||
"organization_tab": "Organization",
|
||||
"landing_page_tab": "Landing Page",
|
||||
"billing_tab": "Billing",
|
||||
"integrations_tab": "Integrations",
|
||||
"language_tab": "Language"
|
||||
},
|
||||
"profile": {
|
||||
"profile_picture": {
|
||||
@@ -172,10 +172,10 @@
|
||||
"integrations": {
|
||||
"heading": "Telegram",
|
||||
"sub_heading": "Connect your account to telegram to get notified of any change within the application.",
|
||||
"step_1": "Step 1: Authenticate your account via the ClassroomIO bot.",
|
||||
"button_1": "Open Bot",
|
||||
"step_2": "Step 2: Enter the Chat ID given to you by the bot.",
|
||||
"button_2": "Connect",
|
||||
"step_authenticate": "Step 1: Authenticate your account via the ClassroomIO bot.",
|
||||
"open_bot_button": "Open Bot",
|
||||
"step_chatId": "Step 2: Enter the Chat ID given to you by the bot.",
|
||||
"connect_button": "Connect",
|
||||
"success_message": "Integration Successful",
|
||||
"disconnect": "Disconnect"
|
||||
},
|
||||
@@ -202,6 +202,11 @@
|
||||
},
|
||||
|
||||
"pricing": {
|
||||
"plan_names": {
|
||||
"free": "Free",
|
||||
"early": "Early Adopter",
|
||||
"enterprise": "Enterprise"
|
||||
},
|
||||
"modal": {
|
||||
"heading": "Upgrade Plan",
|
||||
"thanks": "Thank you for your support",
|
||||
@@ -209,96 +214,37 @@
|
||||
"close": "Close",
|
||||
"learn": "Learn more",
|
||||
"month": "month"
|
||||
},
|
||||
"data": {
|
||||
"1": {
|
||||
"name": "Basic",
|
||||
"description": "Free tier plan for personal use, no credit card required.",
|
||||
"price": {
|
||||
"monthly": "0",
|
||||
"yearly": "0"
|
||||
},
|
||||
"features": {
|
||||
"1": "Unlimited Courses",
|
||||
"2": "Unlimited Q/A",
|
||||
"3": "50 Students",
|
||||
"4": "AI Course Builder (no video upload)",
|
||||
"5": "Live chat & polls"
|
||||
},
|
||||
"cta": {
|
||||
"label": "Signup Now",
|
||||
"dashboard_label": "Downgrade"
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"name": "Early Adopters",
|
||||
"description": "For fast growing teaching businesses that aim to scale.",
|
||||
"price": {
|
||||
"monthly": "35",
|
||||
"yearly": "350"
|
||||
},
|
||||
"features": {
|
||||
"1": "Everything in Basic",
|
||||
"2": "Unlimted Teachers",
|
||||
"3": "10K Students",
|
||||
"4": "Advanced AI Course Builder (Video upload & Certificate)",
|
||||
"5": "Custom Branding",
|
||||
"6": "Includes all Upcoming Features"
|
||||
},
|
||||
"cta": {
|
||||
"label": "I want in 😍",
|
||||
"dashboard_label": "Support us 😍"
|
||||
}
|
||||
},
|
||||
"3": {
|
||||
"name": "Enterprise",
|
||||
"description": "Best suited for larger businesses that need more control",
|
||||
"price": {
|
||||
"monthly": "Request Pricing",
|
||||
"yearly": "Request Pricing"
|
||||
},
|
||||
"features": {
|
||||
"1": "Everything in Early Adopters plus:",
|
||||
"2": "Unlimited students",
|
||||
"3": "Custom Domain",
|
||||
"4": "24/7 Support"
|
||||
},
|
||||
"cta": {
|
||||
"label": "Contact Us",
|
||||
"dashboard_label": "Contact Us"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"setup": {
|
||||
"get_started": "Get Started",
|
||||
"1": {
|
||||
"personal_profile": {
|
||||
"title": "Upload a profile picture and update username",
|
||||
"desc": "Personalize and a human touch making interactions more personal and memorable",
|
||||
"button_label": "Update Profile"
|
||||
},
|
||||
"2": {
|
||||
"organization_profile": {
|
||||
"title": "Update organisation profile picture",
|
||||
"desc": "Establish a professional and recognizable identity for your organization",
|
||||
"button_label": "Update Org Profile"
|
||||
},
|
||||
"3": {
|
||||
"course": {
|
||||
"title": "Create Course",
|
||||
"desc": "Create a course that you will share with your students",
|
||||
"button_label": "Create Course"
|
||||
},
|
||||
"4": {
|
||||
"lesson": {
|
||||
"title": "Create a lesson",
|
||||
"desc": "Break your course into lesson that your students can easily understand",
|
||||
"button_label": "Create Lesson"
|
||||
},
|
||||
"5": {
|
||||
"exercise": {
|
||||
"title": "Create an exercise",
|
||||
"desc": "Test your students allow them to demonstarte their understanding of the subject matter",
|
||||
"button_label": "Create Assignment"
|
||||
},
|
||||
"6": {
|
||||
"publish_course": {
|
||||
"title": "Publish a course",
|
||||
"desc": "Make your course public and purchaseable",
|
||||
"button_label": "Publish Course"
|
||||
@@ -328,7 +274,8 @@
|
||||
"signup": "Sign Up",
|
||||
"redirecting": "Redirecting",
|
||||
"loading_state": "Taking you to the next page, please wait.",
|
||||
"org_loading_state": "Taking you to your organization..."
|
||||
"org_loading_state": "Taking you to your organization...",
|
||||
"add_organization": "+ Add Organization"
|
||||
},
|
||||
|
||||
"markdown_editor": {
|
||||
@@ -414,6 +361,16 @@
|
||||
"No_courses_started": "No courses started"
|
||||
},
|
||||
|
||||
"ai": {
|
||||
"help_me": "Help me write",
|
||||
"placeholder": "Help me write a short description",
|
||||
"text": "Start typing...",
|
||||
"reset": "Reset",
|
||||
"rephrase": "Rephrase",
|
||||
"insert": "Insert",
|
||||
"can_you": "Can you please rephrase this"
|
||||
},
|
||||
|
||||
"courses": {
|
||||
"heading": "Courses",
|
||||
"heading_button": "Create Course",
|
||||
@@ -458,15 +415,15 @@
|
||||
|
||||
"course": {
|
||||
"navItems": {
|
||||
"1": "News Feed",
|
||||
"2": "Lessons",
|
||||
"3": "Attendance",
|
||||
"4": "Submissions",
|
||||
"5": "Marks",
|
||||
"6": "People",
|
||||
"7": "Certificates",
|
||||
"8": "Landing Page",
|
||||
"9": "Settings"
|
||||
"nav_news_feed": "News Feed",
|
||||
"nav_lessons": "Lessons",
|
||||
"nav_attendance": "Attendance",
|
||||
"nav_submissions": "Submissions",
|
||||
"nav_marks": "Marks",
|
||||
"nav_people": "People",
|
||||
"nav_certificates": "Certificates",
|
||||
"nav_landing_page": "Landing Page",
|
||||
"nav_settings": "Settings"
|
||||
},
|
||||
|
||||
"navItem": {
|
||||
@@ -571,12 +528,12 @@
|
||||
"select_file": "Select file( Mp4, MOV, AVI) to upload to your lesson.",
|
||||
"size": "(Max 500 MB)",
|
||||
"oops": "Oops `😬, couldn’t upload video",
|
||||
"sorry": "Sorry we video wasn’t uploaded. The file size is too big,",
|
||||
"sorry_2": "maximum size is 30 MB. Try again!",
|
||||
"big_file": "Sorry we video wasn’t uploaded. The file size is too big,",
|
||||
"maximum_size": "maximum size is 30 MB. Try again!",
|
||||
"button": "Try another file",
|
||||
"try_again": "Please try again",
|
||||
"sorry_3": "Sorry we video wasn’t uploaded, the file format isn’t supported or something went wrong on the server.",
|
||||
"sorry_4": "Upload MP4, MOV and AVI files.",
|
||||
"unsupported_format": "Sorry we video wasn’t uploaded, the file format isn’t supported or something went wrong on the server.",
|
||||
"format": "Upload MP4, MOV and AVI files.",
|
||||
"upgrade": "Upgrade your plan to upload vidoes",
|
||||
"uploading": "Uploading...",
|
||||
"invalid_youtube": "Invalid YouTube link(s)",
|
||||
@@ -597,12 +554,12 @@
|
||||
"new_exercise_modal": {
|
||||
"heading": "New Exercise",
|
||||
"options": {
|
||||
"1": "From Scratch",
|
||||
"subtitle_1": "Create your exercise from scratch if you have your questions already prepared",
|
||||
"2": "Use a Template",
|
||||
"subtitle_2": "Select from 100+ templates of predefined exercise to help you get started",
|
||||
"3": "Use AI",
|
||||
"subtitle_3": "You can generate an exercise with AI from your notes"
|
||||
"from_scratch": "From Scratch",
|
||||
"from_scratch_subtitle": "Create your exercise from scratch if you have your questions already prepared",
|
||||
"use_template": "Use a Template",
|
||||
"use_template_subtitle": "Select from 100+ templates of predefined exercise to help you get started",
|
||||
"use_ai": "Use AI",
|
||||
"use_ai_subtitle": "You can generate an exercise with AI from your notes"
|
||||
},
|
||||
"how": "How do you want to create your exercise",
|
||||
"coming_soon": "Coming soon",
|
||||
@@ -756,9 +713,9 @@
|
||||
"submissions": {
|
||||
"title": "Submitted Exercises",
|
||||
"submission_status": {
|
||||
"1": "Submitted",
|
||||
"2": "In Progress",
|
||||
"3": "Graded"
|
||||
"submitted": "Submitted",
|
||||
"in_progress": "In Progress",
|
||||
"graded": "Graded"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -822,21 +779,21 @@
|
||||
"save": "Save Changes",
|
||||
"unlocked_certificate": "Certificate is now available",
|
||||
"locked_certificate": "Certificates not available",
|
||||
"locked_certificate_body_1": "Your instructor needs to unlock your certificate.",
|
||||
"locked_certificate_body_2": "If you need your certificate, please contact your instructor.",
|
||||
"instructor_unlock": "Your instructor needs to unlock your certificate.",
|
||||
"contact_instructor": "If you need your certificate, please contact your instructor.",
|
||||
"download_certificate": "DownLoad Certificate"
|
||||
},
|
||||
|
||||
"landing_page": {
|
||||
"editor": {
|
||||
"title": {
|
||||
"1": "Header",
|
||||
"2": "Requirement",
|
||||
"3": "Description",
|
||||
"4": "Goals",
|
||||
"5": "Reviews",
|
||||
"6": "Instructor",
|
||||
"7": "Pricing"
|
||||
"header": "Header",
|
||||
"requirement": "Requirement",
|
||||
"description": "Description",
|
||||
"goals": "Goals",
|
||||
"reviews": "Reviews",
|
||||
"instructor": "Instructor",
|
||||
"pricing": "Pricing"
|
||||
},
|
||||
|
||||
"save": "Save",
|
||||
@@ -848,7 +805,8 @@
|
||||
"description": "Description",
|
||||
"short_video": "Short Video",
|
||||
"replace_cover": "Replace cover image",
|
||||
"replace": "Replace"
|
||||
"replace": "Replace",
|
||||
"helper": "Enter a link to a youtube video"
|
||||
},
|
||||
|
||||
"reviews_form": {
|
||||
@@ -1013,7 +971,17 @@
|
||||
"manage": "Manage all your students here and stay connected with them",
|
||||
"name": "Name",
|
||||
"email": "Email",
|
||||
"date_joined": "Date Joined"
|
||||
"date_joined": "Date Joined",
|
||||
"upgrade": "Upgrade your plan to invite more students"
|
||||
},
|
||||
|
||||
"upgrade": {
|
||||
"certificate": "Upgrade your plan to generate certificates",
|
||||
"team": "Upgrade your plan to add team members",
|
||||
"team_members": "Team members",
|
||||
"back": "Back to Settings",
|
||||
"download_lessons": "Upgrade to download lessons",
|
||||
"download_course": "Upgrade to download course"
|
||||
},
|
||||
|
||||
"lms_navigation": {
|
||||
@@ -1069,7 +1037,9 @@
|
||||
},
|
||||
|
||||
"materials": {
|
||||
"apology": "We apologise, there was an error saving your lesson."
|
||||
"apology": "We apologise, there was an error saving your lesson.",
|
||||
"update_translations": "Updating translations failed",
|
||||
"creating_new": "Creating new translations failed"
|
||||
},
|
||||
|
||||
"newsfeed": {
|
||||
@@ -1218,16 +1188,6 @@
|
||||
|
||||
"content": {
|
||||
"heading": "Internationalization in SvelteKit",
|
||||
"toggle_label": "Select Preferred Language",
|
||||
"button_labels": {
|
||||
"0": "{{value:number}}",
|
||||
"1": "{{value:number}}",
|
||||
"2": "{{value:number}}"
|
||||
},
|
||||
"body_text": "This is a small example to demonstrate i18n functionality in SvelteKit using sveltekit-i18n library. sveltekit-i18n is a tiny library with no external dependencies, built for Svelte and SvelteKit. It glues @sveltekit-i18n/base and @sveltekit-i18n/parser-default together to provide you the most straightforward sveltekit-i18n solution. Total number of npm downloads per week as of {{dateValue:date}} are {{download:number}}.",
|
||||
"awards": "You have {{award:gt; 0: {{award; 1:won exactly {{award}} award; default:won {{award}} awards}}; default:not won any awards}}!",
|
||||
"date": "{{val:date}}",
|
||||
"time": "Only 'time' formatter is not available, it must be DateTime formatter",
|
||||
"number": "{{value:currency}}"
|
||||
"toggle_label": "Select Preferred Language"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -63,27 +63,27 @@
|
||||
let openExercise = false;
|
||||
|
||||
const submissionStatus: { [key: number]: string } = {
|
||||
1: $t('course.navItem.submissions.submission_status.1'),
|
||||
2: $t('course.navItem.submissions.submission_status.2'),
|
||||
3: $t('course.navItem.submissions.submission_status.3')
|
||||
1: $t('course.navItem.submissions.submission_status.submitted'),
|
||||
2: $t('course.navItem.submissions.submission_status.in_progress'),
|
||||
3: $t('course.navItem.submissions.submission_status.graded')
|
||||
};
|
||||
|
||||
let sections: sectionType[] = [
|
||||
{
|
||||
id: 1,
|
||||
title: $t('course.navItem.submissions.submission_status.1'),
|
||||
title: $t('course.navItem.submissions.submission_status.submitted'),
|
||||
value: 0,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: $t('course.navItem.submissions.submission_status.2'),
|
||||
title: $t('course.navItem.submissions.submission_status.in_progress'),
|
||||
value: 0,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: $t('course.navItem.submissions.submission_status.3'),
|
||||
title: $t('course.navItem.submissions.submission_status.graded'),
|
||||
value: 10,
|
||||
items: []
|
||||
}
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
$: tabs = [
|
||||
{
|
||||
key: 0,
|
||||
label: $t('settings.tabs.1'),
|
||||
label: $t('settings.tabs.profile_tab'),
|
||||
tabKey: '',
|
||||
href: $page.url.pathname
|
||||
},
|
||||
{
|
||||
key: 1,
|
||||
label: $t('settings.tabs.5'),
|
||||
label: $t('settings.tabs.integrations_tab'),
|
||||
tabKey: 'integrations',
|
||||
href: `${$page.url.pathname}?tab=integrations`,
|
||||
disabled: false
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</div>
|
||||
|
||||
{#if $orgAudience.length >= $currentOrgMaxAudience}
|
||||
<UpgradeBanner>Upgrade your plan to invite more students</UpgradeBanner>
|
||||
<UpgradeBanner>{$t('audience.upgrade')}</UpgradeBanner>
|
||||
{/if}
|
||||
<Audience />
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import TeamMembers from '$lib/components/Org/Settings/TeamMembers.svelte';
|
||||
import { currentOrgPath } from '$lib/utils/store/org';
|
||||
import UpgradeBanner from '$lib/components/Upgrade/Banner.svelte';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -11,13 +12,13 @@
|
||||
<section class="w-full md:max-w-4xl mx-auto">
|
||||
<div class="py-10 px-3 md:px-5">
|
||||
<a class="text-gray-500 dark:text-white text-md" href={`${$currentOrgPath}/settings?tab=org`}
|
||||
>Back to Settings</a
|
||||
>{$t('upgrade.back')}</a
|
||||
>
|
||||
<div class="flex items-center justify-between mb-10">
|
||||
<h1 class="dark:text-white text-3xl font-bold">Team members</h1>
|
||||
<h1 class="dark:text-white text-3xl font-bold">{$t('upgrade.team_members')}</h1>
|
||||
</div>
|
||||
|
||||
<UpgradeBanner>Upgrade your plan to add team members</UpgradeBanner>
|
||||
<UpgradeBanner>{$t('upgrade.team')}</UpgradeBanner>
|
||||
<TeamMembers />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -95,45 +95,45 @@ export const load = async ({ params = { slug: '' } }) => {
|
||||
const data = [
|
||||
{
|
||||
id: 'profile',
|
||||
title: 'setup.1.title',
|
||||
desc: 'setup.1.desc',
|
||||
title: 'setup.personal_profile.title',
|
||||
desc: 'setup.personal_profile.desc',
|
||||
is_completed: false,
|
||||
button_label: 'setup.1.button_label'
|
||||
button_label: 'setup.personal_profile.button_label'
|
||||
},
|
||||
{
|
||||
id: 'organization',
|
||||
title: 'setup.2.title',
|
||||
desc: 'setup.2.desc',
|
||||
title: 'setup.organization_profile.title',
|
||||
desc: 'setup.organization_profile.desc',
|
||||
is_completed: orgHasAvatarUrl,
|
||||
button_label: 'setup.2.button_label'
|
||||
button_label: 'setup.organization_profile.button_label'
|
||||
},
|
||||
{
|
||||
id: 'course',
|
||||
title: 'setup.3.title',
|
||||
desc: 'setup.4.desc',
|
||||
title: 'setup.course.title',
|
||||
desc: 'setup.course.desc',
|
||||
is_completed: isCourseCreated,
|
||||
button_label: 'setup.3.button_label'
|
||||
button_label: 'setup.course.button_label'
|
||||
},
|
||||
{
|
||||
id: 'lesson',
|
||||
title: 'setup.4.title',
|
||||
desc: 'setup.4.desc',
|
||||
title: 'setup.lesson.title',
|
||||
desc: 'setup.lesson.desc',
|
||||
is_completed: isLessonCreated,
|
||||
button_label: 'setup.4.button_label'
|
||||
button_label: 'setup.lesson.button_label'
|
||||
},
|
||||
{
|
||||
id: 'exercise',
|
||||
title: 'setup.5.title',
|
||||
desc: 'setup.5.desc',
|
||||
title: 'setup.exercise.title',
|
||||
desc: 'setup.exercise.desc',
|
||||
is_completed: isExerciseCreated,
|
||||
button_label: 'setup.5.button_label'
|
||||
button_label: 'setup.exercise.button_label'
|
||||
},
|
||||
{
|
||||
id: 'publish',
|
||||
title: 'setup.6.title',
|
||||
desc: 'setup.6.desc',
|
||||
title: 'setup.publish_course.title',
|
||||
desc: 'setup.publish_course.desc',
|
||||
is_completed: isCoursePublished,
|
||||
button_label: 'setup.6.button_label'
|
||||
button_label: 'setup.publish_course.button_label'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# Adding Translation To Your Code - Developer's Guide
|
||||
|
||||
In this guide, we'll walk through the process of adding translations to your code. This enables multi-translation support on the platform, enhancing the experience for every users.
|
||||
|
||||
## Obtain Your RapidAPI Key
|
||||
|
||||
Follow these steps:
|
||||
|
||||
1. Open your browser and navigate to https://rapidapi.com/hub.
|
||||
2. Sign up using your GitHub account or email, whichever you prefer.
|
||||
3. Search for 'Google Translate' then click on the 'Pricing' tab.
|
||||
4. Choose a subscription plan and return to the 'Endpoints' tab.
|
||||
5. Focus on the last tab (on your right).
|
||||
6. Your key is located in the 'headers' object under 'X-RapidAPI-Key'.
|
||||
7. Go to your `.env` file in the `/apps/dashboard` directory and assign your key to this variable `RAPID_API_KEY`
|
||||
|
||||
## Update Your English File
|
||||
|
||||
Once you have your API Key, follow these steps to add a translation:
|
||||
|
||||
1. Open the English file named `en` located in `apps\dashboard\src\lib\utils\translations\en.json`.
|
||||
2. Create an object with a name corresponding to the translation you wish to add.
|
||||
Example: `"tabs": { "profile": "Profile", "landing_page": "Landing Page" }`.
|
||||
3. Now, navigate to the file where you want to insert the translation.
|
||||
4. Import the translation function:
|
||||
|
||||
````bash copy
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
````
|
||||
|
||||
5. Locate the line where you want to add the translation and use the following syntax: `$t('path to the value in the object')`.
|
||||
Example: `<p>{$t('tabs.profile')}</p>` (This will output "Profile").
|
||||
Note: `$t('')` returns a string.
|
||||
|
||||
## Run the translate script
|
||||
|
||||
Once you've updated the English file, you need to update the other files. To do this, run a command. Firstly ensure you're still in the `/apps/dashboard` directory, then execute:
|
||||
|
||||
````bash copy
|
||||
pnpm run script:translate
|
||||
````
|
||||
|
||||
This command runs a script that updates the other translation files.
|
||||
|
||||
Reference in New Issue
Block a user