diff --git a/web/app/components/base/icons/assets/public/education/triangle.svg b/web/app/components/base/icons/assets/public/education/triangle.svg new file mode 100644 index 0000000000..e52c5c5a43 --- /dev/null +++ b/web/app/components/base/icons/assets/public/education/triangle.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/app/components/base/icons/assets/vender/workflow/loop.svg b/web/app/components/base/icons/assets/vender/workflow/loop.svg new file mode 100644 index 0000000000..6692c4dace --- /dev/null +++ b/web/app/components/base/icons/assets/vender/workflow/loop.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/web/app/components/base/icons/src/public/education/Triangle.json b/web/app/components/base/icons/src/public/education/Triangle.json new file mode 100644 index 0000000000..92d7c82c43 --- /dev/null +++ b/web/app/components/base/icons/src/public/education/Triangle.json @@ -0,0 +1,27 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "16", + "height": "22", + "viewBox": "0 0 16 22", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Rectangle 979", + "d": "M0 0H16L9.91493 16.7339C8.76529 19.8955 5.76063 22 2.39658 22H0V0Z", + "fill": "white" + }, + "children": [] + } + ] + }, + "name": "Triangle" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/workflow/LoopStart.tsx b/web/app/components/base/icons/src/public/education/Triangle.tsx similarity index 86% rename from web/app/components/base/icons/src/vender/workflow/LoopStart.tsx rename to web/app/components/base/icons/src/public/education/Triangle.tsx index 0c93cfe8b0..34f2a50666 100644 --- a/web/app/components/base/icons/src/vender/workflow/LoopStart.tsx +++ b/web/app/components/base/icons/src/public/education/Triangle.tsx @@ -2,7 +2,7 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import data from './LoopStart.json' +import data from './Triangle.json' import IconBase from '@/app/components/base/icons/IconBase' import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' @@ -11,6 +11,6 @@ const Icon = React.forwardRef, Omit ) -Icon.displayName = 'LoopStart' +Icon.displayName = 'Triangle' export default Icon diff --git a/web/app/components/base/icons/src/public/education/index.ts b/web/app/components/base/icons/src/public/education/index.ts new file mode 100644 index 0000000000..de505dbbdc --- /dev/null +++ b/web/app/components/base/icons/src/public/education/index.ts @@ -0,0 +1 @@ +export { default as Triangle } from './Triangle' diff --git a/web/app/components/base/icons/src/vender/workflow/Loop.json b/web/app/components/base/icons/src/vender/workflow/Loop.json index 5d1e6f8dc9..65a70d82a1 100644 --- a/web/app/components/base/icons/src/vender/workflow/Loop.json +++ b/web/app/components/base/icons/src/vender/workflow/Loop.json @@ -4,9 +4,9 @@ "isRootNode": true, "name": "svg", "attributes": { - "width": "40", - "height": "40", - "viewBox": "0 0 40 40", + "width": "18", + "height": "16", + "viewBox": "0 0 18 16", "fill": "none", "xmlns": "http://www.w3.org/2000/svg" }, @@ -15,46 +15,18 @@ "type": "element", "name": "g", "attributes": { - "filter": "url(#filter0_dd_10886_10012)", - "style": "transform: scale(2.5) translate(-12px, -8px)" + "id": "loop" }, "children": [ - { - "type": "element", - "name": "rect", - "attributes": { - "x": "8", - "y": "5", - "width": "24", - "height": "24", - "rx": "8", - "fill": "#06AED4" - }, - "children": [] - }, - { - "type": "element", - "name": "rect", - "attributes": { - "x": "8.25", - "y": "5.25", - "width": "23.5", - "height": "23.5", - "rx": "7.75", - "stroke": "#101828", - "stroke-opacity": "0.04", - "stroke-width": "0.5" - }, - "children": [] - }, { "type": "element", "name": "path", "attributes": { + "id": "Vector", "fill-rule": "evenodd", "clip-rule": "evenodd", - "d": "M13.0293 14.3451C14.5076 12.885 16.9007 12.885 18.3791 14.3451L19.9999 15.9459L21.6208 14.3451C23.0992 12.885 25.4922 12.885 26.9706 14.3451C28.4541 15.8103 28.4541 18.1897 26.9707 19.6549C25.4923 21.115 23.0992 21.115 21.6208 19.655L19.9999 18.0541L18.3791 19.655C16.9007 21.115 14.5076 21.115 13.0293 19.655C11.5457 18.1897 11.5457 15.8103 13.0293 14.3451ZM18.9326 17L17.325 15.4123C16.4309 14.5292 14.9774 14.5292 14.0833 15.4123C13.1944 16.2903 13.1944 17.7097 14.0833 18.5877C14.9774 19.4708 16.4309 19.4707 17.325 18.5877C17.325 18.5877 17.325 18.5877 17.325 18.5877L18.9326 17ZM21.0673 17L22.6748 18.5877C22.6748 18.5877 22.6748 18.5877 22.6748 18.5877C23.569 19.4707 25.0224 19.4707 25.9166 18.5877C26.8055 17.7098 26.8055 16.2902 25.9166 15.4123C25.0224 14.5292 23.569 14.5292 22.6748 15.4123C22.6748 15.4123 22.6748 15.4123 22.6748 15.4123L21.0673 17Z", - "fill": "white" + "d": "M2.02915 5.34506C3.50752 3.88498 5.9006 3.88498 7.37896 5.34506L8.99983 6.94588L10.6207 5.34506C12.0991 3.88499 14.4921 3.88498 15.9705 5.34506C17.454 6.81027 17.454 9.18971 15.9705 10.6549C14.4921 12.115 12.0991 12.115 10.6207 10.655L8.99983 9.05413L7.37896 10.655C5.9006 12.115 3.50753 12.115 2.02916 10.655C0.545627 9.18974 0.545611 6.81028 2.02915 5.34506ZM7.93251 8L6.32492 6.4123C5.4308 5.52924 3.97732 5.52923 3.08319 6.4123C2.19426 7.29026 2.19426 8.70975 3.0832 9.58772C3.97733 10.4708 5.4308 10.4707 6.32492 9.58771C6.32492 9.58772 6.32492 9.58771 6.32492 9.58771L7.93251 8ZM10.0671 8L11.6747 9.5877C11.6747 9.58769 11.6747 9.58771 11.6747 9.5877C12.5688 10.4707 14.0223 10.4707 14.9165 9.58773C15.8054 8.70975 15.8054 7.29024 14.9165 6.41229C14.0223 5.52923 12.5689 5.52924 11.6747 6.4123C11.6747 6.4123 11.6747 6.41229 11.6747 6.4123L10.0671 8Z", + "fill": "currentColor" }, "children": [] } @@ -63,4 +35,4 @@ ] }, "name": "Loop" -} +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/workflow/LoopStart.json b/web/app/components/base/icons/src/vender/workflow/LoopStart.json deleted file mode 100644 index 362d54b3db..0000000000 --- a/web/app/components/base/icons/src/vender/workflow/LoopStart.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "icon": { - "type": "element", - "isRootNode": true, - "name": "svg", - "attributes": { - "width": "12", - "height": "12", - "viewBox": "0 0 12 12", - "fill": "none", - "xmlns": "http://www.w3.org/2000/svg" - }, - "children": [ - { - "type": "element", - "name": "g", - "attributes": { - "id": "icons/block-start" - }, - "children": [ - { - "type": "element", - "name": "path", - "attributes": { - "id": "Vector", - "d": "M6.8498 1.72732C6.3379 1.3754 5.6621 1.3754 5.1502 1.72732L2.1502 3.78982C1.74317 4.06965 1.5 4.53193 1.5 5.02588V8.99983C1.5 9.82828 2.17158 10.4998 3 10.4998H4.25C4.52614 10.4998 4.75 10.276 4.75 9.99983V8.24983C4.75 7.55948 5.30965 6.99983 6 6.99983C6.69035 6.99983 7.25 7.55948 7.25 8.24983V9.99983C7.25 10.276 7.47385 10.4998 7.75 10.4998H9C9.82845 10.4998 10.5 9.82828 10.5 8.99983V5.02588C10.5 4.53193 10.2568 4.06965 9.8498 3.78982L6.8498 1.72732Z", - "fill": "red" - }, - "children": [] - } - ] - } - ] - }, - "name": "LoopStart" -} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/workflow/index.ts b/web/app/components/base/icons/src/vender/workflow/index.ts index f63d3158ea..284be92712 100644 --- a/web/app/components/base/icons/src/vender/workflow/index.ts +++ b/web/app/components/base/icons/src/vender/workflow/index.ts @@ -9,12 +9,11 @@ export { default as Http } from './Http' export { default as IfElse } from './IfElse' export { default as IterationStart } from './IterationStart' export { default as Iteration } from './Iteration' -export { default as LoopStart } from './LoopStart' -export { default as Loop } from './Loop' export { default as Jinja } from './Jinja' export { default as KnowledgeRetrieval } from './KnowledgeRetrieval' export { default as ListFilter } from './ListFilter' export { default as Llm } from './Llm' +export { default as Loop } from './Loop' export { default as ParameterExtractor } from './ParameterExtractor' export { default as QuestionClassifier } from './QuestionClassifier' export { default as TemplatingTransform } from './TemplatingTransform' diff --git a/web/app/education-apply/components/education-apply-page.tsx b/web/app/education-apply/components/education-apply-page.tsx index f7c34f0168..4b06d01f62 100644 --- a/web/app/education-apply/components/education-apply-page.tsx +++ b/web/app/education-apply/components/education-apply-page.tsx @@ -1,67 +1,78 @@ 'use client' +import { useTranslation } from 'react-i18next' import UserInfo from './user-info' import SearchInput from './search-input' -import Radio from '@/app/components/base/radio' +import RoleSelector from './role-selector' import Button from '@/app/components/base/button' import Checkbox from '@/app/components/base/checkbox' const EducationApplyAge = () => { + const { t } = useTranslation() + return (
-
- education background image +
-
-
+ dify logo
-
-
-
Get Education Verified
-
You are now eligible for Education Verified status. Please enter your education information below to complete the process and receive an exclusive 50% coupon for the Dify Professional Plan.
+
+
+
{t('education.toVerified')}
+
+ {t('education.toVerifiedTip.front')} + {t('education.toVerifiedTip.coupon')} + {t('education.toVerifiedTip.end')} +
- Your School Name + {t('education.form.schoolName.title')}
- Your School Role + {t('education.form.schoolRole.title')}
- - Student - Teacher - School Administrator - + {}} + />
- Terms & Agreements + {t('education.form.terms.title')}
- Your information and use of education verified status are subject to our Terms of Service and Privacy Policy. By submitting: + {t('education.form.terms.desc.front')} + {t('education.form.terms.desc.termsOfService')} + {t('education.form.terms.desc.and')} + {t('education.form.terms.desc.privacyPolicy')} + {t('education.form.terms.desc.end')}
- I confirm I am at least 18 years old + {t('education.form.terms.option.age')}
- I confirm I am enrolled or employed at the institution provided. Dify may request proof of enrollment/employment. If I misrepresent my eligibility, I agree to pay any fees initially waived based on my education status. + {t('education.form.terms.option.inSchool')}
@@ -69,7 +80,7 @@ const EducationApplyAge = () => { variant='primary' disabled={false} > - Send request + {t('education.submit')}
diff --git a/web/app/education-apply/components/role-selector.tsx b/web/app/education-apply/components/role-selector.tsx new file mode 100644 index 0000000000..685ed0cc79 --- /dev/null +++ b/web/app/education-apply/components/role-selector.tsx @@ -0,0 +1,53 @@ +import { useTranslation } from 'react-i18next' +import cn from '@/utils/classnames' + +type RoleSelectorProps = { + onChange: (value: string) => void + value: string +} + +const RoleSelector = ({ + onChange, + value, +}: RoleSelectorProps) => { + const { t } = useTranslation() + const options = [ + { + key: 'student', + value: t('education.form.schoolRole.option.student'), + }, + { + key: 'teacher', + value: t('education.form.schoolRole.option.teacher'), + }, + { + key: 'school-administrator', + value: t('education.form.schoolRole.option.administrator'), + }, + ] + + return ( +
+ { + options.map(option => ( +
onChange(option.key)} + > +
+
+ {option.value} +
+ )) + } +
+ ) +} + +export default RoleSelector diff --git a/web/app/education-apply/components/search-input.tsx b/web/app/education-apply/components/search-input.tsx index 80051318b2..cf7619f42a 100644 --- a/web/app/education-apply/components/search-input.tsx +++ b/web/app/education-apply/components/search-input.tsx @@ -1,3 +1,4 @@ +import { useTranslation } from 'react-i18next' import Input from '@/app/components/base/input' import { PortalToFollowElem, @@ -6,12 +7,14 @@ import { } from '@/app/components/base/portal-to-follow-elem' const SearchInput = () => { + const { t } = useTranslation() + return ( diff --git a/web/app/education-apply/components/user-info.tsx b/web/app/education-apply/components/user-info.tsx index 0678fd1045..2bb23d74d0 100644 --- a/web/app/education-apply/components/user-info.tsx +++ b/web/app/education-apply/components/user-info.tsx @@ -4,6 +4,7 @@ import Button from '@/app/components/base/button' import { useAppContext } from '@/context/app-context' import { logout } from '@/service/common' import Avatar from '@/app/components/base/avatar' +import { Triangle } from '@/app/components/base/icons/src/public/education' const UserInfo = () => { const router = useRouter() @@ -24,7 +25,13 @@ const UserInfo = () => { } return ( -
+
+
+
+ {t('education.currentSigned')} +
+ +
{ + let res + try { + res = require(`./${lang}/education`).default + } + catch { + res = require('./en-US/education').default + } + + return res +} + const loadLangResources = (lang: string) => ({ translation: { common: require(`./${lang}/common`).default, @@ -31,6 +43,7 @@ const loadLangResources = (lang: string) => ({ plugin: require(`./${lang}/plugin`).default, pluginTags: require(`./${lang}/plugin-tags`).default, time: require(`./${lang}/time`).default, + education: requireSilent(lang), }, }) diff --git a/web/i18n/ja-JP/education.ts b/web/i18n/ja-JP/education.ts new file mode 100644 index 0000000000..2e5ad73860 --- /dev/null +++ b/web/i18n/ja-JP/education.ts @@ -0,0 +1,41 @@ +const translation = { + toVerified: '教育認証を取得', + toVerifiedTip: { + front: '現在、教育認証ステータスを取得する資格があります。以下に教育情報を入力し、認証プロセスを完了すると、Difyプロフェッショナルプランの', + coupon: '50%割引クーポン', + end: 'を受け取ることができます。', + }, + currentSigned: '現在ログイン中のアカウントは', + form: { + schoolName: { + title: '学校名', + placeholder: '学校の正式名称(省略不可)を入力してください。', + }, + schoolRole: { + title: '学校での役割', + option: { + student: '学生', + teacher: '教師', + administrator: '学校管理者', + }, + }, + terms: { + title: '利用規約と同意事項', + desc: { + front: 'お客様の情報および 教育認証ステータス の利用は、当社の ', + and: 'および', + end: 'に従うものとします。送信することで以下を確認します:', + termsOfService: '利用規約', + privacyPolicy: 'プライバシーポリシー', + }, + option: { + age: '18歳以上であることを確認します。', + inSchool: '提供した教育機関に在籍または勤務している ことを確認します。Difyは在籍/雇用証明の提出を求める場合があります。不正な情報を申告した場合、教育認証に基づき免除された費用を支払うことに同意します。', + }, + }, + }, + submit: '送信', + learn: '教育認証の取得方法はこちら', +} + +export default translation diff --git a/web/i18n/zh-Hans/education.ts b/web/i18n/zh-Hans/education.ts index e69de29bb2..df361367e7 100644 --- a/web/i18n/zh-Hans/education.ts +++ b/web/i18n/zh-Hans/education.ts @@ -0,0 +1,41 @@ +const translation = { + toVerified: '获取教育版认证', + toVerifiedTip: { + front: '您现在符合教育版认证的资格。请在下方输入您的教育信息,以完成认证流程,并领取 Dify Professional 版 的', + coupon: '50% 独家优惠券', + end: '。', + }, + currentSigned: '您当前登录的账户是', + form: { + schoolName: { + title: '您的学校名称', + placeholder: '请输入您的学校的官方全称(不得缩写)', + }, + schoolRole: { + title: '您在学校的身份', + option: { + student: '学生', + teacher: '教师', + administrator: '学校管理员', + }, + }, + terms: { + title: '条款与协议', + desc: { + front: '您的信息和教育版认证资格的使用需遵守我们的', + and: '和', + end: '。提交即表示:', + termsOfService: '服务条款', + privacyPolicy: '隐私政策', + }, + option: { + age: '我确认我已年满 18 周岁。', + inSchool: '我确认我目前已在提供的学校入学或受雇。Dify 可能会要求提供入学/雇佣证明。如我虚报资格,我同意支付因教育版认证而被减免的费用。', + }, + }, + }, + submit: '提交', + learn: '了解如何获取教育版认证', +} + +export default translation diff --git a/web/public/education/bg.png b/web/public/education/bg.png index 917b0764f7..0c2e503f5f 100644 Binary files a/web/public/education/bg.png and b/web/public/education/bg.png differ