i18n: add missing __() calls to complete French translation
This commit is contained in:
@@ -157,7 +157,7 @@
|
||||
v-model="showHelpModal"
|
||||
v-model:articles="articles"
|
||||
appName="learning"
|
||||
title="Frappe Learning"
|
||||
:title="__('Frappe Learning')"
|
||||
:logo="LMSLogo"
|
||||
:afterSkip="(step) => capture('onboarding_step_skipped_' + step)"
|
||||
:afterSkipAll="() => capture('onboarding_steps_skipped')"
|
||||
@@ -303,7 +303,7 @@ const unreadNotifications = createResource({
|
||||
const addNotifications = () => {
|
||||
if (user) {
|
||||
sidebarLinks.value.push({
|
||||
label: 'Notifications',
|
||||
label: __('Notifications'),
|
||||
icon: 'Bell',
|
||||
to: 'Notifications',
|
||||
activeFor: ['Notifications'],
|
||||
@@ -315,7 +315,7 @@ const addNotifications = () => {
|
||||
const addQuizzes = () => {
|
||||
if (isInstructor.value || isModerator.value) {
|
||||
sidebarLinks.value.splice(4, 0, {
|
||||
label: 'Quizzes',
|
||||
label: __('Quizzes'),
|
||||
icon: 'CircleHelp',
|
||||
to: 'Quizzes',
|
||||
activeFor: [
|
||||
@@ -331,7 +331,7 @@ const addQuizzes = () => {
|
||||
const addAssignments = () => {
|
||||
if (isInstructor.value || isModerator.value) {
|
||||
sidebarLinks.value.splice(5, 0, {
|
||||
label: 'Assignments',
|
||||
label: __('Assignments'),
|
||||
icon: 'Pencil',
|
||||
to: 'Assignments',
|
||||
activeFor: [
|
||||
@@ -347,7 +347,7 @@ const addAssignments = () => {
|
||||
const addProgrammingExercises = () => {
|
||||
if (isInstructor.value || isModerator.value) {
|
||||
sidebarLinks.value.splice(3, 0, {
|
||||
label: 'Programming Exercises',
|
||||
label: __('Programming Exercises'),
|
||||
icon: 'Code',
|
||||
to: 'ProgrammingExercises',
|
||||
activeFor: [
|
||||
@@ -383,7 +383,7 @@ const addPrograms = () => {
|
||||
|
||||
if (canAddProgram) {
|
||||
sidebarLinks.value.splice(index, 0, {
|
||||
label: 'Programs',
|
||||
label: __('Programs'),
|
||||
icon: 'Route',
|
||||
to: 'Programs',
|
||||
activeFor: activeFor,
|
||||
|
||||
@@ -102,7 +102,7 @@ const props = defineProps({
|
||||
},
|
||||
emptyStateText: {
|
||||
type: String,
|
||||
default: 'Start a discussion',
|
||||
default: __('Start a discussion'),
|
||||
},
|
||||
singleThread: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<div class="flex flex-col items-center justify-center mt-60">
|
||||
<GraduationCap class="size-10 mx-auto stroke-1 text-ink-gray-5" />
|
||||
<div class="text-lg font-semibold text-ink-gray-7 mb-2.5">
|
||||
|
||||
{{ __('No {0}').format(props.type) }}
|
||||
</div>
|
||||
<div
|
||||
|
||||
70
frontend/src/overrides/Onboarding/GettingStartedBanner.vue
Normal file
70
frontend/src/overrides/Onboarding/GettingStartedBanner.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="!isSidebarCollapsed"
|
||||
class="flex flex-col gap-3 shadow-sm rounded-lg py-2.5 px-3 bg-surface-modal text-base"
|
||||
>
|
||||
<div v-if="stepsCompleted != totalSteps" class="inline-flex text-ink-gray-9 gap-2">
|
||||
<StepsIcon class="h-4 my-0.5 shrink-0" />
|
||||
<div class="flex flex-col text-p-sm gap-0.5">
|
||||
<div class="font-medium">
|
||||
{{ __('Getting started') }}
|
||||
</div>
|
||||
<div class="text-ink-gray-7">
|
||||
{{ __('{0}/{1} steps').format(stepsCompleted, totalSteps) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex flex-col gap-1">
|
||||
<div class="flex items-center justify-between gap-1">
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
<StepsIcon class="h-4 my-0.5" />
|
||||
<div class="text-ink-gray-9 font-medium">
|
||||
{{ __('You are all set') }}
|
||||
</div>
|
||||
</div>
|
||||
<FeatherIcon
|
||||
name="x"
|
||||
class="h-4 cursor-pointer"
|
||||
@click="() => { showHelpCenter = true; isOnboardingStepsCompleted = true }"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-p-sm text-ink-gray-7">
|
||||
{{ __('All steps are completed successfully') }}
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
v-if="stepsCompleted != totalSteps"
|
||||
:label="stepsCompleted == 0 ? __('Start now') : __('Continue')"
|
||||
theme="blue"
|
||||
@click="openOnboarding"
|
||||
>
|
||||
<template #prefix>
|
||||
<FeatherIcon name="chevrons-right" class="size-4" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
<Button v-else-if="stepsCompleted != totalSteps" @click="openOnboarding">
|
||||
<StepsIcon class="h-4 my-0.5 shrink-0" />
|
||||
</Button>
|
||||
</template>
|
||||
<script setup>
|
||||
import StepsIcon from 'frappe-ui/frappe/Icons/StepsIcon.vue'
|
||||
import Button from 'frappe-ui/src/components/Button/Button.vue'
|
||||
import FeatherIcon from 'frappe-ui/src/components/FeatherIcon.vue'
|
||||
import { useOnboarding } from 'frappe-ui/frappe/Onboarding/onboarding'
|
||||
import { showHelpCenter } from 'frappe-ui/frappe/HelpCenter/helpCenter'
|
||||
import { showHelpModal, minimize } from 'frappe-ui/frappe/Help/help'
|
||||
|
||||
const props = defineProps({
|
||||
isSidebarCollapsed: { type: Boolean, default: false },
|
||||
appName: { type: String, default: 'frappecrm' },
|
||||
})
|
||||
|
||||
const { stepsCompleted, totalSteps, isOnboardingStepsCompleted } = useOnboarding(props.appName)
|
||||
|
||||
const openOnboarding = () => {
|
||||
minimize.value = false
|
||||
showHelpModal.value = true
|
||||
}
|
||||
</script>
|
||||
|
||||
112
frontend/src/overrides/Onboarding/OnboardingSteps.vue
Normal file
112
frontend/src/overrides/Onboarding/OnboardingSteps.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<div class="flex flex-col justify-center items-center gap-1 mt-4 mb-7">
|
||||
<component :is="logo" class="size-10 shrink-0 rounded mb-4" />
|
||||
<div class="text-base font-medium">
|
||||
{{ __('Welcome to {0}').format(title) }}
|
||||
</div>
|
||||
<div class="text-p-base font-normal">
|
||||
{{ __('{0}/{1} steps completed').format(stepsCompleted, totalSteps) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2.5 overflow-hidden">
|
||||
<div class="flex justify-between items-center py-0.5">
|
||||
<Badge
|
||||
:label="__('{0}% completed').format(completedPercentage)"
|
||||
:theme="completedPercentage == 100 ? 'green' : 'orange'"
|
||||
size="lg"
|
||||
/>
|
||||
<div class="flex">
|
||||
<Button
|
||||
v-if="completedPercentage != 0"
|
||||
variant="ghost"
|
||||
:label="__('Reset all')"
|
||||
@click="() => resetAll(afterResetAll)"
|
||||
/>
|
||||
<Button
|
||||
v-if="completedPercentage != 100"
|
||||
variant="ghost"
|
||||
:label="__('Skip all')"
|
||||
@click="() => skipAll(afterSkipAll)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5 overflow-y-auto">
|
||||
<div
|
||||
v-for="step in steps"
|
||||
:key="step.title"
|
||||
class="group w-full flex gap-2 justify-between items-center hover:bg-surface-gray-1 rounded px-2 py-1.5 cursor-pointer"
|
||||
@click.stop="() => !step.completed && !isDependent(step) && step.onClick()"
|
||||
>
|
||||
<component :is="isDependent(step) ? Tooltip : 'div'" :text="dependsOnTooltip(step)">
|
||||
<div
|
||||
class="flex gap-2 items-center"
|
||||
:class="[
|
||||
step.completed
|
||||
? 'text-ink-gray-5'
|
||||
: isDependent(step)
|
||||
? 'text-ink-gray-4'
|
||||
: 'text-ink-gray-8',
|
||||
]"
|
||||
>
|
||||
<component :is="step.icon" class="h-4" />
|
||||
<div class="text-base" :class="{ 'line-through': step.completed }">
|
||||
{{ step.title }}
|
||||
</div>
|
||||
</div>
|
||||
</component>
|
||||
<Button
|
||||
v-if="!step.completed && !isDependent(step)"
|
||||
:label="__('Skip')"
|
||||
class="!h-4 text-xs !text-ink-gray-6 hidden group-hover:flex"
|
||||
@click="() => skip(step.name, afterSkip)"
|
||||
/>
|
||||
<Button
|
||||
v-else-if="!isDependent(step)"
|
||||
:label="__('Reset')"
|
||||
class="!h-4 text-xs !text-ink-gray-6 hidden group-hover:flex"
|
||||
@click.stop="() => reset(step.name, afterReset)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useOnboarding } from 'frappe-ui/frappe/Onboarding/onboarding'
|
||||
import Tooltip from 'frappe-ui/src/components/Tooltip/Tooltip.vue'
|
||||
import Button from 'frappe-ui/src/components/Button/Button.vue'
|
||||
import Badge from 'frappe-ui/src/components/Badge/Badge.vue'
|
||||
|
||||
const props = defineProps({
|
||||
appName: { type: String, default: 'frappecrm' },
|
||||
title: { type: String, default: 'Frappe CRM' },
|
||||
logo: { type: Object, required: true },
|
||||
afterSkip: { type: Function, default: () => {} },
|
||||
afterSkipAll: { type: Function, default: () => {} },
|
||||
afterReset: { type: Function, default: () => {} },
|
||||
afterResetAll: { type: Function, default: () => {} },
|
||||
})
|
||||
|
||||
function isDependent(step) {
|
||||
if (step.dependsOn && !step.completed) {
|
||||
const dependsOnStep = steps.find((s) => s.name === step.dependsOn)
|
||||
if (dependsOnStep && !dependsOnStep.completed) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function dependsOnTooltip(step) {
|
||||
if (step.dependsOn && !step.completed) {
|
||||
const dependsOnStep = steps.find((s) => s.name === step.dependsOn)
|
||||
if (dependsOnStep && !dependsOnStep.completed) {
|
||||
return `You need to complete "${dependsOnStep.title}" first.`
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const { steps, stepsCompleted, totalSteps, completedPercentage, skip, skipAll, reset, resetAll } =
|
||||
useOnboarding(props.appName)
|
||||
</script>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
}"
|
||||
>
|
||||
</ListView>
|
||||
<EmptyState v-else type="Assignments" />
|
||||
<EmptyState v-else :type="__('Assignments').toLowerCase()" />
|
||||
<div
|
||||
v-if="assignments.data && assignments.hasNextPage"
|
||||
class="flex justify-center my-5"
|
||||
@@ -198,7 +198,7 @@ const assignmentTypes = computed(() => {
|
||||
|
||||
const breadcrumbs = computed(() => [
|
||||
{
|
||||
label: 'Assignments',
|
||||
label: __('Assignments'),
|
||||
route: { name: 'Assignments' },
|
||||
},
|
||||
])
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<BatchCard :batch="batch" />
|
||||
</router-link>
|
||||
</div>
|
||||
<EmptyState v-else-if="!batches.list.loading" type="Batches" />
|
||||
<EmptyState v-else-if="!batches.list.loading" :type="__('Batches').toLowerCase()" />
|
||||
|
||||
<div
|
||||
v-if="!batches.list.loading && batches.hasNextPage"
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<EmptyState v-else type="Job Openings" />
|
||||
<EmptyState v-else :type="__('Job Openings').toLowerCase()" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
<div class="mt-20" ref="discussionsContainer">
|
||||
<Discussions
|
||||
v-if="allowDiscussions"
|
||||
:title="'Questions'"
|
||||
:title="__('Questions')"
|
||||
:doctype="'Course Lesson'"
|
||||
:docname="lesson.data.name"
|
||||
:key="lesson.data.name"
|
||||
|
||||
@@ -144,7 +144,7 @@ onUnmounted(() => {
|
||||
const breadcrumbs = computed(() => {
|
||||
let crumbs = [
|
||||
{
|
||||
label: 'Notifications',
|
||||
label: __('Notifications'),
|
||||
route: {
|
||||
name: 'Notifications',
|
||||
},
|
||||
@@ -155,7 +155,7 @@ const breadcrumbs = computed(() => {
|
||||
|
||||
usePageMeta(() => {
|
||||
return {
|
||||
title: 'Notifications',
|
||||
title: __('Notifications'),
|
||||
icon: brand.favicon,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -323,12 +323,12 @@ const saveProgram = () => {
|
||||
const courseColumns = computed(() => {
|
||||
return [
|
||||
{
|
||||
label: 'Title',
|
||||
label: __('Title'),
|
||||
key: 'course_title',
|
||||
width: 3,
|
||||
},
|
||||
{
|
||||
label: 'ID',
|
||||
label: __('ID'),
|
||||
key: 'course',
|
||||
width: 3,
|
||||
},
|
||||
@@ -338,19 +338,19 @@ const courseColumns = computed(() => {
|
||||
const memberColumns = computed(() => {
|
||||
return [
|
||||
{
|
||||
label: 'Member',
|
||||
label: __('Member'),
|
||||
key: 'member',
|
||||
width: 3,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: 'Full Name',
|
||||
label: __('Full Name'),
|
||||
key: 'full_name',
|
||||
width: 3,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: 'Progress (%)',
|
||||
label: __('Progress (%)'),
|
||||
key: 'progress',
|
||||
width: 3,
|
||||
align: 'right',
|
||||
@@ -361,11 +361,11 @@ const memberColumns = computed(() => {
|
||||
const breadbrumbs = computed(() => {
|
||||
return [
|
||||
{
|
||||
label: 'Programs',
|
||||
label: __('Programs'),
|
||||
route: { name: 'Programs' },
|
||||
},
|
||||
{
|
||||
label: props.programName === 'new' ? 'New Program' : props.programName,
|
||||
label: props.programName === 'new' ? __('New Program') : props.programName,
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<EmptyState v-else type="Programs" />
|
||||
<EmptyState v-else :type="__('Programs').toLowerCase()" />
|
||||
|
||||
<Dialog
|
||||
v-model="showDialog"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
: __('No Quizzes')
|
||||
}}
|
||||
</div>
|
||||
<FormControl v-model="search" type="text" placeholder="Search">
|
||||
<FormControl v-model="search" type="text" :placeholder="__('Search')">
|
||||
<template #prefix>
|
||||
<FeatherIcon name="search" class="size-4 text-ink-gray-5" />
|
||||
</template>
|
||||
@@ -88,7 +88,7 @@
|
||||
</template>
|
||||
</ListSelectBanner>
|
||||
</ListView>
|
||||
<EmptyState v-else type="Quizzes" />
|
||||
<EmptyState v-else :type="__('Quizzes').toLowerCase()" />
|
||||
<div v-if="quizzes.hasNextPage" class="flex justify-center my-5">
|
||||
<Button @click="quizzes.next()">
|
||||
{{ __('Load More') }}
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
<Tooltip :text="__('Active Members')">
|
||||
<NumberChart
|
||||
class="border rounded-md"
|
||||
:config="{ title: 'Signups', value: chartDetails.data.users }"
|
||||
:config="{ title: __('Signups'), value: chartDetails.data.users }"
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip :text="__('Course Enrollments')">
|
||||
<NumberChart
|
||||
class="border rounded-md"
|
||||
:config="{
|
||||
title: 'Enrollments',
|
||||
title: __('Enrollments'),
|
||||
value: chartDetails.data.enrollments,
|
||||
}"
|
||||
/>
|
||||
@@ -122,7 +122,7 @@
|
||||
:config="{
|
||||
data: courseCompletion.data,
|
||||
title: __('Completions'),
|
||||
subtitle: 'Course Completion',
|
||||
subtitle: __('Course Completion'),
|
||||
categoryColumn: 'label',
|
||||
valueColumn: 'value',
|
||||
}"
|
||||
|
||||
Reference in New Issue
Block a user