Co-authored-by: crazywoola <427733928@qq.com>tags/1.7.2
| import { useEffect, useMemo, useState } from 'react' | import { useEffect, useMemo, useState } from 'react' | ||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { RiListUnordered } from '@remixicon/react' | |||||
| import { RiCloseLine, RiListUnordered } from '@remixicon/react' | |||||
| import TemplateEn from './template/template.en.mdx' | import TemplateEn from './template/template.en.mdx' | ||||
| import TemplateZh from './template/template.zh.mdx' | import TemplateZh from './template/template.zh.mdx' | ||||
| import TemplateJa from './template/template.ja.mdx' | import TemplateJa from './template/template.ja.mdx' | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const [toc, setToc] = useState<Array<{ href: string; text: string }>>([]) | const [toc, setToc] = useState<Array<{ href: string; text: string }>>([]) | ||||
| const [isTocExpanded, setIsTocExpanded] = useState(false) | const [isTocExpanded, setIsTocExpanded] = useState(false) | ||||
| const [activeSection, setActiveSection] = useState<string>('') | |||||
| const { theme } = useTheme() | const { theme } = useTheme() | ||||
| // Set initial TOC expanded state based on screen width | // Set initial TOC expanded state based on screen width | ||||
| return null | return null | ||||
| }).filter((item): item is { href: string; text: string } => item !== null) | }).filter((item): item is { href: string; text: string } => item !== null) | ||||
| setToc(tocItems) | setToc(tocItems) | ||||
| // Set initial active section | |||||
| if (tocItems.length > 0) | |||||
| setActiveSection(tocItems[0].href.replace('#', '')) | |||||
| } | } | ||||
| } | } | ||||
| setTimeout(extractTOC, 0) | setTimeout(extractTOC, 0) | ||||
| }, [locale]) | }, [locale]) | ||||
| // Track scroll position for active section highlighting | |||||
| useEffect(() => { | |||||
| const handleScroll = () => { | |||||
| const scrollContainer = document.querySelector('.scroll-container') | |||||
| if (!scrollContainer || toc.length === 0) | |||||
| return | |||||
| // Find active section based on scroll position | |||||
| let currentSection = '' | |||||
| toc.forEach((item) => { | |||||
| const targetId = item.href.replace('#', '') | |||||
| const element = document.getElementById(targetId) | |||||
| if (element) { | |||||
| const rect = element.getBoundingClientRect() | |||||
| // Consider section active if its top is above the middle of viewport | |||||
| if (rect.top <= window.innerHeight / 2) | |||||
| currentSection = targetId | |||||
| } | |||||
| }) | |||||
| if (currentSection && currentSection !== activeSection) | |||||
| setActiveSection(currentSection) | |||||
| } | |||||
| const scrollContainer = document.querySelector('.scroll-container') | |||||
| if (scrollContainer) { | |||||
| scrollContainer.addEventListener('scroll', handleScroll) | |||||
| handleScroll() // Initial check | |||||
| return () => scrollContainer.removeEventListener('scroll', handleScroll) | |||||
| } | |||||
| }, [toc, activeSection]) | |||||
| // Handle TOC item click | // Handle TOC item click | ||||
| const handleTocClick = (e: React.MouseEvent<HTMLAnchorElement>, item: { href: string; text: string }) => { | const handleTocClick = (e: React.MouseEvent<HTMLAnchorElement>, item: { href: string; text: string }) => { | ||||
| e.preventDefault() | e.preventDefault() | ||||
| return ( | return ( | ||||
| <div className="flex"> | <div className="flex"> | ||||
| <div className={`fixed right-20 top-32 z-10 transition-all ${isTocExpanded ? 'w-64' : 'w-10'}`}> | |||||
| <div className={`fixed right-20 top-32 z-10 transition-all duration-150 ease-out ${isTocExpanded ? 'w-[280px]' : 'w-11'}`}> | |||||
| {isTocExpanded | {isTocExpanded | ||||
| ? ( | ? ( | ||||
| <nav className="toc max-h-[calc(100vh-150px)] w-full overflow-y-auto rounded-lg border border-components-panel-border bg-components-panel-bg p-4 shadow-md"> | |||||
| <div className="mb-4 flex items-center justify-between"> | |||||
| <h3 className="text-lg font-semibold text-text-primary">{t('appApi.develop.toc')}</h3> | |||||
| <nav className="toc flex max-h-[calc(100vh-150px)] w-full flex-col overflow-hidden rounded-xl border-[0.5px] border-components-panel-border bg-background-default-hover shadow-xl"> | |||||
| <div className="relative z-10 flex items-center justify-between border-b border-components-panel-border-subtle bg-background-default-hover px-4 py-2.5"> | |||||
| <span className="text-xs font-medium uppercase tracking-wide text-text-tertiary"> | |||||
| {t('appApi.develop.toc')} | |||||
| </span> | |||||
| <button | <button | ||||
| onClick={() => setIsTocExpanded(false)} | onClick={() => setIsTocExpanded(false)} | ||||
| className="text-text-tertiary hover:text-text-secondary" | |||||
| className="group flex h-6 w-6 items-center justify-center rounded-md transition-colors hover:bg-state-base-hover" | |||||
| aria-label="Close" | |||||
| > | > | ||||
| ✕ | |||||
| <RiCloseLine className="h-3 w-3 text-text-quaternary transition-colors group-hover:text-text-secondary" /> | |||||
| </button> | </button> | ||||
| </div> | </div> | ||||
| <ul className="space-y-2"> | |||||
| {toc.map((item, index) => ( | |||||
| <li key={index}> | |||||
| <a | |||||
| href={item.href} | |||||
| className="text-text-secondary transition-colors duration-200 hover:text-text-primary hover:underline" | |||||
| onClick={e => handleTocClick(e, item)} | |||||
| > | |||||
| {item.text} | |||||
| </a> | |||||
| </li> | |||||
| ))} | |||||
| </ul> | |||||
| <div className="from-components-panel-border-subtle/20 pointer-events-none absolute left-0 right-0 top-[41px] z-10 h-2 bg-gradient-to-b to-transparent"></div> | |||||
| <div className="pointer-events-none absolute left-0 right-0 top-[43px] z-10 h-3 bg-gradient-to-b from-background-default-hover to-transparent"></div> | |||||
| <div className="relative flex-1 overflow-y-auto px-3 py-3 pt-1"> | |||||
| {toc.length === 0 ? ( | |||||
| <div className="px-2 py-8 text-center text-xs text-text-quaternary"> | |||||
| {t('appApi.develop.noContent')} | |||||
| </div> | |||||
| ) : ( | |||||
| <ul className="space-y-0.5"> | |||||
| {toc.map((item, index) => { | |||||
| const isActive = activeSection === item.href.replace('#', '') | |||||
| return ( | |||||
| <li key={index}> | |||||
| <a | |||||
| href={item.href} | |||||
| onClick={e => handleTocClick(e, item)} | |||||
| className={cn( | |||||
| 'group relative flex items-center rounded-md px-3 py-2 text-[13px] transition-all duration-200', | |||||
| isActive | |||||
| ? 'bg-state-base-hover font-medium text-text-primary' | |||||
| : 'text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary', | |||||
| )} | |||||
| > | |||||
| <span | |||||
| className={cn( | |||||
| 'mr-2 h-1.5 w-1.5 rounded-full transition-all duration-200', | |||||
| isActive | |||||
| ? 'scale-100 bg-text-accent' | |||||
| : 'scale-75 bg-components-panel-border', | |||||
| )} | |||||
| /> | |||||
| <span className="flex-1 truncate"> | |||||
| {item.text} | |||||
| </span> | |||||
| </a> | |||||
| </li> | |||||
| ) | |||||
| })} | |||||
| </ul> | |||||
| )} | |||||
| </div> | |||||
| <div className="pointer-events-none absolute bottom-0 left-0 right-0 z-10 h-4 rounded-b-xl bg-gradient-to-t from-background-default-hover to-transparent"></div> | |||||
| </nav> | </nav> | ||||
| ) | ) | ||||
| : ( | : ( | ||||
| <button | <button | ||||
| onClick={() => setIsTocExpanded(true)} | onClick={() => setIsTocExpanded(true)} | ||||
| className="flex h-10 w-10 items-center justify-center rounded-full border border-components-panel-border bg-components-button-secondary-bg shadow-md transition-colors duration-200 hover:bg-components-button-secondary-bg-hover" | |||||
| className="group flex h-11 w-11 items-center justify-center rounded-full border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg transition-all duration-150 hover:bg-background-default-hover hover:shadow-xl" | |||||
| aria-label="Open table of contents" | |||||
| > | > | ||||
| <RiListUnordered className="h-6 w-6 text-components-button-secondary-text" /> | |||||
| <RiListUnordered className="h-5 w-5 text-text-tertiary transition-colors group-hover:text-text-secondary" /> | |||||
| </button> | </button> | ||||
| )} | )} | ||||
| </div> | </div> |
| 'use client' | 'use client' | ||||
| import { useEffect, useState } from 'react' | |||||
| import { useEffect, useMemo, useState } from 'react' | |||||
| import { useContext } from 'use-context-selector' | import { useContext } from 'use-context-selector' | ||||
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { RiListUnordered } from '@remixicon/react' | |||||
| import { RiCloseLine, RiListUnordered } from '@remixicon/react' | |||||
| import TemplateEn from './template/template.en.mdx' | import TemplateEn from './template/template.en.mdx' | ||||
| import TemplateZh from './template/template.zh.mdx' | import TemplateZh from './template/template.zh.mdx' | ||||
| import TemplateJa from './template/template.ja.mdx' | import TemplateJa from './template/template.ja.mdx' | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| const [toc, setToc] = useState<Array<{ href: string; text: string }>>([]) | const [toc, setToc] = useState<Array<{ href: string; text: string }>>([]) | ||||
| const [isTocExpanded, setIsTocExpanded] = useState(false) | const [isTocExpanded, setIsTocExpanded] = useState(false) | ||||
| const [activeSection, setActiveSection] = useState<string>('') | |||||
| const { theme } = useTheme() | const { theme } = useTheme() | ||||
| const variables = appDetail?.model_config?.configs?.prompt_variables || [] | const variables = appDetail?.model_config?.configs?.prompt_variables || [] | ||||
| return null | return null | ||||
| }).filter((item): item is { href: string; text: string } => item !== null) | }).filter((item): item is { href: string; text: string } => item !== null) | ||||
| setToc(tocItems) | setToc(tocItems) | ||||
| if (tocItems.length > 0) | |||||
| setActiveSection(tocItems[0].href.replace('#', '')) | |||||
| } | } | ||||
| } | } | ||||
| // Run after component has rendered | |||||
| setTimeout(extractTOC, 0) | setTimeout(extractTOC, 0) | ||||
| }, [appDetail, locale]) | }, [appDetail, locale]) | ||||
| useEffect(() => { | |||||
| const handleScroll = () => { | |||||
| const scrollContainer = document.querySelector('.overflow-auto') | |||||
| if (!scrollContainer || toc.length === 0) | |||||
| return | |||||
| let currentSection = '' | |||||
| toc.forEach((item) => { | |||||
| const targetId = item.href.replace('#', '') | |||||
| const element = document.getElementById(targetId) | |||||
| if (element) { | |||||
| const rect = element.getBoundingClientRect() | |||||
| if (rect.top <= window.innerHeight / 2) | |||||
| currentSection = targetId | |||||
| } | |||||
| }) | |||||
| if (currentSection && currentSection !== activeSection) | |||||
| setActiveSection(currentSection) | |||||
| } | |||||
| const scrollContainer = document.querySelector('.overflow-auto') | |||||
| if (scrollContainer) { | |||||
| scrollContainer.addEventListener('scroll', handleScroll) | |||||
| handleScroll() | |||||
| return () => scrollContainer.removeEventListener('scroll', handleScroll) | |||||
| } | |||||
| }, [toc, activeSection]) | |||||
| const handleTocClick = (e: React.MouseEvent<HTMLAnchorElement>, item: { href: string; text: string }) => { | const handleTocClick = (e: React.MouseEvent<HTMLAnchorElement>, item: { href: string; text: string }) => { | ||||
| e.preventDefault() | e.preventDefault() | ||||
| const targetId = item.href.replace('#', '') | const targetId = item.href.replace('#', '') | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| const Template = useMemo(() => { | |||||
| if (appDetail?.mode === 'chat' || appDetail?.mode === 'agent-chat') { | |||||
| switch (locale) { | |||||
| case LanguagesSupported[1]: | |||||
| return <TemplateChatZh appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| case LanguagesSupported[7]: | |||||
| return <TemplateChatJa appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| default: | |||||
| return <TemplateChatEn appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| } | |||||
| } | |||||
| if (appDetail?.mode === 'advanced-chat') { | |||||
| switch (locale) { | |||||
| case LanguagesSupported[1]: | |||||
| return <TemplateAdvancedChatZh appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| case LanguagesSupported[7]: | |||||
| return <TemplateAdvancedChatJa appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| default: | |||||
| return <TemplateAdvancedChatEn appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| } | |||||
| } | |||||
| if (appDetail?.mode === 'workflow') { | |||||
| switch (locale) { | |||||
| case LanguagesSupported[1]: | |||||
| return <TemplateWorkflowZh appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| case LanguagesSupported[7]: | |||||
| return <TemplateWorkflowJa appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| default: | |||||
| return <TemplateWorkflowEn appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| } | |||||
| } | |||||
| if (appDetail?.mode === 'completion') { | |||||
| switch (locale) { | |||||
| case LanguagesSupported[1]: | |||||
| return <TemplateZh appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| case LanguagesSupported[7]: | |||||
| return <TemplateJa appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| default: | |||||
| return <TemplateEn appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| } | |||||
| } | |||||
| return null | |||||
| }, [appDetail, locale, variables, inputs]) | |||||
| return ( | return ( | ||||
| <div className="flex"> | <div className="flex"> | ||||
| <div className={`fixed right-8 top-32 z-10 transition-all ${isTocExpanded ? 'w-64' : 'w-10'}`}> | |||||
| <div className={`fixed right-20 top-32 z-10 transition-all duration-150 ease-out ${isTocExpanded ? 'w-[280px]' : 'w-11'}`}> | |||||
| {isTocExpanded | {isTocExpanded | ||||
| ? ( | ? ( | ||||
| <nav className="toc max-h-[calc(100vh-150px)] w-full overflow-y-auto rounded-lg border border-components-panel-border bg-components-panel-bg p-4 shadow-md"> | |||||
| <div className="mb-4 flex items-center justify-between"> | |||||
| <h3 className="text-lg font-semibold text-text-primary">{t('appApi.develop.toc')}</h3> | |||||
| <nav className="toc flex max-h-[calc(100vh-150px)] w-full flex-col overflow-hidden rounded-xl border-[0.5px] border-components-panel-border bg-background-default-hover shadow-xl"> | |||||
| <div className="relative z-10 flex items-center justify-between border-b border-components-panel-border-subtle bg-background-default-hover px-4 py-2.5"> | |||||
| <span className="text-xs font-medium uppercase tracking-wide text-text-tertiary"> | |||||
| {t('appApi.develop.toc')} | |||||
| </span> | |||||
| <button | <button | ||||
| onClick={() => setIsTocExpanded(false)} | onClick={() => setIsTocExpanded(false)} | ||||
| className="text-text-tertiary hover:text-text-secondary" | |||||
| className="group flex h-6 w-6 items-center justify-center rounded-md transition-colors hover:bg-state-base-hover" | |||||
| aria-label="Close" | |||||
| > | > | ||||
| ✕ | |||||
| <RiCloseLine className="h-3 w-3 text-text-quaternary transition-colors group-hover:text-text-secondary" /> | |||||
| </button> | </button> | ||||
| </div> | </div> | ||||
| <ul className="space-y-2"> | |||||
| {toc.map((item, index) => ( | |||||
| <li key={index}> | |||||
| <a | |||||
| href={item.href} | |||||
| className="text-text-secondary transition-colors duration-200 hover:text-text-primary hover:underline" | |||||
| onClick={e => handleTocClick(e, item)} | |||||
| > | |||||
| {item.text} | |||||
| </a> | |||||
| </li> | |||||
| ))} | |||||
| </ul> | |||||
| <div className="from-components-panel-border-subtle/20 pointer-events-none absolute left-0 right-0 top-[41px] z-10 h-2 bg-gradient-to-b to-transparent"></div> | |||||
| <div className="pointer-events-none absolute left-0 right-0 top-[43px] z-10 h-3 bg-gradient-to-b from-background-default-hover to-transparent"></div> | |||||
| <div className="relative flex-1 overflow-y-auto px-3 py-3 pt-1"> | |||||
| {toc.length === 0 ? ( | |||||
| <div className="px-2 py-8 text-center text-xs text-text-quaternary"> | |||||
| {t('appApi.develop.noContent')} | |||||
| </div> | |||||
| ) : ( | |||||
| <ul className="space-y-0.5"> | |||||
| {toc.map((item, index) => { | |||||
| const isActive = activeSection === item.href.replace('#', '') | |||||
| return ( | |||||
| <li key={index}> | |||||
| <a | |||||
| href={item.href} | |||||
| onClick={e => handleTocClick(e, item)} | |||||
| className={cn( | |||||
| 'group relative flex items-center rounded-md px-3 py-2 text-[13px] transition-all duration-200', | |||||
| isActive | |||||
| ? 'bg-state-base-hover font-medium text-text-primary' | |||||
| : 'text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary', | |||||
| )} | |||||
| > | |||||
| <span | |||||
| className={cn( | |||||
| 'mr-2 h-1.5 w-1.5 rounded-full transition-all duration-200', | |||||
| isActive | |||||
| ? 'scale-100 bg-text-accent' | |||||
| : 'scale-75 bg-components-panel-border', | |||||
| )} | |||||
| /> | |||||
| <span className="flex-1 truncate"> | |||||
| {item.text} | |||||
| </span> | |||||
| </a> | |||||
| </li> | |||||
| ) | |||||
| })} | |||||
| </ul> | |||||
| )} | |||||
| </div> | |||||
| <div className="pointer-events-none absolute bottom-0 left-0 right-0 z-10 h-4 rounded-b-xl bg-gradient-to-t from-background-default-hover to-transparent"></div> | |||||
| </nav> | </nav> | ||||
| ) | ) | ||||
| : ( | : ( | ||||
| <button | <button | ||||
| onClick={() => setIsTocExpanded(true)} | onClick={() => setIsTocExpanded(true)} | ||||
| className="flex h-10 w-10 items-center justify-center rounded-full border border-components-panel-border bg-components-button-secondary-bg shadow-md transition-colors duration-200 hover:bg-components-button-secondary-bg-hover" | |||||
| className="group flex h-11 w-11 items-center justify-center rounded-full border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg transition-all duration-150 hover:bg-background-default-hover hover:shadow-xl" | |||||
| aria-label="Open table of contents" | |||||
| > | > | ||||
| <RiListUnordered className="h-6 w-6 text-components-button-secondary-text" /> | |||||
| <RiListUnordered className="h-5 w-5 text-text-tertiary transition-colors group-hover:text-text-secondary" /> | |||||
| </button> | </button> | ||||
| )} | )} | ||||
| </div> | </div> | ||||
| <article className={cn('prose-xl prose', theme === Theme.dark && 'prose-invert')} > | |||||
| {(appDetail?.mode === 'chat' || appDetail?.mode === 'agent-chat') && ( | |||||
| (() => { | |||||
| switch (locale) { | |||||
| case LanguagesSupported[1]: | |||||
| return <TemplateChatZh appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| case LanguagesSupported[7]: | |||||
| return <TemplateChatJa appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| default: | |||||
| return <TemplateChatEn appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| } | |||||
| })() | |||||
| )} | |||||
| {appDetail?.mode === 'advanced-chat' && ( | |||||
| (() => { | |||||
| switch (locale) { | |||||
| case LanguagesSupported[1]: | |||||
| return <TemplateAdvancedChatZh appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| case LanguagesSupported[7]: | |||||
| return <TemplateAdvancedChatJa appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| default: | |||||
| return <TemplateAdvancedChatEn appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| } | |||||
| })() | |||||
| )} | |||||
| {appDetail?.mode === 'workflow' && ( | |||||
| (() => { | |||||
| switch (locale) { | |||||
| case LanguagesSupported[1]: | |||||
| return <TemplateWorkflowZh appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| case LanguagesSupported[7]: | |||||
| return <TemplateWorkflowJa appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| default: | |||||
| return <TemplateWorkflowEn appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| } | |||||
| })() | |||||
| )} | |||||
| {appDetail?.mode === 'completion' && ( | |||||
| (() => { | |||||
| switch (locale) { | |||||
| case LanguagesSupported[1]: | |||||
| return <TemplateZh appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| case LanguagesSupported[7]: | |||||
| return <TemplateJa appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| default: | |||||
| return <TemplateEn appDetail={appDetail} variables={variables} inputs={inputs} /> | |||||
| } | |||||
| })() | |||||
| )} | |||||
| <article className={cn('prose-xl prose', theme === Theme.dark && 'prose-invert')}> | |||||
| {Template} | |||||
| </article> | </article> | ||||
| </div> | </div> | ||||
| ) | ) |
| url='/text-to-audio' | url='/text-to-audio' | ||||
| method='POST' | method='POST' | ||||
| title='テキストから音声' | title='テキストから音声' | ||||
| name='#audio' | |||||
| name='#text-to-audio' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> |
| url='/text-to-audio' | url='/text-to-audio' | ||||
| method='POST' | method='POST' | ||||
| title='文字转语音' | title='文字转语音' | ||||
| name='#audio' | |||||
| name='#text-to-audio' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> |
| url='/audio-to-text' | url='/audio-to-text' | ||||
| method='POST' | method='POST' | ||||
| title='Speech to Text' | title='Speech to Text' | ||||
| name='#audio' | |||||
| name='#audio-to-text' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> | ||||
| url='/text-to-audio' | url='/text-to-audio' | ||||
| method='POST' | method='POST' | ||||
| title='Text to Audio' | title='Text to Audio' | ||||
| name='#audio' | |||||
| name='#text-to-audio' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> |
| url='/audio-to-text' | url='/audio-to-text' | ||||
| method='POST' | method='POST' | ||||
| title='音声からテキストへ' | title='音声からテキストへ' | ||||
| name='#audio' | |||||
| name='#audio-to-text' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> | ||||
| url='/text-to-audio' | url='/text-to-audio' | ||||
| method='POST' | method='POST' | ||||
| title='テキストから音声へ' | title='テキストから音声へ' | ||||
| name='#audio' | |||||
| name='#text-to-audio' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> |
| url='/audio-to-text' | url='/audio-to-text' | ||||
| method='POST' | method='POST' | ||||
| title='语音转文字' | title='语音转文字' | ||||
| name='#audio' | |||||
| name='#audio-to-text' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> | ||||
| url='/text-to-audio' | url='/text-to-audio' | ||||
| method='POST' | method='POST' | ||||
| title='文字转语音' | title='文字转语音' | ||||
| name='#audio' | |||||
| name='#text-to-audio' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> |
| url='/audio-to-text' | url='/audio-to-text' | ||||
| method='POST' | method='POST' | ||||
| title='Speech to Text' | title='Speech to Text' | ||||
| name='#audio' | |||||
| name='#audio-to-text' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> | ||||
| url='/text-to-audio' | url='/text-to-audio' | ||||
| method='POST' | method='POST' | ||||
| title='Text to Audio' | title='Text to Audio' | ||||
| name='#audio' | |||||
| name='#text-to-audio' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> |
| url='/audio-to-text' | url='/audio-to-text' | ||||
| method='POST' | method='POST' | ||||
| title='音声からテキストへ' | title='音声からテキストへ' | ||||
| name='#audio' | |||||
| name='#audio-to-text' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> | ||||
| url='/text-to-audio' | url='/text-to-audio' | ||||
| method='POST' | method='POST' | ||||
| title='テキストから音声へ' | title='テキストから音声へ' | ||||
| name='#audio' | |||||
| name='#text-to-audio' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> |
| url='/audio-to-text' | url='/audio-to-text' | ||||
| method='POST' | method='POST' | ||||
| title='语音转文字' | title='语音转文字' | ||||
| name='#audio' | |||||
| name='#audio-to-text' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> | ||||
| url='/text-to-audio' | url='/text-to-audio' | ||||
| method='POST' | method='POST' | ||||
| title='文字转语音' | title='文字转语音' | ||||
| name='#audio' | |||||
| name='#text-to-audio' | |||||
| /> | /> | ||||
| <Row> | <Row> | ||||
| <Col> | <Col> |
| zoomTo50: 'Auf 50% vergrößern', | zoomTo50: 'Auf 50% vergrößern', | ||||
| zoomTo100: 'Auf 100% vergrößern', | zoomTo100: 'Auf 100% vergrößern', | ||||
| zoomToFit: 'An Bildschirm anpassen', | zoomToFit: 'An Bildschirm anpassen', | ||||
| selectionAlignment: 'Ausrichtung der Auswahl', | |||||
| alignLeft: 'Links', | |||||
| alignTop: 'Nach oben', | |||||
| distributeVertical: 'Vertikaler Raum', | |||||
| alignBottom: 'Unteres', | |||||
| distributeHorizontal: 'Horizontaler Raum', | |||||
| vertical: 'Senkrecht', | |||||
| alignMiddle: 'Mitte', | |||||
| alignCenter: 'Mitte', | |||||
| alignRight: 'Rechts', | |||||
| alignNodes: 'Knoten ausrichten', | |||||
| horizontal: 'Horizontal', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Benutzereingabefeld', | userInputField: 'Benutzereingabefeld', |
| zoomTo50: 'Zoom al 50%', | zoomTo50: 'Zoom al 50%', | ||||
| zoomTo100: 'Zoom al 100%', | zoomTo100: 'Zoom al 100%', | ||||
| zoomToFit: 'Ajustar al tamaño', | zoomToFit: 'Ajustar al tamaño', | ||||
| alignTop: 'Arriba', | |||||
| alignBottom: 'Fondo', | |||||
| alignNodes: 'Alinear nodos', | |||||
| alignCenter: 'Centro', | |||||
| selectionAlignment: 'Alineación de selección', | |||||
| horizontal: 'Horizontal', | |||||
| distributeHorizontal: 'Espaciar horizontalmente', | |||||
| vertical: 'Vertical', | |||||
| distributeVertical: 'Espaciar verticalmente', | |||||
| alignMiddle: 'medio', | |||||
| alignLeft: 'izquierdo', | |||||
| alignRight: 'derecho', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Campo de entrada del usuario', | userInputField: 'Campo de entrada del usuario', |
| zoomTo50: 'بزرگنمایی به 50%', | zoomTo50: 'بزرگنمایی به 50%', | ||||
| zoomTo100: 'بزرگنمایی به 100%', | zoomTo100: 'بزرگنمایی به 100%', | ||||
| zoomToFit: 'تناسب با اندازه', | zoomToFit: 'تناسب با اندازه', | ||||
| horizontal: 'افقی', | |||||
| alignBottom: 'پایین', | |||||
| alignRight: 'راست', | |||||
| vertical: 'عمودی', | |||||
| alignCenter: 'مرکز', | |||||
| alignLeft: 'چپ', | |||||
| distributeVertical: 'فضا عمودی', | |||||
| distributeHorizontal: 'فضا به صورت افقی', | |||||
| alignTop: 'بالا', | |||||
| alignNodes: 'تراز کردن گره ها', | |||||
| selectionAlignment: 'تراز انتخاب', | |||||
| alignMiddle: 'میانه', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'فیلد ورودی کاربر', | userInputField: 'فیلد ورودی کاربر', |
| zoomTo50: 'Zoomer à 50%', | zoomTo50: 'Zoomer à 50%', | ||||
| zoomTo100: 'Zoomer à 100%', | zoomTo100: 'Zoomer à 100%', | ||||
| zoomToFit: 'Zoomer pour ajuster', | zoomToFit: 'Zoomer pour ajuster', | ||||
| alignBottom: 'Fond', | |||||
| alignLeft: 'Gauche', | |||||
| alignCenter: 'Centre', | |||||
| alignTop: 'Retour au début', | |||||
| alignNodes: 'Aligner les nœuds', | |||||
| distributeHorizontal: 'Espace horizontal', | |||||
| alignMiddle: 'Milieu', | |||||
| horizontal: 'Horizontal', | |||||
| selectionAlignment: 'Alignement de la sélection', | |||||
| alignRight: 'Droite', | |||||
| vertical: 'Vertical', | |||||
| distributeVertical: 'Espace vertical', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Champ de saisie de l\'utilisateur', | userInputField: 'Champ de saisie de l\'utilisateur', |
| zoomTo50: '50% पर ज़ूम करें', | zoomTo50: '50% पर ज़ूम करें', | ||||
| zoomTo100: '100% पर ज़ूम करें', | zoomTo100: '100% पर ज़ूम करें', | ||||
| zoomToFit: 'फिट करने के लिए ज़ूम करें', | zoomToFit: 'फिट करने के लिए ज़ूम करें', | ||||
| alignRight: 'सही', | |||||
| alignLeft: 'बाईं ओर', | |||||
| alignTop: 'शीर्ष', | |||||
| horizontal: 'क्षैतिज', | |||||
| alignNodes: 'नोड्स को संरेखित करें', | |||||
| selectionAlignment: 'चयन संरेखण', | |||||
| alignCenter: 'केंद्र', | |||||
| vertical: 'ऊर्ध्वाधर', | |||||
| distributeHorizontal: 'क्षैतिज स्पेस', | |||||
| alignBottom: 'तल', | |||||
| distributeVertical: 'अंतरिक्ष को वर्टिकल रूप से', | |||||
| alignMiddle: 'मध्य', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'उपयोगकर्ता इनपुट फ़ील्ड', | userInputField: 'उपयोगकर्ता इनपुट फ़ील्ड', |
| zoomTo50: 'Zoom al 50%', | zoomTo50: 'Zoom al 50%', | ||||
| zoomTo100: 'Zoom al 100%', | zoomTo100: 'Zoom al 100%', | ||||
| zoomToFit: 'Zoom per Adattare', | zoomToFit: 'Zoom per Adattare', | ||||
| alignRight: 'A destra', | |||||
| selectionAlignment: 'Allineamento della selezione', | |||||
| alignBottom: 'Fondoschiena', | |||||
| alignTop: 'In alto', | |||||
| vertical: 'Verticale', | |||||
| alignCenter: 'Centro', | |||||
| alignLeft: 'A sinistra', | |||||
| alignMiddle: 'Mezzo', | |||||
| horizontal: 'Orizzontale', | |||||
| alignNodes: 'Allinea nodi', | |||||
| distributeHorizontal: 'Spazia orizzontalmente', | |||||
| distributeVertical: 'Spazia verticalmente', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Campo di Input Utente', | userInputField: 'Campo di Input Utente', |
| zoomTo50: '50% サイズ', | zoomTo50: '50% サイズ', | ||||
| zoomTo100: '等倍表示', | zoomTo100: '等倍表示', | ||||
| zoomToFit: '画面に合わせる', | zoomToFit: '画面に合わせる', | ||||
| horizontal: '横', | |||||
| alignBottom: '底', | |||||
| alignNodes: 'ノードを整列させる', | |||||
| vertical: '垂直', | |||||
| alignLeft: '左', | |||||
| alignTop: 'トップ', | |||||
| alignRight: '右', | |||||
| alignMiddle: '中間', | |||||
| distributeVertical: '垂直にスペースを', | |||||
| alignCenter: 'センター', | |||||
| selectionAlignment: '選択の整列', | |||||
| distributeHorizontal: '空間を水平方向に', | |||||
| }, | }, | ||||
| variableReference: { | variableReference: { | ||||
| noAvailableVars: '利用可能な変数がありません', | noAvailableVars: '利用可能な変数がありません', |
| zoomTo50: '50% 로 확대', | zoomTo50: '50% 로 확대', | ||||
| zoomTo100: '100% 로 확대', | zoomTo100: '100% 로 확대', | ||||
| zoomToFit: '화면에 맞게 확대', | zoomToFit: '화면에 맞게 확대', | ||||
| alignCenter: '중', | |||||
| alignRight: '오른쪽', | |||||
| alignLeft: '왼쪽', | |||||
| vertical: '세로', | |||||
| alignTop: '맨 위로', | |||||
| alignMiddle: '중간', | |||||
| alignNodes: '노드 정렬', | |||||
| distributeVertical: '수직 공간', | |||||
| horizontal: '가로', | |||||
| selectionAlignment: '선택 정렬', | |||||
| alignBottom: '밑바닥', | |||||
| distributeHorizontal: '수평 공간', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: '사용자 입력 필드', | userInputField: '사용자 입력 필드', |
| zoomTo50: 'Powiększ do 50%', | zoomTo50: 'Powiększ do 50%', | ||||
| zoomTo100: 'Powiększ do 100%', | zoomTo100: 'Powiększ do 100%', | ||||
| zoomToFit: 'Dopasuj do ekranu', | zoomToFit: 'Dopasuj do ekranu', | ||||
| alignMiddle: 'Środek', | |||||
| alignTop: 'Do góry', | |||||
| distributeHorizontal: 'Odstęp w poziomie', | |||||
| alignCenter: 'Centrum', | |||||
| alignRight: 'Prawy', | |||||
| alignNodes: 'Wyrównywanie węzłów', | |||||
| selectionAlignment: 'Wyrównanie zaznaczenia', | |||||
| horizontal: 'Poziomy', | |||||
| distributeVertical: 'Przestrzeń w pionie', | |||||
| alignBottom: 'Dno', | |||||
| alignLeft: 'Lewy', | |||||
| vertical: 'Pionowy', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Pole wprowadzania użytkownika', | userInputField: 'Pole wprowadzania użytkownika', |
| zoomTo50: 'Aproximar para 50%', | zoomTo50: 'Aproximar para 50%', | ||||
| zoomTo100: 'Aproximar para 100%', | zoomTo100: 'Aproximar para 100%', | ||||
| zoomToFit: 'Aproximar para ajustar', | zoomToFit: 'Aproximar para ajustar', | ||||
| vertical: 'Vertical', | |||||
| alignNodes: 'Alinhar nós', | |||||
| selectionAlignment: 'Alinhamento de seleção', | |||||
| alignLeft: 'Esquerda', | |||||
| alignBottom: 'Fundo', | |||||
| distributeHorizontal: 'Espaço horizontalmente', | |||||
| alignMiddle: 'Meio', | |||||
| alignRight: 'Certo', | |||||
| horizontal: 'Horizontal', | |||||
| distributeVertical: 'Espaço Verticalmente', | |||||
| alignCenter: 'Centro', | |||||
| alignTop: 'Início', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Campo de entrada do usuário', | userInputField: 'Campo de entrada do usuário', |
| zoomTo50: 'Mărește la 50%', | zoomTo50: 'Mărește la 50%', | ||||
| zoomTo100: 'Mărește la 100%', | zoomTo100: 'Mărește la 100%', | ||||
| zoomToFit: 'Mărește pentru a se potrivi', | zoomToFit: 'Mărește pentru a se potrivi', | ||||
| horizontal: 'Orizontal', | |||||
| selectionAlignment: 'Alinierea selecției', | |||||
| vertical: 'Vertical', | |||||
| alignRight: 'Dreapta', | |||||
| alignLeft: 'Stânga', | |||||
| alignMiddle: 'Mijloc', | |||||
| distributeVertical: 'Spațiu vertical', | |||||
| alignCenter: 'Centru', | |||||
| distributeHorizontal: 'Spațiu orizontal', | |||||
| alignBottom: 'Fund', | |||||
| alignTop: 'Culme', | |||||
| alignNodes: 'Alinierea nodurilor', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Câmp de introducere utilizator', | userInputField: 'Câmp de introducere utilizator', |
| zoomTo50: 'Масштаб 50%', | zoomTo50: 'Масштаб 50%', | ||||
| zoomTo100: 'Масштаб 100%', | zoomTo100: 'Масштаб 100%', | ||||
| zoomToFit: 'По размеру', | zoomToFit: 'По размеру', | ||||
| alignTop: 'Вверх', | |||||
| alignBottom: 'Дно', | |||||
| alignRight: 'Правильно', | |||||
| distributeHorizontal: 'Пространство по горизонтали', | |||||
| alignMiddle: 'Середина', | |||||
| vertical: 'Вертикальный', | |||||
| alignCenter: 'Центр', | |||||
| alignLeft: 'Налево', | |||||
| selectionAlignment: 'Выравнивание выделения', | |||||
| horizontal: 'Горизонтальный', | |||||
| alignNodes: 'Выравнивание узлов', | |||||
| distributeVertical: 'Пространство по вертикали', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Поле ввода пользователя', | userInputField: 'Поле ввода пользователя', |
| zoomIn: 'Zoom in', | zoomIn: 'Zoom in', | ||||
| zoomTo50: 'Povečaj na 50%', | zoomTo50: 'Povečaj na 50%', | ||||
| zoomTo100: 'Povečaj na 100%', | zoomTo100: 'Povečaj na 100%', | ||||
| alignMiddle: 'Srednji', | |||||
| alignBottom: 'Dno', | |||||
| alignCenter: 'Center', | |||||
| distributeVertical: 'Razmik navpično', | |||||
| alignRight: 'Desno', | |||||
| alignTop: 'Vrh', | |||||
| vertical: 'Navpičen', | |||||
| distributeHorizontal: 'Razmik vodoravno', | |||||
| selectionAlignment: 'Poravnava izbora', | |||||
| alignNodes: 'Poravnava vozlišč', | |||||
| horizontal: 'Vodoraven', | |||||
| alignLeft: 'Levo', | |||||
| }, | }, | ||||
| variableReference: { | variableReference: { | ||||
| conversationVars: 'pogovorne spremenljivke', | conversationVars: 'pogovorne spremenljivke', |
| zoomTo50: 'ซูมไปที่ 50%', | zoomTo50: 'ซูมไปที่ 50%', | ||||
| zoomTo100: 'ซูมไปที่ 100%', | zoomTo100: 'ซูมไปที่ 100%', | ||||
| zoomToFit: 'ซูมให้พอดี', | zoomToFit: 'ซูมให้พอดี', | ||||
| alignBottom: 'ก้น', | |||||
| alignCenter: 'ศูนย์กลาง', | |||||
| alignMiddle: 'กลาง', | |||||
| horizontal: 'แนวราบ', | |||||
| vertical: 'ซึ่งตั้งตรง', | |||||
| alignTop: 'ด้านบน', | |||||
| distributeVertical: 'พื้นที่ในแนวตั้ง', | |||||
| alignLeft: 'ซ้าย', | |||||
| selectionAlignment: 'การจัดตําแหน่งการเลือก', | |||||
| distributeHorizontal: 'ช่องว่างในแนวนอน', | |||||
| alignRight: 'ขวา', | |||||
| alignNodes: 'จัดตําแหน่งโหนด', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'ฟิลด์ป้อนข้อมูลของผู้ใช้', | userInputField: 'ฟิลด์ป้อนข้อมูลของผู้ใช้', |
| zoomTo50: '%50 Yakınlaştır', | zoomTo50: '%50 Yakınlaştır', | ||||
| zoomTo100: '%100 Yakınlaştır', | zoomTo100: '%100 Yakınlaştır', | ||||
| zoomToFit: 'Sığdıracak Şekilde Yakınlaştır', | zoomToFit: 'Sığdıracak Şekilde Yakınlaştır', | ||||
| alignCenter: 'Orta', | |||||
| alignMiddle: 'Orta', | |||||
| alignLeft: 'Sol', | |||||
| alignNodes: 'Düğümleri Hizala', | |||||
| vertical: 'Dikey', | |||||
| alignRight: 'Sağ', | |||||
| alignTop: 'Sayfanın Üstü', | |||||
| alignBottom: 'Dip', | |||||
| selectionAlignment: 'Seçim Hizalama', | |||||
| distributeHorizontal: 'Yatay Boşluk', | |||||
| horizontal: 'Yatay', | |||||
| distributeVertical: 'Dikey Boşluk', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Kullanıcı Giriş Alanı', | userInputField: 'Kullanıcı Giriş Alanı', |
| zoomTo50: 'Збільшити до 50%', | zoomTo50: 'Збільшити до 50%', | ||||
| zoomTo100: 'Збільшити до 100%', | zoomTo100: 'Збільшити до 100%', | ||||
| zoomToFit: 'Збільшити для підгонки', | zoomToFit: 'Збільшити для підгонки', | ||||
| alignCenter: 'Центр', | |||||
| alignRight: 'Праворуч', | |||||
| vertical: 'Вертикальні', | |||||
| alignBottom: 'Низ', | |||||
| alignLeft: 'Ліворуч', | |||||
| alignTop: 'Верх', | |||||
| horizontal: 'Горизонтальні', | |||||
| alignMiddle: 'Середній', | |||||
| distributeVertical: 'Простір по вертикалі', | |||||
| distributeHorizontal: 'Простір по горизонталі', | |||||
| selectionAlignment: 'Вирівнювання вибору', | |||||
| alignNodes: 'Вирівнювання вузлів', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Поле введення користувача', | userInputField: 'Поле введення користувача', |
| zoomTo50: 'Phóng to 50%', | zoomTo50: 'Phóng to 50%', | ||||
| zoomTo100: 'Phóng to 100%', | zoomTo100: 'Phóng to 100%', | ||||
| zoomToFit: 'Phóng to vừa màn hình', | zoomToFit: 'Phóng to vừa màn hình', | ||||
| alignBottom: 'Đáy', | |||||
| alignMiddle: 'Trung', | |||||
| alignRight: 'Bên phải', | |||||
| alignNodes: 'Căn chỉnh các nút', | |||||
| alignLeft: 'Bên trái', | |||||
| horizontal: 'Ngang', | |||||
| alignCenter: 'Trung tâm', | |||||
| alignTop: 'Đỉnh', | |||||
| distributeVertical: 'Không gian theo chiều dọc', | |||||
| selectionAlignment: 'Căn chỉnh lựa chọn', | |||||
| distributeHorizontal: 'Không gian theo chiều ngang', | |||||
| vertical: 'Thẳng đứng', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: 'Trường đầu vào của người dùng', | userInputField: 'Trường đầu vào của người dùng', |
| zoomTo50: '縮放到 50%', | zoomTo50: '縮放到 50%', | ||||
| zoomTo100: '放大到 100%', | zoomTo100: '放大到 100%', | ||||
| zoomToFit: '自適應視圖', | zoomToFit: '自適應視圖', | ||||
| alignNodes: '對齊節點(Align Nodes)', | |||||
| distributeVertical: '垂直空間', | |||||
| alignLeft: '左', | |||||
| distributeHorizontal: '水平空間', | |||||
| vertical: '垂直', | |||||
| alignTop: '返回頁首', | |||||
| alignCenter: '中心', | |||||
| horizontal: '水準', | |||||
| selectionAlignment: '選擇對齊', | |||||
| alignRight: '右', | |||||
| alignBottom: '底', | |||||
| alignMiddle: '中間', | |||||
| }, | }, | ||||
| panel: { | panel: { | ||||
| userInputField: '用戶輸入字段', | userInputField: '用戶輸入字段', |