From b7ee9c6bcfb3d0858936eb4e1e179aa553f9d081 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Fri, 30 May 2025 23:30:19 +0500 Subject: [PATCH 01/13] Add trasns for Environments List and Table --- .../packages/lowcoder/src/i18n/locales/en.ts | 34 +++++++++++++++++- .../setting/environments/EnvironmentsList.tsx | 17 ++++----- .../components/EnvironmentsTable.tsx | 35 ++++++++++--------- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index 190fa053a..fe02321f5 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -2551,8 +2551,40 @@ export const en = { "EnvironmentsFeature2": "Deployment of applications, data sources, and configurations between environments, directly from the UI.", "EnvironmentsFeature3": "Environment-specific access controls and visibility rules.", "EnvironmentsFeature5": "Clear separation of concerns for staging, sandbox, and production operations.", - }, + // Environments page translations + "environments": { + "title": "Environments", + "search": "Search", + "refresh": "Refresh", + "addEnvironment": "Add Environment", + "errorLoadingEnvironments": "Error loading environments", + "noEnvironmentsFoundMatching": "No environments found matching \"{searchText}\"", + "noEnvironmentsFound": "No environments found. Create your first environment to get started.", + "environmentsTypeLabel": "{type} Environments", + "showingAllEnvironments": "Showing all {count} environments", + "unnamedEnvironment": "Unnamed Environment", + "masterEnvironment": "Master Environment", + "viewAuditLogs": "View Audit Logs", + "id": "ID", + "domain": "Domain", + "master": "Master", + "license": "License", + "apiCalls": "API Calls", + "yes": "Yes", + "no": "No", + "copyId": "Copy ID", + "copied": "Copied!", + "percentUsed": "{percent}% used", + "licenseStatus": { + "checking": "Checking...", + "licensed": "Licensed", + "unlicensed": "License Required", + "error": "Setup Required", + "unknown": "Unknown" + } + } + }, "subscription": { "details": "Subscription Details", "productDetails": "Product Details", diff --git a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentsList.tsx b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentsList.tsx index 36be33166..b46381511 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentsList.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentsList.tsx @@ -13,6 +13,7 @@ import StatsCard from "./components/StatsCard"; import { buildEnvironmentId } from "@lowcoder-ee/constants/routesURL"; import { createEnvironment } from "./services/environments.service"; import { getEnvironmentTagColor } from "./utils/environmentUtils"; +import { trans } from "i18n"; import styled from "styled-components"; const EnvironmentsWrapper = styled.div` @@ -157,9 +158,9 @@ const EnvironmentsList: React.FC = () => { return ( - Environments + {trans("enterprise.environments.title")} setSearchText(e.target.value)} style={{ width: "192px", height: "32px", margin: "0 12px 0 0" }} @@ -169,14 +170,14 @@ const EnvironmentsList: React.FC = () => { icon={} onClick={handleRefresh} > - Refresh + {trans("enterprise.environments.refresh")} } onClick={() => setIsCreateModalVisible(true)} > - Add Environment + {trans("enterprise.environments.addEnvironment")} @@ -187,7 +188,7 @@ const EnvironmentsList: React.FC = () => { {environmentStats.map(([type, count]) => ( { {error && ( { {!isLoading && !error && filteredEnvironments.length === 0 && searchText && ( )} {!isLoading && !error && environments.length === 0 && !searchText && ( )} diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx index 2336c8d5d..81f777188 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentsTable.tsx @@ -4,6 +4,7 @@ import { EditOutlined, AuditOutlined, LinkOutlined, EnvironmentOutlined, StarFil import { Environment } from '../types/environment.types'; import { getEnvironmentTagColor, formatEnvironmentType } from '../utils/environmentUtils'; import { getAPICallsStatusColor } from '../services/license.service'; +import { trans } from 'i18n'; const { Text, Title } = Typography; @@ -56,35 +57,35 @@ const EnvironmentsTable: React.FC = ({ return { icon: , color: '#40a9ff', - text: 'Checking...', + text: trans("enterprise.environments.licenseStatus.checking"), status: 'processing' as const }; case 'licensed': return { icon: , color: '#73d13d', - text: 'Licensed', + text: trans("enterprise.environments.licenseStatus.licensed"), status: 'success' as const }; case 'unlicensed': return { icon: , color: '#ff7875', - text: 'License Required', + text: trans("enterprise.environments.licenseStatus.unlicensed"), status: 'warning' as const }; case 'error': return { icon: , color: '#ffc53d', - text: 'Setup Required', + text: trans("enterprise.environments.licenseStatus.error"), status: 'warning' as const }; default: return { icon: , color: '#d9d9d9', - text: 'Unknown', + text: trans("enterprise.environments.licenseStatus.unknown"), status: 'default' as const }; } @@ -163,9 +164,9 @@ const EnvironmentsTable: React.FC = ({ />
- {env.environmentName || 'Unnamed Environment'} + {env.environmentName || trans("enterprise.environments.unnamedEnvironment")} {env.isMaster && ( - <Tooltip title="Master Environment"> + <Tooltip title={trans("enterprise.environments.masterEnvironment")}> <StarFilled style={{ color: '#faad14', marginLeft: '6px', fontSize: '12px' }} /> </Tooltip> )} @@ -192,7 +193,7 @@ const EnvironmentsTable: React.FC<EnvironmentsTableProps> = ({ {/* Only show audit button for licensed environments */} {isAccessible && ( <div> - <Tooltip title="View Audit Logs" placement="top"> + <Tooltip title={trans("enterprise.environments.viewAuditLogs")} placement="top"> <Button type="text" icon={<AuditOutlined />} @@ -214,9 +215,9 @@ const EnvironmentsTable: React.FC<EnvironmentsTableProps> = ({ <div style={{ padding: '8px 0', borderTop: '1px solid #f5f5f5' }}> <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> - <Text type="secondary" style={{ fontSize: '12px' }}>ID:</Text> + <Text type="secondary" style={{ fontSize: '12px' }}>{trans("enterprise.environments.id")}:</Text> {isAccessible ? ( - <Text style={{ fontSize: '12px', fontFamily: 'monospace' }} copyable={{ tooltips: ['Copy ID', 'Copied!'] }}> + <Text style={{ fontSize: '12px', fontFamily: 'monospace' }} copyable={{ tooltips: [trans("enterprise.environments.copyId"), trans("enterprise.environments.copied")] }}> {env.environmentId} </Text> ) : ( @@ -227,7 +228,7 @@ const EnvironmentsTable: React.FC<EnvironmentsTableProps> = ({ </div> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> - <Text type="secondary" style={{ fontSize: '12px' }}>Domain:</Text> + <Text type="secondary" style={{ fontSize: '12px' }}>{trans("enterprise.environments.domain")}:</Text> {env.environmentFrontendUrl ? ( isAccessible ? ( <a @@ -251,14 +252,14 @@ const EnvironmentsTable: React.FC<EnvironmentsTableProps> = ({ </div> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> - <Text type="secondary" style={{ fontSize: '12px' }}>Master:</Text> + <Text type="secondary" style={{ fontSize: '12px' }}>{trans("enterprise.environments.master")}:</Text> <Text style={{ fontSize: '12px' }}> - {env.isMaster ? 'Yes' : 'No'} + {env.isMaster ? trans("enterprise.environments.yes") : trans("enterprise.environments.no")} </Text> </div> <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> - <Text type="secondary" style={{ fontSize: '12px' }}>License:</Text> + <Text type="secondary" style={{ fontSize: '12px' }}>{trans("enterprise.environments.license")}:</Text> <div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}> <span style={{ color: licenseDisplay.color, fontSize: '12px' }}> {licenseDisplay.icon} @@ -275,7 +276,7 @@ const EnvironmentsTable: React.FC<EnvironmentsTableProps> = ({ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '6px' }}> <Text type="secondary" style={{ fontSize: '11px' }}> <ApiOutlined style={{ marginRight: '4px' }} /> - API Calls + {trans("enterprise.environments.apiCalls")} </Text> </div> @@ -295,7 +296,7 @@ const EnvironmentsTable: React.FC<EnvironmentsTableProps> = ({ fontSize: '10px', color: '#8c8c8c' }}> - <span>{env.licenseDetails.apiCallsUsage || 0}% used</span> + <span>{trans("enterprise.environments.percentUsed", { percent: env.licenseDetails.apiCallsUsage || 0 })}</span> </div> </div> )} @@ -310,7 +311,7 @@ const EnvironmentsTable: React.FC<EnvironmentsTableProps> = ({ {environments.length > 10 && ( <div style={{ textAlign: 'center', margin: '16px 0' }}> <Text type="secondary" style={{ fontSize: '13px' }}> - Showing all {environments.length} environments + {trans("enterprise.environments.showingAllEnvironments", { count: environments.length })} </Text> </div> )} From e920c684d8fa9a159effbb364f3d210b1901ed6d Mon Sep 17 00:00:00 2001 From: Faran Javed <faran1997@outlook.com> Date: Fri, 30 May 2025 23:38:02 +0500 Subject: [PATCH 02/13] Add trans for Create Env Modal --- .../packages/lowcoder/src/i18n/locales/en.ts | 84 ++++++++++++++++++- .../components/CreateEnvironmentModal.tsx | 59 ++++++------- 2 files changed, 112 insertions(+), 31 deletions(-) diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index fe02321f5..85b72168f 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -2499,7 +2499,7 @@ export const en = { "API100k": "100,000 API Calls — $100", "API1M": "1,000,000 API Calls — $1,000", "API10M": "10,000,000 API Calls — $10,000", - "UsageOverrunDesc": "When your API package runs low, we’ll alert you. Once the package is consumed, your instance remains functional but will operate at a reduced speed to prevent abuse and maintain fairness.", + "UsageOverrunDesc": "When your API package runs low, we'll alert you. Once the package is consumed, your instance remains functional but will operate at a reduced speed to prevent abuse and maintain fairness.", "UsageTopUpInfo": "You can seamlessly add additional packages anytime to ensure continuous, fast access — no service interruptions.", "AppUsageTitle": "App Usage Logs", "AppUsageIntroTitle": "Understand how your apps are used", @@ -2531,7 +2531,7 @@ export const en = { "BrandingPagesIntro2": "These touchpoints help deliver a fully branded experience even during unexpected scenarios or account transitions.", "BrandingMetaIntro": "Define standard metadata like page title and description to improve your SEO presence and brand messaging.", "BrandingHelpLinksIntro": "Add context-sensitive documentation links directly inside the app, providing just-in-time help to your users.", - "BrandingWhatsNewIntro": "Activate the 'What’s New' section to highlight updates and product announcements in a branded and visible manner.", + "BrandingWhatsNewIntro": "Activate the 'What's New' section to highlight updates and product announcements in a branded and visible manner.", "EnvironmentsIntroTitle": "Lowcoder Staging", "EnvironmentsTitle" : "Multi-Environment Infrastructure", @@ -2582,6 +2582,86 @@ export const en = { "unlicensed": "License Required", "error": "Setup Required", "unknown": "Unknown" + }, + "detail": { + "environmentNotFound": "Environment Not Found", + "returnToEnvironmentsList": "Return to Environments List", + "environmentDetail": "Environment Detail", + "environmentOverview": "Environment Overview", + "noDomainSet": "No domain set", + "environmentId": "Environment ID", + "licenseStatus": "License Status", + "licenseNeeded": "License Needed", + "setupRequired": "Setup Required", + "created": "Created", + "unknown": "Unknown", + "licenseDetails": "License Details", + "apiCallsRemaining": "API Calls Remaining", + "totalApiCallsLimit": "Total API Calls Limit", + "enterpriseEdition": "Enterprise Edition", + "active": "Active", + "inactive": "Inactive", + "licenseInformation": "License Information", + "calls": "calls", + "licenses": "Licenses", + "license": "License", + "workspaces": "Workspaces", + "userGroups": "User Groups", + "type": "Type", + "status": "Status", + "licensed": "Licensed", + "unlicensed": "Unlicensed", + "apiKey": "API Key", + "configured": "Configured", + "notSet": "Not Set", + "masterEnv": "Master Env" + }, + "unlicensed": { + "unlicensedDescription": "This environment needs a valid license to unlock its full capabilities and features. Please make sure your API Service URL is correctly configured and Plugin is installed.", + "errorDescription": "We encountered an issue while checking the license. Please review the configuration settings.", + "defaultDescription": "This environment requires license configuration to proceed.", + "contactLowcoderTeam": "Contact Lowcoder Team", + "editEnvironment": "Edit Environment", + "backToEnvironments": "Back to Environments", + "helpText": "Need assistance? Contact our team for licensing support or edit the environment configuration to resolve this issue.", + "type": "Type", + "status": "Status", + "masterEnv": "Master Env", + "licenseIssue": "License Issue", + "error": "Error", + "missing": "Missing" + }, + "error": { + "itemNotFound": "The item you're looking for doesn't exist or you don't have permission to view it." + }, + "modal": { + "createNewEnvironment": "Create New Environment", + "cancel": "Cancel", + "createEnvironment": "Create Environment", + "environmentName": "Environment Name", + "pleaseEnterName": "Please enter a name", + "nameMinLength": "Name must be at least 2 characters", + "enterEnvironmentName": "Enter environment name", + "description": "Description", + "enterDescription": "Enter description", + "stage": "Stage", + "pleaseSelectStage": "Please select a stage", + "selectStage": "Select stage", + "development": "Development (DEV)", + "testing": "Testing (TEST)", + "preProduction": "Pre-Production (PREPROD)", + "production": "Production (PROD)", + "frontendUrl": "Frontend URL", + "pleaseEnterValidUrl": "Please enter a valid URL", + "apiServiceUrl": "API Service URL", + "nodeServiceUrl": "Node Service URL", + "apiKey": "API Key", + "enterApiKey": "Enter API key", + "masterEnvironment": "Master Environment", + "alreadyMasterEnvironment": "{name} is already the Master environment", + "willBeMaster": "Will be Master", + "configurationRequirements": "Configuration Requirements", + "configurationRequirementsDesc": "Ensure that the API Service URL is configured and correct, the API key is valid, and for license verification make sure you have both the license and plugin properly installed." } } }, diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/CreateEnvironmentModal.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/CreateEnvironmentModal.tsx index 8a6132c0a..170128f7a 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/CreateEnvironmentModal.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/CreateEnvironmentModal.tsx @@ -3,6 +3,7 @@ import { Modal, Form, Input, Select, Switch, Button, Alert, Tooltip } from 'antd import { useSelector } from 'react-redux'; import { selectMasterEnvironment, selectHasMasterEnvironment } from 'redux/selectors/enterpriseSelectors'; import { Environment } from '../types/environment.types'; +import { trans } from 'i18n'; const { Option } = Select; @@ -66,14 +67,14 @@ const CreateEnvironmentModal: React.FC<CreateEnvironmentModalProps> = ({ return ( <Modal - title="Create New Environment" + title={trans("enterprise.environments.modal.createNewEnvironment")} open={visible} onCancel={handleCancel} maskClosable={true} destroyOnHidden={true} footer={[ <Button key="back" onClick={handleCancel}> - Cancel + {trans("enterprise.environments.modal.cancel")} </Button>, <Button key="submit" @@ -81,7 +82,7 @@ const CreateEnvironmentModal: React.FC<CreateEnvironmentModalProps> = ({ loading={loading || submitLoading} onClick={handleSubmit} > - Create Environment + {trans("enterprise.environments.modal.createEnvironment")} </Button> ]} > @@ -95,43 +96,43 @@ const CreateEnvironmentModal: React.FC<CreateEnvironmentModalProps> = ({ > <Form.Item name="environmentName" - label="Environment Name" + label={trans("enterprise.environments.modal.environmentName")} rules={[ - { required: true, message: 'Please enter a name' }, - { min: 2, message: 'Name must be at least 2 characters' } + { required: true, message: trans("enterprise.environments.modal.pleaseEnterName") }, + { min: 2, message: trans("enterprise.environments.modal.nameMinLength") } ]} > - <Input placeholder="Enter environment name" /> + <Input placeholder={trans("enterprise.environments.modal.enterEnvironmentName")} /> </Form.Item> <Form.Item name="environmentDescription" - label="Description" + label={trans("enterprise.environments.modal.description")} > <Input.TextArea - placeholder="Enter description" + placeholder={trans("enterprise.environments.modal.enterDescription")} rows={3} /> </Form.Item> <Form.Item name="environmentType" - label="Stage" - rules={[{ required: true, message: 'Please select a stage' }]} + label={trans("enterprise.environments.modal.stage")} + rules={[{ required: true, message: trans("enterprise.environments.modal.pleaseSelectStage") }]} > - <Select placeholder="Select stage"> - <Option value="DEV">Development (DEV)</Option> - <Option value="TEST">Testing (TEST)</Option> - <Option value="PREPROD">Pre-Production (PREPROD)</Option> - <Option value="PROD">Production (PROD)</Option> + <Select placeholder={trans("enterprise.environments.modal.selectStage")}> + <Option value="DEV">{trans("enterprise.environments.modal.development")}</Option> + <Option value="TEST">{trans("enterprise.environments.modal.testing")}</Option> + <Option value="PREPROD">{trans("enterprise.environments.modal.preProduction")}</Option> + <Option value="PROD">{trans("enterprise.environments.modal.production")}</Option> </Select> </Form.Item> <Form.Item name="environmentFrontendUrl" - label="Frontend URL" + label={trans("enterprise.environments.modal.frontendUrl")} rules={[ - { type: 'url', message: 'Please enter a valid URL' } + { type: 'url', message: trans("enterprise.environments.modal.pleaseEnterValidUrl") } ]} > <Input placeholder="https://example.com" /> @@ -139,9 +140,9 @@ const CreateEnvironmentModal: React.FC<CreateEnvironmentModalProps> = ({ <Form.Item name="environmentApiServiceUrl" - label="API Service URL" + label={trans("enterprise.environments.modal.apiServiceUrl")} rules={[ - { type: 'url', message: 'Please enter a valid URL' } + { type: 'url', message: trans("enterprise.environments.modal.pleaseEnterValidUrl") } ]} > <Input placeholder="https://api.example.com" /> @@ -149,9 +150,9 @@ const CreateEnvironmentModal: React.FC<CreateEnvironmentModalProps> = ({ <Form.Item name="environmentNodeServiceUrl" - label="Node Service URL" + label={trans("enterprise.environments.modal.nodeServiceUrl")} rules={[ - { type: 'url', message: 'Please enter a valid URL' } + { type: 'url', message: trans("enterprise.environments.modal.pleaseEnterValidUrl") } ]} > <Input placeholder="https://node.example.com" /> @@ -159,20 +160,20 @@ const CreateEnvironmentModal: React.FC<CreateEnvironmentModalProps> = ({ <Form.Item name="environmentApikey" - label="API Key" + label={trans("enterprise.environments.modal.apiKey")} > <Input.TextArea - placeholder="Enter API key" + placeholder={trans("enterprise.environments.modal.enterApiKey")} rows={2} /> </Form.Item> - <Form.Item label="Master Environment"> + <Form.Item label={trans("enterprise.environments.modal.masterEnvironment")}> <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}> <Tooltip title={ hasMasterEnvironment - ? `${masterEnvironment?.environmentName} is already the Master environment` + ? trans("enterprise.environments.modal.alreadyMasterEnvironment", { name: masterEnvironment?.environmentName }) : '' } > @@ -185,15 +186,15 @@ const CreateEnvironmentModal: React.FC<CreateEnvironmentModalProps> = ({ </Tooltip> {isMaster && ( <span style={{ color: '#52c41a', fontSize: '12px' }}> - Will be Master + {trans("enterprise.environments.modal.willBeMaster")} </span> )} </div> </Form.Item> <Alert - message="Configuration Requirements" - description="Ensure that the API Service URL is configured and correct, the API key is valid, and for license verification make sure you have both the license and plugin properly installed." + message={trans("enterprise.environments.modal.configurationRequirements")} + description={trans("enterprise.environments.modal.configurationRequirementsDesc")} type="warning" showIcon style={{ marginTop: '16px' }} From 7fc77166393568f48a116edbdc4e392066278af5 Mon Sep 17 00:00:00 2001 From: Faran Javed <faran1997@outlook.com> Date: Fri, 30 May 2025 23:38:27 +0500 Subject: [PATCH 03/13] add trans for error component --- .../pages/setting/environments/components/ErrorComponent.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/ErrorComponent.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/ErrorComponent.tsx index 2f4d5fbac..e2015059d 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/ErrorComponent.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/ErrorComponent.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { Card, Button, Typography } from 'antd'; import { HomeOutlined } from '@ant-design/icons'; import history from '@lowcoder-ee/util/history'; +import { trans } from 'i18n'; const { Title, Text } = Typography; @@ -20,7 +21,7 @@ const ErrorComponent: React.FC<ErrorComponentProps> = ({ errorMessage, returnPat {errorMessage} - The item you're looking for doesn't exist or you don't have permission to view it. + {trans("enterprise.environments.error.itemNotFound")}
@@ -233,7 +234,7 @@ const UnlicensedEnvironmentView: React.FC = ({ display: 'block', lineHeight: '1.5' }}> - Need assistance? Contact our team for licensing support or edit the environment configuration to resolve this issue. + {trans("enterprise.environments.unlicensed.helpText")} From 352d715d5c6032bb24d80defaab94a5b656788ed Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Fri, 30 May 2025 23:42:42 +0500 Subject: [PATCH 05/13] Add trans for Environment Detail Page --- .../environments/EnvironmentDetail.tsx | 73 ++++++++++--------- .../components/EnvironmentHeader.tsx | 11 +-- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx index 2a52b1826..f9495a05d 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/EnvironmentDetail.tsx @@ -46,6 +46,7 @@ import { getEnvironmentTagColor } from "./utils/environmentUtils"; import { formatAPICalls, getAPICallsStatusColor } from "./services/license.service"; import ErrorComponent from './components/ErrorComponent'; import { Level1SettingPageContent } from "../styled"; +import { trans } from "i18n"; /** * Environment Detail Page Component @@ -105,9 +106,9 @@ const EnvironmentDetail: React.FC = () => { if (error || !environment) { return ( ); } @@ -138,26 +139,26 @@ const EnvironmentDetail: React.FC = () => { // Stats data for the cards const statsData = [ { - title: "Type", - value: environment.environmentType || "Unknown", + title: trans("enterprise.environments.detail.type"), + value: environment.environmentType || trans("enterprise.environments.detail.unknown"), icon: , color: getEnvironmentTagColor(environment.environmentType) }, { - title: "Status", - value: environment.isLicensed ? "Licensed" : "Unlicensed", + title: trans("enterprise.environments.detail.status"), + value: environment.isLicensed ? trans("enterprise.environments.detail.licensed") : trans("enterprise.environments.detail.unlicensed"), icon: environment.isLicensed ? : , color: environment.isLicensed ? "#52c41a" : "#ff4d4f" }, { - title: "API Key", - value: environment.environmentApikey ? "Configured" : "Not Set", + title: trans("enterprise.environments.detail.apiKey"), + value: environment.environmentApikey ? trans("enterprise.environments.detail.configured") : trans("enterprise.environments.detail.notSet"), icon: , color: environment.environmentApikey ? "#1890ff" : "#faad14" }, { - title: "Master Env", - value: environment.isMaster ? "Yes" : "No", + title: trans("enterprise.environments.detail.masterEnv"), + value: environment.isMaster ? trans("enterprise.environments.yes") : trans("enterprise.environments.no"), icon: , color: environment.isMaster ? "#722ed1" : "#8c8c8c" } @@ -168,7 +169,7 @@ const EnvironmentDetail: React.FC = () => { key: 'workspaces', label: ( - Workspaces + {trans("enterprise.environments.detail.workspaces")} ), children: @@ -177,7 +178,7 @@ const EnvironmentDetail: React.FC = () => { key: 'userGroups', label: ( - User Groups + {trans("enterprise.environments.detail.userGroups")} ), children: @@ -192,12 +193,12 @@ const EnvironmentDetail: React.FC = () => { items={[ { key: 'environments', - title: 'Environments', + title: trans("enterprise.environments.title"), onClick: () => history.push('/setting/environments') }, { key: 'current', - title: environment.environmentName || "Environment Detail" + title: environment.environmentName || trans("enterprise.environments.detail.environmentDetail") } ]} /> @@ -224,7 +225,7 @@ const EnvironmentDetail: React.FC = () => { {/* Basic Environment Information Card */} { column={{ xxl: 4, xl: 3, lg: 3, md: 2, sm: 1, xs: 1 }} size="small" > - + {environment.environmentFrontendUrl ? ( { {environment.environmentFrontendUrl} ) : ( - "No domain set" + trans("enterprise.environments.detail.noDomainSet") )} - + {environment.environmentId} - + {(() => { switch (environment.licenseStatus) { case 'checking': - return } color="blue" style={{ borderRadius: '4px' }}>Checking...; + return } color="blue" style={{ borderRadius: '4px' }}>{trans("enterprise.environments.licenseStatus.checking")}; case 'licensed': - return } color="green" style={{ borderRadius: '4px' }}>Licensed; + return } color="green" style={{ borderRadius: '4px' }}>{trans("enterprise.environments.licenseStatus.licensed")}; case 'unlicensed': - return } color="orange" style={{ borderRadius: '4px' }}>License Needed; + return } color="orange" style={{ borderRadius: '4px' }}>{trans("enterprise.environments.detail.licenseNeeded")}; case 'error': - return } color="orange" style={{ borderRadius: '4px' }}>Setup Required; + return } color="orange" style={{ borderRadius: '4px' }}>{trans("enterprise.environments.detail.setupRequired")}; default: - return Unknown; + return {trans("enterprise.environments.detail.unknown")}; } })()} - - {environment.createdAt ? new Date(environment.createdAt).toLocaleDateString() : "Unknown"} + + {environment.createdAt ? new Date(environment.createdAt).toLocaleDateString() : trans("enterprise.environments.detail.unknown")} @@ -285,7 +286,7 @@ const EnvironmentDetail: React.FC = () => { title={ - License Details + {trans("enterprise.environments.detail.licenseDetails")} } style={{ @@ -304,7 +305,7 @@ const EnvironmentDetail: React.FC = () => { styles={{ body: { padding: '16px' } }} > ( { color: '#8c8c8c', marginTop: '4px' }}> - {environment.licenseDetails.apiCallsUsage || 0}% used + {trans("enterprise.environments.percentUsed", { percent: environment.licenseDetails.apiCallsUsage || 0 })} @@ -347,7 +348,7 @@ const EnvironmentDetail: React.FC = () => { styles={{ body: { padding: '16px' } }} > value?.toLocaleString()} prefix={} @@ -356,7 +357,7 @@ const EnvironmentDetail: React.FC = () => { color="blue" style={{ marginTop: '12px' }} > - {environment.licenseDetails.eeLicenses.length} License{environment.licenseDetails.eeLicenses.length !== 1 ? 's' : ''} + {environment.licenseDetails.eeLicenses.length} {environment.licenseDetails.eeLicenses.length !== 1 ? trans("enterprise.environments.detail.licenses") : trans("enterprise.environments.detail.license")} @@ -369,8 +370,8 @@ const EnvironmentDetail: React.FC = () => { styles={{ body: { padding: '16px' } }} > ( {
- License Information + {trans("enterprise.environments.detail.licenseInformation")} @@ -408,13 +409,13 @@ const EnvironmentDetail: React.FC = () => {
- ID: {license.customerId} + {trans("enterprise.environments.id")}: {license.customerId}
UUID: {license.uuid.substring(0, 8)}...
- {license.apiCallsLimit.toLocaleString()} calls + {license.apiCallsLimit.toLocaleString()} {trans("enterprise.environments.detail.calls")} diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentHeader.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentHeader.tsx index 4b4c32209..caaa22c86 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentHeader.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/EnvironmentHeader.tsx @@ -3,6 +3,7 @@ import { Button, Tag, Typography, Row, Col } from 'antd'; import { EditOutlined, CloudServerOutlined } from '@ant-design/icons'; import { Environment } from '../types/environment.types'; import { getEnvironmentTagColor } from '../utils/environmentUtils'; +import { trans } from 'i18n'; const { Title, Text } = Typography; @@ -49,7 +50,7 @@ const EnvironmentHeader: React.FC = ({
- {environment.environmentName || "Unnamed Environment"} + {environment.environmentName || trans("enterprise.environments.unnamedEnvironment")}
= ({ fontSize: '14px', fontFamily: 'monospace' }}> - ID: {environment.environmentId} + {trans("enterprise.environments.id")}: {environment.environmentId} = ({ {environment.isMaster && ( - Master + {trans("enterprise.environments.master")} )} {environment.isLicensed === false && ( - Unlicensed + {trans("enterprise.environments.detail.unlicensed")} )}
@@ -93,7 +94,7 @@ const EnvironmentHeader: React.FC = ({ borderRadius: '4px' }} > - Edit Environment + {trans("enterprise.environments.unlicensed.editEnvironment")} From 4ea9653a06cbbe284b916602f7739fa333393058 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Fri, 30 May 2025 23:48:09 +0500 Subject: [PATCH 06/13] Add trans for Edit Environment Modal --- .../packages/lowcoder/src/i18n/locales/en.ts | 3 ++ .../components/EditEnvironmentModal.tsx | 51 ++++++++++--------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index 85b72168f..721e8b3c6 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -2636,8 +2636,10 @@ export const en = { }, "modal": { "createNewEnvironment": "Create New Environment", + "editEnvironment": "Edit Environment", "cancel": "Cancel", "createEnvironment": "Create Environment", + "saveChanges": "Save Changes", "environmentName": "Environment Name", "pleaseEnterName": "Please enter a name", "nameMinLength": "Name must be at least 2 characters", @@ -2660,6 +2662,7 @@ export const en = { "masterEnvironment": "Master Environment", "alreadyMasterEnvironment": "{name} is already the Master environment", "willBeMaster": "Will be Master", + "currentlyMaster": "Currently Master", "configurationRequirements": "Configuration Requirements", "configurationRequirementsDesc": "Ensure that the API Service URL is configured and correct, the API key is valid, and for license verification make sure you have both the license and plugin properly installed." } diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/EditEnvironmentModal.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/EditEnvironmentModal.tsx index 3b90bc826..37d1b0946 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/EditEnvironmentModal.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/EditEnvironmentModal.tsx @@ -3,6 +3,7 @@ import { Modal, Form, Input, Select, Switch, Button, Alert, Tooltip } from 'antd import { useSelector } from 'react-redux'; import { selectMasterEnvironment, selectHasMasterEnvironment } from 'redux/selectors/enterpriseSelectors'; import { Environment } from '../types/environment.types'; +import { trans } from 'i18n'; const { Option } = Select; @@ -81,14 +82,14 @@ const EditEnvironmentModal: React.FC = ({ return ( - Cancel + {trans("enterprise.environments.modal.cancel")} , ]} > @@ -107,72 +108,72 @@ const EditEnvironmentModal: React.FC = ({ > - + - + + + + - +
@@ -185,15 +186,15 @@ const EditEnvironmentModal: React.FC = ({ {isMaster && ( - Currently Master + {trans("enterprise.environments.modal.currentlyMaster")} )}
Date: Sat, 31 May 2025 00:02:52 +0500 Subject: [PATCH 07/13] add translations for workspace and usergroup tabs --- .../packages/lowcoder/src/i18n/locales/en.ts | 51 ++++++++++++++++++ .../environments/components/UserGroupsTab.tsx | 53 ++++++++++--------- .../environments/components/WorkspacesTab.tsx | 49 ++++++++--------- 3 files changed, 103 insertions(+), 50 deletions(-) diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index 721e8b3c6..fefc7d73b 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -2665,6 +2665,57 @@ export const en = { "currentlyMaster": "Currently Master", "configurationRequirements": "Configuration Requirements", "configurationRequirementsDesc": "Ensure that the API Service URL is configured and correct, the API key is valid, and for license verification make sure you have both the license and plugin properly installed." + }, + "workspaces": { + "title": "Workspaces", + "subtitle": "Manage workspaces in this environment", + "refresh": "Refresh", + "errorLoadingWorkspaces": "Error loading workspaces", + "configurationIssue": "Configuration Issue", + "missingConfiguration": "Missing required configuration: API key or API service URL", + "totalWorkspaces": "Total Workspaces", + "managedWorkspaces": "Managed Workspaces", + "unmanagedWorkspaces": "Unmanaged Workspaces", + "workspace": "Workspace", + "role": "Role", + "status": "Status", + "managed": "Managed", + "unmanaged": "Unmanaged", + "actions": "Actions", + "viewAuditLogs": "View Audit Logs", + "audit": "Audit", + "searchWorkspaces": "Search workspaces by name or ID", + "showAll": "Show All", + "managedOnly": "Managed Only", + "showingResults": "Showing {count} of {total} workspaces", + "paginationTotal": "{start}-{end} of {total} workspaces", + "noWorkspacesFound": "No workspaces found in this environment" + }, + "userGroups": { + "title": "User Groups", + "subtitle": "Manage user groups in this environment", + "refresh": "Refresh", + "errorLoadingUserGroups": "Error loading user groups", + "configurationIssue": "Configuration Issue", + "missingConfiguration": "Missing required configuration: API key or API service URL", + "totalGroups": "Total Groups", + "allUsersGroups": "All Users Groups", + "developerGroups": "Developer Groups", + "customGroups": "Custom Groups", + "userGroup": "User Group", + "type": "Type", + "allUsers": "All Users", + "developers": "Developers", + "custom": "Custom", + "members": "Members", + "adminMembers": "Admin Members", + "created": "Created", + "totalMembersTooltip": "Total number of members in this group", + "adminMembersTooltip": "Number of admin users in this group", + "searchUserGroups": "Search user groups by name or ID", + "showingResults": "Showing {count} of {total} user groups", + "paginationTotal": "{start}-{end} of {total} user groups", + "noUserGroupsFound": "No user groups found in this environment" } } }, diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/UserGroupsTab.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/UserGroupsTab.tsx index e9f781b3c..c97d2f461 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/UserGroupsTab.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/UserGroupsTab.tsx @@ -6,6 +6,7 @@ import { Environment } from '../types/environment.types'; import { UserGroup, UserGroupsTabStats } from '../types/userGroup.types'; import { getEnvironmentUserGroups } from '../services/environments.service'; import { Spin, Empty } from 'antd'; +import { trans } from 'i18n'; const { Search } = Input; @@ -36,7 +37,7 @@ const UserGroupsTab: React.FC = ({ environment }) => { try { // Check for required environment properties if (!environment.environmentApikey || !environment.environmentApiServiceUrl) { - setError('Missing required configuration: API key or API service URL'); + setError(trans("enterprise.environments.userGroups.missingConfiguration")); setLoading(false); return; } @@ -65,7 +66,7 @@ const UserGroupsTab: React.FC = ({ environment }) => { custom }); } catch (err) { - setError(err instanceof Error ? err.message : "Failed to fetch user groups"); + setError(err instanceof Error ? err.message : trans("enterprise.environments.userGroups.errorLoadingUserGroups")); } finally { setLoading(false); setRefreshing(false); @@ -134,7 +135,7 @@ const UserGroupsTab: React.FC = ({ environment }) => { // Table columns const columns = [ { - title: 'User Group', + title: trans("enterprise.environments.userGroups.userGroup"), key: 'group', render: (group: UserGroup) => (
@@ -158,31 +159,31 @@ const UserGroupsTab: React.FC = ({ environment }) => { ), }, { - title: 'Type', + title: trans("enterprise.environments.userGroups.type"), key: 'type', render: (_: any, group: UserGroup) => { if (group.allUsersGroup) return ( - All Users + {trans("enterprise.environments.userGroups.allUsers")} ); if (group.devGroup) return ( - Developers + {trans("enterprise.environments.userGroups.developers")} ); return ( - Custom + {trans("enterprise.environments.userGroups.custom")} ); }, }, { - title: 'Members', + title: trans("enterprise.environments.userGroups.members"), key: 'members', render: (_: any, group: UserGroup) => ( - + {group.stats?.userCount || 0} @@ -190,10 +191,10 @@ const UserGroupsTab: React.FC = ({ environment }) => { ), }, { - title: 'Admin Members', + title: trans("enterprise.environments.userGroups.adminMembers"), key: 'adminMembers', render: (_: any, group: UserGroup) => ( - + {group.stats?.adminUserCount || 0} @@ -201,7 +202,7 @@ const UserGroupsTab: React.FC = ({ environment }) => { ), }, { - title: 'Created', + title: trans("enterprise.environments.userGroups.created"), dataIndex: 'createTime', key: 'createTime', render: (createTime: number) => ( @@ -223,10 +224,10 @@ const UserGroupsTab: React.FC = ({ environment }) => { }}>
- <UsergroupAddOutlined style={{ marginRight: 8 }} /> User Groups + <UsergroupAddOutlined style={{ marginRight: 8 }} /> {trans("enterprise.environments.userGroups.title")}

- Manage user groups in this environment + {trans("enterprise.environments.userGroups.subtitle")}

{/* Error display */} {error && ( = ({ environment }) => { {/* Configuration warnings */} {(!environment.environmentApikey || !environment.environmentApiServiceUrl) && !error && ( = ({ environment }) => { } /> } /> } /> } /> @@ -305,7 +306,7 @@ const UserGroupsTab: React.FC = ({ environment }) => {
) : userGroups.length === 0 ? ( ) : ( @@ -313,7 +314,7 @@ const UserGroupsTab: React.FC = ({ environment }) => { {/* Search Bar */}
setSearchText(value)} onChange={e => setSearchText(e.target.value)} @@ -321,7 +322,7 @@ const UserGroupsTab: React.FC = ({ environment }) => { /> {searchText && filteredUserGroups.length !== userGroups.length && (
- Showing {filteredUserGroups.length} of {userGroups.length} user groups + {trans("enterprise.environments.userGroups.showingResults", { count: filteredUserGroups.length, total: userGroups.length })}
)}
@@ -332,7 +333,7 @@ const UserGroupsTab: React.FC = ({ environment }) => { rowKey="groupId" pagination={{ pageSize: 10, - showTotal: (total, range) => `${range[0]}-${range[1]} of ${total} user groups`, + showTotal: (total, range) => trans("enterprise.environments.userGroups.paginationTotal", { start: range[0], end: range[1], total }), size: 'small' }} size="middle" diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/WorkspacesTab.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/WorkspacesTab.tsx index 26732c76a..8e265350c 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/WorkspacesTab.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/WorkspacesTab.tsx @@ -6,6 +6,7 @@ import { Environment } from '../types/environment.types'; import { Workspace } from '../types/workspace.types'; import { getMergedEnvironmentWorkspaces } from '../services/workspace.service'; import { Spin, Empty } from 'antd'; +import { trans } from 'i18n'; import history from '@lowcoder-ee/util/history'; @@ -38,7 +39,7 @@ const WorkspacesTab: React.FC = ({ environment }) => { try { // Check for required environment properties if (!environment.environmentApikey || !environment.environmentApiServiceUrl) { - setError('Missing required configuration: API key or API service URL'); + setError(trans("enterprise.environments.workspaces.missingConfiguration")); setLoading(false); return; } @@ -52,7 +53,7 @@ const WorkspacesTab: React.FC = ({ environment }) => { setWorkspaces(result.workspaces); setStats(result.stats); } catch (err) { - setError(err instanceof Error ? err.message : "Failed to fetch workspaces"); + setError(err instanceof Error ? err.message : trans("enterprise.environments.workspaces.errorLoadingWorkspaces")); } finally { setLoading(false); setRefreshing(false); @@ -130,7 +131,7 @@ const WorkspacesTab: React.FC = ({ environment }) => { // Table columns const columns = [ { - title: 'Workspace', + title: trans("enterprise.environments.workspaces.workspace"), key: 'workspace', render: (workspace: Workspace) => (
@@ -154,12 +155,12 @@ const WorkspacesTab: React.FC = ({ environment }) => { ), }, { - title: 'Role', + title: trans("enterprise.environments.workspaces.role"), dataIndex: 'role', key: 'role', }, { - title: 'Status', + title: trans("enterprise.environments.workspaces.status"), dataIndex: 'status', key: 'status', render: (status: string) => ( @@ -170,7 +171,7 @@ const WorkspacesTab: React.FC = ({ environment }) => { ), }, { - title: 'Managed', + title: trans("enterprise.environments.workspaces.managed"), key: 'managed', render: (_: any, workspace: Workspace) => ( = ({ environment }) => { ? : } - {workspace.managed ? 'Managed' : 'Unmanaged'} + {workspace.managed ? trans("enterprise.environments.workspaces.managed") : trans("enterprise.environments.workspaces.unmanaged")} ), }, { - title: 'Actions', + title: trans("enterprise.environments.workspaces.actions"), key: 'actions', render: (_: any, workspace: Workspace) => ( e.stopPropagation()}> - + @@ -219,10 +220,10 @@ const WorkspacesTab: React.FC = ({ environment }) => { }}>
- <TeamOutlined style={{ marginRight: 8 }} /> Workspaces + <TeamOutlined style={{ marginRight: 8 }} /> {trans("enterprise.environments.workspaces.title")}

- Manage workspaces in this environment + {trans("enterprise.environments.workspaces.subtitle")}

{/* Error display */} {error && ( = ({ environment }) => { {/* Configuration warnings */} {(!environment.environmentApikey || !environment.environmentApiServiceUrl) && !error && ( = ({ environment }) => { } /> } /> } /> @@ -294,7 +295,7 @@ const WorkspacesTab: React.FC = ({ environment }) => { ) : workspaces.length === 0 ? ( ) : ( @@ -302,7 +303,7 @@ const WorkspacesTab: React.FC = ({ environment }) => { {/* Search and Filter Bar */}
setSearchText(value)} onChange={e => setSearchText(e.target.value)} @@ -314,13 +315,13 @@ const WorkspacesTab: React.FC = ({ environment }) => { icon={} style={{ marginLeft: '8px' }} > - {showManagedOnly ? 'Show All' : 'Managed Only'} + {showManagedOnly ? trans("enterprise.environments.workspaces.showAll") : trans("enterprise.environments.workspaces.managedOnly")}
{searchText && displayedWorkspaces.length !== workspaces.length && (
- Showing {displayedWorkspaces.length} of {workspaces.length} workspaces + {trans("enterprise.environments.workspaces.showingResults", { count: displayedWorkspaces.length, total: workspaces.length })}
)} @@ -330,7 +331,7 @@ const WorkspacesTab: React.FC = ({ environment }) => { rowKey="id" pagination={{ pageSize: 10, - showTotal: (total, range) => `${range[0]}-${range[1]} of ${total} workspaces`, + showTotal: (total, range) => trans("enterprise.environments.workspaces.paginationTotal", { start: range[0], end: range[1], total }), size: 'small' }} size="middle" From 1eddf6dac9ef8547f855bb8e648f10bdbe748eb4 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Sat, 31 May 2025 00:16:31 +0500 Subject: [PATCH 08/13] Add trans for Apps, queries and DS tab --- .../packages/lowcoder/src/i18n/locales/en.ts | 90 +++++++++++++++++++ .../environments/components/AppsTab.tsx | 57 ++++++------ .../components/DataSourcesTab.tsx | 55 ++++++------ .../environments/components/QueriesTab.tsx | 53 +++++------ 4 files changed, 174 insertions(+), 81 deletions(-) diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index fefc7d73b..953467957 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -2716,6 +2716,96 @@ export const en = { "showingResults": "Showing {count} of {total} user groups", "paginationTotal": "{start}-{end} of {total} user groups", "noUserGroupsFound": "No user groups found in this environment" + }, + "apps": { + "title": "Apps", + "subtitle": "Manage workspace applications", + "refresh": "Refresh", + "errorLoadingApps": "Error loading apps", + "configurationIssue": "Configuration Issue", + "missingConfiguration": "Missing required configuration: API key or API service URL", + "totalApps": "Total Apps", + "publishedApps": "Published Apps", + "managedApps": "Managed Apps", + "unmanagedApps": "Unmanaged Apps", + "app": "App", + "status": "Status", + "published": "Published", + "draft": "Draft", + "managed": "Managed", + "unmanaged": "Unmanaged", + "deploy": "Deploy", + "audit": "Audit", + "appMustBeManagedToDeploy": "App must be managed before it can be deployed", + "deployThisApp": "Deploy this app to another environment", + "viewAuditLogs": "View Audit Logs", + "searchApps": "Search apps by name or ID", + "showAll": "Show All", + "managedOnly": "Managed Only", + "showingResults": "Showing {count} of {total} apps", + "paginationTotal": "{start}-{end} of {total} apps", + "noAppsFound": "No apps found in this workspace", + "appRecycled": "This app has been moved to recycle bin", + "managedSuccess": "{name} is now Managed", + "unmanagedSuccess": "{name} is now Unmanaged", + "managedError": "Failed to change managed status for {name}" + }, + "dataSources": { + "title": "Data Sources", + "subtitle": "Manage workspace data connections", + "refresh": "Refresh", + "errorLoadingDataSources": "Error loading data sources", + "configurationIssue": "Configuration Issue", + "missingConfiguration": "Missing required configuration: API key or API service URL", + "totalDataSources": "Total Data Sources", + "availableTypes": "Available Types", + "managed": "Managed", + "unmanaged": "Unmanaged", + "dataSource": "Data Source", + "type": "Type", + "status": "Status", + "deploy": "Deploy", + "audit": "Audit", + "dataSourceMustBeManagedToDeploy": "Data source must be managed before it can be deployed", + "deployThisDataSource": "Deploy this data source to another environment", + "viewAuditLogs": "View Audit Logs", + "searchDataSources": "Search data sources by name or ID", + "showAll": "Show All", + "managedOnly": "Managed Only", + "showingResults": "Showing {count} of {total} data sources", + "paginationTotal": "{start}-{end} of {total} data sources", + "noDataSourcesFound": "No data sources found in this workspace", + "managedSuccess": "{name} is now Managed", + "unmanagedSuccess": "{name} is now Unmanaged", + "managedError": "Failed to change managed status for {name}" + }, + "queries": { + "title": "Queries", + "subtitle": "Manage workspace API queries", + "refresh": "Refresh", + "errorLoadingQueries": "Error loading queries", + "configurationIssue": "Configuration Issue", + "missingConfiguration": "Missing required configuration: API key or API service URL", + "totalQueries": "Total Queries", + "managed": "Managed", + "unmanaged": "Unmanaged", + "query": "Query", + "creator": "Creator", + "status": "Status", + "deploy": "Deploy", + "audit": "Audit", + "queryMustBeManagedToDeploy": "Query must be managed before it can be deployed", + "deployThisQuery": "Deploy this query to another environment", + "viewAuditLogs": "View Audit Logs", + "searchQueries": "Search queries by name or ID", + "showAll": "Show All", + "managedOnly": "Managed Only", + "showingResults": "Showing {count} of {total} queries", + "paginationTotal": "{start}-{end} of {total} queries", + "noQueriesFound": "No queries found in this workspace", + "managedSuccess": "{name} is now Managed", + "unmanagedSuccess": "{name} is now Unmanaged", + "managedError": "Failed to change managed status for {name}" } } }, diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/AppsTab.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/AppsTab.tsx index 150b17242..f63bc3071 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/AppsTab.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/AppsTab.tsx @@ -11,6 +11,7 @@ import { useDeployModal } from '../context/DeployModalContext'; import { appsConfig } from '../config/apps.config'; import history from "@lowcoder-ee/util/history"; import { messageInstance } from 'lowcoder-design/src/components/GlobalInstances'; +import { trans } from 'i18n'; const { Search } = Input; @@ -117,10 +118,10 @@ const AppsTab: React.FC = ({ environment, workspaceId }) => { unmanaged: prev.total - managed })); - messageInstance.success(`${app.name} is now ${checked ? 'Managed' : 'Unmanaged'}`); + messageInstance.success(trans(checked ? "enterprise.environments.apps.managedSuccess" : "enterprise.environments.apps.unmanagedSuccess", { name: app.name })); return true; } catch (error) { - messageInstance.error(`Failed to change managed status for ${app.name}`); + messageInstance.error(trans("enterprise.environments.apps.managedError", { name: app.name })); return false; } finally { setRefreshing(false); @@ -141,7 +142,7 @@ const AppsTab: React.FC = ({ environment, workspaceId }) => { // Table columns const columns = [ { - title: 'App', + title: trans("enterprise.environments.apps.app"), key: 'app', render: (app: App) => (
@@ -158,7 +159,7 @@ const AppsTab: React.FC = ({ environment, workspaceId }) => {
{app.name} {app.applicationStatus === 'RECYCLED' && ( - + = ({ environment, workspaceId }) => { ), }, { - title: 'Status', + title: trans("enterprise.environments.apps.status"), key: 'status', render: (app: App) => ( - {app.published ? : null} {app.published ? 'Published' : 'Draft'} + {app.published ? : null} {app.published ? trans("enterprise.environments.apps.published") : trans("enterprise.environments.apps.draft")} - {app.managed ? : } {app.managed ? 'Managed' : 'Unmanaged'} + {app.managed ? : } {app.managed ? trans("enterprise.environments.apps.managed") : trans("enterprise.environments.apps.unmanaged")} ), }, { - title: 'Managed', + title: trans("enterprise.environments.apps.managed"), key: 'managed', render: (_: any, app: App) => ( = ({ environment, workspaceId }) => { ), }, { - title: 'Actions', + title: trans("enterprise.environments.workspaces.actions"), key: 'actions', render: (_: any, app: App) => ( e.stopPropagation()}> - + - + @@ -289,10 +290,10 @@ const AppsTab: React.FC = ({ environment, workspaceId }) => { }}>
- <AppstoreOutlined style={{ marginRight: 8 }} /> Apps + <AppstoreOutlined style={{ marginRight: 8 }} /> {trans("enterprise.environments.apps.title")}

- Manage workspace applications + {trans("enterprise.environments.apps.subtitle")}

{/* Error display */} {error && ( = ({ environment, workspaceId }) => { {/* Configuration warnings */} {(!environment.environmentApikey || !environment.environmentApiServiceUrl) && !error && ( = ({ environment, workspaceId }) => { } /> } /> } /> } /> @@ -371,7 +372,7 @@ const AppsTab: React.FC = ({ environment, workspaceId }) => {
) : apps.length === 0 ? ( ) : ( @@ -379,7 +380,7 @@ const AppsTab: React.FC = ({ environment, workspaceId }) => { {/* Search and Filter Bar */}
setSearchText(value)} onChange={e => setSearchText(e.target.value)} @@ -391,13 +392,13 @@ const AppsTab: React.FC = ({ environment, workspaceId }) => { icon={} style={{ marginLeft: '8px' }} > - {showManagedOnly ? 'Show All' : 'Managed Only'} + {showManagedOnly ? trans("enterprise.environments.apps.showAll") : trans("enterprise.environments.apps.managedOnly")}
{searchText && displayedApps.length !== apps.length && (
- Showing {displayedApps.length} of {apps.length} apps + {trans("enterprise.environments.apps.showingResults", { count: displayedApps.length, total: apps.length })}
)} @@ -407,7 +408,7 @@ const AppsTab: React.FC = ({ environment, workspaceId }) => { rowKey="applicationId" pagination={{ pageSize: 10, - showTotal: (total, range) => `${range[0]}-${range[1]} of ${total} apps`, + showTotal: (total, range) => trans("enterprise.environments.apps.paginationTotal", { start: range[0], end: range[1], total }), size: 'small' }} size="middle" diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/DataSourcesTab.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/DataSourcesTab.tsx index 9cdb0b55a..3179349fa 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/DataSourcesTab.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/DataSourcesTab.tsx @@ -21,6 +21,7 @@ import { ManagedObjectType, setManagedObject, unsetManagedObject } from '../serv import { useDeployModal } from '../context/DeployModalContext'; import { dataSourcesConfig } from '../config/data-sources.config'; import history from "@lowcoder-ee/util/history"; +import { trans } from 'i18n'; const { Search } = Input; @@ -115,10 +116,10 @@ const DataSourcesTab: React.FC = ({ environment, workspaceI unmanaged: prev.total - managed })); - messageInstance.success(`${dataSource.name} is now ${checked ? 'Managed' : 'Unmanaged'}`); + messageInstance.success(trans(checked ? "enterprise.environments.dataSources.managedSuccess" : "enterprise.environments.dataSources.unmanagedSuccess", { name: dataSource.name })); return true; } catch (error) { - messageInstance.error(`Failed to change managed status for ${dataSource.name}`); + messageInstance.error(trans("enterprise.environments.dataSources.managedError", { name: dataSource.name })); return false; } finally { setRefreshing(false); @@ -139,7 +140,7 @@ const DataSourcesTab: React.FC = ({ environment, workspaceI // Table columns const columns = [ { - title: 'Data Source', + title: trans("enterprise.environments.dataSources.dataSource"), key: 'datasource', render: (dataSource: DataSource) => (
@@ -161,7 +162,7 @@ const DataSourcesTab: React.FC = ({ environment, workspaceI ), }, { - title: 'Type', + title: trans("enterprise.environments.dataSources.type"), dataIndex: 'type', key: 'type', render: (type: string) => ( @@ -171,19 +172,19 @@ const DataSourcesTab: React.FC = ({ environment, workspaceI ), }, { - title: 'Status', + title: trans("enterprise.environments.dataSources.status"), key: 'status', render: (dataSource: DataSource) => ( - {dataSource.managed ? : } {dataSource.managed ? 'Managed' : 'Unmanaged'} + {dataSource.managed ? : } {dataSource.managed ? trans("enterprise.environments.dataSources.managed") : trans("enterprise.environments.dataSources.unmanaged")} ), }, { - title: 'Managed', + title: trans("enterprise.environments.dataSources.managed"), key: 'managed', render: (_: any, dataSource: DataSource) => ( = ({ environment, workspaceI ), }, { - title: 'Actions', + title: trans("enterprise.environments.workspaces.actions"), key: 'actions', render: (_: any, dataSource: DataSource) => ( e.stopPropagation()}> - + - + @@ -286,10 +287,10 @@ const DataSourcesTab: React.FC = ({ environment, workspaceI }}>
- <DatabaseOutlined style={{ marginRight: 8 }} /> Data Sources + <DatabaseOutlined style={{ marginRight: 8 }} /> {trans("enterprise.environments.dataSources.title")}

- Manage workspace data connections + {trans("enterprise.environments.dataSources.subtitle")}

{/* Error display */} {error && ( = ({ environment, workspaceI {/* Configuration warnings */} {(!environment.environmentApikey || !environment.environmentApiServiceUrl) && !error && ( = ({ environment, workspaceI } /> } /> } /> } /> @@ -368,7 +369,7 @@ const DataSourcesTab: React.FC = ({ environment, workspaceI ) : dataSources.length === 0 ? ( ) : ( @@ -376,7 +377,7 @@ const DataSourcesTab: React.FC = ({ environment, workspaceI {/* Search and Filter Bar */}
setSearchText(value)} onChange={e => setSearchText(e.target.value)} @@ -388,13 +389,13 @@ const DataSourcesTab: React.FC = ({ environment, workspaceI icon={} style={{ marginLeft: '8px' }} > - {showManagedOnly ? 'Show All' : 'Managed Only'} + {showManagedOnly ? trans("enterprise.environments.dataSources.showAll") : trans("enterprise.environments.dataSources.managedOnly")}
{searchText && displayedDataSources.length !== dataSources.length && (
- Showing {displayedDataSources.length} of {dataSources.length} data sources + {trans("enterprise.environments.dataSources.showingResults", { count: displayedDataSources.length, total: dataSources.length })}
)} @@ -404,7 +405,7 @@ const DataSourcesTab: React.FC = ({ environment, workspaceI rowKey="id" pagination={{ pageSize: 10, - showTotal: (total, range) => `${range[0]}-${range[1]} of ${total} data sources`, + showTotal: (total, range) => trans("enterprise.environments.dataSources.paginationTotal", { start: range[0], end: range[1], total }), size: 'small' }} size="middle" diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/QueriesTab.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/QueriesTab.tsx index 0d754025f..49e55b6d4 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/QueriesTab.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/QueriesTab.tsx @@ -23,6 +23,7 @@ import { ManagedObjectType, setManagedObject, unsetManagedObject } from '../serv import { useDeployModal } from '../context/DeployModalContext'; import { queryConfig } from '../config/query.config'; import history from "@lowcoder-ee/util/history"; +import { trans } from 'i18n'; const { Search } = Input; @@ -116,10 +117,10 @@ const QueriesTab: React.FC = ({ environment, workspaceId }) => unmanaged: prev.total - managed })); - messageInstance.success(`${query.name} is now ${checked ? 'Managed' : 'Unmanaged'}`); + messageInstance.success(trans(checked ? "enterprise.environments.queries.managedSuccess" : "enterprise.environments.queries.unmanagedSuccess", { name: query.name })); return true; } catch (error) { - messageInstance.error(`Failed to change managed status for ${query.name}`); + messageInstance.error(trans("enterprise.environments.queries.managedError", { name: query.name })); return false; } finally { setRefreshing(false); @@ -151,7 +152,7 @@ const QueriesTab: React.FC = ({ environment, workspaceId }) => // Table columns const columns = [ { - title: 'Query', + title: trans("enterprise.environments.queries.query"), key: 'query', render: (query: Query) => (
@@ -174,7 +175,7 @@ const QueriesTab: React.FC = ({ environment, workspaceId }) => ), }, { - title: 'Creator', + title: trans("enterprise.environments.queries.creator"), dataIndex: 'creatorName', key: 'creatorName', render: (creatorName: string) => ( @@ -189,19 +190,19 @@ const QueriesTab: React.FC = ({ environment, workspaceId }) => ) }, { - title: 'Status', + title: trans("enterprise.environments.queries.status"), key: 'status', render: (query: Query) => ( - {query.managed ? : } {query.managed ? 'Managed' : 'Unmanaged'} + {query.managed ? : } {query.managed ? trans("enterprise.environments.queries.managed") : trans("enterprise.environments.queries.unmanaged")} ), }, { - title: 'Managed', + title: trans("enterprise.environments.queries.managed"), key: 'managed', render: (_: any, query: Query) => ( = ({ environment, workspaceId }) => ), }, { - title: 'Actions', + title: trans("enterprise.environments.workspaces.actions"), key: 'actions', render: (_: any, query: Query) => ( e.stopPropagation()}> - + - + @@ -286,10 +287,10 @@ const QueriesTab: React.FC = ({ environment, workspaceId }) => }}>
- <ThunderboltOutlined style={{ marginRight: 8 }} /> Queries + <ThunderboltOutlined style={{ marginRight: 8 }} /> {trans("enterprise.environments.queries.title")}

- Manage workspace API queries + {trans("enterprise.environments.queries.subtitle")}

{/* Error display */} {error && ( = ({ environment, workspaceId }) => {/* Configuration warnings */} {(!environment.environmentApikey || !environment.environmentApiServiceUrl) && !error && ( = ({ environment, workspaceId }) => } /> } /> } /> @@ -361,7 +362,7 @@ const QueriesTab: React.FC = ({ environment, workspaceId }) => ) : queries.length === 0 ? ( ) : ( @@ -369,7 +370,7 @@ const QueriesTab: React.FC = ({ environment, workspaceId }) => {/* Search and Filter Bar */}
setSearchText(value)} onChange={e => setSearchText(e.target.value)} @@ -381,13 +382,13 @@ const QueriesTab: React.FC = ({ environment, workspaceId }) => icon={} style={{ marginLeft: '8px' }} > - {showManagedOnly ? 'Show All' : 'Managed Only'} + {showManagedOnly ? trans("enterprise.environments.queries.showAll") : trans("enterprise.environments.queries.managedOnly")}
{searchText && displayedQueries.length !== queries.length && (
- Showing {displayedQueries.length} of {queries.length} queries + {trans("enterprise.environments.queries.showingResults", { count: displayedQueries.length, total: queries.length })}
)} @@ -397,7 +398,7 @@ const QueriesTab: React.FC = ({ environment, workspaceId }) => rowKey="id" pagination={{ pageSize: 10, - showTotal: (total, range) => `${range[0]}-${range[1]} of ${total} queries`, + showTotal: (total, range) => trans("enterprise.environments.queries.paginationTotal", { start: range[0], end: range[1], total }), size: 'small' }} size="middle" From 5b241f819287416a7faa03e21be10e4a11e47c01 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Sat, 31 May 2025 00:24:52 +0500 Subject: [PATCH 09/13] add trans for environments services --- .../packages/lowcoder/src/i18n/locales/en.ts | 52 ++++++++++++ .../services/enterprise.service.ts | 35 ++++---- .../services/environments.service.ts | 79 ++++++++++--------- 3 files changed, 110 insertions(+), 56 deletions(-) diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index 953467957..5de851179 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -2806,6 +2806,58 @@ export const en = { "managedSuccess": "{name} is now Managed", "unmanagedSuccess": "{name} is now Unmanaged", "managedError": "Failed to change managed status for {name}" + }, + + // Service error messages + "services": { + "environments": { + "missingEnvironmentId": "Missing environment ID", + "failedToUpdateEnvironment": "Failed to update environment", + "environmentCreatedSuccessfully": "Environment created successfully", + "failedToCreateEnvironment": "Failed to create environment", + "failedToFetchEnvironments": "Failed to fetch environments", + "failedToFetchEnvironment": "Failed to fetch environment", + "environmentIdRequired": "Environment ID is required", + "apiKeyRequiredForWorkspaces": "API key is required to fetch workspaces", + "apiServiceUrlRequiredForWorkspaces": "API service URL is required to fetch workspaces", + "failedToFetchWorkspaces": "Failed to fetch workspaces", + "apiKeyRequiredForUserGroups": "API key is required to fetch user groups", + "apiServiceUrlRequiredForUserGroups": "API service URL is required to fetch user groups", + "failedToFetchUserGroups": "Failed to fetch user groups", + "workspaceIdRequired": "Workspace ID is required", + "apiKeyRequiredForApps": "API key is required to fetch apps", + "apiServiceUrlRequiredForApps": "API service URL is required to fetch apps", + "failedToFetchWorkspaceApps": "Failed to fetch workspace apps", + "apiKeyRequiredForDataSources": "API key is required to fetch data sources", + "apiServiceUrlRequiredForDataSources": "API service URL is required to fetch data sources", + "failedToFetchWorkspaceDataSources": "Failed to fetch workspace data sources", + "apiKeyRequiredForQueries": "API key is required to fetch queries", + "apiServiceUrlRequiredForQueries": "API service URL is required to fetch queries", + "failedToFetchWorkspaceQueries": "Failed to fetch workspace queries", + "apiServiceUrlNotConfigured": "API service URL not configured", + "licenseCheckFailed": "License check failed", + "apiKeyRequiredForDeploymentId": "API key is required to fetch deployment ID", + "failedToFetchDeploymentId": "Failed to fetch deployment ID" + }, + "enterprise": { + "missingEnvironmentId": "Missing environment ID", + "failedToFetchManagedWorkspaces": "Failed to fetch managed workspaces", + "missingRequiredParamsToConnectOrg": "Missing required params to connect workspace", + "failedToConnectOrg": "Failed to connect workspace", + "missingOrgGidToUnconnectWorkspace": "Missing workspace GID to unconnect workspace", + "failedToUnconnectOrg": "Failed to unconnect workspace", + "failedToConnectApp": "Failed to connect app", + "failedToUnconnectApp": "Failed to unconnect app", + "failedToFetchDataSources": "Failed to fetch data sources", + "failedToDeployDataSource": "Failed to deploy data source", + "failedToDisconnectManagedDataSource": "Failed to disconnect managed data source", + "environmentIdRequired": "Environment ID is required", + "failedToFetchQueries": "Failed to fetch queries", + "environmentIdAndQueryGidRequired": "Environment ID and Query GID are required", + "failedToDeployQuery": "Failed to deploy query", + "queryGidRequired": "Query GID is required", + "failedToDisconnectQuery": "Failed to disconnect query" + } } } }, diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/enterprise.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/enterprise.service.ts index f676f1734..208085c69 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/enterprise.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/enterprise.service.ts @@ -1,5 +1,6 @@ import axios from "axios"; import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; +import { trans } from "i18n"; import { ManagedOrg } from "../types/enterprise.types"; import { Query } from "../types/query.types"; @@ -17,7 +18,7 @@ export async function getManagedWorkspaces( ): Promise { if (!environmentId) { - throw new Error("Missing environmentId"); + throw new Error(trans("enterprise.environments.services.enterprise.missingEnvironmentId")); } try { @@ -25,7 +26,7 @@ export async function getManagedWorkspaces( const all: ManagedOrg[] = res.data.data; return all.filter(org => org.environmentId === environmentId); } catch (err) { - const errorMsg = err instanceof Error ? err.message : "Failed to fetch managed workspaces"; + const errorMsg = err instanceof Error ? err.message : trans("enterprise.environments.services.enterprise.failedToFetchManagedWorkspaces"); messageInstance.error(errorMsg); throw err; } @@ -48,7 +49,7 @@ export async function connectManagedWorkspace( orgTags: string[] = [], ) { if (!environmentId || !orgName || !org_gid) { - throw new Error("Missing required params to connect org"); + throw new Error(trans("enterprise.environments.services.enterprise.missingRequiredParamsToConnectOrg")); } try { @@ -62,7 +63,7 @@ export async function connectManagedWorkspace( const res = await axios.post(`/api/plugins/enterprise/org`, payload); return res.data; } catch (err) { - const errorMsg = err instanceof Error ? err.message : "Failed to connect org"; + const errorMsg = err instanceof Error ? err.message : trans("enterprise.environments.services.enterprise.failedToConnectOrg"); messageInstance.error(errorMsg); throw err; } @@ -78,7 +79,7 @@ export async function connectManagedWorkspace( */ export async function unconnectManagedWorkspace(orgGid: string) { if (!orgGid) { - throw new Error("Missing orgGid to unconnect workspace"); + throw new Error(trans("enterprise.environments.services.enterprise.missingOrgGidToUnconnectWorkspace")); } try { @@ -87,7 +88,7 @@ export async function unconnectManagedWorkspace(orgGid: string) { }); } catch (err) { const errorMsg = - err instanceof Error ? err.message : "Failed to unconnect org"; + err instanceof Error ? err.message : trans("enterprise.environments.services.enterprise.failedToUnconnectOrg"); messageInstance.error(errorMsg); throw err; } @@ -123,7 +124,7 @@ export async function connectManagedApp( return res.data; } catch (err) { const errorMsg = - err instanceof Error ? err.message : "Failed to connect app"; + err instanceof Error ? err.message : trans("enterprise.environments.services.enterprise.failedToConnectApp"); messageInstance.error(errorMsg); throw err; } @@ -136,7 +137,7 @@ export async function unconnectManagedApp(appGid: string) { params: { appGid }, }); } catch (err) { - const errorMsg = err instanceof Error ? err.message : "Failed to unconnect app"; + const errorMsg = err instanceof Error ? err.message : trans("enterprise.environments.services.enterprise.failedToUnconnectApp"); messageInstance.error(errorMsg); throw err; } @@ -151,7 +152,7 @@ export const getManagedDataSources = async (environmentId: string): Promise { try { if (!environmentId) { - throw new Error('Environment ID is required'); + throw new Error(trans("enterprise.environments.services.enterprise.environmentIdRequired")); } // Get managed queries from the enterprise endpoint @@ -226,7 +227,7 @@ export async function getManagedQueries(environmentId: string): Promise })); } catch (error) { - const errorMsg = error instanceof Error ? error.message : 'Failed to fetch queries'; + const errorMsg = error instanceof Error ? error.message : trans("enterprise.environments.services.enterprise.failedToFetchQueries"); messageInstance.error(errorMsg); throw error; } @@ -240,7 +241,7 @@ export async function connectManagedQuery( ): Promise { try { if (!environmentId || !queryGid) { - throw new Error('Environment ID and Query GID are required'); + throw new Error(trans("enterprise.environments.services.enterprise.environmentIdAndQueryGidRequired")); } const response = await axios.post('/api/plugins/enterprise/qlQuery', { @@ -253,7 +254,7 @@ export async function connectManagedQuery( return response.status === 200; } catch (error) { - const errorMsg = error instanceof Error ? error.message : 'Failed to deploy query'; + const errorMsg = error instanceof Error ? error.message : trans("enterprise.environments.services.enterprise.failedToDeployQuery"); messageInstance.error(errorMsg); throw error; } @@ -263,7 +264,7 @@ export async function connectManagedQuery( export async function unconnectManagedQuery(queryGid: string): Promise { try { if (!queryGid) { - throw new Error('Query GID is required'); + throw new Error(trans("enterprise.environments.services.enterprise.queryGidRequired")); } const response = await axios.delete(`/api/plugins/enterprise/qlQuery`, { @@ -275,7 +276,7 @@ export async function unconnectManagedQuery(queryGid: string): Promise return response.status === 200; } catch (error) { - const errorMsg = error instanceof Error ? error.message : 'Failed to disconnect query'; + const errorMsg = error instanceof Error ? error.message : trans("enterprise.environments.services.enterprise.failedToDisconnectQuery"); messageInstance.error(errorMsg); throw error; } diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts index b3ccb5314..6f38a87b3 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts @@ -1,5 +1,6 @@ import axios from "axios"; import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; +import { trans } from "i18n"; import { Environment } from "../types/environment.types"; import { Workspace } from "../types/workspace.types"; import { UserGroup } from "../types/userGroup.types"; @@ -16,7 +17,7 @@ export async function updateEnvironment( environmentData: Partial ): Promise { if (!environmentId) { - throw new Error("Missing environmentId"); + throw new Error(trans("enterprise.environments.services.environments.missingEnvironmentId")); } try { @@ -39,7 +40,7 @@ export async function updateEnvironment( return res.data; } catch (err) { - const errorMsg = err instanceof Error ? err.message : "Failed to update environment"; + const errorMsg = err instanceof Error ? err.message : trans("enterprise.environments.services.environments.failedToUpdateEnvironment"); messageInstance.error(errorMsg); throw err; } @@ -70,13 +71,13 @@ export async function createEnvironment( const res = await axios.post(`/api/plugins/enterprise/environments`, payload); if (res.data) { - messageInstance.success("Environment created successfully"); + messageInstance.success(trans("enterprise.environments.services.environments.environmentCreatedSuccessfully")); return res.data; } else { - throw new Error("Failed to create environment"); + throw new Error(trans("enterprise.environments.services.environments.failedToCreateEnvironment")); } } catch (err) { - const errorMsg = err instanceof Error ? err.message : "Failed to create environment"; + const errorMsg = err instanceof Error ? err.message : trans("enterprise.environments.services.environments.failedToCreateEnvironment"); messageInstance.error(errorMsg); throw err; } @@ -97,7 +98,7 @@ export async function getEnvironments(): Promise { return response.data.data || []; } catch (error) { const errorMessage = - error instanceof Error ? error.message : "Failed to fetch environments"; + error instanceof Error ? error.message : trans("enterprise.environments.services.environments.failedToFetchEnvironments"); messageInstance.error(errorMessage); throw error; } @@ -115,7 +116,7 @@ export async function getEnvironmentById(id: string): Promise { ); if (!response.data) { - throw new Error("Failed to fetch environment"); + throw new Error(trans("enterprise.environments.services.environments.failedToFetchEnvironment")); } const environment = response.data.data; @@ -140,18 +141,18 @@ export async function getEnvironmentById(id: string): Promise { } else { envWithLicense.isLicensed = false; envWithLicense.licenseStatus = 'error'; - envWithLicense.licenseError = 'API service URL not configured'; + envWithLicense.licenseError = trans("enterprise.environments.services.environments.apiServiceUrlNotConfigured"); } } catch (error) { envWithLicense.isLicensed = false; envWithLicense.licenseStatus = 'error'; - envWithLicense.licenseError = error instanceof Error ? error.message : 'License check failed'; + envWithLicense.licenseError = error instanceof Error ? error.message : trans("enterprise.environments.services.environments.licenseCheckFailed"); } return envWithLicense; } catch (error) { const errorMessage = - error instanceof Error ? error.message : "Failed to fetch environment"; + error instanceof Error ? error.message : trans("enterprise.environments.services.environments.failedToFetchEnvironment"); messageInstance.error(errorMessage); throw error; } @@ -177,14 +178,14 @@ export async function getEnvironmentWorkspaces( try { // Check if required parameters are provided if (!environmentId) { - throw new Error("Environment ID is required"); + throw new Error(trans("enterprise.environments.services.environments.environmentIdRequired")); } if (!apiKey) { - throw new Error("API key is required to fetch workspaces"); + throw new Error(trans("enterprise.environments.services.environments.apiKeyRequiredForWorkspaces")); } if (!apiServiceUrl) { - throw new Error('API service URL is required to fetch workspaces'); + throw new Error(trans("enterprise.environments.services.environments.apiServiceUrlRequiredForWorkspaces")); } // Set up headers with the API key @@ -197,7 +198,7 @@ export async function getEnvironmentWorkspaces( // Check if response is valid if (!response.data || !response.data.success) { - throw new Error(response.data?.message || "Failed to fetch workspaces"); + throw new Error(response.data?.message || trans("enterprise.environments.services.environments.failedToFetchWorkspaces")); } // Extract workspaces from the response @@ -224,7 +225,7 @@ export async function getEnvironmentWorkspaces( } catch (error) { // Handle and transform error const errorMessage = - error instanceof Error ? error.message : "Failed to fetch workspaces"; + error instanceof Error ? error.message : trans("enterprise.environments.services.environments.failedToFetchWorkspaces"); messageInstance.error(errorMessage); throw error; } @@ -244,15 +245,15 @@ export async function getEnvironmentUserGroups( try { // Check if required parameters are provided if (!environmentId) { - throw new Error('Environment ID is required'); + throw new Error(trans("enterprise.environments.services.environments.environmentIdRequired")); } if (!apiKey) { - throw new Error('API key is required to fetch user groups'); + throw new Error(trans("enterprise.environments.services.environments.apiKeyRequiredForUserGroups")); } if (!apiServiceUrl) { - throw new Error('API service URL is required to fetch user groups'); + throw new Error(trans("enterprise.environments.services.environments.apiServiceUrlRequiredForUserGroups")); } // Set up headers with the Bearer token format @@ -265,7 +266,7 @@ export async function getEnvironmentUserGroups( // Check if response is valid if (!response.data) { - throw new Error('Failed to fetch user groups'); + throw new Error(trans("enterprise.environments.services.environments.failedToFetchUserGroups")); } // The response data is already an array of user groups @@ -274,7 +275,7 @@ export async function getEnvironmentUserGroups( return userGroups; } catch (error) { // Handle and transform error - const errorMessage = error instanceof Error ? error.message : 'Failed to fetch user groups'; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.environments.failedToFetchUserGroups"); messageInstance.error(errorMessage); throw error; } @@ -341,15 +342,15 @@ export async function getWorkspaceApps( try { // Check if required parameters are provided if (!workspaceId) { - throw new Error('Workspace ID is required'); + throw new Error(trans("enterprise.environments.services.environments.workspaceIdRequired")); } if (!apiKey) { - throw new Error('API key is required to fetch apps'); + throw new Error(trans("enterprise.environments.services.environments.apiKeyRequiredForApps")); } if (!apiServiceUrl) { - throw new Error('API service URL is required to fetch apps'); + throw new Error(trans("enterprise.environments.services.environments.apiServiceUrlRequiredForApps")); } // Set up headers with the Bearer token format @@ -384,7 +385,7 @@ export async function getWorkspaceApps( } catch (error) { // Handle and transform error - const errorMessage = error instanceof Error ? error.message : 'Failed to fetch workspace apps'; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.environments.failedToFetchWorkspaceApps"); messageInstance.error(errorMessage); throw error; } @@ -410,15 +411,15 @@ export async function getWorkspaceDataSources( try { // Check if required parameters are provided if (!workspaceId) { - throw new Error('Workspace ID is required'); + throw new Error(trans("enterprise.environments.services.environments.workspaceIdRequired")); } if (!apiKey) { - throw new Error('API key is required to fetch data sources'); + throw new Error(trans("enterprise.environments.services.environments.apiKeyRequiredForDataSources")); } if (!apiServiceUrl) { - throw new Error('API service URL is required to fetch data sources'); + throw new Error(trans("enterprise.environments.services.environments.apiServiceUrlRequiredForDataSources")); } // Set up headers with the Bearer token format @@ -442,7 +443,7 @@ export async function getWorkspaceDataSources( return response.data.data ; } catch (error) { // Handle and transform error - const errorMessage = error instanceof Error ? error.message : 'Failed to fetch workspace data sources'; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.environments.failedToFetchWorkspaceDataSources"); messageInstance.error(errorMessage); throw error; } @@ -471,15 +472,15 @@ export async function getWorkspaceQueries( try { // Check if required parameters are provided if (!workspaceId) { - throw new Error('Workspace ID is required'); + throw new Error(trans("enterprise.environments.services.environments.workspaceIdRequired")); } if (!apiKey) { - throw new Error('API key is required to fetch queries'); + throw new Error(trans("enterprise.environments.services.environments.apiKeyRequiredForQueries")); } if (!apiServiceUrl) { - throw new Error('API service URL is required to fetch queries'); + throw new Error(trans("enterprise.environments.services.environments.apiServiceUrlRequiredForQueries")); } // Set up headers with the Bearer token format @@ -524,7 +525,7 @@ export async function getWorkspaceQueries( } catch (error) { // Handle and transform error - const errorMessage = error instanceof Error ? error.message : 'Failed to fetch workspace queries'; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.environments.failedToFetchWorkspaceQueries"); messageInstance.error(errorMessage); throw error; } @@ -561,12 +562,12 @@ export async function getEnvironmentsWithLicenseStatus(): Promise } else { envWithLicense.isLicensed = false; envWithLicense.licenseStatus = 'error'; - envWithLicense.licenseError = 'API service URL not configured'; + envWithLicense.licenseError = trans("enterprise.environments.services.environments.apiServiceUrlNotConfigured"); } } catch (error) { envWithLicense.isLicensed = false; envWithLicense.licenseStatus = 'error'; - envWithLicense.licenseError = error instanceof Error ? error.message : 'License check failed'; + envWithLicense.licenseError = error instanceof Error ? error.message : trans("enterprise.environments.services.environments.licenseCheckFailed"); } return envWithLicense; @@ -576,7 +577,7 @@ export async function getEnvironmentsWithLicenseStatus(): Promise return environmentsWithLicense; } catch (error) { const errorMessage = - error instanceof Error ? error.message : "Failed to fetch environments"; + error instanceof Error ? error.message : trans("enterprise.environments.services.environments.failedToFetchEnvironments"); messageInstance.error(errorMessage); throw error; } @@ -595,11 +596,11 @@ export async function getEnvironmentDeploymentId( try { // Check if required parameters are provided if (!apiServiceUrl) { - throw new Error('API service URL is required'); + throw new Error(trans("enterprise.environments.services.environments.apiServiceUrlRequiredForWorkspaces")); } if (!apiKey) { - throw new Error('API key is required to fetch deployment ID'); + throw new Error(trans("enterprise.environments.services.environments.apiKeyRequiredForDeploymentId")); } // Set up headers with the Bearer token format @@ -612,14 +613,14 @@ export async function getEnvironmentDeploymentId( // Check if response is valid if (!response.data) { - throw new Error('Failed to fetch deployment ID'); + throw new Error(trans("enterprise.environments.services.environments.failedToFetchDeploymentId")); } // The response should return a string directly return response.data; } catch (error) { // Handle and transform error - const errorMessage = error instanceof Error ? error.message : 'Failed to fetch deployment ID'; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.environments.failedToFetchDeploymentId"); messageInstance.error(errorMessage); throw error; } From 7daf6d5a7692fa4e9638daec40cd3dfbf9d71d01 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Sat, 31 May 2025 00:41:22 +0500 Subject: [PATCH 10/13] Add deployment related trans --- .../packages/lowcoder/src/i18n/locales/en.ts | 57 +++++++++++++++++++ .../components/DeployItemModal.tsx | 38 +++++++------ .../components/credentialConfirmations.tsx | 32 ++++++----- .../environments/config/apps.config.tsx | 16 +++--- .../config/data-sources.config.tsx | 5 +- .../environments/config/query.config.tsx | 5 +- .../environments/config/workspace.config.tsx | 3 +- 7 files changed, 111 insertions(+), 45 deletions(-) diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index 5de851179..d0b638e50 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -2808,6 +2808,63 @@ export const en = { "managedError": "Failed to change managed status for {name}" }, + // Deploy Modal and Credential Confirmations + "deployModal": { + "deployTitle": "Deploy {singularLabel}: {name}", + "loadingEnvironments": "Loading environments...", + "sourceEnvironment": "Source Environment", + "targetEnvironment": "Target Environment", + "selectTargetEnvironment": "Select target environment", + "selectTargetEnvironmentValidation": "Please select a target environment", + "confirmed": "Confirmed", + "cancel": "Cancel", + "deploy": "Deploy", + "targetEnvironmentNotFound": "Target environment not found", + "confirmCredentialOverwrite": "Please confirm credential overwrite before deploying", + "deploySuccess": "Successfully deployed {name} to target environment", + "deployFailed": "Failed to deploy {singularLabel}", + "selectFieldValidation": "Please select {label}", + "selectFieldPlaceholder": "Select {label}", + "inputFieldValidation": "Please input {label}", + "inputFieldPlaceholder": "Enter {label}" + }, + + "credentialConfirmations": { + "firstConfirmation": { + "title": "Overwrite Credentials Warning", + "message": "This action will overwrite existing credentials in the target environment.", + "description": "This is a serious operation that may affect other applications and users.", + "question": "Are you sure you want to proceed?", + "continueButton": "Continue", + "cancelButton": "Cancel" + }, + "secondConfirmation": { + "title": "Final Confirmation Required", + "message": "Final Warning: Credential Overwrite", + "description": "You are about to overwrite credentials in the target environment. This action cannot be undone and may break existing integrations.", + "confirmOnceMore": "Please confirm one more time.", + "finalQuestion": "Are you absolutely certain you want to overwrite the credentials?", + "confirmButton": "Yes, Overwrite Credentials", + "cancelButton": "Cancel" + } + }, + + "config": { + "singularLabels": { + "app": "App", + "dataSource": "Data Source", + "query": "Query", + "workspace": "Workspace" + }, + "fields": { + "updateDependenciesIfNeeded": "Update Dependencies If Needed", + "publishOnTarget": "Publish On Target", + "publicToAll": "Public To All", + "publicToMarketplace": "Public To Marketplace", + "overwriteCredentials": "Overwrite Credentials" + } + }, + // Service error messages "services": { "environments": { diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/DeployItemModal.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/DeployItemModal.tsx index b7051185c..757f55153 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/DeployItemModal.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/DeployItemModal.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { Modal, Form, Select, Checkbox, Button, Spin, Input, Tag, Space, Alert } from 'antd'; import { messageInstance } from 'lowcoder-design/src/components/GlobalInstances'; +import { trans } from "i18n"; import { useSelector } from 'react-redux'; import { selectLicensedEnvironments, selectEnvironmentsLoading } from 'redux/selectors/enterpriseSelectors'; import { Environment } from '../types/environment.types'; @@ -87,13 +88,13 @@ function DeployItemModal({ const targetEnv = licensedEnvironments.find(env => env.environmentId === values.targetEnvId); if (!targetEnv) { - messageInstance.error('Target environment not found'); + messageInstance.error(trans("enterprise.environments.deployModal.targetEnvironmentNotFound")); return; } // Additional check for credential overwrite if (values.deployCredential && credentialConfirmationStep !== 2) { - messageInstance.error('Please confirm credential overwrite before deploying'); + messageInstance.error(trans("enterprise.environments.deployModal.confirmCredentialOverwrite")); return; } @@ -105,12 +106,12 @@ function DeployItemModal({ // Execute deployment await config.deploy.execute(params); - messageInstance.success(`Successfully deployed ${item.name} to target environment`); + messageInstance.success(trans("enterprise.environments.deployModal.deploySuccess", { name: item.name })); if (onSuccess) onSuccess(); onClose(); } catch (error) { console.error('Deployment error:', error); - messageInstance.error(`Failed to deploy ${config.deploy.singularLabel.toLowerCase()}`); + messageInstance.error(trans("enterprise.environments.deployModal.deployFailed", { singularLabel: config.deploy.singularLabel.toLowerCase() })); } finally { setDeploying(false); } @@ -118,7 +119,10 @@ function DeployItemModal({ return ( {isLoading ? (
- +
) : (
{/* Source environment display */} - + {sourceEnvironment.environmentName} {sourceEnvironment.environmentType && ( @@ -147,10 +151,10 @@ function DeployItemModal({ - {targetEnvironments.map((env) => ( @@ -196,7 +200,7 @@ function DeployItemModal({ style={{ marginLeft: 8 }} icon={} > - Confirmed + {trans("enterprise.environments.deployModal.confirmed")} )} @@ -209,9 +213,9 @@ function DeployItemModal({ name={field.name} label={field.label} initialValue={field.defaultValue} - rules={field.required ? [{ required: true, message: `Please select ${field.label}` }] : undefined} + rules={field.required ? [{ required: true, message: trans("enterprise.environments.deployModal.selectFieldValidation", { label: field.label }) }] : undefined} > - {field.options?.map(option => ( {option.label} @@ -227,9 +231,9 @@ function DeployItemModal({ name={field.name} label={field.label} initialValue={field.defaultValue} - rules={field.required ? [{ required: true, message: `Please input ${field.label}` }] : undefined} + rules={field.required ? [{ required: true, message: trans("enterprise.environments.deployModal.inputFieldValidation", { label: field.label }) }] : undefined} > - + ); default: @@ -239,10 +243,10 @@ function DeployItemModal({ diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/credentialConfirmations.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/credentialConfirmations.tsx index dfaee1cc5..694eec008 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/credentialConfirmations.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/credentialConfirmations.tsx @@ -1,6 +1,6 @@ - import { Modal, Alert } from 'antd'; import { ExclamationCircleOutlined, WarningOutlined } from '@ant-design/icons'; +import { trans } from "i18n"; interface ConfirmHandlers { onOk: () => void; @@ -15,21 +15,23 @@ export function showFirstCredentialOverwriteConfirm({ onOk, onCancel }: ConfirmH title: (
- Overwrite Credentials Warning + + {trans("enterprise.environments.credentialConfirmations.firstConfirmation.title")} +
), icon: null, content: (

- This is a serious operation that may affect other applications and users. + {trans("enterprise.environments.credentialConfirmations.firstConfirmation.description")}

- Are you sure you want to proceed? + {trans("enterprise.environments.credentialConfirmations.firstConfirmation.question")}

} @@ -39,8 +41,8 @@ export function showFirstCredentialOverwriteConfirm({ onOk, onCancel }: ConfirmH /> ), - okText: 'Continue', - cancelText: 'Cancel', + okText: trans("enterprise.environments.credentialConfirmations.firstConfirmation.continueButton"), + cancelText: trans("enterprise.environments.credentialConfirmations.firstConfirmation.cancelButton"), okButtonProps: { style: { backgroundColor: '#ff7a00', borderColor: '#ff7a00', fontWeight: 500 } }, @@ -62,21 +64,23 @@ export function showSecondCredentialOverwriteConfirm({ onOk, onCancel }: Confirm title: (
- Final Confirmation Required + + {trans("enterprise.environments.credentialConfirmations.secondConfirmation.title")} +
), icon: null, content: (

- You are about to overwrite credentials in the target environment. This action cannot be undone and may break existing integrations. + {trans("enterprise.environments.credentialConfirmations.secondConfirmation.description")}

- Please confirm one more time. + {trans("enterprise.environments.credentialConfirmations.secondConfirmation.confirmOnceMore")}

} @@ -93,14 +97,14 @@ export function showSecondCredentialOverwriteConfirm({ onOk, onCancel }: Confirm }} >

- Are you absolutely certain you want to overwrite the credentials? + {trans("enterprise.environments.credentialConfirmations.secondConfirmation.finalQuestion")}

), - okText: 'Yes, Overwrite Credentials', + okText: trans("enterprise.environments.credentialConfirmations.secondConfirmation.confirmButton"), okType: 'danger', - cancelText: 'Cancel', + cancelText: trans("enterprise.environments.credentialConfirmations.secondConfirmation.cancelButton"), okButtonProps: { style: { fontWeight: 500 } }, cancelButtonProps: { style: { fontWeight: 500 } }, width: 520, diff --git a/client/packages/lowcoder/src/pages/setting/environments/config/apps.config.tsx b/client/packages/lowcoder/src/pages/setting/environments/config/apps.config.tsx index 197b2a826..6409cd5e4 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/config/apps.config.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/config/apps.config.tsx @@ -2,11 +2,9 @@ import { DeployableItemConfig } from '../types/deployable-item.types'; import { Environment } from '../types/environment.types'; import { deployApp } from '../services/apps.service'; - +import { trans } from "i18n"; import { App } from '../types/app.types'; - - // Define AppStats interface if not already defined @@ -14,35 +12,35 @@ export const appsConfig: DeployableItemConfig = { deploy: { - singularLabel: 'App', + singularLabel: trans("enterprise.environments.config.singularLabels.app"), fields: [ { name: 'updateDependenciesIfNeeded', - label: 'Update Dependencies If Needed', + label: trans("enterprise.environments.config.fields.updateDependenciesIfNeeded"), type: 'checkbox', defaultValue: false }, { name: 'publishOnTarget', - label: 'Publish On Target', + label: trans("enterprise.environments.config.fields.publishOnTarget"), type: 'checkbox', defaultValue: false }, { name: 'publicToAll', - label: 'Public To All', + label: trans("enterprise.environments.config.fields.publicToAll"), type: 'checkbox', defaultValue: false }, { name: 'publicToMarketplace', - label: 'Public To Marketplace', + label: trans("enterprise.environments.config.fields.publicToMarketplace"), type: 'checkbox', defaultValue: false }, { name: 'deployCredential', - label: 'Overwrite Credentials', + label: trans("enterprise.environments.config.fields.overwriteCredentials"), type: 'checkbox', defaultValue: false } diff --git a/client/packages/lowcoder/src/pages/setting/environments/config/data-sources.config.tsx b/client/packages/lowcoder/src/pages/setting/environments/config/data-sources.config.tsx index ce802e8de..c739a972d 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/config/data-sources.config.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/config/data-sources.config.tsx @@ -4,14 +4,15 @@ import { DeployableItemConfig } from '../types/deployable-item.types'; import { DataSource} from '../types/datasource.types'; import { Environment } from '../types/environment.types'; import { deployDataSource, DataSourceStats } from '../services/datasources.service'; +import { trans } from "i18n"; export const dataSourcesConfig: DeployableItemConfig = { deploy: { - singularLabel: 'Data Source', + singularLabel: trans("enterprise.environments.config.singularLabels.dataSource"), fields: [ { name: 'deployCredential', - label: 'Overwrite Credentials', + label: trans("enterprise.environments.config.fields.overwriteCredentials"), type: 'checkbox', defaultValue: false } diff --git a/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx b/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx index 7495e5371..0a10f2bff 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/config/query.config.tsx @@ -3,15 +3,16 @@ import { DeployableItemConfig } from '../types/deployable-item.types'; import { Query } from '../types/query.types'; import { deployQuery } from '../services/query.service'; import { Environment } from '../types/environment.types'; +import { trans } from "i18n"; export const queryConfig: DeployableItemConfig = { deploy: { - singularLabel: 'Query', + singularLabel: trans("enterprise.environments.config.singularLabels.query"), fields: [ { name: 'deployCredential', - label: 'Overwrite Credentials', + label: trans("enterprise.environments.config.fields.overwriteCredentials"), type: 'checkbox', defaultValue: false } diff --git a/client/packages/lowcoder/src/pages/setting/environments/config/workspace.config.tsx b/client/packages/lowcoder/src/pages/setting/environments/config/workspace.config.tsx index e35423f2f..78865a91a 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/config/workspace.config.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/config/workspace.config.tsx @@ -4,12 +4,13 @@ import { DeployableItemConfig } from '../types/deployable-item.types'; import { Environment } from '../types/environment.types'; import { deployWorkspace } from '../services/workspace.service'; import { Workspace } from '../types/workspace.types'; +import { trans } from "i18n"; export const workspaceConfig: DeployableItemConfig = { // Deploy configuration deploy: { - singularLabel: 'Workspace', + singularLabel: trans("enterprise.environments.config.singularLabels.workspace"), fields: [ // Removed deployCredential field as workspaces don't need credential overwrite ], From d193effd8f1450055ba3a37d572d4af3a1dfead5 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Sat, 31 May 2025 00:50:25 +0500 Subject: [PATCH 11/13] add apps services --- client/packages/lowcoder/src/i18n/locales/en.ts | 4 ++++ .../src/pages/setting/environments/services/apps.service.ts | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index d0b638e50..bc2f7fbe4 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -2914,6 +2914,10 @@ export const en = { "failedToDeployQuery": "Failed to deploy query", "queryGidRequired": "Query GID is required", "failedToDisconnectQuery": "Failed to disconnect query" + }, + "apps": { + "failedToFetchApps": "Failed to fetch apps", + "failedToDeployApp": "Failed to deploy app" } } } diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/apps.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/apps.service.ts index db7f21dff..3078bb604 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/apps.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/apps.service.ts @@ -1,5 +1,6 @@ // services/appService.ts import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; +import { trans } from "i18n"; import { getWorkspaceApps } from "./environments.service"; import { getManagedApps } from "./enterprise.service"; import { App, AppStats } from "../types/app.types"; @@ -99,7 +100,7 @@ export async function getMergedWorkspaceApps( }; } catch (error) { const errorMessage = - error instanceof Error ? error.message : "Failed to fetch apps"; + error instanceof Error ? error.message : trans("enterprise.environments.services.apps.failedToFetchApps"); messageInstance.error(errorMessage); throw error; } @@ -137,7 +138,7 @@ export const deployApp = async (params: DeployAppParams): Promise => { return response.status === 200; } catch (error) { - const errorMessage = error instanceof Error ? error.message : 'Failed to deploy app'; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.apps.failedToDeployApp"); // Don't show message directly, let the calling component handle it throw new Error(errorMessage); } From f4bca6275d5a71f4e3dcce99c4fd49179ffb21b3 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Sat, 31 May 2025 00:59:36 +0500 Subject: [PATCH 12/13] add more services in trans --- .../packages/lowcoder/src/i18n/locales/en.ts | 46 +++++++++++++++++++ .../components/ContactLowcoderModal.tsx | 19 ++++---- .../services/datasources.service.ts | 13 +++--- .../environments/services/license.service.ts | 22 +++++---- .../services/managed-objects.service.ts | 23 +++++----- .../environments/services/query.service.ts | 1 + .../services/workspace.service.ts | 5 +- 7 files changed, 93 insertions(+), 36 deletions(-) diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index bc2f7fbe4..d5914e6d1 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -2829,6 +2829,22 @@ export const en = { "inputFieldPlaceholder": "Enter {label}" }, + // Add contact lowcoder modal + "contactLowcoder": { + "title": "Contact Lowcoder Team", + "environmentLabel": "Environment:", + "environmentIdLabel": "Environment ID:", + "deploymentIdLabel": "Deployment ID:", + "loading": "Loading...", + "notAvailable": "Not available", + "unnamedEnvironment": "Unnamed Environment", + "fetchingDeploymentInfo": "Fetching deployment information...", + "unableToLoadContactForm": "Unable to Load Contact Form", + "apiConfigurationError": "Environment API service URL or API key not configured", + "failedToFetchDeploymentId": "Failed to fetch deployment ID", + "ensureProperConfiguration": "Please ensure the environment is properly configured to contact support." + }, + "credentialConfirmations": { "firstConfirmation": { "title": "Overwrite Credentials Warning", @@ -2918,6 +2934,36 @@ export const en = { "apps": { "failedToFetchApps": "Failed to fetch apps", "failedToDeployApp": "Failed to deploy app" + }, + "datasources": { + "workspaceIdRequired": "Workspace ID is required", + "apiKeyRequiredToFetchDataSources": "API key is required to fetch data sources", + "apiServiceUrlRequiredToFetchDataSources": "API service URL is required to fetch data sources", + "failedToFetchDataSources": "Failed to fetch data sources", + "failedToDeployDataSource": "Failed to deploy data source" + }, + "workspace": { + "failedToFetchWorkspaces": "Failed to fetch workspaces", + "failedToDeployWorkspace": "Failed to deploy workspace" + }, + "managedObjects": { + "missingRequiredParameters": "Missing required parameters", + "failedToCheckManagedStatus": "Failed to check managed status", + "failedToSetAsManaged": "Failed to set {{objType}} as managed", + "failedToRemoveFromManaged": "Failed to remove {{objType}} from managed", + "missingEnvironmentId": "Missing environment ID", + "failedToFetchManagedObjects": "Failed to fetch managed objects", + "failedToFetchManagedObject": "Failed to fetch managed object", + "managedObjectNotFound": "Managed object not found for objGid: {{objGid}}" + }, + "license": { + "apiServiceUrlRequired": "API service URL is required", + "licenseInformationUnavailable": "License information unavailable", + "licenseCheckTookTooLong": "License check took too long", + "licenseServiceNotAvailable": "License service not available", + "authenticationRequired": "Authentication required - please check API key", + "licenseServiceTemporarilyUnavailable": "License service temporarily unavailable", + "remainingAPICalls": "{{remaining}} remaining ({{used}}/{{total}} used, {{percentage}}%)", } } } diff --git a/client/packages/lowcoder/src/pages/setting/environments/components/ContactLowcoderModal.tsx b/client/packages/lowcoder/src/pages/setting/environments/components/ContactLowcoderModal.tsx index 34ab0526f..7362d35ee 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/components/ContactLowcoderModal.tsx +++ b/client/packages/lowcoder/src/pages/setting/environments/components/ContactLowcoderModal.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { Modal, Card, Row, Col, Typography, Divider, Spin, Alert } from 'antd'; import { CustomerServiceOutlined, CloudServerOutlined } from '@ant-design/icons'; import { useSelector } from 'react-redux'; +import { trans } from 'i18n'; import { Environment } from '../types/environment.types'; import { getEnvironmentDeploymentId } from '../services/environments.service'; import { HubspotModal } from '../../hubspotModal'; @@ -34,7 +35,7 @@ const ContactLowcoderModal: React.FC = ({ const fetchDeploymentId = async () => { if (!visible || !environment.environmentApiServiceUrl || !environment.environmentApikey) { if (visible) { - setError('Environment API service URL or API key not configured'); + setError(trans('enterprise.environments.contactLowcoder.apiConfigurationError')); } return; } @@ -51,7 +52,7 @@ const ContactLowcoderModal: React.FC = ({ setShowHubspotModal(true); } catch (err) { console.error('Failed to fetch deployment ID:', err); - setError(err instanceof Error ? err.message : 'Failed to fetch deployment ID'); + setError(err instanceof Error ? err.message : trans('enterprise.environments.contactLowcoder.failedToFetchDeploymentId')); } finally { setIsLoading(false); } @@ -91,7 +92,7 @@ const ContactLowcoderModal: React.FC = ({ title={
- Contact Lowcoder Team + {trans('enterprise.environments.contactLowcoder.title')}
} open={visible} @@ -119,15 +120,15 @@ const ContactLowcoderModal: React.FC = ({
- Environment: {environment.environmentName || 'Unnamed Environment'} + {trans('enterprise.environments.contactLowcoder.environmentLabel')} {environment.environmentName || trans('enterprise.environments.contactLowcoder.unnamedEnvironment')}
- Environment ID: {environment.environmentId} + {trans('enterprise.environments.contactLowcoder.environmentIdLabel')} {environment.environmentId}
- Deployment ID: {isLoading ? 'Loading...' : deploymentId || 'Not available'} + {trans('enterprise.environments.contactLowcoder.deploymentIdLabel')} {isLoading ? trans('enterprise.environments.contactLowcoder.loading') : deploymentId || trans('enterprise.environments.contactLowcoder.notAvailable')}
@@ -148,14 +149,14 @@ const ContactLowcoderModal: React.FC = ({ }}> - Fetching deployment information... + {trans('enterprise.environments.contactLowcoder.fetchingDeploymentInfo')} )} {error && ( = ({ fontSize: '14px' }}> -
Please ensure the environment is properly configured to contact support.
+
{trans('enterprise.environments.contactLowcoder.ensureProperConfiguration')}
)} diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/datasources.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/datasources.service.ts index 2fc492028..a14fe941b 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/datasources.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/datasources.service.ts @@ -1,6 +1,7 @@ // services/dataSources.service.ts import axios from 'axios'; import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; +import { trans } from "i18n"; import { DataSource, DataSourceWithMeta } from "../types/datasource.types"; import { getManagedObjects, ManagedObject, ManagedObjectType , transferManagedObject } from "./managed-objects.service"; @@ -32,15 +33,15 @@ export async function getWorkspaceDataSources( try { // Check if required parameters are provided if (!workspaceId) { - throw new Error('Workspace ID is required'); + throw new Error(trans("enterprise.environments.services.datasources.workspaceIdRequired")); } if (!apiKey) { - throw new Error('API key is required to fetch data sources'); + throw new Error(trans("enterprise.environments.services.datasources.apiKeyRequiredToFetchDataSources")); } if (!apiServiceUrl) { - throw new Error('API service URL is required to fetch data sources'); + throw new Error(trans("enterprise.environments.services.datasources.apiServiceUrlRequiredToFetchDataSources")); } // Set up headers with the Bearer token format @@ -64,7 +65,7 @@ export async function getWorkspaceDataSources( return response.data.data; } catch (error) { // Handle and transform error - const errorMessage = error instanceof Error ? error.message : 'Failed to fetch data sources'; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.datasources.failedToFetchDataSources"); messageInstance.error(errorMessage); throw error; } @@ -143,7 +144,7 @@ export async function getMergedWorkspaceDataSources( }; } catch (error) { const errorMessage = - error instanceof Error ? error.message : "Failed to fetch data sources"; + error instanceof Error ? error.message : trans("enterprise.environments.services.datasources.failedToFetchDataSources"); messageInstance.error(errorMessage); throw error; } @@ -170,7 +171,7 @@ export async function deployDataSource(params: DeployDataSourceParams): Promise< } return response.status === 200; } catch (error) { - const errorMessage = error instanceof Error ? error.message : 'Failed to deploy data source'; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.datasources.failedToDeployDataSource"); messageInstance.error(errorMessage); throw error; } diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts index ebc0ae46a..e2fac5ef6 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/license.service.ts @@ -1,4 +1,5 @@ import axios from 'axios'; +import { trans } from 'i18n'; import { EnvironmentLicense, DetailedLicenseInfo } from '../types/environment.types'; /** @@ -15,7 +16,7 @@ export async function checkEnvironmentLicense( if (!apiServiceUrl) { return { isValid: false, - error: 'API service URL is required' + error: trans('enterprise.environments.services.license.apiServiceUrlRequired') }; } @@ -30,7 +31,7 @@ export async function checkEnvironmentLicense( `${apiServiceUrl}/api/plugins/enterprise/license`, { headers, - timeout: 500 // Very short timeout for immediate failure when endpoint doesn't exist + timeout: 1500 // Very short timeout for immediate failure when endpoint doesn't exist } ); @@ -65,17 +66,17 @@ export async function checkEnvironmentLicense( } catch (error) { // Determine the specific error type - let errorMessage = 'License information unavailable'; + let errorMessage = trans('enterprise.environments.services.license.licenseInformationUnavailable'); if (axios.isAxiosError(error)) { if (error.code === 'ECONNABORTED') { - errorMessage = 'License check took too long'; + errorMessage = trans('enterprise.environments.services.license.licenseCheckTookTooLong'); } else if (error.response?.status === 404) { - errorMessage = 'License service not available'; + errorMessage = trans('enterprise.environments.services.license.licenseServiceNotAvailable'); } else if (error.response?.status === 401) { - errorMessage = 'Authentication required - please check API key'; + errorMessage = trans('enterprise.environments.services.license.authenticationRequired'); } else if (error.response && error.response.status >= 500) { - errorMessage = 'License service temporarily unavailable'; + errorMessage = trans('enterprise.environments.services.license.licenseServiceTemporarilyUnavailable'); } } @@ -96,7 +97,12 @@ export function formatAPICalls(remaining: number, total: number): string { const used = total - remaining; const percentage = total > 0 ? Math.round((used / total) * 100) : 0; - return `${remaining.toLocaleString()} remaining (${used.toLocaleString()}/${total.toLocaleString()} used, ${percentage}%)`; + return trans('enterprise.environments.services.license.remainingAPICalls', { + remaining: remaining.toLocaleString(), + used: used.toLocaleString(), + total: total.toLocaleString(), + percentage + }); } /** diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/managed-objects.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/managed-objects.service.ts index 0a4e0b14a..e70322221 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/managed-objects.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/managed-objects.service.ts @@ -1,5 +1,6 @@ import axios from "axios"; import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; +import { trans } from "i18n"; // Object types that can be managed export enum ManagedObjectType { @@ -32,7 +33,7 @@ export async function isManagedObject( ): Promise { try { if (!objGid || !environmentId || !objType) { - throw new Error("Missing required parameters"); + throw new Error(trans("enterprise.environments.services.managedObjects.missingRequiredParameters")); } const response = await axios.get(`/api/plugins/enterprise/managed-obj`, { @@ -50,7 +51,7 @@ export async function isManagedObject( return false; } - const errorMessage = error instanceof Error ? error.message : "Failed to check managed status"; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.managedObjects.failedToCheckManagedStatus"); messageInstance.error(errorMessage); throw error; } @@ -73,7 +74,7 @@ export async function setManagedObject( ): Promise { try { if (!objGid || !environmentId || !objType) { - throw new Error("Missing required parameters"); + throw new Error(trans("enterprise.environments.services.managedObjects.missingRequiredParameters")); } const requestBody = { @@ -87,7 +88,7 @@ export async function setManagedObject( return response.status === 200; } catch (error) { - const errorMessage = error instanceof Error ? error.message : `Failed to set ${objType} as managed`; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.managedObjects.failedToSetAsManaged", { objType }); messageInstance.error(errorMessage); throw error; } @@ -108,7 +109,7 @@ export async function unsetManagedObject( ): Promise { try { if (!objGid || !environmentId || !objType) { - throw new Error("Missing required parameters"); + throw new Error(trans("enterprise.environments.services.managedObjects.missingRequiredParameters")); } const response = await axios.delete(`/api/plugins/enterprise/managed-obj`, { @@ -121,7 +122,7 @@ export async function unsetManagedObject( return response.status === 200; } catch (error) { - const errorMessage = error instanceof Error ? error.message : `Failed to remove ${objType} from managed`; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.managedObjects.failedToRemoveFromManaged", { objType }); messageInstance.error(errorMessage); throw error; } @@ -134,7 +135,7 @@ export async function getManagedObjects( ): Promise { try { if (!environmentId) { - throw new Error("Missing environment ID"); + throw new Error(trans("enterprise.environments.services.managedObjects.missingEnvironmentId")); } const response = await axios.get(`/api/plugins/enterprise/managed-obj/list`, { @@ -146,7 +147,7 @@ export async function getManagedObjects( return response.data.data; } catch (error) { - const errorMessage = error instanceof Error ? error.message : "Failed to fetch managed objects"; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.managedObjects.failedToFetchManagedObjects"); messageInstance.error(errorMessage); throw error; } @@ -166,7 +167,7 @@ export async function getSingleManagedObject( ): Promise { try { if (!objGid || !environmentId || !objType) { - throw new Error("Missing required parameters"); + throw new Error(trans("enterprise.environments.services.managedObjects.missingRequiredParameters")); } const response = await axios.get(`/api/plugins/enterprise/managed-obj`, { @@ -184,7 +185,7 @@ export async function getSingleManagedObject( return null; } - const errorMessage = error instanceof Error ? error.message : "Failed to fetch managed object"; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.managedObjects.failedToFetchManagedObject"); messageInstance.error(errorMessage); throw error; } @@ -197,7 +198,7 @@ export async function transferManagedObject(objGid: string, sourceEnvId: string, if (managedObject) { await setManagedObject(managedObject.objGid, targetEnvId, objType, managedObject.managedId); } else { - throw new Error(`Managed object not found for objGid: ${objGid}`); + throw new Error(trans("enterprise.environments.services.managedObjects.managedObjectNotFound", { objGid })); } } catch (error) { console.error('Error transferring managed object:', error); diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts index 20b79f4ee..a79f10f87 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/query.service.ts @@ -2,6 +2,7 @@ * Get merged queries (both regular and managed) for a workspace */ import axios from 'axios'; +import { trans } from 'i18n'; import { getManagedObjects, ManagedObjectType, transferManagedObject } from './managed-objects.service'; import { getWorkspaceQueries } from './environments.service'; import { Query, QueryStats } from '../types/query.types'; diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/workspace.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/workspace.service.ts index b7cf4a37c..6cbe947ab 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/workspace.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/workspace.service.ts @@ -1,5 +1,6 @@ // services/workspacesService.ts (or wherever makes sense in your structure) import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; +import { trans } from "i18n"; import { getEnvironmentWorkspaces } from "./environments.service"; import { getManagedObjects, ManagedObject, ManagedObjectType, transferManagedObject } from "./managed-objects.service"; import { Workspace } from "../types/workspace.types"; @@ -69,7 +70,7 @@ export async function getMergedEnvironmentWorkspaces( } }; } catch (error) { - const errorMessage = error instanceof Error ? error.message : "Failed to fetch workspaces"; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.workspace.failedToFetchWorkspaces"); messageInstance.error(errorMessage); throw error; } @@ -107,7 +108,7 @@ export async function deployWorkspace(params: { return response.status === 200; } catch (error) { - const errorMessage = error instanceof Error ? error.message : 'Failed to deploy workspace'; + const errorMessage = error instanceof Error ? error.message : trans("enterprise.environments.services.workspace.failedToDeployWorkspace"); // Don't show message directly, let the calling component handle it throw new Error(errorMessage); } From bbc0828d5cb8c3a21c012625ea0652d6a5aea6b0 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Sat, 31 May 2025 01:43:50 +0500 Subject: [PATCH 13/13] remove duplicate trans import --- .../pages/setting/environments/services/environments.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts b/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts index 6ef0b0f01..a781184f4 100644 --- a/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts +++ b/client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts @@ -8,7 +8,6 @@ import {App} from "../types/app.types"; import { DataSourceWithMeta } from '../types/datasource.types'; import { Query, QueryResponse } from "../types/query.types"; import { checkEnvironmentLicense } from './license.service'; -import { trans } from "i18n"; export async function updateEnvironment( environmentId: string,