Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d16a30064 | |||
| cf601c33c0 | |||
| ea3a61077a | |||
| d1a898b40d | |||
| a521a81ef0 | |||
| ab5a54dbb6 | |||
| 44ad8fa60a | |||
| 5b27a241d7 | |||
| 084019ca65 | |||
| ba147af8fe | |||
| 1b3f4db07d | |||
| c36705d458 | |||
| 0e126cb8cf | |||
| c48183a539 | |||
| 50f380dbbe | |||
| 66023a9a68 | |||
| c3fbc3354c | |||
| a7d2ed11f3 | |||
| 6a3dc92572 | |||
| e3a4667422 | |||
| c4dd99bba9 |
@@ -9,6 +9,16 @@ Builds:
|
||||
- linux - application for linux
|
||||
- win - application for Windows
|
||||
|
||||
## 7.1.5
|
||||
|
||||
- FIXED: Issues with cloud and file loading
|
||||
- ADDED: Support for displaying MongoDB UUID #1394
|
||||
- ADDED: SVG icon sanitization
|
||||
|
||||
## 7.1.4
|
||||
|
||||
- FIXED: NPM installation failure #1375
|
||||
|
||||
## 7.1.3
|
||||
|
||||
- FIXED: "Add files" button in import/export #1373
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "7.1.4",
|
||||
"version": "7.1.6",
|
||||
"name": "dbgate-all",
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
|
||||
@@ -12,6 +12,13 @@ import isPlainObject from 'lodash/isPlainObject';
|
||||
import md5 from 'blueimp-md5';
|
||||
|
||||
export const MAX_GRID_TEXT_LENGTH = 1000; // maximum length of text in grid cell, longer text is truncated
|
||||
export const MAX_GRID_BINARY_SIZE = 10000; // maximum binary size (base64 chars or byte count) before showing 'too large' in grid cell
|
||||
|
||||
function formatByteSize(bytes: number): string {
|
||||
if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
||||
if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
||||
return `${bytes} B`;
|
||||
}
|
||||
|
||||
export type EditorDataType =
|
||||
| 'null'
|
||||
@@ -49,6 +56,26 @@ export function base64ToHex(base64String) {
|
||||
return '0x' + hexString.toUpperCase();
|
||||
}
|
||||
|
||||
export function base64ToUuid(base64String): string | null {
|
||||
let binaryString: string;
|
||||
try {
|
||||
binaryString = atob(base64String);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
if (binaryString.length !== 16) {
|
||||
return null;
|
||||
}
|
||||
const hex = Array.from(binaryString, c => c.charCodeAt(0).toString(16).padStart(2, '0')).join('');
|
||||
return [
|
||||
hex.slice(0, 8),
|
||||
hex.slice(8, 12),
|
||||
hex.slice(12, 16),
|
||||
hex.slice(16, 20),
|
||||
hex.slice(20, 32),
|
||||
].join('-');
|
||||
}
|
||||
|
||||
export function hexToBase64(hexString) {
|
||||
const binaryString = hexString
|
||||
.match(/.{1,2}/g)
|
||||
@@ -57,6 +84,23 @@ export function hexToBase64(hexString) {
|
||||
return btoa(binaryString);
|
||||
}
|
||||
|
||||
const uuidPattern = '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}';
|
||||
const uuidRegex = new RegExp(`^${uuidPattern}$`);
|
||||
const uuid3WrapperRegex = new RegExp(`^UUID3\\("(${uuidPattern})"\\)$`);
|
||||
const uuid4WrapperRegex = new RegExp(`^UUID\\("(${uuidPattern})"\\)$`);
|
||||
|
||||
export function uuidToBase64(uuid: string): string | null {
|
||||
if (!uuid || !uuidRegex.test(uuid)) {
|
||||
return null;
|
||||
}
|
||||
const hex = uuid.replace(/-/g, '');
|
||||
const binaryString = hex
|
||||
.match(/.{1,2}/g)
|
||||
.map(byte => String.fromCharCode(parseInt(byte, 16)))
|
||||
.join('');
|
||||
return btoa(binaryString);
|
||||
}
|
||||
|
||||
export function parseCellValue(value, editorTypes?: DataEditorTypesBehaviour) {
|
||||
if (!_isString(value)) return value;
|
||||
|
||||
@@ -65,6 +109,20 @@ export function parseCellValue(value, editorTypes?: DataEditorTypesBehaviour) {
|
||||
}
|
||||
|
||||
if (editorTypes?.parseHexAsBuffer) {
|
||||
const mUuid3 = value.match(uuid3WrapperRegex);
|
||||
if (mUuid3) {
|
||||
const base64Uuid3 = uuidToBase64(mUuid3[1]);
|
||||
if (base64Uuid3 != null) return { $binary: { base64: base64Uuid3, subType: '03' } };
|
||||
}
|
||||
const mUuid4 = value.match(uuid4WrapperRegex);
|
||||
if (mUuid4) {
|
||||
const base64Uuid4 = uuidToBase64(mUuid4[1]);
|
||||
if (base64Uuid4 != null) return { $binary: { base64: base64Uuid4, subType: '04' } };
|
||||
}
|
||||
if (uuidRegex.test(value)) {
|
||||
const base64UuidPlain = uuidToBase64(value);
|
||||
if (base64UuidPlain != null) return { $binary: { base64: base64UuidPlain, subType: '04' } };
|
||||
}
|
||||
const mHex = value.match(/^0x([0-9a-fA-F][0-9a-fA-F])+$/);
|
||||
if (mHex) {
|
||||
return {
|
||||
@@ -266,6 +324,21 @@ export function stringifyCellValue(
|
||||
if (value === false) return { value: 'false', gridStyle: 'valueCellStyle' };
|
||||
|
||||
if (value?.$binary?.base64) {
|
||||
const subType = value.$binary.subType;
|
||||
if (subType === '03' || subType === '04') {
|
||||
const uuidStr = base64ToUuid(value.$binary.base64);
|
||||
if (uuidStr != null) {
|
||||
if (intent === 'gridCellIntent' || intent === 'exportIntent' || intent === 'clipboardIntent' || intent === 'stringConversionIntent') {
|
||||
return { value: uuidStr, gridStyle: 'valueCellStyle' };
|
||||
}
|
||||
// For editing intents: tag with subType so parseCellValue can round-trip it
|
||||
const tag = subType === '03' ? 'UUID3' : 'UUID';
|
||||
return { value: `${tag}("${uuidStr}")`, gridStyle: 'valueCellStyle' };
|
||||
}
|
||||
}
|
||||
if (intent === 'gridCellIntent' && value.$binary.base64.length > MAX_GRID_BINARY_SIZE) {
|
||||
return { value: `(Field too large, ${formatByteSize(Math.round(value.$binary.base64.length * 3 / 4))})`, gridStyle: 'nullCellStyle' };
|
||||
}
|
||||
return {
|
||||
value: base64ToHex(value.$binary.base64),
|
||||
gridStyle: 'valueCellStyle',
|
||||
@@ -354,6 +427,14 @@ export function stringifyCellValue(
|
||||
}
|
||||
}
|
||||
|
||||
if (value?.type === 'Buffer' && _isArray(value.data)) {
|
||||
if (intent === 'gridCellIntent') {
|
||||
return value.data.length > MAX_GRID_BINARY_SIZE
|
||||
? { value: `(Field too large, ${formatByteSize(value.data.length)})`, gridStyle: 'nullCellStyle' }
|
||||
: { value: '0x' + arrayToHexString(value.data), gridStyle: 'valueCellStyle' };
|
||||
}
|
||||
}
|
||||
|
||||
if (_isArray(value)) {
|
||||
switch (intent) {
|
||||
case 'gridCellIntent':
|
||||
@@ -482,7 +563,7 @@ export function shouldOpenMultilineDialog(value) {
|
||||
}
|
||||
|
||||
export function isJsonLikeLongString(value) {
|
||||
return _isString(value) && value.length > 100 && value.match(/^\s*\{.*\}\s*$|^\s*\[.*\]\s*$/m);
|
||||
return _isString(value) && value.length > 100 && value.length <= MAX_GRID_BINARY_SIZE && value.match(/^\s*\{.*\}\s*$|^\s*\[.*\]\s*$/m);
|
||||
}
|
||||
|
||||
export function getIconForRedisType(type) {
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
"date-fns": "^4.1.0",
|
||||
"debug": "^4.3.4",
|
||||
"dom-to-image": "^2.6.0",
|
||||
"dompurify": "^3.3.2",
|
||||
"flatpickr": "^4.6.13",
|
||||
"fuzzy": "^0.1.3",
|
||||
"highlight.js": "^11.11.1",
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
export let icon;
|
||||
export let title = null;
|
||||
export let padLeft = false;
|
||||
@@ -34,6 +36,7 @@
|
||||
export let colorClass = null;
|
||||
$: iconValue = typeof icon === 'string' ? icon : icon?.light || icon?.dark || '';
|
||||
$: isSvgString = iconValue.trim().startsWith('<svg');
|
||||
$: sanitizedSvg = isSvgString ? DOMPurify.sanitize(iconValue, { USE_PROFILES: { svg: true, svgFilters: true } }) : '';
|
||||
$: isTextIcon = iconValue.trim().startsWith('text ');
|
||||
|
||||
const iconNames = {
|
||||
@@ -379,7 +382,7 @@
|
||||
|
||||
{#if isSvgString}
|
||||
<span class="svg-inline" class:padLeft class:padRight {title} {style} on:click data-testid={$$props['data-testid']}>
|
||||
{@html iconValue}
|
||||
{@html sanitizedSvg}
|
||||
</span>
|
||||
{:else if isTextIcon}
|
||||
{@const textIconParts = iconValue.trim().split(' ')}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
unsubscribeCachePeek,
|
||||
} from './cache';
|
||||
import stableStringify from 'json-stable-stringify';
|
||||
import { derived } from 'svelte/store';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
import { extendDatabaseInfo } from 'dbgate-tools';
|
||||
import { setLocalStorage } from '../utility/storageCache';
|
||||
import { apiCall, apiOff, apiOn } from './api';
|
||||
@@ -175,11 +175,13 @@ const filesLoader = ({ folder, parseFrontMatter = false }) => ({
|
||||
url: 'files/list',
|
||||
params: parseFrontMatter ? { folder, parseFrontMatter: true } : { folder },
|
||||
reloadTrigger: { key: `files-changed`, folder },
|
||||
errorValue: [],
|
||||
});
|
||||
const allFilesLoader = () => ({
|
||||
url: 'files/list-all',
|
||||
params: {},
|
||||
reloadTrigger: { key: `all-files-changed` },
|
||||
errorValue: [],
|
||||
});
|
||||
const authTypesLoader = ({ engine }) => ({
|
||||
url: 'plugins/auth-types',
|
||||
@@ -188,25 +190,34 @@ const authTypesLoader = ({ engine }) => ({
|
||||
errorValue: null,
|
||||
});
|
||||
|
||||
const publicCloudErrorStore = writable(false);
|
||||
const cloudContentErrorStore = writable(false);
|
||||
|
||||
const publicCloudFilesLoader = () => ({
|
||||
url: 'cloud/public-files',
|
||||
params: {},
|
||||
reloadTrigger: { key: `public-cloud-changed` },
|
||||
errorValue: [],
|
||||
onError: err => publicCloudErrorStore.set(!!err),
|
||||
});
|
||||
const cloudContentListLoader = () => ({
|
||||
url: 'cloud/content-list',
|
||||
params: {},
|
||||
reloadTrigger: { key: `cloud-content-changed` },
|
||||
errorValue: [],
|
||||
onError: err => cloudContentErrorStore.set(!!err),
|
||||
});
|
||||
const teamFilesLoader = () => ({
|
||||
url: 'team-files/list',
|
||||
params: {},
|
||||
reloadTrigger: { key: `team-files-changed` },
|
||||
errorValue: [],
|
||||
});
|
||||
const teamFoldersLoader = () => ({
|
||||
url: 'team-files/list-folders',
|
||||
params: {},
|
||||
reloadTrigger: { key: `team-folders-changed` },
|
||||
errorValue: [],
|
||||
});
|
||||
const promoWidgetLoader = () => ({
|
||||
url: 'cloud/premium-promo-widget',
|
||||
@@ -220,15 +231,17 @@ const fileThemesLoader = () => ({
|
||||
});
|
||||
|
||||
async function getCore(loader, args) {
|
||||
const { url, params, reloadTrigger, transform, onLoaded, errorValue } = loader(args);
|
||||
const { url, params, reloadTrigger, transform, onLoaded, onError, errorValue } = loader(args);
|
||||
const key = stableStringify({ url, ...params });
|
||||
|
||||
async function doLoad() {
|
||||
const resp = await apiCall(url, params);
|
||||
if (resp?.errorMessage && errorValue !== undefined) {
|
||||
if (onError) onError(resp.errorMessage);
|
||||
if (onLoaded) onLoaded(errorValue);
|
||||
return errorValue;
|
||||
}
|
||||
if (onError) onError(null);
|
||||
const res = (transform || (x => x))(resp);
|
||||
if (onLoaded) onLoaded(res);
|
||||
return res;
|
||||
@@ -551,6 +564,9 @@ export function getPublicCloudFiles(args) {
|
||||
export function usePublicCloudFiles(args = {}) {
|
||||
return useCore(publicCloudFilesLoader, args);
|
||||
}
|
||||
export function usePublicCloudError() {
|
||||
return publicCloudErrorStore;
|
||||
}
|
||||
|
||||
export function getCloudContentList(args) {
|
||||
return getCore(cloudContentListLoader, args);
|
||||
@@ -558,6 +574,9 @@ export function getCloudContentList(args) {
|
||||
export function useCloudContentList(args = {}) {
|
||||
return useCore(cloudContentListLoader, args);
|
||||
}
|
||||
export function useCloudContentError() {
|
||||
return cloudContentErrorStore;
|
||||
}
|
||||
|
||||
export function getTeamFiles(args) {
|
||||
return getCore(teamFilesLoader, args);
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
|
||||
import AppObjectList from '../appobj/AppObjectList.svelte';
|
||||
import * as cloudContentAppObject from '../appobj/CloudContentAppObject.svelte';
|
||||
import { useCloudContentList, usePublicCloudFiles, useServerStatus } from '../utility/metadataLoaders';
|
||||
import {
|
||||
useCloudContentList,
|
||||
usePublicCloudFiles,
|
||||
useServerStatus,
|
||||
useCloudContentError,
|
||||
} from '../utility/metadataLoaders';
|
||||
import { _t } from '../translations';
|
||||
|
||||
import WidgetsInnerContainer from './WidgetsInnerContainer.svelte';
|
||||
@@ -47,6 +52,7 @@
|
||||
|
||||
const cloudContentList = useCloudContentList();
|
||||
const serverStatus = useServerStatus();
|
||||
const cloudContentError = useCloudContentError();
|
||||
const cloudContentColorFactory = useCloudContentColorFactory();
|
||||
const connectionColorFactory = useConnectionColorFactory();
|
||||
|
||||
@@ -259,16 +265,19 @@
|
||||
icon="icon plus-thick"
|
||||
menu={createAddItemMenu}
|
||||
title={_t('privateCloudWidget.addNewConnectionOrFile', { defaultMessage: 'Add new connection or file' })}
|
||||
disabled={$cloudContentError}
|
||||
/>
|
||||
<DropDownButton
|
||||
icon="icon add-folder"
|
||||
menu={createAddFolderMenu}
|
||||
title={_t('privateCloudWidget.addNewFolder', { defaultMessage: 'Add new folder' })}
|
||||
disabled={$cloudContentError}
|
||||
/>
|
||||
<InlineButton
|
||||
on:click={handleRefreshContent}
|
||||
title={_t('privateCloudWidget.refreshFiles', { defaultMessage: 'Refresh files' })}
|
||||
data-testid="CloudItemsWidget_buttonRefreshContent"
|
||||
disabled={$cloudContentError}
|
||||
>
|
||||
<FontIcon icon="icon refresh" />
|
||||
</InlineButton>
|
||||
@@ -300,7 +309,14 @@
|
||||
groupContextMenu={createGroupContextMenu}
|
||||
/>
|
||||
|
||||
{#if !cloudContentFlat?.length}
|
||||
{#if $cloudContentError}
|
||||
<ErrorInfo
|
||||
message={_t('privateCloudWidget.cloudUnavailable', {
|
||||
defaultMessage: 'DbGate Cloud is temporarily unavailable',
|
||||
})}
|
||||
icon="img warn"
|
||||
/>
|
||||
{:else if !cloudContentFlat?.length}
|
||||
<ErrorInfo
|
||||
message={_t('privateCloudWidget.noContent', { defaultMessage: 'You have no content on DbGate cloud' })}
|
||||
icon="img info"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import AppObjectList from '../appobj/AppObjectList.svelte';
|
||||
import * as publicCloudFileAppObject from '../appobj/PublicCloudFileAppObject.svelte';
|
||||
import { usePublicCloudFiles } from '../utility/metadataLoaders';
|
||||
import { usePublicCloudFiles, usePublicCloudError } from '../utility/metadataLoaders';
|
||||
import { _t } from '../translations';
|
||||
|
||||
import WidgetsInnerContainer from './WidgetsInnerContainer.svelte';
|
||||
@@ -20,6 +20,7 @@
|
||||
let filter = '';
|
||||
|
||||
const publicFiles = usePublicCloudFiles();
|
||||
const publicCloudError = usePublicCloudError();
|
||||
|
||||
function handleRefreshPublic() {
|
||||
refreshPublicCloudFiles(true);
|
||||
@@ -42,6 +43,7 @@
|
||||
on:click={handleRefreshPublic}
|
||||
title={_t('publicCloudWidget.refreshFiles', { defaultMessage: 'Refresh files' })}
|
||||
data-testid="CloudItemsWidget_buttonRefreshPublic"
|
||||
disabled={$publicCloudError}
|
||||
>
|
||||
<FontIcon icon="icon refresh" />
|
||||
</InlineButton>
|
||||
@@ -54,7 +56,14 @@
|
||||
{filter}
|
||||
/>
|
||||
|
||||
{#if !$publicFiles?.length}
|
||||
{#if $publicCloudError}
|
||||
<ErrorInfo
|
||||
message={_t('publicCloudWidget.cloudUnavailable', {
|
||||
defaultMessage: 'DbGate Cloud is temporarily unavailable',
|
||||
})}
|
||||
icon="img warn"
|
||||
/>
|
||||
{:else if !$publicFiles?.length}
|
||||
<ErrorInfo
|
||||
message={_t('publicCloudWidget.noFilesFound', { defaultMessage: 'No files found for your configuration' })}
|
||||
/>
|
||||
|
||||
@@ -6,7 +6,7 @@ const Analyser = require('./Analyser');
|
||||
const isPromise = require('is-promise');
|
||||
const mongodb = require('mongodb');
|
||||
const { ObjectId } = require('mongodb');
|
||||
const { EJSON } = require('bson');
|
||||
const { EJSON, Binary } = require('bson');
|
||||
const { serializeJsTypesForJsonStringify, deserializeJsTypesFromJsonParse, getLogger } = require('dbgate-tools');
|
||||
const createBulkInsertStream = require('./createBulkInsertStream');
|
||||
const {
|
||||
@@ -53,8 +53,18 @@ function findArrayResult(resValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function BinData(_subType, base64) {
|
||||
return Buffer.from(base64, 'base64');
|
||||
function BinData(subType, base64) {
|
||||
let numericSubType;
|
||||
if (typeof subType === 'string') {
|
||||
const hex = subType.startsWith('0x') || subType.startsWith('0X') ? subType.slice(2) : subType;
|
||||
numericSubType = parseInt(hex, 16);
|
||||
} else {
|
||||
numericSubType = subType;
|
||||
}
|
||||
if (!Number.isInteger(numericSubType) || numericSubType < 0 || numericSubType > 255) {
|
||||
throw new TypeError(`BinData subType must be an integer between 0 and 255, got: ${subType}`);
|
||||
}
|
||||
return new Binary(Buffer.from(base64, 'base64'), numericSubType);
|
||||
}
|
||||
|
||||
async function getScriptableDb(dbhan) {
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "Přidat nové připojení nebo soubor",
|
||||
"privateCloudWidget.addNewFolder": "Přidat novou složku",
|
||||
"privateCloudWidget.administrateAccess": "Spravovat přístup",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate Cloud je dočasně nedostupný",
|
||||
"privateCloudWidget.createConnection": "Vytvořit připojení na DbGate Cloud",
|
||||
"privateCloudWidget.createSharedFolder": "Vytvořit sdílenou složku",
|
||||
"privateCloudWidget.deleteFolder": "Smazat složku",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "Přejmenovat složku",
|
||||
"privateCloudWidget.searchPlaceholder": "Hledat cloudová připojení a soubory",
|
||||
"privateCloudWidget.yourInviteLink": "Váš pozvánkový odkaz (ve tvaru dbgate://folder/xxx)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate Cloud je dočasně nedostupný",
|
||||
"publicCloudWidget.noFilesFound": "Pro vaši konfiguraci nebyly nalezeny žádné soubory",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "Jsou zobrazeny pouze soubory relevantní pro vaše připojení, platformu a edici DbGate. Nejprve prosím definujte připojení.",
|
||||
"publicCloudWidget.publicKnowledgeBase": "Veřejná znalostní báze",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "Neue Verbindung oder Datei hinzufügen",
|
||||
"privateCloudWidget.addNewFolder": "Neuen Ordner hinzufügen",
|
||||
"privateCloudWidget.administrateAccess": "Zugriff verwalten",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate Cloud ist vorübergehend nicht verfügbar",
|
||||
"privateCloudWidget.createConnection": "Verbindung in DbGate Cloud erstellen",
|
||||
"privateCloudWidget.createSharedFolder": "Freigegebenen Ordner erstellen",
|
||||
"privateCloudWidget.deleteFolder": "Ordner löschen",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "Ordner umbenennen",
|
||||
"privateCloudWidget.searchPlaceholder": "Cloud-Verbindungen und Dateien suchen",
|
||||
"privateCloudWidget.yourInviteLink": "Ihr Einladungslink (im Format dbgate://folder/xxx)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate Cloud ist vorübergehend nicht verfügbar",
|
||||
"publicCloudWidget.noFilesFound": "Keine Dateien für Ihre Konfiguration gefunden",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "Es werden nur Dateien aufgelistet, die für Ihre Verbindungen, Plattform und DbGate-Edition relevant sind. Bitte definieren Sie zuerst Verbindungen.",
|
||||
"publicCloudWidget.publicKnowledgeBase": "Öffentliche Wissensdatenbank",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "Add new connection or file",
|
||||
"privateCloudWidget.addNewFolder": "Add new folder",
|
||||
"privateCloudWidget.administrateAccess": "Administrate access",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate Cloud is temporarily unavailable",
|
||||
"privateCloudWidget.createConnection": "Create connection on DbGate Cloud",
|
||||
"privateCloudWidget.createSharedFolder": "Create shared folder",
|
||||
"privateCloudWidget.deleteFolder": "Delete folder",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "Rename folder",
|
||||
"privateCloudWidget.searchPlaceholder": "Search cloud connections and files",
|
||||
"privateCloudWidget.yourInviteLink": "Your invite link (in form dbgate://folder/xxx)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate Cloud is temporarily unavailable",
|
||||
"publicCloudWidget.noFilesFound": "No files found for your configuration",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "Only files relevant for your connections, platform and DbGate edition are listed. Please define connections at first.",
|
||||
"publicCloudWidget.publicKnowledgeBase": "Public Knowledge Base",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "Agregar nueva conexión o archivo",
|
||||
"privateCloudWidget.addNewFolder": "Agregar nueva carpeta",
|
||||
"privateCloudWidget.administrateAccess": "Administrar acceso",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate Cloud está temporalmente no disponible",
|
||||
"privateCloudWidget.createConnection": "Crear conexión en DbGate Cloud",
|
||||
"privateCloudWidget.createSharedFolder": "Crear carpeta compartida",
|
||||
"privateCloudWidget.deleteFolder": "Eliminar carpeta",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "Renombrar carpeta",
|
||||
"privateCloudWidget.searchPlaceholder": "Buscar conexiones y archivos en la nube",
|
||||
"privateCloudWidget.yourInviteLink": "Su enlace de invitación (en forma dbgate://folder/xxx)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate Cloud está temporalmente no disponible",
|
||||
"publicCloudWidget.noFilesFound": "No se encontraron archivos para su configuración",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "Solo se listan archivos relevantes para sus conexiones, plataforma y edición de DbGate. Defina primero las conexiones.",
|
||||
"publicCloudWidget.publicKnowledgeBase": "Base de conocimiento pública",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "Ajouter une nouvelle connexion ou un fichier",
|
||||
"privateCloudWidget.addNewFolder": "Ajouter un nouveau dossier",
|
||||
"privateCloudWidget.administrateAccess": "Gérer les accès",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate Cloud est temporairement indisponible",
|
||||
"privateCloudWidget.createConnection": "Créer une connexion sur DbGate Cloud",
|
||||
"privateCloudWidget.createSharedFolder": "Créer un dossier partagé",
|
||||
"privateCloudWidget.deleteFolder": "Supprimer le dossier",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "Renommer le dossier",
|
||||
"privateCloudWidget.searchPlaceholder": "Rechercher des connexions et fichiers cloud",
|
||||
"privateCloudWidget.yourInviteLink": "Votre lien d'invitation (sous la forme dbgate://folder/xxx)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate Cloud est temporairement indisponible",
|
||||
"publicCloudWidget.noFilesFound": "Aucun fichier trouvé pour votre configuration",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "Seuls les fichiers pertinents pour vos connexions, votre plateforme et votre édition de DbGate sont listés. Veuillez d'abord définir des connexions.",
|
||||
"publicCloudWidget.publicKnowledgeBase": "Base de connaissances publique",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "Aggiungi nuova connessione o file",
|
||||
"privateCloudWidget.addNewFolder": "Aggiungi nuova cartella",
|
||||
"privateCloudWidget.administrateAccess": "Amministra accesso",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate Cloud è temporaneamente non disponibile",
|
||||
"privateCloudWidget.createConnection": "Crea connessione su DbGate Cloud",
|
||||
"privateCloudWidget.createSharedFolder": "Crea cartella condivisa",
|
||||
"privateCloudWidget.deleteFolder": "Elimina cartella",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "Rinomina cartella",
|
||||
"privateCloudWidget.searchPlaceholder": "Cerca connessioni e file cloud",
|
||||
"privateCloudWidget.yourInviteLink": "Il tuo link di invito (nel formato dbgate://folder/xxx)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate Cloud è temporaneamente non disponibile",
|
||||
"publicCloudWidget.noFilesFound": "Nessun file trovato per la tua configurazione",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "Sono elencati solo i file rilevanti per le tue connessioni, piattaforma ed edizione DbGate. Definisci prima le connessioni.",
|
||||
"publicCloudWidget.publicKnowledgeBase": "Knowledge Base pubblica",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "新しい接続またはファイルを追加",
|
||||
"privateCloudWidget.addNewFolder": "新しいフォルダーを追加",
|
||||
"privateCloudWidget.administrateAccess": "アクセスを管理",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGateクラウドは一時的に利用できません",
|
||||
"privateCloudWidget.createConnection": "DbGateクラウドに接続を作成",
|
||||
"privateCloudWidget.createSharedFolder": "共有フォルダーを作成",
|
||||
"privateCloudWidget.deleteFolder": "フォルダーを削除",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "フォルダー名を変更",
|
||||
"privateCloudWidget.searchPlaceholder": "クラウド接続とファイルを検索",
|
||||
"privateCloudWidget.yourInviteLink": "招待リンク(dbgate://folder/xxx の形式)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGateクラウドは一時的に利用できません",
|
||||
"publicCloudWidget.noFilesFound": "設定に該当するファイルが見つかりません",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "接続、プラットフォーム、DbGateエディションに関連するファイルのみが一覧表示されます。まず接続を定義してください。",
|
||||
"publicCloudWidget.publicKnowledgeBase": "公開ナレッジベース",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "새 연결 또는 파일 추가",
|
||||
"privateCloudWidget.addNewFolder": "새 폴더 추가",
|
||||
"privateCloudWidget.administrateAccess": "접근 권한 관리",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate 클라우드는 일시적으로 사용할 수 없습니다",
|
||||
"privateCloudWidget.createConnection": "DbGate 클라우드에 연결 생성",
|
||||
"privateCloudWidget.createSharedFolder": "공유 폴더 생성",
|
||||
"privateCloudWidget.deleteFolder": "폴더 삭제",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "폴더 이름 변경",
|
||||
"privateCloudWidget.searchPlaceholder": "클라우드 연결 및 파일 검색",
|
||||
"privateCloudWidget.yourInviteLink": "초대 링크(dbgate://folder/xxx 형식)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate 클라우드는 일시적으로 사용할 수 없습니다",
|
||||
"publicCloudWidget.noFilesFound": "구성에 해당하는 파일을 찾을 수 없습니다",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "연결, 플랫폼 및 DbGate 에디션과 관련된 파일만 표시됩니다. 먼저 연결을 정의하세요.",
|
||||
"publicCloudWidget.publicKnowledgeBase": "공개 지식 베이스",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "Adicionar nova conexão ou arquivo",
|
||||
"privateCloudWidget.addNewFolder": "Adicionar nova pasta",
|
||||
"privateCloudWidget.administrateAccess": "Administrar acesso",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate Cloud está temporariamente indisponível",
|
||||
"privateCloudWidget.createConnection": "Criar conexão no DbGate Cloud",
|
||||
"privateCloudWidget.createSharedFolder": "Criar pasta compartilhada",
|
||||
"privateCloudWidget.deleteFolder": "Excluir pasta",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "Renomear pasta",
|
||||
"privateCloudWidget.searchPlaceholder": "Pesquisar conexões e arquivos na nuvem",
|
||||
"privateCloudWidget.yourInviteLink": "Seu link de convite (no formato dbgate://folder/xxx)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate Cloud está temporariamente indisponível",
|
||||
"publicCloudWidget.noFilesFound": "Nenhum arquivo encontrado para sua configuração",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "Apenas arquivos relevantes para suas conexões, plataforma e edição do DbGate são listados. Defina conexões primeiro.",
|
||||
"publicCloudWidget.publicKnowledgeBase": "Base de Conhecimento Pública",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "Pridať nové pripojenie alebo súbor",
|
||||
"privateCloudWidget.addNewFolder": "Pridať nový priečinok",
|
||||
"privateCloudWidget.administrateAccess": "Spravovať prístup",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate Cloud je dočasne nedostupný",
|
||||
"privateCloudWidget.createConnection": "Vytvoriť pripojenie na DbGate Cloud",
|
||||
"privateCloudWidget.createSharedFolder": "Vytvoriť zdieľaný priečinok",
|
||||
"privateCloudWidget.deleteFolder": "Odstrániť priečinok",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "Premenovať priečinok",
|
||||
"privateCloudWidget.searchPlaceholder": "Hľadať cloud pripojenia a súbory",
|
||||
"privateCloudWidget.yourInviteLink": "Váš pozývací odkaz (vo forme dbgate://folder/xxx)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate Cloud je dočasne nedostupný",
|
||||
"publicCloudWidget.noFilesFound": "Pre vašu konfiguráciu neboli nájdené žiadne súbory",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "Sú zobrazené iba súbory relevantné pre vaše pripojenia, platformu a edíciu DbGate. Najprv definujte pripojenia.",
|
||||
"publicCloudWidget.publicKnowledgeBase": "Verejná znalostná báza",
|
||||
|
||||
@@ -1195,6 +1195,7 @@
|
||||
"privateCloudWidget.addNewConnectionOrFile": "添加新连接或文件",
|
||||
"privateCloudWidget.addNewFolder": "添加新文件夹",
|
||||
"privateCloudWidget.administrateAccess": "管理访问权限",
|
||||
"privateCloudWidget.cloudUnavailable": "DbGate 云暂时不可用",
|
||||
"privateCloudWidget.createConnection": "在 DbGate 云上创建连接",
|
||||
"privateCloudWidget.createSharedFolder": "创建共享文件夹",
|
||||
"privateCloudWidget.deleteFolder": "删除文件夹",
|
||||
@@ -1207,6 +1208,7 @@
|
||||
"privateCloudWidget.renameFolder": "重命名文件夹",
|
||||
"privateCloudWidget.searchPlaceholder": "搜索云连接和文件",
|
||||
"privateCloudWidget.yourInviteLink": "您的邀请链接(格式为 dbgate://folder/xxx)",
|
||||
"publicCloudWidget.cloudUnavailable": "DbGate 云暂时不可用",
|
||||
"publicCloudWidget.noFilesFound": "未找到适合您配置的文件",
|
||||
"publicCloudWidget.onlyRelevantFilesListed": "仅列出与您的连接、平台和 DbGate 版本相关的文件。请先定义连接。",
|
||||
"publicCloudWidget.publicKnowledgeBase": "公共知识库",
|
||||
|
||||
Reference in New Issue
Block a user