- Nodes
+ {t('chatflows.nodes')}
{Object.keys(nodeConfig)
.sort()
@@ -870,9 +887,12 @@ formData.append("openAIApiKey[openAIEmbeddings_0]", "sk-my-openai-2nd-key")`
- Variables
+ {t('common.labels.variables')}
-
+
@@ -910,7 +930,7 @@ formData.append("openAIApiKey[openAIEmbeddings_0]", "sk-my-openai-2nd-key")`
>
- You can also specify multiple values for a config parameter by specifying the node id
+ {t('chatflows.specifyMultipleValues')}
@@ -918,10 +938,10 @@ formData.append("openAIApiKey[openAIEmbeddings_0]", "sk-my-openai-2nd-key")`
theme={atomOneDark}
text={
dialogProps.isFormDataRequired
- ? getMultiConfigCodeWithFormData(codeLang)
+ ? getMultiConfigCodeWithFormData(codeLang.id)
: getMultiConfigCode()
}
- language={getLang(codeLang)}
+ language={getLang(codeLang.id)}
showLineNumbers={false}
wrapLines
/>
@@ -931,16 +951,24 @@ formData.append("openAIApiKey[openAIEmbeddings_0]", "sk-my-openai-2nd-key")`
)}
{getIsChatflowStreamingApi.data?.isStreaming && (
- Read
-
- here
-
- on how to stream response back to application
+
+ )
+ }}
+ />
)}
>
)}
- {codeLang === 'Share Chatbot' && !chatflowApiKeyId && (
+ {codeLang.id === 'Share Chatbot' && !chatflowApiKeyId && (
)}
diff --git a/packages/ui/src/views/chatflows/EmbedChat.jsx b/packages/ui/src/views/chatflows/EmbedChat.jsx
index 2c17966423c..4d1b6c43b57 100644
--- a/packages/ui/src/views/chatflows/EmbedChat.jsx
+++ b/packages/ui/src/views/chatflows/EmbedChat.jsx
@@ -10,6 +10,10 @@ import { CheckboxInput } from '@/ui-component/checkbox/Checkbox'
// Const
import { baseURL } from '@/store/constant'
+// i18n
+import { useTranslation, Trans } from 'react-i18next'
+import i18next from 'i18next'
+
function TabPanel(props) {
const { children, value, index, ...other } = props
return (
@@ -102,17 +106,17 @@ export const defaultThemeConfig = {
},
tooltip: {
showTooltip: true,
- tooltipMessage: 'Hi There 👋!',
+ tooltipMessage: i18next.t('chatflows.chat.tooltipMessage'),
tooltipBackgroundColor: 'black',
tooltipTextColor: 'white',
tooltipFontSize: 16
},
disclaimer: {
- title: 'Disclaimer',
- message: 'By using this chatbot, you agree to the
Terms & Condition',
+ title: i18next.t('chatflows.chat.disclaimer.title'),
+ message: i18next.t('chatflows.chat.disclaimer.message'),
textColor: 'black',
buttonColor: '#3b82f6',
- buttonText: 'Start Chatting',
+ buttonText: i18next.t('chatflows.chat.disclaimer.buttonText'),
buttonTextColor: 'white',
blurredBackgroundColor: 'rgba(0, 0, 0, 0.4)',
backgroundColor: 'white'
@@ -121,19 +125,19 @@ export const defaultThemeConfig = {
chatWindow: {
showTitle: true,
showAgentMessages: true,
- title: 'Flowise Bot',
+ title: i18next.t('chatflows.chat.chatWindow.title'),
titleAvatarSrc: 'https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/svg/google-messages.svg',
- welcomeMessage: 'Hello! This is custom welcome message',
- errorMessage: 'This is a custom error message',
+ welcomeMessage: i18next.t('chatflows.chat.chatWindow.welcomeMessage'),
+ errorMessage: i18next.t('chatflows.chat.chatWindow.errorMessage'),
backgroundColor: '#ffffff',
- backgroundImage: 'enter image path or link',
+ backgroundImage: i18next.t('chatflows.chat.chatWindow.backgroundImage'),
height: 700,
width: 400,
fontSize: 16,
starterPrompts: ['What is a bot?', 'Who are you?'],
starterPromptFontSize: 15,
clearChatOnReload: false,
- sourceDocsTitle: 'Sources:',
+ sourceDocsTitle: i18next.t('chatflows.chat.chatWindow.sourceDocsTitle'),
renderHTML: true,
botMessage: {
backgroundColor: '#f7f8ff',
@@ -148,12 +152,12 @@ export const defaultThemeConfig = {
avatarSrc: 'https://raw.githubusercontent.com/zahidkhawaja/langchain-chat-nextjs/main/public/usericon.png'
},
textInput: {
- placeholder: 'Type your question',
+ placeholder: i18next.t('chatflows.chat.textInput.placeholder'),
backgroundColor: '#ffffff',
textColor: '#303235',
sendButtonColor: '#3B81F6',
maxChars: 50,
- maxCharsWarningMessage: 'You exceeded the characters limit. Please input less than 50 characters.',
+ maxCharsWarningMessage: i18next.t('chatflows.chat.textInput.maxCharsWarningMessage'),
autoFocus: true,
sendMessageSound: true,
sendSoundLocation: 'send_message.mp3',
@@ -169,8 +173,8 @@ export const defaultThemeConfig = {
},
footer: {
textColor: '#303235',
- text: 'Powered by',
- company: 'Flowise',
+ text: i18next.t('chatflows.chat.footer.text'),
+ company: i18next.t('chatflows.chat.footer.company'),
companyLink: 'https://flowiseai.com'
}
}
@@ -286,7 +290,13 @@ const App = () => {
}
const EmbedChat = ({ chatflowid }) => {
- const codes = ['Popup Html', 'Fullpage Html', 'Popup React', 'Fullpage React']
+ const { t } = useTranslation()
+ const codes = [
+ { id: 'Popup Html', label: 'chatflows.codes.popupHtml' },
+ { id: 'Fullpage Html', label: 'chatflows.codes.fullpageHtml' },
+ { id: 'Popup React', label: 'chatflows.codes.popupReact' },
+ { id: 'Fullpage React', label: 'chatflows.codes.fullpageReact' }
+ ]
const [value, setValue] = useState(0)
const [embedChatCheckboxVal, setEmbedChatCheckbox] = useState(false)
@@ -332,9 +342,9 @@ const EmbedChat = ({ chatflowid }) => {
<>
-
+
{codes.map((codeLang, index) => (
-
+
))}
@@ -345,30 +355,41 @@ const EmbedChat = ({ chatflowid }) => {
{(value === 0 || value === 1) && (
<>
- Paste this anywhere in the {``} tag of your html file.
+ {t('chatflows.bodyTag.prefix')} {''} {t('chatflows.bodyTag.suffix')}
- You can also specify a
-
- version
-
- : {`https://cdn.jsdelivr.net/npm/flowise-embed@/dist/web.js`}
+ ,
+ code: ,
+ a: (
+ // eslint-disable-next-line jsx-a11y/anchor-has-content
+
+ )
+ }}
+ />
+ {`https://cdn.jsdelivr.net/npm/flowise-embed@/dist/web.js`}
>
)}
-
+
-
+
{embedChatCheckboxVal && (
{
+ const { t } = useTranslation()
const dispatch = useDispatch()
const theme = useTheme()
const chatflow = useSelector((state) => state.canvas.chatflow)
@@ -184,7 +188,7 @@ const ShareChatbot = ({ isSessionMemory, isAgentCanvas }) => {
})
if (saveResp.data) {
enqueueSnackbar({
- message: 'Chatbot Configuration Saved',
+ message: t('chatflows.messages.save.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -199,9 +203,9 @@ const ShareChatbot = ({ isSessionMemory, isAgentCanvas }) => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to save Chatbot Configuration: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('chatflows.messages.save.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -221,7 +225,7 @@ const ShareChatbot = ({ isSessionMemory, isAgentCanvas }) => {
const saveResp = await chatflowsApi.updateChatflow(chatflowid, { isPublic: checked })
if (saveResp.data) {
enqueueSnackbar({
- message: 'Chatbot Configuration Saved',
+ message: t('chatflows.messages.save.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -236,9 +240,9 @@ const ShareChatbot = ({ isSessionMemory, isAgentCanvas }) => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to save Chatbot Configuration: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('chatflows.messages.save.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -429,7 +433,7 @@ const ShareChatbot = ({ isSessionMemory, isAgentCanvas }) => {
{`${baseURL}/chatbot/${chatflowid}`}
{
navigator.clipboard.writeText(`${baseURL}/chatbot/${chatflowid}`)
@@ -441,7 +445,11 @@ const ShareChatbot = ({ isSessionMemory, isAgentCanvas }) => {
>
- window.open(`${baseURL}/chatbot/${chatflowid}`, '_blank')}>
+ window.open(`${baseURL}/chatbot/${chatflowid}`, '_blank')}
+ >
@@ -454,86 +462,100 @@ const ShareChatbot = ({ isSessionMemory, isAgentCanvas }) => {
onSwitchChange(event.target.checked)
}}
/>
- Make Public
-
+ {t('chatflows.actions.makePublic.title')}
+
- Title Settings
+ {t('chatflows.cards.titleSettings')}
- {textField(title, 'title', 'Title', 'string', 'Flowise Assistant')}
+ {textField(title, 'title', t('chatflows.inputs.title.title'), 'string', t('chatflows.inputs.title.placeholder'))}
{textField(
titleAvatarSrc,
'titleAvatarSrc',
- 'Title Avatar Link',
+ t('chatflows.inputs.titleAvatarSrc.title'),
'string',
`https://raw.githubusercontent.com/FlowiseAI/Flowise/main/assets/FloWiseAI_dark.png`
)}
- {colorField(titleBackgroundColor, 'titleBackgroundColor', 'Title Background Color')}
- {colorField(titleTextColor, 'titleTextColor', 'Title TextColor')}
+ {colorField(titleBackgroundColor, 'titleBackgroundColor', t('chatflows.inputs.titleBackgroundColor.title'))}
+ {colorField(titleTextColor, 'titleTextColor', t('chatflows.inputs.titleTextColor.title'))}
- General Settings
+ {t('chatflows.cards.generalSettings')}
- {textField(welcomeMessage, 'welcomeMessage', 'Welcome Message', 'string', 'Hello! This is custom welcome message')}
- {textField(errorMessage, 'errorMessage', 'Error Message', 'string', 'This is custom error message')}
- {colorField(backgroundColor, 'backgroundColor', 'Background Color')}
- {textField(fontSize, 'fontSize', 'Font Size', 'number')}
- {colorField(poweredByTextColor, 'poweredByTextColor', 'PoweredBy TextColor')}
- {isAgentCanvas && booleanField(showAgentMessages, 'showAgentMessages', 'Show agent reasonings when using Agentflow')}
- {booleanField(renderHTML, 'renderHTML', 'Render HTML on the chat')}
- {isSessionMemory &&
- booleanField(generateNewSession, 'generateNewSession', 'Start new session when chatbot link is opened or refreshed')}
+ {textField(
+ welcomeMessage,
+ 'welcomeMessage',
+ t('chatflows.inputs.welcomeMessage.title'),
+ 'string',
+ t('chatflows.inputs.welcomeMessage.placeholder')
+ )}
+ {textField(
+ errorMessage,
+ 'errorMessage',
+ t('chatflows.inputs.errorMessage.title'),
+ 'string',
+ t('chatflows.inputs.errorMessage.placeholder')
+ )}
+ {colorField(backgroundColor, 'backgroundColor', t('chatflows.inputs.backgroundColor.title'))}
+ {textField(fontSize, 'fontSize', t('chatflows.inputs.fontSize.title'), 'number')}
+ {colorField(poweredByTextColor, 'poweredByTextColor', t('chatflows.inputs.poweredByTextColor.title'))}
+ {isAgentCanvas && booleanField(showAgentMessages, 'showAgentMessages', t('chatflows.inputs.showAgentMessages.title'))}
+ {booleanField(renderHTML, 'renderHTML', t('chatflows.inputs.renderHTML.title'))}
+ {isSessionMemory && booleanField(generateNewSession, 'generateNewSession', t('chatflows.inputs.generateNewSession.title'))}
- Bot Message
+ {t('chatflows.cards.botMessage')}
- {colorField(botMessageBackgroundColor, 'botMessageBackgroundColor', 'Background Color')}
- {colorField(botMessageTextColor, 'botMessageTextColor', 'Text Color')}
+ {colorField(botMessageBackgroundColor, 'botMessageBackgroundColor', t('chatflows.inputs.backgroundColor.title'))}
+ {colorField(botMessageTextColor, 'botMessageTextColor', t('chatflows.inputs.textColor.title'))}
{textField(
botMessageAvatarSrc,
'botMessageAvatarSrc',
- 'Avatar Link',
+ t('chatflows.inputs.avatarSrc.title'),
'string',
`https://raw.githubusercontent.com/zahidkhawaja/langchain-chat-nextjs/main/public/parroticon.png`
)}
- {booleanField(botMessageShowAvatar, 'botMessageShowAvatar', 'Show Avatar')}
+ {booleanField(botMessageShowAvatar, 'botMessageShowAvatar', t('chatflows.inputs.showAvatar.title'))}
- User Message
+ {t('chatflows.cards.userMessage')}
- {colorField(userMessageBackgroundColor, 'userMessageBackgroundColor', 'Background Color')}
- {colorField(userMessageTextColor, 'userMessageTextColor', 'Text Color')}
+ {colorField(userMessageBackgroundColor, 'userMessageBackgroundColor', t('chatflows.inputs.backgroundColor.title'))}
+ {colorField(userMessageTextColor, 'userMessageTextColor', t('chatflows.inputs.textColor.title'))}
{textField(
userMessageAvatarSrc,
'userMessageAvatarSrc',
- 'Avatar Link',
+ t('chatflows.inputs.avatarSrc.title'),
'string',
`https://raw.githubusercontent.com/zahidkhawaja/langchain-chat-nextjs/main/public/usericon.png`
)}
- {booleanField(userMessageShowAvatar, 'userMessageShowAvatar', 'Show Avatar')}
+ {booleanField(userMessageShowAvatar, 'userMessageShowAvatar', t('chatflows.inputs.showAvatar.title'))}
- Text Input
+ {t('chatflows.cards.textInput')}
- {colorField(textInputBackgroundColor, 'textInputBackgroundColor', 'Background Color')}
- {colorField(textInputTextColor, 'textInputTextColor', 'Text Color')}
- {textField(textInputPlaceholder, 'textInputPlaceholder', 'TextInput Placeholder', 'string', `Type question..`)}
- {colorField(textInputSendButtonColor, 'textInputSendButtonColor', 'TextIntput Send Button Color')}
+ {colorField(textInputBackgroundColor, 'textInputBackgroundColor', t('chatflows.inputs.backgroundColor.title'))}
+ {colorField(textInputTextColor, 'textInputTextColor', t('chatflows.inputs.textColor.title'))}
+ {textField(
+ textInputPlaceholder,
+ 'textInputPlaceholder',
+ t('chatflows.inputs.textInputPlaceholder.title'),
+ 'string',
+ t('chatflows.inputs.textInputPlaceholder.placeholder')
+ )}
+ {colorField(textInputSendButtonColor, 'textInputSendButtonColor', t('chatflows.inputs.textInputSendButtonColor.title'))}
{
variant='contained'
onClick={() => onSave()}
>
- Save Changes
+ {t('chatflows.actions.saveChanges')}
{
}}
>
- Copied!
+ {t('common.messages.copied')}
>
diff --git a/packages/ui/src/views/chatflows/index.jsx b/packages/ui/src/views/chatflows/index.jsx
index 3a094b54e4f..4fef71dce34 100644
--- a/packages/ui/src/views/chatflows/index.jsx
+++ b/packages/ui/src/views/chatflows/index.jsx
@@ -30,9 +30,13 @@ import { useError } from '@/store/context/ErrorContext'
// icons
import { IconLayoutGrid, IconList, IconPlus } from '@tabler/icons-react'
+// i18n
+import { useTranslation } from 'react-i18next'
+
// ==============================|| CHATFLOWS ||============================== //
const Chatflows = () => {
+ const { t } = useTranslation()
const navigate = useNavigate()
const theme = useTheme()
@@ -138,9 +142,9 @@ const Chatflows = () => {
{
}}
variant='contained'
value='card'
- title='Card View'
+ title={t('common.actions.cardView')}
>
@@ -170,7 +174,7 @@ const Chatflows = () => {
}}
variant='contained'
value='list'
- title='List View'
+ title={t('common.actions.listView')}
>
@@ -182,7 +186,7 @@ const Chatflows = () => {
startIcon={}
sx={{ borderRadius: 2, height: 40 }}
>
- Add New
+ {t('common.actions.addNew')}
@@ -226,7 +230,7 @@ const Chatflows = () => {
alt='WorkflowEmptySVG'
/>
-
No Chatflows Yet
+
{t('chatflows.notFound')}
)}
diff --git a/packages/ui/src/views/chatmessage/AgentExecutedDataCard.jsx b/packages/ui/src/views/chatmessage/AgentExecutedDataCard.jsx
index f4559b67b62..f3f08fb0d6f 100644
--- a/packages/ui/src/views/chatmessage/AgentExecutedDataCard.jsx
+++ b/packages/ui/src/views/chatmessage/AgentExecutedDataCard.jsx
@@ -47,6 +47,9 @@ import { useTheme } from '@mui/material/styles'
import { FLOWISE_CREDENTIAL_ID, AGENTFLOW_ICONS } from '@/store/constant'
import { NodeExecutionDetails } from '@/views/agentexecutions/NodeExecutionDetails'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const getIconColor = (status) => {
switch (status) {
case 'FINISHED':
@@ -116,6 +119,7 @@ const StyledTreeItemLabelText = styled(Typography)(({ theme }) => ({
}))
function CustomLabel({ icon: Icon, itemStatus, children, name, label, data, metadata, ...other }) {
+ const { t } = useTranslation()
const [openDialog, setOpenDialog] = useState(false)
const handleOpenDialog = (event) => {
@@ -179,7 +183,7 @@ function CustomLabel({ icon: Icon, itemStatus, children, name, label, data, meta
) : (
-
No data available for this item
+
{t('chatmessage.notFound')}
)}
-
+
@@ -325,6 +329,7 @@ CustomTreeItem.propTypes = {
CustomTreeItem.displayName = 'CustomTreeItem'
const AgentExecutedDataCard = ({ status, execution, agentflowId, sessionId }) => {
+ const { t } = useTranslation()
const [executionTree, setExecution] = useState([])
const [expandedItems, setExpandedItems] = useState([])
const [selectedItem, setSelectedItem] = useState(null)
@@ -411,7 +416,7 @@ const AgentExecutedDataCard = ({ status, execution, agentflowId, sessionId }) =>
// Create a virtual node for this iteration
const iterationNodeId = `${parentId}_${iterationIndex}`
- const iterationLabel = `Iteration #${iterationIndex}`
+ const iterationLabel = t('chatmessage.iteration', { index: iterationIndex })
// Determine status based on child nodes
const childNodes = nodeIds.map((id) => nodeMap.get(id))
@@ -718,7 +723,7 @@ const AgentExecutedDataCard = ({ status, execution, agentflowId, sessionId }) =>
fontWeight: 500
}}
>
- Process Flow
+ {t('chatmessage.processFlow')}
diff --git a/packages/ui/src/views/chatmessage/AgentReasoningCard.jsx b/packages/ui/src/views/chatmessage/AgentReasoningCard.jsx
index ef69b49b54e..4286316731e 100644
--- a/packages/ui/src/views/chatmessage/AgentReasoningCard.jsx
+++ b/packages/ui/src/views/chatmessage/AgentReasoningCard.jsx
@@ -4,6 +4,9 @@ import { MemoizedReactMarkdown } from '@/ui-component/markdown/MemoizedReactMark
import nextAgentGIF from '@/assets/images/next-agent.gif'
import PropTypes from 'prop-types'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const AgentReasoningCard = ({
agent,
index,
@@ -19,6 +22,7 @@ const AgentReasoningCard = ({
onURLClick,
getLabel
}) => {
+ const { t } = useTranslation()
if (agent.nextAgent) {
return (
}
- onClick={() => onSourceDialogClick(tool, 'Used Tools')}
+ onClick={() => onSourceDialogClick(tool, t('chatmessage.usedTools'))}
/>
) : null
})}
@@ -106,13 +110,13 @@ const AgentReasoningCard = ({
}
- onClick={() => onSourceDialogClick(agent.state, 'State')}
+ onClick={() => onSourceDialogClick(agent.state, t('common.labels.state'))}
/>
)}
@@ -137,7 +141,7 @@ const AgentReasoningCard = ({
)}
{agent.instructions &&
{agent.instructions}
}
- {agent.messages.length === 0 && !agent.instructions &&
Finished
}
+ {agent.messages.length === 0 && !agent.instructions &&
{t('chatmessage.finished')}
}
{agent.sourceDocuments && agent.sourceDocuments.length > 0 && (
{removeDuplicateURL(agent).map((source, index) => {
diff --git a/packages/ui/src/views/chatmessage/ChatExpandDialog.jsx b/packages/ui/src/views/chatmessage/ChatExpandDialog.jsx
index 702d778de9d..7a1216aaf02 100644
--- a/packages/ui/src/views/chatmessage/ChatExpandDialog.jsx
+++ b/packages/ui/src/views/chatmessage/ChatExpandDialog.jsx
@@ -7,7 +7,11 @@ import ChatMessage from './ChatMessage'
import { StyledButton } from '@/ui-component/button/StyledButton'
import { IconEraser } from '@tabler/icons-react'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const ChatExpandDialog = ({ show, dialogProps, isAgentCanvas, onClear, onCancel, previews, setPreviews }) => {
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const customization = useSelector((state) => state.customization)
@@ -29,16 +33,22 @@ const ChatExpandDialog = ({ show, dialogProps, isAgentCanvas, onClear, onCancel,
}
>
- Clear Chat
+ {t('chatmessage.actions.clearChat')}
)}
{!customization.isDarkMode && (
- }>
- Clear Chat
+ }
+ >
+ {t('chatmessage.actions.clearChat')}
)}
diff --git a/packages/ui/src/views/chatmessage/ChatMessage.jsx b/packages/ui/src/views/chatmessage/ChatMessage.jsx
index bf55a262022..9a46bde13fc 100644
--- a/packages/ui/src/views/chatmessage/ChatMessage.jsx
+++ b/packages/ui/src/views/chatmessage/ChatMessage.jsx
@@ -92,6 +92,8 @@ import FollowUpPromptsCard from '@/ui-component/cards/FollowUpPromptsCard'
// History
import { ChatInputHistory } from './ChatInputHistory'
+// i18n
+
const messageImageStyle = {
width: '128px',
height: '128px',
@@ -160,7 +162,7 @@ const CardWithDeleteOverlay = ({ item, disabled, customization, onDelete }) => {
disabled={disabled}
onClick={() => onDelete(item)}
startIcon={
}
- title='Remove attachment'
+ title={t('chatmessage.actions.removeAttachment')}
sx={{
position: 'absolute',
top: 0,
@@ -338,7 +340,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
}
}
if (!acceptFile) {
- alert(`Cannot upload file. Kindly check the allowed file types and maximum allowed size.`)
+ alert(t('chatmessage.errors.cannotUpload'))
}
return acceptFile
}
@@ -827,7 +829,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
inputRef.current?.focus()
}, 100)
enqueueSnackbar({
- message: 'Message stopped',
+ message: t('chatmessage.messages.message.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -840,8 +842,12 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
})
}
- const handleError = (message = 'Oops! There seems to be an error. Please try again.') => {
- message = message.replace(`Unable to parse JSON response from chat agent.\n\n`, '')
+ const handleError = (message) => {
+ if (!message) {
+ message = t('chatmessage.errors.tryAgain')
+ } else {
+ message = message.replace(`Unable to parse JSON response from chat agent.\n\n`, '')
+ }
setMessages((prevMessages) => [...prevMessages, { message, type: 'apiMessage' }])
setLoading(false)
setUserInput('')
@@ -1046,7 +1052,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
try {
uploads = await handleFileUploads(uploads)
} catch (error) {
- handleError('Unable to upload documents')
+ handleError(t('chatmessage.errors.unableUpload'))
return
}
@@ -1701,8 +1707,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
setMessages((prevMessages) => {
let allMessages = [...cloneDeep(prevMessages)]
if (allMessages[allMessages.length - 1].type !== 'leadCaptureMessage') return allMessages
- allMessages[allMessages.length - 1].message =
- leadsConfig.successMessage || 'Thank you for submitting your contact information.'
+ allMessages[allMessages.length - 1].message = leadsConfig.successMessage || t('chatmessage.submitting')
return allMessages
})
}
@@ -1857,7 +1862,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
} else {
console.error('Error with TTS:', error)
enqueueSnackbar({
- message: `TTS failed: ${error.message}`,
+ message: t('chatmessage.messages.tts.error', { msg: error.message }),
options: { variant: 'error' }
})
}
@@ -2386,10 +2391,10 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
}}
>
- {formTitle || 'Please Fill Out The Form'}
+ {formTitle || t('chatmessage.fillForm')}
- {formDescription || 'Complete all fields below to continue'}
+ {formDescription || t('chatmessage.completeForm')}
{/* Form inputs */}
@@ -2426,7 +2431,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
background: 'linear-gradient(45deg, #673ab7 30%, #1e88e5 90%)'
}}
>
- {loading ? 'Submitting...' : 'Submit'}
+ {t(loading ? 'chatmessage.submittingLoading' : 'common.actions.submit')}
@@ -2448,7 +2453,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
{isDragActive &&
(getAllowChatFlowUploads.data?.isImageUploadAllowed || getAllowChatFlowUploads.data?.isRAGFileUploadAllowed) && (
- Drop here to upload
+ {t('chatmessage.dragDrop.here')}
{[
...getAllowChatFlowUploads.data.imgUploadSizeAndTypes,
...getAllowChatFlowUploads.data.fileUploadSizeAndTypes
@@ -2457,7 +2462,9 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
<>
{allowed.fileTypes?.join(', ')}
{allowed.maxUploadSize && (
- Max Allowed Size: {allowed.maxUploadSize} MB
+
+ {t('chatmessage.dragDrop.maxSize', { size: allowed.maxUploadSize })}
+
)}
>
)
@@ -2587,7 +2594,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
variant='outlined'
clickable
icon={}
- onClick={() => onSourceDialogClick(tool, 'Called Tools')}
+ onClick={() => onSourceDialogClick(tool, t('chatmessage.calledTools'))}
/>
) : null
})}
@@ -2622,7 +2629,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
color={tool.error ? theme.palette.error.main : undefined}
/>
}
- onClick={() => onSourceDialogClick(tool, 'Used Tools')}
+ onClick={() => onSourceDialogClick(tool, t('chatmessage.usedTools'))}
/>
) : null
})}
@@ -2655,7 +2662,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
}}
>
- {leadsConfig.title || 'Let us know where we can reach you:'}
+ {leadsConfig.title || t('chatmessage.know')}
@@ -2940,7 +2947,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
- Try these prompts
+ {t('chatmessage.tryThese')}
-
- To record audio, use modern browsers like Chrome or Firefox that support audio recording.
-
+ {t('chatmessage.unsupproted')}
@@ -3002,7 +3007,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
00:00
- {isLoadingRecording && Sending...}
+ {isLoadingRecording && {t('chatmessage.sendingLoading')}}
@@ -3030,7 +3035,7 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
onKeyDown={handleEnter}
id='userInput'
name='userInput'
- placeholder={loading ? 'Waiting for response...' : 'Type your question...'}
+ placeholder={t(loading ? 'chatmessage.waitingResponse' : 'chatmessage.typeQuestion')}
value={userInput}
onChange={onChange}
multiline={true}
@@ -3149,7 +3154,9 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
handleAbort()}
disabled={isMessageStopping}
@@ -3208,13 +3215,13 @@ const ChatMessage = ({ open, chatflowid, isAgentCanvas, isDialog, previews, setP
setFeedback('')
}}
>
- Provide Feedback
+ {t('chatmessage.provideFeedback')}
-
+
diff --git a/packages/ui/src/views/chatmessage/ChatPopUp.jsx b/packages/ui/src/views/chatmessage/ChatPopUp.jsx
index 1731feb7eca..16d96de423a 100644
--- a/packages/ui/src/views/chatmessage/ChatPopUp.jsx
+++ b/packages/ui/src/views/chatmessage/ChatPopUp.jsx
@@ -27,7 +27,11 @@ import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackba
// Utils
import { getLocalStorageChatflow, removeLocalStorageChatHistory } from '@/utils/genericHelper'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange }) => {
+ const { t } = useTranslation()
const theme = useTheme()
const { confirm } = useConfirm()
const dispatch = useDispatch()
@@ -86,10 +90,10 @@ const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange }) => {
const clearChat = async () => {
const confirmPayload = {
- title: `Clear Chat History`,
- description: `Are you sure you want to clear all chat history?`,
- confirmButtonName: 'Clear',
- cancelButtonName: 'Cancel'
+ title: t('chatmessage.actions.clearHistory.title'),
+ description: t('chatmessage.actions.clearHistory.description'),
+ confirmButtonName: t('common.actions.clear'),
+ cancelButtonName: t('common.actions.cancel')
}
const isConfirmed = await confirm(confirmPayload)
@@ -101,7 +105,7 @@ const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange }) => {
removeLocalStorageChatHistory(chatflowid)
resetChatDialog()
enqueueSnackbar({
- message: 'Succesfully cleared all chat history',
+ message: t('chatmessage.messages.clear.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -147,8 +151,8 @@ const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange }) => {
ref={anchorRef}
size='small'
color='secondary'
- aria-label='chat'
- title='Chat'
+ aria-label={t('chatmessage.actions.chat')}
+ title={t('chatmessage.actions.chat')}
onClick={handleToggle}
>
{open ? : }
@@ -160,8 +164,8 @@ const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange }) => {
onClick={clearChat}
size='small'
color='error'
- aria-label='clear'
- title='Clear Chat History'
+ aria-label={t('common.actions.clear')}
+ title={t('chatmessage.actions.clearHistory.title')}
>
@@ -172,8 +176,8 @@ const ChatPopUp = ({ chatflowid, isAgentCanvas, onOpenChange }) => {
onClick={expandChat}
size='small'
color='primary'
- aria-label='expand'
- title='Expand Chat'
+ aria-label={t('common.actions.expand')}
+ title={t('chatmessage.actions.expandChat')}
>
diff --git a/packages/ui/src/views/chatmessage/ThinkingCard.jsx b/packages/ui/src/views/chatmessage/ThinkingCard.jsx
index 4c5b3771cd9..11aebee446f 100644
--- a/packages/ui/src/views/chatmessage/ThinkingCard.jsx
+++ b/packages/ui/src/views/chatmessage/ThinkingCard.jsx
@@ -4,7 +4,11 @@ import { Box, Collapse, Typography, CircularProgress } from '@mui/material'
import { useTheme } from '@mui/material/styles'
import { IconChevronDown, IconChevronRight, IconBrain } from '@tabler/icons-react'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const ThinkingCard = ({ thinking, thinkingDuration, isThinking, customization }) => {
+ const { t } = useTranslation()
const theme = useTheme()
const [isExpanded, setIsExpanded] = useState(false)
@@ -30,12 +34,12 @@ const ThinkingCard = ({ thinking, thinkingDuration, isThinking, customization })
// Determine header text
const getHeaderText = () => {
if (isThinking) {
- return 'Thinking...'
+ return t('chatmessage.thinking.loading')
}
if (thinkingDuration !== undefined && thinkingDuration !== null) {
- return `Thought for ${thinkingDuration} second${thinkingDuration !== 1 ? 's' : ''}`
+ return t('chatmessage.thinking.done', { count: thinkingDuration })
}
- return 'Thinking...'
+ return t('chatmessage.thinking.loading')
}
return (
diff --git a/packages/ui/src/views/chatmessage/ValidationPopUp.jsx b/packages/ui/src/views/chatmessage/ValidationPopUp.jsx
index 1cd9b97c2f4..d2a5b7d109e 100644
--- a/packages/ui/src/views/chatmessage/ValidationPopUp.jsx
+++ b/packages/ui/src/views/chatmessage/ValidationPopUp.jsx
@@ -22,9 +22,13 @@ import useNotifier from '@/utils/useNotifier'
import { enqueueSnackbar as enqueueSnackbarAction } from '@/store/actions'
import { AGENTFLOW_ICONS } from '@/store/constant'
+// i18n
+import { useTranslation } from 'react-i18next'
+
// Utils
const ValidationPopUp = ({ chatflowid, hidden }) => {
+ const { t } = useTranslation()
const theme = useTheme()
const dispatch = useDispatch()
const customization = useSelector((state) => state.customization)
@@ -60,7 +64,7 @@ const ValidationPopUp = ({ chatflowid, hidden }) => {
if (response.data.length === 0) {
enqueueSnackbar({
- message: 'No issues found in your flow!',
+ message: t('chatmessage.messages.validation.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -71,7 +75,7 @@ const ValidationPopUp = ({ chatflowid, hidden }) => {
} catch (error) {
console.error(error)
enqueueSnackbar({
- message: error.message || 'Failed to validate flow',
+ message: error.message || t('chatmessage.messages.validation.error'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -145,8 +149,8 @@ const ValidationPopUp = ({ chatflowid, hidden }) => {
ref={anchorRef}
size='small'
color='teal'
- aria-label='validation'
- title='Validate Nodes'
+ aria-label={t('chatmessage.actions.validation')}
+ title={t('chatmessage.actions.validateNodes')}
onClick={handleToggle}
>
{open ? : }
@@ -189,7 +193,7 @@ const ValidationPopUp = ({ chatflowid, hidden }) => {
shadow={theme.shadows[16]}
>
- Checklist ({previews.length})
+ {t('chatmessage.checklist', { count: previews.length })}
{
startIcon={loading ? null : }
sx={{ color: 'white', minWidth: '120px' }}
>
- {loading ? 'Validating...' : 'Validate Flow'}
+ {t(
+ loading
+ ? 'chatmessage.actions.validateFlow.loading'
+ : 'chatmessage.actions.validateFlow.title'
+ )}
diff --git a/packages/ui/src/views/credentials/AddEditCredentialDialog.jsx b/packages/ui/src/views/credentials/AddEditCredentialDialog.jsx
index fecdb30a74f..20d09cd5a20 100644
--- a/packages/ui/src/views/credentials/AddEditCredentialDialog.jsx
+++ b/packages/ui/src/views/credentials/AddEditCredentialDialog.jsx
@@ -32,7 +32,11 @@ import { baseURL, REDACTED_CREDENTIAL_VALUE } from '@/store/constant'
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from '@/store/actions'
import keySVG from '@/assets/images/key.svg'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setError }) => {
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const dispatch = useDispatch()
@@ -127,7 +131,7 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
const createResp = await credentialsApi.createCredential(obj)
if (createResp.data) {
enqueueSnackbar({
- message: 'New Credential added',
+ message: t('credentials.messages.add.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -143,9 +147,9 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
} catch (error) {
if (setError) setError(error)
enqueueSnackbar({
- message: `Failed to add new Credential: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('credentials.messages.add.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -179,7 +183,7 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
const saveResp = await credentialsApi.updateCredential(credential.id, saveObj)
if (saveResp.data) {
enqueueSnackbar({
- message: 'Credential saved',
+ message: t('credentials.messages.save.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -195,9 +199,9 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
} catch (error) {
if (setError) setError(error)
enqueueSnackbar({
- message: `Failed to save Credential: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('credentials.messages.save.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -276,7 +280,7 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
if (event.data.type === 'OAUTH2_SUCCESS') {
enqueueSnackbar({
- message: 'OAuth2 authorization completed successfully',
+ message: t('credentials.messages.setOAuth2.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -290,7 +294,7 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
onConfirm(credentialId)
} else if (event.data.type === 'OAUTH2_ERROR') {
enqueueSnackbar({
- message: event.data.message || 'OAuth2 authorization failed',
+ message: event.data.message || t('credentials.messages.setOAuth2.errors.simple'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -341,7 +345,9 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
console.error('OAuth2 authorization error:', error)
if (setError) setError(error)
enqueueSnackbar({
- message: `OAuth2 authorization failed: ${error.response?.data?.message || error.message || 'Unknown error'}`,
+ message: t('credentials.messages.setOAuth2.errors.withMsg', {
+ msg: error.response?.data?.message || error.message || t('common.errors.unknownError')
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -419,7 +425,7 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
}}
>
- Cannot edit shared credential.
+ {t('credentials.cannotShare')}
)}
@@ -444,7 +450,7 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
- Credential Name
+ {t('credentials.inputs.credentialName')}
*
@@ -462,7 +468,7 @@ const AddEditCredentialDialog = ({ show, dialogProps, onCancel, onConfirm, setEr
{!shared && componentCredential && componentCredential.name && componentCredential.name.includes('OAuth2') && (
- OAuth Redirect URL
+ {t('credentials.inputs.oAuthRedirectUrl')}
)}
diff --git a/packages/ui/src/views/credentials/CredentialInputHandler.jsx b/packages/ui/src/views/credentials/CredentialInputHandler.jsx
index 26411168865..38e81dee299 100644
--- a/packages/ui/src/views/credentials/CredentialInputHandler.jsx
+++ b/packages/ui/src/views/credentials/CredentialInputHandler.jsx
@@ -13,9 +13,13 @@ import { SwitchInput } from '@/ui-component/switch/Switch'
import { JsonEditorInput } from '@/ui-component/json/JsonEditor'
import { TooltipWithParser } from '@/ui-component/tooltip/TooltipWithParser'
+// i18n
+import { useTranslation } from 'react-i18next'
+
// ===========================|| NodeInputHandler ||=========================== //
const CredentialInputHandler = ({ inputParam, data, disabled = false }) => {
+ const { t } = useTranslation()
const customization = useSelector((state) => state.customization)
const ref = useRef(null)
@@ -27,8 +31,8 @@ const CredentialInputHandler = ({ inputParam, data, disabled = false }) => {
value,
inputParam,
disabled,
- confirmButtonName: 'Save',
- cancelButtonName: 'Cancel'
+ confirmButtonName: t('common.actions.save'),
+ cancelButtonName: t('common.actions.cancel')
}
setExpandDialogProps(dialogProp)
setShowExpandDialog(true)
@@ -58,7 +62,7 @@ const CredentialInputHandler = ({ inputParam, data, disabled = false }) => {
height: 25,
width: 25
}}
- title='Expand'
+ title={t('common.actions.expand')}
color='primary'
onClick={() => onExpandDialogClicked(data[inputParam.name] ?? inputParam.default ?? '', inputParam)}
>
@@ -117,7 +121,7 @@ const CredentialInputHandler = ({ inputParam, data, disabled = false }) => {
name={inputParam.name}
options={inputParam.options}
onSelect={(newValue) => (data[inputParam.name] = newValue)}
- value={data[inputParam.name] ?? inputParam.default ?? 'choose an option'}
+ value={data[inputParam.name] ?? inputParam.default ?? t('components.dropdown.chooseOption')}
/>
)}
diff --git a/packages/ui/src/views/credentials/CredentialListDialog.jsx b/packages/ui/src/views/credentials/CredentialListDialog.jsx
index edf5d6e23dd..d1f49b2e22d 100644
--- a/packages/ui/src/views/credentials/CredentialListDialog.jsx
+++ b/packages/ui/src/views/credentials/CredentialListDialog.jsx
@@ -11,7 +11,11 @@ import { baseURL } from '@/store/constant'
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from '@/store/actions'
import keySVG from '@/assets/images/key.svg'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const CredentialListDialog = ({ show, dialogProps, onCancel, onCredentialSelected }) => {
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const dispatch = useDispatch()
const theme = useTheme()
@@ -70,7 +74,7 @@ const CredentialListDialog = ({ show, dialogProps, onCancel, onCredentialSelecte
id='input-search-credential'
value={searchValue}
onChange={(e) => filterSearch(e.target.value)}
- placeholder='Search credential'
+ placeholder={t('credentials.inputs.search')}
startAdornment={
@@ -86,7 +90,7 @@ const CredentialListDialog = ({ show, dialogProps, onCancel, onCredentialSelecte
color: theme.palette.grey[900]
}
}}
- title='Clear Search'
+ title={t('common.actions.clearSearch')}
>
diff --git a/packages/ui/src/views/credentials/index.jsx b/packages/ui/src/views/credentials/index.jsx
index 3ab68e34bc9..c5d19616162 100644
--- a/packages/ui/src/views/credentials/index.jsx
+++ b/packages/ui/src/views/credentials/index.jsx
@@ -51,6 +51,9 @@ import { SET_COMPONENT_CREDENTIALS } from '@/store/actions'
import { useError } from '@/store/context/ErrorContext'
import ShareWithWorkspaceDialog from '@/ui-component/dialog/ShareWithWorkspaceDialog'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const StyledTableCell = styled(TableCell)(({ theme }) => ({
borderColor: theme.palette.grey[900] + 25,
padding: '6px 16px',
@@ -74,6 +77,7 @@ const StyledTableRow = styled(TableRow)(() => ({
// ==============================|| Credentials ||============================== //
const Credentials = () => {
+ const { t } = useTranslation()
const theme = useTheme()
const customization = useSelector((state) => state.customization)
const dispatch = useDispatch()
@@ -109,7 +113,7 @@ const Credentials = () => {
const listCredential = () => {
const dialogProp = {
- title: 'Add New Credential',
+ title: t('credentials.dialogs.add'),
componentsCredentials
}
setCredentialListDialogProps(dialogProp)
@@ -119,8 +123,8 @@ const Credentials = () => {
const addNew = (credentialComponent) => {
const dialogProp = {
type: 'ADD',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Add',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('common.actions.add'),
credentialComponent
}
setSpecificCredentialDialogProps(dialogProp)
@@ -130,8 +134,8 @@ const Credentials = () => {
const edit = (credential) => {
const dialogProp = {
type: 'EDIT',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Save',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('common.actions.save'),
data: credential
}
setSpecificCredentialDialogProps(dialogProp)
@@ -141,12 +145,12 @@ const Credentials = () => {
const share = (credential) => {
const dialogProps = {
type: 'EDIT',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Share',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('common.actions.share'),
data: {
id: credential.id,
name: credential.name,
- title: 'Share Credential',
+ title: t('credentials.dialogs.share'),
itemType: 'credential'
}
}
@@ -156,10 +160,10 @@ const Credentials = () => {
const deleteCredential = async (credential) => {
const confirmPayload = {
- title: `Delete`,
- description: `Delete credential ${credential.name}?`,
- confirmButtonName: 'Delete',
- cancelButtonName: 'Cancel'
+ title: t('common.dialogs.delete'),
+ description: t('credentials.dialogs.delete.description', { name: credential.name }),
+ confirmButtonName: t('common.actions.delete'),
+ cancelButtonName: t('common.actions.cancel')
}
const isConfirmed = await confirm(confirmPayload)
@@ -168,7 +172,7 @@ const Credentials = () => {
const deleteResp = await credentialsApi.deleteCredential(credential.id)
if (deleteResp.data) {
enqueueSnackbar({
- message: 'Credential deleted',
+ message: t('credentials.messages.delete.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -183,9 +187,9 @@ const Credentials = () => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to delete Credential: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('credentials.messages.delete.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -245,9 +249,9 @@ const Credentials = () => {
{
onClick={listCredential}
startIcon={}
>
- Add Credential
+ {t('credentials.actions.addCredential')}
{!isLoading && credentials.length <= 0 ? (
@@ -268,7 +272,7 @@ const Credentials = () => {
alt='CredentialEmptySVG'
/>
- No Credentials Yet
+ {t('credentials.notFound')}
) : (
{
}}
>
- Name
- Last Updated
- Created
+ {t('common.labels.name')}
+ {t('credentials.table.lastUpdated')}
+ {t('credentials.table.created')}
@@ -380,10 +384,14 @@ const Credentials = () => {
- {moment(credential.updatedDate).format('MMMM Do, YYYY HH:mm:ss')}
+ {moment(credential.updatedDate).format(
+ t('common.formats.dateMonthDayYearTime24Long')
+ )}
- {moment(credential.createdDate).format('MMMM Do, YYYY HH:mm:ss')}
+ {moment(credential.createdDate).format(
+ t('common.formats.dateMonthDayYearTime24Long')
+ )}
{!credential.shared && (
<>
@@ -391,7 +399,7 @@ const Credentials = () => {
share(credential)}
>
@@ -401,7 +409,7 @@ const Credentials = () => {
edit(credential)}
>
@@ -411,7 +419,7 @@ const Credentials = () => {
deleteCredential(credential)}
>
@@ -422,7 +430,9 @@ const Credentials = () => {
)}
{credential.shared && (
<>
- Shared Credential
+
+ {t('credentials.table.title')}
+
>
)}
diff --git a/packages/ui/src/views/datasets/AddEditDatasetDialog.jsx b/packages/ui/src/views/datasets/AddEditDatasetDialog.jsx
index babb70eb5bb..09403e5c490 100644
--- a/packages/ui/src/views/datasets/AddEditDatasetDialog.jsx
+++ b/packages/ui/src/views/datasets/AddEditDatasetDialog.jsx
@@ -25,17 +25,14 @@ import datasetApi from '@/api/dataset'
// utils
import useNotifier from '@/utils/useNotifier'
+// i18n
+import { useTranslation } from 'react-i18next'
+
// const
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from '@/store/actions'
-const CSVFORMAT = `Only the first 2 columns will be considered:
-----------------------------
-| Input | Output |
-----------------------------
-| test input | test output |
-----------------------------
-`
const AddEditDatasetDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const dispatch = useDispatch()
@@ -94,7 +91,7 @@ const AddEditDatasetDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
const createResp = await datasetApi.createDataset(obj)
if (createResp.data) {
enqueueSnackbar({
- message: 'New Dataset added',
+ message: t('datasets.messages.addDataset.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -109,9 +106,9 @@ const AddEditDatasetDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to add new Dataset: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('datasets.messages.addDataset.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -137,7 +134,7 @@ const AddEditDatasetDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
const saveResp = await datasetApi.updateDataset(dataset.id, saveObj)
if (saveResp.data) {
enqueueSnackbar({
- message: 'Dataset saved',
+ message: t('datasets.messages.saveDataset.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -152,9 +149,9 @@ const AddEditDatasetDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to save Dataset: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('datasets.messages.saveDataset.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -182,14 +179,15 @@ const AddEditDatasetDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
- {dialogProps.type === 'ADD' ? 'Add Dataset' : 'Edit Dataset'}
+ {t(dialogProps.type === 'ADD' ? 'datasets.dialogs.addDataset' : 'datasets.dialogs.editDataset')}
- Name *
+ {t('common.labels.name')}
+ *
@@ -205,7 +203,7 @@ const AddEditDatasetDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
-
Description
+
{t('common.labels.description')}
{
- Upload CSV
- ${CSVFORMAT}`} />
+ {t('datasets.inputs.uploadCsv.title')}
+ ${t('datasets.inputs.uploadCsv.tooltip')}`}
+ />
@@ -233,13 +234,9 @@ const AddEditDatasetDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
disabled={false}
fileType='.csv'
onChange={(newValue) => setSelectedFile(newValue)}
- value={selectedFile ?? 'Choose a file to upload'}
- />
-
+
)}
diff --git a/packages/ui/src/views/datasets/AddEditDatasetRowDialog.jsx b/packages/ui/src/views/datasets/AddEditDatasetRowDialog.jsx
index 920a33a6c25..e8f55f9a717 100644
--- a/packages/ui/src/views/datasets/AddEditDatasetRowDialog.jsx
+++ b/packages/ui/src/views/datasets/AddEditDatasetRowDialog.jsx
@@ -25,7 +25,11 @@ import useNotifier from '@/utils/useNotifier'
// const
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from '@/store/actions'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const AddEditDatasetRowDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const dispatch = useDispatch()
@@ -83,7 +87,7 @@ const AddEditDatasetRowDialog = ({ show, dialogProps, onCancel, onConfirm }) =>
const createResp = await datasetApi.createDatasetRow(obj)
if (createResp.data) {
enqueueSnackbar({
- message: 'New Row added for the given Dataset',
+ message: t('datasets.messages.addRow.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -98,9 +102,9 @@ const AddEditDatasetRowDialog = ({ show, dialogProps, onCancel, onConfirm }) =>
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to add new row in the Dataset: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('datasets.messages.addRow.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -126,7 +130,7 @@ const AddEditDatasetRowDialog = ({ show, dialogProps, onCancel, onConfirm }) =>
const saveResp = await datasetApi.updateDatasetRow(row.id, saveObj)
if (saveResp.data) {
enqueueSnackbar({
- message: 'Dataset Row saved',
+ message: t('datasets.messages.saveRow.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -141,9 +145,9 @@ const AddEditDatasetRowDialog = ({ show, dialogProps, onCancel, onConfirm }) =>
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to save Dataset Row: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('datasets.messages.saveRow.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -171,14 +175,17 @@ const AddEditDatasetRowDialog = ({ show, dialogProps, onCancel, onConfirm }) =>
- {dialogProps.type === 'ADD' ? `Add Item to ${datasetName} Dataset` : `Edit Item in ${datasetName} Dataset`}
+ {t(dialogProps.type === 'ADD' ? `datasets.dialogs.addRow` : `datasets.dialogs.editRow`, {
+ name: datasetName
+ })}
- Input *
+ {t('datasets.inputs.input')}
+ *
@@ -198,7 +205,8 @@ const AddEditDatasetRowDialog = ({ show, dialogProps, onCancel, onConfirm }) =>
- Anticipated Output *
+ {t('datasets.inputs.anticipatedOutput')}
+ *
diff --git a/packages/ui/src/views/datasets/DatasetItems.jsx b/packages/ui/src/views/datasets/DatasetItems.jsx
index 868f17fe3b0..9515213df0b 100644
--- a/packages/ui/src/views/datasets/DatasetItems.jsx
+++ b/packages/ui/src/views/datasets/DatasetItems.jsx
@@ -47,9 +47,13 @@ import empty_datasetSVG from '@/assets/images/empty_datasets.svg'
import { IconTrash, IconPlus, IconX, IconUpload, IconArrowsDownUp } from '@tabler/icons-react'
import DragIndicatorIcon from '@mui/icons-material/DragIndicator'
+// i18n
+import { useTranslation } from 'react-i18next'
+
// ==============================|| Dataset Items ||============================== //
const EvalDatasetRows = () => {
+ const { t } = useTranslation()
const theme = useTheme()
const customization = useSelector((state) => state.customization)
const dispatch = useDispatch()
@@ -159,8 +163,8 @@ const EvalDatasetRows = () => {
const addNew = () => {
const dialogProp = {
type: 'ADD',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Add',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('common.actions.add'),
data: {
datasetId: datasetId,
datasetName: dataset.name
@@ -173,8 +177,8 @@ const EvalDatasetRows = () => {
const uploadCSV = () => {
const dialogProp = {
type: 'ADD',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Upload',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('datasets.actions.upload'),
data: {
datasetId: datasetId,
datasetName: dataset.name
@@ -187,8 +191,8 @@ const EvalDatasetRows = () => {
const editDs = () => {
const dialogProp = {
type: 'EDIT',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Save',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('common.actions.save'),
data: dataset
}
setDatasetDialogProps(dialogProp)
@@ -198,8 +202,8 @@ const EvalDatasetRows = () => {
const edit = (item) => {
const dialogProp = {
type: 'EDIT',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Save',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('common.actions.save'),
data: {
datasetName: dataset.name,
...item
@@ -211,10 +215,10 @@ const EvalDatasetRows = () => {
const deleteDatasetItems = async () => {
const confirmPayload = {
- title: `Delete`,
- description: `Delete ${selected.length} dataset items?`,
- confirmButtonName: 'Delete',
- cancelButtonName: 'Cancel'
+ title: t('common.dialogs.delete'),
+ description: t('datasets.dialogs.delete.description.items', { count: selected.length }),
+ confirmButtonName: t('common.actions.delete'),
+ cancelButtonName: t('common.actions.cancel')
}
const isConfirmed = await confirm(confirmPayload)
@@ -223,7 +227,7 @@ const EvalDatasetRows = () => {
const deleteResp = await datasetsApi.deleteDatasetItems(selected)
if (deleteResp.data) {
enqueueSnackbar({
- message: 'Dataset Items deleted',
+ message: t('datasets.messages.deleteRow.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -238,9 +242,9 @@ const EvalDatasetRows = () => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to delete dataset items: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('datasets.messages.deleteRow.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -295,7 +299,7 @@ const EvalDatasetRows = () => {
onEdit={editDs}
onBack={() => window.history.back()}
search={false}
- title={`Dataset : ${dataset?.name || ''}`}
+ title={t('datasets.dataset', { name: dataset?.name || '' })}
description={dataset?.description}
>
{
onClick={uploadCSV}
startIcon={}
>
- Upload CSV
+ {t('datasets.actions.uploadCsv')}
{
onClick={addNew}
startIcon={}
>
- New Item
+ {t('datasets.actions.newItem')}
{selected.length > 0 && (
@@ -327,7 +331,7 @@ const EvalDatasetRows = () => {
color='error'
startIcon={
}
>
- Delete {selected.length} {selected.length === 1 ? 'item' : 'items'}
+ {t('datasets.actions.deleteItem', { count: selected.length })}
)}
{!isLoading && dataset?.rows?.length <= 0 ? (
@@ -339,7 +343,7 @@ const EvalDatasetRows = () => {
alt='empty_datasetSVG'
/>
-
No Dataset Items Yet
+
{t('datasets.notFoundRows')}
{
startIcon={}
onClick={addNew}
>
- New Item
+ {t('datasets.actions.newItem')}
) : (
@@ -356,7 +360,7 @@ const EvalDatasetRows = () => {
sx={{ border: 1, borderColor: theme.palette.grey[900] + 25, borderRadius: 2 }}
component={Paper}
>
-
+
{
checked={selected.length === (dataset?.rows || []).length}
onChange={onSelectAllClick}
inputProps={{
- 'aria-label': 'select all'
+ 'aria-label': t('common.actions.selectAll')
}}
/>
- Input
- Expected Output
+ {t('datasets.table.input')}
+ {t('datasets.table.expectedOutput')}
@@ -470,7 +474,7 @@ const EvalDatasetRows = () => {
- Use the drag icon at (extreme right) to reorder the dataset items
+ {t('datasets.datasetTooltip')}
{/* Pagination and Page Size Controls */}
diff --git a/packages/ui/src/views/datasets/UploadCSVFileDialog.jsx b/packages/ui/src/views/datasets/UploadCSVFileDialog.jsx
index 355a0176725..3480b3e8079 100644
--- a/packages/ui/src/views/datasets/UploadCSVFileDialog.jsx
+++ b/packages/ui/src/views/datasets/UploadCSVFileDialog.jsx
@@ -25,15 +25,12 @@ import useNotifier from '@/utils/useNotifier'
// const
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from '@/store/actions'
-const CSVFORMAT = `Only the first 2 columns will be considered:
-----------------------------
-| Input | Output |
-----------------------------
-| test input | test output |
-----------------------------
-`
+
+// i18n
+import { useTranslation } from 'react-i18next'
const UploadCSVFileDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const dispatch = useDispatch()
@@ -81,7 +78,7 @@ const UploadCSVFileDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
const createResp = await datasetApi.createDatasetRow(obj)
if (createResp.data) {
enqueueSnackbar({
- message: 'New Row added for the given Dataset',
+ message: t('datasets.messages.addRow.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -96,9 +93,9 @@ const UploadCSVFileDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to add new row in the Dataset: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('datasets.messages.addRow.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -144,15 +141,15 @@ const UploadCSVFileDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
}}
/>
- {'Upload Items to [' + datasetName + '] Dataset'}
+ {t('datasets.dialogs.upload', { name: datasetName })}
- Upload CSV
- ${CSVFORMAT}`} />
+ {t('datasets.inputs.uploadCsv.title')}
+ ${t('datasets.inputs.uploadCsv.tooltip')}`} />
@@ -160,13 +157,9 @@ const UploadCSVFileDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
disabled={false}
fileType='.csv'
onChange={(newValue) => setSelectedFile(newValue)}
- value={selectedFile ?? 'Choose a file to upload'}
- />
-
+
diff --git a/packages/ui/src/views/datasets/index.jsx b/packages/ui/src/views/datasets/index.jsx
index 95fdfb1e305..ae374756f8e 100644
--- a/packages/ui/src/views/datasets/index.jsx
+++ b/packages/ui/src/views/datasets/index.jsx
@@ -49,9 +49,13 @@ import { truncateString } from '@/utils/genericHelper'
import { useError } from '@/store/context/ErrorContext'
+// i18n
+import { useTranslation } from 'react-i18next'
+
// ==============================|| Datasets ||============================== //
const EvalDatasets = () => {
+ const { t } = useTranslation()
const navigate = useNavigate()
const theme = useTheme()
const { confirm } = useConfirm()
@@ -101,8 +105,8 @@ const EvalDatasets = () => {
const addNew = () => {
const dialogProp = {
type: 'ADD',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Add',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('common.actions.add'),
data: {}
}
setDatasetDialogProps(dialogProp)
@@ -112,8 +116,8 @@ const EvalDatasets = () => {
const edit = (dataset) => {
const dialogProp = {
type: 'EDIT',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Save',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('common.actions.save'),
data: dataset
}
setDatasetDialogProps(dialogProp)
@@ -122,10 +126,10 @@ const EvalDatasets = () => {
const deleteDataset = async (dataset) => {
const confirmPayload = {
- title: `Delete`,
- description: `Delete dataset ${dataset.name}?`,
- confirmButtonName: 'Delete',
- cancelButtonName: 'Cancel'
+ title: t('common.dialogs.delete'),
+ description: t('datasets.dialogs.delete.description.datasets', { name: dataset.name }),
+ confirmButtonName: t('common.actions.delete'),
+ cancelButtonName: t('common.actions.cancel')
}
const isConfirmed = await confirm(confirmPayload)
@@ -134,7 +138,7 @@ const EvalDatasets = () => {
const deleteResp = await datasetsApi.deleteDataset(dataset.id)
if (deleteResp.data) {
enqueueSnackbar({
- message: 'Dataset deleted',
+ message: t('datasets.messages.deleteDataset.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -149,9 +153,9 @@ const EvalDatasets = () => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to delete dataset: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('datasets.messages.deleteDataset.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -205,7 +209,7 @@ const EvalDatasets = () => {
isEditButton={false}
onSearchChange={onSearchChange}
search={true}
- title='Datasets'
+ title={t('datasets.title')}
description=''
>
{
onClick={addNew}
startIcon={}
>
- Add New
+ {t('common.actions.addNew')}
{!isLoading && datasets.length <= 0 ? (
@@ -227,7 +231,7 @@ const EvalDatasets = () => {
alt='empty_datasetSVG'
/>
- No Datasets Yet
+ {t('datasets.notFoundDataset')}
) : (
<>
@@ -245,10 +249,10 @@ const EvalDatasets = () => {
}}
>
- Name
- Description
- Rows
- Last Updated
+ {t('common.labels.name')}
+ {t('common.labels.description')}
+ {t('datasets.table.rows')}
+ {t('datasets.table.lastUpdated')}
@@ -320,11 +324,17 @@ const EvalDatasets = () => {
goToRows(ds)}>{ds?.rowCount}
goToRows(ds)}>
- {moment(ds.updatedDate).format('MMMM Do YYYY, hh:mm A')}
+ {moment(ds.updatedDate).format(
+ t('common.formats.dateMonthDayYearTime12Short')
+ )}
- edit(ds)}>
+ edit(ds)}
+ >
@@ -332,7 +342,7 @@ const EvalDatasets = () => {
deleteDataset(ds)}
>
diff --git a/packages/ui/src/views/docstore/AddDocStoreDialog.jsx b/packages/ui/src/views/docstore/AddDocStoreDialog.jsx
index 0198c94984e..5cb8a18a4bd 100644
--- a/packages/ui/src/views/docstore/AddDocStoreDialog.jsx
+++ b/packages/ui/src/views/docstore/AddDocStoreDialog.jsx
@@ -25,7 +25,11 @@ import documentStoreApi from '@/api/documentstore'
// utils
import useNotifier from '@/utils/useNotifier'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const AddDocStoreDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const dispatch = useDispatch()
@@ -74,7 +78,7 @@ const AddDocStoreDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
const createResp = await documentStoreApi.createDocumentStore(obj)
if (createResp.data) {
enqueueSnackbar({
- message: 'New Document Store created.',
+ message: t('docstore.messages.create.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -93,9 +97,9 @@ const AddDocStoreDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to add new Document Store: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('docstore.messages.create.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -121,7 +125,7 @@ const AddDocStoreDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
const saveResp = await documentStoreApi.updateDocumentStore(docStoreId, saveObj)
if (saveResp.data) {
enqueueSnackbar({
- message: 'Document Store Updated!',
+ message: t('docstore.messages.update.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -140,9 +144,9 @@ const AddDocStoreDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
}
} catch (error) {
enqueueSnackbar({
- message: `Failed to update Document Store: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('docstore.messages.update.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -177,7 +181,8 @@ const AddDocStoreDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
- Name *
+ {t('common.labels.name')}
+ *
@@ -194,7 +199,7 @@ const AddDocStoreDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
-
Description
+
{t('common.labels.description')}
@@ -212,7 +217,7 @@ const AddDocStoreDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
-
+
{
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const customization = useSelector((state) => state.customization)
const dispatch = useDispatch()
@@ -83,7 +87,7 @@ const ComponentsListDialog = ({ show, dialogProps, onCancel, apiCall, onSelected
id='input-search-credential'
value={searchValue}
onChange={(e) => onSearchChange(e.target.value)}
- placeholder='Search'
+ placeholder={t('common.actions.search')}
startAdornment={
@@ -99,7 +103,7 @@ const ComponentsListDialog = ({ show, dialogProps, onCancel, apiCall, onSelected
color: theme.palette.grey[900]
}
}}
- title='Clear Search'
+ title={t('common.actions.clearSearch')}
>
diff --git a/packages/ui/src/views/docstore/DeleteDocStoreDialog.jsx b/packages/ui/src/views/docstore/DeleteDocStoreDialog.jsx
index 261d9a38af8..4b002a4011d 100644
--- a/packages/ui/src/views/docstore/DeleteDocStoreDialog.jsx
+++ b/packages/ui/src/views/docstore/DeleteDocStoreDialog.jsx
@@ -38,7 +38,11 @@ import nodesApi from '@/api/nodes'
import useApi from '@/hooks/useApi'
import { initNode } from '@/utils/genericHelper'
+// i18n
+import { useTranslation, Trans } from 'react-i18next'
+
const DeleteDocStoreDialog = ({ show, dialogProps, onCancel, onDelete }) => {
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const theme = useTheme()
const [nodeConfigExpanded, setNodeConfigExpanded] = useState({})
@@ -199,17 +203,20 @@ const DeleteDocStoreDialog = ({ show, dialogProps, onCancel, onDelete }) => {
>
- Note: Without a Record Manager configured, only the document chunks will be removed from the
- document store. The actual vector embeddings in your vector store database will remain unchanged. To enable
- automatic cleanup of vector store data, please configure a Record Manager.{' '}
-
- Learn more
-
+ ,
+ a: (
+
+ )
+ }}
+ />
)}
@@ -217,11 +224,11 @@ const DeleteDocStoreDialog = ({ show, dialogProps, onCancel, onDelete }) => {
- Configuration
+ {t('docstore.labels.configuration')}
-
+
@@ -294,10 +301,10 @@ const DeleteDocStoreDialog = ({ show, dialogProps, onCancel, onDelete }) => {
diff --git a/packages/ui/src/views/docstore/DocStoreAPIDialog.jsx b/packages/ui/src/views/docstore/DocStoreAPIDialog.jsx
index 74e51400c5a..38a2a09c00d 100644
--- a/packages/ui/src/views/docstore/DocStoreAPIDialog.jsx
+++ b/packages/ui/src/views/docstore/DocStoreAPIDialog.jsx
@@ -23,7 +23,11 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { IconInfoCircle } from '@tabler/icons-react'
import { baseURL } from '@/store/constant'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const DocStoreAPIDialog = ({ show, dialogProps, onCancel }) => {
+ const { t } = useTranslation()
const [nodeConfig, setNodeConfig] = useState({})
const [values, setValues] = useState('')
const theme = useTheme()
@@ -33,7 +37,7 @@ const DocStoreAPIDialog = ({ show, dialogProps, onCancel }) => {
const getConfigApi = useApi(documentstoreApi.getDocumentStoreConfig)
const formDataRequest = () => {
- return `With the Upsert API, you can choose an existing document and reuse the same configuration for upserting.
+ return `${t('docstore.api.upsertNote')}
\`\`\`python
import requests
@@ -135,7 +139,7 @@ curl -X POST ${baseURL}/api/v1/document-store/upsert/${dialogProps.storeId} \\
}
const jsonDataRequest = () => {
- return `With the Upsert API, you can choose an existing document and reuse the same configuration for upserting.
+ return `${t('docstore.api.upsertNote')}
\`\`\`python
import requests
@@ -349,7 +353,7 @@ curl -X POST ${baseURL}/api/v1/document-store/upsert/${dialogProps.storeId} \\
}}
/>
- Note: Upsert API can only be used when the existing document loader has been upserted before.
+ {t('docstore.labels.note')} {t('docstore.api.upsertNote')}
@@ -357,7 +361,7 @@ curl -X POST ${baseURL}/api/v1/document-store/upsert/${dialogProps.storeId} \\
{values}
- You can override existing configurations:
+ {t('docstore.labels.override')}
diff --git a/packages/ui/src/views/docstore/DocStoreInputHandler.jsx b/packages/ui/src/views/docstore/DocStoreInputHandler.jsx
index 184d9d76b90..6ddbd771b05 100644
--- a/packages/ui/src/views/docstore/DocStoreInputHandler.jsx
+++ b/packages/ui/src/views/docstore/DocStoreInputHandler.jsx
@@ -26,9 +26,13 @@ import { flowContext } from '@/store/context/ReactFlowContext'
// const
import { FLOWISE_CREDENTIAL_ID } from '@/store/constant'
+// i18n
+import { useTranslation } from 'react-i18next'
+
// ===========================|| DocStoreInputHandler ||=========================== //
const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataChange }) => {
+ const { t } = useTranslation()
const customization = useSelector((state) => state.customization)
const flowContextValue = useContext(flowContext)
const nodeDataChangeHandler = onNodeDataChange || flowContextValue?.onNodeDataChange
@@ -51,8 +55,8 @@ const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataCh
value,
inputParam,
disabled,
- confirmButtonName: 'Save',
- cancelButtonName: 'Cancel'
+ confirmButtonName: t('common.actions.save'),
+ cancelButtonName: t('common.actions.cancel')
}
setExpandDialogProps(dialogProps)
setShowExpandDialog(true)
@@ -64,8 +68,8 @@ const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataCh
relativeLinksMethod,
limit,
selectedLinks,
- confirmButtonName: 'Save',
- cancelButtonName: 'Cancel'
+ confirmButtonName: t('common.actions.save'),
+ cancelButtonName: t('common.actions.cancel')
}
setManageScrapedLinksDialogProps(dialogProps)
setShowManageScrapedLinksDialog(true)
@@ -109,7 +113,7 @@ const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataCh
height: 25,
width: 25
}}
- title='Expand'
+ title={t('common.actions.expand')}
color='primary'
onClick={() =>
onExpandDialogClicked(data.inputs[inputParam.name] ?? inputParam.default ?? '', inputParam)
@@ -157,7 +161,7 @@ const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataCh
disabled={disabled}
fileType={inputParam.fileType || '*'}
onChange={(newValue) => handleDataChange({ inputParam, newValue })}
- value={data.inputs[inputParam.name] ?? inputParam.default ?? 'Choose a file to upload'}
+ value={data.inputs[inputParam.name] ?? inputParam.default ?? t('components.file.chooseFile')}
/>
)}
{inputParam.type === 'boolean' && (
@@ -219,7 +223,7 @@ const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataCh
name={inputParam.name}
options={inputParam.options}
onSelect={(newValue) => handleDataChange({ inputParam, newValue })}
- value={data.inputs[inputParam.name] ?? inputParam.default ?? 'choose an option'}
+ value={data.inputs[inputParam.name] ?? inputParam.default ?? t('components.dropdown.chooseOption')}
/>
)}
{inputParam.type === 'multiOptions' && (
@@ -229,7 +233,7 @@ const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataCh
name={inputParam.name}
options={inputParam.options}
onSelect={(newValue) => handleDataChange({ inputParam, newValue })}
- value={data.inputs[inputParam.name] ?? inputParam.default ?? 'choose an option'}
+ value={data.inputs[inputParam.name] ?? inputParam.default ?? t('components.dropdown.chooseOption')}
/>
)}
{(inputParam.type === 'asyncOptions' || inputParam.type === 'asyncMultiOptions') && (
@@ -244,7 +248,9 @@ const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataCh
nodeData={data}
freeSolo={inputParam.freeSolo}
multiple={inputParam.type === 'asyncMultiOptions'}
- value={data.inputs[inputParam.name] ?? inputParam.default ?? 'choose an option'}
+ value={
+ data.inputs[inputParam.name] ?? inputParam.default ?? t('components.dropdown.chooseOption')
+ }
onSelect={(newValue) => handleDataChange({ inputParam, newValue })}
onCreateNew={() => addAsyncOption(inputParam.name)}
fullWidth={true}
@@ -252,7 +258,7 @@ const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataCh
{inputParam.refresh && (
setReloadTimestamp(Date.now().toString())}
@@ -289,7 +295,7 @@ const DocStoreInputHandler = ({ inputParam, data, disabled = false, onNodeDataCh
)
}
>
- Manage Links
+ {t('common.actions.manageLinks')}
{
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const dispatch = useDispatch()
const theme = useTheme()
@@ -83,7 +87,7 @@ const DocumentLoaderListDialog = ({ show, dialogProps, onCancel, onDocLoaderSele
id='input-search-credential'
value={searchValue}
onChange={(e) => onSearchChange(e.target.value)}
- placeholder='Search'
+ placeholder={t('common.actions.search')}
startAdornment={
@@ -99,7 +103,7 @@ const DocumentLoaderListDialog = ({ show, dialogProps, onCancel, onDocLoaderSele
color: theme.palette.grey[900]
}
}}
- title='Clear Search'
+ title={t('common.actions.clearSearch')}
>
diff --git a/packages/ui/src/views/docstore/DocumentStoreDetail.jsx b/packages/ui/src/views/docstore/DocumentStoreDetail.jsx
index dac334fa4fc..dabc66e9bbc 100644
--- a/packages/ui/src/views/docstore/DocumentStoreDetail.jsx
+++ b/packages/ui/src/views/docstore/DocumentStoreDetail.jsx
@@ -66,6 +66,9 @@ import doc_store_details_emptySVG from '@/assets/images/doc_store_details_empty.
import { closeSnackbar as closeSnackbarAction, enqueueSnackbar as enqueueSnackbarAction } from '@/store/actions'
import { useError } from '@/store/context/ErrorContext'
+// i18n
+import { useTranslation } from 'react-i18next'
+
// ==============================|| DOCUMENTS ||============================== //
const StyledTableCell = styled(TableCell)(({ theme }) => ({
@@ -125,6 +128,7 @@ const StyledMenu = styled((props) => (
}))
const DocumentStoreDetails = () => {
+ const { t } = useTranslation()
const theme = useTheme()
const customization = useSelector((state) => state.customization)
const navigate = useNavigate()
@@ -180,7 +184,7 @@ const DocumentStoreDetails = () => {
const listLoaders = () => {
const dialogProp = {
- title: 'Select Document Loader'
+ title: t('docstore.dialogs.selectDocumentLoader')
}
setDocumentLoaderListDialogProps(dialogProp)
setShowDocumentLoaderListDialog(true)
@@ -206,7 +210,7 @@ const DocumentStoreDetails = () => {
setBackdropLoading(false)
if (deleteResp.data) {
enqueueSnackbar({
- message: 'Store, Loader and associated document chunks deleted',
+ message: t('docstore.messages.deleteStore.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -223,9 +227,9 @@ const DocumentStoreDetails = () => {
setBackdropLoading(false)
setError(error)
enqueueSnackbar({
- message: `Failed to delete Document Store: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('docstore.messages.deleteStore.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -247,7 +251,7 @@ const DocumentStoreDetails = () => {
setBackdropLoading(false)
if (deleteResp.data) {
enqueueSnackbar({
- message: 'Loader and associated document chunks deleted',
+ message: t('docstore.messages.deleteLoader.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -264,9 +268,9 @@ const DocumentStoreDetails = () => {
setError(error)
setBackdropLoading(false)
enqueueSnackbar({
- message: `Failed to delete Document Loader: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('docstore.messages.deleteLoader.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -284,7 +288,7 @@ const DocumentStoreDetails = () => {
const onLoaderDelete = (file, vectorStoreConfig, recordManagerConfig) => {
// Get the display name in the format "LoaderName (sourceName)"
- const loaderName = file.loaderName || 'Unknown'
+ const loaderName = file.loaderName || t('docstore.common.unknown')
let sourceName = ''
// Prefer files.name when files array exists and has items
@@ -303,7 +307,7 @@ const DocumentStoreDetails = () => {
const displayName = sourceName ? `${loaderName} (${sourceName})` : loaderName
- let description = `Delete "${displayName}"? This will delete all the associated document chunks from the document store.`
+ let description = t('docstore.dialogs.delete.description.loader.simple', { name: displayName })
if (
recordManagerConfig &&
@@ -311,7 +315,7 @@ const DocumentStoreDetails = () => {
Object.keys(recordManagerConfig).length > 0 &&
Object.keys(vectorStoreConfig).length > 0
) {
- description = `Delete "${displayName}"? This will delete all the associated document chunks from the document store and remove the actual data from the vector store database.`
+ description = t('docstore.dialogs.delete.description.loader.withData', { name: displayName })
}
const props = {
@@ -328,7 +332,7 @@ const DocumentStoreDetails = () => {
}
const onStoreDelete = (vectorStoreConfig, recordManagerConfig) => {
- let description = `Delete Store ${getSpecificDocumentStore.data?.name}? This will delete all the associated loaders and document chunks from the document store.`
+ let description = t('docstore.dialogs.delete.description.store.simple', { name: getSpecificDocumentStore.data?.name })
if (
recordManagerConfig &&
@@ -336,11 +340,11 @@ const DocumentStoreDetails = () => {
Object.keys(recordManagerConfig).length > 0 &&
Object.keys(vectorStoreConfig).length > 0
) {
- description = `Delete Store ${getSpecificDocumentStore.data?.name}? This will delete all the associated loaders and document chunks from the document store, and remove the actual data from the vector store database.`
+ description = t('docstore.dialogs.delete.description.store.withData', { name: getSpecificDocumentStore.data?.name })
}
const props = {
- title: `Delete`,
+ title: t('common.dialogs.delete'),
description,
vectorStoreConfig,
recordManagerConfig,
@@ -353,10 +357,10 @@ const DocumentStoreDetails = () => {
const onStoreRefresh = async (storeId) => {
const confirmPayload = {
- title: `Refresh all loaders and upsert all chunks?`,
- description: `This will re-process all loaders and upsert all chunks. This action might take some time.`,
- confirmButtonName: 'Refresh',
- cancelButtonName: 'Cancel'
+ title: t('docstore.dialogs.confirm.title'),
+ description: t('docstore.dialogs.confirm.description'),
+ confirmButtonName: t('common.actions.refresh'),
+ cancelButtonName: t('common.actions.cancel')
}
const isConfirmed = await confirm(confirmPayload)
@@ -367,7 +371,7 @@ const DocumentStoreDetails = () => {
const resp = await documentsApi.refreshLoader(storeId)
if (resp.data) {
enqueueSnackbar({
- message: 'Document store refresh successfully!',
+ message: t('docstore.messages.storeRefresh.success'),
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
@@ -383,9 +387,9 @@ const DocumentStoreDetails = () => {
} catch (error) {
setBackdropLoading(false)
enqueueSnackbar({
- message: `Failed to refresh document store: ${
- typeof error.response.data === 'object' ? error.response.data.message : error.response.data
- }`,
+ message: t('docstore.messages.storeRefresh.error', {
+ msg: typeof error.response.data === 'object' ? error.response.data.message : error.response.data
+ }),
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
@@ -407,10 +411,10 @@ const DocumentStoreDetails = () => {
id: documentStore.id
}
const dialogProp = {
- title: 'Edit Document Store',
+ title: t('docstore.dialogs.editDocumentStore'),
type: 'EDIT',
- cancelButtonName: 'Cancel',
- confirmButtonName: 'Update',
+ cancelButtonName: t('common.actions.cancel'),
+ confirmButtonName: t('docstore.actions.update'),
data: data
}
setDialogProps(dialogProp)
@@ -430,7 +434,7 @@ const DocumentStoreDetails = () => {
const onViewUpsertAPI = (storeId, loaderId) => {
const props = {
- title: `Upsert API`,
+ title: t('docstore.dialogs.upsertApi'),
storeId,
loaderId
}
@@ -487,7 +491,7 @@ const DocumentStoreDetails = () => {
onClick={onConfirm}
size='small'
color='primary'
- title='Refresh Document Store'
+ title={t('docstore.actions.refreshDocumentStore')}
>
@@ -499,7 +503,7 @@ const DocumentStoreDetails = () => {
startIcon={}
onClick={listLoaders}
>
- Add Document Loader
+ {t('docstore.actions.addDocumentLoader')}
@@ -600,7 +604,7 @@ const DocumentStoreDetails = () => {
}}
>
- Chatflows Used:
+ {t('docstore.labels.chatflowsUsed')}
{getSpecificDocumentStore.data.whereUsed.map((chatflowUsed, index) => (
{
alt='doc_store_details_emptySVG'
/>
- No Document Added Yet
+ {t('docstore.empty.documents')}
}
onClick={listLoaders}
>
- Add Document Loader
+ {t('docstore.actions.addDocumentLoader')}
) : (
@@ -643,7 +647,7 @@ const DocumentStoreDetails = () => {
sx={{ border: 1, borderColor: theme.palette.grey[900] + 25, borderRadius: 2 }}
component={Paper}
>
-
+
{
>
- Loader
- Splitter
- Source(s)
- Chunks
- Chars
+ {t('docstore.table.loader')}
+ {t('docstore.table.splitter')}
+ {t('docstore.table.source')}
+ {t('docstore.table.chunks')}
+ {t('docstore.table.chars')}
- Actions
+ {t('docstore.table.actions')}
@@ -755,7 +759,7 @@ const DocumentStoreDetails = () => {
color='warning'
style={{ color: 'darkred', fontWeight: 500, fontStyle: 'italic', fontSize: 12 }}
>
- Some files are pending processing. Please Refresh to get the latest status.
+ {t('docstore.labels.pendingRefresh')}
)}
@@ -800,6 +804,7 @@ const DocumentStoreDetails = () => {
}
function LoaderRow(props) {
+ const { t } = useTranslation()
const [anchorEl, setAnchorEl] = useState(null)
const open = Boolean(anchorEl)
@@ -830,7 +835,7 @@ function LoaderRow(props) {
// Return format: "LoaderName (sourceName)" or just "LoaderName" if no source
if (!sourceName) {
- return loaderName || 'No source'
+ return loaderName || t('docstore.common.noSource')
}
return loaderName ? `${loaderName} (${sourceName})` : sourceName
}
@@ -852,7 +857,7 @@ function LoaderRow(props) {
{props.loader.loaderName}
- {props.loader.splitterName ?? 'None'}
+ {props.loader.splitterName ?? t('common.labels.none')}
{formatSources(props.loader.files, props.loader.source)}
@@ -894,7 +899,7 @@ function LoaderRow(props) {
disableRipple
>
- Preview & Process
+ {t('docstore.actions.menu.previewProcess')}
@@ -906,7 +911,7 @@ function LoaderRow(props) {
disableRipple
>
- View & Edit Chunks
+ {t('docstore.actions.menu.viewEditChunks')}
@@ -918,7 +923,7 @@ function LoaderRow(props) {
disableRipple
>
- Upsert Chunks
+ {t('docstore.actions.menu.upsertChunks')}
@@ -930,7 +935,7 @@ function LoaderRow(props) {
disableRipple
>
- View API
+ {t('docstore.actions.menu.viewApi')}
@@ -943,7 +948,7 @@ function LoaderRow(props) {
disableRipple
>
- Delete
+ {t('common.actions.delete')}
diff --git a/packages/ui/src/views/docstore/ExpandedChunkDialog.jsx b/packages/ui/src/views/docstore/ExpandedChunkDialog.jsx
index 0d7976e00a2..4867d2f24ca 100644
--- a/packages/ui/src/views/docstore/ExpandedChunkDialog.jsx
+++ b/packages/ui/src/views/docstore/ExpandedChunkDialog.jsx
@@ -13,7 +13,11 @@ import { IconEdit, IconTrash, IconX, IconLanguage } from '@tabler/icons-react'
import { CodeEditor } from '@/ui-component/editor/CodeEditor'
import { PermissionButton, PermissionIconButton } from '@/ui-component/button/RBACButtons'
+// i18n
+import { useTranslation } from 'react-i18next'
+
const ExpandedChunkDialog = ({ show, dialogProps, onCancel, onChunkEdit, onDeleteChunk, isReadOnly }) => {
+ const { t } = useTranslation()
const portalElement = document.getElementById('portal')
const customization = useSelector((state) => state.customization)
@@ -93,15 +97,15 @@ const ExpandedChunkDialog = ({ show, dialogProps, onCancel, onChunkEdit, onDelet
onClick={() => setIsEdit(true)}
size='small'
color='primary'
- title='Edit Chunk'
+ title={t('docstore.actions.editChunk')}
sx={{ ml: 2 }}
>
)}
{isEdit && !isReadOnly && (
-