From 2e2763f80fcc6ea4c58d985b49a23e6541bcb702 Mon Sep 17 00:00:00 2001 From: Asier Isayas Date: Tue, 11 Aug 2026 11:38:15 -0400 Subject: [PATCH] Localize connection-string login validation and connectivity messages Move the hardcoded SQL/Tables/Gremlin connection-string login strings into en/Resources.json and reference them via the type-safe Keys object (t(Keys.connectExplorer.errors.*)). --- src/Localization/en/Resources.json | 15 ++++++++++++++- .../Hosted/Components/ConnectExplorer.tsx | 9 ++++----- src/Platform/Hosted/HostedUtils.ts | 13 +++++++------ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/Localization/en/Resources.json b/src/Localization/en/Resources.json index 9b1299b06..b43188c74 100644 --- a/src/Localization/en/Resources.json +++ b/src/Localization/en/Resources.json @@ -1174,5 +1174,18 @@ "retryConsoleMessage": "Data transfer job \"{{jobName}}\" in progress, total count: {{totalCount}}, processed count: {{processedCount}}" } } + }, + "connectExplorer": { + "errors": { + "connectionStringMissing": "Connection string is missing.", + "accountNameMissing": "Account name is missing from the connection string.", + "endpointHostMissing": "Endpoint host is missing from the connection string.", + "endpointHostNotAllowed": "Endpoint host is not allowed.", + "accountNameMismatch": "Account name does not match the endpoint host.", + "accountKeyMissing": "Account key is missing from the connection string.", + "connectivityInvalid": "Unable to connect to the account with the provided connection string.", + "connectivityUnreachable": "Unable to connect to the account. Please verify the connection string is correct and that the account is reachable.", + "connectFailed": "Failed to connect using the provided connection string. Please verify it is correct and try again." + } } -} \ No newline at end of file +} diff --git a/src/Platform/Hosted/Components/ConnectExplorer.tsx b/src/Platform/Hosted/Components/ConnectExplorer.tsx index 0377fa1ee..46fcd89bf 100644 --- a/src/Platform/Hosted/Components/ConnectExplorer.tsx +++ b/src/Platform/Hosted/Components/ConnectExplorer.tsx @@ -1,5 +1,6 @@ import { useBoolean } from "@fluentui/react-hooks"; import { client } from "Common/CosmosClient"; +import { Keys, t } from "Localization"; import { updateUserContext, userContext } from "UserContext"; import * as React from "react"; import ConnectImage from "../../../../images/HdeConnectCosmosDB.svg"; @@ -60,7 +61,7 @@ export const validateDirectConnectionStringConnectivity = async ( ): Promise => { const masterKey = extractAccountKeyFromConnectionString(connectionString); if (!metadata?.documentEndpoint || !masterKey) { - return "Unable to connect to the account with the provided connection string."; + return t(Keys.connectExplorer.errors.connectivityInvalid); } // Configure the client the same way the Data Explorer will, then issue a lightweight authenticated @@ -76,7 +77,7 @@ export const validateDirectConnectionStringConnectivity = async ( await client().getDatabaseAccount(); return undefined; } catch { - return "Unable to connect to the account. Please verify the connection string is correct and that the account is reachable."; + return t(Keys.connectExplorer.errors.connectivityUnreachable); } }; @@ -148,9 +149,7 @@ export const ConnectExplorer: React.FunctionComponent = ({ setEncryptedToken(encryptedToken); setAuthType(AuthType.ConnectionString); } catch (error) { - setErrorMessage( - "Failed to connect using the provided connection string. Please verify it is correct and try again.", - ); + setErrorMessage(t(Keys.connectExplorer.errors.connectFailed)); } }} > diff --git a/src/Platform/Hosted/HostedUtils.ts b/src/Platform/Hosted/HostedUtils.ts index 5801f8a4a..1e3675a0e 100644 --- a/src/Platform/Hosted/HostedUtils.ts +++ b/src/Platform/Hosted/HostedUtils.ts @@ -1,5 +1,6 @@ import { AccountKind, CapabilityNames } from "../../Common/Constants"; import { AccessInputMetadata, ApiKind } from "../../Contracts/DataModels"; +import { Keys, t } from "../../Localization"; import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility"; import { userContext } from "../../UserContext"; @@ -133,16 +134,16 @@ export function validateDirectConnectionStringLogin( metadata: AccessInputMetadata, ): string | undefined { if (!connectionString) { - return "Connection string is missing."; + return t(Keys.connectExplorer.errors.connectionStringMissing); } if (!metadata || !metadata.accountName) { - return "Account name is missing from the connection string."; + return t(Keys.connectExplorer.errors.accountNameMissing); } const host = extractEndpointHostFromConnectionString(connectionString); if (!host) { - return "Endpoint host is missing from the connection string."; + return t(Keys.connectExplorer.errors.endpointHostMissing); } // The host must belong to one of the allowlisted runtime endpoint zones. @@ -150,17 +151,17 @@ export function validateDirectConnectionStringLogin( host.toLowerCase().endsWith(`.${zone.toLowerCase()}`), ); if (!isAllowlistedHost) { - return "Endpoint host is not allowed."; + return t(Keys.connectExplorer.errors.endpointHostNotAllowed); } // The account name must be the first DNS label of the host. if (host.split(".")[0].toLowerCase() !== metadata.accountName.toLowerCase()) { - return "Account name does not match the endpoint host."; + return t(Keys.connectExplorer.errors.accountNameMismatch); } // Direct login signs requests with the account key, so it must be present in the connection string. if (!extractAccountKeyFromConnectionString(connectionString)) { - return "Account key is missing from the connection string."; + return t(Keys.connectExplorer.errors.accountKeyMissing); } return undefined;